mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 19:57:07 +00:00
Expose LitterHopper status for LR4 (#143684)
* Expose LitterHopper status for LR4 * Proper naming and icons * Add simple tests * fix test: lowercase enabled * over-torque, not OT * Don't use icon_fn for simple state map * short not Short * Better state names
This commit is contained in:
parent
30656a4e72
commit
e05f7a9633
@ -6,7 +6,7 @@ from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Generic
|
||||
|
||||
from pylitterbot import LitterRobot, Robot
|
||||
from pylitterbot import LitterRobot, LitterRobot4, Robot
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
@ -47,6 +47,15 @@ BINARY_SENSOR_MAP: dict[type[Robot], tuple[RobotBinarySensorEntityDescription, .
|
||||
is_on_fn=lambda robot: robot.sleep_mode_enabled,
|
||||
),
|
||||
),
|
||||
LitterRobot4: (
|
||||
RobotBinarySensorEntityDescription[LitterRobot4](
|
||||
key="hopper_connected",
|
||||
translation_key="hopper_connected",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
entity_registry_enabled_default=False,
|
||||
is_on_fn=lambda robot: not robot.is_hopper_removed,
|
||||
),
|
||||
),
|
||||
Robot: ( # type: ignore[type-abstract] # only used for isinstance check
|
||||
RobotBinarySensorEntityDescription[Robot](
|
||||
key="power_status",
|
||||
|
@ -6,6 +6,9 @@
|
||||
},
|
||||
"sleep_mode": {
|
||||
"default": "mdi:sleep"
|
||||
},
|
||||
"hopper_connected": {
|
||||
"default": "mdi:filter-check"
|
||||
}
|
||||
},
|
||||
"button": {
|
||||
@ -32,6 +35,19 @@
|
||||
"default": "mdi:scale"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"hopper_status": {
|
||||
"default": "mdi:filter",
|
||||
"state": {
|
||||
"disabled": "mdi:filter-remove",
|
||||
"empty": "mdi:filter-minus-outline",
|
||||
"enabled": "mdi:filter-check",
|
||||
"motor_disconnected": "mdi:engine-off",
|
||||
"motor_fault_short": "mdi:flash-off",
|
||||
"motor_ot_amps": "mdi:flash-alert"
|
||||
}
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"night_light_mode": {
|
||||
"default": "mdi:lightbulb-off",
|
||||
|
@ -57,9 +57,9 @@ ROBOT_SENSOR_MAP: dict[type[Robot], list[RobotSensorEntityDescription]] = {
|
||||
translation_key="sleep_mode_start_time",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
value_fn=(
|
||||
lambda robot: robot.sleep_mode_start_time
|
||||
if robot.sleep_mode_enabled
|
||||
else None
|
||||
lambda robot: (
|
||||
robot.sleep_mode_start_time if robot.sleep_mode_enabled else None
|
||||
)
|
||||
),
|
||||
),
|
||||
RobotSensorEntityDescription[LitterRobot](
|
||||
@ -67,9 +67,9 @@ ROBOT_SENSOR_MAP: dict[type[Robot], list[RobotSensorEntityDescription]] = {
|
||||
translation_key="sleep_mode_end_time",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
value_fn=(
|
||||
lambda robot: robot.sleep_mode_end_time
|
||||
if robot.sleep_mode_enabled
|
||||
else None
|
||||
lambda robot: (
|
||||
robot.sleep_mode_end_time if robot.sleep_mode_enabled else None
|
||||
)
|
||||
),
|
||||
),
|
||||
RobotSensorEntityDescription[LitterRobot](
|
||||
@ -117,6 +117,24 @@ ROBOT_SENSOR_MAP: dict[type[Robot], list[RobotSensorEntityDescription]] = {
|
||||
),
|
||||
],
|
||||
LitterRobot4: [
|
||||
RobotSensorEntityDescription[LitterRobot4](
|
||||
key="hopper_status",
|
||||
translation_key="hopper_status",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=[
|
||||
"enabled",
|
||||
"disabled",
|
||||
"motor_fault_short",
|
||||
"motor_ot_amps",
|
||||
"motor_disconnected",
|
||||
"empty",
|
||||
],
|
||||
value_fn=(
|
||||
lambda robot: (
|
||||
status.name.lower() if (status := robot.hopper_status) else None
|
||||
)
|
||||
),
|
||||
),
|
||||
RobotSensorEntityDescription[LitterRobot4](
|
||||
key="litter_level",
|
||||
translation_key="litter_level",
|
||||
|
@ -34,6 +34,9 @@
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"hopper_connected": {
|
||||
"name": "Hopper connected"
|
||||
},
|
||||
"sleeping": {
|
||||
"name": "Sleeping"
|
||||
},
|
||||
@ -59,6 +62,17 @@
|
||||
"food_level": {
|
||||
"name": "Food level"
|
||||
},
|
||||
"hopper_status": {
|
||||
"name": "Hopper status",
|
||||
"state": {
|
||||
"enabled": "[%key:common::state::enabled%]",
|
||||
"disabled": "[%key:common::state::disabled%]",
|
||||
"motor_fault_short": "Motor shorted",
|
||||
"motor_ot_amps": "Motor overtorqued",
|
||||
"motor_disconnected": "Motor disconnected",
|
||||
"empty": "Empty"
|
||||
}
|
||||
},
|
||||
"last_seen": {
|
||||
"name": "Last seen"
|
||||
},
|
||||
|
@ -7,6 +7,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pylitterbot import Account, FeederRobot, LitterRobot3, LitterRobot4, Pet, Robot
|
||||
from pylitterbot.exceptions import InvalidCommandException
|
||||
from pylitterbot.robot.litterrobot4 import HopperStatus
|
||||
import pytest
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -84,6 +85,15 @@ def mock_account_with_litterrobot_4() -> MagicMock:
|
||||
return create_mock_account(v4=True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_account_with_litterhopper() -> MagicMock:
|
||||
"""Mock account with LitterHopper attached to Litter-Robot 4."""
|
||||
return create_mock_account(
|
||||
robot_data={"hopperStatus": HopperStatus.ENABLED, "isHopperRemoved": False},
|
||||
v4=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_account_with_feederrobot() -> MagicMock:
|
||||
"""Mock account with Feeder-Robot."""
|
||||
|
@ -30,3 +30,18 @@ async def test_binary_sensors(
|
||||
state = hass.states.get("binary_sensor.test_power_status")
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == BinarySensorDeviceClass.PLUG
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_litterhopper_binary_sensors(
|
||||
hass: HomeAssistant,
|
||||
mock_account_with_litterhopper: MagicMock,
|
||||
) -> None:
|
||||
"""Tests LitterHopper-specific binary sensors."""
|
||||
await setup_integration(hass, mock_account_with_litterhopper, BINARY_SENSOR_DOMAIN)
|
||||
|
||||
state = hass.states.get("binary_sensor.test_hopper_connected")
|
||||
assert state.state == "on"
|
||||
assert (
|
||||
state.attributes.get(ATTR_DEVICE_CLASS) == BinarySensorDeviceClass.CONNECTIVITY
|
||||
)
|
||||
|
@ -114,3 +114,12 @@ async def test_pet_weight_sensor(
|
||||
sensor = hass.states.get("sensor.kitty_weight")
|
||||
assert sensor.state == "9.1"
|
||||
assert sensor.attributes["unit_of_measurement"] == UnitOfMass.POUNDS
|
||||
|
||||
|
||||
async def test_litterhopper_sensor(
|
||||
hass: HomeAssistant, mock_account_with_litterhopper: MagicMock
|
||||
) -> None:
|
||||
"""Tests LitterHopper sensors."""
|
||||
await setup_integration(hass, mock_account_with_litterhopper, PLATFORM_DOMAIN)
|
||||
sensor = hass.states.get("sensor.test_hopper_status")
|
||||
assert sensor.state == "enabled"
|
||||
|
Loading…
x
Reference in New Issue
Block a user