mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add coordinator to emoncms (#120008)
This commit is contained in:
parent
1a962b415e
commit
cb045a794d
31
homeassistant/components/emoncms/coordinator.py
Normal file
31
homeassistant/components/emoncms/coordinator.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"""DataUpdateCoordinator for the emoncms integration."""
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pyemoncms import EmoncmsClient
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EmoncmsCoordinator(DataUpdateCoordinator[list[dict[str, Any]] | None]):
|
||||||
|
"""Emoncms Data Update Coordinator."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
emoncms_client: EmoncmsClient,
|
||||||
|
scan_interval: timedelta,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the emoncms data coordinator."""
|
||||||
|
super().__init__(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name="emoncms_coordinator",
|
||||||
|
update_method=emoncms_client.async_list_feeds,
|
||||||
|
update_interval=scan_interval,
|
||||||
|
)
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@ -17,18 +18,22 @@ from homeassistant.components.sensor import (
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_API_KEY,
|
CONF_API_KEY,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
|
CONF_SCAN_INTERVAL,
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
CONF_URL,
|
CONF_URL,
|
||||||
CONF_VALUE_TEMPLATE,
|
CONF_VALUE_TEMPLATE,
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
UnitOfPower,
|
UnitOfPower,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import template
|
from homeassistant.helpers import template
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from .coordinator import EmoncmsCoordinator
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -84,19 +89,21 @@ async def async_setup_platform(
|
|||||||
exclude_feeds = config.get(CONF_EXCLUDE_FEEDID)
|
exclude_feeds = config.get(CONF_EXCLUDE_FEEDID)
|
||||||
include_only_feeds = config.get(CONF_ONLY_INCLUDE_FEEDID)
|
include_only_feeds = config.get(CONF_ONLY_INCLUDE_FEEDID)
|
||||||
sensor_names = config.get(CONF_SENSOR_NAMES)
|
sensor_names = config.get(CONF_SENSOR_NAMES)
|
||||||
|
scan_interval = config.get(CONF_SCAN_INTERVAL, timedelta(seconds=30))
|
||||||
|
|
||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
emoncms_client = EmoncmsClient(url, apikey, session=async_get_clientsession(hass))
|
emoncms_client = EmoncmsClient(url, apikey, session=async_get_clientsession(hass))
|
||||||
elems = await emoncms_client.async_list_feeds()
|
coordinator = EmoncmsCoordinator(hass, emoncms_client, scan_interval)
|
||||||
|
await coordinator.async_refresh()
|
||||||
|
elems = coordinator.data
|
||||||
if elems is None:
|
if elems is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
sensors = []
|
sensors: list[EmonCmsSensor] = []
|
||||||
|
|
||||||
for elem in elems:
|
for idx, elem in enumerate(elems):
|
||||||
if exclude_feeds is not None and int(elem["id"]) in exclude_feeds:
|
if exclude_feeds is not None and int(elem["id"]) in exclude_feeds:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -114,48 +121,48 @@ async def async_setup_platform(
|
|||||||
|
|
||||||
sensors.append(
|
sensors.append(
|
||||||
EmonCmsSensor(
|
EmonCmsSensor(
|
||||||
hass,
|
coordinator,
|
||||||
emoncms_client,
|
|
||||||
name,
|
name,
|
||||||
value_template,
|
value_template,
|
||||||
unit_of_measurement,
|
unit_of_measurement,
|
||||||
str(sensorid),
|
str(sensorid),
|
||||||
elem,
|
idx,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
async_add_entities(sensors)
|
async_add_entities(sensors)
|
||||||
|
|
||||||
|
|
||||||
class EmonCmsSensor(SensorEntity):
|
class EmonCmsSensor(CoordinatorEntity[EmoncmsCoordinator], SensorEntity):
|
||||||
"""Implementation of an Emoncms sensor."""
|
"""Implementation of an Emoncms sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
coordinator: EmoncmsCoordinator,
|
||||||
emoncms_client: EmoncmsClient,
|
|
||||||
name: str | None,
|
name: str | None,
|
||||||
value_template: template.Template | None,
|
value_template: template.Template | None,
|
||||||
unit_of_measurement: str | None,
|
unit_of_measurement: str | None,
|
||||||
sensorid: str,
|
sensorid: str,
|
||||||
elem: dict[str, Any],
|
idx: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
self.idx = idx
|
||||||
|
elem = {}
|
||||||
|
if self.coordinator.data:
|
||||||
|
elem = self.coordinator.data[self.idx]
|
||||||
if name is None:
|
if name is None:
|
||||||
# Suppress ID in sensor name if it's 1, since most people won't
|
# Suppress ID in sensor name if it's 1, since most people won't
|
||||||
# have more than one EmonCMS source and it's redundant to show the
|
# have more than one EmonCMS source and it's redundant to show the
|
||||||
# ID if there's only one.
|
# ID if there's only one.
|
||||||
id_for_name = "" if str(sensorid) == "1" else sensorid
|
id_for_name = "" if str(sensorid) == "1" else sensorid
|
||||||
# Use the feed name assigned in EmonCMS or fall back to the feed ID
|
# Use the feed name assigned in EmonCMS or fall back to the feed ID
|
||||||
feed_name = elem.get("name") or f"Feed {elem['id']}"
|
feed_name = elem.get("name", f"Feed {elem.get('id')}")
|
||||||
self._attr_name = f"EmonCMS{id_for_name} {feed_name}"
|
self._attr_name = f"EmonCMS{id_for_name} {feed_name}"
|
||||||
else:
|
else:
|
||||||
self._attr_name = name
|
self._attr_name = name
|
||||||
self._hass = hass
|
|
||||||
self._emoncms_client = emoncms_client
|
|
||||||
self._value_template = value_template
|
self._value_template = value_template
|
||||||
self._attr_native_unit_of_measurement = unit_of_measurement
|
self._attr_native_unit_of_measurement = unit_of_measurement
|
||||||
self._sensorid = sensorid
|
self._sensorid = sensorid
|
||||||
self._feed_id = elem["id"]
|
|
||||||
|
|
||||||
if unit_of_measurement in ("kWh", "Wh"):
|
if unit_of_measurement in ("kWh", "Wh"):
|
||||||
self._attr_device_class = SensorDeviceClass.ENERGY
|
self._attr_device_class = SensorDeviceClass.ENERGY
|
||||||
@ -208,9 +215,10 @@ class EmonCmsSensor(SensorEntity):
|
|||||||
elif elem["value"] is not None:
|
elif elem["value"] is not None:
|
||||||
self._attr_native_value = round(float(elem["value"]), DECIMALS)
|
self._attr_native_value = round(float(elem["value"]), DECIMALS)
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
@callback
|
||||||
"""Get the latest data and updates the state."""
|
def _handle_coordinator_update(self) -> None:
|
||||||
elem = await self._emoncms_client.async_get_feed_fields(self._feed_id)
|
"""Handle updated data from the coordinator."""
|
||||||
if elem is None:
|
data = self.coordinator.data
|
||||||
return
|
if data:
|
||||||
self._update_attributes(elem)
|
self._update_attributes(data[self.idx])
|
||||||
|
super()._handle_coordinator_update()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user