mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
Mark entities for dead zwave_js nodes as unavailable (#48017)
* Don't create any devices or entities for dead zwave_js nodes * mark entities for dead nodes as unavailable * add test * watch for node status updates * update tests to handle node status changes as well
This commit is contained in:
parent
378b5f75ec
commit
8f186957ea
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from zwave_js_server.client import Client as ZwaveClient
|
from zwave_js_server.client import Client as ZwaveClient
|
||||||
|
from zwave_js_server.model.node import NodeStatus
|
||||||
from zwave_js_server.model.value import Value as ZwaveValue, get_value_id
|
from zwave_js_server.model.value import Value as ZwaveValue, get_value_id
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -18,6 +19,8 @@ from .helpers import get_device_id, get_unique_id
|
|||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
EVENT_VALUE_UPDATED = "value updated"
|
EVENT_VALUE_UPDATED = "value updated"
|
||||||
|
EVENT_DEAD = "dead"
|
||||||
|
EVENT_ALIVE = "alive"
|
||||||
|
|
||||||
|
|
||||||
class ZWaveBaseEntity(Entity):
|
class ZWaveBaseEntity(Entity):
|
||||||
@ -90,6 +93,11 @@ class ZWaveBaseEntity(Entity):
|
|||||||
self.async_on_remove(
|
self.async_on_remove(
|
||||||
self.info.node.on(EVENT_VALUE_UPDATED, self._value_changed)
|
self.info.node.on(EVENT_VALUE_UPDATED, self._value_changed)
|
||||||
)
|
)
|
||||||
|
for status_event in (EVENT_ALIVE, EVENT_DEAD):
|
||||||
|
self.async_on_remove(
|
||||||
|
self.info.node.on(status_event, self._node_status_alive_or_dead)
|
||||||
|
)
|
||||||
|
|
||||||
self.async_on_remove(
|
self.async_on_remove(
|
||||||
async_dispatcher_connect(
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
@ -135,7 +143,20 @@ class ZWaveBaseEntity(Entity):
|
|||||||
@property
|
@property
|
||||||
def available(self) -> bool:
|
def available(self) -> bool:
|
||||||
"""Return entity availability."""
|
"""Return entity availability."""
|
||||||
return self.client.connected and bool(self.info.node.ready)
|
return (
|
||||||
|
self.client.connected
|
||||||
|
and bool(self.info.node.ready)
|
||||||
|
and self.info.node.status != NodeStatus.DEAD
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _node_status_alive_or_dead(self, event_data: dict) -> None:
|
||||||
|
"""
|
||||||
|
Call when node status changes to alive or dead.
|
||||||
|
|
||||||
|
Should not be overridden by subclasses.
|
||||||
|
"""
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _value_changed(self, event_data: dict) -> None:
|
def _value_changed(self, event_data: dict) -> None:
|
||||||
|
@ -22,6 +22,7 @@ CLIMATE_MAIN_HEAT_ACTIONNER = "climate.main_heat_actionner"
|
|||||||
BULB_6_MULTI_COLOR_LIGHT_ENTITY = "light.bulb_6_multi_color"
|
BULB_6_MULTI_COLOR_LIGHT_ENTITY = "light.bulb_6_multi_color"
|
||||||
EATON_RF9640_ENTITY = "light.allloaddimmer"
|
EATON_RF9640_ENTITY = "light.allloaddimmer"
|
||||||
AEON_SMART_SWITCH_LIGHT_ENTITY = "light.smart_switch_6"
|
AEON_SMART_SWITCH_LIGHT_ENTITY = "light.smart_switch_6"
|
||||||
|
SCHLAGE_BE469_LOCK_ENTITY = "lock.touchscreen_deadbolt"
|
||||||
ID_LOCK_CONFIG_PARAMETER_SENSOR = (
|
ID_LOCK_CONFIG_PARAMETER_SENSOR = (
|
||||||
"sensor.z_wave_module_for_id_lock_150_and_101_config_parameter_door_lock_mode"
|
"sensor.z_wave_module_for_id_lock_150_and_101_config_parameter_door_lock_mode"
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test the Z-Wave JS lock platform."""
|
"""Test the Z-Wave JS lock platform."""
|
||||||
from zwave_js_server.const import ATTR_CODE_SLOT, ATTR_USERCODE
|
from zwave_js_server.const import ATTR_CODE_SLOT, ATTR_USERCODE
|
||||||
from zwave_js_server.event import Event
|
from zwave_js_server.event import Event
|
||||||
|
from zwave_js_server.model.node import NodeStatus
|
||||||
|
|
||||||
from homeassistant.components.lock import (
|
from homeassistant.components.lock import (
|
||||||
DOMAIN as LOCK_DOMAIN,
|
DOMAIN as LOCK_DOMAIN,
|
||||||
@ -12,9 +13,14 @@ from homeassistant.components.zwave_js.lock import (
|
|||||||
SERVICE_CLEAR_LOCK_USERCODE,
|
SERVICE_CLEAR_LOCK_USERCODE,
|
||||||
SERVICE_SET_LOCK_USERCODE,
|
SERVICE_SET_LOCK_USERCODE,
|
||||||
)
|
)
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_LOCKED, STATE_UNLOCKED
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID,
|
||||||
|
STATE_LOCKED,
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
STATE_UNLOCKED,
|
||||||
|
)
|
||||||
|
|
||||||
SCHLAGE_BE469_LOCK_ENTITY = "lock.touchscreen_deadbolt"
|
from .common import SCHLAGE_BE469_LOCK_ENTITY
|
||||||
|
|
||||||
|
|
||||||
async def test_door_lock(hass, client, lock_schlage_be469, integration):
|
async def test_door_lock(hass, client, lock_schlage_be469, integration):
|
||||||
@ -203,3 +209,16 @@ async def test_door_lock(hass, client, lock_schlage_be469, integration):
|
|||||||
"value": 1,
|
"value": 1,
|
||||||
}
|
}
|
||||||
assert args["value"] == 0
|
assert args["value"] == 0
|
||||||
|
|
||||||
|
event = Event(
|
||||||
|
type="dead",
|
||||||
|
data={
|
||||||
|
"source": "node",
|
||||||
|
"event": "dead",
|
||||||
|
"nodeId": 20,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
node.receive_event(event)
|
||||||
|
|
||||||
|
assert node.status == NodeStatus.DEAD
|
||||||
|
assert hass.states.get(SCHLAGE_BE469_LOCK_ENTITY).state == STATE_UNAVAILABLE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user