Fix zwave_js update entity startup state (#78563)

* Fix update entity startup state

* Only write state if there is a change

* Add test to show that when an existing entity gets recreated, skipped version does not reset

* Remove unused blocks

* Update homeassistant/components/zwave_js/update.py

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
Raman Gupta 2022-09-17 13:43:35 -04:00 committed by GitHub
parent 6e4a0b9fdc
commit 01acc3d1e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 15 deletions

View File

@ -99,7 +99,7 @@ class ZWaveNodeFirmwareUpdate(UpdateEntity):
self._attr_name = "Firmware" self._attr_name = "Firmware"
self._base_unique_id = get_valueless_base_unique_id(driver, node) self._base_unique_id = get_valueless_base_unique_id(driver, node)
self._attr_unique_id = f"{self._base_unique_id}.firmware_update" self._attr_unique_id = f"{self._base_unique_id}.firmware_update"
self._attr_installed_version = self._attr_latest_version = node.firmware_version self._attr_installed_version = node.firmware_version
# device may not be precreated in main handler yet # device may not be precreated in main handler yet
self._attr_device_info = get_device_info(driver, node) self._attr_device_info = get_device_info(driver, node)
@ -187,20 +187,26 @@ class ZWaveNodeFirmwareUpdate(UpdateEntity):
err, err,
) )
else: else:
if available_firmware_updates: # If we have an available firmware update that is a higher version than
self._latest_version_firmware = latest_firmware = max( # what's on the node, we should advertise it, otherwise the installed
available_firmware_updates, # version is the latest.
key=lambda x: AwesomeVersion(x.version), if (
available_firmware_updates
and (
latest_firmware := max(
available_firmware_updates,
key=lambda x: AwesomeVersion(x.version),
)
) )
and AwesomeVersion(latest_firmware.version)
# If we have an available firmware update that is a higher version than > AwesomeVersion(self.node.firmware_version)
# what's on the node, we should advertise it, otherwise there is ):
# nothing to do. self._latest_version_firmware = latest_firmware
new_version = latest_firmware.version self._attr_latest_version = latest_firmware.version
current_version = self.node.firmware_version self.async_write_ha_state()
if AwesomeVersion(new_version) > AwesomeVersion(current_version): elif self._attr_latest_version != self._attr_installed_version:
self._attr_latest_version = new_version self._attr_latest_version = self._attr_installed_version
self.async_write_ha_state() self.async_write_ha_state()
finally: finally:
self._poll_unsub = async_call_later( self._poll_unsub = async_call_later(
self.hass, timedelta(days=1), self._async_update self.hass, timedelta(days=1), self._async_update

View File

@ -13,8 +13,10 @@ from homeassistant.components.update.const import (
ATTR_INSTALLED_VERSION, ATTR_INSTALLED_VERSION,
ATTR_LATEST_VERSION, ATTR_LATEST_VERSION,
ATTR_RELEASE_URL, ATTR_RELEASE_URL,
ATTR_SKIPPED_VERSION,
DOMAIN as UPDATE_DOMAIN, DOMAIN as UPDATE_DOMAIN,
SERVICE_INSTALL, SERVICE_INSTALL,
SERVICE_SKIP,
) )
from homeassistant.components.zwave_js.const import DOMAIN, SERVICE_REFRESH_VALUE from homeassistant.components.zwave_js.const import DOMAIN, SERVICE_REFRESH_VALUE
from homeassistant.components.zwave_js.helpers import get_valueless_base_unique_id from homeassistant.components.zwave_js.helpers import get_valueless_base_unique_id
@ -64,7 +66,6 @@ async def test_update_entity_states(
): ):
"""Test update entity states.""" """Test update entity states."""
ws_client = await hass_ws_client(hass) ws_client = await hass_ws_client(hass)
await hass.async_block_till_done()
assert hass.states.get(UPDATE_ENTITY).state == STATE_OFF assert hass.states.get(UPDATE_ENTITY).state == STATE_OFF
@ -453,3 +454,63 @@ async def test_update_entity_install_failed(
# validate that the install task failed # validate that the install task failed
with pytest.raises(HomeAssistantError): with pytest.raises(HomeAssistantError):
await install_task await install_task
async def test_update_entity_reload(
hass,
client,
climate_radio_thermostat_ct100_plus_different_endpoints,
integration,
):
"""Test update entity maintains state after reload."""
assert hass.states.get(UPDATE_ENTITY).state == STATE_OFF
client.async_send_command.return_value = {"updates": []}
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=1))
await hass.async_block_till_done()
state = hass.states.get(UPDATE_ENTITY)
assert state
assert state.state == STATE_OFF
client.async_send_command.return_value = FIRMWARE_UPDATES
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=2))
await hass.async_block_till_done()
state = hass.states.get(UPDATE_ENTITY)
assert state
assert state.state == STATE_ON
attrs = state.attributes
assert not attrs[ATTR_AUTO_UPDATE]
assert attrs[ATTR_INSTALLED_VERSION] == "10.7"
assert not attrs[ATTR_IN_PROGRESS]
assert attrs[ATTR_LATEST_VERSION] == "11.2.4"
assert attrs[ATTR_RELEASE_URL] is None
await hass.services.async_call(
UPDATE_DOMAIN,
SERVICE_SKIP,
{
ATTR_ENTITY_ID: UPDATE_ENTITY,
},
blocking=True,
)
state = hass.states.get(UPDATE_ENTITY)
assert state
assert state.state == STATE_OFF
assert state.attributes[ATTR_SKIPPED_VERSION] == "11.2.4"
await hass.config_entries.async_reload(integration.entry_id)
await hass.async_block_till_done()
# Trigger another update and make sure the skipped version is still skipped
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(days=4))
await hass.async_block_till_done()
state = hass.states.get(UPDATE_ENTITY)
assert state
assert state.state == STATE_OFF
assert state.attributes[ATTR_SKIPPED_VERSION] == "11.2.4"