DSMR: Remove Gas derivative sensor (#52147)
This commit is contained in:
parent
0e5040d917
commit
afa00b7626
2 changed files with 4 additions and 125 deletions
|
@ -15,12 +15,7 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP
|
||||||
CONF_HOST,
|
|
||||||
CONF_PORT,
|
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
|
||||||
TIME_HOURS,
|
|
||||||
)
|
|
||||||
from homeassistant.core import CoreState, HomeAssistant, callback
|
from homeassistant.core import CoreState, HomeAssistant, callback
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
@ -172,7 +167,7 @@ async def async_setup_entry(
|
||||||
else:
|
else:
|
||||||
gas_obis = obis_ref.GAS_METER_READING
|
gas_obis = obis_ref.GAS_METER_READING
|
||||||
|
|
||||||
# Add gas meter reading and derivative for usage
|
# Add gas meter reading
|
||||||
devices += [
|
devices += [
|
||||||
DSMREntity(
|
DSMREntity(
|
||||||
"Gas Consumption",
|
"Gas Consumption",
|
||||||
|
@ -181,15 +176,7 @@ async def async_setup_entry(
|
||||||
gas_obis,
|
gas_obis,
|
||||||
config,
|
config,
|
||||||
True,
|
True,
|
||||||
),
|
)
|
||||||
DerivativeDSMREntity(
|
|
||||||
"Hourly Gas Consumption",
|
|
||||||
DEVICE_NAME_GAS,
|
|
||||||
config[CONF_SERIAL_ID_GAS],
|
|
||||||
gas_obis,
|
|
||||||
config,
|
|
||||||
False,
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(devices)
|
async_add_entities(devices)
|
||||||
|
@ -374,66 +361,3 @@ class DSMREntity(SensorEntity):
|
||||||
return "low"
|
return "low"
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class DerivativeDSMREntity(DSMREntity):
|
|
||||||
"""Calculated derivative for values where the DSMR doesn't offer one.
|
|
||||||
|
|
||||||
Gas readings are only reported per hour and don't offer a rate only
|
|
||||||
the current meter reading. This entity converts subsequents readings
|
|
||||||
into a hourly rate.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_previous_reading = None
|
|
||||||
_previous_timestamp = None
|
|
||||||
_state = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state(self):
|
|
||||||
"""Return the calculated current hourly rate."""
|
|
||||||
return self._state
|
|
||||||
|
|
||||||
@property
|
|
||||||
def force_update(self):
|
|
||||||
"""Disable force update."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""Enable polling."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
async def async_update(self):
|
|
||||||
"""Recalculate hourly rate if timestamp has changed.
|
|
||||||
|
|
||||||
DSMR updates gas meter reading every hour. Along with the new
|
|
||||||
value a timestamp is provided for the reading. Test if the last
|
|
||||||
known timestamp differs from the current one then calculate a
|
|
||||||
new rate for the previous hour.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# check if the timestamp for the object differs from the previous one
|
|
||||||
timestamp = self.get_dsmr_object_attr("datetime")
|
|
||||||
if timestamp and timestamp != self._previous_timestamp:
|
|
||||||
current_reading = self.get_dsmr_object_attr("value")
|
|
||||||
|
|
||||||
if self._previous_reading is None:
|
|
||||||
# Can't calculate rate without previous datapoint
|
|
||||||
# just store current point
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# Recalculate the rate
|
|
||||||
diff = current_reading - self._previous_reading
|
|
||||||
timediff = timestamp - self._previous_timestamp
|
|
||||||
total_seconds = timediff.total_seconds()
|
|
||||||
self._state = round(float(diff) / total_seconds * 3600, 3)
|
|
||||||
|
|
||||||
self._previous_reading = current_reading
|
|
||||||
self._previous_timestamp = timestamp
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unit_of_measurement(self):
|
|
||||||
"""Return the unit of measurement of this entity, per hour, if any."""
|
|
||||||
unit = self.get_dsmr_object_attr("unit")
|
|
||||||
if unit:
|
|
||||||
return f"{unit}/{TIME_HOURS}"
|
|
||||||
|
|
|
@ -13,13 +13,8 @@ from unittest.mock import DEFAULT, MagicMock
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.dsmr.const import DOMAIN
|
from homeassistant.components.dsmr.const import DOMAIN
|
||||||
from homeassistant.components.dsmr.sensor import DerivativeDSMREntity
|
|
||||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import ENERGY_KILO_WATT_HOUR, VOLUME_CUBIC_METERS
|
||||||
ENERGY_KILO_WATT_HOUR,
|
|
||||||
VOLUME_CUBIC_METERS,
|
|
||||||
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
@ -179,46 +174,6 @@ async def test_setup_only_energy(hass, dsmr_connection_fixture):
|
||||||
assert not entry
|
assert not entry
|
||||||
|
|
||||||
|
|
||||||
async def test_derivative():
|
|
||||||
"""Test calculation of derivative value."""
|
|
||||||
from dsmr_parser.objects import MBusObject
|
|
||||||
|
|
||||||
config = {"platform": "dsmr"}
|
|
||||||
|
|
||||||
entity = DerivativeDSMREntity("test", "test_device", "5678", "1.0.0", config, False)
|
|
||||||
await entity.async_update()
|
|
||||||
|
|
||||||
assert entity.state is None, "initial state not unknown"
|
|
||||||
|
|
||||||
entity.telegram = {
|
|
||||||
"1.0.0": MBusObject(
|
|
||||||
[
|
|
||||||
{"value": datetime.datetime.fromtimestamp(1551642213)},
|
|
||||||
{"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
await entity.async_update()
|
|
||||||
|
|
||||||
assert entity.state is None, "state after first update should still be unknown"
|
|
||||||
|
|
||||||
entity.telegram = {
|
|
||||||
"1.0.0": MBusObject(
|
|
||||||
[
|
|
||||||
{"value": datetime.datetime.fromtimestamp(1551642543)},
|
|
||||||
{"value": Decimal(745.698), "unit": VOLUME_CUBIC_METERS},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
await entity.async_update()
|
|
||||||
|
|
||||||
assert (
|
|
||||||
abs(entity.state - 0.033) < 0.00001
|
|
||||||
), "state should be hourly usage calculated from first and second update"
|
|
||||||
|
|
||||||
assert entity.unit_of_measurement == VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR
|
|
||||||
|
|
||||||
|
|
||||||
async def test_v4_meter(hass, dsmr_connection_fixture):
|
async def test_v4_meter(hass, dsmr_connection_fixture):
|
||||||
"""Test if v4 meter is correctly parsed."""
|
"""Test if v4 meter is correctly parsed."""
|
||||||
(connection_factory, transport, protocol) = dsmr_connection_fixture
|
(connection_factory, transport, protocol) = dsmr_connection_fixture
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue