1
1
"""The AMS HAN meter integration."""
2
+
2
3
from __future__ import annotations
3
4
4
5
import asyncio
6
+ import logging
5
7
from dataclasses import dataclass
6
- import datetime as dt
7
8
from enum import Enum
8
- import logging
9
- from typing import Callable , Mapping , cast
9
+ from typing import TYPE_CHECKING , cast
10
10
11
- from han import common as han_type , meter_connection , obis_map
11
+ from han import common as han_type
12
+ from han import meter_connection , obis_map
12
13
from homeassistant import const as ha_const
13
- from homeassistant .const import Platform , UnitOfReactivePower
14
14
from homeassistant .components import sensor as ha_sensor
15
15
from homeassistant .config_entries import ConfigEntry
16
- from homeassistant .core import CALLBACK_TYPE , callback , HomeAssistant , Event
16
+ from homeassistant .const import Platform , UnitOfReactivePower
17
+ from homeassistant .core import CALLBACK_TYPE , Event , HomeAssistant , callback
17
18
from homeassistant .helpers import entity_registry
18
- from homeassistant .helpers .typing import ConfigType
19
19
20
20
from .const import (
21
21
CONF_CONNECTION_CONFIG ,
25
25
)
26
26
from .metercon import async_setup_meter_mqtt_subscriptions , setup_meter_connection
27
27
28
+ if TYPE_CHECKING :
29
+ import datetime as dt
30
+ from collections .abc import Callable , Mapping
31
+
32
+ CFG_VERSION_1 = 1
33
+ CFG_VERSION_2 = 2
34
+ CFG_VERSION_3 = 1
35
+
28
36
_LOGGER : logging .Logger = logging .getLogger (__name__ )
29
37
30
38
type AmsHanConfigEntry = ConfigEntry [AmsHanData ]
31
39
32
40
33
41
@dataclass
34
42
class AmsHanData :
43
+ """Integration runtime data."""
44
+
35
45
integration : AmsHanIntegration
36
46
37
47
@@ -59,7 +69,7 @@ async def async_setup_receiver(
59
69
) -> None :
60
70
"""Set up MQTT or serial/tcp-ip receiver."""
61
71
connection_type = ConnectionType (config_data [CONF_CONNECTION_TYPE ])
62
- if ConnectionType . MQTT == connection_type :
72
+ if connection_type == ConnectionType . MQTT :
63
73
self ._mqtt_unsubscribe = await async_setup_meter_mqtt_subscriptions (
64
74
hass ,
65
75
config_data [CONF_CONNECTION_CONFIG ],
@@ -110,12 +120,9 @@ def stop_receive(self) -> None:
110
120
self ._mqtt_unsubscribe = None
111
121
112
122
113
- async def async_setup (hass : HomeAssistant , _ : ConfigType ) -> bool :
114
- """Set up the amshan component."""
115
- return True
116
-
117
-
118
- async def async_setup_entry (hass : HomeAssistant , config_entry : AmsHanConfigEntry ) -> bool :
123
+ async def async_setup_entry (
124
+ hass : HomeAssistant , config_entry : AmsHanConfigEntry
125
+ ) -> bool :
119
126
"""Set up amshan from a config entry."""
120
127
integration = AmsHanIntegration ()
121
128
@@ -138,26 +145,28 @@ async def on_hass_stop(event: Event) -> None:
138
145
139
146
config_entry .runtime_data = AmsHanData (integration )
140
147
141
- await hass .config_entries .async_forward_entry_setups (config_entry , [Platform .SENSOR ])
148
+ await hass .config_entries .async_forward_entry_setups (
149
+ config_entry , [Platform .SENSOR ]
150
+ )
142
151
143
152
_LOGGER .debug ("async_setup_entry complete." )
144
153
145
154
return True
146
155
147
156
148
157
async def async_migrate_config_entry (
149
- hass : HomeAssistant , config_entry : ConfigEntry
158
+ hass : HomeAssistant , config_entry : AmsHanConfigEntry
150
159
) -> bool :
151
160
"""Migrate config when ConfigFlow version has changed."""
152
161
initial_version = config_entry .version
153
162
current_data = config_entry .data
154
163
_LOGGER .debug ("Check for config entry migration of version %d" , initial_version )
155
164
156
- if config_entry .version == 1 :
157
- await _async_migrate_entries (
165
+ if config_entry .version == CFG_VERSION_1 :
166
+ _migrate_entries (
158
167
hass , config_entry .entry_id , _migrate_entity_entry_from_v1_to_v2
159
168
)
160
- config_entry .version = 2
169
+ config_entry .version = CFG_VERSION_2
161
170
current_data = {
162
171
CONF_CONNECTION_TYPE : (
163
172
ConnectionType .MQTT
@@ -170,9 +179,9 @@ async def async_migrate_config_entry(
170
179
}
171
180
_LOGGER .debug ("Config entry migrated to version 2" )
172
181
173
- if config_entry .version == 2 :
174
- config_entry .version = 3
175
- await _async_migrate_entries (
182
+ if config_entry .version == CFG_VERSION_2 :
183
+ config_entry .version = CFG_VERSION_3
184
+ _migrate_entries (
176
185
hass , config_entry .entry_id , _migrate_entity_entry_from_v2_to_v3
177
186
)
178
187
_LOGGER .debug ("Config entry migrated to version 3" )
@@ -204,15 +213,15 @@ async def async_unload_entry(
204
213
205
214
@callback
206
215
async def async_config_entry_changed (
207
- hass : HomeAssistant , config_entry : ConfigEntry
208
- ):
216
+ hass : HomeAssistant , config_entry : AmsHanConfigEntry
217
+ ) -> None :
209
218
"""Handle config entry changed callback."""
210
219
_LOGGER .info ("Config entry has changed. Reload integration." )
211
220
await hass .config_entries .async_reload (config_entry .entry_id )
212
221
213
222
214
- def _migrate_entity_entry_from_v1_to_v2 (entity : entity_registry .RegistryEntry ):
215
- def replace_ending (source , old , new ) :
223
+ def _migrate_entity_entry_from_v1_to_v2 (entity : entity_registry .RegistryEntry ) -> dict :
224
+ def replace_ending (source : str , old : str , new : str ) -> str :
216
225
if source .endswith (old ):
217
226
return source [: - len (old )] + new
218
227
return source
@@ -225,7 +234,7 @@ def replace_ending(source, old, new):
225
234
return update
226
235
227
236
228
- def _migrate_entity_entry_from_v2_to_v3 (entity : entity_registry .RegistryEntry ):
237
+ def _migrate_entity_entry_from_v2_to_v3 (entity : entity_registry .RegistryEntry ) -> dict :
229
238
update = {}
230
239
231
240
v3_migrate_fields = [
@@ -279,23 +288,25 @@ def _migrate_entity_entry_from_v2_to_v3(entity: entity_registry.RegistryEntry):
279
288
return update
280
289
281
290
282
- async def _async_migrate_entries (
291
+ def _migrate_entries (
283
292
hass : HomeAssistant ,
284
293
config_entry_id : str ,
285
294
entry_callback : Callable [[entity_registry .RegistryEntry ], dict | None ],
286
295
) -> None :
287
- ent_reg = await entity_registry .async_get_registry (hass )
296
+ ent_reg = entity_registry .async_get (hass )
288
297
289
298
# Workaround:
290
299
# entity_registry.async_migrate_entries fails with:
291
- # " RuntimeError: dictionary keys changed during iteration"
300
+ # RuntimeError: dictionary keys changed during iteration"
292
301
# Try to get all entries from the dictionary before working on them.
293
- # The migration dows not directly change any keys of the registry. Concurrency problem in HA?
302
+ # The migration dows not directly change any keys of the registry.
303
+ # Concurrency problem in HA?
294
304
295
- entries = []
296
- for entry in ent_reg .entities .values ():
297
- if entry .config_entry_id == config_entry_id :
298
- entries .append (entry )
305
+ entries = [
306
+ entry
307
+ for entry in ent_reg .entities .values ()
308
+ if entry .config_entry_id == config_entry_id
309
+ ]
299
310
300
311
for entry in entries :
301
312
updates = entry_callback (entry )
0 commit comments