mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 17:27:10 +00:00
Add binary sensors to drop_connect integration (#106248)
This commit is contained in:
parent
656d0696bb
commit
c41173bb29
@ -15,7 +15,7 @@ from .coordinator import DROPDeviceDataUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
|
138
homeassistant/components/drop_connect/binary_sensor.py
Normal file
138
homeassistant/components/drop_connect/binary_sensor.py
Normal file
@ -0,0 +1,138 @@
|
||||
"""Support for DROP binary sensors."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import (
|
||||
CONF_DEVICE_TYPE,
|
||||
DEV_HUB,
|
||||
DEV_LEAK_DETECTOR,
|
||||
DEV_PROTECTION_VALVE,
|
||||
DEV_PUMP_CONTROLLER,
|
||||
DEV_RO_FILTER,
|
||||
DEV_SALT_SENSOR,
|
||||
DEV_SOFTENER,
|
||||
DOMAIN,
|
||||
)
|
||||
from .coordinator import DROPDeviceDataUpdateCoordinator
|
||||
from .entity import DROPEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
LEAK_ICON = "mdi:pipe-leak"
|
||||
NOTIFICATION_ICON = "mdi:bell-ring"
|
||||
PUMP_ICON = "mdi:water-pump"
|
||||
SALT_ICON = "mdi:shaker"
|
||||
WATER_ICON = "mdi:water"
|
||||
|
||||
# Binary sensor type constants
|
||||
LEAK_DETECTED = "leak"
|
||||
PENDING_NOTIFICATION = "pending_notification"
|
||||
PUMP_STATUS = "pump"
|
||||
RESERVE_IN_USE = "reserve_in_use"
|
||||
SALT_LOW = "salt"
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class DROPBinarySensorEntityDescription(BinarySensorEntityDescription):
|
||||
"""Describes DROP binary sensor entity."""
|
||||
|
||||
value_fn: Callable[[DROPDeviceDataUpdateCoordinator], bool | None]
|
||||
|
||||
|
||||
BINARY_SENSORS: list[DROPBinarySensorEntityDescription] = [
|
||||
DROPBinarySensorEntityDescription(
|
||||
key=LEAK_DETECTED,
|
||||
translation_key=LEAK_DETECTED,
|
||||
icon=LEAK_ICON,
|
||||
device_class=BinarySensorDeviceClass.MOISTURE,
|
||||
value_fn=lambda device: device.drop_api.leak_detected(),
|
||||
),
|
||||
DROPBinarySensorEntityDescription(
|
||||
key=PENDING_NOTIFICATION,
|
||||
translation_key=PENDING_NOTIFICATION,
|
||||
icon=NOTIFICATION_ICON,
|
||||
value_fn=lambda device: device.drop_api.notification_pending(),
|
||||
),
|
||||
DROPBinarySensorEntityDescription(
|
||||
key=SALT_LOW,
|
||||
translation_key=SALT_LOW,
|
||||
icon=SALT_ICON,
|
||||
value_fn=lambda device: device.drop_api.salt_low(),
|
||||
),
|
||||
DROPBinarySensorEntityDescription(
|
||||
key=RESERVE_IN_USE,
|
||||
translation_key=RESERVE_IN_USE,
|
||||
icon=WATER_ICON,
|
||||
value_fn=lambda device: device.drop_api.reserve_in_use(),
|
||||
),
|
||||
DROPBinarySensorEntityDescription(
|
||||
key=PUMP_STATUS,
|
||||
translation_key=PUMP_STATUS,
|
||||
icon=PUMP_ICON,
|
||||
value_fn=lambda device: device.drop_api.pump_status(),
|
||||
),
|
||||
]
|
||||
|
||||
# Defines which binary sensors are used by each device type
|
||||
DEVICE_BINARY_SENSORS: dict[str, list[str]] = {
|
||||
DEV_HUB: [LEAK_DETECTED, PENDING_NOTIFICATION],
|
||||
DEV_LEAK_DETECTOR: [LEAK_DETECTED],
|
||||
DEV_PROTECTION_VALVE: [LEAK_DETECTED],
|
||||
DEV_PUMP_CONTROLLER: [LEAK_DETECTED, PUMP_STATUS],
|
||||
DEV_RO_FILTER: [LEAK_DETECTED],
|
||||
DEV_SALT_SENSOR: [SALT_LOW],
|
||||
DEV_SOFTENER: [RESERVE_IN_USE],
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the DROP binary sensors from config entry."""
|
||||
_LOGGER.debug(
|
||||
"Set up binary sensor for device type %s with entry_id is %s",
|
||||
config_entry.data[CONF_DEVICE_TYPE],
|
||||
config_entry.entry_id,
|
||||
)
|
||||
|
||||
if config_entry.data[CONF_DEVICE_TYPE] in DEVICE_BINARY_SENSORS:
|
||||
async_add_entities(
|
||||
DROPBinarySensor(hass.data[DOMAIN][config_entry.entry_id], sensor)
|
||||
for sensor in BINARY_SENSORS
|
||||
if sensor.key in DEVICE_BINARY_SENSORS[config_entry.data[CONF_DEVICE_TYPE]]
|
||||
)
|
||||
|
||||
|
||||
class DROPBinarySensor(DROPEntity, BinarySensorEntity):
|
||||
"""Representation of a DROP binary sensor."""
|
||||
|
||||
entity_description: DROPBinarySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DROPDeviceDataUpdateCoordinator,
|
||||
entity_description: DROPBinarySensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the binary sensor."""
|
||||
super().__init__(entity_description.key, coordinator)
|
||||
self.entity_description = entity_description
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the binary sensor."""
|
||||
return self.entity_description.value_fn(self.coordinator) == 1
|
@ -25,6 +25,13 @@
|
||||
"cart1": { "name": "Cartridge 1 life remaining" },
|
||||
"cart2": { "name": "Cartridge 2 life remaining" },
|
||||
"cart3": { "name": "Cartridge 3 life remaining" }
|
||||
},
|
||||
"binary_sensor": {
|
||||
"leak": { "name": "Leak detected" },
|
||||
"pending_notification": { "name": "Notification unread" },
|
||||
"reserve_in_use": { "name": "Reserve capacity in use" },
|
||||
"salt": { "name": "Salt low" },
|
||||
"pump": { "name": "Pump status" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
192
tests/components/drop_connect/test_binary_sensor.py
Normal file
192
tests/components/drop_connect/test_binary_sensor.py
Normal file
@ -0,0 +1,192 @@
|
||||
"""Test DROP binary sensor entities."""
|
||||
|
||||
from homeassistant.components.drop_connect.const import DOMAIN
|
||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .common import (
|
||||
TEST_DATA_HUB,
|
||||
TEST_DATA_HUB_RESET,
|
||||
TEST_DATA_HUB_TOPIC,
|
||||
TEST_DATA_LEAK,
|
||||
TEST_DATA_LEAK_RESET,
|
||||
TEST_DATA_LEAK_TOPIC,
|
||||
TEST_DATA_PROTECTION_VALVE,
|
||||
TEST_DATA_PROTECTION_VALVE_RESET,
|
||||
TEST_DATA_PROTECTION_VALVE_TOPIC,
|
||||
TEST_DATA_PUMP_CONTROLLER,
|
||||
TEST_DATA_PUMP_CONTROLLER_RESET,
|
||||
TEST_DATA_PUMP_CONTROLLER_TOPIC,
|
||||
TEST_DATA_RO_FILTER,
|
||||
TEST_DATA_RO_FILTER_RESET,
|
||||
TEST_DATA_RO_FILTER_TOPIC,
|
||||
TEST_DATA_SALT,
|
||||
TEST_DATA_SALT_RESET,
|
||||
TEST_DATA_SALT_TOPIC,
|
||||
TEST_DATA_SOFTENER,
|
||||
TEST_DATA_SOFTENER_RESET,
|
||||
TEST_DATA_SOFTENER_TOPIC,
|
||||
)
|
||||
|
||||
from tests.common import async_fire_mqtt_message
|
||||
from tests.typing import MqttMockHAClient
|
||||
|
||||
|
||||
async def test_binary_sensors_hub(
|
||||
hass: HomeAssistant, config_entry_hub, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for hubs."""
|
||||
config_entry_hub.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
pending_notifications_sensor_name = (
|
||||
"binary_sensor.hub_drop_1_c0ffee_notification_unread"
|
||||
)
|
||||
hass.states.async_set(pending_notifications_sensor_name, STATE_UNKNOWN)
|
||||
leak_sensor_name = "binary_sensor.hub_drop_1_c0ffee_leak_detected"
|
||||
hass.states.async_set(leak_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(hass, TEST_DATA_HUB_TOPIC, TEST_DATA_HUB_RESET)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, TEST_DATA_HUB_TOPIC, TEST_DATA_HUB)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
pending_notifications = hass.states.get(pending_notifications_sensor_name)
|
||||
assert pending_notifications.state == STATE_ON
|
||||
|
||||
leak = hass.states.get(leak_sensor_name)
|
||||
assert leak.state == STATE_OFF
|
||||
|
||||
|
||||
async def test_binary_sensors_salt(
|
||||
hass: HomeAssistant, config_entry_salt, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for salt sensors."""
|
||||
config_entry_salt.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
salt_sensor_name = "binary_sensor.salt_sensor_salt_low"
|
||||
hass.states.async_set(salt_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(hass, TEST_DATA_SALT_TOPIC, TEST_DATA_SALT_RESET)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, TEST_DATA_SALT_TOPIC, TEST_DATA_SALT)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
salt = hass.states.get(salt_sensor_name)
|
||||
assert salt.state == STATE_ON
|
||||
|
||||
|
||||
async def test_binary_sensors_leak(
|
||||
hass: HomeAssistant, config_entry_leak, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for leak detectors."""
|
||||
config_entry_leak.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak_sensor_name = "binary_sensor.leak_detector_leak_detected"
|
||||
hass.states.async_set(leak_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(hass, TEST_DATA_LEAK_TOPIC, TEST_DATA_LEAK_RESET)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, TEST_DATA_LEAK_TOPIC, TEST_DATA_LEAK)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak = hass.states.get(leak_sensor_name)
|
||||
assert leak.state == STATE_ON
|
||||
|
||||
|
||||
async def test_binary_sensors_softener(
|
||||
hass: HomeAssistant, config_entry_softener, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for softeners."""
|
||||
config_entry_softener.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
reserve_in_use_sensor_name = "binary_sensor.softener_reserve_capacity_in_use"
|
||||
hass.states.async_set(reserve_in_use_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(hass, TEST_DATA_SOFTENER_TOPIC, TEST_DATA_SOFTENER_RESET)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, TEST_DATA_SOFTENER_TOPIC, TEST_DATA_SOFTENER)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
reserve_in_use = hass.states.get(reserve_in_use_sensor_name)
|
||||
assert reserve_in_use.state == STATE_ON
|
||||
|
||||
|
||||
async def test_binary_sensors_protection_valve(
|
||||
hass: HomeAssistant, config_entry_protection_valve, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for protection valves."""
|
||||
config_entry_protection_valve.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak_sensor_name = "binary_sensor.protection_valve_leak_detected"
|
||||
hass.states.async_set(leak_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, TEST_DATA_PROTECTION_VALVE_TOPIC, TEST_DATA_PROTECTION_VALVE_RESET
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(
|
||||
hass, TEST_DATA_PROTECTION_VALVE_TOPIC, TEST_DATA_PROTECTION_VALVE
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak = hass.states.get(leak_sensor_name)
|
||||
assert leak.state == STATE_ON
|
||||
|
||||
|
||||
async def test_binary_sensors_pump_controller(
|
||||
hass: HomeAssistant, config_entry_pump_controller, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for pump controllers."""
|
||||
config_entry_pump_controller.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak_sensor_name = "binary_sensor.pump_controller_leak_detected"
|
||||
hass.states.async_set(leak_sensor_name, STATE_UNKNOWN)
|
||||
pump_sensor_name = "binary_sensor.pump_controller_pump_status"
|
||||
hass.states.async_set(pump_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, TEST_DATA_PUMP_CONTROLLER_TOPIC, TEST_DATA_PUMP_CONTROLLER_RESET
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(
|
||||
hass, TEST_DATA_PUMP_CONTROLLER_TOPIC, TEST_DATA_PUMP_CONTROLLER
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak = hass.states.get(leak_sensor_name)
|
||||
assert leak.state == STATE_ON
|
||||
pump = hass.states.get(pump_sensor_name)
|
||||
assert pump.state == STATE_ON
|
||||
|
||||
|
||||
async def test_binary_sensors_ro_filter(
|
||||
hass: HomeAssistant, config_entry_ro_filter, mqtt_mock: MqttMockHAClient
|
||||
) -> None:
|
||||
"""Test DROP binary sensors for RO filters."""
|
||||
config_entry_ro_filter.add_to_hass(hass)
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak_sensor_name = "binary_sensor.ro_filter_leak_detected"
|
||||
hass.states.async_set(leak_sensor_name, STATE_UNKNOWN)
|
||||
|
||||
async_fire_mqtt_message(hass, TEST_DATA_RO_FILTER_TOPIC, TEST_DATA_RO_FILTER_RESET)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, TEST_DATA_RO_FILTER_TOPIC, TEST_DATA_RO_FILTER)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
leak = hass.states.get(leak_sensor_name)
|
||||
assert leak.state == STATE_ON
|
Loading…
x
Reference in New Issue
Block a user