From 3e4dacb885ae4e286bd67fee572859d2bc7b68c8 Mon Sep 17 00:00:00 2001 From: Brian Towles Date: Wed, 30 Jun 2021 04:56:02 -0500 Subject: [PATCH] Add Modern Forms binary sensor platform (#52312) Co-authored-by: Erik Montnemery Co-authored-by: Franck Nijhof --- .../components/modern_forms/__init__.py | 2 + .../components/modern_forms/binary_sensor.py | 114 ++++++++++++++++++ .../modern_forms/test_binary_sensor.py | 46 +++++++ 3 files changed, 162 insertions(+) create mode 100644 homeassistant/components/modern_forms/binary_sensor.py create mode 100644 tests/components/modern_forms/test_binary_sensor.py diff --git a/homeassistant/components/modern_forms/__init__.py b/homeassistant/components/modern_forms/__init__.py index 24195b96ea4..a31b2655184 100644 --- a/homeassistant/components/modern_forms/__init__.py +++ b/homeassistant/components/modern_forms/__init__.py @@ -11,6 +11,7 @@ from aiomodernforms import ( ) from aiomodernforms.models import Device as ModernFormsDeviceState +from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN from homeassistant.components.fan import DOMAIN as FAN_DOMAIN from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN @@ -30,6 +31,7 @@ from .const import ATTR_IDENTIFIERS, ATTR_MANUFACTURER, DOMAIN SCAN_INTERVAL = timedelta(seconds=5) PLATFORMS = [ + BINARY_SENSOR_DOMAIN, LIGHT_DOMAIN, FAN_DOMAIN, SENSOR_DOMAIN, diff --git a/homeassistant/components/modern_forms/binary_sensor.py b/homeassistant/components/modern_forms/binary_sensor.py new file mode 100644 index 00000000000..f8e3f8bbcf8 --- /dev/null +++ b/homeassistant/components/modern_forms/binary_sensor.py @@ -0,0 +1,114 @@ +"""Support for Modern Forms Binary Sensors.""" +from __future__ import annotations + +from homeassistant.components.binary_sensor import BinarySensorEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.util import dt as dt_util + +from . import ModernFormsDataUpdateCoordinator, ModernFormsDeviceEntity +from .const import CLEAR_TIMER, DOMAIN + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up Modern Forms binary sensors.""" + coordinator: ModernFormsDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] + + binary_sensors: list[ModernFormsBinarySensor] = [ + ModernFormsFanSleepTimerActive(entry.entry_id, coordinator), + ] + + # Only setup light sleep timer sensor if light unit installed + if coordinator.data.info.light_type: + binary_sensors.append( + ModernFormsLightSleepTimerActive(entry.entry_id, coordinator) + ) + + async_add_entities(binary_sensors) + + +class ModernFormsBinarySensor(ModernFormsDeviceEntity, BinarySensorEntity): + """Defines a Modern Forms binary sensor.""" + + def __init__( + self, + *, + entry_id: str, + coordinator: ModernFormsDataUpdateCoordinator, + name: str, + icon: str, + key: str, + ) -> None: + """Initialize Modern Forms switch.""" + super().__init__( + entry_id=entry_id, coordinator=coordinator, name=name, icon=icon + ) + + self._attr_unique_id = f"{coordinator.data.info.mac_address}_{key}" + + +class ModernFormsLightSleepTimerActive(ModernFormsBinarySensor): + """Defines a Modern Forms Light Sleep Timer Active sensor.""" + + _attr_entity_registry_enabled_default = False + + def __init__( + self, entry_id: str, coordinator: ModernFormsDataUpdateCoordinator + ) -> None: + """Initialize Modern Forms Light Sleep Timer Active sensor.""" + super().__init__( + coordinator=coordinator, + entry_id=entry_id, + icon="mdi:av-timer", + key="light_sleep_timer_active", + name=f"{coordinator.data.info.device_name} Light Sleep Timer Active", + ) + + @property + def is_on(self) -> bool: + """Return the state of the timer.""" + return not ( + self.coordinator.data.state.light_sleep_timer == CLEAR_TIMER + or ( + dt_util.utc_from_timestamp( + self.coordinator.data.state.light_sleep_timer + ) + - dt_util.utcnow() + ).total_seconds() + < 0 + ) + + +class ModernFormsFanSleepTimerActive(ModernFormsBinarySensor): + """Defines a Modern Forms Fan Sleep Timer Active sensor.""" + + _attr_entity_registry_enabled_default = False + + def __init__( + self, entry_id: str, coordinator: ModernFormsDataUpdateCoordinator + ) -> None: + """Initialize Modern Forms Fan Sleep Timer Active sensor.""" + super().__init__( + coordinator=coordinator, + entry_id=entry_id, + icon="mdi:av-timer", + key="fan_sleep_timer_active", + name=f"{coordinator.data.info.device_name} Fan Sleep Timer Active", + ) + + @property + def is_on(self) -> bool: + """Return the state of the timer.""" + return not ( + self.coordinator.data.state.fan_sleep_timer == CLEAR_TIMER + or ( + dt_util.utc_from_timestamp(self.coordinator.data.state.fan_sleep_timer) + - dt_util.utcnow() + ).total_seconds() + < 0 + ) diff --git a/tests/components/modern_forms/test_binary_sensor.py b/tests/components/modern_forms/test_binary_sensor.py new file mode 100644 index 00000000000..bc32e309958 --- /dev/null +++ b/tests/components/modern_forms/test_binary_sensor.py @@ -0,0 +1,46 @@ +"""Tests for the Modern Forms sensor platform.""" +from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN +from homeassistant.components.modern_forms.const import DOMAIN +from homeassistant.const import ATTR_ICON +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from tests.components.modern_forms import init_integration +from tests.test_util.aiohttp import AiohttpClientMocker + + +async def test_binary_sensors( + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker +) -> None: + """Test the creation and values of the Modern Forms sensors.""" + + registry = er.async_get(hass) + + registry.async_get_or_create( + BINARY_SENSOR_DOMAIN, + DOMAIN, + "AA:BB:CC:DD:EE:FF_light_sleep_timer_active", + suggested_object_id="modernformsfan_light_sleep_timer_active", + disabled_by=None, + ) + registry.async_get_or_create( + BINARY_SENSOR_DOMAIN, + DOMAIN, + "AA:BB:CC:DD:EE:FF_fan_sleep_timer_active", + suggested_object_id="modernformsfan_fan_sleep_timer_active", + disabled_by=None, + ) + + await init_integration(hass, aioclient_mock) + + # Light timer remaining time + state = hass.states.get("binary_sensor.modernformsfan_light_sleep_timer_active") + assert state + assert state.attributes.get(ATTR_ICON) == "mdi:av-timer" + assert state.state == "off" + + # Fan timer remaining time + state = hass.states.get("binary_sensor.modernformsfan_fan_sleep_timer_active") + assert state + assert state.attributes.get(ATTR_ICON) == "mdi:av-timer" + assert state.state == "off"