mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Add heat meter to Powerfox integration (#134799)
This commit is contained in:
parent
67e2379d2b
commit
99d7f462a0
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from powerfox import PowerMeter, WaterMeter
|
from powerfox import HeatMeter, PowerMeter, WaterMeter
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
@ -52,6 +52,22 @@ async def async_get_config_entry_diagnostics(
|
|||||||
if isinstance(coordinator.data, WaterMeter)
|
if isinstance(coordinator.data, WaterMeter)
|
||||||
else {}
|
else {}
|
||||||
),
|
),
|
||||||
|
**(
|
||||||
|
{
|
||||||
|
"heat_meter": {
|
||||||
|
"outdated": coordinator.data.outdated,
|
||||||
|
"timestamp": datetime.strftime(
|
||||||
|
coordinator.data.timestamp, "%Y-%m-%d %H:%M:%S"
|
||||||
|
),
|
||||||
|
"total_energy": coordinator.data.total_energy,
|
||||||
|
"delta_energy": coordinator.data.delta_energy,
|
||||||
|
"total_volume": coordinator.data.total_volume,
|
||||||
|
"delta_volume": coordinator.data.delta_volume,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isinstance(coordinator.data, HeatMeter)
|
||||||
|
else {}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
for coordinator in powerfox_data
|
for coordinator in powerfox_data
|
||||||
],
|
],
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from powerfox import Device, PowerMeter, WaterMeter
|
from powerfox import Device, HeatMeter, PowerMeter, WaterMeter
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
@ -23,7 +23,7 @@ from .entity import PowerfoxEntity
|
|||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
class PowerfoxSensorEntityDescription[T: (PowerMeter, WaterMeter)](
|
class PowerfoxSensorEntityDescription[T: (PowerMeter, WaterMeter, HeatMeter)](
|
||||||
SensorEntityDescription
|
SensorEntityDescription
|
||||||
):
|
):
|
||||||
"""Describes Poweropti sensor entity."""
|
"""Describes Poweropti sensor entity."""
|
||||||
@ -93,6 +93,40 @@ SENSORS_WATER: tuple[PowerfoxSensorEntityDescription[WaterMeter], ...] = (
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SENSORS_HEAT: tuple[PowerfoxSensorEntityDescription[HeatMeter], ...] = (
|
||||||
|
PowerfoxSensorEntityDescription[HeatMeter](
|
||||||
|
key="heat_total_energy",
|
||||||
|
translation_key="heat_total_energy",
|
||||||
|
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||||
|
device_class=SensorDeviceClass.ENERGY,
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
value_fn=lambda meter: meter.total_energy,
|
||||||
|
),
|
||||||
|
PowerfoxSensorEntityDescription[HeatMeter](
|
||||||
|
key="heat_delta_energy",
|
||||||
|
translation_key="heat_delta_energy",
|
||||||
|
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||||
|
device_class=SensorDeviceClass.ENERGY,
|
||||||
|
value_fn=lambda meter: meter.delta_energy,
|
||||||
|
),
|
||||||
|
PowerfoxSensorEntityDescription[HeatMeter](
|
||||||
|
key="heat_total_volume",
|
||||||
|
translation_key="heat_total_volume",
|
||||||
|
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||||
|
device_class=SensorDeviceClass.WATER,
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
value_fn=lambda meter: meter.total_volume,
|
||||||
|
),
|
||||||
|
PowerfoxSensorEntityDescription[HeatMeter](
|
||||||
|
key="heat_delta_volume",
|
||||||
|
translation_key="heat_delta_volume",
|
||||||
|
suggested_display_precision=2,
|
||||||
|
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||||
|
device_class=SensorDeviceClass.WATER,
|
||||||
|
value_fn=lambda meter: meter.delta_volume,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -121,6 +155,15 @@ async def async_setup_entry(
|
|||||||
)
|
)
|
||||||
for description in SENSORS_WATER
|
for description in SENSORS_WATER
|
||||||
)
|
)
|
||||||
|
if isinstance(coordinator.data, HeatMeter):
|
||||||
|
entities.extend(
|
||||||
|
PowerfoxSensorEntity(
|
||||||
|
coordinator=coordinator,
|
||||||
|
description=description,
|
||||||
|
device=coordinator.device,
|
||||||
|
)
|
||||||
|
for description in SENSORS_HEAT
|
||||||
|
)
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,18 @@
|
|||||||
},
|
},
|
||||||
"warm_water": {
|
"warm_water": {
|
||||||
"name": "Warm water"
|
"name": "Warm water"
|
||||||
|
},
|
||||||
|
"heat_total_energy": {
|
||||||
|
"name": "Total energy"
|
||||||
|
},
|
||||||
|
"heat_delta_energy": {
|
||||||
|
"name": "Delta energy"
|
||||||
|
},
|
||||||
|
"heat_total_volume": {
|
||||||
|
"name": "Total volume"
|
||||||
|
},
|
||||||
|
"heat_delta_volume": {
|
||||||
|
"name": "Delta volume"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ from collections.abc import Generator
|
|||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from powerfox import Device, DeviceType, PowerMeter, WaterMeter
|
from powerfox import Device, DeviceType, HeatMeter, PowerMeter, WaterMeter
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.powerfox.const import DOMAIN
|
from homeassistant.components.powerfox.const import DOMAIN
|
||||||
@ -53,6 +53,14 @@ def mock_powerfox_client() -> Generator[AsyncMock]:
|
|||||||
type=DeviceType.COLD_WATER_METER,
|
type=DeviceType.COLD_WATER_METER,
|
||||||
name="Wateropti",
|
name="Wateropti",
|
||||||
),
|
),
|
||||||
|
Device(
|
||||||
|
id="9x9x1f12xx5x",
|
||||||
|
date_added=datetime(2024, 11, 26, 9, 22, 35, tzinfo=UTC),
|
||||||
|
main_device=False,
|
||||||
|
bidirectional=False,
|
||||||
|
type=DeviceType.HEAT_METER,
|
||||||
|
name="Heatopti",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
client.device.side_effect = [
|
client.device.side_effect = [
|
||||||
PowerMeter(
|
PowerMeter(
|
||||||
@ -70,6 +78,14 @@ def mock_powerfox_client() -> Generator[AsyncMock]:
|
|||||||
cold_water=1111.111,
|
cold_water=1111.111,
|
||||||
warm_water=0.0,
|
warm_water=0.0,
|
||||||
),
|
),
|
||||||
|
HeatMeter(
|
||||||
|
outdated=False,
|
||||||
|
timestamp=datetime(2024, 11, 26, 10, 48, 51, tzinfo=UTC),
|
||||||
|
total_energy=1111.111,
|
||||||
|
delta_energy=111,
|
||||||
|
total_volume=1111.111,
|
||||||
|
delta_volume=0.111,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
yield client
|
yield client
|
||||||
|
|
||||||
|
@ -21,6 +21,16 @@
|
|||||||
'warm_water': 0.0,
|
'warm_water': 0.0,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'heat_meter': dict({
|
||||||
|
'delta_energy': 111,
|
||||||
|
'delta_volume': 0.111,
|
||||||
|
'outdated': False,
|
||||||
|
'timestamp': '2024-11-26 10:48:51',
|
||||||
|
'total_energy': 1111.111,
|
||||||
|
'total_volume': 1111.111,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
@ -1,4 +1,205 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
|
# name: test_all_sensors[sensor.heatopti_delta_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.heatopti_delta_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Delta energy',
|
||||||
|
'platform': 'powerfox',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'heat_delta_energy',
|
||||||
|
'unique_id': '9x9x1f12xx5x_heat_delta_energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_delta_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Heatopti Delta energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.heatopti_delta_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '111',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_delta_volume-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.heatopti_delta_volume',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
'sensor': dict({
|
||||||
|
'suggested_display_precision': 2,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.WATER: 'water'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Delta volume',
|
||||||
|
'platform': 'powerfox',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'heat_delta_volume',
|
||||||
|
'unique_id': '9x9x1f12xx5x_heat_delta_volume',
|
||||||
|
'unit_of_measurement': <UnitOfVolume.CUBIC_METERS: 'm³'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_delta_volume-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'water',
|
||||||
|
'friendly_name': 'Heatopti Delta volume',
|
||||||
|
'unit_of_measurement': <UnitOfVolume.CUBIC_METERS: 'm³'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.heatopti_delta_volume',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '0.111',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_total_energy-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.heatopti_total_energy',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Total energy',
|
||||||
|
'platform': 'powerfox',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'heat_total_energy',
|
||||||
|
'unique_id': '9x9x1f12xx5x_heat_total_energy',
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_total_energy-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'energy',
|
||||||
|
'friendly_name': 'Heatopti Total energy',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.heatopti_total_energy',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '1111.111',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_total_volume-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.heatopti_total_volume',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.WATER: 'water'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Total volume',
|
||||||
|
'platform': 'powerfox',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'heat_total_volume',
|
||||||
|
'unique_id': '9x9x1f12xx5x_heat_total_volume',
|
||||||
|
'unit_of_measurement': <UnitOfVolume.CUBIC_METERS: 'm³'>,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_sensors[sensor.heatopti_total_volume-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'water',
|
||||||
|
'friendly_name': 'Heatopti Total volume',
|
||||||
|
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||||
|
'unit_of_measurement': <UnitOfVolume.CUBIC_METERS: 'm³'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.heatopti_total_volume',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '1111.111',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_sensors[sensor.poweropti_energy_return-entry]
|
# name: test_all_sensors[sensor.poweropti_energy_return-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user