From ad9f4db983b54e327758ccd6d8b7db8f2981fee4 Mon Sep 17 00:00:00 2001 From: Patryk <36936369+C6H6@users.noreply.github.com> Date: Tue, 24 Mar 2020 21:49:01 +0100 Subject: [PATCH] Add leak sensor support to Homekit integration (#33171) * Add leak sensor support to Homekit integration * Add leak entries to binary_sensor/strings.json * Revert changes from binary_sensor * Fix * Review fix --- .../homekit_controller/binary_sensor.py | 20 +++++++++++++++ .../components/homekit_controller/const.py | 1 + .../homekit_controller/test_binary_sensor.py | 25 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/homeassistant/components/homekit_controller/binary_sensor.py b/homeassistant/components/homekit_controller/binary_sensor.py index 39d0e19ba40..b96e5f651e3 100644 --- a/homeassistant/components/homekit_controller/binary_sensor.py +++ b/homeassistant/components/homekit_controller/binary_sensor.py @@ -4,6 +4,7 @@ import logging from aiohomekit.model.characteristics import CharacteristicsTypes from homeassistant.components.binary_sensor import ( + DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_OPENING, @@ -89,11 +90,30 @@ class HomeKitOccupancySensor(HomeKitEntity, BinarySensorDevice): return self.service.value(CharacteristicsTypes.OCCUPANCY_DETECTED) == 1 +class HomeKitLeakSensor(HomeKitEntity, BinarySensorDevice): + """Representation of a Homekit leak sensor.""" + + def get_characteristic_types(self): + """Define the homekit characteristics the entity is tracking.""" + return [CharacteristicsTypes.LEAK_DETECTED] + + @property + def device_class(self): + """Define this binary_sensor as a leak sensor.""" + return DEVICE_CLASS_MOISTURE + + @property + def is_on(self): + """Return true if a leak is detected from the binary sensor.""" + return self.service.value(CharacteristicsTypes.LEAK_DETECTED) == 1 + + ENTITY_TYPES = { "motion": HomeKitMotionSensor, "contact": HomeKitContactSensor, "smoke": HomeKitSmokeSensor, "occupancy": HomeKitOccupancySensor, + "leak": HomeKitLeakSensor, } diff --git a/homeassistant/components/homekit_controller/const.py b/homeassistant/components/homekit_controller/const.py index a13ad22df51..7b40863141c 100644 --- a/homeassistant/components/homekit_controller/const.py +++ b/homeassistant/components/homekit_controller/const.py @@ -27,6 +27,7 @@ HOMEKIT_ACCESSORY_DISPATCH = { "temperature": "sensor", "battery": "sensor", "smoke": "binary_sensor", + "leak": "binary_sensor", "fan": "fan", "fanv2": "fan", "air-quality": "air_quality", diff --git a/tests/components/homekit_controller/test_binary_sensor.py b/tests/components/homekit_controller/test_binary_sensor.py index 8817ed5c22d..460d14d0d48 100644 --- a/tests/components/homekit_controller/test_binary_sensor.py +++ b/tests/components/homekit_controller/test_binary_sensor.py @@ -3,6 +3,7 @@ from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.services import ServicesTypes from homeassistant.components.binary_sensor import ( + DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_OPENING, @@ -15,6 +16,7 @@ MOTION_DETECTED = ("motion", "motion-detected") CONTACT_STATE = ("contact", "contact-state") SMOKE_DETECTED = ("smoke", "smoke-detected") OCCUPANCY_DETECTED = ("occupancy", "occupancy-detected") +LEAK_DETECTED = ("leak", "leak-detected") def create_motion_sensor_service(accessory): @@ -107,3 +109,26 @@ async def test_occupancy_sensor_read_state(hass, utcnow): assert state.state == "on" assert state.attributes["device_class"] == DEVICE_CLASS_OCCUPANCY + + +def create_leak_sensor_service(accessory): + """Define leak characteristics.""" + service = accessory.add_service(ServicesTypes.LEAK_SENSOR) + + cur_state = service.add_char(CharacteristicsTypes.LEAK_DETECTED) + cur_state.value = 0 + + +async def test_leak_sensor_read_state(hass, utcnow): + """Test that we can read the state of a HomeKit leak sensor accessory.""" + helper = await setup_test_component(hass, create_leak_sensor_service) + + helper.characteristics[LEAK_DETECTED].value = 0 + state = await helper.poll_and_get_state() + assert state.state == "off" + + helper.characteristics[LEAK_DETECTED].value = 1 + state = await helper.poll_and_get_state() + assert state.state == "on" + + assert state.attributes["device_class"] == DEVICE_CLASS_MOISTURE