fix(snmp): a UPS on mains reads "On battery: No, on mains", not "0s" (#5214)

UPS-MIB upsSecondsOnBattery is zero whenever the UPS is on mains power, so
"On battery for 0s" read as a timer that had just started. The reading gets
its own unit, battery_seconds: zero says "No, on mains", anything else
"for <span>". The metric key stays on_battery_for, so stored history keeps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 13:16:24 -04:00
co-authored by Claude Opus 5.5
parent f67678998c
commit f035a3b14a
2 changed files with 7 additions and 1 deletions
+5 -1
View File
@@ -69,7 +69,7 @@ PRESETS: dict[str, tuple[str, str, tuple[Reading, ...]]] = {
Reading("1.3.6.1.2.1.33.1.2.3.0", "runtime_left", "Runtime left", "minutes"),
Reading("1.3.6.1.2.1.33.1.4.4.1.5.1", "load", "Load", "percent"),
Reading("1.3.6.1.2.1.33.1.3.3.1.3.1", "input_voltage", "Input", "volts"),
Reading("1.3.6.1.2.1.33.1.2.2.0", "on_battery_for", "On battery for", "seconds"))),
Reading("1.3.6.1.2.1.33.1.2.2.0", "on_battery_for", "On battery", "battery_seconds"))),
"linux": ("Linux server", "CPU, memory and load from net-snmp (snmpd's UCD-SNMP-MIB).",
(Reading("1.3.6.1.4.1.2021.11.11.0", "cpu_used", "CPU used", "percent", scale=-1.0, offset=100.0),
Reading("1.3.6.1.4.1.2021.10.1.5.1", "load_1m", "Load (1m)", "number", scale=0.01),
@@ -183,6 +183,9 @@ def format_value(unit: str, value: float | None) -> str:
return human_duration(value / 100)
if unit == "seconds":
return human_duration(value)
if unit == "battery_seconds":
# UPS-MIB upsSecondsOnBattery: zero whenever the UPS is on mains power.
return f"for {human_duration(value)}" if value > 0 else "No, on mains"
if unit == "minutes":
return human_duration(value * 60)
if unit == "percent":
@@ -207,6 +210,7 @@ def format_value(unit: str, value: float | None) -> str:
# What a chart's axis says for a stored unit, and how its values scale for it.
def chart_axis(unit: str) -> tuple[str, float]:
return {"centiseconds": ("days", 1 / 8_640_000), "seconds": ("seconds", 1.0),
"battery_seconds": ("seconds on battery", 1.0),
"minutes": ("minutes", 1.0), "percent": ("%", 1.0), "celsius": ("°C", 1.0),
"volts": ("V", 1.0), "decivolts": ("V", 0.1), "bytes": ("MiB", 1 / 1_048_576),
"kilobytes": ("MiB", 1 / 1024), "bits_per_second": ("Mbit/s", 1e-6),
+2
View File
@@ -54,6 +54,8 @@ def test_presets_come_in_order_and_names_may_not_repeat():
("volts", 121.0, "121 V"),
("decivolts", 1203, "120.3 V"),
("minutes", 45, "45m"),
("battery_seconds", 0, "No, on mains"),
("battery_seconds", 300, "for 5m"),
("kilobytes", 2048, "2.0 MiB"),
("bits_per_second", 12_345_678, "12.3 Mbit/s"),
("bits_per_second", 950, "950 bit/s"),