mirror of
https://github.com/home-assistant/core.git
synced 2025-07-12 15:57:06 +00:00
Support multiple EDL21 meters (#33594)
* edl21: Add 'name' option * edl21: Include domain and electricity ID in unique ID As a side-effect, this makes electricity IDs mandatory, i.e. devices which don't transmit their ID won't register any sensors. * edl21: Implement upgrade path for unique IDs * Update homeassistant/components/edl21/sensor.py Drop DOMAIN from unique ID. Co-Authored-By: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
e4e89becc6
commit
73fb57fd32
@ -8,6 +8,7 @@ from sml.asyncio import SmlProtocol
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import (
|
from homeassistant.helpers.dispatcher import (
|
||||||
@ -15,6 +16,7 @@ from homeassistant.helpers.dispatcher import (
|
|||||||
async_dispatcher_send,
|
async_dispatcher_send,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers.entity_registry import async_get_registry
|
||||||
from homeassistant.helpers.typing import Optional
|
from homeassistant.helpers.typing import Optional
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
@ -26,7 +28,12 @@ ICON_POWER = "mdi:flash"
|
|||||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
|
||||||
SIGNAL_EDL21_TELEGRAM = "edl21_telegram"
|
SIGNAL_EDL21_TELEGRAM = "edl21_telegram"
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Required(CONF_SERIAL_PORT): cv.string})
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_SERIAL_PORT): cv.string,
|
||||||
|
vol.Optional(CONF_NAME, default=""): cv.string,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
@ -74,6 +81,7 @@ class EDL21:
|
|||||||
self._registered_obis = set()
|
self._registered_obis = set()
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._async_add_entities = async_add_entities
|
self._async_add_entities = async_add_entities
|
||||||
|
self._name = config[CONF_NAME]
|
||||||
self._proto = SmlProtocol(config[CONF_SERIAL_PORT])
|
self._proto = SmlProtocol(config[CONF_SERIAL_PORT])
|
||||||
self._proto.add_listener(self.event, ["SmlGetListResponse"])
|
self._proto.add_listener(self.event, ["SmlGetListResponse"])
|
||||||
|
|
||||||
@ -85,19 +93,35 @@ class EDL21:
|
|||||||
"""Handle events from pysml."""
|
"""Handle events from pysml."""
|
||||||
assert isinstance(message_body, SmlGetListResponse)
|
assert isinstance(message_body, SmlGetListResponse)
|
||||||
|
|
||||||
|
electricity_id = None
|
||||||
|
for telegram in message_body.get("valList", []):
|
||||||
|
if telegram.get("objName") == "1-0:0.0.9*255":
|
||||||
|
electricity_id = telegram.get("value")
|
||||||
|
break
|
||||||
|
|
||||||
|
if electricity_id is None:
|
||||||
|
return
|
||||||
|
electricity_id = electricity_id.replace(" ", "")
|
||||||
|
|
||||||
new_entities = []
|
new_entities = []
|
||||||
for telegram in message_body.get("valList", []):
|
for telegram in message_body.get("valList", []):
|
||||||
obis = telegram.get("objName")
|
obis = telegram.get("objName")
|
||||||
if not obis:
|
if not obis:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if obis in self._registered_obis:
|
if (electricity_id, obis) in self._registered_obis:
|
||||||
async_dispatcher_send(self._hass, SIGNAL_EDL21_TELEGRAM, telegram)
|
async_dispatcher_send(
|
||||||
|
self._hass, SIGNAL_EDL21_TELEGRAM, electricity_id, telegram
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
name = self._OBIS_NAMES.get(obis)
|
name = self._OBIS_NAMES.get(obis)
|
||||||
if name:
|
if name:
|
||||||
new_entities.append(EDL21Entity(obis, name, telegram))
|
if self._name:
|
||||||
self._registered_obis.add(obis)
|
name = f"{self._name}: {name}"
|
||||||
|
new_entities.append(
|
||||||
|
EDL21Entity(electricity_id, obis, name, telegram)
|
||||||
|
)
|
||||||
|
self._registered_obis.add((electricity_id, obis))
|
||||||
elif obis not in self._OBIS_BLACKLIST:
|
elif obis not in self._OBIS_BLACKLIST:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Unhandled sensor %s detected. Please report at "
|
"Unhandled sensor %s detected. Please report at "
|
||||||
@ -107,16 +131,41 @@ class EDL21:
|
|||||||
self._OBIS_BLACKLIST.add(obis)
|
self._OBIS_BLACKLIST.add(obis)
|
||||||
|
|
||||||
if new_entities:
|
if new_entities:
|
||||||
|
self._hass.loop.create_task(self.add_entities(new_entities))
|
||||||
|
|
||||||
|
async def add_entities(self, new_entities) -> None:
|
||||||
|
"""Migrate old unique IDs, then add entities to hass."""
|
||||||
|
registry = await async_get_registry(self._hass)
|
||||||
|
|
||||||
|
for entity in new_entities:
|
||||||
|
old_entity_id = registry.async_get_entity_id(
|
||||||
|
"sensor", DOMAIN, entity.old_unique_id
|
||||||
|
)
|
||||||
|
if old_entity_id is not None:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Migrating unique_id from [%s] to [%s]",
|
||||||
|
entity.old_unique_id,
|
||||||
|
entity.unique_id,
|
||||||
|
)
|
||||||
|
if registry.async_get_entity_id("sensor", DOMAIN, entity.unique_id):
|
||||||
|
registry.async_remove(old_entity_id)
|
||||||
|
else:
|
||||||
|
registry.async_update_entity(
|
||||||
|
old_entity_id, new_unique_id=entity.unique_id
|
||||||
|
)
|
||||||
|
|
||||||
self._async_add_entities(new_entities, update_before_add=True)
|
self._async_add_entities(new_entities, update_before_add=True)
|
||||||
|
|
||||||
|
|
||||||
class EDL21Entity(Entity):
|
class EDL21Entity(Entity):
|
||||||
"""Entity reading values from EDL21 telegram."""
|
"""Entity reading values from EDL21 telegram."""
|
||||||
|
|
||||||
def __init__(self, obis, name, telegram):
|
def __init__(self, electricity_id, obis, name, telegram):
|
||||||
"""Initialize an EDL21Entity."""
|
"""Initialize an EDL21Entity."""
|
||||||
|
self._electricity_id = electricity_id
|
||||||
self._obis = obis
|
self._obis = obis
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._unique_id = f"{electricity_id}_{obis}"
|
||||||
self._telegram = telegram
|
self._telegram = telegram
|
||||||
self._min_time = MIN_TIME_BETWEEN_UPDATES
|
self._min_time = MIN_TIME_BETWEEN_UPDATES
|
||||||
self._last_update = utcnow()
|
self._last_update = utcnow()
|
||||||
@ -132,8 +181,10 @@ class EDL21Entity(Entity):
|
|||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_telegram(telegram):
|
def handle_telegram(electricity_id, telegram):
|
||||||
"""Update attributes from last received telegram for this object."""
|
"""Update attributes from last received telegram for this object."""
|
||||||
|
if self._electricity_id != electricity_id:
|
||||||
|
return
|
||||||
if self._obis != telegram.get("objName"):
|
if self._obis != telegram.get("objName"):
|
||||||
return
|
return
|
||||||
if self._telegram == telegram:
|
if self._telegram == telegram:
|
||||||
@ -164,6 +215,11 @@ class EDL21Entity(Entity):
|
|||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
"""Return a unique ID."""
|
"""Return a unique ID."""
|
||||||
|
return self._unique_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def old_unique_id(self) -> str:
|
||||||
|
"""Return a less unique ID as used in the first version of edl21."""
|
||||||
return self._obis
|
return self._obis
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
Loading…
x
Reference in New Issue
Block a user