Add Armed binary sensor to local Risco (#81997)

This commit is contained in:
On Freund 2022-11-12 22:29:31 +02:00 committed by GitHub
parent ee910bd0e4
commit 4bb1f4ec79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 39 deletions

View file

@ -35,6 +35,10 @@ async def async_setup_entry(
RiscoLocalAlarmedBinarySensor(local_data.system.id, zone_id, zone)
for zone_id, zone in local_data.system.zones.items()
)
async_add_entities(
RiscoLocalArmedBinarySensor(local_data.system.id, zone_id, zone)
for zone_id, zone in local_data.system.zones.items()
)
else:
coordinator: RiscoDataUpdateCoordinator = hass.data[DOMAIN][
config_entry.entry_id
@ -92,8 +96,6 @@ class RiscoLocalBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
class RiscoLocalAlarmedBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
"""Representation whether a zone in Risco local is currently triggering an alarm."""
_attr_should_poll = False
def __init__(self, system_id: str, zone_id: int, zone: Zone) -> None:
"""Init the zone."""
super().__init__(
@ -108,3 +110,22 @@ class RiscoLocalAlarmedBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return self._zone.alarmed
class RiscoLocalArmedBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
"""Representation whether a zone in Risco local is currently armed."""
def __init__(self, system_id: str, zone_id: int, zone: Zone) -> None:
"""Init the zone."""
super().__init__(
system_id=system_id,
name="Armed",
suffix="_armed",
zone_id=zone_id,
zone=zone,
)
@property
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return self._zone.armed

View file

@ -3,7 +3,7 @@
"name": "Risco",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/risco",
"requirements": ["pyrisco==0.5.5"],
"requirements": ["pyrisco==0.5.6"],
"codeowners": ["@OnFreund"],
"quality_scale": "platinum",
"iot_class": "local_push",

View file

@ -1860,7 +1860,7 @@ pyrecswitch==1.0.2
pyrepetierng==0.1.0
# homeassistant.components.risco
pyrisco==0.5.5
pyrisco==0.5.6
# homeassistant.components.rituals_perfume_genie
pyrituals==0.0.6

View file

@ -1316,7 +1316,7 @@ pyps4-2ndscreen==1.3.1
pyqwikswitch==0.93
# homeassistant.components.risco
pyrisco==0.5.5
pyrisco==0.5.6
# homeassistant.components.rituals_perfume_genie
pyrituals==0.0.6

View file

@ -70,6 +70,8 @@ def two_zone_local():
zone_mocks[0], "alarmed", new_callable=PropertyMock(return_value=False)
), patch.object(
zone_mocks[0], "bypassed", new_callable=PropertyMock(return_value=False)
), patch.object(
zone_mocks[0], "armed", new_callable=PropertyMock(return_value=False)
), patch.object(
zone_mocks[1], "id", new_callable=PropertyMock(return_value=1)
), patch.object(
@ -78,6 +80,8 @@ def two_zone_local():
zone_mocks[1], "alarmed", new_callable=PropertyMock(return_value=False)
), patch.object(
zone_mocks[1], "bypassed", new_callable=PropertyMock(return_value=False)
), patch.object(
zone_mocks[1], "armed", new_callable=PropertyMock(return_value=False)
), patch(
"homeassistant.components.risco.RiscoLocal.partitions",
new_callable=PropertyMock(return_value={}),

View file

@ -15,6 +15,8 @@ FIRST_ENTITY_ID = "binary_sensor.zone_0"
SECOND_ENTITY_ID = "binary_sensor.zone_1"
FIRST_ALARMED_ENTITY_ID = FIRST_ENTITY_ID + "_alarmed"
SECOND_ALARMED_ENTITY_ID = SECOND_ENTITY_ID + "_alarmed"
FIRST_ARMED_ENTITY_ID = FIRST_ENTITY_ID + "_armed"
SECOND_ARMED_ENTITY_ID = SECOND_ENTITY_ID + "_armed"
@pytest.mark.parametrize("exception", [CannotConnectError, UnauthorizedError])
@ -95,33 +97,19 @@ async def test_local_setup(hass, two_zone_local, setup_risco_local):
assert device.manufacturer == "Risco"
async def _check_local_state(hass, zones, triggered, entity_id, zone_id, callback):
with patch.object(
zones[zone_id],
"triggered",
new_callable=PropertyMock(return_value=triggered),
):
await callback(zone_id, zones[zone_id])
await hass.async_block_till_done()
expected_triggered = STATE_ON if triggered else STATE_OFF
assert hass.states.get(entity_id).state == expected_triggered
assert hass.states.get(entity_id).attributes["zone_id"] == zone_id
async def _check_alarmed_local_state(
hass, zones, alarmed, entity_id, zone_id, callback
async def _check_local_state(
hass, zones, property, value, entity_id, zone_id, callback
):
with patch.object(
zones[zone_id],
"alarmed",
new_callable=PropertyMock(return_value=alarmed),
property,
new_callable=PropertyMock(return_value=value),
):
await callback(zone_id, zones[zone_id])
await hass.async_block_till_done()
expected_alarmed = STATE_ON if alarmed else STATE_OFF
assert hass.states.get(entity_id).state == expected_alarmed
expected_value = STATE_ON if value else STATE_OFF
assert hass.states.get(entity_id).state == expected_value
assert hass.states.get(entity_id).attributes["zone_id"] == zone_id
@ -134,34 +122,64 @@ def _mock_zone_handler():
async def test_local_states(
hass, two_zone_local, _mock_zone_handler, setup_risco_local
):
"""Test the various alarm states."""
"""Test the various zone states."""
callback = _mock_zone_handler.call_args.args[0]
assert callback is not None
await _check_local_state(hass, two_zone_local, True, FIRST_ENTITY_ID, 0, callback)
await _check_local_state(hass, two_zone_local, False, FIRST_ENTITY_ID, 0, callback)
await _check_local_state(hass, two_zone_local, True, SECOND_ENTITY_ID, 1, callback)
await _check_local_state(hass, two_zone_local, False, SECOND_ENTITY_ID, 1, callback)
await _check_local_state(
hass, two_zone_local, "triggered", True, FIRST_ENTITY_ID, 0, callback
)
await _check_local_state(
hass, two_zone_local, "triggered", False, FIRST_ENTITY_ID, 0, callback
)
await _check_local_state(
hass, two_zone_local, "triggered", True, SECOND_ENTITY_ID, 1, callback
)
await _check_local_state(
hass, two_zone_local, "triggered", False, SECOND_ENTITY_ID, 1, callback
)
async def test_alarmed_local_states(
hass, two_zone_local, _mock_zone_handler, setup_risco_local
):
"""Test the various alarm states."""
"""Test the various zone alarmed states."""
callback = _mock_zone_handler.call_args.args[0]
assert callback is not None
await _check_alarmed_local_state(
hass, two_zone_local, True, FIRST_ALARMED_ENTITY_ID, 0, callback
await _check_local_state(
hass, two_zone_local, "alarmed", True, FIRST_ALARMED_ENTITY_ID, 0, callback
)
await _check_alarmed_local_state(
hass, two_zone_local, False, FIRST_ALARMED_ENTITY_ID, 0, callback
await _check_local_state(
hass, two_zone_local, "alarmed", False, FIRST_ALARMED_ENTITY_ID, 0, callback
)
await _check_alarmed_local_state(
hass, two_zone_local, True, SECOND_ALARMED_ENTITY_ID, 1, callback
await _check_local_state(
hass, two_zone_local, "alarmed", True, SECOND_ALARMED_ENTITY_ID, 1, callback
)
await _check_alarmed_local_state(
hass, two_zone_local, False, SECOND_ALARMED_ENTITY_ID, 1, callback
await _check_local_state(
hass, two_zone_local, "alarmed", False, SECOND_ALARMED_ENTITY_ID, 1, callback
)
async def test_armed_local_states(
hass, two_zone_local, _mock_zone_handler, setup_risco_local
):
"""Test the various zone armed states."""
callback = _mock_zone_handler.call_args.args[0]
assert callback is not None
await _check_local_state(
hass, two_zone_local, "armed", True, FIRST_ARMED_ENTITY_ID, 0, callback
)
await _check_local_state(
hass, two_zone_local, "armed", False, FIRST_ARMED_ENTITY_ID, 0, callback
)
await _check_local_state(
hass, two_zone_local, "armed", True, SECOND_ARMED_ENTITY_ID, 1, callback
)
await _check_local_state(
hass, two_zone_local, "armed", False, SECOND_ARMED_ENTITY_ID, 1, callback
)