Add last_reset property to Tasmota energy sensors (#51107)

* Add last_reset property to Tasmota energy sensors

* Correct device class for energy sensors
This commit is contained in:
Erik Montnemery 2021-05-26 17:58:06 +02:00 committed by GitHub
parent 19c505c0f0
commit 16e90f12ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 6 deletions

View File

@ -3,7 +3,7 @@
"name": "Tasmota",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/tasmota",
"requirements": ["hatasmota==0.2.13"],
"requirements": ["hatasmota==0.2.14"],
"dependencies": ["mqtt"],
"mqtt": ["tasmota/discovery/#"],
"codeowners": ["@emontnemery"],

View File

@ -1,6 +1,8 @@
"""Support for Tasmota sensors."""
from __future__ import annotations
import logging
from hatasmota import const as hc, status_sensor
from homeassistant.components import sensor
@ -11,6 +13,7 @@ from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CO2,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_ILLUMINANCE,
DEVICE_CLASS_POWER,
@ -40,11 +43,14 @@ from homeassistant.const import (
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.util import dt as dt_util
from .const import DATA_REMOVE_DISCOVER_COMPONENT
from .discovery import TASMOTA_DISCOVERY_ENTITY_NEW
from .mixins import TasmotaAvailability, TasmotaDiscoveryUpdate
_LOGGER = logging.getLogger(__name__)
DEVICE_CLASS = "device_class"
STATE_CLASS = "state_class"
ICON = "icon"
@ -106,13 +112,16 @@ SENSOR_DEVICE_CLASS_ICON_MAP = {
DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
STATE_CLASS: STATE_CLASS_MEASUREMENT,
},
hc.SENSOR_TODAY: {DEVICE_CLASS: DEVICE_CLASS_POWER},
hc.SENSOR_TOTAL: {DEVICE_CLASS: DEVICE_CLASS_POWER},
hc.SENSOR_TODAY: {DEVICE_CLASS: DEVICE_CLASS_ENERGY},
hc.SENSOR_TOTAL: {
DEVICE_CLASS: DEVICE_CLASS_ENERGY,
STATE_CLASS: STATE_CLASS_MEASUREMENT,
},
hc.SENSOR_TOTAL_START_TIME: {ICON: "mdi:progress-clock"},
hc.SENSOR_TVOC: {ICON: "mdi:air-filter"},
hc.SENSOR_VOLTAGE: {ICON: "mdi:alpha-v-circle-outline"},
hc.SENSOR_WEIGHT: {ICON: "mdi:scale"},
hc.SENSOR_YESTERDAY: {DEVICE_CLASS: DEVICE_CLASS_POWER},
hc.SENSOR_YESTERDAY: {DEVICE_CLASS: DEVICE_CLASS_ENERGY},
}
SENSOR_UNIT_MAP = {
@ -166,6 +175,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class TasmotaSensor(TasmotaAvailability, TasmotaDiscoveryUpdate, SensorEntity):
"""Representation of a Tasmota sensor."""
_attr_last_reset = None
def __init__(self, **kwds):
"""Initialize the Tasmota sensor."""
self._state = None
@ -178,6 +189,18 @@ class TasmotaSensor(TasmotaAvailability, TasmotaDiscoveryUpdate, SensorEntity):
def state_updated(self, state, **kwargs):
"""Handle state updates."""
self._state = state
if "last_reset" in kwargs:
try:
last_reset = dt_util.as_utc(
dt_util.parse_datetime(kwargs["last_reset"])
)
if last_reset is None:
raise ValueError
self._attr_last_reset = last_reset
except ValueError:
_LOGGER.warning(
"Invalid last_reset timestamp '%s'", kwargs["last_reset"]
)
self.async_write_ha_state()
@property

View File

@ -738,7 +738,7 @@ hass-nabucasa==0.43.0
hass_splunk==0.1.1
# homeassistant.components.tasmota
hatasmota==0.2.13
hatasmota==0.2.14
# homeassistant.components.jewish_calendar
hdate==0.10.2

View File

@ -411,7 +411,7 @@ hangups==0.4.11
hass-nabucasa==0.43.0
# homeassistant.components.tasmota
hatasmota==0.2.13
hatasmota==0.2.14
# homeassistant.components.jewish_calendar
hdate==0.10.2

View File

@ -233,6 +233,55 @@ async def test_indexed_sensor_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
assert state.state == "7.8"
async def test_indexed_sensor_state_via_mqtt2(hass, mqtt_mock, setup_tasmota):
"""Test state update via MQTT for sensor with last_reset property."""
config = copy.deepcopy(DEFAULT_CONFIG)
sensor_config = copy.deepcopy(INDEXED_SENSOR_CONFIG)
mac = config["mac"]
async_fire_mqtt_message(
hass,
f"{DEFAULT_PREFIX}/{mac}/config",
json.dumps(config),
)
await hass.async_block_till_done()
async_fire_mqtt_message(
hass,
f"{DEFAULT_PREFIX}/{mac}/sensors",
json.dumps(sensor_config),
)
await hass.async_block_till_done()
state = hass.states.get("sensor.tasmota_energy_total")
assert state.state == "unavailable"
assert not state.attributes.get(ATTR_ASSUMED_STATE)
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/LWT", "Online")
state = hass.states.get("sensor.tasmota_energy_total")
assert state.state == STATE_UNKNOWN
assert not state.attributes.get(ATTR_ASSUMED_STATE)
# Test periodic state update
async_fire_mqtt_message(
hass,
"tasmota_49A3BC/tele/SENSOR",
'{"ENERGY":{"Total":1.2,"TotalStartTime":"2018-11-23T15:33:47"}}',
)
state = hass.states.get("sensor.tasmota_energy_total")
assert state.state == "1.2"
assert state.attributes["last_reset"] == "2018-11-23T15:33:47+00:00"
# Test polled state update
async_fire_mqtt_message(
hass,
"tasmota_49A3BC/stat/STATUS10",
'{"StatusSNS":{"ENERGY":{"Total":5.6,"TotalStartTime":"2018-11-23T16:33:47"}}}',
)
state = hass.states.get("sensor.tasmota_energy_total")
assert state.state == "5.6"
assert state.attributes["last_reset"] == "2018-11-23T16:33:47+00:00"
async def test_bad_indexed_sensor_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
"""Test state update via MQTT where sensor is not matching configuration."""
config = copy.deepcopy(DEFAULT_CONFIG)