Add time entity for sleep mode start time to Litter-Robot 3 (#94194)

pull/95418/head
Nathan Spencer 2023-06-27 14:25:29 -06:00 committed by GitHub
parent 21c619e702
commit ec8988f8ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 123 additions and 1 deletions

View File

@ -18,7 +18,7 @@ PLATFORMS_BY_TYPE = {
Platform.SWITCH,
),
LitterRobot: (Platform.VACUUM,),
LitterRobot3: (Platform.BUTTON,),
LitterRobot3: (Platform.BUTTON, Platform.TIME),
LitterRobot4: (Platform.UPDATE,),
FeederRobot: (Platform.BUTTON,),
}

View File

@ -128,6 +128,11 @@
"name": "Panel lockout"
}
},
"time": {
"sleep_mode_start_time": {
"name": "Sleep mode start time"
}
},
"vacuum": {
"litter_box": {
"name": "Litter box"

View File

@ -0,0 +1,82 @@
"""Support for Litter-Robot time."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from datetime import datetime, time
from typing import Any, Generic
from pylitterbot import LitterRobot3
from homeassistant.components.time import TimeEntity, TimeEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util
from .const import DOMAIN
from .entity import LitterRobotEntity, _RobotT
from .hub import LitterRobotHub
@dataclass
class RequiredKeysMixin(Generic[_RobotT]):
"""A class that describes robot time entity required keys."""
value_fn: Callable[[_RobotT], time | None]
set_fn: Callable[[_RobotT, time], Coroutine[Any, Any, bool]]
@dataclass
class RobotTimeEntityDescription(TimeEntityDescription, RequiredKeysMixin[_RobotT]):
"""A class that describes robot time entities."""
def _as_local_time(start: datetime | None) -> time | None:
"""Return a datetime as local time."""
return dt_util.as_local(start).time() if start else None
LITTER_ROBOT_3_SLEEP_START = RobotTimeEntityDescription[LitterRobot3](
key="sleep_mode_start_time",
translation_key="sleep_mode_start_time",
entity_category=EntityCategory.CONFIG,
value_fn=lambda robot: _as_local_time(robot.sleep_mode_start_time),
set_fn=lambda robot, value: robot.set_sleep_mode(
robot.sleep_mode_enabled, value.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE)
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Litter-Robot cleaner using config entry."""
hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
[
LitterRobotTimeEntity(
robot=robot, hub=hub, description=LITTER_ROBOT_3_SLEEP_START
)
for robot in hub.litter_robots()
if isinstance(robot, LitterRobot3)
]
)
class LitterRobotTimeEntity(LitterRobotEntity[_RobotT], TimeEntity):
"""Litter-Robot time entity."""
entity_description: RobotTimeEntityDescription[_RobotT]
@property
def native_value(self) -> time | None:
"""Return the value reported by the time."""
return self.entity_description.value_fn(self.robot)
async def async_set_value(self, value: time) -> None:
"""Update the current value."""
await self.entity_description.set_fn(self.robot, value)

View File

@ -0,0 +1,35 @@
"""Test the Litter-Robot time entity."""
from __future__ import annotations
from datetime import time
from unittest.mock import MagicMock
from pylitterbot import LitterRobot3
from homeassistant.components.time import DOMAIN as PLATFORM_DOMAIN
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from .conftest import setup_integration
SLEEP_START_TIME_ENTITY_ID = "time.test_sleep_mode_start_time"
async def test_sleep_mode_start_time(
hass: HomeAssistant, mock_account: MagicMock
) -> None:
"""Tests the sleep mode start time."""
await setup_integration(hass, mock_account, PLATFORM_DOMAIN)
entity = hass.states.get(SLEEP_START_TIME_ENTITY_ID)
assert entity
assert entity.state == "17:16:00"
robot: LitterRobot3 = mock_account.robots[0]
await hass.services.async_call(
PLATFORM_DOMAIN,
"set_value",
{ATTR_ENTITY_ID: SLEEP_START_TIME_ENTITY_ID, "time": time(23, 0)},
blocking=True,
)
robot.set_sleep_mode.assert_awaited_once_with(True, time(23, 0))