Code cleanup in litterrobot (#86037)

This commit is contained in:
Nathan Spencer 2023-01-16 12:58:30 -07:00 committed by GitHub
parent 5fbc005224
commit c6f60bf45d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 23 additions and 67 deletions

View file

@ -8,18 +8,14 @@ from typing import Any, Generic
from pylitterbot import FeederRobot, LitterRobot3 from pylitterbot import FeederRobot, LitterRobot3
from homeassistant.components.button import ( from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
DOMAIN as PLATFORM,
ButtonEntity,
ButtonEntityDescription,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
from .entity import LitterRobotEntity, _RobotT, async_update_unique_id from .entity import LitterRobotEntity, _RobotT
from .hub import LitterRobotHub from .hub import LitterRobotHub
@ -47,7 +43,6 @@ async def async_setup_entry(
), ),
) )
) )
async_update_unique_id(hass, PLATFORM, entities)
async_add_entities(entities) async_add_entities(entities)
@ -65,7 +60,7 @@ class RobotButtonEntityDescription(ButtonEntityDescription, RequiredKeysMixin[_R
LITTER_ROBOT_BUTTON = RobotButtonEntityDescription[LitterRobot3]( LITTER_ROBOT_BUTTON = RobotButtonEntityDescription[LitterRobot3](
key="reset_waste_drawer", key="reset_waste_drawer",
name="Reset Waste Drawer", name="Reset waste drawer",
icon="mdi:delete-variant", icon="mdi:delete-variant",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
press_fn=lambda robot: robot.reset_waste_drawer(), press_fn=lambda robot: robot.reset_waste_drawer(),

View file

@ -1,15 +1,12 @@
"""Litter-Robot entities for common data and methods.""" """Litter-Robot entities for common data and methods."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Iterable
from typing import Generic, TypeVar from typing import Generic, TypeVar
from pylitterbot import Robot from pylitterbot import Robot
from pylitterbot.robot import EVENT_UPDATE from pylitterbot.robot import EVENT_UPDATE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo, EntityDescription from homeassistant.helpers.entity import DeviceInfo, EntityDescription
import homeassistant.helpers.entity_registry as er
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
CoordinatorEntity, CoordinatorEntity,
DataUpdateCoordinator, DataUpdateCoordinator,
@ -37,9 +34,6 @@ class LitterRobotEntity(
self.hub = hub self.hub = hub
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{self.robot.serial}-{description.key}" self._attr_unique_id = f"{self.robot.serial}-{description.key}"
# The following can be removed in 2022.12 after adjusting names in entities appropriately
if description.name is not None:
self._attr_name = description.name.capitalize()
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
@ -57,18 +51,3 @@ class LitterRobotEntity(
"""Set up a listener for the entity.""" """Set up a listener for the entity."""
await super().async_added_to_hass() await super().async_added_to_hass()
self.async_on_remove(self.robot.on(EVENT_UPDATE, self.async_write_ha_state)) self.async_on_remove(self.robot.on(EVENT_UPDATE, self.async_write_ha_state))
def async_update_unique_id(
hass: HomeAssistant, domain: str, entities: Iterable[LitterRobotEntity[_RobotT]]
) -> None:
"""Update unique ID to be based on entity description key instead of name.
Introduced with release 2022.9.
"""
ent_reg = er.async_get(hass)
for entity in entities:
old_unique_id = f"{entity.robot.serial}-{entity.entity_description.name}"
if entity_id := ent_reg.async_get_entity_id(domain, DOMAIN, old_unique_id):
new_unique_id = f"{entity.robot.serial}-{entity.entity_description.key}"
ent_reg.async_update_entity(entity_id, new_unique_id=new_unique_id)

View file

@ -8,11 +8,7 @@ from typing import Any, Generic, TypeVar
from pylitterbot import FeederRobot, LitterRobot from pylitterbot import FeederRobot, LitterRobot
from homeassistant.components.select import ( from homeassistant.components.select import SelectEntity, SelectEntityDescription
DOMAIN as PLATFORM,
SelectEntity,
SelectEntityDescription,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfTime from homeassistant.const import UnitOfTime
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@ -20,7 +16,7 @@ from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
from .entity import LitterRobotEntity, _RobotT, async_update_unique_id from .entity import LitterRobotEntity, _RobotT
from .hub import LitterRobotHub from .hub import LitterRobotHub
_CastTypeT = TypeVar("_CastTypeT", int, float) _CastTypeT = TypeVar("_CastTypeT", int, float)
@ -46,7 +42,7 @@ class RobotSelectEntityDescription(
LITTER_ROBOT_SELECT = RobotSelectEntityDescription[LitterRobot, int]( LITTER_ROBOT_SELECT = RobotSelectEntityDescription[LitterRobot, int](
key="cycle_delay", key="cycle_delay",
name="Clean Cycle Wait Time Minutes", name="Clean cycle wait time minutes",
icon="mdi:timer-outline", icon="mdi:timer-outline",
unit_of_measurement=UnitOfTime.MINUTES, unit_of_measurement=UnitOfTime.MINUTES,
current_fn=lambda robot: robot.clean_cycle_wait_time_minutes, current_fn=lambda robot: robot.clean_cycle_wait_time_minutes,
@ -83,7 +79,6 @@ async def async_setup_entry(
), ),
) )
) )
async_update_unique_id(hass, PLATFORM, entities)
async_add_entities(entities) async_add_entities(entities)

View file

@ -9,7 +9,6 @@ from typing import Any, Generic, Union, cast
from pylitterbot import FeederRobot, LitterRobot, LitterRobot4, Robot from pylitterbot import FeederRobot, LitterRobot, LitterRobot4, Robot
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
DOMAIN as PLATFORM,
SensorDeviceClass, SensorDeviceClass,
SensorEntity, SensorEntity,
SensorEntityDescription, SensorEntityDescription,
@ -22,7 +21,7 @@ from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
from .entity import LitterRobotEntity, _RobotT, async_update_unique_id from .entity import LitterRobotEntity, _RobotT
from .hub import LitterRobotHub from .hub import LitterRobotHub
@ -71,32 +70,32 @@ ROBOT_SENSOR_MAP: dict[type[Robot], list[RobotSensorEntityDescription]] = {
LitterRobot: [ LitterRobot: [
RobotSensorEntityDescription[LitterRobot]( RobotSensorEntityDescription[LitterRobot](
key="waste_drawer_level", key="waste_drawer_level",
name="Waste Drawer", name="Waste drawer",
native_unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
icon_fn=lambda state: icon_for_gauge_level(state, 10), icon_fn=lambda state: icon_for_gauge_level(state, 10),
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
RobotSensorEntityDescription[LitterRobot]( RobotSensorEntityDescription[LitterRobot](
key="sleep_mode_start_time", key="sleep_mode_start_time",
name="Sleep Mode Start Time", name="Sleep mode start time",
device_class=SensorDeviceClass.TIMESTAMP, device_class=SensorDeviceClass.TIMESTAMP,
should_report=lambda robot: robot.sleep_mode_enabled, should_report=lambda robot: robot.sleep_mode_enabled,
), ),
RobotSensorEntityDescription[LitterRobot]( RobotSensorEntityDescription[LitterRobot](
key="sleep_mode_end_time", key="sleep_mode_end_time",
name="Sleep Mode End Time", name="Sleep mode end time",
device_class=SensorDeviceClass.TIMESTAMP, device_class=SensorDeviceClass.TIMESTAMP,
should_report=lambda robot: robot.sleep_mode_enabled, should_report=lambda robot: robot.sleep_mode_enabled,
), ),
RobotSensorEntityDescription[LitterRobot]( RobotSensorEntityDescription[LitterRobot](
key="last_seen", key="last_seen",
name="Last Seen", name="Last seen",
device_class=SensorDeviceClass.TIMESTAMP, device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
), ),
RobotSensorEntityDescription[LitterRobot]( RobotSensorEntityDescription[LitterRobot](
key="status_code", key="status_code",
name="Status Code", name="Status code",
translation_key="status_code", translation_key="status_code",
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
device_class=SensorDeviceClass.ENUM, device_class=SensorDeviceClass.ENUM,
@ -171,5 +170,4 @@ async def async_setup_entry(
if isinstance(robot, robot_type) if isinstance(robot, robot_type)
for description in entity_descriptions for description in entity_descriptions
] ]
async_update_unique_id(hass, PLATFORM, entities)
async_add_entities(entities) async_add_entities(entities)

View file

@ -7,18 +7,14 @@ from typing import Any, Generic, Union
from pylitterbot import FeederRobot, LitterRobot from pylitterbot import FeederRobot, LitterRobot
from homeassistant.components.switch import ( from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
DOMAIN as PLATFORM,
SwitchEntity,
SwitchEntityDescription,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import DOMAIN
from .entity import LitterRobotEntity, _RobotT, async_update_unique_id from .entity import LitterRobotEntity, _RobotT
from .hub import LitterRobotHub from .hub import LitterRobotHub
@ -40,13 +36,13 @@ class RobotSwitchEntityDescription(SwitchEntityDescription, RequiredKeysMixin[_R
ROBOT_SWITCHES = [ ROBOT_SWITCHES = [
RobotSwitchEntityDescription[Union[LitterRobot, FeederRobot]]( RobotSwitchEntityDescription[Union[LitterRobot, FeederRobot]](
key="night_light_mode_enabled", key="night_light_mode_enabled",
name="Night Light Mode", name="Night light mode",
icons=("mdi:lightbulb-on", "mdi:lightbulb-off"), icons=("mdi:lightbulb-on", "mdi:lightbulb-off"),
set_fn=lambda robot, value: robot.set_night_light(value), set_fn=lambda robot, value: robot.set_night_light(value),
), ),
RobotSwitchEntityDescription[Union[LitterRobot, FeederRobot]]( RobotSwitchEntityDescription[Union[LitterRobot, FeederRobot]](
key="panel_lock_enabled", key="panel_lock_enabled",
name="Panel Lockout", name="Panel lockout",
icons=("mdi:lock", "mdi:lock-open"), icons=("mdi:lock", "mdi:lock-open"),
set_fn=lambda robot, value: robot.set_panel_lockout(value), set_fn=lambda robot, value: robot.set_panel_lockout(value),
), ),
@ -91,5 +87,4 @@ async def async_setup_entry(
for robot in hub.account.robots for robot in hub.account.robots
if isinstance(robot, (LitterRobot, FeederRobot)) if isinstance(robot, (LitterRobot, FeederRobot))
] ]
async_update_unique_id(hass, PLATFORM, entities)
async_add_entities(entities) async_add_entities(entities)

View file

@ -36,10 +36,9 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up Litter-Robot update platform.""" """Set up Litter-Robot update platform."""
hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id] hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id]
robots = hub.account.robots
entities = [ entities = [
RobotUpdateEntity(robot=robot, hub=hub, description=FIRMWARE_UPDATE_ENTITY) RobotUpdateEntity(robot=robot, hub=hub, description=FIRMWARE_UPDATE_ENTITY)
for robot in robots for robot in hub.litter_robots()
if isinstance(robot, LitterRobot4) if isinstance(robot, LitterRobot4)
] ]
async_add_entities(entities, True) async_add_entities(entities, True)

View file

@ -9,7 +9,6 @@ from pylitterbot.enums import LitterBoxStatus
import voluptuous as vol import voluptuous as vol
from homeassistant.components.vacuum import ( from homeassistant.components.vacuum import (
DOMAIN as PLATFORM,
STATE_CLEANING, STATE_CLEANING,
STATE_DOCKED, STATE_DOCKED,
STATE_ERROR, STATE_ERROR,
@ -26,7 +25,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import DOMAIN from .const import DOMAIN
from .entity import LitterRobotEntity, async_update_unique_id from .entity import LitterRobotEntity
from .hub import LitterRobotHub from .hub import LitterRobotHub
SERVICE_SET_SLEEP_MODE = "set_sleep_mode" SERVICE_SET_SLEEP_MODE = "set_sleep_mode"
@ -43,7 +42,7 @@ LITTER_BOX_STATUS_STATE_MAP = {
LitterBoxStatus.OFF: STATE_OFF, LitterBoxStatus.OFF: STATE_OFF,
} }
LITTER_BOX_ENTITY = StateVacuumEntityDescription("litter_box", name="Litter Box") LITTER_BOX_ENTITY = StateVacuumEntityDescription("litter_box", name="Litter box")
async def async_setup_entry( async def async_setup_entry(
@ -53,12 +52,10 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up Litter-Robot cleaner using config entry.""" """Set up Litter-Robot cleaner using config entry."""
hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id] hub: LitterRobotHub = hass.data[DOMAIN][entry.entry_id]
entities = [ entities = [
LitterRobotCleaner(robot=robot, hub=hub, description=LITTER_BOX_ENTITY) LitterRobotCleaner(robot=robot, hub=hub, description=LITTER_BOX_ENTITY)
for robot in hub.litter_robots() for robot in hub.litter_robots()
] ]
async_update_unique_id(hass, PLATFORM, entities)
async_add_entities(entities) async_add_entities(entities)
platform = entity_platform.async_get_current_platform() platform = entity_platform.async_get_current_platform()

View file

@ -24,8 +24,7 @@ import homeassistant.helpers.entity_registry as er
from .common import VACUUM_ENTITY_ID from .common import VACUUM_ENTITY_ID
from .conftest import setup_integration from .conftest import setup_integration
VACUUM_UNIQUE_ID_OLD = "LR3C012345-Litter Box" VACUUM_UNIQUE_ID = "LR3C012345-litter_box"
VACUUM_UNIQUE_ID_NEW = "LR3C012345-litter_box"
COMPONENT_SERVICE_DOMAIN = { COMPONENT_SERVICE_DOMAIN = {
SERVICE_SET_SLEEP_MODE: DOMAIN, SERVICE_SET_SLEEP_MODE: DOMAIN,
@ -36,15 +35,14 @@ async def test_vacuum(hass: HomeAssistant, mock_account: MagicMock) -> None:
"""Tests the vacuum entity was set up.""" """Tests the vacuum entity was set up."""
ent_reg = er.async_get(hass) ent_reg = er.async_get(hass)
# Create entity entry to migrate to new unique ID
ent_reg.async_get_or_create( ent_reg.async_get_or_create(
PLATFORM_DOMAIN, PLATFORM_DOMAIN,
DOMAIN, DOMAIN,
VACUUM_UNIQUE_ID_OLD, VACUUM_UNIQUE_ID,
suggested_object_id=VACUUM_ENTITY_ID.replace(PLATFORM_DOMAIN, ""), suggested_object_id=VACUUM_ENTITY_ID.replace(PLATFORM_DOMAIN, ""),
) )
ent_reg_entry = ent_reg.async_get(VACUUM_ENTITY_ID) ent_reg_entry = ent_reg.async_get(VACUUM_ENTITY_ID)
assert ent_reg_entry.unique_id == VACUUM_UNIQUE_ID_OLD assert ent_reg_entry.unique_id == VACUUM_UNIQUE_ID
await setup_integration(hass, mock_account, PLATFORM_DOMAIN) await setup_integration(hass, mock_account, PLATFORM_DOMAIN)
assert len(ent_reg.entities) == 1 assert len(ent_reg.entities) == 1
@ -56,7 +54,7 @@ async def test_vacuum(hass: HomeAssistant, mock_account: MagicMock) -> None:
assert vacuum.attributes["is_sleeping"] is False assert vacuum.attributes["is_sleeping"] is False
ent_reg_entry = ent_reg.async_get(VACUUM_ENTITY_ID) ent_reg_entry = ent_reg.async_get(VACUUM_ENTITY_ID)
assert ent_reg_entry.unique_id == VACUUM_UNIQUE_ID_NEW assert ent_reg_entry.unique_id == VACUUM_UNIQUE_ID
async def test_vacuum_status_when_sleeping( async def test_vacuum_status_when_sleeping(