1 """Support for monitoring emoncms feeds."""
3 from __future__
import annotations
7 import voluptuous
as vol
10 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
13 SensorEntityDescription,
18 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
19 CONCENTRATION_PARTS_PER_MILLION,
22 CONF_UNIT_OF_MEASUREMENT,
27 UnitOfElectricCurrent,
28 UnitOfElectricPotential,
48 from .config_flow
import sensor_name
51 CONF_ONLY_INCLUDE_FEEDID,
57 from .coordinator
import EmoncmsCoordinator
59 SENSORS: dict[str |
None, SensorEntityDescription] = {
62 translation_key=
"energy",
63 device_class=SensorDeviceClass.ENERGY,
64 native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
65 state_class=SensorStateClass.TOTAL_INCREASING,
69 translation_key=
"energy",
70 device_class=SensorDeviceClass.ENERGY,
71 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
72 state_class=SensorStateClass.TOTAL_INCREASING,
76 translation_key=
"power",
77 device_class=SensorDeviceClass.POWER,
78 native_unit_of_measurement=UnitOfPower.KILO_WATT,
79 state_class=SensorStateClass.MEASUREMENT,
83 translation_key=
"power",
84 device_class=SensorDeviceClass.POWER,
85 native_unit_of_measurement=UnitOfPower.WATT,
86 state_class=SensorStateClass.MEASUREMENT,
90 translation_key=
"voltage",
91 device_class=SensorDeviceClass.VOLTAGE,
92 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
93 state_class=SensorStateClass.MEASUREMENT,
97 translation_key=
"current",
98 device_class=SensorDeviceClass.CURRENT,
99 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
100 state_class=SensorStateClass.MEASUREMENT,
103 key=
"apparent_power",
104 translation_key=
"apparent_power",
105 device_class=SensorDeviceClass.APPARENT_POWER,
106 native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
107 state_class=SensorStateClass.MEASUREMENT,
110 key=
"temperature|celsius",
111 translation_key=
"temperature",
112 device_class=SensorDeviceClass.TEMPERATURE,
113 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
114 state_class=SensorStateClass.MEASUREMENT,
117 key=
"temperature|fahrenheit",
118 translation_key=
"temperature",
119 device_class=SensorDeviceClass.TEMPERATURE,
120 native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
121 state_class=SensorStateClass.MEASUREMENT,
124 key=
"temperature|kelvin",
125 translation_key=
"temperature",
126 device_class=SensorDeviceClass.TEMPERATURE,
127 native_unit_of_measurement=UnitOfTemperature.KELVIN,
128 state_class=SensorStateClass.MEASUREMENT,
132 translation_key=
"frequency",
133 device_class=SensorDeviceClass.FREQUENCY,
134 native_unit_of_measurement=UnitOfFrequency.HERTZ,
135 state_class=SensorStateClass.MEASUREMENT,
139 translation_key=
"pressure",
140 device_class=SensorDeviceClass.PRESSURE,
141 native_unit_of_measurement=UnitOfPressure.HPA,
142 state_class=SensorStateClass.MEASUREMENT,
146 translation_key=
"decibel",
147 device_class=SensorDeviceClass.SIGNAL_STRENGTH,
148 native_unit_of_measurement=UnitOfSoundPressure.DECIBEL,
149 state_class=SensorStateClass.MEASUREMENT,
152 key=
"volume|cubic_meter",
153 translation_key=
"volume",
154 device_class=SensorDeviceClass.VOLUME_STORAGE,
155 native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
156 state_class=SensorStateClass.MEASUREMENT,
159 key=
"flow|cubic_meters_per_hour",
160 translation_key=
"flow",
161 device_class=SensorDeviceClass.VOLUME_FLOW_RATE,
162 native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
163 state_class=SensorStateClass.MEASUREMENT,
166 key=
"flow|liters_per_minute",
167 translation_key=
"flow",
168 device_class=SensorDeviceClass.VOLUME_FLOW_RATE,
169 native_unit_of_measurement=UnitOfVolumeFlowRate.LITERS_PER_MINUTE,
170 state_class=SensorStateClass.MEASUREMENT,
173 key=
"speed|meters_per_second",
174 translation_key=
"speed",
175 device_class=SensorDeviceClass.SPEED,
176 native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
177 state_class=SensorStateClass.MEASUREMENT,
180 key=
"concentration|microgram_per_cubic_meter",
181 translation_key=
"concentration",
182 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
183 state_class=SensorStateClass.MEASUREMENT,
186 key=
"concentration|microgram_parts_per_million",
187 translation_key=
"concentration",
188 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
189 state_class=SensorStateClass.MEASUREMENT,
193 translation_key=
"percent",
194 native_unit_of_measurement=PERCENTAGE,
195 state_class=SensorStateClass.MEASUREMENT,
199 ATTR_FEEDID =
"FeedId"
200 ATTR_FEEDNAME =
"FeedName"
201 ATTR_LASTUPDATETIME =
"LastUpdated"
202 ATTR_LASTUPDATETIMESTR =
"LastUpdatedStr"
205 ATTR_USERID =
"UserId"
206 CONF_SENSOR_NAMES =
"sensor_names"
208 DEFAULT_UNIT = UnitOfPower.WATT
210 ONLY_INCL_EXCL_NONE =
"only_include_exclude_or_none"
212 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
214 vol.Required(CONF_API_KEY): cv.string,
215 vol.Required(CONF_URL): cv.string,
216 vol.Required(CONF_ID): cv.positive_int,
217 vol.Exclusive(CONF_ONLY_INCLUDE_FEEDID, ONLY_INCL_EXCL_NONE): vol.All(
218 cv.ensure_list, [cv.positive_int]
220 vol.Exclusive(CONF_EXCLUDE_FEEDID, ONLY_INCL_EXCL_NONE): vol.All(
221 cv.ensure_list, [cv.positive_int]
223 vol.Optional(CONF_SENSOR_NAMES): vol.All(
224 {cv.positive_int: vol.All(cv.string, vol.Length(min=1))}
226 vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
227 vol.Optional(CONF_UNIT_OF_MEASUREMENT, default=DEFAULT_UNIT): cv.string,
235 async_add_entities: AddEntitiesCallback,
236 discovery_info: DiscoveryInfoType |
None =
None,
238 """Import config from yaml."""
239 if CONF_VALUE_TEMPLATE
in config:
243 f
"remove_{CONF_VALUE_TEMPLATE}_{DOMAIN}",
246 severity=IssueSeverity.ERROR,
247 translation_key=f
"remove_{CONF_VALUE_TEMPLATE}",
248 translation_placeholders={
250 "parameter": CONF_VALUE_TEMPLATE,
254 if CONF_ONLY_INCLUDE_FEEDID
not in config:
258 f
"missing_{CONF_ONLY_INCLUDE_FEEDID}_{DOMAIN}",
261 severity=IssueSeverity.WARNING,
262 translation_key=f
"missing_{CONF_ONLY_INCLUDE_FEEDID}",
263 translation_placeholders={
267 result = await hass.config_entries.flow.async_init(
268 DOMAIN, context={
"source": SOURCE_IMPORT}, data=config
271 result.get(
"type") == FlowResultType.CREATE_ENTRY
272 or result.get(
"reason") ==
"already_configured"
276 HOMEASSISTANT_DOMAIN,
277 f
"deprecated_yaml_{DOMAIN}",
280 breaks_in_ha_version=
"2025.3.0",
281 severity=IssueSeverity.WARNING,
282 translation_key=
"deprecated_yaml",
283 translation_placeholders={
285 "integration_title":
"emoncms",
293 async_add_entities: AddEntitiesCallback,
295 """Set up the emoncms sensors."""
297 exclude_feeds = entry.data.get(CONF_EXCLUDE_FEEDID)
298 include_only_feeds = entry.options.get(
299 CONF_ONLY_INCLUDE_FEEDID, entry.data.get(CONF_ONLY_INCLUDE_FEEDID)
302 if exclude_feeds
is None and include_only_feeds
is None:
305 coordinator = entry.runtime_data
307 unique_id = entry.unique_id
if entry.unique_id
else entry.entry_id
308 elems = coordinator.data
311 sensors: list[EmonCmsSensor] = []
313 for idx, elem
in enumerate(elems):
314 if include_only_feeds
is not None and elem[FEED_ID]
not in include_only_feeds:
329 """Implementation of an Emoncms sensor."""
331 _attr_has_entity_name =
True
335 coordinator: EmoncmsCoordinator,
337 unit_of_measurement: str |
None,
341 """Initialize the sensor."""
345 if self.coordinator.data:
346 elem = self.coordinator.data[self.
idxidx]
348 "emoncms_details": f
"{elem[FEED_TAG]} {elem[FEED_NAME]}",
351 description = SENSORS.get(unit_of_measurement)
352 if description
is not None:
359 """Update entity attributes."""
361 ATTR_FEEDID: elem[FEED_ID],
362 ATTR_TAG: elem[FEED_TAG],
363 ATTR_FEEDNAME: elem[FEED_NAME],
365 if elem[
"value"]
is not None:
370 template.timestamp_local(
float(elem[
"time"]))
374 if elem[
"value"]
is not None:
379 """Handle updated data from the coordinator."""
380 data = self.coordinator.data
_attr_native_unit_of_measurement
None _update_attributes(self, dict[str, Any] elem)
None __init__(self, EmoncmsCoordinator coordinator, str unique_id, str|None unit_of_measurement, str name, int idx)
None _handle_coordinator_update(self)
_attr_extra_state_attributes
_attr_translation_placeholders
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
None async_create_issue(HomeAssistant hass, str entry_id)