From 2b101dd5c21ab7c9059515325d9f79f86d7740c7 Mon Sep 17 00:00:00 2001 From: Jeef Date: Wed, 26 Jan 2022 08:16:25 -0700 Subject: [PATCH] Add IntelliFire sensors (#64600) Co-authored-by: Franck Nijhof Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --- .coveragerc | 1 + .../components/intellifire/__init__.py | 2 +- .../components/intellifire/binary_sensor.py | 4 +- .../components/intellifire/manifest.json | 10 +- .../components/intellifire/sensor.py | 128 ++++++++++++++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 7 files changed, 137 insertions(+), 12 deletions(-) create mode 100644 homeassistant/components/intellifire/sensor.py diff --git a/.coveragerc b/.coveragerc index b18d18cf83f..c301d4e30d3 100644 --- a/.coveragerc +++ b/.coveragerc @@ -513,6 +513,7 @@ omit = homeassistant/components/intellifire/__init__.py homeassistant/components/intellifire/coordinator.py homeassistant/components/intellifire/binary_sensor.py + homeassistant/components/intellifire/sensor.py homeassistant/components/incomfort/* homeassistant/components/intesishome/* homeassistant/components/ios/* diff --git a/homeassistant/components/intellifire/__init__.py b/homeassistant/components/intellifire/__init__.py index 26fcb92bffc..6774f235af9 100644 --- a/homeassistant/components/intellifire/__init__.py +++ b/homeassistant/components/intellifire/__init__.py @@ -10,7 +10,7 @@ from homeassistant.core import HomeAssistant from .const import DOMAIN, LOGGER from .coordinator import IntellifireDataUpdateCoordinator -PLATFORMS = [Platform.BINARY_SENSOR] +PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/homeassistant/components/intellifire/binary_sensor.py b/homeassistant/components/intellifire/binary_sensor.py index 0c636ec597b..62082bb9ab4 100644 --- a/homeassistant/components/intellifire/binary_sensor.py +++ b/homeassistant/components/intellifire/binary_sensor.py @@ -20,7 +20,7 @@ from .const import DOMAIN @dataclass -class IntellifireSensorEntityDescriptionMixin: +class IntellifireBinarySensorRequiredKeysMixin: """Mixin for required keys.""" value_fn: Callable[[IntellifirePollData], bool] @@ -28,7 +28,7 @@ class IntellifireSensorEntityDescriptionMixin: @dataclass class IntellifireBinarySensorEntityDescription( - BinarySensorEntityDescription, IntellifireSensorEntityDescriptionMixin + BinarySensorEntityDescription, IntellifireBinarySensorRequiredKeysMixin ): """Describes a binary sensor entity.""" diff --git a/homeassistant/components/intellifire/manifest.json b/homeassistant/components/intellifire/manifest.json index ab7a814693f..42edf00ad25 100644 --- a/homeassistant/components/intellifire/manifest.json +++ b/homeassistant/components/intellifire/manifest.json @@ -3,12 +3,8 @@ "name": "IntelliFire", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/intellifire", - "requirements": [ - "intellifire4py==0.4.3" - ], + "requirements": ["intellifire4py==0.5"], "dependencies": [], - "codeowners": [ - "@jeeftor" - ], + "codeowners": ["@jeeftor"], "iot_class": "local_polling" -} \ No newline at end of file +} diff --git a/homeassistant/components/intellifire/sensor.py b/homeassistant/components/intellifire/sensor.py new file mode 100644 index 00000000000..991e4e69e8c --- /dev/null +++ b/homeassistant/components/intellifire/sensor.py @@ -0,0 +1,128 @@ +"""Platform for sensor integration.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from datetime import datetime, timedelta + +from intellifire4py import IntellifirePollData + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, + SensorStateClass, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import TEMP_CELSIUS +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.util.dt import utcnow + +from . import IntellifireDataUpdateCoordinator +from .const import DOMAIN + + +class IntellifireSensor(CoordinatorEntity, SensorEntity): + """Define a generic class for Sensors.""" + + # Define types + coordinator: IntellifireDataUpdateCoordinator + entity_description: IntellifireSensorEntityDescription + _attr_attribution = "Data provided by unpublished Intellifire API" + + def __init__( + self, + coordinator: IntellifireDataUpdateCoordinator, + description: IntellifireSensorEntityDescription, + ) -> None: + """Init the sensor.""" + super().__init__(coordinator=coordinator) + self.entity_description = description + + # Set the Display name the User will see + self._attr_name = f"Fireplace {description.name}" + self._attr_unique_id = f"{description.key}_{coordinator.api.data.serial}" + # Configure the Device Info + self._attr_device_info = self.coordinator.device_info + + @property + def native_value(self) -> int | str | datetime | None: + """Return the state.""" + return self.entity_description.value_fn(self.coordinator.api.data) + + +def _time_remaining_to_timestamp(data: IntellifirePollData) -> datetime | None: + """Define a sensor that takes into account timezone.""" + if not (seconds_offset := data.timeremaining_s): + return None + return utcnow() + timedelta(seconds=seconds_offset) + + +@dataclass +class IntellifireSensorRequiredKeysMixin: + """Mixin for required keys.""" + + value_fn: Callable[[IntellifirePollData], int | str | datetime | None] + + +@dataclass +class IntellifireSensorEntityDescription( + SensorEntityDescription, IntellifireSensorRequiredKeysMixin +): + """Describes a sensor sensor entity.""" + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Define setup entry call.""" + + coordinator: IntellifireDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] + async_add_entities( + IntellifireSensor(coordinator=coordinator, description=description) + for description in INTELLIFIRE_SENSORS + ) + + +INTELLIFIRE_SENSORS: tuple[IntellifireSensorEntityDescription, ...] = ( + IntellifireSensorEntityDescription( + key="flame_height", + icon="mdi:fire-circle", + name="Flame Height", + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.flameheight, + ), + IntellifireSensorEntityDescription( + key="temperature", + name="Temperature", + state_class=SensorStateClass.MEASUREMENT, + device_class=SensorDeviceClass.TEMPERATURE, + native_unit_of_measurement=TEMP_CELSIUS, + value_fn=lambda data: data.temperature_c, + ), + IntellifireSensorEntityDescription( + key="target_temp", + name="Target Temperature", + state_class=SensorStateClass.MEASUREMENT, + device_class=SensorDeviceClass.TEMPERATURE, + native_unit_of_measurement=TEMP_CELSIUS, + value_fn=lambda data: data.thermostat_setpoint_c, + ), + IntellifireSensorEntityDescription( + key="fan_speed", + icon="mdi:fan", + name="Fan Speed", + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.fanspeed, + ), + IntellifireSensorEntityDescription( + key="timer_end_timestamp", + icon="mdi:timer-sand", + name="Timer End", + state_class=SensorStateClass.MEASUREMENT, + device_class=SensorDeviceClass.TIMESTAMP, + value_fn=_time_remaining_to_timestamp, + ), +) diff --git a/requirements_all.txt b/requirements_all.txt index ade4f3ffce3..be954ae03f8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -914,7 +914,7 @@ influxdb-client==1.24.0 influxdb==5.3.1 # homeassistant.components.intellifire -intellifire4py==0.4.3 +intellifire4py==0.5 # homeassistant.components.iotawatt iotawattpy==0.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e9667af7321..0152fec832e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -586,7 +586,7 @@ influxdb-client==1.24.0 influxdb==5.3.1 # homeassistant.components.intellifire -intellifire4py==0.4.3 +intellifire4py==0.5 # homeassistant.components.iotawatt iotawattpy==0.1.0