Skip to content
Snippets Groups Projects
Unverified Commit fa987564 authored by Raman Gupta's avatar Raman Gupta Committed by GitHub
Browse files

Handle dead nodes in zwave_js update entity (#77763)

parent cd24223c
No related branches found
No related tags found
No related merge requests found
...@@ -86,17 +86,24 @@ class ZWaveNodeFirmwareUpdate(UpdateEntity): ...@@ -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 ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment