Handle dead nodes in zwave_js update entity (#77763)
This commit is contained in:
parent
cd24223c1f
commit
fa987564a7
2 changed files with 77 additions and 80 deletions
|
@ -86,17 +86,24 @@ class ZWaveNodeFirmwareUpdate(UpdateEntity):
|
||||||
|
|
||||||
self._attr_installed_version = self._attr_latest_version = node.firmware_version
|
self._attr_installed_version = self._attr_latest_version = node.firmware_version
|
||||||
|
|
||||||
def _update_on_wake_up(self, _: dict[str, Any]) -> None:
|
def _update_on_status_change(self, _: dict[str, Any]) -> None:
|
||||||
"""Update the entity when node is awake."""
|
"""Update the entity when node is awake."""
|
||||||
self._status_unsub = None
|
self._status_unsub = None
|
||||||
self.hass.async_create_task(self.async_update(True))
|
self.hass.async_create_task(self.async_update(True))
|
||||||
|
|
||||||
async def async_update(self, write_state: bool = False) -> None:
|
async def async_update(self, write_state: bool = False) -> None:
|
||||||
"""Update the entity."""
|
"""Update the entity."""
|
||||||
if self.node.status == NodeStatus.ASLEEP:
|
for status, event_name in (
|
||||||
if not self._status_unsub:
|
(NodeStatus.ASLEEP, "wake up"),
|
||||||
self._status_unsub = self.node.once("wake up", self._update_on_wake_up)
|
(NodeStatus.DEAD, "alive"),
|
||||||
return
|
):
|
||||||
|
if self.node.status == status:
|
||||||
|
if not self._status_unsub:
|
||||||
|
self._status_unsub = self.node.once(
|
||||||
|
event_name, self._update_on_status_change
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
if available_firmware_updates := (
|
if available_firmware_updates := (
|
||||||
await self.driver.controller.async_get_available_firmware_updates(
|
await self.driver.controller.async_get_available_firmware_updates(
|
||||||
self.node, API_KEY_FIRMWARE_UPDATE_SERVICE
|
self.node, API_KEY_FIRMWARE_UPDATE_SERVICE
|
||||||
|
|
|
@ -24,6 +24,31 @@ from homeassistant.util import datetime as dt_util
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
UPDATE_ENTITY = "update.z_wave_thermostat_firmware"
|
UPDATE_ENTITY = "update.z_wave_thermostat_firmware"
|
||||||
|
FIRMWARE_UPDATES = {
|
||||||
|
"updates": [
|
||||||
|
{
|
||||||
|
"version": "10.11.1",
|
||||||
|
"changelog": "blah 1",
|
||||||
|
"files": [
|
||||||
|
{"target": 0, "url": "https://example1.com", "integrity": "sha1"}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "11.2.4",
|
||||||
|
"changelog": "blah 2",
|
||||||
|
"files": [
|
||||||
|
{"target": 0, "url": "https://example2.com", "integrity": "sha2"}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "11.1.5",
|
||||||
|
"changelog": "blah 3",
|
||||||
|
"files": [
|
||||||
|
{"target": 0, "url": "https://example3.com", "integrity": "sha3"}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_update_entity_success(
|
async def test_update_entity_success(
|
||||||
|
@ -60,31 +85,7 @@ async def test_update_entity_success(
|
||||||
result = await ws_client.receive_json()
|
result = await ws_client.receive_json()
|
||||||
assert result["result"] is None
|
assert result["result"] is None
|
||||||
|
|
||||||
client.async_send_command.return_value = {
|
client.async_send_command.return_value = FIRMWARE_UPDATES
|
||||||
"updates": [
|
|
||||||
{
|
|
||||||
"version": "10.11.1",
|
|
||||||
"changelog": "blah 1",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example1.com", "integrity": "sha1"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "11.2.4",
|
|
||||||
"changelog": "blah 2",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example2.com", "integrity": "sha2"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "11.1.5",
|
|
||||||
"changelog": "blah 3",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example3.com", "integrity": "sha3"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=2))
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=2))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -171,31 +172,7 @@ async def test_update_entity_failure(
|
||||||
hass_ws_client,
|
hass_ws_client,
|
||||||
):
|
):
|
||||||
"""Test update entity failed install."""
|
"""Test update entity failed install."""
|
||||||
client.async_send_command.return_value = {
|
client.async_send_command.return_value = FIRMWARE_UPDATES
|
||||||
"updates": [
|
|
||||||
{
|
|
||||||
"version": "10.11.1",
|
|
||||||
"changelog": "blah 1",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example1.com", "integrity": "sha1"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "11.2.4",
|
|
||||||
"changelog": "blah 2",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example2.com", "integrity": "sha2"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "11.1.5",
|
|
||||||
"changelog": "blah 3",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example3.com", "integrity": "sha3"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=1))
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=1))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -228,31 +205,7 @@ async def test_update_entity_sleep(
|
||||||
multisensor_6.receive_event(event)
|
multisensor_6.receive_event(event)
|
||||||
client.async_send_command.reset_mock()
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
client.async_send_command.return_value = {
|
client.async_send_command.return_value = FIRMWARE_UPDATES
|
||||||
"updates": [
|
|
||||||
{
|
|
||||||
"version": "10.11.1",
|
|
||||||
"changelog": "blah 1",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example1.com", "integrity": "sha1"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "11.2.4",
|
|
||||||
"changelog": "blah 2",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example2.com", "integrity": "sha2"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "11.1.5",
|
|
||||||
"changelog": "blah 3",
|
|
||||||
"files": [
|
|
||||||
{"target": 0, "url": "https://example3.com", "integrity": "sha3"}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=1))
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=1))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -273,3 +226,40 @@ async def test_update_entity_sleep(
|
||||||
args = client.async_send_command.call_args_list[0][0][0]
|
args = client.async_send_command.call_args_list[0][0][0]
|
||||||
assert args["command"] == "controller.get_available_firmware_updates"
|
assert args["command"] == "controller.get_available_firmware_updates"
|
||||||
assert args["nodeId"] == multisensor_6.node_id
|
assert args["nodeId"] == multisensor_6.node_id
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_entity_dead(
|
||||||
|
hass,
|
||||||
|
client,
|
||||||
|
multisensor_6,
|
||||||
|
integration,
|
||||||
|
):
|
||||||
|
"""Test update occurs when device is dead after it becomes alive."""
|
||||||
|
event = Event(
|
||||||
|
"dead",
|
||||||
|
data={"source": "node", "event": "dead", "nodeId": multisensor_6.node_id},
|
||||||
|
)
|
||||||
|
multisensor_6.receive_event(event)
|
||||||
|
client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
client.async_send_command.return_value = FIRMWARE_UPDATES
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=1))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Because node is asleep we shouldn't attempt to check for firmware updates
|
||||||
|
assert len(client.async_send_command.call_args_list) == 0
|
||||||
|
|
||||||
|
event = Event(
|
||||||
|
"alive",
|
||||||
|
data={"source": "node", "event": "alive", "nodeId": multisensor_6.node_id},
|
||||||
|
)
|
||||||
|
multisensor_6.receive_event(event)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Now that the node is up we can check for updates
|
||||||
|
assert len(client.async_send_command.call_args_list) > 0
|
||||||
|
|
||||||
|
args = client.async_send_command.call_args_list[0][0][0]
|
||||||
|
assert args["command"] == "controller.get_available_firmware_updates"
|
||||||
|
assert args["nodeId"] == multisensor_6.node_id
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue