Only create Zonneplan entities for contracted energy types (#183844)

This commit is contained in:
Erwin Douna
2026-10-02 10:22:09 +02:00
committed by GitHub
parent 4af5f3a28c
commit 214daa1ebb
4 changed files with 67 additions and 23 deletions
@@ -28,6 +28,7 @@ class ZonneplanBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Describes a Zonneplan binary sensor."""
is_on_fn: Callable[[ZonneplanCoordinator], bool | None]
supported_fn: Callable[[ZonneplanCoordinator], bool]
BINARY_SENSORS: tuple[ZonneplanBinarySensorEntityDescription, ...] = (
@@ -46,6 +47,7 @@ BINARY_SENSORS: tuple[ZonneplanBinarySensorEntityDescription, ...] = (
)
else None
),
supported_fn=lambda coordinator: bool(coordinator.data.electricity_prices),
),
)
@@ -95,6 +97,7 @@ async def async_setup_entry(
*(
ZonneplanBinarySensor(coordinator, description)
for description in BINARY_SENSORS
if description.supported_fn(coordinator)
),
*(
ZonneplanBatteryBinarySensor(
+9 -1
View File
@@ -33,7 +33,7 @@ class ZonneplanPriceSensorEntityDescription(SensorEntityDescription):
"""Describes a Zonneplan price sensor."""
value_fn: Callable[[ZonneplanCoordinator], float | str | datetime | None]
supported_fn: Callable[[ZonneplanCoordinator], bool] | None = None
supported_fn: Callable[[ZonneplanCoordinator], bool]
ZONNEPLAN_SENSORS: tuple[ZonneplanPriceSensorEntityDescription, ...] = (
@@ -303,6 +303,7 @@ class ZonneplanUsageSensorEntityDescription(SensorEntityDescription):
group_fn: Callable[[ZonneplanData], ElectricityChartGroup | GasChartGroup | None]
value_fn: Callable[[ZonneplanData], Decimal | None]
supported_fn: Callable[[ZonneplanData], bool]
ZONNEPLAN_USAGE_SENSORS: tuple[ZonneplanUsageSensorEntityDescription, ...] = (
@@ -320,6 +321,7 @@ ZONNEPLAN_USAGE_SENSORS: tuple[ZonneplanUsageSensorEntityDescription, ...] = (
if data.electricity_usage and (group := data.electricity_usage.group)
else None
),
supported_fn=lambda data: data.electricity_usage is not None,
),
ZonneplanUsageSensorEntityDescription(
key="electricity_produced_this_month",
@@ -335,6 +337,7 @@ ZONNEPLAN_USAGE_SENSORS: tuple[ZonneplanUsageSensorEntityDescription, ...] = (
if data.electricity_usage and (group := data.electricity_usage.group)
else None
),
supported_fn=lambda data: data.electricity_usage is not None,
),
ZonneplanUsageSensorEntityDescription(
key="gas_delivered_this_month",
@@ -348,6 +351,7 @@ ZONNEPLAN_USAGE_SENSORS: tuple[ZonneplanUsageSensorEntityDescription, ...] = (
if data.gas_usage and (group := data.gas_usage.group)
else None
),
supported_fn=lambda data: data.gas_usage is not None,
),
ZonneplanUsageSensorEntityDescription(
key="electricity_cost_this_month",
@@ -366,6 +370,7 @@ ZONNEPLAN_USAGE_SENSORS: tuple[ZonneplanUsageSensorEntityDescription, ...] = (
and group.has_data
else None
),
supported_fn=lambda data: data.electricity_usage is not None,
),
ZonneplanUsageSensorEntityDescription(
key="gas_cost_this_month",
@@ -380,6 +385,7 @@ ZONNEPLAN_USAGE_SENSORS: tuple[ZonneplanUsageSensorEntityDescription, ...] = (
if data.gas_usage and (group := data.gas_usage.group) and group.has_data
else None
),
supported_fn=lambda data: data.gas_usage is not None,
),
)
@@ -397,10 +403,12 @@ async def async_setup_entry(
*(
ZonneplanPriceSensor(coordinator, description)
for description in ZONNEPLAN_SENSORS
if description.supported_fn(coordinator)
),
*(
ZonneplanUsageSensor(coordinator, description)
for description in ZONNEPLAN_USAGE_SENSORS
if description.supported_fn(coordinator.data)
),
]
)
@@ -1,4 +1,40 @@
# serializer version: 1
# name: test_entities_not_created_for_missing_market_segment[missing_electricity]
list([
'sensor.zonneplan_gas_cost_this_month',
'sensor.zonneplan_gas_price_daily',
'sensor.zonneplan_gas_used_this_month',
])
# ---
# name: test_entities_not_created_for_missing_market_segment[missing_gas]
list([
'binary_sensor.thuisbatterij_backup_power_active',
'binary_sensor.thuisbatterij_grid_congestion',
'binary_sensor.thuisbatterij_home_optimization_active',
'binary_sensor.thuisbatterij_load_balancing_overload',
'binary_sensor.zonneplan_electricity_price_low',
'sensor.zonneplan_current_electricity_price',
'sensor.zonneplan_current_electricity_tariff_group',
'sensor.zonneplan_current_sustainability_score',
'sensor.zonneplan_electricity_cost_this_month',
'sensor.zonneplan_electricity_price_low_today_end_time',
'sensor.zonneplan_electricity_price_low_today_start_time',
'sensor.zonneplan_electricity_price_low_tomorrow_end_time',
'sensor.zonneplan_electricity_price_low_tomorrow_start_time',
'sensor.zonneplan_electricity_prices_tomorrow_status',
'sensor.zonneplan_electricity_returned_this_month',
'sensor.zonneplan_electricity_used_this_month',
'sensor.zonneplan_highest_electricity_price_today',
'sensor.zonneplan_highest_electricity_price_tomorrow',
'sensor.zonneplan_lowest_electricity_price_today',
'sensor.zonneplan_lowest_electricity_price_tomorrow',
'sensor.zonneplan_next_hour_electricity_price',
])
# ---
# name: test_entities_not_created_for_missing_market_segment[no_energy_contract]
list([
])
# ---
# name: test_sensor[prices_incoming][sensor.zonneplan_current_electricity_price-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
+19 -22
View File
@@ -52,32 +52,22 @@ async def test_sensor(
@pytest.mark.parametrize(
("missing_market_segment", "entity_id"),
"missing_market_segments",
[
pytest.param(
"electricity",
"sensor.zonneplan_current_electricity_price",
id="missing_electricity",
),
pytest.param("gas", "sensor.zonneplan_gas_price_daily", id="missing_gas"),
pytest.param(
"electricity",
"sensor.zonneplan_electricity_used_this_month",
id="missing_electricity_usage",
),
pytest.param(
"gas", "sensor.zonneplan_gas_used_this_month", id="missing_gas_usage"
),
pytest.param({"electricity"}, id="missing_electricity"),
pytest.param({"gas"}, id="missing_gas"),
pytest.param({"electricity", "gas"}, id="no_energy_contract"),
],
)
async def test_sensor_unknown_for_missing_market_segment(
async def test_entities_not_created_for_missing_market_segment(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_zonneplan_client: AsyncMock,
missing_market_segment: str,
entity_id: str,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
missing_market_segments: set[str],
) -> None:
"""Test a sensor is unknown when its market segment isn't on the account."""
"""Test no entities are created for a market segment that isn't on the account."""
mock_zonneplan_client.async_get_account.return_value = dataclasses.replace(
MOCK_ACCOUNT,
address_groups=[
@@ -86,7 +76,7 @@ async def test_sensor_unknown_for_missing_market_segment(
connections=[
connection
for connection in address_group.connections
if connection.market_segment != missing_market_segment
if connection.market_segment not in missing_market_segments
],
)
for address_group in MOCK_ACCOUNT.address_groups
@@ -97,8 +87,15 @@ async def test_sensor_unknown_for_missing_market_segment(
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert (state := hass.states.get(entity_id))
assert state.state == STATE_UNKNOWN
assert (
sorted(
entity.entity_id
for entity in er.async_entries_for_config_entry(
entity_registry, mock_config_entry.entry_id
)
)
== snapshot
)
@pytest.mark.parametrize(