mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add energy and gas sensors to demo integration (#77206)
This commit is contained in:
parent
853fab0a68
commit
2497ff5a39
@ -6,6 +6,7 @@ from random import random
|
|||||||
from homeassistant import config_entries, setup
|
from homeassistant import config_entries, setup
|
||||||
from homeassistant.components import persistent_notification
|
from homeassistant.components import persistent_notification
|
||||||
from homeassistant.components.recorder import get_instance
|
from homeassistant.components.recorder import get_instance
|
||||||
|
from homeassistant.components.recorder.models import StatisticMetaData
|
||||||
from homeassistant.components.recorder.statistics import (
|
from homeassistant.components.recorder.statistics import (
|
||||||
async_add_external_statistics,
|
async_add_external_statistics,
|
||||||
get_last_statistics,
|
get_last_statistics,
|
||||||
@ -260,15 +261,16 @@ def _generate_sum_statistics(start, end, init_value, max_diff):
|
|||||||
return statistics
|
return statistics
|
||||||
|
|
||||||
|
|
||||||
async def _insert_statistics(hass):
|
async def _insert_statistics(hass: HomeAssistant) -> None:
|
||||||
"""Insert some fake statistics."""
|
"""Insert some fake statistics."""
|
||||||
now = dt_util.now()
|
now = dt_util.now()
|
||||||
yesterday = now - datetime.timedelta(days=1)
|
yesterday = now - datetime.timedelta(days=1)
|
||||||
yesterday_midnight = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
|
yesterday_midnight = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
# Fake yesterday's temperatures
|
# Fake yesterday's temperatures
|
||||||
metadata = {
|
metadata: StatisticMetaData = {
|
||||||
"source": DOMAIN,
|
"source": DOMAIN,
|
||||||
|
"name": "Outdoor temperature",
|
||||||
"statistic_id": f"{DOMAIN}:temperature_outdoor",
|
"statistic_id": f"{DOMAIN}:temperature_outdoor",
|
||||||
"unit_of_measurement": "°C",
|
"unit_of_measurement": "°C",
|
||||||
"has_mean": True,
|
"has_mean": True,
|
||||||
@ -279,26 +281,94 @@ async def _insert_statistics(hass):
|
|||||||
)
|
)
|
||||||
async_add_external_statistics(hass, metadata, statistics)
|
async_add_external_statistics(hass, metadata, statistics)
|
||||||
|
|
||||||
# Fake yesterday's energy consumption
|
# Add external energy consumption in kWh, ~ 12 kWh / day
|
||||||
|
# This should be possible to pick for the energy dashboard
|
||||||
|
statistic_id = f"{DOMAIN}:energy_consumption_kwh"
|
||||||
metadata = {
|
metadata = {
|
||||||
"source": DOMAIN,
|
"source": DOMAIN,
|
||||||
"statistic_id": f"{DOMAIN}:energy_consumption",
|
"name": "Energy consumption 1",
|
||||||
|
"statistic_id": statistic_id,
|
||||||
"unit_of_measurement": "kWh",
|
"unit_of_measurement": "kWh",
|
||||||
"has_mean": False,
|
"has_mean": False,
|
||||||
"has_sum": True,
|
"has_sum": True,
|
||||||
}
|
}
|
||||||
statistic_id = f"{DOMAIN}:energy_consumption"
|
|
||||||
sum_ = 0
|
sum_ = 0
|
||||||
last_stats = await get_instance(hass).async_add_executor_job(
|
last_stats = await get_instance(hass).async_add_executor_job(
|
||||||
get_last_statistics, hass, 1, statistic_id, True
|
get_last_statistics, hass, 1, statistic_id, True
|
||||||
)
|
)
|
||||||
if "domain:energy_consumption" in last_stats:
|
if statistic_id in last_stats:
|
||||||
sum_ = last_stats["domain.electricity_total"]["sum"] or 0
|
sum_ = last_stats[statistic_id][0]["sum"] or 0
|
||||||
|
statistics = _generate_sum_statistics(
|
||||||
|
yesterday_midnight, yesterday_midnight + datetime.timedelta(days=1), sum_, 2
|
||||||
|
)
|
||||||
|
async_add_external_statistics(hass, metadata, statistics)
|
||||||
|
|
||||||
|
# Add external energy consumption in MWh, ~ 12 kWh / day
|
||||||
|
# This should not be possible to pick for the energy dashboard
|
||||||
|
statistic_id = f"{DOMAIN}:energy_consumption_mwh"
|
||||||
|
metadata = {
|
||||||
|
"source": DOMAIN,
|
||||||
|
"name": "Energy consumption 2",
|
||||||
|
"statistic_id": statistic_id,
|
||||||
|
"unit_of_measurement": "MWh",
|
||||||
|
"has_mean": False,
|
||||||
|
"has_sum": True,
|
||||||
|
}
|
||||||
|
sum_ = 0
|
||||||
|
last_stats = await get_instance(hass).async_add_executor_job(
|
||||||
|
get_last_statistics, hass, 1, statistic_id, True
|
||||||
|
)
|
||||||
|
if statistic_id in last_stats:
|
||||||
|
sum_ = last_stats[statistic_id][0]["sum"] or 0
|
||||||
|
statistics = _generate_sum_statistics(
|
||||||
|
yesterday_midnight, yesterday_midnight + datetime.timedelta(days=1), sum_, 0.002
|
||||||
|
)
|
||||||
|
async_add_external_statistics(hass, metadata, statistics)
|
||||||
|
|
||||||
|
# Add external gas consumption in m³, ~6 m3/day
|
||||||
|
# This should be possible to pick for the energy dashboard
|
||||||
|
statistic_id = f"{DOMAIN}:gas_consumption_m3"
|
||||||
|
metadata = {
|
||||||
|
"source": DOMAIN,
|
||||||
|
"name": "Gas consumption 1",
|
||||||
|
"statistic_id": statistic_id,
|
||||||
|
"unit_of_measurement": "m³",
|
||||||
|
"has_mean": False,
|
||||||
|
"has_sum": True,
|
||||||
|
}
|
||||||
|
sum_ = 0
|
||||||
|
last_stats = await get_instance(hass).async_add_executor_job(
|
||||||
|
get_last_statistics, hass, 1, statistic_id, True
|
||||||
|
)
|
||||||
|
if statistic_id in last_stats:
|
||||||
|
sum_ = last_stats[statistic_id][0]["sum"] or 0
|
||||||
statistics = _generate_sum_statistics(
|
statistics = _generate_sum_statistics(
|
||||||
yesterday_midnight, yesterday_midnight + datetime.timedelta(days=1), sum_, 1
|
yesterday_midnight, yesterday_midnight + datetime.timedelta(days=1), sum_, 1
|
||||||
)
|
)
|
||||||
async_add_external_statistics(hass, metadata, statistics)
|
async_add_external_statistics(hass, metadata, statistics)
|
||||||
|
|
||||||
|
# Add external gas consumption in ft³, ~180 ft3/day
|
||||||
|
# This should not be possible to pick for the energy dashboard
|
||||||
|
statistic_id = f"{DOMAIN}:gas_consumption_ft3"
|
||||||
|
metadata = {
|
||||||
|
"source": DOMAIN,
|
||||||
|
"name": "Gas consumption 2",
|
||||||
|
"statistic_id": statistic_id,
|
||||||
|
"unit_of_measurement": "ft³",
|
||||||
|
"has_mean": False,
|
||||||
|
"has_sum": True,
|
||||||
|
}
|
||||||
|
sum_ = 0
|
||||||
|
last_stats = await get_instance(hass).async_add_executor_job(
|
||||||
|
get_last_statistics, hass, 1, statistic_id, True
|
||||||
|
)
|
||||||
|
if statistic_id in last_stats:
|
||||||
|
sum_ = last_stats[statistic_id][0]["sum"] or 0
|
||||||
|
statistics = _generate_sum_statistics(
|
||||||
|
yesterday_midnight, yesterday_midnight + datetime.timedelta(days=1), sum_, 30
|
||||||
|
)
|
||||||
|
async_add_external_statistics(hass, metadata, statistics)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||||
"""Set the config entry up."""
|
"""Set the config entry up."""
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
"""Demo platform that has a couple of fake sensors."""
|
"""Demo platform that has a couple of fake sensors."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
|
DOMAIN as SENSOR_DOMAIN,
|
||||||
|
RestoreSensor,
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorStateClass,
|
SensorStateClass,
|
||||||
@ -11,13 +16,17 @@ from homeassistant.const import (
|
|||||||
ATTR_BATTERY_LEVEL,
|
ATTR_BATTERY_LEVEL,
|
||||||
CONCENTRATION_PARTS_PER_MILLION,
|
CONCENTRATION_PARTS_PER_MILLION,
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
|
ENERGY_MEGA_WATT_HOUR,
|
||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
POWER_WATT,
|
POWER_WATT,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
|
VOLUME_CUBIC_FEET,
|
||||||
|
VOLUME_CUBIC_METERS,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
|
||||||
|
|
||||||
from . import DOMAIN
|
from . import DOMAIN
|
||||||
@ -77,14 +86,45 @@ async def async_setup_platform(
|
|||||||
POWER_WATT,
|
POWER_WATT,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
DemoSensor(
|
DemoSumSensor(
|
||||||
"sensor_6",
|
"sensor_6",
|
||||||
"Today energy",
|
"Total energy 1",
|
||||||
15,
|
0.5, # 6kWh / h
|
||||||
SensorDeviceClass.ENERGY,
|
SensorDeviceClass.ENERGY,
|
||||||
SensorStateClass.MEASUREMENT,
|
SensorStateClass.TOTAL,
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
None,
|
None,
|
||||||
|
"total_energy_kwh",
|
||||||
|
),
|
||||||
|
DemoSumSensor(
|
||||||
|
"sensor_7",
|
||||||
|
"Total energy 2",
|
||||||
|
0.00025, # 0.003 MWh/h (3 kWh / h)
|
||||||
|
SensorDeviceClass.ENERGY,
|
||||||
|
SensorStateClass.TOTAL,
|
||||||
|
ENERGY_MEGA_WATT_HOUR,
|
||||||
|
None,
|
||||||
|
"total_energy_mwh",
|
||||||
|
),
|
||||||
|
DemoSumSensor(
|
||||||
|
"sensor_8",
|
||||||
|
"Total gas 1",
|
||||||
|
0.025, # 0.30 m³/h (10.6 ft³ / h)
|
||||||
|
SensorDeviceClass.GAS,
|
||||||
|
SensorStateClass.TOTAL,
|
||||||
|
VOLUME_CUBIC_METERS,
|
||||||
|
None,
|
||||||
|
"total_gas_m3",
|
||||||
|
),
|
||||||
|
DemoSumSensor(
|
||||||
|
"sensor_9",
|
||||||
|
"Total gas 2",
|
||||||
|
1.0, # 12 ft³/h (0.34 m³ / h)
|
||||||
|
SensorDeviceClass.GAS,
|
||||||
|
SensorStateClass.TOTAL,
|
||||||
|
VOLUME_CUBIC_FEET,
|
||||||
|
None,
|
||||||
|
"total_gas_ft3",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -129,3 +169,58 @@ class DemoSensor(SensorEntity):
|
|||||||
|
|
||||||
if battery:
|
if battery:
|
||||||
self._attr_extra_state_attributes = {ATTR_BATTERY_LEVEL: battery}
|
self._attr_extra_state_attributes = {ATTR_BATTERY_LEVEL: battery}
|
||||||
|
|
||||||
|
|
||||||
|
class DemoSumSensor(RestoreSensor):
|
||||||
|
"""Representation of a Demo sensor."""
|
||||||
|
|
||||||
|
_attr_should_poll = False
|
||||||
|
_attr_native_value: float
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
unique_id: str,
|
||||||
|
name: str,
|
||||||
|
five_minute_increase: float,
|
||||||
|
device_class: SensorDeviceClass,
|
||||||
|
state_class: SensorStateClass | None,
|
||||||
|
unit_of_measurement: str | None,
|
||||||
|
battery: StateType,
|
||||||
|
suggested_entity_id: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the sensor."""
|
||||||
|
self.entity_id = f"{SENSOR_DOMAIN}.{suggested_entity_id}"
|
||||||
|
self._attr_device_class = device_class
|
||||||
|
self._attr_name = name
|
||||||
|
self._attr_native_unit_of_measurement = unit_of_measurement
|
||||||
|
self._attr_native_value = 0
|
||||||
|
self._attr_state_class = state_class
|
||||||
|
self._attr_unique_id = unique_id
|
||||||
|
self._five_minute_increase = five_minute_increase
|
||||||
|
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, unique_id)},
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if battery:
|
||||||
|
self._attr_extra_state_attributes = {ATTR_BATTERY_LEVEL: battery}
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_bump_sum(self, now: datetime) -> None:
|
||||||
|
"""Bump the sum."""
|
||||||
|
self._attr_native_value += self._five_minute_increase
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Call when entity about to be added to hass."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
state = await self.async_get_last_sensor_data()
|
||||||
|
if state:
|
||||||
|
self._attr_native_value = cast(float, state.native_value)
|
||||||
|
|
||||||
|
self.async_on_remove(
|
||||||
|
async_track_time_interval(
|
||||||
|
self.hass, self._async_bump_sum, timedelta(minutes=5)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@ -57,7 +57,7 @@ async def test_demo_statistics(hass, recorder_mock):
|
|||||||
assert {
|
assert {
|
||||||
"has_mean": True,
|
"has_mean": True,
|
||||||
"has_sum": False,
|
"has_sum": False,
|
||||||
"name": None,
|
"name": "Outdoor temperature",
|
||||||
"source": "demo",
|
"source": "demo",
|
||||||
"statistic_id": "demo:temperature_outdoor",
|
"statistic_id": "demo:temperature_outdoor",
|
||||||
"unit_of_measurement": "°C",
|
"unit_of_measurement": "°C",
|
||||||
@ -65,9 +65,9 @@ async def test_demo_statistics(hass, recorder_mock):
|
|||||||
assert {
|
assert {
|
||||||
"has_mean": False,
|
"has_mean": False,
|
||||||
"has_sum": True,
|
"has_sum": True,
|
||||||
"name": None,
|
"name": "Energy consumption 1",
|
||||||
"source": "demo",
|
"source": "demo",
|
||||||
"statistic_id": "demo:energy_consumption",
|
"statistic_id": "demo:energy_consumption_kwh",
|
||||||
"unit_of_measurement": "kWh",
|
"unit_of_measurement": "kWh",
|
||||||
} in statistic_ids
|
} in statistic_ids
|
||||||
|
|
||||||
|
@ -767,7 +767,7 @@ def test_compile_hourly_sum_statistics_nan_inf_state(
|
|||||||
"bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue",
|
"bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"sensor.today_energy",
|
"sensor.power_consumption",
|
||||||
"from integration demo ",
|
"from integration demo ",
|
||||||
"bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+demo%22",
|
"bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+demo%22",
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user