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 <joostlek@outlook.com>

* Update homeassistant/components/mystrom/sensor.py

Co-authored-by: G Johansson <goran.johansson@shiftit.se>

* Update homeassistant/components/mystrom/sensor.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update __init__.py

* Update const.py

* Update sensor.py

* Apply suggestions from code review

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
Philippe Wechsler 2023-10-18 16:01:46 +02:00 committed by GitHub
parent 799342497b
commit 5f35eecf93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 96 additions and 3 deletions

View file

@ -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

View file

@ -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):

View file

@ -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)