1
mirror of https://github.com/home-assistant/core synced 2024-07-27 18:58:57 +02:00

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:
On Freund 2020-11-08 20:14:43 +02:00 committed by GitHub
parent 7c397a02b7
commit 5a7e4b4dae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 79 deletions

View File

@ -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):

View File

@ -11,6 +11,7 @@ DOMAIN = "risco"
RISCO_EVENT = "risco_event"
DATA_COORDINATOR = "risco"
DATA_ZONES = "zones"
EVENTS_COORDINATOR = "risco_events"
DEFAULT_SCAN_INTERVAL = 30

View File

@ -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):

View File

@ -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:

View File

@ -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()

View File

@ -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