mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Upgrade dsmr_parser to 0.11 (#9576)
This commit is contained in:
parent
a298b0790b
commit
fafc4a6042
@ -1,29 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
Support for Dutch Smart Meter Requirements.
|
Support for Dutch Smart Meter (also known as Smartmeter or P1 port).
|
||||||
|
|
||||||
Also known as: Smartmeter or P1 port.
|
|
||||||
|
|
||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/sensor.dsmr/
|
https://home-assistant.io/components/sensor.dsmr/
|
||||||
|
|
||||||
Technical overview:
|
|
||||||
|
|
||||||
DSMR is a standard to which Dutch smartmeters must comply. It specifies that
|
|
||||||
the smartmeter must send out a 'telegram' every 10 seconds over a serial port.
|
|
||||||
|
|
||||||
The contents of this telegram differ between version but they generally consist
|
|
||||||
of lines with 'obis' (Object Identification System, a numerical ID for a value)
|
|
||||||
followed with the value and unit.
|
|
||||||
|
|
||||||
This module sets up a asynchronous reading loop using the `dsmr_parser` module
|
|
||||||
which waits for a complete telegram, parser it and puts it on an async queue as
|
|
||||||
a dictionary of `obis`/object mapping. The numeric value and unit of each value
|
|
||||||
can be read from the objects attributes. Because the `obis` are know for each
|
|
||||||
DSMR version the Entities for this component are create during bootstrap.
|
|
||||||
|
|
||||||
Another loop (DSMR class) is setup which reads the telegram queue,
|
|
||||||
stores/caches the latest telegram and notifies the Entities that the telegram
|
|
||||||
has been updated.
|
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
@ -40,7 +19,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
REQUIREMENTS = ['dsmr_parser==0.8']
|
REQUIREMENTS = ['dsmr_parser==0.11']
|
||||||
|
|
||||||
CONF_DSMR_VERSION = 'dsmr_version'
|
CONF_DSMR_VERSION = 'dsmr_version'
|
||||||
CONF_RECONNECT_INTERVAL = 'reconnect_interval'
|
CONF_RECONNECT_INTERVAL = 'reconnect_interval'
|
||||||
@ -54,6 +33,7 @@ ICON_POWER = 'mdi:flash'
|
|||||||
|
|
||||||
# Smart meter sends telegram every 10 seconds
|
# Smart meter sends telegram every 10 seconds
|
||||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10)
|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10)
|
||||||
|
|
||||||
RECONNECT_INTERVAL = 5
|
RECONNECT_INTERVAL = 5
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
@ -98,7 +78,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
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 and derivative for usage
|
||||||
devices += [
|
devices += [
|
||||||
DSMREntity('Gas Consumption', gas_obis),
|
DSMREntity('Gas Consumption', gas_obis),
|
||||||
DerivativeDSMREntity('Hourly Gas Consumption', gas_obis),
|
DerivativeDSMREntity('Hourly Gas Consumption', gas_obis),
|
||||||
@ -107,7 +87,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
async_add_devices(devices)
|
async_add_devices(devices)
|
||||||
|
|
||||||
def update_entities_telegram(telegram):
|
def update_entities_telegram(telegram):
|
||||||
"""Update entities with latests telegram & trigger state update."""
|
"""Update entities with latests telegram and trigger state update."""
|
||||||
# Make all device entities aware of new telegram
|
# Make all device entities aware of new telegram
|
||||||
for device in devices:
|
for device in devices:
|
||||||
device.telegram = telegram
|
device.telegram = telegram
|
||||||
@ -127,7 +107,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def connect_and_reconnect():
|
def connect_and_reconnect():
|
||||||
"""Connect to DSMR and keep reconnecting until HA stops."""
|
"""Connect to DSMR and keep reconnecting until Home Assistant stops."""
|
||||||
while hass.state != CoreState.stopping:
|
while hass.state != CoreState.stopping:
|
||||||
# Start DSMR asyncio.Protocol reader
|
# Start DSMR asyncio.Protocol reader
|
||||||
try:
|
try:
|
||||||
@ -135,26 +115,26 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
reader_factory())
|
reader_factory())
|
||||||
except (serial.serialutil.SerialException, ConnectionRefusedError,
|
except (serial.serialutil.SerialException, ConnectionRefusedError,
|
||||||
TimeoutError):
|
TimeoutError):
|
||||||
# log any error while establishing connection and drop to retry
|
# Log any error while establishing connection and drop to retry
|
||||||
# connection wait
|
# connection wait
|
||||||
_LOGGER.exception("Error connecting to DSMR")
|
_LOGGER.exception("Error connecting to DSMR")
|
||||||
transport = None
|
transport = None
|
||||||
|
|
||||||
if transport:
|
if transport:
|
||||||
# register listener to close transport on HA shutdown
|
# Register listener to close transport on HA shutdown
|
||||||
stop_listerer = hass.bus.async_listen_once(
|
stop_listerer = hass.bus.async_listen_once(
|
||||||
EVENT_HOMEASSISTANT_STOP, transport.close)
|
EVENT_HOMEASSISTANT_STOP, transport.close)
|
||||||
|
|
||||||
# wait for reader to close
|
# Wait for reader to close
|
||||||
yield from protocol.wait_closed()
|
yield from protocol.wait_closed()
|
||||||
|
|
||||||
if hass.state != CoreState.stopping:
|
if hass.state != CoreState.stopping:
|
||||||
# unexpected disconnect
|
# Unexpected disconnect
|
||||||
if transport:
|
if transport:
|
||||||
# remove listerer
|
# remove listerer
|
||||||
stop_listerer()
|
stop_listerer()
|
||||||
|
|
||||||
# reflect disconnect state in devices state by setting an
|
# Reflect disconnect state in devices state by setting an
|
||||||
# empty telegram resulting in `unknown` states
|
# empty telegram resulting in `unknown` states
|
||||||
update_entities_telegram({})
|
update_entities_telegram({})
|
||||||
|
|
||||||
@ -162,7 +142,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
yield from asyncio.sleep(config[CONF_RECONNECT_INTERVAL],
|
yield from asyncio.sleep(config[CONF_RECONNECT_INTERVAL],
|
||||||
loop=hass.loop)
|
loop=hass.loop)
|
||||||
|
|
||||||
# Cannot be hass.async_add_job because job runs forever
|
# Can't be hass.async_add_job because job runs forever
|
||||||
hass.loop.create_task(connect_and_reconnect())
|
hass.loop.create_task(connect_and_reconnect())
|
||||||
|
|
||||||
|
|
||||||
@ -181,7 +161,7 @@ class DSMREntity(Entity):
|
|||||||
if self._obis not in self.telegram:
|
if self._obis not in self.telegram:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# get the attribute value if the object has it
|
# Get the attribute value if the object has it
|
||||||
dsmr_object = self.telegram[self._obis]
|
dsmr_object = self.telegram[self._obis]
|
||||||
return getattr(dsmr_object, attribute, None)
|
return getattr(dsmr_object, attribute, None)
|
||||||
|
|
||||||
@ -237,7 +217,6 @@ class DerivativeDSMREntity(DSMREntity):
|
|||||||
Gas readings are only reported per hour and don't offer a rate only
|
Gas readings are only reported per hour and don't offer a rate only
|
||||||
the current meter reading. This entity converts subsequents readings
|
the current meter reading. This entity converts subsequents readings
|
||||||
into a hourly rate.
|
into a hourly rate.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_previous_reading = None
|
_previous_reading = None
|
||||||
@ -265,11 +244,11 @@ class DerivativeDSMREntity(DSMREntity):
|
|||||||
current_reading = self.get_dsmr_object_attr('value')
|
current_reading = self.get_dsmr_object_attr('value')
|
||||||
|
|
||||||
if self._previous_reading is None:
|
if self._previous_reading is None:
|
||||||
# can't calculate rate without previous datapoint
|
# Can't calculate rate without previous datapoint
|
||||||
# just store current point
|
# just store current point
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# recalculate the rate
|
# Recalculate the rate
|
||||||
diff = current_reading - self._previous_reading
|
diff = current_reading - self._previous_reading
|
||||||
self._state = diff
|
self._state = diff
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ dnspython3==1.15.0
|
|||||||
dovado==0.4.1
|
dovado==0.4.1
|
||||||
|
|
||||||
# homeassistant.components.sensor.dsmr
|
# homeassistant.components.sensor.dsmr
|
||||||
dsmr_parser==0.8
|
dsmr_parser==0.11
|
||||||
|
|
||||||
# homeassistant.components.dweet
|
# homeassistant.components.dweet
|
||||||
# homeassistant.components.sensor.dweet
|
# homeassistant.components.sensor.dweet
|
||||||
|
@ -37,7 +37,7 @@ aiohttp_cors==0.5.3
|
|||||||
apns2==0.1.1
|
apns2==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.sensor.dsmr
|
# homeassistant.components.sensor.dsmr
|
||||||
dsmr_parser==0.8
|
dsmr_parser==0.11
|
||||||
|
|
||||||
# homeassistant.components.sensor.season
|
# homeassistant.components.sensor.season
|
||||||
ephem==3.7.6.0
|
ephem==3.7.6.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user