From a050c8827b49f00bceb6715980f268a87a052c61 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Mon, 19 Apr 2021 00:30:58 +0200 Subject: [PATCH] Add battery sensor to fritzbox smart home devices (#49374) --- homeassistant/components/fritzbox/sensor.py | 56 ++++++++++++++++++++- tests/components/fritzbox/__init__.py | 1 + tests/components/fritzbox/test_sensor.py | 8 +++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/fritzbox/sensor.py b/homeassistant/components/fritzbox/sensor.py index 4d9c1693c1f..52d2617b223 100644 --- a/homeassistant/components/fritzbox/sensor.py +++ b/homeassistant/components/fritzbox/sensor.py @@ -2,7 +2,12 @@ import requests from homeassistant.components.sensor import SensorEntity -from homeassistant.const import CONF_DEVICES, TEMP_CELSIUS +from homeassistant.const import ( + CONF_DEVICES, + DEVICE_CLASS_BATTERY, + PERCENTAGE, + TEMP_CELSIUS, +) from .const import ( ATTR_STATE_DEVICE_LOCKED, @@ -29,9 +34,58 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entities.append(FritzBoxTempSensor(device, fritz)) devices.add(device.ain) + if device.battery_level is not None: + entities.append(FritzBoxBatterySensor(device, fritz)) + devices.add(f"{device.ain}_battery") + async_add_entities(entities) +class FritzBoxBatterySensor(SensorEntity): + """The entity class for Fritzbox battery sensors.""" + + def __init__(self, device, fritz): + """Initialize the sensor.""" + self._device = device + self._fritz = fritz + + @property + def device_info(self): + """Return device specific attributes.""" + return { + "name": self.name, + "identifiers": {(FRITZBOX_DOMAIN, self._device.ain)}, + "manufacturer": self._device.manufacturer, + "model": self._device.productname, + "sw_version": self._device.fw_version, + } + + @property + def unique_id(self): + """Return the unique ID of the device.""" + return f"{self._device.ain}_battery" + + @property + def name(self): + """Return the name of the device.""" + return f"{self._device.name} Battery" + + @property + def state(self): + """Return the state of the sensor.""" + return self._device.battery_level + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return PERCENTAGE + + @property + def device_class(self): + """Return the device class.""" + return DEVICE_CLASS_BATTERY + + class FritzBoxTempSensor(SensorEntity): """The entity class for Fritzbox temperature sensors.""" diff --git a/tests/components/fritzbox/__init__.py b/tests/components/fritzbox/__init__.py index f19e05b84df..8e0932b9000 100644 --- a/tests/components/fritzbox/__init__.py +++ b/tests/components/fritzbox/__init__.py @@ -64,6 +64,7 @@ class FritzDeviceSensorMock(Mock): """Mock of a AVM Fritz!Box sensor device.""" ain = "fake_ain" + battery_level = 23 device_lock = "fake_locked_device" fw_version = "1.2.3" has_alarm = False diff --git a/tests/components/fritzbox/test_sensor.py b/tests/components/fritzbox/test_sensor.py index 6dde22f074e..00c9923bbea 100644 --- a/tests/components/fritzbox/test_sensor.py +++ b/tests/components/fritzbox/test_sensor.py @@ -13,6 +13,7 @@ from homeassistant.components.sensor import DOMAIN from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, + PERCENTAGE, TEMP_CELSIUS, ) from homeassistant.helpers.typing import HomeAssistantType @@ -47,6 +48,13 @@ async def test_setup(hass: HomeAssistantType, fritz: Mock): assert state.attributes[ATTR_STATE_LOCKED] == "fake_locked" assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == TEMP_CELSIUS + state = hass.states.get(f"{ENTITY_ID}_battery") + + assert state + assert state.state == "23" + assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name Battery" + assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == PERCENTAGE + async def test_update(hass: HomeAssistantType, fritz: Mock): """Test update with error."""