mirror of
https://github.com/home-assistant/core.git
synced 2025-07-11 23:37:18 +00:00
Add sensors for energy trends for devices (#129439)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
ec19712388
commit
3adc3d7732
@ -79,10 +79,16 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
sense_monitor_id = data.sense_monitor_id
|
sense_monitor_id = data.sense_monitor_id
|
||||||
|
|
||||||
entities: list[SensorEntity] = [
|
entities: list[SensorEntity] = []
|
||||||
SenseDevicePowerSensor(device, sense_monitor_id, realtime_coordinator)
|
|
||||||
for device in config_entry.runtime_data.data.devices
|
for device in config_entry.runtime_data.data.devices:
|
||||||
]
|
entities.append(
|
||||||
|
SenseDevicePowerSensor(device, sense_monitor_id, realtime_coordinator)
|
||||||
|
)
|
||||||
|
entities.extend(
|
||||||
|
SenseDeviceEnergySensor(device, scale, trends_coordinator, sense_monitor_id)
|
||||||
|
for scale in Scale
|
||||||
|
)
|
||||||
|
|
||||||
for variant_id, variant_name in SENSOR_VARIANTS:
|
for variant_id, variant_name in SENSOR_VARIANTS:
|
||||||
entities.append(
|
entities.append(
|
||||||
@ -242,3 +248,35 @@ class SenseDevicePowerSensor(SenseDeviceEntity, SensorEntity):
|
|||||||
def native_value(self) -> float:
|
def native_value(self) -> float:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
return self._device.power_w
|
return self._device.power_w
|
||||||
|
|
||||||
|
|
||||||
|
class SenseDeviceEnergySensor(SenseDeviceEntity, SensorEntity):
|
||||||
|
"""Implementation of a Sense device energy sensor."""
|
||||||
|
|
||||||
|
_attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
|
||||||
|
_attr_state_class = SensorStateClass.TOTAL_INCREASING
|
||||||
|
_attr_device_class = SensorDeviceClass.ENERGY
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: SenseDevice,
|
||||||
|
scale: Scale,
|
||||||
|
coordinator: SenseTrendCoordinator,
|
||||||
|
sense_monitor_id: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the Sense device sensor."""
|
||||||
|
super().__init__(
|
||||||
|
device,
|
||||||
|
coordinator,
|
||||||
|
sense_monitor_id,
|
||||||
|
f"{device.id}-{TRENDS_SENSOR_TYPES[scale].lower()}-energy",
|
||||||
|
)
|
||||||
|
self._attr_translation_key = f"{TRENDS_SENSOR_TYPES[scale].lower()}_energy"
|
||||||
|
self._attr_suggested_display_precision = 2
|
||||||
|
self._scale = scale
|
||||||
|
self._device = device
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self) -> float:
|
||||||
|
"""Return the state of the sensor."""
|
||||||
|
return self._device.energy_kwh[self._scale]
|
||||||
|
@ -32,5 +32,24 @@
|
|||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"entity": {
|
||||||
|
"sensor": {
|
||||||
|
"daily_energy": {
|
||||||
|
"name": "Daily energy"
|
||||||
|
},
|
||||||
|
"weekly_energy": {
|
||||||
|
"name": "Weekly energy"
|
||||||
|
},
|
||||||
|
"monthly_energy": {
|
||||||
|
"name": "Monthly energy"
|
||||||
|
},
|
||||||
|
"yearly_energy": {
|
||||||
|
"name": "Yearly energy"
|
||||||
|
},
|
||||||
|
"bill_energy": {
|
||||||
|
"name": "Bill energy"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,11 +3,12 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import MagicMock, PropertyMock
|
from unittest.mock import MagicMock, PropertyMock
|
||||||
|
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from sense_energy import Scale
|
from sense_energy import Scale
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.sense.const import ACTIVE_UPDATE_RATE
|
from homeassistant.components.sense.const import ACTIVE_UPDATE_RATE, TREND_UPDATE_RATE
|
||||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -15,7 +16,14 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
from . import setup_platform
|
from . import setup_platform
|
||||||
from .const import DEVICE_1_NAME, DEVICE_2_NAME, DEVICE_2_POWER, MONITOR_ID
|
from .const import (
|
||||||
|
DEVICE_1_DAY_ENERGY,
|
||||||
|
DEVICE_1_NAME,
|
||||||
|
DEVICE_2_DAY_ENERGY,
|
||||||
|
DEVICE_2_NAME,
|
||||||
|
DEVICE_2_POWER,
|
||||||
|
MONITOR_ID,
|
||||||
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
|
|
||||||
@ -63,6 +71,47 @@ async def test_device_power_sensors(
|
|||||||
assert state.state == f"{DEVICE_2_POWER:.1f}"
|
assert state.state == f"{DEVICE_2_POWER:.1f}"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_device_energy_sensors(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_sense: MagicMock,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""Test the Sense device power sensors."""
|
||||||
|
await setup_platform(hass, config_entry, SENSOR_DOMAIN)
|
||||||
|
device_1, device_2 = mock_sense.devices
|
||||||
|
|
||||||
|
state = hass.states.get(f"sensor.{DEVICE_1_NAME.lower()}_daily_energy")
|
||||||
|
assert state.state == f"{DEVICE_1_DAY_ENERGY:.0f}"
|
||||||
|
|
||||||
|
state = hass.states.get(f"sensor.{DEVICE_2_NAME.lower()}_daily_energy")
|
||||||
|
assert state.state == f"{DEVICE_2_DAY_ENERGY:.0f}"
|
||||||
|
|
||||||
|
device_1.energy_kwh[Scale.DAY] = 0
|
||||||
|
device_2.energy_kwh[Scale.DAY] = 0
|
||||||
|
freezer.tick(timedelta(seconds=TREND_UPDATE_RATE))
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(f"sensor.{DEVICE_1_NAME.lower()}_daily_energy")
|
||||||
|
assert state.state == "0"
|
||||||
|
|
||||||
|
state = hass.states.get(f"sensor.{DEVICE_2_NAME.lower()}_daily_energy")
|
||||||
|
assert state.state == "0"
|
||||||
|
|
||||||
|
device_2.energy_kwh[Scale.DAY] = DEVICE_1_DAY_ENERGY
|
||||||
|
freezer.tick(timedelta(seconds=TREND_UPDATE_RATE))
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(f"sensor.{DEVICE_1_NAME.lower()}_daily_energy")
|
||||||
|
assert state.state == "0"
|
||||||
|
|
||||||
|
state = hass.states.get(f"sensor.{DEVICE_2_NAME.lower()}_daily_energy")
|
||||||
|
assert state.state == f"{DEVICE_1_DAY_ENERGY:.0f}"
|
||||||
|
|
||||||
|
|
||||||
async def test_voltage_sensors(
|
async def test_voltage_sensors(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user