From 33af2602af85af6fbe1605d110530ec50d23daad Mon Sep 17 00:00:00 2001 From: Simone Chemelli Date: Sun, 25 Jul 2021 19:43:31 +0200 Subject: [PATCH] Fix wan/device uptime and add state_class to counters for Fritz (#52574) * Fix wan/device uptime, add state_class to counters * Rebase + cleanup + adapt to final fritzconnection * Bump fritzconnection library * Missing bump --- homeassistant/components/fritz/manifest.json | 2 +- homeassistant/components/fritz/sensor.py | 50 +++++++++++++++---- .../fritzbox_callmonitor/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/fritz/manifest.json b/homeassistant/components/fritz/manifest.json index a7c51a69cf7..46531183afd 100644 --- a/homeassistant/components/fritz/manifest.json +++ b/homeassistant/components/fritz/manifest.json @@ -3,7 +3,7 @@ "name": "AVM FRITZ!Box Tools", "documentation": "https://www.home-assistant.io/integrations/fritz", "requirements": [ - "fritzconnection==1.4.2", + "fritzconnection==1.6.0", "xmltodict==0.12.0" ], "dependencies": ["network"], diff --git a/homeassistant/components/fritz/sensor.py b/homeassistant/components/fritz/sensor.py index 215848251e9..482d5b1d688 100644 --- a/homeassistant/components/fritz/sensor.py +++ b/homeassistant/components/fritz/sensor.py @@ -26,9 +26,9 @@ from .const import DOMAIN, UPTIME_DEVIATION _LOGGER = logging.getLogger(__name__) -def _retrieve_uptime_state(status: FritzStatus, last_value: str) -> str: - """Return uptime from device.""" - delta_uptime = utcnow() - datetime.timedelta(seconds=status.uptime) +def _uptime_calculation(seconds_uptime: float, last_value: str | None) -> str: + """Calculate uptime with deviation.""" + delta_uptime = utcnow() - datetime.timedelta(seconds=seconds_uptime) if ( not last_value @@ -42,6 +42,18 @@ def _retrieve_uptime_state(status: FritzStatus, last_value: str) -> str: return last_value +def _retrieve_device_uptime_state(status: FritzStatus, last_value: str) -> str: + """Return uptime from device.""" + return _uptime_calculation(status.device_uptime, last_value) + + +def _retrieve_connection_uptime_state( + status: FritzStatus, last_value: str | None +) -> str: + """Return uptime from connection.""" + return _uptime_calculation(status.connection_uptime, last_value) + + def _retrieve_external_ip_state(status: FritzStatus, last_value: str) -> str: """Return external ip from device.""" return status.external_ip # type: ignore[no-any-return] @@ -83,6 +95,7 @@ class SensorData(TypedDict, total=False): name: str device_class: str | None state_class: str | None + last_reset: bool unit_of_measurement: str | None icon: str | None state_provider: Callable @@ -94,10 +107,15 @@ SENSOR_DATA = { icon="mdi:earth", state_provider=_retrieve_external_ip_state, ), - "uptime": SensorData( - name="Uptime", + "device_uptime": SensorData( + name="Device Uptime", device_class=DEVICE_CLASS_TIMESTAMP, - state_provider=_retrieve_uptime_state, + state_provider=_retrieve_device_uptime_state, + ), + "connection_uptime": SensorData( + name="Connection Uptime", + device_class=DEVICE_CLASS_TIMESTAMP, + state_provider=_retrieve_connection_uptime_state, ), "kb_s_sent": SensorData( name="kB/s sent", @@ -127,12 +145,16 @@ SENSOR_DATA = { ), "gb_sent": SensorData( name="GB sent", + state_class=STATE_CLASS_MEASUREMENT, + last_reset=True, unit_of_measurement=DATA_GIGABYTES, icon="mdi:upload", state_provider=_retrieve_gb_sent_state, ), "gb_received": SensorData( name="GB received", + state_class=STATE_CLASS_MEASUREMENT, + last_reset=True, unit_of_measurement=DATA_GIGABYTES, icon="mdi:download", state_provider=_retrieve_gb_received_state, @@ -170,7 +192,8 @@ class FritzBoxSensor(FritzBoxBaseEntity, SensorEntity): ) -> None: """Init FRITZ!Box connectivity class.""" self._sensor_data: SensorData = SENSOR_DATA[sensor_type] - self._last_value: str | None = None + self._last_device_value: str | None = None + self._last_wan_value: str | None = None self._attr_available = True self._attr_device_class = self._sensor_data.get("device_class") self._attr_icon = self._sensor_data.get("icon") @@ -197,6 +220,15 @@ class FritzBoxSensor(FritzBoxBaseEntity, SensorEntity): self._attr_available = False return - self._attr_state = self._last_value = self._state_provider( - status, self._last_value + self._attr_state = self._last_device_value = self._state_provider( + status, self._last_device_value ) + + if self._sensor_data.get("last_reset") is True: + self._last_wan_value = _retrieve_connection_uptime_state( + status, self._last_wan_value + ) + self._attr_last_reset = datetime.datetime.strptime( + self._last_wan_value, + "%Y-%m-%dT%H:%M:%S%z", + ) diff --git a/homeassistant/components/fritzbox_callmonitor/manifest.json b/homeassistant/components/fritzbox_callmonitor/manifest.json index 531fa13e232..0a1f7330c6d 100644 --- a/homeassistant/components/fritzbox_callmonitor/manifest.json +++ b/homeassistant/components/fritzbox_callmonitor/manifest.json @@ -3,7 +3,7 @@ "name": "AVM FRITZ!Box Call Monitor", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/fritzbox_callmonitor", - "requirements": ["fritzconnection==1.4.2"], + "requirements": ["fritzconnection==1.6.0"], "codeowners": [], "iot_class": "local_polling" } diff --git a/requirements_all.txt b/requirements_all.txt index d8ea2df8be5..84cfa5f0cf7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -646,7 +646,7 @@ freesms==0.2.0 # homeassistant.components.fritz # homeassistant.components.fritzbox_callmonitor -fritzconnection==1.4.2 +fritzconnection==1.6.0 # homeassistant.components.google_translate gTTS==2.2.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0ca209f342e..2f9828c479d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -358,7 +358,7 @@ freebox-api==0.0.10 # homeassistant.components.fritz # homeassistant.components.fritzbox_callmonitor -fritzconnection==1.4.2 +fritzconnection==1.6.0 # homeassistant.components.google_translate gTTS==2.2.3