diff --git a/homeassistant/components/sofar/sensor.py b/homeassistant/components/sofar/sensor.py index 7318620431fe..f446a9af5e4d 100644 --- a/homeassistant/components/sofar/sensor.py +++ b/homeassistant/components/sofar/sensor.py @@ -434,12 +434,6 @@ SENSOR_DESCRIPTIONS: tuple[SofarSensorDescription, ...] = ( state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, ), - SofarSensorDescription( - key="serial_number", - component="identity", - translation_key="serial_number", - entity_category=EntityCategory.DIAGNOSTIC, - ), SofarSensorDescription( key="grid_frequency", component="grid", diff --git a/homeassistant/components/sofar/strings.json b/homeassistant/components/sofar/strings.json index ca13c38cbdc2..9d052060427b 100644 --- a/homeassistant/components/sofar/strings.json +++ b/homeassistant/components/sofar/strings.json @@ -399,9 +399,6 @@ "reactive_power_pcc_total": { "name": "Reactive power PCC total" }, - "serial_number": { - "name": "Serial number" - }, "solar_generation_today": { "name": "Solar generation today" }, diff --git a/tests/components/sofar/snapshots/test_sensor.ambr b/tests/components/sofar/snapshots/test_sensor.ambr index 372a5bde4ec1..5655ad95c02e 100644 --- a/tests/components/sofar/snapshots/test_sensor.ambr +++ b/tests/components/sofar/snapshots/test_sensor.ambr @@ -6709,56 +6709,6 @@ 'state': '0.0', }) # --- -# name: test_all_entities[sensor.hydxxktl_3p_serial_number-entry] - EntityRegistryEntrySnapshot({ - 'aliases': list([ - None, - ]), - 'area_id': None, - 'capabilities': None, - 'config_entry_id': , - 'config_subentry_id': , - 'device_class': None, - 'device_id': , - 'disabled_by': None, - 'domain': 'sensor', - 'entity_category': , - 'entity_id': 'sensor.hydxxktl_3p_serial_number', - 'has_entity_name': True, - 'hidden_by': None, - 'icon': None, - 'id': , - 'labels': set({ - }), - 'name': None, - 'object_id_base': 'Serial number', - 'options': dict({ - }), - 'original_device_class': None, - 'original_icon': None, - 'original_name': 'Serial number', - 'platform': 'sofar', - 'previous_unique_id': None, - 'suggested_object_id': None, - 'supported_features': 0, - 'translation_key': 'serial_number', - 'unique_id': 'SP1XXES100XX_serial_number', - 'unit_of_measurement': None, - }) -# --- -# name: test_all_entities[sensor.hydxxktl_3p_serial_number-state] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - : 'HYDxxKTL-3P Serial number', - }), - 'context': , - 'entity_id': 'sensor.hydxxktl_3p_serial_number', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': 'SP1XXES100XX', - }) -# --- # name: test_all_entities[sensor.hydxxktl_3p_solar_generation_today-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/sofar/test_init.py b/tests/components/sofar/test_init.py index f0d1005a47ae..7793ba2113d6 100644 --- a/tests/components/sofar/test_init.py +++ b/tests/components/sofar/test_init.py @@ -130,7 +130,6 @@ async def test_setup_entry_unreachable_link_retries_and_recovers( async def test_settings_failure_does_not_block_reading_sensors( hass: HomeAssistant, - entity_registry: er.EntityRegistry, mock_connection: MockModbusConnection, mock_config_entry: MockConfigEntry, ) -> None: @@ -154,51 +153,42 @@ async def test_settings_failure_does_not_block_reading_sensors( assert mock_config_entry.state is ConfigEntryState.LOADED assert hass.states.async_entity_ids("sensor") - - # Created despite the failure, so the coordinator keeps a listener and - # retries; without one it would never poll again short of a reload. - entity_id = entity_registry.async_get_entity_id( - SENSOR_DOMAIN, DOMAIN, f"{MOCK_SERIAL}_serial_number" - ) - assert entity_id is not None - assert (state := hass.states.get(entity_id)) is not None - assert state.state == STATE_UNAVAILABLE + assert mock_config_entry.runtime_data.settings.last_update_success is False async def test_settings_recover_without_a_reload( hass: HomeAssistant, freezer: FrozenDateTimeFactory, - entity_registry: er.EntityRegistry, - mock_connection: MockModbusConnection, - mock_config_entry: MockConfigEntry, ) -> None: - """Test settings sensors come back on their own once the link heals.""" - mock_config_entry.add_to_hass(hass) - unit = mock_connection.for_unit(1) + """Test the settings coordinator recovers on its own once the link heals.""" + connection = MockModbusConnection() + seed_hybrid_inverter(connection.for_unit(1)) + unit = connection.for_unit(1) # A settings-only register, so the readings poll still sets up. unit.fail_read(0x1105, ModbusConnectionError("settings unreachable")) + entry = MockConfigEntry( + domain=DOMAIN, + unique_id=MOCK_HYBRID_SERIAL, + data=MOCK_USER_INPUT, + title=MOCK_HYBRID_MODEL, + ) + entry.add_to_hass(hass) with patch( "homeassistant.components.sofar.async_get_unit", - side_effect=lambda hass, entry, params, unit_id: mock_connection.for_unit( - unit_id - ), + side_effect=lambda hass, entry, params, unit_id: connection.for_unit(unit_id), ): - await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done(wait_background_tasks=True) - entity_id = entity_registry.async_get_entity_id( - SENSOR_DOMAIN, DOMAIN, f"{MOCK_SERIAL}_serial_number" - ) - assert entity_id is not None - assert hass.states.get(entity_id).state == STATE_UNAVAILABLE + assert entry.runtime_data.settings.last_update_success is False unit.fail_read(0x1105, None) freezer.tick(timedelta(seconds=SETTINGS_SCAN_INTERVAL)) async_fire_time_changed(hass) await hass.async_block_till_done() - assert hass.states.get(entity_id).state == MOCK_SERIAL + assert entry.runtime_data.settings.last_update_success is True async def test_sensor_platform_is_forwarded( @@ -228,26 +218,30 @@ async def test_device_versions_recover_without_a_reload( hass: HomeAssistant, freezer: FrozenDateTimeFactory, device_registry: dr.DeviceRegistry, - mock_connection: MockModbusConnection, - mock_config_entry: MockConfigEntry, ) -> None: """Test firmware versions reach the device once identity answers.""" - mock_config_entry.add_to_hass(hass) - unit = mock_connection.for_unit(1) + connection = MockModbusConnection() + seed_hybrid_inverter(connection.for_unit(1)) + unit = connection.for_unit(1) # Inside the identity block, so the whole component fails to read. unit.fail_read(0x044D, ModbusConnectionError("identity unreachable")) + entry = MockConfigEntry( + domain=DOMAIN, + unique_id=MOCK_HYBRID_SERIAL, + data=MOCK_USER_INPUT, + title=MOCK_HYBRID_MODEL, + ) + entry.add_to_hass(hass) with patch( "homeassistant.components.sofar.async_get_unit", - side_effect=lambda hass, entry, params, unit_id: mock_connection.for_unit( - unit_id - ), + side_effect=lambda hass, entry, params, unit_id: connection.for_unit(unit_id), ): - await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done(wait_background_tasks=True) device = device_registry.async_get_device_by_identifier( - (DOMAIN, MOCK_SERIAL), mock_config_entry.entry_id + (DOMAIN, MOCK_HYBRID_SERIAL), entry.entry_id ) assert device is not None assert device.hw_version is None @@ -259,7 +253,7 @@ async def test_device_versions_recover_without_a_reload( await hass.async_block_till_done() device = device_registry.async_get_device_by_identifier( - (DOMAIN, MOCK_SERIAL), mock_config_entry.entry_id + (DOMAIN, MOCK_HYBRID_SERIAL), entry.entry_id ) assert device is not None assert device.hw_version == MOCK_HW_VERSION diff --git a/tests/components/sofar/test_sensor.py b/tests/components/sofar/test_sensor.py index 59b101f9c656..805ec980736f 100644 --- a/tests/components/sofar/test_sensor.py +++ b/tests/components/sofar/test_sensor.py @@ -98,13 +98,13 @@ async def test_sensor_entities_created_and_state( @pytest.mark.parametrize( ("serial", "model", "seed", "created", "enabled"), [ - pytest.param(MOCK_SERIAL, MOCK_MODEL, seed_pv_inverter, 73, 23, id="pv"), + pytest.param(MOCK_SERIAL, MOCK_MODEL, seed_pv_inverter, 72, 22, id="pv"), pytest.param( MOCK_HYBRID_SERIAL, MOCK_HYBRID_MODEL, seed_hybrid_inverter, - 139, - 46, + 138, + 45, id="hybrid", ), ], @@ -155,15 +155,30 @@ async def test_enabled_by_default_partition( async def test_settings_backed_sensor_created_and_state( hass: HomeAssistant, entity_registry: er.EntityRegistry, - init_integration: MockConfigEntry, ) -> None: """Test a settings-polled component reaches the sensor platform.""" - serial_id = entity_registry.async_get_entity_id( - SENSOR_DOMAIN, "sofar", f"{MOCK_SERIAL}_serial_number" + connection = MockModbusConnection() + seed_hybrid_inverter(connection.for_unit(1)) + entry = MockConfigEntry( + domain=DOMAIN, + unique_id=MOCK_HYBRID_SERIAL, + data=MOCK_USER_INPUT, + title=MOCK_HYBRID_MODEL, ) - assert serial_id is not None - assert (state := hass.states.get(serial_id)) is not None - assert state.state == MOCK_SERIAL + entry.add_to_hass(hass) + with patch( + "homeassistant.components.sofar.async_get_unit", + side_effect=lambda hass, entry, params, unit_id: connection.for_unit(unit_id), + ): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done(wait_background_tasks=True) + + rtc_id = entity_registry.async_get_entity_id( + SENSOR_DOMAIN, "sofar", f"{MOCK_HYBRID_SERIAL}_sync_rtc_result" + ) + assert rtc_id is not None + assert (state := hass.states.get(rtc_id)) is not None + assert state.state == "successful" @pytest.mark.usefixtures("entity_registry_enabled_by_default")