diff --git a/homeassistant/components/ebusd/__init__.py b/homeassistant/components/ebusd/__init__.py index 5c36c311bff..a32993af094 100644 --- a/homeassistant/components/ebusd/__init__.py +++ b/homeassistant/components/ebusd/__init__.py @@ -1,6 +1,7 @@ """Support for Ebusd daemon for communication with eBUS heating systems.""" import logging +from typing import Any import ebusdpy import voluptuous as vol @@ -17,7 +18,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers.discovery import load_platform from homeassistant.helpers.typing import ConfigType -from .const import DOMAIN, SENSOR_TYPES +from .const import DOMAIN, EBUSD_DATA, SENSOR_TYPES _LOGGER = logging.getLogger(__name__) @@ -28,9 +29,9 @@ CACHE_TTL = 900 SERVICE_EBUSD_WRITE = "ebusd_write" -def verify_ebusd_config(config): +def verify_ebusd_config(config: ConfigType) -> ConfigType: """Verify eBusd config.""" - circuit = config[CONF_CIRCUIT] + circuit: str = config[CONF_CIRCUIT] for condition in config[CONF_MONITORED_CONDITIONS]: if condition not in SENSOR_TYPES[circuit]: raise vol.Invalid(f"Condition '{condition}' not in '{circuit}'.") @@ -59,17 +60,17 @@ CONFIG_SCHEMA = vol.Schema( def setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the eBusd component.""" _LOGGER.debug("Integration setup started") - conf = config[DOMAIN] - name = conf[CONF_NAME] - circuit = conf[CONF_CIRCUIT] - monitored_conditions = conf.get(CONF_MONITORED_CONDITIONS) - server_address = (conf.get(CONF_HOST), conf.get(CONF_PORT)) + conf: ConfigType = config[DOMAIN] + name: str = conf[CONF_NAME] + circuit: str = conf[CONF_CIRCUIT] + monitored_conditions: list[str] = conf[CONF_MONITORED_CONDITIONS] + server_address: tuple[str, int] = (conf[CONF_HOST], conf[CONF_PORT]) try: ebusdpy.init(server_address) except (TimeoutError, OSError): return False - hass.data[DOMAIN] = EbusdData(server_address, circuit) + hass.data[EBUSD_DATA] = EbusdData(server_address, circuit) sensor_config = { CONF_MONITORED_CONDITIONS: monitored_conditions, "client_name": name, @@ -77,7 +78,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool: } load_platform(hass, Platform.SENSOR, DOMAIN, sensor_config, config) - hass.services.register(DOMAIN, SERVICE_EBUSD_WRITE, hass.data[DOMAIN].write) + hass.services.register(DOMAIN, SERVICE_EBUSD_WRITE, hass.data[EBUSD_DATA].write) _LOGGER.debug("Ebusd integration setup completed") return True @@ -86,13 +87,13 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool: class EbusdData: """Get the latest data from Ebusd.""" - def __init__(self, address, circuit): + def __init__(self, address: tuple[str, int], circuit: str) -> None: """Initialize the data object.""" self._circuit = circuit self._address = address - self.value = {} + self.value: dict[str, Any] = {} - def update(self, name, stype): + def update(self, name: str, stype: int) -> None: """Call the Ebusd API to update the data.""" try: _LOGGER.debug("Opening socket to ebusd %s", name) diff --git a/homeassistant/components/ebusd/const.py b/homeassistant/components/ebusd/const.py index 4fb3032e19b..10e46f6a2b9 100644 --- a/homeassistant/components/ebusd/const.py +++ b/homeassistant/components/ebusd/const.py @@ -1,5 +1,9 @@ """Constants for ebus component.""" +from __future__ import annotations + +from typing import TYPE_CHECKING + from homeassistant.components.sensor import SensorDeviceClass from homeassistant.const import ( PERCENTAGE, @@ -8,277 +12,283 @@ from homeassistant.const import ( UnitOfTemperature, UnitOfTime, ) +from homeassistant.util.hass_dict import HassKey + +if TYPE_CHECKING: + from . import EbusdData DOMAIN = "ebusd" +EBUSD_DATA: HassKey[EbusdData] = HassKey(DOMAIN) # SensorTypes from ebusdpy module : # 0='decimal', 1='time-schedule', 2='switch', 3='string', 4='value;status' -SENSOR_TYPES = { +type SensorSpecs = tuple[str, str | None, str | None, int, SensorDeviceClass | None] +SENSOR_TYPES: dict[str, dict[str, SensorSpecs]] = { "700": { - "ActualFlowTemperatureDesired": [ + "ActualFlowTemperatureDesired": ( "Hc1ActualFlowTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "MaxFlowTemperatureDesired": [ + ), + "MaxFlowTemperatureDesired": ( "Hc1MaxFlowTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "MinFlowTemperatureDesired": [ + ), + "MinFlowTemperatureDesired": ( "Hc1MinFlowTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "PumpStatus": ["Hc1PumpStatus", None, "mdi:toggle-switch", 2, None], - "HCSummerTemperatureLimit": [ + ), + "PumpStatus": ("Hc1PumpStatus", None, "mdi:toggle-switch", 2, None), + "HCSummerTemperatureLimit": ( "Hc1SummerTempLimit", UnitOfTemperature.CELSIUS, "mdi:weather-sunny", 0, SensorDeviceClass.TEMPERATURE, - ], - "HolidayTemperature": [ + ), + "HolidayTemperature": ( "HolidayTemp", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "HWTemperatureDesired": [ + ), + "HWTemperatureDesired": ( "HwcTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "HWActualTemperature": [ + ), + "HWActualTemperature": ( "HwcStorageTemp", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "HWTimerMonday": ["hwcTimer.Monday", None, "mdi:timer-outline", 1, None], - "HWTimerTuesday": ["hwcTimer.Tuesday", None, "mdi:timer-outline", 1, None], - "HWTimerWednesday": ["hwcTimer.Wednesday", None, "mdi:timer-outline", 1, None], - "HWTimerThursday": ["hwcTimer.Thursday", None, "mdi:timer-outline", 1, None], - "HWTimerFriday": ["hwcTimer.Friday", None, "mdi:timer-outline", 1, None], - "HWTimerSaturday": ["hwcTimer.Saturday", None, "mdi:timer-outline", 1, None], - "HWTimerSunday": ["hwcTimer.Sunday", None, "mdi:timer-outline", 1, None], - "HWOperativeMode": ["HwcOpMode", None, "mdi:math-compass", 3, None], - "WaterPressure": [ + ), + "HWTimerMonday": ("hwcTimer.Monday", None, "mdi:timer-outline", 1, None), + "HWTimerTuesday": ("hwcTimer.Tuesday", None, "mdi:timer-outline", 1, None), + "HWTimerWednesday": ("hwcTimer.Wednesday", None, "mdi:timer-outline", 1, None), + "HWTimerThursday": ("hwcTimer.Thursday", None, "mdi:timer-outline", 1, None), + "HWTimerFriday": ("hwcTimer.Friday", None, "mdi:timer-outline", 1, None), + "HWTimerSaturday": ("hwcTimer.Saturday", None, "mdi:timer-outline", 1, None), + "HWTimerSunday": ("hwcTimer.Sunday", None, "mdi:timer-outline", 1, None), + "HWOperativeMode": ("HwcOpMode", None, "mdi:math-compass", 3, None), + "WaterPressure": ( "WaterPressure", UnitOfPressure.BAR, "mdi:water-pump", 0, SensorDeviceClass.PRESSURE, - ], - "Zone1RoomZoneMapping": ["z1RoomZoneMapping", None, "mdi:label", 0, None], - "Zone1NightTemperature": [ + ), + "Zone1RoomZoneMapping": ("z1RoomZoneMapping", None, "mdi:label", 0, None), + "Zone1NightTemperature": ( "z1NightTemp", UnitOfTemperature.CELSIUS, "mdi:weather-night", 0, SensorDeviceClass.TEMPERATURE, - ], - "Zone1DayTemperature": [ + ), + "Zone1DayTemperature": ( "z1DayTemp", UnitOfTemperature.CELSIUS, "mdi:weather-sunny", 0, SensorDeviceClass.TEMPERATURE, - ], - "Zone1HolidayTemperature": [ + ), + "Zone1HolidayTemperature": ( "z1HolidayTemp", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "Zone1RoomTemperature": [ + ), + "Zone1RoomTemperature": ( "z1RoomTemp", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "Zone1ActualRoomTemperatureDesired": [ + ), + "Zone1ActualRoomTemperatureDesired": ( "z1ActualRoomTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "Zone1TimerMonday": ["z1Timer.Monday", None, "mdi:timer-outline", 1, None], - "Zone1TimerTuesday": ["z1Timer.Tuesday", None, "mdi:timer-outline", 1, None], - "Zone1TimerWednesday": [ + ), + "Zone1TimerMonday": ("z1Timer.Monday", None, "mdi:timer-outline", 1, None), + "Zone1TimerTuesday": ("z1Timer.Tuesday", None, "mdi:timer-outline", 1, None), + "Zone1TimerWednesday": ( "z1Timer.Wednesday", None, "mdi:timer-outline", 1, None, - ], - "Zone1TimerThursday": ["z1Timer.Thursday", None, "mdi:timer-outline", 1, None], - "Zone1TimerFriday": ["z1Timer.Friday", None, "mdi:timer-outline", 1, None], - "Zone1TimerSaturday": ["z1Timer.Saturday", None, "mdi:timer-outline", 1, None], - "Zone1TimerSunday": ["z1Timer.Sunday", None, "mdi:timer-outline", 1, None], - "Zone1OperativeMode": ["z1OpMode", None, "mdi:math-compass", 3, None], - "ContinuosHeating": [ + ), + "Zone1TimerThursday": ("z1Timer.Thursday", None, "mdi:timer-outline", 1, None), + "Zone1TimerFriday": ("z1Timer.Friday", None, "mdi:timer-outline", 1, None), + "Zone1TimerSaturday": ("z1Timer.Saturday", None, "mdi:timer-outline", 1, None), + "Zone1TimerSunday": ("z1Timer.Sunday", None, "mdi:timer-outline", 1, None), + "Zone1OperativeMode": ("z1OpMode", None, "mdi:math-compass", 3, None), + "ContinuosHeating": ( "ContinuosHeating", UnitOfTemperature.CELSIUS, "mdi:weather-snowy", 0, SensorDeviceClass.TEMPERATURE, - ], - "PowerEnergyConsumptionLastMonth": [ + ), + "PowerEnergyConsumptionLastMonth": ( "PrEnergySumHcLastMonth", UnitOfEnergy.KILO_WATT_HOUR, "mdi:flash", 0, SensorDeviceClass.ENERGY, - ], - "PowerEnergyConsumptionThisMonth": [ + ), + "PowerEnergyConsumptionThisMonth": ( "PrEnergySumHcThisMonth", UnitOfEnergy.KILO_WATT_HOUR, "mdi:flash", 0, SensorDeviceClass.ENERGY, - ], + ), }, "ehp": { - "HWTemperature": [ + "HWTemperature": ( "HwcTemp", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], - "OutsideTemp": [ + ), + "OutsideTemp": ( "OutsideTemp", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], + ), }, "bai": { - "HotWaterTemperature": [ + "HotWaterTemperature": ( "HwcTemp", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], - "StorageTemperature": [ + ), + "StorageTemperature": ( "StorageTemp", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], - "DesiredStorageTemperature": [ + ), + "DesiredStorageTemperature": ( "StorageTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "OutdoorsTemperature": [ + ), + "OutdoorsTemperature": ( "OutdoorstempSensor", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], - "WaterPressure": [ + ), + "WaterPressure": ( "WaterPressure", UnitOfPressure.BAR, "mdi:pipe", 4, SensorDeviceClass.PRESSURE, - ], - "AverageIgnitionTime": [ + ), + "AverageIgnitionTime": ( "averageIgnitiontime", UnitOfTime.SECONDS, "mdi:av-timer", 0, SensorDeviceClass.DURATION, - ], - "MaximumIgnitionTime": [ + ), + "MaximumIgnitionTime": ( "maxIgnitiontime", UnitOfTime.SECONDS, "mdi:av-timer", 0, SensorDeviceClass.DURATION, - ], - "MinimumIgnitionTime": [ + ), + "MinimumIgnitionTime": ( "minIgnitiontime", UnitOfTime.SECONDS, "mdi:av-timer", 0, SensorDeviceClass.DURATION, - ], - "ReturnTemperature": [ + ), + "ReturnTemperature": ( "ReturnTemp", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], - "CentralHeatingPump": ["WP", None, "mdi:toggle-switch", 2, None], - "HeatingSwitch": ["HeatingSwitch", None, "mdi:toggle-switch", 2, None], - "DesiredFlowTemperature": [ + ), + "CentralHeatingPump": ("WP", None, "mdi:toggle-switch", 2, None), + "HeatingSwitch": ("HeatingSwitch", None, "mdi:toggle-switch", 2, None), + "DesiredFlowTemperature": ( "FlowTempDesired", UnitOfTemperature.CELSIUS, None, 0, SensorDeviceClass.TEMPERATURE, - ], - "FlowTemperature": [ + ), + "FlowTemperature": ( "FlowTemp", UnitOfTemperature.CELSIUS, None, 4, SensorDeviceClass.TEMPERATURE, - ], - "Flame": ["Flame", None, "mdi:toggle-switch", 2, None], - "PowerEnergyConsumptionHeatingCircuit": [ + ), + "Flame": ("Flame", None, "mdi:toggle-switch", 2, None), + "PowerEnergyConsumptionHeatingCircuit": ( "PrEnergySumHc1", UnitOfEnergy.KILO_WATT_HOUR, "mdi:flash", 0, SensorDeviceClass.ENERGY, - ], - "PowerEnergyConsumptionHotWaterCircuit": [ + ), + "PowerEnergyConsumptionHotWaterCircuit": ( "PrEnergySumHwc1", UnitOfEnergy.KILO_WATT_HOUR, "mdi:flash", 0, SensorDeviceClass.ENERGY, - ], - "RoomThermostat": ["DCRoomthermostat", None, "mdi:toggle-switch", 2, None], - "HeatingPartLoad": [ + ), + "RoomThermostat": ("DCRoomthermostat", None, "mdi:toggle-switch", 2, None), + "HeatingPartLoad": ( "PartloadHcKW", UnitOfEnergy.KILO_WATT_HOUR, "mdi:flash", 0, SensorDeviceClass.ENERGY, - ], - "StateNumber": ["StateNumber", None, "mdi:fire", 3, None], - "ModulationPercentage": [ + ), + "StateNumber": ("StateNumber", None, "mdi:fire", 3, None), + "ModulationPercentage": ( "ModulationTempDesired", PERCENTAGE, "mdi:percent", 0, None, - ], + ), }, } diff --git a/homeassistant/components/ebusd/sensor.py b/homeassistant/components/ebusd/sensor.py index 0db0334f94f..a69a0343220 100644 --- a/homeassistant/components/ebusd/sensor.py +++ b/homeassistant/components/ebusd/sensor.py @@ -4,6 +4,7 @@ from __future__ import annotations import datetime import logging +from typing import Any, cast from homeassistant.components.sensor import SensorDeviceClass, SensorEntity from homeassistant.core import HomeAssistant @@ -11,7 +12,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.util import Throttle, dt as dt_util -from .const import DOMAIN +from . import EbusdData +from .const import EBUSD_DATA, SensorSpecs TIME_FRAME1_BEGIN = "time_frame1_begin" TIME_FRAME1_END = "time_frame1_end" @@ -33,9 +35,9 @@ def setup_platform( """Set up the Ebus sensor.""" if not discovery_info: return - ebusd_api = hass.data[DOMAIN] - monitored_conditions = discovery_info["monitored_conditions"] - name = discovery_info["client_name"] + ebusd_api = hass.data[EBUSD_DATA] + monitored_conditions: list[str] = discovery_info["monitored_conditions"] + name: str = discovery_info["client_name"] add_entities( ( @@ -49,9 +51,8 @@ def setup_platform( class EbusdSensor(SensorEntity): """Ebusd component sensor methods definition.""" - def __init__(self, data, sensor, name): + def __init__(self, data: EbusdData, sensor: SensorSpecs, name: str) -> None: """Initialize the sensor.""" - self._state = None self._client_name = name ( self._name, @@ -63,20 +64,15 @@ class EbusdSensor(SensorEntity): self.data = data @property - def name(self): + def name(self) -> str: """Return the name of the sensor.""" return f"{self._client_name} {self._name}" @property - def native_value(self): - """Return the state of the sensor.""" - return self._state - - @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, Any] | None: """Return the device state attributes.""" - if self._type == 1 and self._state is not None: - schedule = { + if self._type == 1 and (native_value := self.native_value) is not None: + schedule: dict[str, str | None] = { TIME_FRAME1_BEGIN: None, TIME_FRAME1_END: None, TIME_FRAME2_BEGIN: None, @@ -84,7 +80,7 @@ class EbusdSensor(SensorEntity): TIME_FRAME3_BEGIN: None, TIME_FRAME3_END: None, } - time_frame = self._state.split(";") + time_frame = cast(str, native_value).split(";") for index, item in enumerate(sorted(schedule.items())): if index < len(time_frame): parsed = datetime.datetime.strptime(time_frame[index], "%H:%M") @@ -101,12 +97,12 @@ class EbusdSensor(SensorEntity): return self._device_class @property - def icon(self): + def icon(self) -> str | None: """Icon to use in the frontend, if any.""" return self._icon @property - def native_unit_of_measurement(self): + def native_unit_of_measurement(self) -> str | None: """Return the unit of measurement.""" return self._unit_of_measurement @@ -118,6 +114,6 @@ class EbusdSensor(SensorEntity): if self._name not in self.data.value: return - self._state = self.data.value[self._name] + self._attr_native_value = self.data.value[self._name] except RuntimeError: _LOGGER.debug("EbusdData.update exception")