mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 17:57:55 +00:00
Add button to litterrobot (#59734)
This commit is contained in:
parent
ce9385d442
commit
eaaa53d8d5
@ -2,6 +2,11 @@
|
||||
|
||||
from pylitterbot.exceptions import LitterRobotException, LitterRobotLoginException
|
||||
|
||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN
|
||||
from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.components.vacuum import DOMAIN as VACUUM_DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
@ -9,7 +14,7 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from .const import DOMAIN
|
||||
from .hub import LitterRobotHub
|
||||
|
||||
PLATFORMS = ["select", "sensor", "switch", "vacuum"]
|
||||
PLATFORMS = [BUTTON_DOMAIN, SELECT_DOMAIN, SENSOR_DOMAIN, SWITCH_DOMAIN, VACUUM_DOMAIN]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
43
homeassistant/components/litterrobot/button.py
Normal file
43
homeassistant/components/litterrobot/button.py
Normal file
@ -0,0 +1,43 @@
|
||||
"""Support for Litter-Robot button."""
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.button import ButtonEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .entity import LitterRobotEntity
|
||||
from .hub import LitterRobotHub
|
||||
|
||||
TYPE_RESET_WASTE_DRAWER = "Reset Waste Drawer"
|
||||
|
||||
|
||||
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(
|
||||
[
|
||||
LitterRobotResetWasteDrawerButton(
|
||||
robot=robot, entity_type=TYPE_RESET_WASTE_DRAWER, hub=hub
|
||||
)
|
||||
for robot in hub.account.robots
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class LitterRobotResetWasteDrawerButton(LitterRobotEntity, ButtonEntity):
|
||||
"""Litter-Robot reset waste drawer button."""
|
||||
|
||||
_attr_icon = "mdi:delete-variant"
|
||||
_attr_entity_category = ENTITY_CATEGORY_CONFIG
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Press the button."""
|
||||
await self.robot.reset_waste_drawer()
|
||||
self.coordinator.async_set_updated_data(True)
|
@ -1,6 +1,7 @@
|
||||
"""Support for Litter-Robot "Vacuum"."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from pylitterbot.enums import LitterBoxStatus
|
||||
@ -29,6 +30,8 @@ from .const import DOMAIN
|
||||
from .entity import LitterRobotControlEntity
|
||||
from .hub import LitterRobotHub
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SUPPORT_LITTERROBOT = (
|
||||
SUPPORT_START | SUPPORT_STATE | SUPPORT_STATUS | SUPPORT_TURN_OFF | SUPPORT_TURN_ON
|
||||
)
|
||||
@ -121,6 +124,13 @@ class LitterRobotCleaner(LitterRobotControlEntity, StateVacuumEntity):
|
||||
|
||||
async def async_reset_waste_drawer(self) -> None:
|
||||
"""Reset the waste drawer level."""
|
||||
# The Litter-Robot reset waste drawer service has been replaced by a
|
||||
# dedicated button entity and marked as deprecated
|
||||
_LOGGER.warning(
|
||||
"The 'litterrobot.reset_waste_drawer' service is deprecated and "
|
||||
"replaced by a dedicated reset waste drawer button entity; Please "
|
||||
"use that entity to reset the waste drawer instead"
|
||||
)
|
||||
await self.robot.reset_waste_drawer()
|
||||
self.coordinator.async_set_updated_data(True)
|
||||
|
||||
@ -136,6 +146,13 @@ class LitterRobotCleaner(LitterRobotControlEntity, StateVacuumEntity):
|
||||
|
||||
async def async_set_wait_time(self, minutes: int) -> None:
|
||||
"""Set the wait time."""
|
||||
# The Litter-Robot set wait time service has been replaced by a
|
||||
# dedicated select entity and marked as deprecated
|
||||
_LOGGER.warning(
|
||||
"The 'litterrobot.set_wait_time' service is deprecated and "
|
||||
"replaced by a dedicated set wait time select entity; Please "
|
||||
"use that entity to set the wait time instead"
|
||||
)
|
||||
await self.perform_action_and_refresh(self.robot.set_wait_time, minutes)
|
||||
|
||||
@property
|
||||
|
48
tests/components/litterrobot/test_button.py
Normal file
48
tests/components/litterrobot/test_button.py
Normal file
@ -0,0 +1,48 @@
|
||||
"""Test the Litter-Robot button entity."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from freezegun import freeze_time
|
||||
|
||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_ICON,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .conftest import setup_integration
|
||||
|
||||
BUTTON_ENTITY = "button.test_reset_waste_drawer"
|
||||
|
||||
|
||||
@freeze_time("2021-11-15 17:37:00", tz_offset=-7)
|
||||
async def test_button(hass: HomeAssistant, mock_account: MagicMock) -> None:
|
||||
"""Test the creation and values of the Litter-Robot button."""
|
||||
await setup_integration(hass, mock_account, BUTTON_DOMAIN)
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
state = hass.states.get(BUTTON_ENTITY)
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:delete-variant"
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
entry = entity_registry.async_get(BUTTON_ENTITY)
|
||||
assert entry
|
||||
assert entry.entity_category == ENTITY_CATEGORY_CONFIG
|
||||
|
||||
await hass.services.async_call(
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: BUTTON_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_account.robots[0].reset_waste_drawer.call_count == 1
|
||||
mock_account.robots[0].reset_waste_drawer.assert_called_with()
|
||||
|
||||
state = hass.states.get(BUTTON_ENTITY)
|
||||
assert state
|
||||
assert state.state == "2021-11-15T10:37:00+00:00"
|
@ -1,5 +1,9 @@
|
||||
"""Test the Litter-Robot vacuum entity."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from voluptuous.error import MultipleInvalid
|
||||
@ -36,7 +40,7 @@ COMPONENT_SERVICE_DOMAIN = {
|
||||
}
|
||||
|
||||
|
||||
async def test_vacuum(hass: HomeAssistant, mock_account):
|
||||
async def test_vacuum(hass: HomeAssistant, mock_account: MagicMock) -> None:
|
||||
"""Tests the vacuum entity was set up."""
|
||||
await setup_integration(hass, mock_account, PLATFORM_DOMAIN)
|
||||
assert hass.services.has_service(DOMAIN, SERVICE_RESET_WASTE_DRAWER)
|
||||
@ -48,8 +52,8 @@ async def test_vacuum(hass: HomeAssistant, mock_account):
|
||||
|
||||
|
||||
async def test_vacuum_status_when_sleeping(
|
||||
hass: HomeAssistant, mock_account_with_sleeping_robot
|
||||
):
|
||||
hass: HomeAssistant, mock_account_with_sleeping_robot: MagicMock
|
||||
) -> None:
|
||||
"""Tests the vacuum status when sleeping."""
|
||||
await setup_integration(hass, mock_account_with_sleeping_robot, PLATFORM_DOMAIN)
|
||||
|
||||
@ -58,14 +62,18 @@ async def test_vacuum_status_when_sleeping(
|
||||
assert vacuum.attributes.get(ATTR_STATUS) == "Ready (Sleeping)"
|
||||
|
||||
|
||||
async def test_no_robots(hass: HomeAssistant, mock_account_with_no_robots):
|
||||
async def test_no_robots(
|
||||
hass: HomeAssistant, mock_account_with_no_robots: MagicMock
|
||||
) -> None:
|
||||
"""Tests the vacuum entity was set up."""
|
||||
await setup_integration(hass, mock_account_with_no_robots, PLATFORM_DOMAIN)
|
||||
|
||||
assert not hass.services.has_service(DOMAIN, SERVICE_RESET_WASTE_DRAWER)
|
||||
|
||||
|
||||
async def test_vacuum_with_error(hass: HomeAssistant, mock_account_with_error):
|
||||
async def test_vacuum_with_error(
|
||||
hass: HomeAssistant, mock_account_with_error: MagicMock
|
||||
) -> None:
|
||||
"""Tests a vacuum entity with an error."""
|
||||
await setup_integration(hass, mock_account_with_error, PLATFORM_DOMAIN)
|
||||
|
||||
@ -80,39 +88,34 @@ async def test_vacuum_with_error(hass: HomeAssistant, mock_account_with_error):
|
||||
(SERVICE_START, "start_cleaning", None),
|
||||
(SERVICE_TURN_OFF, "set_power_status", None),
|
||||
(SERVICE_TURN_ON, "set_power_status", None),
|
||||
(
|
||||
SERVICE_RESET_WASTE_DRAWER,
|
||||
"reset_waste_drawer",
|
||||
None,
|
||||
),
|
||||
(SERVICE_RESET_WASTE_DRAWER, "reset_waste_drawer", {"deprecated": True}),
|
||||
(
|
||||
SERVICE_SET_SLEEP_MODE,
|
||||
"set_sleep_mode",
|
||||
{"enabled": True, "start_time": "22:30"},
|
||||
{"data": {"enabled": True, "start_time": "22:30"}},
|
||||
),
|
||||
(SERVICE_SET_SLEEP_MODE, "set_sleep_mode", {"data": {"enabled": True}}),
|
||||
(SERVICE_SET_SLEEP_MODE, "set_sleep_mode", {"data": {"enabled": False}}),
|
||||
(
|
||||
SERVICE_SET_SLEEP_MODE,
|
||||
"set_sleep_mode",
|
||||
{"enabled": True},
|
||||
),
|
||||
(
|
||||
SERVICE_SET_SLEEP_MODE,
|
||||
"set_sleep_mode",
|
||||
{"enabled": False},
|
||||
SERVICE_SET_WAIT_TIME,
|
||||
"set_wait_time",
|
||||
{"data": {"minutes": 3}, "deprecated": True},
|
||||
),
|
||||
(
|
||||
SERVICE_SET_WAIT_TIME,
|
||||
"set_wait_time",
|
||||
{"minutes": 3},
|
||||
),
|
||||
(
|
||||
SERVICE_SET_WAIT_TIME,
|
||||
"set_wait_time",
|
||||
{"minutes": "15"},
|
||||
{"data": {"minutes": "15"}, "deprecated": True},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_commands(hass: HomeAssistant, mock_account, service, command, extra):
|
||||
async def test_commands(
|
||||
hass: HomeAssistant,
|
||||
mock_account: MagicMock,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
service: str,
|
||||
command: str,
|
||||
extra: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test sending commands to the vacuum."""
|
||||
await setup_integration(hass, mock_account, PLATFORM_DOMAIN)
|
||||
|
||||
@ -120,9 +123,9 @@ async def test_commands(hass: HomeAssistant, mock_account, service, command, ext
|
||||
assert vacuum
|
||||
assert vacuum.state == STATE_DOCKED
|
||||
|
||||
data = {ATTR_ENTITY_ID: VACUUM_ENTITY_ID}
|
||||
if extra:
|
||||
data.update(extra)
|
||||
extra = extra or {}
|
||||
data = {ATTR_ENTITY_ID: VACUUM_ENTITY_ID, **extra.get("data", {})}
|
||||
deprecated = extra.get("deprecated", False)
|
||||
|
||||
await hass.services.async_call(
|
||||
COMPONENT_SERVICE_DOMAIN.get(service, PLATFORM_DOMAIN),
|
||||
@ -133,9 +136,10 @@ async def test_commands(hass: HomeAssistant, mock_account, service, command, ext
|
||||
future = utcnow() + timedelta(seconds=REFRESH_WAIT_TIME_SECONDS)
|
||||
async_fire_time_changed(hass, future)
|
||||
getattr(mock_account.robots[0], command).assert_called_once()
|
||||
assert (f"'{DOMAIN}.{service}' service is deprecated" in caplog.text) is deprecated
|
||||
|
||||
|
||||
async def test_invalid_wait_time(hass: HomeAssistant, mock_account):
|
||||
async def test_invalid_wait_time(hass: HomeAssistant, mock_account: MagicMock) -> None:
|
||||
"""Test an attempt to send an invalid wait time to the vacuum."""
|
||||
await setup_integration(hass, mock_account, PLATFORM_DOMAIN)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user