Add distinct import / export entities to Fronius (#116535)

This commit is contained in:
Matthias Alphart 2024-06-22 11:12:21 +02:00 committed by GitHub
parent 3d9f053256
commit 77edc149ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 103 additions and 18 deletions

View file

@ -549,6 +549,25 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
FroniusSensorEntityDescription(
key="power_battery_discharge",
response_key="power_battery",
default_value=0,
value_fn=lambda value: max(value, 0), # type: ignore[type-var]
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
),
FroniusSensorEntityDescription(
key="power_battery_charge",
response_key="power_battery",
default_value=0,
value_fn=lambda value: max(0 - value, 0), # type: ignore[operator]
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
),
FroniusSensorEntityDescription(
key="power_grid",
@ -556,6 +575,25 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
FroniusSensorEntityDescription(
key="power_grid_import",
response_key="power_grid",
default_value=0,
value_fn=lambda value: max(value, 0), # type: ignore[type-var]
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
),
FroniusSensorEntityDescription(
key="power_grid_export",
response_key="power_grid",
default_value=0,
value_fn=lambda value: max(0 - value, 0), # type: ignore[operator]
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
),
FroniusSensorEntityDescription(
key="power_load",
@ -563,6 +601,26 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
FroniusSensorEntityDescription(
key="power_load_generated",
response_key="power_load",
default_value=0,
value_fn=lambda value: max(value, 0), # type: ignore[type-var]
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
FroniusSensorEntityDescription(
key="power_load_consumed",
response_key="power_load",
default_value=0,
value_fn=lambda value: max(0 - value, 0), # type: ignore[operator]
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
),
FroniusSensorEntityDescription(
key="power_photovoltaics",
@ -670,7 +728,7 @@ class _FroniusSensorEntity(CoordinatorEntity["FroniusCoordinatorBase"], SensorEn
if self.entity_description.invalid_when_falsy and not new_value:
return None
if self.entity_description.value_fn is not None:
return self.entity_description.value_fn(new_value)
new_value = self.entity_description.value_fn(new_value)
if isinstance(new_value, float):
return round(new_value, 4)
return new_value

View file

@ -234,12 +234,30 @@
"power_battery": {
"name": "Power battery"
},
"power_battery_discharge": {
"name": "Power battery discharge"
},
"power_battery_charge": {
"name": "Power battery charge"
},
"power_grid": {
"name": "Power grid"
},
"power_grid_import": {
"name": "Power grid import"
},
"power_grid_export": {
"name": "Power grid export"
},
"power_load": {
"name": "Power load"
},
"power_load_generated": {
"name": "Power load generated"
},
"power_load_consumed": {
"name": "Power load consumed"
},
"power_photovoltaics": {
"name": "Power photovoltaics"
},

View file

@ -34,14 +34,14 @@ async def test_symo_inverter(
mock_responses(aioclient_mock, night=True)
config_entry = await setup_fronius_integration(hass)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 21
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 22
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusInverterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 54
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 58
assert_state("sensor.symo_20_dc_current", 0)
assert_state("sensor.symo_20_energy_day", 10828)
assert_state("sensor.symo_20_total_energy", 44186900)
@ -54,14 +54,14 @@ async def test_symo_inverter(
freezer.tick(FroniusInverterUpdateCoordinator.default_interval)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 58
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 62
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusInverterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 60
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 64
# 4 additional AC entities
assert_state("sensor.symo_20_dc_current", 2.19)
assert_state("sensor.symo_20_energy_day", 1113)
@ -97,7 +97,7 @@ async def test_symo_logger(
mock_responses(aioclient_mock)
await setup_fronius_integration(hass)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 25
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 26
# states are rounded to 4 decimals
assert_state("sensor.solarnet_grid_export_tariff", 0.078)
assert_state("sensor.solarnet_co2_factor", 0.53)
@ -119,14 +119,14 @@ async def test_symo_meter(
mock_responses(aioclient_mock)
config_entry = await setup_fronius_integration(hass)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 25
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 26
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusMeterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 60
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 64
# states are rounded to 4 decimals
assert_state("sensor.smart_meter_63a_current_phase_1", 7.755)
assert_state("sensor.smart_meter_63a_current_phase_2", 6.68)
@ -222,20 +222,23 @@ async def test_symo_power_flow(
mock_responses(aioclient_mock, night=True)
config_entry = await setup_fronius_integration(hass)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 21
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 22
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusInverterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 54
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 58
# states are rounded to 4 decimals
assert_state("sensor.solarnet_energy_day", 10828)
assert_state("sensor.solarnet_total_energy", 44186900)
assert_state("sensor.solarnet_energy_year", 25507686)
assert_state("sensor.solarnet_power_grid", 975.31)
assert_state("sensor.solarnet_power_grid_import", 975.31)
assert_state("sensor.solarnet_power_grid_export", 0)
assert_state("sensor.solarnet_power_load", -975.31)
assert_state("sensor.solarnet_power_load_consumed", 975.31)
assert_state("sensor.solarnet_relative_autonomy", 0)
# Second test at daytime when inverter is producing
@ -244,12 +247,16 @@ async def test_symo_power_flow(
async_fire_time_changed(hass)
await hass.async_block_till_done()
# 54 because power_flow `rel_SelfConsumption` and `P_PV` is not `null` anymore
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 56
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 60
assert_state("sensor.solarnet_energy_day", 1101.7001)
assert_state("sensor.solarnet_total_energy", 44188000)
assert_state("sensor.solarnet_energy_year", 25508788)
assert_state("sensor.solarnet_power_grid", 1703.74)
assert_state("sensor.solarnet_power_grid_import", 1703.74)
assert_state("sensor.solarnet_power_grid_export", 0)
assert_state("sensor.solarnet_power_load", -2814.74)
assert_state("sensor.solarnet_power_load_generated", 0)
assert_state("sensor.solarnet_power_load_consumed", 2814.74)
assert_state("sensor.solarnet_power_photovoltaics", 1111)
assert_state("sensor.solarnet_relative_autonomy", 39.4708)
assert_state("sensor.solarnet_relative_self_consumption", 100)
@ -259,7 +266,7 @@ async def test_symo_power_flow(
freezer.tick(FroniusPowerFlowUpdateCoordinator.default_interval)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 56
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 60
assert_state("sensor.solarnet_energy_day", 10828)
assert_state("sensor.solarnet_total_energy", 44186900)
assert_state("sensor.solarnet_energy_year", 25507686)
@ -285,14 +292,14 @@ async def test_gen24(
mock_responses(aioclient_mock, fixture_set="gen24")
config_entry = await setup_fronius_integration(hass, is_logger=False)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 23
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 24
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusMeterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 54
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 58
# inverter 1
assert_state("sensor.inverter_name_ac_current", 0.1589)
assert_state("sensor.inverter_name_dc_current_2", 0.0754)
@ -386,14 +393,14 @@ async def test_gen24_storage(
hass, is_logger=False, unique_id="12345678"
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 35
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 37
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusMeterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 66
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 72
# inverter 1
assert_state("sensor.gen24_storage_dc_current", 0.3952)
assert_state("sensor.gen24_storage_dc_voltage_2", 318.8103)
@ -452,6 +459,8 @@ async def test_gen24_storage(
# power_flow
assert_state("sensor.solarnet_power_grid", 2274.9)
assert_state("sensor.solarnet_power_battery", 0.1591)
assert_state("sensor.solarnet_power_battery_charge", 0)
assert_state("sensor.solarnet_power_battery_discharge", 0.1591)
assert_state("sensor.solarnet_power_load", -2459.3092)
assert_state("sensor.solarnet_relative_self_consumption", 100.0)
assert_state("sensor.solarnet_power_photovoltaics", 216.4328)
@ -514,14 +523,14 @@ async def test_primo_s0(
mock_responses(aioclient_mock, fixture_set="primo_s0", inverter_ids=[1, 2])
config_entry = await setup_fronius_integration(hass, is_logger=True)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 30
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 31
await enable_all_entities(
hass,
freezer,
config_entry.entry_id,
FroniusMeterUpdateCoordinator.default_interval,
)
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 43
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 47
# logger
assert_state("sensor.solarnet_grid_export_tariff", 1)
assert_state("sensor.solarnet_co2_factor", 0.53)