From 3a6a1a4d6b2da4f3310e6d9d2727207ee44f6fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hjelseth=20H=C3=B8yer?= Date: Tue, 25 May 2021 22:53:16 +0200 Subject: [PATCH] Tibber, state class (#50951) --- homeassistant/components/tibber/sensor.py | 123 ++++++++++++++++++---- 1 file changed, 105 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/tibber/sensor.py b/homeassistant/components/tibber/sensor.py index 58e27b6b653..70dfa54c70a 100644 --- a/homeassistant/components/tibber/sensor.py +++ b/homeassistant/components/tibber/sensor.py @@ -1,6 +1,6 @@ """Support for Tibber sensors.""" import asyncio -from datetime import timedelta +from datetime import datetime, timedelta import logging from random import randrange @@ -12,6 +12,7 @@ from homeassistant.components.sensor import ( DEVICE_CLASS_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, SensorEntity, ) from homeassistant.const import ( @@ -42,52 +43,89 @@ PARALLEL_UPDATES = 0 SIGNAL_UPDATE_ENTITY = "tibber_rt_update_{}" RT_SENSOR_MAP = { - "averagePower": ["average power", DEVICE_CLASS_POWER, POWER_WATT], - "power": ["power", DEVICE_CLASS_POWER, POWER_WATT], - "minPower": ["min power", DEVICE_CLASS_POWER, POWER_WATT], - "maxPower": ["max power", DEVICE_CLASS_POWER, POWER_WATT], + "averagePower": ["average power", DEVICE_CLASS_POWER, POWER_WATT, None], + "power": ["power", DEVICE_CLASS_POWER, POWER_WATT, None], + "minPower": ["min power", DEVICE_CLASS_POWER, POWER_WATT, None], + "maxPower": ["max power", DEVICE_CLASS_POWER, POWER_WATT, None], "accumulatedConsumption": [ "accumulated consumption", DEVICE_CLASS_ENERGY, ENERGY_KILO_WATT_HOUR, + STATE_CLASS_MEASUREMENT, ], "accumulatedConsumptionLastHour": [ - "accumulated consumption last hour", + "accumulated consumption current hour", DEVICE_CLASS_ENERGY, ENERGY_KILO_WATT_HOUR, + STATE_CLASS_MEASUREMENT, ], "accumulatedProduction": [ "accumulated production", DEVICE_CLASS_ENERGY, ENERGY_KILO_WATT_HOUR, + STATE_CLASS_MEASUREMENT, ], "accumulatedProductionLastHour": [ - "accumulated production last hour", + "accumulated production current hour", DEVICE_CLASS_ENERGY, ENERGY_KILO_WATT_HOUR, + STATE_CLASS_MEASUREMENT, ], "lastMeterConsumption": [ "last meter consumption", DEVICE_CLASS_ENERGY, ENERGY_KILO_WATT_HOUR, + STATE_CLASS_MEASUREMENT, ], "lastMeterProduction": [ "last meter production", DEVICE_CLASS_ENERGY, ENERGY_KILO_WATT_HOUR, + STATE_CLASS_MEASUREMENT, + ], + "voltagePhase1": [ + "voltage phase1", + DEVICE_CLASS_VOLTAGE, + VOLT, + STATE_CLASS_MEASUREMENT, + ], + "voltagePhase2": [ + "voltage phase2", + DEVICE_CLASS_VOLTAGE, + VOLT, + STATE_CLASS_MEASUREMENT, + ], + "voltagePhase3": [ + "voltage phase3", + DEVICE_CLASS_VOLTAGE, + VOLT, + STATE_CLASS_MEASUREMENT, + ], + "currentL1": [ + "current L1", + DEVICE_CLASS_CURRENT, + ELECTRICAL_CURRENT_AMPERE, + STATE_CLASS_MEASUREMENT, + ], + "currentL2": [ + "current L2", + DEVICE_CLASS_CURRENT, + ELECTRICAL_CURRENT_AMPERE, + STATE_CLASS_MEASUREMENT, + ], + "currentL3": [ + "current L3", + DEVICE_CLASS_CURRENT, + ELECTRICAL_CURRENT_AMPERE, + STATE_CLASS_MEASUREMENT, ], - "voltagePhase1": ["voltage phase1", DEVICE_CLASS_VOLTAGE, VOLT], - "voltagePhase2": ["voltage phase2", DEVICE_CLASS_VOLTAGE, VOLT], - "voltagePhase3": ["voltage phase3", DEVICE_CLASS_VOLTAGE, VOLT], - "currentL1": ["current L1", DEVICE_CLASS_CURRENT, ELECTRICAL_CURRENT_AMPERE], - "currentL2": ["current L2", DEVICE_CLASS_CURRENT, ELECTRICAL_CURRENT_AMPERE], - "currentL3": ["current L3", DEVICE_CLASS_CURRENT, ELECTRICAL_CURRENT_AMPERE], "signalStrength": [ "signal strength", DEVICE_CLASS_SIGNAL_STRENGTH, SIGNAL_STRENGTH_DECIBELS, + STATE_CLASS_MEASUREMENT, ], - "accumulatedCost": ["accumulated cost", None, None], + "accumulatedCost": ["accumulated cost", None, None, STATE_CLASS_MEASUREMENT], } @@ -250,7 +288,9 @@ class TibberSensorRT(TibberSensor): _attr_should_poll = False - def __init__(self, tibber_home, sensor_name, device_class, unit, initial_state): + def __init__( + self, tibber_home, sensor_name, device_class, unit, initial_state, state_class + ): """Initialize the sensor.""" super().__init__(tibber_home) self._sensor_name = sensor_name @@ -261,6 +301,29 @@ class TibberSensorRT(TibberSensor): self._attr_state = initial_state self._attr_unique_id = f"{self._tibber_home.home_id}_rt_{self._sensor_name}" self._attr_unit_of_measurement = unit + self._attr_state_class = state_class + if sensor_name in [ + "last meter consumption", + "last meter production", + ]: + self._attr_last_reset = datetime.fromtimestamp(0) + elif self._sensor_name in [ + "accumulated consumption", + "accumulated production", + "accumulated cost", + ]: + self._attr_last_reset = dt_util.as_utc( + dt_util.now().replace(hour=0, minute=0, second=0, microsecond=0) + ) + elif self._sensor_name in [ + "accumulated consumption current hour", + "accumulated production current hour", + ]: + self._attr_last_reset = dt_util.as_utc( + dt_util.now().replace(minute=0, second=0, microsecond=0) + ) + else: + self._attr_last_reset = None async def async_added_to_hass(self): """Start listen for real time data.""" @@ -278,8 +341,23 @@ class TibberSensorRT(TibberSensor): return self._tibber_home.rt_subscription_running @callback - def _set_state(self, state): + def _set_state(self, state, timestamp): """Set sensor state.""" + if state < self._attr_state and self._sensor_name in [ + "accumulated consumption", + "accumulated production", + "accumulated cost", + ]: + self._attr_last_reset = dt_util.as_utc( + timestamp.replace(hour=0, minute=0, second=0, microsecond=0) + ) + if state < self._attr_state and self._sensor_name in [ + "accumulated consumption current hour", + "accumulated production current hour", + ]: + self._attr_last_reset = dt_util.as_utc( + timestamp.replace(minute=0, second=0, microsecond=0) + ) self._attr_state = state self.async_write_ha_state() @@ -307,6 +385,7 @@ class TibberRtDataHandler: if live_measurement is None: return + timestamp = datetime.fromisoformat(live_measurement.pop("timestamp")) new_entities = [] for sensor_type, state in live_measurement.items(): if state is None or sensor_type not in RT_SENSOR_MAP: @@ -316,13 +395,21 @@ class TibberRtDataHandler: self.hass, SIGNAL_UPDATE_ENTITY.format(RT_SENSOR_MAP[sensor_type][0]), state, + timestamp, ) else: - sensor_name, device_class, unit = RT_SENSOR_MAP[sensor_type] + sensor_name, device_class, unit, state_class = RT_SENSOR_MAP[ + sensor_type + ] if sensor_type == "accumulatedCost": unit = self._tibber_home.currency entity = TibberSensorRT( - self._tibber_home, sensor_name, device_class, unit, state + self._tibber_home, + sensor_name, + device_class, + unit, + state, + state_class, ) new_entities.append(entity) self._entities.add(sensor_type)