mirror of
https://github.com/home-assistant/core.git
synced 2025-08-31 18:31:35 +02:00
Handle Z-Wave RssiErrorReceived (#150846)
This commit is contained in:
@@ -4,15 +4,15 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Mapping
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
import voluptuous as vol
|
||||
from zwave_js_server.const import CommandClass
|
||||
from zwave_js_server.const import CommandClass, RssiError
|
||||
from zwave_js_server.const.command_class.meter import (
|
||||
RESET_METER_OPTION_TARGET_VALUE,
|
||||
RESET_METER_OPTION_TYPE,
|
||||
)
|
||||
from zwave_js_server.exceptions import BaseZwaveJSServerError
|
||||
from zwave_js_server.exceptions import BaseZwaveJSServerError, RssiErrorReceived
|
||||
from zwave_js_server.model.controller import Controller
|
||||
from zwave_js_server.model.controller.statistics import ControllerStatistics
|
||||
from zwave_js_server.model.driver import Driver
|
||||
@@ -1049,7 +1049,7 @@ class ZWaveStatisticsSensor(SensorEntity):
|
||||
self,
|
||||
config_entry: ZwaveJSConfigEntry,
|
||||
driver: Driver,
|
||||
statistics_src: ZwaveNode | Controller,
|
||||
statistics_src: Controller | ZwaveNode,
|
||||
description: ZWaveJSStatisticsSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize a Z-Wave statistics entity."""
|
||||
@@ -1080,13 +1080,31 @@ class ZWaveStatisticsSensor(SensorEntity):
|
||||
)
|
||||
|
||||
@callback
|
||||
def statistics_updated(self, event_data: dict) -> None:
|
||||
def _statistics_updated(self, event_data: dict) -> None:
|
||||
"""Call when statistics updated event is received."""
|
||||
self._attr_native_value = self.entity_description.convert(
|
||||
event_data["statistics_updated"], self.entity_description.key
|
||||
statistics = cast(
|
||||
ControllerStatistics | NodeStatistics, event_data["statistics_updated"]
|
||||
)
|
||||
self._set_statistics(statistics)
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def _set_statistics(
|
||||
self, statistics: ControllerStatistics | NodeStatistics
|
||||
) -> None:
|
||||
"""Set updated statistics."""
|
||||
try:
|
||||
self._attr_native_value = self.entity_description.convert(
|
||||
statistics, self.entity_description.key
|
||||
)
|
||||
except RssiErrorReceived as err:
|
||||
if err.error is RssiError.NOT_AVAILABLE:
|
||||
self._attr_available = False
|
||||
return
|
||||
self._attr_native_value = None
|
||||
# Reset available state.
|
||||
self._attr_available = True
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Call when entity is added."""
|
||||
self.async_on_remove(
|
||||
@@ -1104,10 +1122,8 @@ class ZWaveStatisticsSensor(SensorEntity):
|
||||
)
|
||||
)
|
||||
self.async_on_remove(
|
||||
self.statistics_src.on("statistics updated", self.statistics_updated)
|
||||
self.statistics_src.on("statistics updated", self._statistics_updated)
|
||||
)
|
||||
|
||||
# Set initial state
|
||||
self._attr_native_value = self.entity_description.convert(
|
||||
self.statistics_src.statistics, self.entity_description.key
|
||||
)
|
||||
self._set_statistics(self.statistics_src.statistics)
|
||||
|
@@ -1045,6 +1045,183 @@ async def test_last_seen_statistics_sensors(
|
||||
assert state.state == "2024-01-01T12:00:00+00:00"
|
||||
|
||||
|
||||
async def test_rssi_sensor_error(
|
||||
hass: HomeAssistant,
|
||||
zp3111: Node,
|
||||
integration: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test rssi sensor error."""
|
||||
entity_id = "sensor.4_in_1_sensor_signal_strength"
|
||||
|
||||
entity_registry.async_update_entity(entity_id, disabled_by=None)
|
||||
|
||||
# reload integration and check if entity is correctly there
|
||||
await hass.config_entries.async_reload(integration.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "unknown"
|
||||
|
||||
# Fire statistics updated event for node
|
||||
event = Event(
|
||||
"statistics updated",
|
||||
{
|
||||
"source": "node",
|
||||
"event": "statistics updated",
|
||||
"nodeId": zp3111.node_id,
|
||||
"statistics": {
|
||||
"commandsTX": 1,
|
||||
"commandsRX": 2,
|
||||
"commandsDroppedTX": 3,
|
||||
"commandsDroppedRX": 4,
|
||||
"timeoutResponse": 5,
|
||||
"rtt": 6,
|
||||
"rssi": 7, # baseline
|
||||
"lwr": {
|
||||
"protocolDataRate": 1,
|
||||
"rssi": 1,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"nlwr": {
|
||||
"protocolDataRate": 2,
|
||||
"rssi": 2,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"lastSeen": "2024-01-01T00:00:00+0000",
|
||||
},
|
||||
},
|
||||
)
|
||||
zp3111.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "7"
|
||||
|
||||
event = Event(
|
||||
"statistics updated",
|
||||
{
|
||||
"source": "node",
|
||||
"event": "statistics updated",
|
||||
"nodeId": zp3111.node_id,
|
||||
"statistics": {
|
||||
"commandsTX": 1,
|
||||
"commandsRX": 2,
|
||||
"commandsDroppedTX": 3,
|
||||
"commandsDroppedRX": 4,
|
||||
"timeoutResponse": 5,
|
||||
"rtt": 6,
|
||||
"rssi": 125, # no signal detected
|
||||
"lwr": {
|
||||
"protocolDataRate": 1,
|
||||
"rssi": 1,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"nlwr": {
|
||||
"protocolDataRate": 2,
|
||||
"rssi": 2,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"lastSeen": "2024-01-01T00:00:00+0000",
|
||||
},
|
||||
},
|
||||
)
|
||||
zp3111.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "unknown"
|
||||
|
||||
event = Event(
|
||||
"statistics updated",
|
||||
{
|
||||
"source": "node",
|
||||
"event": "statistics updated",
|
||||
"nodeId": zp3111.node_id,
|
||||
"statistics": {
|
||||
"commandsTX": 1,
|
||||
"commandsRX": 2,
|
||||
"commandsDroppedTX": 3,
|
||||
"commandsDroppedRX": 4,
|
||||
"timeoutResponse": 5,
|
||||
"rtt": 6,
|
||||
"rssi": 127, # not available
|
||||
"lwr": {
|
||||
"protocolDataRate": 1,
|
||||
"rssi": 1,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"nlwr": {
|
||||
"protocolDataRate": 2,
|
||||
"rssi": 2,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"lastSeen": "2024-01-01T00:00:00+0000",
|
||||
},
|
||||
},
|
||||
)
|
||||
zp3111.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "unavailable"
|
||||
|
||||
event = Event(
|
||||
"statistics updated",
|
||||
{
|
||||
"source": "node",
|
||||
"event": "statistics updated",
|
||||
"nodeId": zp3111.node_id,
|
||||
"statistics": {
|
||||
"commandsTX": 1,
|
||||
"commandsRX": 2,
|
||||
"commandsDroppedTX": 3,
|
||||
"commandsDroppedRX": 4,
|
||||
"timeoutResponse": 5,
|
||||
"rtt": 6,
|
||||
"rssi": 126, # receiver saturated
|
||||
"lwr": {
|
||||
"protocolDataRate": 1,
|
||||
"rssi": 1,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"nlwr": {
|
||||
"protocolDataRate": 2,
|
||||
"rssi": 2,
|
||||
"repeaters": [],
|
||||
"repeaterRSSI": [],
|
||||
"routeFailedBetween": [],
|
||||
},
|
||||
"lastSeen": "2024-01-01T00:00:00+0000",
|
||||
},
|
||||
},
|
||||
)
|
||||
zp3111.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "unknown"
|
||||
|
||||
|
||||
ENERGY_PRODUCTION_ENTITY_MAP = {
|
||||
"energy_production_power": {
|
||||
"state": 1.23,
|
||||
|
Reference in New Issue
Block a user