Correct the spelling in the JBD and EcoFlow snapshots, the diagnostic tool, and the tests. UPS.from_dict maps the old name to the new name, so a client still reads data from an older server during an upgrade. InfluxDB and Prometheus now receive this measurement under the new name.
168 lines
5.6 KiB
Python
168 lines
5.6 KiB
Python
import pytest
|
|
from bmspy.classes import (
|
|
BMSScalarField,
|
|
BMSMultiField,
|
|
BMSInfoField,
|
|
UPS,
|
|
_field_from_dict,
|
|
_UPSSnapshot,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# BMSScalarField
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestBMSScalarField:
|
|
def test_get_existing_attribute(self):
|
|
f = BMSScalarField(help="Voltage", raw_value=52.0, value="52.00", units="V")
|
|
assert f.get("help") == "Voltage"
|
|
assert f.get("raw_value") == 52.0
|
|
assert f.get("units") == "V"
|
|
|
|
def test_get_missing_attribute_returns_default(self):
|
|
f = BMSScalarField(help="Voltage", raw_value=52.0, value="52.00")
|
|
assert f.get("nonexistent") is None
|
|
assert f.get("nonexistent", 42) == 42
|
|
|
|
def test_units_defaults_to_none(self):
|
|
f = BMSScalarField(help="Cycles", raw_value=10, value="10")
|
|
assert f.units is None
|
|
assert f.get("units") is None
|
|
|
|
def test_bool_raw_value(self):
|
|
f = BMSScalarField(help="Flag", raw_value=True, value="1")
|
|
assert f.raw_value is True
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# BMSMultiField
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestBMSMultiField:
|
|
def test_get_existing_attribute(self):
|
|
f = BMSMultiField(
|
|
help="Cell Voltages",
|
|
label="cell",
|
|
raw_values={1: 3.6, 2: 3.61},
|
|
values={1: "3.600", 2: "3.610"},
|
|
units="V",
|
|
)
|
|
assert f.get("label") == "cell"
|
|
assert f.get("raw_values") == {1: 3.6, 2: 3.61}
|
|
assert f.get("units") == "V"
|
|
|
|
def test_get_missing_returns_default(self):
|
|
f = BMSMultiField(help="h", label="l", raw_values={}, values={})
|
|
assert f.get("missing") is None
|
|
assert f.get("missing", "fallback") == "fallback"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# BMSInfoField
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestBMSInfoField:
|
|
def test_get_existing_attribute(self):
|
|
f = BMSInfoField(help="Date of Manufacture", info="2023-01-15")
|
|
assert f.get("help") == "Date of Manufacture"
|
|
assert f.get("info") == "2023-01-15"
|
|
|
|
def test_get_missing_returns_none(self):
|
|
f = BMSInfoField(help="h", info="i")
|
|
assert f.get("units") is None
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _field_from_dict
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestFieldFromDict:
|
|
def test_scalar_field(self):
|
|
d = {"help": "Voltage", "raw_value": 52.0, "value": "52.00", "units": "V"}
|
|
f = _field_from_dict(d)
|
|
assert isinstance(f, BMSScalarField)
|
|
assert f.raw_value == 52.0
|
|
assert f.units == "V"
|
|
|
|
def test_multi_field(self):
|
|
d = {
|
|
"help": "Cell Voltages",
|
|
"label": "cell",
|
|
"raw_values": {1: 3.6},
|
|
"values": {1: "3.600"},
|
|
"units": "V",
|
|
}
|
|
f = _field_from_dict(d)
|
|
assert isinstance(f, BMSMultiField)
|
|
assert f.label == "cell"
|
|
assert f.raw_values == {1: 3.6}
|
|
|
|
def test_info_field(self):
|
|
d = {"help": "Date of Manufacture", "info": "2023-01-15"}
|
|
f = _field_from_dict(d)
|
|
assert isinstance(f, BMSInfoField)
|
|
assert f.info == "2023-01-15"
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# UPS / _UPSSnapshot
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class TestUPS:
|
|
def _snapshot(self):
|
|
return UPS.from_dict({
|
|
"bms_voltage": {"help": "Voltage", "raw_value": 52.0, "value": "52.00", "units": "V"},
|
|
"bms_date": {"help": "Date", "info": "2023-01-15"},
|
|
"bms_temps": {
|
|
"help": "Temperature",
|
|
"label": "sensor",
|
|
"raw_values": {1: 25.0},
|
|
"values": {1: "25.00"},
|
|
"units": "°C",
|
|
},
|
|
})
|
|
|
|
def test_from_dict_returns_ups_instance(self):
|
|
assert isinstance(self._snapshot(), UPS)
|
|
|
|
def test_from_dict_scalar_field(self):
|
|
ups = self._snapshot()
|
|
items = dict(ups.items())
|
|
assert isinstance(items["bms_voltage"], BMSScalarField)
|
|
assert items["bms_voltage"].raw_value == 52.0
|
|
|
|
def test_from_dict_info_field(self):
|
|
ups = self._snapshot()
|
|
items = dict(ups.items())
|
|
assert isinstance(items["bms_date"], BMSInfoField)
|
|
assert items["bms_date"].info == "2023-01-15"
|
|
|
|
def test_from_dict_multi_field(self):
|
|
ups = self._snapshot()
|
|
items = dict(ups.items())
|
|
assert isinstance(items["bms_temps"], BMSMultiField)
|
|
assert items["bms_temps"].raw_values == {1: 25.0}
|
|
|
|
def test_from_dict_corrects_renamed_field(self):
|
|
field = {"help": "Temperature", "label": "sensor", "raw_values": {1: 25.0}, "values": {1: "25.00"}}
|
|
ups = UPS.from_dict({"bms_temperature_celcius": field})
|
|
assert [name for name, _ in ups.items()] == ["bms_temperature_celsius"]
|
|
|
|
def test_bool_true_when_populated(self):
|
|
assert bool(self._snapshot()) is True
|
|
|
|
def test_bool_false_when_empty(self):
|
|
empty = UPS.from_dict({})
|
|
assert bool(empty) is False
|
|
|
|
def test_items_yields_all_fields(self):
|
|
ups = self._snapshot()
|
|
keys = [k for k, _ in ups.items()]
|
|
assert set(keys) == {"bms_voltage", "bms_date", "bms_temps"}
|
|
|
|
def test_items_empty_snapshot(self):
|
|
ups = UPS.from_dict({})
|
|
assert list(ups.items()) == []
|