Reload enphase_envoy integration upon envoy firmware change detection (#124650)

* Reload enphase_envoy integration upon envoy firmware change detection.

* remove persistant notification
This commit is contained in:
Arie Catsman 2024-09-11 19:39:54 +02:00 committed by GitHub
parent f52f60307b
commit 66f9e06c25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 55 additions and 0 deletions

View File

@ -24,6 +24,7 @@ SCAN_INTERVAL = timedelta(seconds=60)
TOKEN_REFRESH_CHECK_INTERVAL = timedelta(days=1)
STALE_TOKEN_THRESHOLD = timedelta(days=30).total_seconds()
NOTIFICATION_ID = "enphase_envoy_notification"
_LOGGER = logging.getLogger(__name__)
@ -35,6 +36,7 @@ class EnphaseUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""DataUpdateCoordinator to gather data from any envoy."""
envoy_serial_number: str
envoy_firmware: str
def __init__(
self, hass: HomeAssistant, envoy: Envoy, entry: EnphaseConfigEntry
@ -46,6 +48,7 @@ class EnphaseUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
self.username = entry_data[CONF_USERNAME]
self.password = entry_data[CONF_PASSWORD]
self._setup_complete = False
self.envoy_firmware = ""
self._cancel_token_refresh: CALLBACK_TYPE | None = None
super().__init__(
hass,
@ -158,6 +161,24 @@ class EnphaseUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
raise ConfigEntryAuthFailed from err
except EnvoyError as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
# if we have a firmware version from previous setup, compare to current one
# when envoy gets new firmware there will be an authentication failure
# which results in getting fw version again, if so reload the integration.
if (current_firmware := self.envoy_firmware) and current_firmware != (
new_firmware := envoy.firmware
):
_LOGGER.warning(
"Envoy firmware changed from: %s to: %s, reloading enphase envoy integration",
current_firmware,
new_firmware,
)
# reload the integration to get all established again
self.hass.async_create_task(
self.hass.config_entries.async_reload(self.entry.entry_id)
)
# remember firmware version for next time
self.envoy_firmware = envoy.firmware
_LOGGER.debug("Envoy data: %s", envoy_data)
return envoy_data.raw

View File

@ -1,6 +1,7 @@
"""Test Enphase Envoy sensors."""
from itertools import chain
import logging
from unittest.mock import AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
@ -1002,3 +1003,36 @@ async def test_sensor_missing_data(
# test the original inverter is now unknown
assert (entity_state := hass.states.get("sensor.inverter_1"))
assert entity_state.state == STATE_UNKNOWN
@pytest.mark.parametrize(
("mock_envoy"),
[
"envoy_metered_batt_relay",
],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_fw_update(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_envoy: AsyncMock,
entity_registry: er.EntityRegistry,
freezer: FrozenDateTimeFactory,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test enphase_envoy sensor update over fw update."""
logging.getLogger("homeassistant.components.enphase_envoy").setLevel(logging.DEBUG)
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, config_entry)
# force HA to detect changed data by changing raw
mock_envoy.firmware = "0.0.0"
# Move time to next update
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert "firmware changed from: " in caplog.text
assert "to: 0.0.0, reloading enphase envoy integration" in caplog.text