Add support for Feeder-Robot sensors (#77395)

This commit is contained in:
Nathan Spencer 2022-08-29 09:48:24 -06:00 committed by GitHub
parent 2e8d598795
commit d4ae81d2bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 22 deletions

View File

@ -35,6 +35,7 @@ async def async_setup_entry(
class LitterRobotResetWasteDrawerButton(LitterRobotEntity, ButtonEntity): class LitterRobotResetWasteDrawerButton(LitterRobotEntity, ButtonEntity):
"""Litter-Robot reset waste drawer button.""" """Litter-Robot reset waste drawer button."""
robot: LitterRobot3
_attr_icon = "mdi:delete-variant" _attr_icon = "mdi:delete-variant"
_attr_entity_category = EntityCategory.CONFIG _attr_entity_category = EntityCategory.CONFIG

View File

@ -6,7 +6,7 @@ from datetime import time
import logging import logging
from typing import Any from typing import Any
from pylitterbot import LitterRobot from pylitterbot import LitterRobot, Robot
from pylitterbot.exceptions import InvalidCommandException from pylitterbot.exceptions import InvalidCommandException
from typing_extensions import ParamSpec from typing_extensions import ParamSpec
@ -23,7 +23,6 @@ from .const import DOMAIN
from .hub import LitterRobotHub from .hub import LitterRobotHub
_P = ParamSpec("_P") _P = ParamSpec("_P")
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
REFRESH_WAIT_TIME_SECONDS = 8 REFRESH_WAIT_TIME_SECONDS = 8
@ -32,9 +31,7 @@ REFRESH_WAIT_TIME_SECONDS = 8
class LitterRobotEntity(CoordinatorEntity[DataUpdateCoordinator[bool]]): class LitterRobotEntity(CoordinatorEntity[DataUpdateCoordinator[bool]]):
"""Generic Litter-Robot entity representing common data and methods.""" """Generic Litter-Robot entity representing common data and methods."""
def __init__( def __init__(self, robot: Robot, entity_type: str, hub: LitterRobotHub) -> None:
self, robot: LitterRobot, entity_type: str, hub: LitterRobotHub
) -> None:
"""Pass coordinator to CoordinatorEntity.""" """Pass coordinator to CoordinatorEntity."""
super().__init__(hub.coordinator) super().__init__(hub.coordinator)
self.robot = robot self.robot = robot
@ -60,15 +57,16 @@ class LitterRobotEntity(CoordinatorEntity[DataUpdateCoordinator[bool]]):
manufacturer="Litter-Robot", manufacturer="Litter-Robot",
model=self.robot.model, model=self.robot.model,
name=self.robot.name, name=self.robot.name,
sw_version=getattr(self.robot, "firmware", None),
) )
class LitterRobotControlEntity(LitterRobotEntity): class LitterRobotControlEntity(LitterRobotEntity):
"""A Litter-Robot entity that can control the unit.""" """A Litter-Robot entity that can control the unit."""
def __init__( robot: LitterRobot
self, robot: LitterRobot, entity_type: str, hub: LitterRobotHub
) -> None: def __init__(self, robot: Robot, entity_type: str, hub: LitterRobotHub) -> None:
"""Init a Litter-Robot control entity.""" """Init a Litter-Robot control entity."""
super().__init__(robot=robot, entity_type=entity_type, hub=hub) super().__init__(robot=robot, entity_type=entity_type, hub=hub)
self._refresh_callback: CALLBACK_TYPE | None = None self._refresh_callback: CALLBACK_TYPE | None = None
@ -135,11 +133,10 @@ class LitterRobotControlEntity(LitterRobotEntity):
class LitterRobotConfigEntity(LitterRobotControlEntity): class LitterRobotConfigEntity(LitterRobotControlEntity):
"""A Litter-Robot entity that can control configuration of the unit.""" """A Litter-Robot entity that can control configuration of the unit."""
robot: LitterRobot
_attr_entity_category = EntityCategory.CONFIG _attr_entity_category = EntityCategory.CONFIG
def __init__( def __init__(self, robot: Robot, entity_type: str, hub: LitterRobotHub) -> None:
self, robot: LitterRobot, entity_type: str, hub: LitterRobotHub
) -> None:
"""Init a Litter-Robot control entity.""" """Init a Litter-Robot control entity."""
super().__init__(robot=robot, entity_type=entity_type, hub=hub) super().__init__(robot=robot, entity_type=entity_type, hub=hub)
self._assumed_state: bool | None = None self._assumed_state: bool | None = None

View File

@ -6,7 +6,7 @@ from datetime import timedelta
import logging import logging
from typing import Any from typing import Any
from pylitterbot import Account, LitterRobot from pylitterbot import Account, FeederRobot, LitterRobot
from pylitterbot.exceptions import LitterRobotException, LitterRobotLoginException from pylitterbot.exceptions import LitterRobotException, LitterRobotLoginException
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
@ -62,3 +62,9 @@ class LitterRobotHub:
return ( return (
robot for robot in self.account.robots if isinstance(robot, LitterRobot) robot for robot in self.account.robots if isinstance(robot, LitterRobot)
) )
def feeder_robots(self) -> Generator[FeederRobot, Any, Any]:
"""Get Feeder-Robots from the account."""
return (
robot for robot in self.account.robots if isinstance(robot, FeederRobot)
)

View File

@ -6,7 +6,7 @@ from dataclasses import dataclass
from datetime import datetime from datetime import datetime
from typing import Any, Union, cast from typing import Any, Union, cast
from pylitterbot import LitterRobot from pylitterbot import FeederRobot, LitterRobot, Robot
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,
@ -36,23 +36,30 @@ def icon_for_gauge_level(gauge_level: int | None = None, offset: int = 0) -> str
@dataclass @dataclass
class LitterRobotSensorEntityDescription(SensorEntityDescription): class RobotSensorEntityDescription(SensorEntityDescription):
"""A class that describes Litter-Robot sensor entities.""" """A class that describes robot sensor entities."""
icon_fn: Callable[[Any], str | None] = lambda _: None icon_fn: Callable[[Any], str | None] = lambda _: None
should_report: Callable[[Robot], bool] = lambda _: True
@dataclass
class LitterRobotSensorEntityDescription(RobotSensorEntityDescription):
"""A class that describes Litter-Robot sensor entities."""
should_report: Callable[[LitterRobot], bool] = lambda _: True should_report: Callable[[LitterRobot], bool] = lambda _: True
class LitterRobotSensorEntity(LitterRobotEntity, SensorEntity): class LitterRobotSensorEntity(LitterRobotEntity, SensorEntity):
"""Litter-Robot sensor entity.""" """Litter-Robot sensor entity."""
entity_description: LitterRobotSensorEntityDescription entity_description: RobotSensorEntityDescription
def __init__( def __init__(
self, self,
robot: LitterRobot, robot: LitterRobot | FeederRobot,
hub: LitterRobotHub, hub: LitterRobotHub,
description: LitterRobotSensorEntityDescription, description: RobotSensorEntityDescription,
) -> None: ) -> None:
"""Initialize a Litter-Robot sensor entity.""" """Initialize a Litter-Robot sensor entity."""
assert description.name assert description.name
@ -76,7 +83,7 @@ class LitterRobotSensorEntity(LitterRobotEntity, SensorEntity):
return super().icon return super().icon
ROBOT_SENSORS = [ LITTER_ROBOT_SENSORS = [
LitterRobotSensorEntityDescription( LitterRobotSensorEntityDescription(
name="Waste Drawer", name="Waste Drawer",
key="waste_drawer_level", key="waste_drawer_level",
@ -109,6 +116,13 @@ ROBOT_SENSORS = [
), ),
] ]
FEEDER_ROBOT_SENSOR = RobotSensorEntityDescription(
name="Food Level",
key="food_level",
native_unit_of_measurement=PERCENTAGE,
icon_fn=lambda state: icon_for_gauge_level(state, 10),
)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
@ -118,7 +132,15 @@ async def async_setup_entry(
"""Set up Litter-Robot sensors using config entry.""" """Set up Litter-Robot sensors using config entry."""
hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id] hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id]
async_add_entities( async_add_entities(
LitterRobotSensorEntity(robot=robot, hub=hub, description=description) [
for description in ROBOT_SENSORS LitterRobotSensorEntity(robot=robot, hub=hub, description=description)
for robot in hub.litter_robots() for description in LITTER_ROBOT_SENSORS
for robot in hub.litter_robots()
]
+ [
LitterRobotSensorEntity(
robot=robot, hub=hub, description=FEEDER_ROBOT_SENSOR
)
for robot in hub.feeder_robots()
]
) )