diff --git a/homeassistant/components/broadlink/const.py b/homeassistant/components/broadlink/const.py index 41c4964c2b369372a7daf43660c8b7a856685c6f..041c2aba9f0dd1908268984ffea52ba0c61563d5 100644 --- a/homeassistant/components/broadlink/const.py +++ b/homeassistant/components/broadlink/const.py @@ -6,6 +6,7 @@ DOMAIN = "broadlink" DOMAINS_AND_TYPES = { Platform.CLIMATE: {"HYS"}, + Platform.LIGHT: {"LB1", "LB2"}, Platform.REMOTE: {"RM4MINI", "RM4PRO", "RMMINI", "RMMINIB", "RMPRO"}, Platform.SENSOR: { "A1", @@ -35,7 +36,7 @@ DOMAINS_AND_TYPES = { "SP4", "SP4B", }, - Platform.LIGHT: {"LB1", "LB2"}, + Platform.TIME: {"HYS"}, } DEVICE_TYPES = set.union(*DOMAINS_AND_TYPES.values()) diff --git a/homeassistant/components/broadlink/time.py b/homeassistant/components/broadlink/time.py new file mode 100644 index 0000000000000000000000000000000000000000..3dcb045fead914c9a1db6cc04a84341480990ac7 --- /dev/null +++ b/homeassistant/components/broadlink/time.py @@ -0,0 +1,63 @@ +"""Support for Broadlink device time.""" + +from __future__ import annotations + +from datetime import time +from typing import Any + +from homeassistant.components.time import TimeEntity +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 BroadlinkDevice +from .const import DOMAIN +from .entity import BroadlinkEntity + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the Broadlink time.""" + device = hass.data[DOMAIN].devices[config_entry.entry_id] + async_add_entities([BroadlinkTime(device)]) + + +class BroadlinkTime(BroadlinkEntity, TimeEntity): + """Representation of a Broadlink device time.""" + + _attr_has_entity_name = True + _attr_native_value: time | None = None + + def __init__(self, device: BroadlinkDevice) -> None: + """Initialize the sensor.""" + super().__init__(device) + + self._attr_unique_id = f"{device.unique_id}-device_time" + + def _update_state(self, data: dict[str, Any]) -> None: + """Update the state of the entity.""" + if data is None or "hour" not in data or "min" not in data or "sec" not in data: + self._attr_native_value = None + else: + self._attr_native_value = time( + hour=data["hour"], + minute=data["min"], + second=data["sec"], + tzinfo=dt_util.get_default_time_zone(), + ) + + async def async_set_value(self, value: time) -> None: + """Change the value.""" + await self._device.async_request( + self._device.api.set_time, + hour=value.hour, + minute=value.minute, + second=value.second, + day=self._coordinator.data["dayofweek"], + ) + self._attr_native_value = value + self.async_write_ha_state() diff --git a/tests/components/broadlink/__init__.py b/tests/components/broadlink/__init__.py index 1c87de8d9e2569b512cac0af66dc3fa4d4cae866..61ef27815fdf98493737ffa8e275dbfab2429605 100644 --- a/tests/components/broadlink/__init__.py +++ b/tests/components/broadlink/__init__.py @@ -89,6 +89,16 @@ BROADLINK_DEVICES = { 57, 5, ), + "Guest room": ( + "192.168.0.66", + "34ea34b61d2e", + "HY02/HY03", + "Hysen", + "HYS", + 0x4EAD, + 10024, + 5, + ), } diff --git a/tests/components/broadlink/test_time.py b/tests/components/broadlink/test_time.py new file mode 100644 index 0000000000000000000000000000000000000000..819954158bb66a30d2b0191b6fa691c564df3694 --- /dev/null +++ b/tests/components/broadlink/test_time.py @@ -0,0 +1,67 @@ +"""Tests for Broadlink time.""" + +from homeassistant.components.broadlink.const import DOMAIN +from homeassistant.components.time import ( + ATTR_TIME, + DOMAIN as TIME_DOMAIN, + SERVICE_SET_VALUE, +) +from homeassistant.const import ATTR_ENTITY_ID, Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.helpers.entity_component import async_update_entity + +from . import get_device + + +async def test_time( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, + entity_registry: er.EntityRegistry, +) -> None: + """Test Broadlink time.""" + await hass.config.async_set_time_zone("UTC") + + device = get_device("Guest room") + mock_setup = await device.setup_entry(hass) + + device_entry = device_registry.async_get_device( + identifiers={(DOMAIN, mock_setup.entry.unique_id)} + ) + entries = er.async_entries_for_device(entity_registry, device_entry.id) + times = [entry for entry in entries if entry.domain == Platform.TIME] + assert len(times) == 1 + + time = times[0] + + mock_setup.api.get_full_status.return_value = { + "dayofweek": 3, + "hour": 2, + "min": 3, + "sec": 4, + } + await async_update_entity(hass, time.entity_id) + assert mock_setup.api.get_full_status.call_count == 2 + state = hass.states.get(time.entity_id) + assert state.state == "02:03:04+00:00" + + # set value + await hass.services.async_call( + TIME_DOMAIN, + SERVICE_SET_VALUE, + { + ATTR_ENTITY_ID: time.entity_id, + ATTR_TIME: "03:04:05", + }, + blocking=True, + ) + state = hass.states.get(time.entity_id) + assert state.state == "03:04:05" + assert mock_setup.api.set_time.call_count == 1 + call_args = mock_setup.api.set_time.call_args.kwargs + assert call_args == { + "hour": 3, + "minute": 4, + "second": 5, + "day": 3, + }