From ddd5b9f92c7fedc4abc79d2a762bf8409f097767 Mon Sep 17 00:00:00 2001 From: Sebastien Lavoie Date: Sun, 29 Mar 2026 08:53:03 -0400 Subject: [PATCH] feat: add sensor and binary_sensor entity stubs Co-Authored-By: Claude Sonnet 4.6 --- custom_components/dkncloudna/binary_sensor.py | 79 +++++++++++++++ custom_components/dkncloudna/sensor.py | 98 +++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 custom_components/dkncloudna/binary_sensor.py create mode 100644 custom_components/dkncloudna/sensor.py diff --git a/custom_components/dkncloudna/binary_sensor.py b/custom_components/dkncloudna/binary_sensor.py new file mode 100644 index 0000000..5380316 --- /dev/null +++ b/custom_components/dkncloudna/binary_sensor.py @@ -0,0 +1,79 @@ +"""Binary sensor entities for DKN Cloud NA.""" + +from __future__ import annotations + +from dataclasses import dataclass + +from homeassistant.components.binary_sensor import ( + BinarySensorDeviceClass, + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .coordinator import DknCoordinator +from .entity import DknEntity + + +@dataclass(frozen=True, kw_only=True) +class DknBinarySensorEntityDescription(BinarySensorEntityDescription): + """Extend BinarySensorEntityDescription with a device_data key.""" + data_key: str = "" + + +BINARY_SENSOR_DESCRIPTIONS: tuple[DknBinarySensorEntityDescription, ...] = ( + DknBinarySensorEntityDescription( + key="connected", + translation_key="connected", + data_key="isConnected", + device_class=BinarySensorDeviceClass.CONNECTIVITY, + entity_category=EntityCategory.DIAGNOSTIC, + ), + DknBinarySensorEntityDescription( + key="machine_ready", + translation_key="machine_ready", + data_key="machineready", + entity_category=EntityCategory.DIAGNOSTIC, + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up binary sensor entities.""" + coordinator: DknCoordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"] + async_add_entities( + DknBinarySensorEntity(coordinator, mac, desc) + for mac in (coordinator.data or {}) + for desc in BINARY_SENSOR_DESCRIPTIONS + ) + + +class DknBinarySensorEntity(DknEntity, BinarySensorEntity): + """A binary sensor for one boolean property of a DKN device.""" + + entity_description: DknBinarySensorEntityDescription + + def __init__( + self, + coordinator: DknCoordinator, + mac: str, + description: DknBinarySensorEntityDescription, + ) -> None: + super().__init__(coordinator, mac) + self.entity_description = description + self._attr_unique_id = f"{DOMAIN}_{mac}_{description.key}" + + @property + def is_on(self) -> bool | None: + value = self._device_data.get(self.entity_description.data_key) + if value is None: + return None + return bool(value) diff --git a/custom_components/dkncloudna/sensor.py b/custom_components/dkncloudna/sensor.py new file mode 100644 index 0000000..65a7899 --- /dev/null +++ b/custom_components/dkncloudna/sensor.py @@ -0,0 +1,98 @@ +"""Sensor entities for DKN Cloud NA.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, + SensorStateClass, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import SIGNAL_STRENGTH_DECIBELS_MILLIWATT, UnitOfTemperature +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .coordinator import DknCoordinator +from .entity import DknEntity + + +@dataclass(frozen=True, kw_only=True) +class DknSensorEntityDescription(SensorEntityDescription): + """Extend SensorEntityDescription with a device_data key.""" + data_key: str = "" + + +SENSOR_DESCRIPTIONS: tuple[DknSensorEntityDescription, ...] = ( + DknSensorEntityDescription( + key="room_temperature", + translation_key="room_temperature", + data_key="work_temp", + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + ), + DknSensorEntityDescription( + key="exterior_temperature", + translation_key="exterior_temperature", + data_key="ext_temp", + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + entity_registry_enabled_default=False, + ), + DknSensorEntityDescription( + key="wifi_signal", + translation_key="wifi_signal", + data_key="stat_rssi", + device_class=SensorDeviceClass.SIGNAL_STRENGTH, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + entity_category=EntityCategory.DIAGNOSTIC, + ), + DknSensorEntityDescription( + key="error_code", + translation_key="error_code", + data_key="error_ascii1", + entity_category=EntityCategory.DIAGNOSTIC, + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up sensor entities.""" + coordinator: DknCoordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"] + async_add_entities( + DknSensorEntity(coordinator, mac, desc) + for mac in (coordinator.data or {}) + for desc in SENSOR_DESCRIPTIONS + ) + + +class DknSensorEntity(DknEntity, SensorEntity): + """A single sensor for one property of a DKN device.""" + + entity_description: DknSensorEntityDescription + + def __init__( + self, + coordinator: DknCoordinator, + mac: str, + description: DknSensorEntityDescription, + ) -> None: + super().__init__(coordinator, mac) + self.entity_description = description + self._attr_unique_id = f"{DOMAIN}_{mac}_{description.key}" + + @property + def native_value(self) -> Any: + return self._device_data.get(self.entity_description.data_key)