Keep Sofar diagnostics downloadable when the inverter is unreachable (#183218)

This commit is contained in:
darkrain-nl
2026-09-26 21:58:40 +02:00
committed by GitHub
parent c9f01eb001
commit e34a15c912
3 changed files with 44 additions and 3 deletions
+11 -3
View File
@@ -3,6 +3,8 @@
from dataclasses import asdict
from typing import Any
from modbus_connection import ModbusError
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.core import HomeAssistant
@@ -19,8 +21,13 @@ async def async_get_config_entry_diagnostics(
"""Return diagnostics for a config entry."""
runtime_data = entry.runtime_data
device = runtime_data.readings.device
raw = await device.async_read_raw()
if (holding := raw.get("holding")) is not None:
raw = masks = read_error = None
try:
raw = await device.async_read_raw()
masks = await device.async_read_masks()
except ModbusError as err:
read_error = type(err).__name__
if raw is not None and (holding := raw.get("holding")) is not None:
for address in _SERIAL_NUMBER_REGISTERS:
holding.pop(address, None)
@@ -32,11 +39,12 @@ async def async_get_config_entry_diagnostics(
"readings_components": device.readings_components,
"settings_components": device.settings_components,
"active_faults": sorted(fault.key for fault in device.state.active_faults),
"address_masks": await device.async_read_masks(),
"address_masks": masks,
"link": {
"tuning": asdict(runtime_data.tuner.tuning),
"stats": asdict(runtime_data.link.stats),
},
"read_error": read_error,
"raw": raw,
},
TO_REDACT,
@@ -194,6 +194,7 @@
'4358': 0,
}),
}),
'read_error': None,
'readings_components': list([
'state',
'grid',
@@ -2,7 +2,9 @@
from unittest.mock import patch
from modbus_connection import ModbusConnectionError, ModbusError, ModbusTimeoutError
from modbus_connection.mock import MockModbusConnection
import pytest
from syrupy.assertion import SnapshotAssertion
from syrupy.matchers import path_type
@@ -83,3 +85,33 @@ async def test_diagnostics_decodes_address_masks(
diag = await get_diagnostics_for_config_entry(hass, hass_client, init_integration)
assert diag["address_masks"]["1024"] == 0x0001000200030004
@pytest.mark.parametrize(
("error", "error_name"),
[
pytest.param(ModbusTimeoutError("silent"), "ModbusTimeoutError", id="timeout"),
pytest.param(
ModbusConnectionError("gone"), "ModbusConnectionError", id="link_lost"
),
],
)
async def test_diagnostics_inverter_unreachable(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
mock_connection: MockModbusConnection,
init_integration: MockConfigEntry,
error: ModbusError,
error_name: str,
) -> None:
"""Test diagnostics still download when the inverter stops answering."""
unit = mock_connection.for_unit(1)
unit.fail_requests(error)
unit.read_events.clear()
diag = await get_diagnostics_for_config_entry(hass, hass_client, init_integration)
assert diag["read_error"] == error_name
assert diag["raw"] is None
assert diag["address_masks"] is None
assert len(unit.read_events) == 1