From 5f35eecf935b0b6617174347d756874786847ce0 Mon Sep 17 00:00:00 2001 From: Philippe Wechsler <29612400+MadMonkey87@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:01:46 +0200 Subject: [PATCH] Add sensors for myStrom plugs (#97024) * support sensors for myStrom plugs * added myStrom sensor to coveragerc * some improvements from pr reviews * adapt to the SensorEntityDescription pattern * Apply suggestions from code review Co-authored-by: Joost Lekkerkerker * Update homeassistant/components/mystrom/sensor.py Co-authored-by: G Johansson * Update homeassistant/components/mystrom/sensor.py Co-authored-by: Joost Lekkerkerker * Update __init__.py * Update const.py * Update sensor.py * Apply suggestions from code review --------- Co-authored-by: Joost Lekkerkerker Co-authored-by: G Johansson --- .coveragerc | 1 + homeassistant/components/mystrom/__init__.py | 6 +- homeassistant/components/mystrom/sensor.py | 92 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 homeassistant/components/mystrom/sensor.py diff --git a/.coveragerc b/.coveragerc index e12222594ac..29f93c04da6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -789,6 +789,7 @@ omit = homeassistant/components/mystrom/binary_sensor.py homeassistant/components/mystrom/light.py homeassistant/components/mystrom/switch.py + homeassistant/components/mystrom/sensor.py homeassistant/components/nad/media_player.py homeassistant/components/nanoleaf/__init__.py homeassistant/components/nanoleaf/button.py diff --git a/homeassistant/components/mystrom/__init__.py b/homeassistant/components/mystrom/__init__.py index 3166c05db19..96bc49ca853 100644 --- a/homeassistant/components/mystrom/__init__.py +++ b/homeassistant/components/mystrom/__init__.py @@ -16,7 +16,7 @@ from homeassistant.exceptions import ConfigEntryNotReady from .const import DOMAIN from .models import MyStromData -PLATFORMS_SWITCH = [Platform.SWITCH] +PLATFORMS_PLUGS = [Platform.SWITCH, Platform.SENSOR] PLATFORMS_BULB = [Platform.LIGHT] _LOGGER = logging.getLogger(__name__) @@ -55,7 +55,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: device_type = info["type"] if device_type in [101, 106, 107, 120]: device = _get_mystrom_switch(host) - platforms = PLATFORMS_SWITCH + platforms = PLATFORMS_PLUGS await _async_get_device_state(device, info["ip"]) elif device_type in [102, 105]: mac = info["mac"] @@ -87,7 +87,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: device_type = hass.data[DOMAIN][entry.entry_id].info["type"] platforms = [] if device_type in [101, 106, 107, 120]: - platforms.extend(PLATFORMS_SWITCH) + platforms.extend(PLATFORMS_PLUGS) elif device_type in [102, 105]: platforms.extend(PLATFORMS_BULB) if unload_ok := await hass.config_entries.async_unload_platforms(entry, platforms): diff --git a/homeassistant/components/mystrom/sensor.py b/homeassistant/components/mystrom/sensor.py new file mode 100644 index 00000000000..982528bd97c --- /dev/null +++ b/homeassistant/components/mystrom/sensor.py @@ -0,0 +1,92 @@ +"""Support for myStrom sensors of switches/plugs.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass + +from pymystrom.switch import MyStromSwitch + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, + SensorStateClass, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import UnitOfPower, UnitOfTemperature +from homeassistant.core import HomeAssistant +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN, MANUFACTURER + + +@dataclass +class MyStromSwitchSensorEntityDescription(SensorEntityDescription): + """Class describing mystrom switch sensor entities.""" + + value_fn: Callable[[MyStromSwitch], float | None] = lambda _: None + + +SENSOR_TYPES: tuple[MyStromSwitchSensorEntityDescription, ...] = ( + MyStromSwitchSensorEntityDescription( + key="consumption", + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfPower.WATT, + value_fn=lambda device: device.consumption, + ), + MyStromSwitchSensorEntityDescription( + key="temperature", + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + value_fn=lambda device: device.temperature, + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up the myStrom entities.""" + device: MyStromSwitch = hass.data[DOMAIN][entry.entry_id].device + sensors = [] + + for description in SENSOR_TYPES: + if description.value_fn(device) is not None: + sensors.append(MyStromSwitchSensor(device, entry.title, description)) + + async_add_entities(sensors) + + +class MyStromSwitchSensor(SensorEntity): + """Representation of the consumption or temperature of a myStrom switch/plug.""" + + entity_description: MyStromSwitchSensorEntityDescription + device: MyStromSwitch + + _attr_has_entity_name = True + + def __init__( + self, + device: MyStromSwitch, + name: str, + description: MyStromSwitchSensorEntityDescription, + ) -> None: + """Initialize the sensor.""" + self.device = device + self.entity_description = description + + self._attr_unique_id = f"{device.mac}-{description.key}" + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, device.mac)}, + name=name, + manufacturer=MANUFACTURER, + sw_version=device.firmware, + ) + + @property + def native_value(self) -> float | None: + """Return the value of the sensor.""" + return self.entity_description.value_fn(self.device)