Skip to content

Commit 4e2fe63

Browse files
authored
Check for Z-Wave firmware updates of sleeping devices (#150123)
1 parent d0cc999 commit 4e2fe63

File tree

2 files changed

+8
-69
lines changed

2 files changed

+8
-69
lines changed

homeassistant/components/zwave_js/update.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from typing import Any, Final, cast
1111

1212
from awesomeversion import AwesomeVersion
13-
from zwave_js_server.const import NodeStatus
1413
from zwave_js_server.exceptions import BaseZwaveJSServerError, FailedZWaveCommand
1514
from zwave_js_server.model.driver import Driver
1615
from zwave_js_server.model.firmware import (
@@ -192,7 +191,6 @@ def __init__(
192191
self.entity_description = entity_description
193192
self.node = node
194193
self._latest_version_firmware: FirmwareUpdateInfo | None = None
195-
self._status_unsub: Callable[[], None] | None = None
196194
self._poll_unsub: Callable[[], None] | None = None
197195
self._progress_unsub: Callable[[], None] | None = None
198196
self._finished_unsub: Callable[[], None] | None = None
@@ -213,12 +211,6 @@ def extra_restore_state_data(self) -> ZWaveFirmwareUpdateExtraStoredData:
213211
"""Return ZWave Node Firmware Update specific state data to be restored."""
214212
return ZWaveFirmwareUpdateExtraStoredData(self._latest_version_firmware)
215213

216-
@callback
217-
def _update_on_status_change(self, _: dict[str, Any]) -> None:
218-
"""Update the entity when node is awake."""
219-
self._status_unsub = None
220-
self.hass.async_create_task(self._async_update())
221-
222214
@callback
223215
def update_progress(self, event: dict[str, Any]) -> None:
224216
"""Update install progress on event."""
@@ -270,14 +262,6 @@ async def _async_update(self, _: HomeAssistant | datetime | None = None) -> None
270262
)
271263
return
272264

273-
# If device is asleep, wait for it to wake up before attempting an update
274-
if self.node.status == NodeStatus.ASLEEP:
275-
if not self._status_unsub:
276-
self._status_unsub = self.node.once(
277-
"wake up", self._update_on_status_change
278-
)
279-
return
280-
281265
try:
282266
# Retrieve all firmware updates including non-stable ones but filter
283267
# non-stable channels out
@@ -436,10 +420,6 @@ async def async_added_to_hass(self) -> None:
436420

437421
async def async_will_remove_from_hass(self) -> None:
438422
"""Call when entity will be removed."""
439-
if self._status_unsub:
440-
self._status_unsub()
441-
self._status_unsub = None
442-
443423
if self._poll_unsub:
444424
self._poll_unsub()
445425
self._poll_unsub = None

tests/components/zwave_js/test_update.py

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ async def test_update_entity_sleep(
269269
zen_31: Node,
270270
integration: MockConfigEntry,
271271
) -> None:
272-
"""Test update occurs when device is asleep after it wakes up."""
272+
"""Test update occurs when device is asleep."""
273273
event = Event(
274274
"sleep",
275275
data={"source": "node", "event": "sleep", "nodeId": zen_31.node_id},
@@ -283,29 +283,13 @@ async def test_update_entity_sleep(
283283
await hass.async_block_till_done()
284284

285285
# Two nodes in total, the controller node and the zen_31 node.
286-
# The zen_31 node is asleep,
287-
# so we should only check for updates for the controller node.
288-
assert client.async_send_command.call_count == 1
289-
args = client.async_send_command.call_args[0][0]
290-
assert args["command"] == "controller.get_available_firmware_updates"
291-
assert args["nodeId"] == 1
292-
293-
client.async_send_command.reset_mock()
294-
295-
event = Event(
296-
"wake up",
297-
data={"source": "node", "event": "wake up", "nodeId": zen_31.node_id},
298-
)
299-
zen_31.receive_event(event)
300-
await hass.async_block_till_done()
301-
302-
# Now that the zen_31 node is awake we can check for updates for it.
303-
# The controller node has already been checked,
304-
# so won't get another check now.
305-
assert client.async_send_command.call_count == 1
306-
args = client.async_send_command.call_args[0][0]
307-
assert args["command"] == "controller.get_available_firmware_updates"
308-
assert args["nodeId"] == 94
286+
# We should check for updates for both nodes, including the sleeping one
287+
# since the firmware check no longer requires device communication first.
288+
assert client.async_send_command.call_count == 2
289+
# Check calls were made for both nodes
290+
call_args = [call[0][0] for call in client.async_send_command.call_args_list]
291+
assert any(args["nodeId"] == 1 for args in call_args) # Controller node
292+
assert any(args["nodeId"] == 94 for args in call_args) # zen_31 node
309293

310294

311295
async def test_update_entity_dead(
@@ -1158,28 +1142,3 @@ async def test_update_entity_no_latest_version(
11581142
assert state.state == STATE_OFF
11591143
assert state.attributes[ATTR_SKIPPED_VERSION] is None
11601144
assert state.attributes[ATTR_LATEST_VERSION] == latest_version
1161-
1162-
1163-
async def test_update_entity_unload_asleep_node(
1164-
hass: HomeAssistant,
1165-
client: MagicMock,
1166-
wallmote_central_scene: Node,
1167-
integration: MockConfigEntry,
1168-
) -> None:
1169-
"""Test unloading config entry after attempting an update for an asleep node."""
1170-
config_entry = integration
1171-
assert client.async_send_command.call_count == 0
1172-
1173-
client.async_send_command.reset_mock()
1174-
client.async_send_command.return_value = {"updates": []}
1175-
1176-
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=5, days=1))
1177-
await hass.async_block_till_done()
1178-
1179-
# Once call completed for the (awake) controller node.
1180-
assert client.async_send_command.call_count == 1
1181-
assert len(wallmote_central_scene._listeners["wake up"]) == 1
1182-
1183-
await hass.config_entries.async_unload(config_entry.entry_id)
1184-
assert client.async_send_command.call_count == 1
1185-
assert len(wallmote_central_scene._listeners["wake up"]) == 0

0 commit comments

Comments
 (0)