Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The dsmr component."""
2 
3 from __future__ import annotations
4 
5 from asyncio import CancelledError, Task
6 from contextlib import suppress
7 from dataclasses import dataclass
8 from typing import Any
9 
10 from dsmr_parser.objects import Telegram
11 
12 from homeassistant.config_entries import ConfigEntry
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.helpers import entity_registry as er
15 
16 from .const import CONF_DSMR_VERSION, PLATFORMS
17 
18 
19 @dataclass
20 class DsmrState:
21  """State of integration."""
22 
23  task: Task | None = None
24  telegram: Telegram | None = None
25 
26 
27 type DsmrConfigEntry = ConfigEntry[DsmrState]
28 
29 
30 async def async_setup_entry(hass: HomeAssistant, entry: DsmrConfigEntry) -> bool:
31  """Set up DSMR from a config entry."""
32 
33  @callback
34  def _async_migrate_entity_entry(
35  entity_entry: er.RegistryEntry,
36  ) -> dict[str, Any] | None:
37  """Migrate DSMR entity entry."""
38  return async_migrate_entity_entry(entry, entity_entry)
39 
40  await er.async_migrate_entries(hass, entry.entry_id, _async_migrate_entity_entry)
41 
42  entry.runtime_data = DsmrState()
43  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
44  entry.async_on_unload(entry.add_update_listener(async_update_options))
45 
46  return True
47 
48 
49 async def async_unload_entry(hass: HomeAssistant, entry: DsmrConfigEntry) -> bool:
50  """Unload a config entry."""
51 
52  # Cancel the reconnect task
53  if task := entry.runtime_data.task:
54  task.cancel()
55  with suppress(CancelledError):
56  await task
57 
58  return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
59 
60 
61 async def async_update_options(hass: HomeAssistant, entry: DsmrConfigEntry) -> None:
62  """Update options."""
63  await hass.config_entries.async_reload(entry.entry_id)
64 
65 
66 @callback
68  config_entry: ConfigEntry, entity_entry: er.RegistryEntry
69 ) -> dict[str, Any] | None:
70  """Migrate DSMR entity entries.
71 
72  - Migrates unique ID for sensors based on entity description name to key.
73  """
74 
75  # Replace names with keys in unique ID
76  for old, new in (
77  ("Power_Consumption", "current_electricity_usage"),
78  ("Power_Production", "current_electricity_delivery"),
79  ("Power_Tariff", "electricity_active_tariff"),
80  ("Energy_Consumption_(tarif_1)", "electricity_used_tariff_1"),
81  ("Energy_Consumption_(tarif_2)", "electricity_used_tariff_2"),
82  ("Energy_Production_(tarif_1)", "electricity_delivered_tariff_1"),
83  ("Energy_Production_(tarif_2)", "electricity_delivered_tariff_2"),
84  ("Power_Consumption_Phase_L1", "instantaneous_active_power_l1_positive"),
85  ("Power_Consumption_Phase_L3", "instantaneous_active_power_l3_positive"),
86  ("Power_Consumption_Phase_L2", "instantaneous_active_power_l2_positive"),
87  ("Power_Production_Phase_L1", "instantaneous_active_power_l1_negative"),
88  ("Power_Production_Phase_L2", "instantaneous_active_power_l2_negative"),
89  ("Power_Production_Phase_L3", "instantaneous_active_power_l3_negative"),
90  ("Short_Power_Failure_Count", "short_power_failure_count"),
91  ("Long_Power_Failure_Count", "long_power_failure_count"),
92  ("Voltage_Sags_Phase_L1", "voltage_sag_l1_count"),
93  ("Voltage_Sags_Phase_L2", "voltage_sag_l2_count"),
94  ("Voltage_Sags_Phase_L3", "voltage_sag_l3_count"),
95  ("Voltage_Swells_Phase_L1", "voltage_swell_l1_count"),
96  ("Voltage_Swells_Phase_L2", "voltage_swell_l2_count"),
97  ("Voltage_Swells_Phase_L3", "voltage_swell_l3_count"),
98  ("Voltage_Phase_L1", "instantaneous_voltage_l1"),
99  ("Voltage_Phase_L2", "instantaneous_voltage_l2"),
100  ("Voltage_Phase_L3", "instantaneous_voltage_l3"),
101  ("Current_Phase_L1", "instantaneous_current_l1"),
102  ("Current_Phase_L2", "instantaneous_current_l2"),
103  ("Current_Phase_L3", "instantaneous_current_l3"),
104  ("Max_power_per_phase", "belgium_max_power_per_phase"),
105  ("Max_current_per_phase", "belgium_max_current_per_phase"),
106  ("Energy_Consumption_(total)", "electricity_imported_total"),
107  ("Energy_Production_(total)", "electricity_exported_total"),
108  ):
109  if entity_entry.unique_id.endswith(old):
110  return {"new_unique_id": entity_entry.unique_id.replace(old, new)}
111 
112  # Replace unique ID for gas sensors, based on DSMR version
113  old = "Gas_Consumption"
114  if entity_entry.unique_id.endswith(old):
115  dsmr_version = config_entry.data[CONF_DSMR_VERSION]
116  if dsmr_version in {"4", "5", "5L"}:
117  return {
118  "new_unique_id": entity_entry.unique_id.replace(
119  old, "hourly_gas_meter_reading"
120  )
121  }
122  if dsmr_version == "5B":
123  return {
124  "new_unique_id": entity_entry.unique_id.replace(
125  old, "belgium_5min_gas_meter_reading"
126  )
127  }
128  if dsmr_version == "2.2":
129  return {
130  "new_unique_id": entity_entry.unique_id.replace(
131  old, "gas_meter_reading"
132  )
133  }
134 
135  # No migration needed
136  return None
dict[str, Any]|None async_migrate_entity_entry(ConfigEntry config_entry, er.RegistryEntry entity_entry)
Definition: __init__.py:69
bool async_setup_entry(HomeAssistant hass, DsmrConfigEntry entry)
Definition: __init__.py:30
None async_update_options(HomeAssistant hass, DsmrConfigEntry entry)
Definition: __init__.py:61
bool async_unload_entry(HomeAssistant hass, DsmrConfigEntry entry)
Definition: __init__.py:49