diff --git a/homeassistant/components/roborock/binary_sensor.py b/homeassistant/components/roborock/binary_sensor.py new file mode 100644 index 00000000000000..d61c1ee14b9c7c --- /dev/null +++ b/homeassistant/components/roborock/binary_sensor.py @@ -0,0 +1,110 @@ +"""Support for Roborock sensors.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass + +from roborock.roborock_typing import DeviceProp + +from homeassistant.components.binary_sensor import ( + BinarySensorDeviceClass, + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.util import slugify + +from .const import DOMAIN +from .coordinator import RoborockDataUpdateCoordinator +from .device import RoborockCoordinatedEntity + + +@dataclass +class RoborockBinarySensorDescriptionMixin: + """A class that describes binary sensor entities.""" + + value_fn: Callable[[DeviceProp], bool] + + +@dataclass +class RoborockBinarySensorDescription( + BinarySensorEntityDescription, RoborockBinarySensorDescriptionMixin +): + """A class that describes Roborock binary sensors.""" + + +BINARY_SENSOR_DESCRIPTIONS = [ + RoborockBinarySensorDescription( + key="dry_status", + translation_key="mop_drying_status", + icon="mdi:heat-wave", + device_class=BinarySensorDeviceClass.RUNNING, + entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.status.dry_status, + ), + RoborockBinarySensorDescription( + key="water_box_carriage_status", + translation_key="mop_attached", + icon="mdi:square-rounded", + device_class=BinarySensorDeviceClass.CONNECTIVITY, + entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.status.water_box_carriage_status, + ), + RoborockBinarySensorDescription( + key="water_box_status", + translation_key="water_box_attached", + icon="mdi:water", + device_class=BinarySensorDeviceClass.CONNECTIVITY, + entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.status.water_box_status, + ), +] + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the Roborock vacuum binary sensors.""" + coordinators: dict[str, RoborockDataUpdateCoordinator] = hass.data[DOMAIN][ + config_entry.entry_id + ] + async_add_entities( + RoborockBinarySensorEntity( + f"{description.key}_{slugify(device_id)}", + coordinator, + description, + ) + for device_id, coordinator in coordinators.items() + for description in BINARY_SENSOR_DESCRIPTIONS + if description.value_fn(coordinator.roborock_device_info.props) is not None + ) + + +class RoborockBinarySensorEntity(RoborockCoordinatedEntity, BinarySensorEntity): + """Representation of a Roborock binary sensor.""" + + entity_description: RoborockBinarySensorDescription + + def __init__( + self, + unique_id: str, + coordinator: RoborockDataUpdateCoordinator, + description: RoborockBinarySensorDescription, + ) -> None: + """Initialize the entity.""" + super().__init__(unique_id, coordinator) + self.entity_description = description + + @property + def is_on(self) -> bool: + """Return the value reported by the sensor.""" + return bool( + self.entity_description.value_fn( + self.coordinator.roborock_device_info.props + ) + ) diff --git a/homeassistant/components/roborock/const.py b/homeassistant/components/roborock/const.py index 2fc59134d140f8..36078e53b3e9ef 100644 --- a/homeassistant/components/roborock/const.py +++ b/homeassistant/components/roborock/const.py @@ -13,4 +13,5 @@ Platform.SWITCH, Platform.TIME, Platform.NUMBER, + Platform.BINARY_SENSOR, ] diff --git a/homeassistant/components/roborock/strings.json b/homeassistant/components/roborock/strings.json index 5ca2292f804186..269bbf04cf20ad 100644 --- a/homeassistant/components/roborock/strings.json +++ b/homeassistant/components/roborock/strings.json @@ -27,6 +27,17 @@ } }, "entity": { + "binary_sensor": { + "mop_attached": { + "name": "Mop attached" + }, + "mop_drying_status": { + "name": "Mop drying" + }, + "water_box_attached": { + "name": "Water box attached" + } + }, "number": { "volume": { "name": "Volume" diff --git a/tests/components/roborock/test_binary_sensor.py b/tests/components/roborock/test_binary_sensor.py new file mode 100644 index 00000000000000..d4d415424bc45e --- /dev/null +++ b/tests/components/roborock/test_binary_sensor.py @@ -0,0 +1,17 @@ +"""Test Roborock Binary Sensor.""" + +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry + + +async def test_binary_sensors( + hass: HomeAssistant, setup_entry: MockConfigEntry +) -> None: + """Test binary sensors and check test values are correctly set.""" + assert len(hass.states.async_all("binary_sensor")) == 2 + assert hass.states.get("binary_sensor.roborock_s7_maxv_mop_attached").state == "on" + assert ( + hass.states.get("binary_sensor.roborock_s7_maxv_water_box_attached").state + == "on" + )