Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Creates HomeWizard sensor entities."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from typing import Final
8 
9 from homewizard_energy.v1.models import Data, ExternalDevice
10 
12  DEVICE_CLASS_UNITS,
13  SensorDeviceClass,
14  SensorEntity,
15  SensorEntityDescription,
16  SensorStateClass,
17 )
18 from homeassistant.const import (
19  ATTR_VIA_DEVICE,
20  PERCENTAGE,
21  EntityCategory,
22  UnitOfApparentPower,
23  UnitOfElectricCurrent,
24  UnitOfElectricPotential,
25  UnitOfEnergy,
26  UnitOfFrequency,
27  UnitOfPower,
28  UnitOfReactivePower,
29  UnitOfVolume,
30 )
31 from homeassistant.core import HomeAssistant
32 from homeassistant.helpers.device_registry import DeviceInfo
33 from homeassistant.helpers.entity_platform import AddEntitiesCallback
34 from homeassistant.helpers.typing import StateType
35 
36 from . import HomeWizardConfigEntry
37 from .const import DOMAIN
38 from .coordinator import HWEnergyDeviceUpdateCoordinator
39 from .entity import HomeWizardEntity
40 
41 PARALLEL_UPDATES = 1
42 
43 
44 @dataclass(frozen=True, kw_only=True)
46  """Class describing HomeWizard sensor entities."""
47 
48  enabled_fn: Callable[[Data], bool] = lambda data: True
49  has_fn: Callable[[Data], bool]
50  value_fn: Callable[[Data], StateType]
51 
52 
53 @dataclass(frozen=True, kw_only=True)
55  """Class describing HomeWizard sensor entities."""
56 
57  suggested_device_class: SensorDeviceClass
58  device_name: str
59 
60 
61 def to_percentage(value: float | None) -> float | None:
62  """Convert 0..1 value to percentage when value is not None."""
63  return value * 100 if value is not None else None
64 
65 
66 SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
68  key="smr_version",
69  translation_key="dsmr_version",
70  entity_category=EntityCategory.DIAGNOSTIC,
71  has_fn=lambda data: data.smr_version is not None,
72  value_fn=lambda data: data.smr_version,
73  ),
75  key="meter_model",
76  translation_key="meter_model",
77  entity_category=EntityCategory.DIAGNOSTIC,
78  has_fn=lambda data: data.meter_model is not None,
79  value_fn=lambda data: data.meter_model,
80  ),
82  key="unique_meter_id",
83  translation_key="unique_meter_id",
84  entity_category=EntityCategory.DIAGNOSTIC,
85  has_fn=lambda data: data.unique_meter_id is not None,
86  value_fn=lambda data: data.unique_meter_id,
87  ),
89  key="wifi_ssid",
90  translation_key="wifi_ssid",
91  entity_category=EntityCategory.DIAGNOSTIC,
92  has_fn=lambda data: data.wifi_ssid is not None,
93  value_fn=lambda data: data.wifi_ssid,
94  ),
96  key="active_tariff",
97  translation_key="active_tariff",
98  has_fn=lambda data: data.active_tariff is not None,
99  value_fn=lambda data: (
100  None if data.active_tariff is None else str(data.active_tariff)
101  ),
102  device_class=SensorDeviceClass.ENUM,
103  options=["1", "2", "3", "4"],
104  ),
106  key="wifi_strength",
107  translation_key="wifi_strength",
108  native_unit_of_measurement=PERCENTAGE,
109  state_class=SensorStateClass.MEASUREMENT,
110  entity_category=EntityCategory.DIAGNOSTIC,
111  entity_registry_enabled_default=False,
112  has_fn=lambda data: data.wifi_strength is not None,
113  value_fn=lambda data: data.wifi_strength,
114  ),
116  key="total_power_import_kwh",
117  translation_key="total_energy_import_kwh",
118  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
119  device_class=SensorDeviceClass.ENERGY,
120  state_class=SensorStateClass.TOTAL_INCREASING,
121  has_fn=lambda data: data.total_energy_import_kwh is not None,
122  value_fn=lambda data: data.total_energy_import_kwh,
123  ),
125  key="total_power_import_t1_kwh",
126  translation_key="total_energy_import_tariff_kwh",
127  translation_placeholders={"tariff": "1"},
128  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
129  device_class=SensorDeviceClass.ENERGY,
130  state_class=SensorStateClass.TOTAL_INCREASING,
131  has_fn=lambda data: (
132  # SKT/SDM230/630 provides both total and tariff 1: duplicate.
133  data.total_energy_import_t1_kwh is not None
134  and data.total_energy_export_t2_kwh is not None
135  ),
136  value_fn=lambda data: data.total_energy_import_t1_kwh,
137  ),
139  key="total_power_import_t2_kwh",
140  translation_key="total_energy_import_tariff_kwh",
141  translation_placeholders={"tariff": "2"},
142  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
143  device_class=SensorDeviceClass.ENERGY,
144  state_class=SensorStateClass.TOTAL_INCREASING,
145  has_fn=lambda data: data.total_energy_import_t2_kwh is not None,
146  value_fn=lambda data: data.total_energy_import_t2_kwh,
147  ),
149  key="total_power_import_t3_kwh",
150  translation_key="total_energy_import_tariff_kwh",
151  translation_placeholders={"tariff": "3"},
152  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
153  device_class=SensorDeviceClass.ENERGY,
154  state_class=SensorStateClass.TOTAL_INCREASING,
155  has_fn=lambda data: data.total_energy_import_t3_kwh is not None,
156  value_fn=lambda data: data.total_energy_import_t3_kwh,
157  ),
159  key="total_power_import_t4_kwh",
160  translation_key="total_energy_import_tariff_kwh",
161  translation_placeholders={"tariff": "4"},
162  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
163  device_class=SensorDeviceClass.ENERGY,
164  state_class=SensorStateClass.TOTAL_INCREASING,
165  has_fn=lambda data: data.total_energy_import_t4_kwh is not None,
166  value_fn=lambda data: data.total_energy_import_t4_kwh,
167  ),
169  key="total_power_export_kwh",
170  translation_key="total_energy_export_kwh",
171  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
172  device_class=SensorDeviceClass.ENERGY,
173  state_class=SensorStateClass.TOTAL_INCREASING,
174  has_fn=lambda data: data.total_energy_export_kwh is not None,
175  enabled_fn=lambda data: data.total_energy_export_kwh != 0,
176  value_fn=lambda data: data.total_energy_export_kwh,
177  ),
179  key="total_power_export_t1_kwh",
180  translation_key="total_energy_export_tariff_kwh",
181  translation_placeholders={"tariff": "1"},
182  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
183  device_class=SensorDeviceClass.ENERGY,
184  state_class=SensorStateClass.TOTAL_INCREASING,
185  has_fn=lambda data: (
186  # SKT/SDM230/630 provides both total and tariff 1: duplicate.
187  data.total_energy_export_t1_kwh is not None
188  and data.total_energy_export_t2_kwh is not None
189  ),
190  enabled_fn=lambda data: data.total_energy_export_t1_kwh != 0,
191  value_fn=lambda data: data.total_energy_export_t1_kwh,
192  ),
194  key="total_power_export_t2_kwh",
195  translation_key="total_energy_export_tariff_kwh",
196  translation_placeholders={"tariff": "2"},
197  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
198  device_class=SensorDeviceClass.ENERGY,
199  state_class=SensorStateClass.TOTAL_INCREASING,
200  has_fn=lambda data: data.total_energy_export_t2_kwh is not None,
201  enabled_fn=lambda data: data.total_energy_export_t2_kwh != 0,
202  value_fn=lambda data: data.total_energy_export_t2_kwh,
203  ),
205  key="total_power_export_t3_kwh",
206  translation_key="total_energy_export_tariff_kwh",
207  translation_placeholders={"tariff": "3"},
208  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
209  device_class=SensorDeviceClass.ENERGY,
210  state_class=SensorStateClass.TOTAL_INCREASING,
211  has_fn=lambda data: data.total_energy_export_t3_kwh is not None,
212  enabled_fn=lambda data: data.total_energy_export_t3_kwh != 0,
213  value_fn=lambda data: data.total_energy_export_t3_kwh,
214  ),
216  key="total_power_export_t4_kwh",
217  translation_key="total_energy_export_tariff_kwh",
218  translation_placeholders={"tariff": "4"},
219  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
220  device_class=SensorDeviceClass.ENERGY,
221  state_class=SensorStateClass.TOTAL_INCREASING,
222  has_fn=lambda data: data.total_energy_export_t4_kwh is not None,
223  enabled_fn=lambda data: data.total_energy_export_t4_kwh != 0,
224  value_fn=lambda data: data.total_energy_export_t4_kwh,
225  ),
227  key="active_power_w",
228  native_unit_of_measurement=UnitOfPower.WATT,
229  device_class=SensorDeviceClass.POWER,
230  state_class=SensorStateClass.MEASUREMENT,
231  suggested_display_precision=0,
232  has_fn=lambda data: data.active_power_w is not None,
233  value_fn=lambda data: data.active_power_w,
234  ),
236  key="active_power_l1_w",
237  translation_key="active_power_phase_w",
238  translation_placeholders={"phase": "1"},
239  native_unit_of_measurement=UnitOfPower.WATT,
240  device_class=SensorDeviceClass.POWER,
241  state_class=SensorStateClass.MEASUREMENT,
242  suggested_display_precision=0,
243  has_fn=lambda data: data.active_power_l1_w is not None,
244  value_fn=lambda data: data.active_power_l1_w,
245  ),
247  key="active_power_l2_w",
248  translation_key="active_power_phase_w",
249  translation_placeholders={"phase": "2"},
250  native_unit_of_measurement=UnitOfPower.WATT,
251  device_class=SensorDeviceClass.POWER,
252  state_class=SensorStateClass.MEASUREMENT,
253  suggested_display_precision=0,
254  has_fn=lambda data: data.active_power_l2_w is not None,
255  value_fn=lambda data: data.active_power_l2_w,
256  ),
258  key="active_power_l3_w",
259  translation_key="active_power_phase_w",
260  translation_placeholders={"phase": "3"},
261  native_unit_of_measurement=UnitOfPower.WATT,
262  device_class=SensorDeviceClass.POWER,
263  state_class=SensorStateClass.MEASUREMENT,
264  suggested_display_precision=0,
265  has_fn=lambda data: data.active_power_l3_w is not None,
266  value_fn=lambda data: data.active_power_l3_w,
267  ),
269  key="active_voltage_v",
270  native_unit_of_measurement=UnitOfElectricPotential.VOLT,
271  device_class=SensorDeviceClass.VOLTAGE,
272  state_class=SensorStateClass.MEASUREMENT,
273  entity_registry_enabled_default=False,
274  has_fn=lambda data: data.active_voltage_v is not None,
275  value_fn=lambda data: data.active_voltage_v,
276  ),
278  key="active_voltage_l1_v",
279  translation_key="active_voltage_phase_v",
280  translation_placeholders={"phase": "1"},
281  native_unit_of_measurement=UnitOfElectricPotential.VOLT,
282  device_class=SensorDeviceClass.VOLTAGE,
283  state_class=SensorStateClass.MEASUREMENT,
284  entity_registry_enabled_default=False,
285  has_fn=lambda data: data.active_voltage_l1_v is not None,
286  value_fn=lambda data: data.active_voltage_l1_v,
287  ),
289  key="active_voltage_l2_v",
290  translation_key="active_voltage_phase_v",
291  translation_placeholders={"phase": "2"},
292  native_unit_of_measurement=UnitOfElectricPotential.VOLT,
293  device_class=SensorDeviceClass.VOLTAGE,
294  state_class=SensorStateClass.MEASUREMENT,
295  entity_registry_enabled_default=False,
296  has_fn=lambda data: data.active_voltage_l2_v is not None,
297  value_fn=lambda data: data.active_voltage_l2_v,
298  ),
300  key="active_voltage_l3_v",
301  translation_key="active_voltage_phase_v",
302  translation_placeholders={"phase": "3"},
303  native_unit_of_measurement=UnitOfElectricPotential.VOLT,
304  device_class=SensorDeviceClass.VOLTAGE,
305  state_class=SensorStateClass.MEASUREMENT,
306  entity_registry_enabled_default=False,
307  has_fn=lambda data: data.active_voltage_l3_v is not None,
308  value_fn=lambda data: data.active_voltage_l3_v,
309  ),
311  key="active_current_a",
312  native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
313  device_class=SensorDeviceClass.CURRENT,
314  state_class=SensorStateClass.MEASUREMENT,
315  entity_registry_enabled_default=False,
316  has_fn=lambda data: data.active_current_a is not None,
317  value_fn=lambda data: data.active_current_a,
318  ),
320  key="active_current_l1_a",
321  translation_key="active_current_phase_a",
322  translation_placeholders={"phase": "1"},
323  native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
324  device_class=SensorDeviceClass.CURRENT,
325  state_class=SensorStateClass.MEASUREMENT,
326  entity_registry_enabled_default=False,
327  has_fn=lambda data: data.active_current_l1_a is not None,
328  value_fn=lambda data: data.active_current_l1_a,
329  ),
331  key="active_current_l2_a",
332  translation_key="active_current_phase_a",
333  translation_placeholders={"phase": "2"},
334  native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
335  device_class=SensorDeviceClass.CURRENT,
336  state_class=SensorStateClass.MEASUREMENT,
337  entity_registry_enabled_default=False,
338  has_fn=lambda data: data.active_current_l2_a is not None,
339  value_fn=lambda data: data.active_current_l2_a,
340  ),
342  key="active_current_l3_a",
343  translation_key="active_current_phase_a",
344  translation_placeholders={"phase": "3"},
345  native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
346  device_class=SensorDeviceClass.CURRENT,
347  state_class=SensorStateClass.MEASUREMENT,
348  entity_registry_enabled_default=False,
349  has_fn=lambda data: data.active_current_l3_a is not None,
350  value_fn=lambda data: data.active_current_l3_a,
351  ),
353  key="active_frequency_hz",
354  native_unit_of_measurement=UnitOfFrequency.HERTZ,
355  device_class=SensorDeviceClass.FREQUENCY,
356  state_class=SensorStateClass.MEASUREMENT,
357  entity_registry_enabled_default=False,
358  has_fn=lambda data: data.active_frequency_hz is not None,
359  value_fn=lambda data: data.active_frequency_hz,
360  ),
362  key="active_apparent_power_va",
363  native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
364  device_class=SensorDeviceClass.APPARENT_POWER,
365  state_class=SensorStateClass.MEASUREMENT,
366  entity_registry_enabled_default=False,
367  has_fn=lambda data: data.active_apparent_power_va is not None,
368  value_fn=lambda data: data.active_apparent_power_va,
369  ),
371  key="active_apparent_power_l1_va",
372  translation_key="active_apparent_power_phase_va",
373  translation_placeholders={"phase": "1"},
374  native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
375  device_class=SensorDeviceClass.APPARENT_POWER,
376  state_class=SensorStateClass.MEASUREMENT,
377  entity_registry_enabled_default=False,
378  has_fn=lambda data: data.active_apparent_power_l1_va is not None,
379  value_fn=lambda data: data.active_apparent_power_l1_va,
380  ),
382  key="active_apparent_power_l2_va",
383  translation_key="active_apparent_power_phase_va",
384  translation_placeholders={"phase": "2"},
385  native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
386  device_class=SensorDeviceClass.APPARENT_POWER,
387  state_class=SensorStateClass.MEASUREMENT,
388  entity_registry_enabled_default=False,
389  has_fn=lambda data: data.active_apparent_power_l2_va is not None,
390  value_fn=lambda data: data.active_apparent_power_l2_va,
391  ),
393  key="active_apparent_power_l3_va",
394  translation_key="active_apparent_power_phase_va",
395  translation_placeholders={"phase": "3"},
396  native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
397  device_class=SensorDeviceClass.APPARENT_POWER,
398  state_class=SensorStateClass.MEASUREMENT,
399  entity_registry_enabled_default=False,
400  has_fn=lambda data: data.active_apparent_power_l3_va is not None,
401  value_fn=lambda data: data.active_apparent_power_l3_va,
402  ),
404  key="active_reactive_power_var",
405  native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
406  device_class=SensorDeviceClass.REACTIVE_POWER,
407  state_class=SensorStateClass.MEASUREMENT,
408  entity_registry_enabled_default=False,
409  has_fn=lambda data: data.active_reactive_power_var is not None,
410  value_fn=lambda data: data.active_reactive_power_var,
411  ),
413  key="active_reactive_power_l1_var",
414  translation_key="active_reactive_power_phase_var",
415  translation_placeholders={"phase": "1"},
416  native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
417  device_class=SensorDeviceClass.REACTIVE_POWER,
418  state_class=SensorStateClass.MEASUREMENT,
419  entity_registry_enabled_default=False,
420  has_fn=lambda data: data.active_reactive_power_l1_var is not None,
421  value_fn=lambda data: data.active_reactive_power_l1_var,
422  ),
424  key="active_reactive_power_l2_var",
425  translation_key="active_reactive_power_phase_var",
426  translation_placeholders={"phase": "2"},
427  native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
428  device_class=SensorDeviceClass.REACTIVE_POWER,
429  state_class=SensorStateClass.MEASUREMENT,
430  entity_registry_enabled_default=False,
431  has_fn=lambda data: data.active_reactive_power_l2_var is not None,
432  value_fn=lambda data: data.active_reactive_power_l2_var,
433  ),
435  key="active_reactive_power_l3_var",
436  translation_key="active_reactive_power_phase_var",
437  translation_placeholders={"phase": "3"},
438  native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
439  device_class=SensorDeviceClass.REACTIVE_POWER,
440  state_class=SensorStateClass.MEASUREMENT,
441  entity_registry_enabled_default=False,
442  has_fn=lambda data: data.active_reactive_power_l3_var is not None,
443  value_fn=lambda data: data.active_reactive_power_l3_var,
444  ),
446  key="active_power_factor",
447  native_unit_of_measurement=PERCENTAGE,
448  device_class=SensorDeviceClass.POWER_FACTOR,
449  state_class=SensorStateClass.MEASUREMENT,
450  entity_registry_enabled_default=False,
451  has_fn=lambda data: data.active_power_factor is not None,
452  value_fn=lambda data: to_percentage(data.active_power_factor),
453  ),
455  key="active_power_factor_l1",
456  translation_key="active_power_factor_phase",
457  translation_placeholders={"phase": "1"},
458  native_unit_of_measurement=PERCENTAGE,
459  device_class=SensorDeviceClass.POWER_FACTOR,
460  state_class=SensorStateClass.MEASUREMENT,
461  entity_registry_enabled_default=False,
462  has_fn=lambda data: data.active_power_factor_l1 is not None,
463  value_fn=lambda data: to_percentage(data.active_power_factor_l1),
464  ),
466  key="active_power_factor_l2",
467  translation_key="active_power_factor_phase",
468  translation_placeholders={"phase": "2"},
469  native_unit_of_measurement=PERCENTAGE,
470  device_class=SensorDeviceClass.POWER_FACTOR,
471  state_class=SensorStateClass.MEASUREMENT,
472  entity_registry_enabled_default=False,
473  has_fn=lambda data: data.active_power_factor_l2 is not None,
474  value_fn=lambda data: to_percentage(data.active_power_factor_l2),
475  ),
477  key="active_power_factor_l3",
478  translation_key="active_power_factor_phase",
479  translation_placeholders={"phase": "3"},
480  native_unit_of_measurement=PERCENTAGE,
481  device_class=SensorDeviceClass.POWER_FACTOR,
482  state_class=SensorStateClass.MEASUREMENT,
483  entity_registry_enabled_default=False,
484  has_fn=lambda data: data.active_power_factor_l3 is not None,
485  value_fn=lambda data: to_percentage(data.active_power_factor_l3),
486  ),
488  key="voltage_sag_l1_count",
489  translation_key="voltage_sag_phase_count",
490  translation_placeholders={"phase": "1"},
491  entity_category=EntityCategory.DIAGNOSTIC,
492  has_fn=lambda data: data.voltage_sag_l1_count is not None,
493  value_fn=lambda data: data.voltage_sag_l1_count,
494  ),
496  key="voltage_sag_l2_count",
497  translation_key="voltage_sag_phase_count",
498  translation_placeholders={"phase": "2"},
499  entity_category=EntityCategory.DIAGNOSTIC,
500  has_fn=lambda data: data.voltage_sag_l2_count is not None,
501  value_fn=lambda data: data.voltage_sag_l2_count,
502  ),
504  key="voltage_sag_l3_count",
505  translation_key="voltage_sag_phase_count",
506  translation_placeholders={"phase": "3"},
507  entity_category=EntityCategory.DIAGNOSTIC,
508  has_fn=lambda data: data.voltage_sag_l3_count is not None,
509  value_fn=lambda data: data.voltage_sag_l3_count,
510  ),
512  key="voltage_swell_l1_count",
513  translation_key="voltage_swell_phase_count",
514  translation_placeholders={"phase": "1"},
515  entity_category=EntityCategory.DIAGNOSTIC,
516  has_fn=lambda data: data.voltage_swell_l1_count is not None,
517  value_fn=lambda data: data.voltage_swell_l1_count,
518  ),
520  key="voltage_swell_l2_count",
521  translation_key="voltage_swell_phase_count",
522  translation_placeholders={"phase": "2"},
523  entity_category=EntityCategory.DIAGNOSTIC,
524  has_fn=lambda data: data.voltage_swell_l2_count is not None,
525  value_fn=lambda data: data.voltage_swell_l2_count,
526  ),
528  key="voltage_swell_l3_count",
529  translation_key="voltage_swell_phase_count",
530  translation_placeholders={"phase": "3"},
531  entity_category=EntityCategory.DIAGNOSTIC,
532  has_fn=lambda data: data.voltage_swell_l3_count is not None,
533  value_fn=lambda data: data.voltage_swell_l3_count,
534  ),
536  key="any_power_fail_count",
537  translation_key="any_power_fail_count",
538  entity_category=EntityCategory.DIAGNOSTIC,
539  has_fn=lambda data: data.any_power_fail_count is not None,
540  value_fn=lambda data: data.any_power_fail_count,
541  ),
543  key="long_power_fail_count",
544  translation_key="long_power_fail_count",
545  entity_category=EntityCategory.DIAGNOSTIC,
546  has_fn=lambda data: data.long_power_fail_count is not None,
547  value_fn=lambda data: data.long_power_fail_count,
548  ),
550  key="active_power_average_w",
551  translation_key="active_power_average_w",
552  native_unit_of_measurement=UnitOfPower.WATT,
553  device_class=SensorDeviceClass.POWER,
554  has_fn=lambda data: data.active_power_average_w is not None,
555  value_fn=lambda data: data.active_power_average_w,
556  ),
558  key="monthly_power_peak_w",
559  translation_key="monthly_power_peak_w",
560  native_unit_of_measurement=UnitOfPower.WATT,
561  device_class=SensorDeviceClass.POWER,
562  has_fn=lambda data: data.monthly_power_peak_w is not None,
563  value_fn=lambda data: data.monthly_power_peak_w,
564  ),
566  key="active_liter_lpm",
567  translation_key="active_liter_lpm",
568  native_unit_of_measurement="l/min",
569  state_class=SensorStateClass.MEASUREMENT,
570  has_fn=lambda data: data.active_liter_lpm is not None,
571  value_fn=lambda data: data.active_liter_lpm,
572  ),
574  key="total_liter_m3",
575  translation_key="total_liter_m3",
576  native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
577  device_class=SensorDeviceClass.WATER,
578  state_class=SensorStateClass.TOTAL_INCREASING,
579  has_fn=lambda data: data.total_liter_m3 is not None,
580  value_fn=lambda data: data.total_liter_m3,
581  ),
582 )
583 
584 
585 EXTERNAL_SENSORS = {
586  ExternalDevice.DeviceType.GAS_METER: HomeWizardExternalSensorEntityDescription(
587  key="gas_meter",
588  suggested_device_class=SensorDeviceClass.GAS,
589  state_class=SensorStateClass.TOTAL_INCREASING,
590  device_name="Gas meter",
591  ),
592  ExternalDevice.DeviceType.HEAT_METER: HomeWizardExternalSensorEntityDescription(
593  key="heat_meter",
594  suggested_device_class=SensorDeviceClass.ENERGY,
595  state_class=SensorStateClass.TOTAL_INCREASING,
596  device_name="Heat meter",
597  ),
598  ExternalDevice.DeviceType.WARM_WATER_METER: HomeWizardExternalSensorEntityDescription(
599  key="warm_water_meter",
600  suggested_device_class=SensorDeviceClass.WATER,
601  state_class=SensorStateClass.TOTAL_INCREASING,
602  device_name="Warm water meter",
603  ),
604  ExternalDevice.DeviceType.WATER_METER: HomeWizardExternalSensorEntityDescription(
605  key="water_meter",
606  suggested_device_class=SensorDeviceClass.WATER,
607  state_class=SensorStateClass.TOTAL_INCREASING,
608  device_name="Water meter",
609  ),
610  ExternalDevice.DeviceType.INLET_HEAT_METER: HomeWizardExternalSensorEntityDescription(
611  key="inlet_heat_meter",
612  suggested_device_class=SensorDeviceClass.ENERGY,
613  state_class=SensorStateClass.TOTAL_INCREASING,
614  device_name="Inlet heat meter",
615  ),
616 }
617 
618 
620  hass: HomeAssistant,
621  entry: HomeWizardConfigEntry,
622  async_add_entities: AddEntitiesCallback,
623 ) -> None:
624  """Initialize sensors."""
625 
626  data = entry.runtime_data.data.data
627 
628  # Initialize default sensors
629  entities: list = [
630  HomeWizardSensorEntity(entry.runtime_data, description)
631  for description in SENSORS
632  if description.has_fn(data)
633  ]
634 
635  # Initialize external devices
636  if data.external_devices is not None:
637  for unique_id, device in data.external_devices.items():
638  if description := EXTERNAL_SENSORS.get(device.meter_type):
639  # Add external device
640  entities.append(
642  entry.runtime_data, description, unique_id
643  )
644  )
645 
646  async_add_entities(entities)
647 
648 
650  """Representation of a HomeWizard Sensor."""
651 
652  entity_description: HomeWizardSensorEntityDescription
653 
654  def __init__(
655  self,
656  coordinator: HWEnergyDeviceUpdateCoordinator,
657  description: HomeWizardSensorEntityDescription,
658  ) -> None:
659  """Initialize Sensor Domain."""
660  super().__init__(coordinator)
661  self.entity_descriptionentity_description = description
662  self._attr_unique_id_attr_unique_id = f"{coordinator.config_entry.unique_id}_{description.key}"
663  if not description.enabled_fn(self.coordinator.data.data):
664  self._attr_entity_registry_enabled_default_attr_entity_registry_enabled_default = False
665 
666  @property
667  def native_value(self) -> StateType:
668  """Return the sensor value."""
669  return self.entity_descriptionentity_description.value_fn(self.coordinator.data.data)
670 
671  @property
672  def available(self) -> bool:
673  """Return availability of meter."""
674  return super().available and self.native_valuenative_valuenative_value is not None
675 
676 
678  """Representation of externally connected HomeWizard Sensor."""
679 
680  def __init__(
681  self,
682  coordinator: HWEnergyDeviceUpdateCoordinator,
683  description: HomeWizardExternalSensorEntityDescription,
684  device_unique_id: str,
685  ) -> None:
686  """Initialize Externally connected HomeWizard Sensors."""
687  super().__init__(coordinator)
688  self.entity_descriptionentity_description = description
689  self._device_id_device_id = device_unique_id
690  self._suggested_device_class_suggested_device_class = description.suggested_device_class
691  self._attr_unique_id_attr_unique_id = f"{DOMAIN}_{device_unique_id}"
693  identifiers={(DOMAIN, device_unique_id)},
694  name=description.device_name,
695  manufacturer="HomeWizard",
696  model=coordinator.data.device.product_type,
697  serial_number=device_unique_id,
698  )
699  if coordinator.data.device.serial is not None:
700  self._attr_device_info_attr_device_info_attr_device_info[ATTR_VIA_DEVICE] = (
701  DOMAIN,
702  coordinator.data.device.serial,
703  )
704 
705  @property
706  def native_value(self) -> float | int | str | None:
707  """Return the sensor value."""
708  return self.devicedevice.value if self.devicedevice is not None else None
709 
710  @property
711  def device(self) -> ExternalDevice | None:
712  """Return ExternalDevice object."""
713  return (
714  self.coordinator.data.data.external_devices[self._device_id_device_id]
715  if self.coordinator.data.data.external_devices is not None
716  else None
717  )
718 
719  @property
720  def available(self) -> bool:
721  """Return availability of meter."""
722  return super().available and self.devicedevice is not None
723 
724  @property
725  def native_unit_of_measurement(self) -> str | None:
726  """Return unit of measurement based on device unit."""
727  if (device := self.devicedevice) is None:
728  return None
729 
730  # API returns 'm3' but we expect m³
731  if device.unit == "m3":
732  return UnitOfVolume.CUBIC_METERS
733 
734  return device.unit
735 
736  @property
737  def device_class(self) -> SensorDeviceClass | None:
738  """Validate unit of measurement and set device class."""
739  if (
740  self.native_unit_of_measurementnative_unit_of_measurementnative_unit_of_measurement
741  not in DEVICE_CLASS_UNITS[self._suggested_device_class_suggested_device_class]
742  ):
743  return None
744 
745  return self._suggested_device_class_suggested_device_class
None __init__(self, HWEnergyDeviceUpdateCoordinator coordinator, HomeWizardExternalSensorEntityDescription description, str device_unique_id)
Definition: sensor.py:685
None __init__(self, HWEnergyDeviceUpdateCoordinator coordinator, HomeWizardSensorEntityDescription description)
Definition: sensor.py:658
StateType|date|datetime|Decimal native_value(self)
Definition: __init__.py:460
float|None to_percentage(float|None value)
Definition: sensor.py:61
None async_setup_entry(HomeAssistant hass, HomeWizardConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:623