Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for monitoring a Neurio energy sensor."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 
8 import neurio
9 import requests.exceptions
10 import voluptuous as vol
11 
13  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
14  SensorDeviceClass,
15  SensorEntity,
16  SensorStateClass,
17 )
18 from homeassistant.const import CONF_API_KEY, UnitOfEnergy, UnitOfPower
19 from homeassistant.core import HomeAssistant
21 from homeassistant.helpers.entity_platform import AddEntitiesCallback
22 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
23 from homeassistant.util import Throttle
24 import homeassistant.util.dt as dt_util
25 
26 _LOGGER = logging.getLogger(__name__)
27 
28 CONF_API_SECRET = "api_secret"
29 CONF_SENSOR_ID = "sensor_id"
30 
31 ACTIVE_NAME = "Energy Usage"
32 DAILY_NAME = "Daily Energy Usage"
33 
34 ACTIVE_TYPE = "active"
35 DAILY_TYPE = "daily"
36 
37 
38 MIN_TIME_BETWEEN_DAILY_UPDATES = timedelta(seconds=150)
39 MIN_TIME_BETWEEN_ACTIVE_UPDATES = timedelta(seconds=10)
40 
41 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
42  {
43  vol.Required(CONF_API_KEY): cv.string,
44  vol.Required(CONF_API_SECRET): cv.string,
45  vol.Required(CONF_SENSOR_ID): cv.string,
46  }
47 )
48 
49 
51  hass: HomeAssistant,
52  config: ConfigType,
53  add_entities: AddEntitiesCallback,
54  discovery_info: DiscoveryInfoType | None = None,
55 ) -> None:
56  """Set up the Neurio sensor."""
57  api_key = config.get(CONF_API_KEY)
58  api_secret = config.get(CONF_API_SECRET)
59  sensor_id = config.get(CONF_SENSOR_ID)
60 
61  data = NeurioData(api_key, api_secret, sensor_id)
62 
63  @Throttle(MIN_TIME_BETWEEN_DAILY_UPDATES)
64  def update_daily():
65  """Update the daily power usage."""
66  data.get_daily_usage()
67 
68  @Throttle(MIN_TIME_BETWEEN_ACTIVE_UPDATES)
69  def update_active():
70  """Update the active power usage."""
71  data.get_active_power()
72 
73  update_daily()
74  update_active()
75 
76  # Active power sensor
77  add_entities([NeurioEnergy(data, ACTIVE_NAME, ACTIVE_TYPE, update_active)])
78  # Daily power sensor
79  add_entities([NeurioEnergy(data, DAILY_NAME, DAILY_TYPE, update_daily)])
80 
81 
82 class NeurioData:
83  """Stores data retrieved from Neurio sensor."""
84 
85  def __init__(self, api_key, api_secret, sensor_id):
86  """Initialize the data."""
87  self.api_keyapi_key = api_key
88  self.api_secretapi_secret = api_secret
89  self.sensor_idsensor_id = sensor_id
90 
91  self._daily_usage_daily_usage = None
92  self._active_power_active_power = None
93 
94  self._state_state = None
95 
96  neurio_tp = neurio.TokenProvider(key=api_key, secret=api_secret)
97  self.neurio_clientneurio_client = neurio.Client(token_provider=neurio_tp)
98 
99  @property
100  def daily_usage(self):
101  """Return latest daily usage value."""
102  return self._daily_usage_daily_usage
103 
104  @property
105  def active_power(self):
106  """Return latest active power value."""
107  return self._active_power_active_power
108 
109  def get_active_power(self) -> None:
110  """Return current power value."""
111  try:
112  sample = self.neurio_clientneurio_client.get_samples_live_last(self.sensor_idsensor_id)
113  self._active_power_active_power = sample["consumptionPower"]
114  except (requests.exceptions.RequestException, ValueError, KeyError):
115  _LOGGER.warning("Could not update current power usage")
116 
117  def get_daily_usage(self) -> None:
118  """Return current daily power usage."""
119  kwh = 0
120  start_time = dt_util.start_of_local_day().astimezone(dt_util.UTC).isoformat()
121  end_time = dt_util.utcnow().isoformat()
122 
123  _LOGGER.debug("Start: %s, End: %s", start_time, end_time)
124 
125  try:
126  history = self.neurio_clientneurio_client.get_samples_stats(
127  self.sensor_idsensor_id, start_time, "days", end_time
128  )
129  except (requests.exceptions.RequestException, ValueError, KeyError):
130  _LOGGER.warning("Could not update daily power usage")
131  return
132 
133  for result in history:
134  kwh += result["consumptionEnergy"] / 3600000
135 
136  self._daily_usage_daily_usage = round(kwh, 2)
137 
138 
140  """Implementation of a Neurio energy sensor."""
141 
142  _attr_icon = "mdi:flash"
143 
144  def __init__(self, data, name, sensor_type, update_call):
145  """Initialize the sensor."""
146  self._name_name = name
147  self._data_data = data
148  self._sensor_type_sensor_type = sensor_type
149  self.update_sensorupdate_sensor = update_call
150  self._state_state = None
151 
152  if sensor_type == ACTIVE_TYPE:
153  self._unit_of_measurement_unit_of_measurement = UnitOfPower.WATT
154  self._attr_device_class_attr_device_class = SensorDeviceClass.POWER
155  self._attr_state_class_attr_state_class = SensorStateClass.MEASUREMENT
156  elif sensor_type == DAILY_TYPE:
157  self._unit_of_measurement_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
158  self._attr_device_class_attr_device_class = SensorDeviceClass.ENERGY
159  self._attr_state_class_attr_state_class = SensorStateClass.TOTAL_INCREASING
160 
161  @property
162  def name(self):
163  """Return the name of the sensor."""
164  return self._name_name
165 
166  @property
167  def native_value(self):
168  """Return the state of the sensor."""
169  return self._state_state
170 
171  @property
173  """Return the unit of measurement of this entity, if any."""
174  return self._unit_of_measurement_unit_of_measurement
175 
176  def update(self) -> None:
177  """Get the latest data, update state."""
178  self.update_sensorupdate_sensor()
179 
180  if self._sensor_type_sensor_type == ACTIVE_TYPE:
181  self._state_state = self._data_data.active_power
182  elif self._sensor_type_sensor_type == DAILY_TYPE:
183  self._state_state = self._data_data.daily_usage
def __init__(self, api_key, api_secret, sensor_id)
Definition: sensor.py:85
def __init__(self, data, name, sensor_type, update_call)
Definition: sensor.py:144
def add_entities(account, async_add_entities, tracked)
Definition: sensor.py:40
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:55