Trigger update of ESPHome update entity when static info updates (#87058)

Trigger update of update entity when static info updates
This commit is contained in:
Paulus Schoutsen 2023-01-31 22:13:41 -05:00 committed by GitHub
parent f7ae265760
commit 8417f22904
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 8 deletions

View File

@ -646,9 +646,10 @@ async def platform_async_setup_entry(
# Add entities to Home Assistant # Add entities to Home Assistant
async_add_entities(add_entities) async_add_entities(add_entities)
signal = f"esphome_{entry.entry_id}_on_list"
entry_data.cleanup_callbacks.append( entry_data.cleanup_callbacks.append(
async_dispatcher_connect(hass, signal, async_list_entities) async_dispatcher_connect(
hass, entry_data.signal_static_info_updated, async_list_entities
)
) )

View File

@ -107,6 +107,11 @@ class RuntimeEntryData:
return self.device_info.friendly_name return self.device_info.friendly_name
return self.name return self.name
@property
def signal_static_info_updated(self) -> str:
"""Return the signal to listen to for updates on static info."""
return f"esphome_{self.entry_id}_on_list"
@callback @callback
def async_update_ble_connection_limits(self, free: int, limit: int) -> None: def async_update_ble_connection_limits(self, free: int, limit: int) -> None:
"""Update the BLE connection limits.""" """Update the BLE connection limits."""
@ -168,8 +173,7 @@ class RuntimeEntryData:
await self._ensure_platforms_loaded(hass, entry, needed_platforms) await self._ensure_platforms_loaded(hass, entry, needed_platforms)
# Then send dispatcher event # Then send dispatcher event
signal = f"esphome_{self.entry_id}_on_list" async_dispatcher_send(hass, self.signal_static_info_updated, infos)
async_dispatcher_send(hass, signal, infos)
@callback @callback
def async_subscribe_state_update( def async_subscribe_state_update(

View File

@ -5,7 +5,7 @@ import asyncio
import logging import logging
from typing import Any, cast from typing import Any, cast
from aioesphomeapi import DeviceInfo as ESPHomeDeviceInfo from aioesphomeapi import DeviceInfo as ESPHomeDeviceInfo, EntityInfo
from homeassistant.components.update import ( from homeassistant.components.update import (
UpdateDeviceClass, UpdateDeviceClass,
@ -13,7 +13,7 @@ from homeassistant.components.update import (
UpdateEntityFeature, UpdateEntityFeature,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
@ -115,6 +115,23 @@ class ESPHomeUpdateEntity(CoordinatorEntity[ESPHomeDashboard], UpdateEntity):
"""URL to the full release notes of the latest version available.""" """URL to the full release notes of the latest version available."""
return "https://esphome.io/changelog/" return "https://esphome.io/changelog/"
async def async_added_to_hass(self) -> None:
"""Handle entity added to Home Assistant."""
await super().async_added_to_hass()
@callback
def _static_info_updated(infos: list[EntityInfo]) -> None:
"""Handle static info update."""
self.async_write_ha_state()
self.async_on_remove(
async_dispatcher_connect(
self.hass,
self._entry_data.signal_static_info_updated,
_static_info_updated,
)
)
async def async_install( async def async_install(
self, version: str | None, backup: bool, **kwargs: Any self, version: str | None, backup: bool, **kwargs: Any
) -> None: ) -> None:

View File

@ -1,9 +1,11 @@
"""Test ESPHome update entities.""" """Test ESPHome update entities."""
import dataclasses
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import pytest import pytest
from homeassistant.components.esphome.dashboard import async_get_dashboard from homeassistant.components.esphome.dashboard import async_get_dashboard
from homeassistant.helpers.dispatcher import async_dispatcher_send
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -57,8 +59,6 @@ async def test_update_entity(
mock_dashboard["configured"] = devices_payload mock_dashboard["configured"] = devices_payload
await async_get_dashboard(hass).async_refresh() await async_get_dashboard(hass).async_refresh()
mock_config_entry.add_to_hass(hass)
with patch( with patch(
"homeassistant.components.esphome.update.DomainData.get_entry_data", "homeassistant.components.esphome.update.DomainData.get_entry_data",
return_value=Mock(available=True, device_info=mock_device_info), return_value=Mock(available=True, device_info=mock_device_info),
@ -93,3 +93,46 @@ async def test_update_entity(
assert len(mock_upload.mock_calls) == 1 assert len(mock_upload.mock_calls) == 1
assert mock_upload.mock_calls[0][1][0] == "test.yaml" assert mock_upload.mock_calls[0][1][0] == "test.yaml"
async def test_update_static_info(
hass,
mock_config_entry,
mock_device_info,
mock_dashboard,
):
"""Test ESPHome update entity."""
mock_dashboard["configured"] = [
{
"name": "test",
"current_version": "1.2.3",
},
]
await async_get_dashboard(hass).async_refresh()
signal_static_info_updated = f"esphome_{mock_config_entry.entry_id}_on_list"
runtime_data = Mock(
available=True,
device_info=mock_device_info,
signal_static_info_updated=signal_static_info_updated,
)
with patch(
"homeassistant.components.esphome.update.DomainData.get_entry_data",
return_value=runtime_data,
):
assert await hass.config_entries.async_forward_entry_setup(
mock_config_entry, "update"
)
state = hass.states.get("update.none_firmware")
assert state is not None
assert state.state == "on"
runtime_data.device_info = dataclasses.replace(
runtime_data.device_info, esphome_version="1.2.3"
)
async_dispatcher_send(hass, signal_static_info_updated, [])
state = hass.states.get("update.none_firmware")
assert state.state == "off"