Add zone_entity_id to Risco events (#39678)
* Add zone_entity_id to Risco events * Add comment * Fix dependency on order
This commit is contained in:
parent
7c397a02b7
commit
5a7e4b4dae
6 changed files with 90 additions and 79 deletions
|
@ -5,7 +5,7 @@ from homeassistant.components.binary_sensor import (
|
|||
)
|
||||
from homeassistant.helpers import entity_platform
|
||||
|
||||
from .const import DATA_COORDINATOR, DOMAIN
|
||||
from .const import DATA_COORDINATOR, DATA_ZONES, DOMAIN
|
||||
from .entity import RiscoEntity
|
||||
|
||||
SERVICE_BYPASS_ZONE = "bypass_zone"
|
||||
|
@ -21,12 +21,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
)
|
||||
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id][DATA_COORDINATOR]
|
||||
entities = [
|
||||
RiscoBinarySensor(coordinator, zone_id, zone)
|
||||
entities = {
|
||||
zone_id: RiscoBinarySensor(coordinator, zone_id, zone)
|
||||
for zone_id, zone in coordinator.data.zones.items()
|
||||
]
|
||||
|
||||
async_add_entities(entities, False)
|
||||
}
|
||||
hass.data[DOMAIN][config_entry.entry_id][DATA_ZONES] = entities
|
||||
async_add_entities(entities.values(), False)
|
||||
|
||||
|
||||
class RiscoBinarySensor(BinarySensorEntity, RiscoEntity):
|
||||
|
@ -63,7 +63,7 @@ class RiscoBinarySensor(BinarySensorEntity, RiscoEntity):
|
|||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return {"bypassed": self._zone.bypassed}
|
||||
return {"zone_id": self._zone_id, "bypassed": self._zone.bypassed}
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
|
|
|
@ -11,6 +11,7 @@ DOMAIN = "risco"
|
|||
RISCO_EVENT = "risco_event"
|
||||
|
||||
DATA_COORDINATOR = "risco"
|
||||
DATA_ZONES = "zones"
|
||||
EVENTS_COORDINATOR = "risco_events"
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = 30
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from homeassistant.const import DEVICE_CLASS_TIMESTAMP
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN, EVENTS_COORDINATOR
|
||||
from .const import DATA_ZONES, DOMAIN, EVENTS_COORDINATOR
|
||||
|
||||
CATEGORIES = {
|
||||
2: "Alarm",
|
||||
|
@ -29,22 +29,28 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
"""Set up sensors for device."""
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id][EVENTS_COORDINATOR]
|
||||
sensors = [
|
||||
RiscoSensor(coordinator, id, [], name) for id, name in CATEGORIES.items()
|
||||
RiscoSensor(coordinator, id, [], name, config_entry.entry_id)
|
||||
for id, name in CATEGORIES.items()
|
||||
]
|
||||
sensors.append(RiscoSensor(coordinator, None, CATEGORIES.keys(), "Other"))
|
||||
sensors.append(
|
||||
RiscoSensor(
|
||||
coordinator, None, CATEGORIES.keys(), "Other", config_entry.entry_id
|
||||
)
|
||||
)
|
||||
async_add_entities(sensors)
|
||||
|
||||
|
||||
class RiscoSensor(CoordinatorEntity):
|
||||
"""Sensor for Risco events."""
|
||||
|
||||
def __init__(self, coordinator, category_id, excludes, name) -> None:
|
||||
def __init__(self, coordinator, category_id, excludes, name, entry_id) -> None:
|
||||
"""Initialize sensor."""
|
||||
super().__init__(coordinator)
|
||||
self._event = None
|
||||
self._category_id = category_id
|
||||
self._excludes = excludes
|
||||
self._name = name
|
||||
self._entry_id = entry_id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -88,7 +94,14 @@ class RiscoSensor(CoordinatorEntity):
|
|||
if self._event is None:
|
||||
return None
|
||||
|
||||
return {atr: getattr(self._event, atr, None) for atr in EVENT_ATTRIBUTES}
|
||||
attrs = {atr: getattr(self._event, atr, None) for atr in EVENT_ATTRIBUTES}
|
||||
if self._event.zone_id is not None:
|
||||
zones = self.hass.data[DOMAIN][self._entry_id][DATA_ZONES]
|
||||
zone = zones.get(self._event.zone_id)
|
||||
if zone is not None:
|
||||
attrs["zone_entity_id"] = zone.entity_id
|
||||
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
|
|
|
@ -1,51 +1,19 @@
|
|||
"""Tests for the Risco binary sensors."""
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.risco import CannotConnectError, UnauthorizedError
|
||||
from homeassistant.components.risco.const import DOMAIN
|
||||
from homeassistant.const import STATE_OFF, STATE_ON
|
||||
from homeassistant.helpers.entity_component import async_update_entity
|
||||
|
||||
from .util import TEST_CONFIG, TEST_SITE_UUID, setup_risco
|
||||
from .util import two_zone_alarm # noqa: F401
|
||||
|
||||
from tests.async_mock import MagicMock, PropertyMock, patch
|
||||
from tests.async_mock import PropertyMock, patch
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
FIRST_ENTITY_ID = "binary_sensor.zone_0"
|
||||
SECOND_ENTITY_ID = "binary_sensor.zone_1"
|
||||
|
||||
|
||||
def _zone_mock():
|
||||
return MagicMock(
|
||||
triggered=False,
|
||||
bypassed=False,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def two_zone_alarm():
|
||||
"""Fixture to mock alarm with two zones."""
|
||||
zone_mocks = {0: _zone_mock(), 1: _zone_mock()}
|
||||
alarm_mock = MagicMock()
|
||||
with patch.object(
|
||||
zone_mocks[0], "id", new_callable=PropertyMock(return_value=0)
|
||||
), patch.object(
|
||||
zone_mocks[0], "name", new_callable=PropertyMock(return_value="Zone 0")
|
||||
), patch.object(
|
||||
zone_mocks[1], "id", new_callable=PropertyMock(return_value=1)
|
||||
), patch.object(
|
||||
zone_mocks[1], "name", new_callable=PropertyMock(return_value="Zone 1")
|
||||
), patch.object(
|
||||
alarm_mock,
|
||||
"zones",
|
||||
new_callable=PropertyMock(return_value=zone_mocks),
|
||||
), patch(
|
||||
"homeassistant.components.risco.RiscoAPI.get_state",
|
||||
return_value=alarm_mock,
|
||||
):
|
||||
yield alarm_mock
|
||||
|
||||
|
||||
async def test_cannot_connect(hass):
|
||||
"""Test connection error."""
|
||||
|
||||
|
@ -78,7 +46,7 @@ async def test_unauthorized(hass):
|
|||
assert not registry.async_is_registered(SECOND_ENTITY_ID)
|
||||
|
||||
|
||||
async def test_setup(hass, two_zone_alarm):
|
||||
async def test_setup(hass, two_zone_alarm): # noqa: F811
|
||||
"""Test entity setup."""
|
||||
registry = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
|
@ -116,9 +84,10 @@ async def _check_state(hass, alarm, triggered, bypassed, entity_id, zone_id):
|
|||
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["bypassed"] == bypassed
|
||||
assert hass.states.get(entity_id).attributes["zone_id"] == zone_id
|
||||
|
||||
|
||||
async def test_states(hass, two_zone_alarm):
|
||||
async def test_states(hass, two_zone_alarm): # noqa: F811
|
||||
"""Test the various alarm states."""
|
||||
await setup_risco(hass)
|
||||
|
||||
|
@ -132,7 +101,7 @@ async def test_states(hass, two_zone_alarm):
|
|||
await _check_state(hass, two_zone_alarm, False, False, SECOND_ENTITY_ID, 1)
|
||||
|
||||
|
||||
async def test_bypass(hass, two_zone_alarm):
|
||||
async def test_bypass(hass, two_zone_alarm): # noqa: F811
|
||||
"""Test bypassing a zone."""
|
||||
await setup_risco(hass)
|
||||
with patch("homeassistant.components.risco.RiscoAPI.bypass_zone") as mock:
|
||||
|
@ -145,7 +114,7 @@ async def test_bypass(hass, two_zone_alarm):
|
|||
mock.assert_awaited_once_with(0, True)
|
||||
|
||||
|
||||
async def test_unbypass(hass, two_zone_alarm):
|
||||
async def test_unbypass(hass, two_zone_alarm): # noqa: F811
|
||||
"""Test unbypassing a zone."""
|
||||
await setup_risco(hass)
|
||||
with patch("homeassistant.components.risco.RiscoAPI.bypass_zone") as mock:
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
"""Tests for the Risco event sensors."""
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.risco import (
|
||||
LAST_EVENT_TIMESTAMP_KEY,
|
||||
CannotConnectError,
|
||||
|
@ -9,6 +7,7 @@ from homeassistant.components.risco import (
|
|||
from homeassistant.components.risco.const import DOMAIN, EVENTS_COORDINATOR
|
||||
|
||||
from .util import TEST_CONFIG, setup_risco
|
||||
from .util import two_zone_alarm # noqa: F401
|
||||
|
||||
from tests.async_mock import MagicMock, patch
|
||||
from tests.common import MockConfigEntry
|
||||
|
@ -60,7 +59,7 @@ TEST_EVENTS = [
|
|||
name="Alarm is on",
|
||||
text="Yes it is.",
|
||||
partition_id=0,
|
||||
zone_id=12,
|
||||
zone_id=1,
|
||||
user_id=None,
|
||||
group=None,
|
||||
priority=0,
|
||||
|
@ -106,16 +105,6 @@ CATEGORIES_TO_EVENTS = {
|
|||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def emptry_alarm():
|
||||
"""Fixture to mock an empty alarm."""
|
||||
with patch(
|
||||
"homeassistant.components.risco.RiscoAPI.get_state",
|
||||
return_value=MagicMock(paritions={}, zones={}),
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
async def test_cannot_connect(hass):
|
||||
"""Test connection error."""
|
||||
|
||||
|
@ -151,23 +140,29 @@ async def test_unauthorized(hass):
|
|||
|
||||
|
||||
def _check_state(hass, category, entity_id):
|
||||
event = TEST_EVENTS[CATEGORIES_TO_EVENTS[category]]
|
||||
assert hass.states.get(entity_id).state == event.time
|
||||
assert hass.states.get(entity_id).attributes["category_id"] == event.category_id
|
||||
assert hass.states.get(entity_id).attributes["category_name"] == event.category_name
|
||||
assert hass.states.get(entity_id).attributes["type_id"] == event.type_id
|
||||
assert hass.states.get(entity_id).attributes["type_name"] == event.type_name
|
||||
assert hass.states.get(entity_id).attributes["name"] == event.name
|
||||
assert hass.states.get(entity_id).attributes["text"] == event.text
|
||||
assert hass.states.get(entity_id).attributes["partition_id"] == event.partition_id
|
||||
assert hass.states.get(entity_id).attributes["zone_id"] == event.zone_id
|
||||
assert hass.states.get(entity_id).attributes["user_id"] == event.user_id
|
||||
assert hass.states.get(entity_id).attributes["group"] == event.group
|
||||
assert hass.states.get(entity_id).attributes["priority"] == event.priority
|
||||
assert hass.states.get(entity_id).attributes["raw"] == event.raw
|
||||
event_index = CATEGORIES_TO_EVENTS[category]
|
||||
event = TEST_EVENTS[event_index]
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == event.time
|
||||
assert state.attributes["category_id"] == event.category_id
|
||||
assert state.attributes["category_name"] == event.category_name
|
||||
assert state.attributes["type_id"] == event.type_id
|
||||
assert state.attributes["type_name"] == event.type_name
|
||||
assert state.attributes["name"] == event.name
|
||||
assert state.attributes["text"] == event.text
|
||||
assert state.attributes["partition_id"] == event.partition_id
|
||||
assert state.attributes["zone_id"] == event.zone_id
|
||||
assert state.attributes["user_id"] == event.user_id
|
||||
assert state.attributes["group"] == event.group
|
||||
assert state.attributes["priority"] == event.priority
|
||||
assert state.attributes["raw"] == event.raw
|
||||
if event_index == 2:
|
||||
assert state.attributes["zone_entity_id"] == "binary_sensor.zone_1"
|
||||
else:
|
||||
assert "zone_entity_id" not in state.attributes
|
||||
|
||||
|
||||
async def test_setup(hass, emptry_alarm):
|
||||
async def test_setup(hass, two_zone_alarm): # noqa: F811
|
||||
"""Test entity setup."""
|
||||
registry = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""Utilities for Risco tests."""
|
||||
from pytest import fixture
|
||||
|
||||
from homeassistant.components.risco.const import DOMAIN
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_PIN, CONF_USERNAME
|
||||
|
||||
from tests.async_mock import PropertyMock, patch
|
||||
from tests.async_mock import MagicMock, PropertyMock, patch
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
TEST_CONFIG = {
|
||||
|
@ -35,3 +37,34 @@ async def setup_risco(hass, options={}):
|
|||
await hass.async_block_till_done()
|
||||
|
||||
return config_entry
|
||||
|
||||
|
||||
def _zone_mock():
|
||||
return MagicMock(
|
||||
triggered=False,
|
||||
bypassed=False,
|
||||
)
|
||||
|
||||
|
||||
@fixture
|
||||
def two_zone_alarm():
|
||||
"""Fixture to mock alarm with two zones."""
|
||||
zone_mocks = {0: _zone_mock(), 1: _zone_mock()}
|
||||
alarm_mock = MagicMock()
|
||||
with patch.object(
|
||||
zone_mocks[0], "id", new_callable=PropertyMock(return_value=0)
|
||||
), patch.object(
|
||||
zone_mocks[0], "name", new_callable=PropertyMock(return_value="Zone 0")
|
||||
), patch.object(
|
||||
zone_mocks[1], "id", new_callable=PropertyMock(return_value=1)
|
||||
), patch.object(
|
||||
zone_mocks[1], "name", new_callable=PropertyMock(return_value="Zone 1")
|
||||
), patch.object(
|
||||
alarm_mock,
|
||||
"zones",
|
||||
new_callable=PropertyMock(return_value=zone_mocks),
|
||||
), patch(
|
||||
"homeassistant.components.risco.RiscoAPI.get_state",
|
||||
return_value=alarm_mock,
|
||||
):
|
||||
yield alarm_mock
|
||||
|
|
Loading…
Add table
Reference in a new issue