feat: report facts, not warnings (0.2.0) #5
No files matched your search
@@ -395,39 +395,6 @@ class FritzBoxDriver(ResidentialGatewayDriver):
|
||||
|
||||
return result
|
||||
|
||||
def get_device_warnings(self) -> list[dict[str, Any]]:
|
||||
"""Return device warnings derived from DSL line quality and firmware state.
|
||||
|
||||
Called during the poll cycle via ``_collect_system_snapshots``.
|
||||
Reads ``UserInterface1`` for firmware updates and
|
||||
``WANDSLInterfaceConfig1`` for line quality.
|
||||
"""
|
||||
warnings: list[dict[str, Any]] = []
|
||||
available = self.fc.services if self.fc else {}
|
||||
|
||||
if "UserInterface1" in available:
|
||||
try:
|
||||
ui_info = self._call("UserInterface1", "X_AVM-DE_GetInfo")
|
||||
if ui_info.get("NewX_AVM-DE_UpdateState", "") == "Available":
|
||||
warnings.append({
|
||||
"code": "firmware_update_available",
|
||||
"meta": {"latest_version": ui_info.get("NewX_AVM-DE_Version", "")},
|
||||
})
|
||||
except _OPTIONAL_SERVICE_ERRORS:
|
||||
pass
|
||||
|
||||
if "WANDSLInterfaceConfig1" in available:
|
||||
try:
|
||||
info = self._call("WANDSLInterfaceConfig1", "GetInfo")
|
||||
# SNR margin is in dB×10; < 60 means < 6 dB — borderline line quality
|
||||
snr_down = int(_to_float(info.get("NewDownstreamNoiseMargin")))
|
||||
if 0 < snr_down < 60:
|
||||
warnings.append({"code": "dsl_snr_low", "meta": {"snr_db_x10": snr_down}})
|
||||
except _OPTIONAL_SERVICE_ERRORS:
|
||||
pass
|
||||
|
||||
return warnings
|
||||
|
||||
def get_arp_table(self, vrf: str = "") -> list[dict[str, Any]]:
|
||||
"""Return the ARP table, derived from :meth:`get_hosts`.
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "napalm-fritzbox"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
description = "NAPALM driver for AVM FritzBox (TR-064 via fritzconnection)."
|
||||
readme = "README.md"
|
||||
license = { text = "Apache-2.0" }
|
||||
|
||||
@@ -647,37 +647,14 @@ class TestAutoMaxBitRate:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# get_device_warnings
|
||||
# warnings
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestGetDeviceWarnings:
|
||||
def test_returns_empty_list(self, driver):
|
||||
# UI_INFO has UpdateState=Available → one warning expected
|
||||
warnings = driver.get_device_warnings()
|
||||
codes = [w["code"] for w in warnings]
|
||||
assert "firmware_update_available" in codes
|
||||
|
||||
def test_no_firmware_warning_when_no_update(self, driver):
|
||||
driver.fc.call_action.side_effect = lambda svc, act, **kw: (
|
||||
UI_INFO_NO_UPDATE if (svc, act) == ("UserInterface1", "X_AVM-DE_GetInfo")
|
||||
else _call_action(svc, act, **kw)
|
||||
)
|
||||
warnings = driver.get_device_warnings()
|
||||
assert not any(w["code"] == "firmware_update_available" for w in warnings)
|
||||
|
||||
def test_dsl_snr_low_warning(self, driver):
|
||||
low_snr = dict(DSL_INFO, NewDownstreamNoiseMargin=40) # 4.0 dB < 6 dB threshold
|
||||
driver.fc.call_action.side_effect = lambda svc, act, **kw: (
|
||||
low_snr if (svc, act) == ("WANDSLInterfaceConfig1", "GetInfo")
|
||||
else _call_action(svc, act, **kw)
|
||||
)
|
||||
warnings = driver.get_device_warnings()
|
||||
assert any(w["code"] == "dsl_snr_low" for w in warnings)
|
||||
|
||||
def test_no_dsl_warning_when_snr_ok(self, driver):
|
||||
warnings = driver.get_device_warnings()
|
||||
assert not any(w["code"] == "dsl_snr_low" for w in warnings)
|
||||
def test_no_warnings_of_its_own():
|
||||
"""The DSL margin and the firmware on offer are facts in get_system_config; the
|
||||
application decides they are warnings (netOrk #1111)."""
|
||||
assert "get_device_warnings" not in vars(FritzBoxDriver)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user