Add tampering sensor to deCONZ integration (#49776)
parent
883513e089
commit
056f636568
|
@ -6,6 +6,7 @@ from homeassistant.components.binary_sensor import (
|
|||
DEVICE_CLASS_MOISTURE,
|
||||
DEVICE_CLASS_MOTION,
|
||||
DEVICE_CLASS_OPENING,
|
||||
DEVICE_CLASS_PROBLEM,
|
||||
DEVICE_CLASS_SMOKE,
|
||||
DEVICE_CLASS_VIBRATION,
|
||||
DOMAIN,
|
||||
|
@ -55,6 +56,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
):
|
||||
entities.append(DeconzBinarySensor(sensor, gateway))
|
||||
|
||||
if sensor.tampered is not None:
|
||||
known_tampering_sensors = set(gateway.entities[DOMAIN])
|
||||
new_tampering_sensor = DeconzTampering(sensor, gateway)
|
||||
if new_tampering_sensor.unique_id not in known_tampering_sensors:
|
||||
entities.append(new_tampering_sensor)
|
||||
|
||||
if entities:
|
||||
async_add_entities(entities)
|
||||
|
||||
|
@ -113,3 +120,36 @@ class DeconzBinarySensor(DeconzDevice, BinarySensorEntity):
|
|||
attr[ATTR_VIBRATIONSTRENGTH] = self._device.vibrationstrength
|
||||
|
||||
return attr
|
||||
|
||||
|
||||
class DeconzTampering(DeconzDevice, BinarySensorEntity):
|
||||
"""Representation of a deCONZ tampering sensor."""
|
||||
|
||||
TYPE = DOMAIN
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique identifier for this device."""
|
||||
return f"{self.serial}-tampered"
|
||||
|
||||
@callback
|
||||
def async_update_callback(self, force_update: bool = False) -> None:
|
||||
"""Update the sensor's state."""
|
||||
keys = {"tampered", "reachable"}
|
||||
if force_update or self._device.changed_keys.intersection(keys):
|
||||
super().async_update_callback(force_update=force_update)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the sensor."""
|
||||
return self._device.tampered
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name of the sensor."""
|
||||
return f"{self._device.name} Tampered"
|
||||
|
||||
@property
|
||||
def device_class(self) -> str:
|
||||
"""Return the class of the sensor."""
|
||||
return DEVICE_CLASS_PROBLEM
|
||||
|
|
|
@ -82,7 +82,7 @@ async def test_alarm_control_panel(hass, aioclient_mock, mock_deconz_websocket):
|
|||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 2
|
||||
assert hass.states.get("alarm_control_panel.keypad").state == STATE_ALARM_DISARMED
|
||||
|
||||
# Event signals alarm control panel armed away
|
||||
|
@ -261,7 +261,7 @@ async def test_alarm_control_panel(hass, aioclient_mock, mock_deconz_websocket):
|
|||
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 1
|
||||
assert len(states) == 2
|
||||
for state in states:
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from unittest.mock import patch
|
|||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
DEVICE_CLASS_MOTION,
|
||||
DEVICE_CLASS_PROBLEM,
|
||||
DEVICE_CLASS_VIBRATION,
|
||||
)
|
||||
from homeassistant.components.deconz.const import (
|
||||
|
@ -116,6 +117,52 @@ async def test_binary_sensors(hass, aioclient_mock, mock_deconz_websocket):
|
|||
assert len(hass.states.async_all()) == 0
|
||||
|
||||
|
||||
async def test_tampering_sensor(hass, aioclient_mock, mock_deconz_websocket):
|
||||
"""Verify tampering sensor works."""
|
||||
data = {
|
||||
"sensors": {
|
||||
"1": {
|
||||
"name": "Presence sensor",
|
||||
"type": "ZHAPresence",
|
||||
"state": {"dark": False, "presence": False, "tampered": False},
|
||||
"config": {"on": True, "reachable": True, "temperature": 10},
|
||||
"uniqueid": "00:00:00:00:00:00:00:00-00",
|
||||
},
|
||||
}
|
||||
}
|
||||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
assert len(hass.states.async_all()) == 3
|
||||
presence_tamper = hass.states.get("binary_sensor.presence_sensor_tampered")
|
||||
assert presence_tamper.state == STATE_OFF
|
||||
assert presence_tamper.attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_PROBLEM
|
||||
|
||||
event_changed_sensor = {
|
||||
"t": "event",
|
||||
"e": "changed",
|
||||
"r": "sensors",
|
||||
"id": "1",
|
||||
"state": {"tampered": True},
|
||||
}
|
||||
await mock_deconz_websocket(data=event_changed_sensor)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("binary_sensor.presence_sensor_tampered").state == STATE_ON
|
||||
|
||||
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
|
||||
assert (
|
||||
hass.states.get("binary_sensor.presence_sensor_tampered").state
|
||||
== STATE_UNAVAILABLE
|
||||
)
|
||||
|
||||
await hass.config_entries.async_remove(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 0
|
||||
|
||||
|
||||
async def test_allow_clip_sensor(hass, aioclient_mock):
|
||||
"""Test that CLIP sensors can be allowed."""
|
||||
data = {
|
||||
|
|
|
@ -232,7 +232,7 @@ async def test_deconz_alarm_events(hass, aioclient_mock, mock_deconz_websocket):
|
|||
|
||||
device_registry = await hass.helpers.device_registry.async_get_registry()
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 2
|
||||
# 1 alarm control device + 2 additional devices for deconz service and host
|
||||
assert (
|
||||
len(async_entries_for_config_entry(device_registry, config_entry.entry_id)) == 3
|
||||
|
@ -294,7 +294,7 @@ async def test_deconz_alarm_events(hass, aioclient_mock, mock_deconz_websocket):
|
|||
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 2
|
||||
for state in states:
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
|
Loading…
Reference in New Issue