Add diagnostics to Comelit SimpleHome (#128794)
* Add diagnostics to Comelit SimpleHome * add test * add missing tests * introduce SnapshotAssertion * cleanup * exclude date based props
This commit is contained in:
parent
3e8f3cfb49
commit
e08e8641cb
4 changed files with 396 additions and 1 deletions
93
homeassistant/components/comelit/diagnostics.py
Normal file
93
homeassistant/components/comelit/diagnostics.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
"""Diagnostics support for Comelit integration."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from aiocomelit import (
|
||||||
|
ComelitSerialBridgeObject,
|
||||||
|
ComelitVedoAreaObject,
|
||||||
|
ComelitVedoZoneObject,
|
||||||
|
)
|
||||||
|
from aiocomelit.const import BRIDGE
|
||||||
|
|
||||||
|
from homeassistant.components.diagnostics import async_redact_data
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_PIN, CONF_TYPE
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .coordinator import ComelitBaseCoordinator
|
||||||
|
|
||||||
|
TO_REDACT = {CONF_PIN}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_config_entry_diagnostics(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Return diagnostics for a config entry."""
|
||||||
|
|
||||||
|
coordinator: ComelitBaseCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
dev_list: list[dict[str, Any]] = []
|
||||||
|
dev_type_list: list[dict[int, Any]] = []
|
||||||
|
|
||||||
|
for dev_type in coordinator.data:
|
||||||
|
dev_type_list = []
|
||||||
|
for sensor_data in coordinator.data[dev_type].values():
|
||||||
|
if isinstance(sensor_data, ComelitSerialBridgeObject):
|
||||||
|
dev_type_list.append(
|
||||||
|
{
|
||||||
|
sensor_data.index: {
|
||||||
|
"name": sensor_data.name,
|
||||||
|
"status": sensor_data.status,
|
||||||
|
"human_status": sensor_data.human_status,
|
||||||
|
"protected": sensor_data.protected,
|
||||||
|
"val": sensor_data.val,
|
||||||
|
"zone": sensor_data.zone,
|
||||||
|
"power": sensor_data.power,
|
||||||
|
"power_unit": sensor_data.power_unit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if isinstance(sensor_data, ComelitVedoAreaObject):
|
||||||
|
dev_type_list.append(
|
||||||
|
{
|
||||||
|
sensor_data.index: {
|
||||||
|
"name": sensor_data.name,
|
||||||
|
"human_status": sensor_data.human_status.value,
|
||||||
|
"p1": sensor_data.p1,
|
||||||
|
"p2": sensor_data.p2,
|
||||||
|
"ready": sensor_data.ready,
|
||||||
|
"armed": sensor_data.armed,
|
||||||
|
"alarm": sensor_data.alarm,
|
||||||
|
"alarm_memory": sensor_data.alarm_memory,
|
||||||
|
"sabotage": sensor_data.sabotage,
|
||||||
|
"anomaly": sensor_data.anomaly,
|
||||||
|
"in_time": sensor_data.in_time,
|
||||||
|
"out_time": sensor_data.out_time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if isinstance(sensor_data, ComelitVedoZoneObject):
|
||||||
|
dev_type_list.append(
|
||||||
|
{
|
||||||
|
sensor_data.index: {
|
||||||
|
"name": sensor_data.name,
|
||||||
|
"human_status": sensor_data.human_status.value,
|
||||||
|
"status": sensor_data.status,
|
||||||
|
"status_api": sensor_data.status_api,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
dev_list.append({dev_type: dev_type_list})
|
||||||
|
|
||||||
|
return {
|
||||||
|
"entry": async_redact_data(entry.as_dict(), TO_REDACT),
|
||||||
|
"type": entry.data.get(CONF_TYPE, BRIDGE),
|
||||||
|
"device_info": {
|
||||||
|
"last_update success": coordinator.last_update_success,
|
||||||
|
"last_exception": repr(coordinator.last_exception),
|
||||||
|
"devices": dev_list,
|
||||||
|
},
|
||||||
|
}
|
|
@ -1,6 +1,19 @@
|
||||||
"""Common stuff for Comelit SimpleHome tests."""
|
"""Common stuff for Comelit SimpleHome tests."""
|
||||||
|
|
||||||
from aiocomelit.const import VEDO
|
from aiocomelit import ComelitVedoAreaObject, ComelitVedoZoneObject
|
||||||
|
from aiocomelit.api import ComelitSerialBridgeObject
|
||||||
|
from aiocomelit.const import (
|
||||||
|
CLIMATE,
|
||||||
|
COVER,
|
||||||
|
IRRIGATION,
|
||||||
|
LIGHT,
|
||||||
|
OTHER,
|
||||||
|
SCENARIO,
|
||||||
|
VEDO,
|
||||||
|
WATT,
|
||||||
|
AlarmAreaState,
|
||||||
|
AlarmZoneState,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant.components.comelit.const import DOMAIN
|
from homeassistant.components.comelit.const import DOMAIN
|
||||||
from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_PIN, CONF_PORT, CONF_TYPE
|
from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_PIN, CONF_PORT, CONF_TYPE
|
||||||
|
@ -27,3 +40,67 @@ MOCK_USER_BRIDGE_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][0]
|
||||||
MOCK_USER_VEDO_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][1]
|
MOCK_USER_VEDO_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][1]
|
||||||
|
|
||||||
FAKE_PIN = 5678
|
FAKE_PIN = 5678
|
||||||
|
|
||||||
|
BRIDGE_DEVICE_QUERY = {
|
||||||
|
CLIMATE: {},
|
||||||
|
COVER: {
|
||||||
|
0: ComelitSerialBridgeObject(
|
||||||
|
index=0,
|
||||||
|
name="Cover0",
|
||||||
|
status=0,
|
||||||
|
human_status="closed",
|
||||||
|
type="cover",
|
||||||
|
val=0,
|
||||||
|
protected=0,
|
||||||
|
zone="Open space",
|
||||||
|
power=0.0,
|
||||||
|
power_unit=WATT,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
LIGHT: {
|
||||||
|
0: ComelitSerialBridgeObject(
|
||||||
|
index=0,
|
||||||
|
name="Light0",
|
||||||
|
status=0,
|
||||||
|
human_status="off",
|
||||||
|
type="light",
|
||||||
|
val=0,
|
||||||
|
protected=0,
|
||||||
|
zone="Bathroom",
|
||||||
|
power=0.0,
|
||||||
|
power_unit=WATT,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
OTHER: {},
|
||||||
|
IRRIGATION: {},
|
||||||
|
SCENARIO: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
VEDO_DEVICE_QUERY = {
|
||||||
|
"aree": {
|
||||||
|
0: ComelitVedoAreaObject(
|
||||||
|
index=0,
|
||||||
|
name="Area0",
|
||||||
|
p1=True,
|
||||||
|
p2=False,
|
||||||
|
ready=False,
|
||||||
|
armed=False,
|
||||||
|
alarm=False,
|
||||||
|
alarm_memory=False,
|
||||||
|
sabotage=False,
|
||||||
|
anomaly=False,
|
||||||
|
in_time=False,
|
||||||
|
out_time=False,
|
||||||
|
human_status=AlarmAreaState.UNKNOWN,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"zone": {
|
||||||
|
0: ComelitVedoZoneObject(
|
||||||
|
index=0,
|
||||||
|
name="Zone0",
|
||||||
|
status_api="0x000",
|
||||||
|
status=0,
|
||||||
|
human_status=AlarmZoneState.REST,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
144
tests/components/comelit/snapshots/test_diagnostics.ambr
Normal file
144
tests/components/comelit/snapshots/test_diagnostics.ambr
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
# serializer version: 1
|
||||||
|
# name: test_entry_diagnostics_bridge
|
||||||
|
dict({
|
||||||
|
'device_info': dict({
|
||||||
|
'devices': list([
|
||||||
|
dict({
|
||||||
|
'clima': list([
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'shutter': list([
|
||||||
|
dict({
|
||||||
|
'0': dict({
|
||||||
|
'human_status': 'closed',
|
||||||
|
'name': 'Cover0',
|
||||||
|
'power': 0.0,
|
||||||
|
'power_unit': 'W',
|
||||||
|
'protected': 0,
|
||||||
|
'status': 0,
|
||||||
|
'val': 0,
|
||||||
|
'zone': 'Open space',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'light': list([
|
||||||
|
dict({
|
||||||
|
'0': dict({
|
||||||
|
'human_status': 'off',
|
||||||
|
'name': 'Light0',
|
||||||
|
'power': 0.0,
|
||||||
|
'power_unit': 'W',
|
||||||
|
'protected': 0,
|
||||||
|
'status': 0,
|
||||||
|
'val': 0,
|
||||||
|
'zone': 'Bathroom',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'other': list([
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'irrigation': list([
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'scenario': list([
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
'last_exception': 'None',
|
||||||
|
'last_update success': True,
|
||||||
|
}),
|
||||||
|
'entry': dict({
|
||||||
|
'data': dict({
|
||||||
|
'host': 'fake_host',
|
||||||
|
'pin': '**REDACTED**',
|
||||||
|
'port': 80,
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'discovery_keys': dict({
|
||||||
|
}),
|
||||||
|
'domain': 'comelit',
|
||||||
|
'minor_version': 1,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'pref_disable_new_entities': False,
|
||||||
|
'pref_disable_polling': False,
|
||||||
|
'source': 'user',
|
||||||
|
'title': 'Mock Title',
|
||||||
|
'unique_id': None,
|
||||||
|
'version': 1,
|
||||||
|
}),
|
||||||
|
'type': 'Serial bridge',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_entry_diagnostics_vedo
|
||||||
|
dict({
|
||||||
|
'device_info': dict({
|
||||||
|
'devices': list([
|
||||||
|
dict({
|
||||||
|
'aree': list([
|
||||||
|
dict({
|
||||||
|
'0': dict({
|
||||||
|
'alarm': False,
|
||||||
|
'alarm_memory': False,
|
||||||
|
'anomaly': False,
|
||||||
|
'armed': False,
|
||||||
|
'human_status': 'unknown',
|
||||||
|
'in_time': False,
|
||||||
|
'name': 'Area0',
|
||||||
|
'out_time': False,
|
||||||
|
'p1': True,
|
||||||
|
'p2': False,
|
||||||
|
'ready': False,
|
||||||
|
'sabotage': False,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'zone': list([
|
||||||
|
dict({
|
||||||
|
'0': dict({
|
||||||
|
'human_status': 'rest',
|
||||||
|
'name': 'Zone0',
|
||||||
|
'status': 0,
|
||||||
|
'status_api': '0x000',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
'last_exception': 'None',
|
||||||
|
'last_update success': True,
|
||||||
|
}),
|
||||||
|
'entry': dict({
|
||||||
|
'data': dict({
|
||||||
|
'host': 'fake_vedo_host',
|
||||||
|
'pin': '**REDACTED**',
|
||||||
|
'port': 8080,
|
||||||
|
'type': 'Vedo system',
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'discovery_keys': dict({
|
||||||
|
}),
|
||||||
|
'domain': 'comelit',
|
||||||
|
'minor_version': 1,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'pref_disable_new_entities': False,
|
||||||
|
'pref_disable_polling': False,
|
||||||
|
'source': 'user',
|
||||||
|
'title': 'Mock Title',
|
||||||
|
'unique_id': None,
|
||||||
|
'version': 1,
|
||||||
|
}),
|
||||||
|
'type': 'Vedo system',
|
||||||
|
})
|
||||||
|
# ---
|
81
tests/components/comelit/test_diagnostics.py
Normal file
81
tests/components/comelit/test_diagnostics.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
"""Tests for Comelit Simplehome diagnostics platform."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from syrupy import SnapshotAssertion
|
||||||
|
from syrupy.filters import props
|
||||||
|
|
||||||
|
from homeassistant.components.comelit.const import DOMAIN
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .const import (
|
||||||
|
BRIDGE_DEVICE_QUERY,
|
||||||
|
MOCK_USER_BRIDGE_DATA,
|
||||||
|
MOCK_USER_VEDO_DATA,
|
||||||
|
VEDO_DEVICE_QUERY,
|
||||||
|
)
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||||
|
from tests.typing import ClientSessionGenerator
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entry_diagnostics_bridge(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test Bridge config entry diagnostics."""
|
||||||
|
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_BRIDGE_DATA)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch("aiocomelit.api.ComeliteSerialBridgeApi.login"),
|
||||||
|
patch(
|
||||||
|
"aiocomelit.api.ComeliteSerialBridgeApi.get_all_devices",
|
||||||
|
return_value=BRIDGE_DEVICE_QUERY,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state == ConfigEntryState.LOADED
|
||||||
|
assert await get_diagnostics_for_config_entry(hass, hass_client, entry) == snapshot(
|
||||||
|
exclude=props(
|
||||||
|
"entry_id",
|
||||||
|
"created_at",
|
||||||
|
"modified_at",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entry_diagnostics_vedo(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test Vedo System config entry diagnostics."""
|
||||||
|
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_VEDO_DATA)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch("aiocomelit.api.ComelitVedoApi.login"),
|
||||||
|
patch(
|
||||||
|
"aiocomelit.api.ComelitVedoApi.get_all_areas_and_zones",
|
||||||
|
return_value=VEDO_DEVICE_QUERY,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state == ConfigEntryState.LOADED
|
||||||
|
assert await get_diagnostics_for_config_entry(hass, hass_client, entry) == snapshot(
|
||||||
|
exclude=props(
|
||||||
|
"entry_id",
|
||||||
|
"created_at",
|
||||||
|
"modified_at",
|
||||||
|
)
|
||||||
|
)
|
Loading…
Add table
Reference in a new issue