Fix UPS functionality for multiple devices
This commit is contained in:
+79
-10
@@ -9,6 +9,7 @@ import socket
|
||||
from collections import deque
|
||||
|
||||
from bmspy import client
|
||||
from bmspy.classes import UPS, BMSScalarField
|
||||
|
||||
DAEMON_UPDATE_PERIOD = 30
|
||||
|
||||
@@ -18,6 +19,46 @@ warning_sent = False
|
||||
alert_sent = False
|
||||
|
||||
|
||||
def _get_field_value(device: UPS, field_name: str) -> float | None:
|
||||
"""Return the raw_value of a named BMSScalarField from a UPS, or None if not found."""
|
||||
for name, field in device.items():
|
||||
if name == field_name and isinstance(field, BMSScalarField):
|
||||
return field.raw_value
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_ups_device(data: dict[str, UPS], requested: str | None) -> str | None:
|
||||
"""Return the device name to monitor, or None and print an error if the selection is invalid.
|
||||
|
||||
Rules:
|
||||
- No devices → error.
|
||||
- requested is set and found → use it.
|
||||
- requested is set but not found → error listing available devices.
|
||||
- requested is None and exactly one device → use it.
|
||||
- requested is None and multiple devices → error; user must specify one.
|
||||
"""
|
||||
if not data:
|
||||
print("Error: no UPS devices found")
|
||||
return None
|
||||
if requested is not None:
|
||||
if requested not in data:
|
||||
print(
|
||||
"Error: UPS '{}' not found. Available: {}".format(
|
||||
requested, ", ".join(sorted(data))
|
||||
)
|
||||
)
|
||||
return None
|
||||
return requested
|
||||
if len(data) > 1:
|
||||
print(
|
||||
"Error: multiple UPS devices found, specify one with --device: {}".format(
|
||||
", ".join(sorted(data))
|
||||
)
|
||||
)
|
||||
return None
|
||||
return next(iter(data))
|
||||
|
||||
|
||||
def handle_shutdown(action: str = "cancel", delay: int = 0, debug: int = 0) -> None:
|
||||
"""Schedule or cancel a system shutdown; only schedules once per incident."""
|
||||
global scheduled_shutdown
|
||||
@@ -157,6 +198,14 @@ def main() -> None:
|
||||
default="/run/bmspy/bms",
|
||||
help="Socket to communicate with daemon",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--device",
|
||||
dest="device",
|
||||
action="store",
|
||||
default=None,
|
||||
metavar="NAME",
|
||||
help="Name of the UPS device to monitor (required if multiple devices are available)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verbose",
|
||||
"-v",
|
||||
@@ -173,10 +222,19 @@ def main() -> None:
|
||||
client.handle_registration(args.socket, "ups", debug)
|
||||
atexit.register(client.handle_registration, args.socket, "ups", debug)
|
||||
|
||||
initial_data = client.read_data(args.socket, "ups")
|
||||
device_name = _resolve_ups_device(initial_data, args.device)
|
||||
if device_name is None:
|
||||
return
|
||||
|
||||
history = deque()
|
||||
while True:
|
||||
data = client.read_data(args.socket, "ups")
|
||||
history.append(data)
|
||||
data = client.read_data(args.socket, "ups", device=device_name)
|
||||
device_obj = data.get(device_name)
|
||||
if device_obj is None:
|
||||
time.sleep(DAEMON_UPDATE_PERIOD)
|
||||
continue
|
||||
history.append(device_obj)
|
||||
|
||||
# Remove the oldest data from the history
|
||||
while len(history) > 10:
|
||||
@@ -192,19 +250,30 @@ def main() -> None:
|
||||
time.sleep(DAEMON_UPDATE_PERIOD)
|
||||
continue
|
||||
|
||||
current_amps = float(data["bms_current_amps"]["raw_value"])
|
||||
charge_ratio = float(data["bms_capacity_charge_ratio"]["raw_value"]) * 100
|
||||
comparison_1_current_amps = float(comparison_1["bms_current_amps"]["raw_value"])
|
||||
current_amps = float(_get_field_value(device_obj, "bms_current_amps") or 0.0)
|
||||
charge_ratio = (
|
||||
float(_get_field_value(device_obj, "bms_capacity_charge_ratio") or 0.0) * 100
|
||||
)
|
||||
comparison_1_current_amps = float(
|
||||
_get_field_value(comparison_1, "bms_current_amps") or 0.0
|
||||
)
|
||||
comparison_1_charge_ratio = (
|
||||
float(comparison_1["bms_capacity_charge_ratio"]["raw_value"]) * 100
|
||||
float(_get_field_value(comparison_1, "bms_capacity_charge_ratio") or 0.0)
|
||||
* 100
|
||||
)
|
||||
comparison_2_current_amps = float(
|
||||
_get_field_value(comparison_2, "bms_current_amps") or 0.0
|
||||
)
|
||||
comparison_2_current_amps = float(comparison_2["bms_current_amps"]["raw_value"])
|
||||
comparison_2_charge_ratio = (
|
||||
float(comparison_2["bms_capacity_charge_ratio"]["raw_value"]) * 100
|
||||
float(_get_field_value(comparison_2, "bms_capacity_charge_ratio") or 0.0)
|
||||
* 100
|
||||
)
|
||||
comparison_3_current_amps = float(
|
||||
_get_field_value(comparison_3, "bms_current_amps") or 0.0
|
||||
)
|
||||
comparison_3_current_amps = float(comparison_3["bms_current_amps"]["raw_value"])
|
||||
comparison_3_charge_ratio = (
|
||||
float(comparison_3["bms_capacity_charge_ratio"]["raw_value"]) * 100
|
||||
float(_get_field_value(comparison_3, "bms_capacity_charge_ratio") or 0.0)
|
||||
* 100
|
||||
)
|
||||
|
||||
if debug > 1:
|
||||
|
||||
Reference in New Issue
Block a user