Migrate Emoncms to external library (#119772)

* Migrate Emoncms to external library

https://github.com/Open-Building-Management/pyemoncms

* Remove the throttle decorator

* Remove MIN_TIME_BETWEEN_UPDATES as not used
This commit is contained in:
Alexandre CUER 2024-06-17 13:59:47 +02:00 committed by GitHub
parent dcca749d50
commit 442554c223
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 85 deletions

View File

@ -3,5 +3,6 @@
"name": "Emoncms", "name": "Emoncms",
"codeowners": ["@borpin", "@alexandrecuer"], "codeowners": ["@borpin", "@alexandrecuer"],
"documentation": "https://www.home-assistant.io/integrations/emoncms", "documentation": "https://www.home-assistant.io/integrations/emoncms",
"iot_class": "local_polling" "iot_class": "local_polling",
"requirements": ["pyemoncms==0.0.6"]
} }

View File

@ -2,12 +2,10 @@
from __future__ import annotations from __future__ import annotations
from datetime import timedelta
from http import HTTPStatus
import logging import logging
from typing import Any from typing import Any
import requests from pyemoncms import EmoncmsClient
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
@ -30,7 +28,6 @@ from homeassistant.helpers import template
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.util import Throttle
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -48,7 +45,6 @@ CONF_SENSOR_NAMES = "sensor_names"
DECIMALS = 2 DECIMALS = 2
DEFAULT_UNIT = UnitOfPower.WATT DEFAULT_UNIT = UnitOfPower.WATT
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5)
ONLY_INCL_EXCL_NONE = "only_include_exclude_or_none" ONLY_INCL_EXCL_NONE = "only_include_exclude_or_none"
@ -72,17 +68,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
) )
def get_id( async def async_setup_platform(
sensorid: str, feedtag: str, feedname: str, feedid: str, feeduserid: str
) -> str:
"""Return unique identifier for feed / sensor."""
return f"emoncms{sensorid}_{feedtag}_{feedname}_{feedid}_{feeduserid}"
def setup_platform(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType, config: ConfigType,
add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None, discovery_info: DiscoveryInfoType | None = None,
) -> None: ) -> None:
"""Set up the Emoncms sensor.""" """Set up the Emoncms sensor."""
@ -98,16 +87,15 @@ def setup_platform(
if value_template is not None: if value_template is not None:
value_template.hass = hass value_template.hass = hass
data = EmonCmsData(hass, url, apikey) emoncms_client = EmoncmsClient(url, apikey)
elems = await emoncms_client.async_list_feeds()
data.update() if elems is None:
if data.data is None:
return return
sensors = [] sensors = []
for elem in data.data: for elem in 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
@ -126,7 +114,7 @@ def setup_platform(
sensors.append( sensors.append(
EmonCmsSensor( EmonCmsSensor(
hass, hass,
data, emoncms_client,
name, name,
value_template, value_template,
unit_of_measurement, unit_of_measurement,
@ -134,7 +122,7 @@ def setup_platform(
elem, elem,
) )
) )
add_entities(sensors) async_add_entities(sensors)
class EmonCmsSensor(SensorEntity): class EmonCmsSensor(SensorEntity):
@ -143,7 +131,7 @@ class EmonCmsSensor(SensorEntity):
def __init__( def __init__(
self, self,
hass: HomeAssistant, hass: HomeAssistant,
data: EmonCmsData, 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,
@ -161,14 +149,12 @@ class EmonCmsSensor(SensorEntity):
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._identifier = get_id(
sensorid, elem["tag"], elem["name"], elem["id"], elem["userid"]
)
self._hass = hass self._hass = hass
self._data = data 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
@ -221,65 +207,9 @@ 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)
def update(self) -> None: async def async_update(self) -> None:
"""Get the latest data and updates the state.""" """Get the latest data and updates the state."""
self._data.update() elem = await self._emoncms_client.async_get_feed_fields(self._feed_id)
if self._data.data is None:
return
elem = next(
(
elem
for elem in self._data.data
if get_id(
self._sensorid,
elem["tag"],
elem["name"],
elem["id"],
elem["userid"],
)
== self._identifier
),
None,
)
if elem is None: if elem is None:
return return
self._update_attributes(elem) self._update_attributes(elem)
class EmonCmsData:
"""The class for handling the data retrieval."""
def __init__(self, hass: HomeAssistant, url: str, apikey: str) -> None:
"""Initialize the data object."""
self._apikey = apikey
self._url = f"{url}/feed/list.json"
self._hass = hass
self.data: list[dict[str, Any]] | None = None
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self) -> None:
"""Get the latest data from Emoncms."""
try:
parameters = {"apikey": self._apikey}
req = requests.get(
self._url, params=parameters, allow_redirects=True, timeout=5
)
except requests.exceptions.RequestException as exception:
_LOGGER.error(exception)
return
if req.status_code == HTTPStatus.OK:
self.data = req.json()
else:
_LOGGER.error(
(
"Please verify if the specified configuration value "
"'%s' is correct! (HTTP Status_code = %d)"
),
CONF_URL,
req.status_code,
)

View File

@ -1826,6 +1826,9 @@ pyefergy==22.5.0
# homeassistant.components.energenie_power_sockets # homeassistant.components.energenie_power_sockets
pyegps==0.2.5 pyegps==0.2.5
# homeassistant.components.emoncms
pyemoncms==0.0.6
# homeassistant.components.enphase_envoy # homeassistant.components.enphase_envoy
pyenphase==1.20.3 pyenphase==1.20.3