Skip to content

Commit 85e9d3c

Browse files
authored
Migrate Z-Wave.Me to use runtime_data (#168562)
1 parent fe9db39 commit 85e9d3c

File tree

15 files changed

+163
-202
lines changed

15 files changed

+163
-202
lines changed

homeassistant/components/zwave_me/__init__.py

Lines changed: 15 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,37 @@
11
"""The Z-Wave-Me WS integration."""
22

3-
from zwave_me_ws import ZWaveMe, ZWaveMeData
4-
53
from homeassistant.config_entries import ConfigEntry
6-
from homeassistant.const import CONF_TOKEN, CONF_URL
74
from homeassistant.core import HomeAssistant
85
from homeassistant.exceptions import ConfigEntryNotReady
96
from homeassistant.helpers import device_registry as dr
10-
from homeassistant.helpers.dispatcher import dispatcher_send
11-
12-
from .const import DOMAIN, PLATFORMS, ZWaveMePlatform
137

14-
ZWAVE_ME_PLATFORMS = [platform.value for platform in ZWaveMePlatform]
8+
from .const import PLATFORMS
9+
from .controller import ZWaveMeConfigEntry, ZWaveMeController
1510

1611

17-
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
12+
async def async_setup_entry(hass: HomeAssistant, entry: ZWaveMeConfigEntry) -> bool:
1813
"""Set up Z-Wave-Me from a config entry."""
19-
hass.data.setdefault(DOMAIN, {})
20-
controller = hass.data[DOMAIN][entry.entry_id] = ZWaveMeController(hass, entry)
21-
if await controller.async_establish_connection():
22-
await async_setup_platforms(hass, entry, controller)
23-
registry = dr.async_get(hass)
24-
controller.remove_stale_devices(registry)
25-
return True
26-
raise ConfigEntryNotReady
14+
controller = ZWaveMeController(hass, entry)
15+
16+
if not await controller.async_establish_connection():
17+
raise ConfigEntryNotReady
18+
19+
entry.runtime_data = controller
20+
await async_setup_platforms(hass, entry, controller)
21+
registry = dr.async_get(hass)
22+
controller.remove_stale_devices(registry)
23+
return True
2724

2825

29-
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
26+
async def async_unload_entry(hass: HomeAssistant, entry: ZWaveMeConfigEntry) -> bool:
3027
"""Unload a config entry."""
3128

3229
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
3330
if unload_ok:
34-
controller = hass.data[DOMAIN].pop(entry.entry_id)
35-
await controller.zwave_api.close_ws()
31+
await entry.runtime_data.zwave_api.close_ws()
3632
return unload_ok
3733

3834

39-
class ZWaveMeController:
40-
"""Main ZWave-Me API class."""
41-
42-
def __init__(self, hass: HomeAssistant, config: ConfigEntry) -> None:
43-
"""Create the API instance."""
44-
self.device_ids: set = set()
45-
self._hass = hass
46-
self.config = config
47-
self.zwave_api = ZWaveMe(
48-
on_device_create=self.on_device_create,
49-
on_device_update=self.on_device_update,
50-
on_device_remove=self.on_device_unavailable,
51-
on_device_destroy=self.on_device_destroy,
52-
on_new_device=self.add_device,
53-
token=self.config.data[CONF_TOKEN],
54-
url=self.config.data[CONF_URL],
55-
platforms=ZWAVE_ME_PLATFORMS,
56-
)
57-
self.platforms_inited = False
58-
59-
async def async_establish_connection(self):
60-
"""Get connection status."""
61-
return await self.zwave_api.get_connection()
62-
63-
def add_device(self, device: ZWaveMeData) -> None:
64-
"""Send signal to create device."""
65-
if device.id in self.device_ids:
66-
dispatcher_send(self._hass, f"ZWAVE_ME_INFO_{device.id}", device)
67-
else:
68-
dispatcher_send(
69-
self._hass, f"ZWAVE_ME_NEW_{device.deviceType.upper()}", device
70-
)
71-
self.device_ids.add(device.id)
72-
73-
def on_device_create(self, devices: list[ZWaveMeData]) -> None:
74-
"""Create multiple devices."""
75-
for device in devices:
76-
if device.deviceType in ZWAVE_ME_PLATFORMS and self.platforms_inited:
77-
self.add_device(device)
78-
79-
def on_device_update(self, new_info: ZWaveMeData) -> None:
80-
"""Send signal to update device."""
81-
dispatcher_send(self._hass, f"ZWAVE_ME_INFO_{new_info.id}", new_info)
82-
83-
def on_device_unavailable(self, device_id: str) -> None:
84-
"""Send signal to set device unavailable."""
85-
dispatcher_send(self._hass, f"ZWAVE_ME_UNAVAILABLE_{device_id}")
86-
87-
def on_device_destroy(self, device_id: str) -> None:
88-
"""Send signal to destroy device."""
89-
dispatcher_send(self._hass, f"ZWAVE_ME_DESTROY_{device_id}")
90-
91-
def remove_stale_devices(self, registry: dr.DeviceRegistry):
92-
"""Remove old-format devices in the registry."""
93-
for device_id in self.device_ids:
94-
device = registry.async_get_device(
95-
identifiers={(DOMAIN, f"{self.config.unique_id}-{device_id}")}
96-
)
97-
if device is not None:
98-
registry.async_remove_device(device.id)
99-
100-
10135
async def async_setup_platforms(
10236
hass: HomeAssistant, entry: ConfigEntry, controller: ZWaveMeController
10337
) -> None:

homeassistant/components/zwave_me/binary_sensor.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
BinarySensorEntity,
1010
BinarySensorEntityDescription,
1111
)
12-
from homeassistant.config_entries import ConfigEntry
1312
from homeassistant.core import HomeAssistant, callback
1413
from homeassistant.helpers.dispatcher import async_dispatcher_connect
1514
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
1615

17-
from . import ZWaveMeController
18-
from .const import DOMAIN, ZWaveMePlatform
16+
from .const import ZWaveMePlatform
17+
from .controller import ZWaveMeConfigEntry, ZWaveMeController
1918
from .entity import ZWaveMeEntity
2019

2120
BINARY_SENSORS_MAP: dict[str, BinarySensorEntityDescription] = {
@@ -32,22 +31,22 @@
3231

3332
async def async_setup_entry(
3433
hass: HomeAssistant,
35-
config_entry: ConfigEntry,
34+
config_entry: ZWaveMeConfigEntry,
3635
async_add_entities: AddConfigEntryEntitiesCallback,
3736
) -> None:
3837
"""Set up the binary sensor platform."""
3938

4039
@callback
4140
def add_new_device(new_device: ZWaveMeData) -> None:
42-
controller: ZWaveMeController = hass.data[DOMAIN][config_entry.entry_id]
43-
description = BINARY_SENSORS_MAP.get(
44-
new_device.probeType, BINARY_SENSORS_MAP["generic"]
45-
)
46-
sensor = ZWaveMeBinarySensor(controller, new_device, description)
47-
4841
async_add_entities(
4942
[
50-
sensor,
43+
ZWaveMeBinarySensor(
44+
config_entry.runtime_data,
45+
new_device,
46+
BINARY_SENSORS_MAP.get(
47+
new_device.probeType, BINARY_SENSORS_MAP["generic"]
48+
),
49+
)
5150
]
5251
)
5352

homeassistant/components/zwave_me/button.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,27 @@
11
"""Representation of a toggleButton."""
22

33
from homeassistant.components.button import ButtonEntity
4-
from homeassistant.config_entries import ConfigEntry
54
from homeassistant.core import HomeAssistant, callback
65
from homeassistant.helpers.dispatcher import async_dispatcher_connect
76
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
87

9-
from .const import DOMAIN, ZWaveMePlatform
8+
from .const import ZWaveMePlatform
9+
from .controller import ZWaveMeConfigEntry
1010
from .entity import ZWaveMeEntity
1111

1212
DEVICE_NAME = ZWaveMePlatform.BUTTON
1313

1414

1515
async def async_setup_entry(
1616
hass: HomeAssistant,
17-
config_entry: ConfigEntry,
17+
config_entry: ZWaveMeConfigEntry,
1818
async_add_entities: AddConfigEntryEntitiesCallback,
1919
) -> None:
2020
"""Set up the number platform."""
2121

2222
@callback
2323
def add_new_device(new_device):
24-
controller = hass.data[DOMAIN][config_entry.entry_id]
25-
button = ZWaveMeButton(controller, new_device)
26-
27-
async_add_entities(
28-
[
29-
button,
30-
]
31-
)
24+
async_add_entities([ZWaveMeButton(config_entry.runtime_data, new_device)])
3225

3326
config_entry.async_on_unload(
3427
async_dispatcher_connect(

homeassistant/components/zwave_me/climate.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
ClimateEntityFeature,
1212
HVACMode,
1313
)
14-
from homeassistant.config_entries import ConfigEntry
1514
from homeassistant.const import ATTR_TEMPERATURE
1615
from homeassistant.core import HomeAssistant, callback
1716
from homeassistant.helpers.dispatcher import async_dispatcher_connect
1817
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
1918

20-
from .const import DOMAIN, ZWaveMePlatform
19+
from .const import ZWaveMePlatform
20+
from .controller import ZWaveMeConfigEntry
2121
from .entity import ZWaveMeEntity
2222

2323
TEMPERATURE_DEFAULT_STEP = 0.5
@@ -27,22 +27,15 @@
2727

2828
async def async_setup_entry(
2929
hass: HomeAssistant,
30-
config_entry: ConfigEntry,
30+
config_entry: ZWaveMeConfigEntry,
3131
async_add_entities: AddConfigEntryEntitiesCallback,
3232
) -> None:
3333
"""Set up the climate platform."""
3434

3535
@callback
3636
def add_new_device(new_device: ZWaveMeData) -> None:
3737
"""Add a new device."""
38-
controller = hass.data[DOMAIN][config_entry.entry_id]
39-
climate = ZWaveMeClimate(controller, new_device)
40-
41-
async_add_entities(
42-
[
43-
climate,
44-
]
45-
)
38+
async_add_entities([ZWaveMeClimate(config_entry.runtime_data, new_device)])
4639

4740
config_entry.async_on_unload(
4841
async_dispatcher_connect(
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""The Z-Wave-Me WS controller."""
2+
3+
from zwave_me_ws import ZWaveMe, ZWaveMeData
4+
5+
from homeassistant.config_entries import ConfigEntry
6+
from homeassistant.const import CONF_TOKEN, CONF_URL
7+
from homeassistant.core import HomeAssistant
8+
from homeassistant.helpers import device_registry as dr
9+
from homeassistant.helpers.dispatcher import dispatcher_send
10+
11+
from .const import DOMAIN, ZWaveMePlatform
12+
13+
type ZWaveMeConfigEntry = ConfigEntry[ZWaveMeController]
14+
15+
ZWAVE_ME_PLATFORMS = [platform.value for platform in ZWaveMePlatform]
16+
17+
18+
class ZWaveMeController:
19+
"""Main ZWave-Me API class."""
20+
21+
def __init__(self, hass: HomeAssistant, config: ZWaveMeConfigEntry) -> None:
22+
"""Create the API instance."""
23+
self.device_ids: set[str] = set()
24+
self._hass = hass
25+
self.config = config
26+
self.zwave_api = ZWaveMe(
27+
on_device_create=self.on_device_create,
28+
on_device_update=self.on_device_update,
29+
on_device_remove=self.on_device_unavailable,
30+
on_device_destroy=self.on_device_destroy,
31+
on_new_device=self.add_device,
32+
token=self.config.data[CONF_TOKEN],
33+
url=self.config.data[CONF_URL],
34+
platforms=ZWAVE_ME_PLATFORMS,
35+
)
36+
self.platforms_inited = False
37+
38+
async def async_establish_connection(self) -> bool:
39+
"""Get connection status."""
40+
return await self.zwave_api.get_connection()
41+
42+
def add_device(self, device: ZWaveMeData) -> None:
43+
"""Send signal to create device."""
44+
if device.id in self.device_ids:
45+
dispatcher_send(self._hass, f"ZWAVE_ME_INFO_{device.id}", device)
46+
else:
47+
dispatcher_send(
48+
self._hass, f"ZWAVE_ME_NEW_{device.deviceType.upper()}", device
49+
)
50+
self.device_ids.add(device.id)
51+
52+
def on_device_create(self, devices: list[ZWaveMeData]) -> None:
53+
"""Create multiple devices."""
54+
for device in devices:
55+
if device.deviceType in ZWAVE_ME_PLATFORMS and self.platforms_inited:
56+
self.add_device(device)
57+
58+
def on_device_update(self, new_info: ZWaveMeData) -> None:
59+
"""Send signal to update device."""
60+
dispatcher_send(self._hass, f"ZWAVE_ME_INFO_{new_info.id}", new_info)
61+
62+
def on_device_unavailable(self, device_id: str) -> None:
63+
"""Send signal to set device unavailable."""
64+
dispatcher_send(self._hass, f"ZWAVE_ME_UNAVAILABLE_{device_id}")
65+
66+
def on_device_destroy(self, device_id: str) -> None:
67+
"""Send signal to destroy device."""
68+
dispatcher_send(self._hass, f"ZWAVE_ME_DESTROY_{device_id}")
69+
70+
def remove_stale_devices(self, registry: dr.DeviceRegistry):
71+
"""Remove old-format devices in the registry."""
72+
for device_id in self.device_ids:
73+
device = registry.async_get_device(
74+
identifiers={(DOMAIN, f"{self.config.unique_id}-{device_id}")}
75+
)
76+
if device is not None:
77+
registry.async_remove_device(device.id)

homeassistant/components/zwave_me/cover.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,27 @@
99
CoverEntity,
1010
CoverEntityFeature,
1111
)
12-
from homeassistant.config_entries import ConfigEntry
1312
from homeassistant.core import HomeAssistant, callback
1413
from homeassistant.helpers.dispatcher import async_dispatcher_connect
1514
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
1615

17-
from .const import DOMAIN, ZWaveMePlatform
16+
from .const import ZWaveMePlatform
17+
from .controller import ZWaveMeConfigEntry
1818
from .entity import ZWaveMeEntity
1919

2020
DEVICE_NAME = ZWaveMePlatform.COVER
2121

2222

2323
async def async_setup_entry(
2424
hass: HomeAssistant,
25-
config_entry: ConfigEntry,
25+
config_entry: ZWaveMeConfigEntry,
2626
async_add_entities: AddConfigEntryEntitiesCallback,
2727
) -> None:
2828
"""Set up the cover platform."""
2929

3030
@callback
3131
def add_new_device(new_device):
32-
controller = hass.data[DOMAIN][config_entry.entry_id]
33-
cover = ZWaveMeCover(controller, new_device)
34-
35-
async_add_entities(
36-
[
37-
cover,
38-
]
39-
)
32+
async_add_entities([ZWaveMeCover(config_entry.runtime_data, new_device)])
4033

4134
config_entry.async_on_unload(
4235
async_dispatcher_connect(

homeassistant/components/zwave_me/entity.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
from homeassistant.helpers.entity import Entity
99

1010
from .const import DOMAIN
11+
from .controller import ZWaveMeController
1112

1213

1314
class ZWaveMeEntity(Entity):
1415
"""Representation of a ZWaveMe device."""
1516

16-
def __init__(self, controller, device):
17+
def __init__(self, controller: ZWaveMeController, device: ZWaveMeData) -> None:
1718
"""Initialize the device."""
1819
self.controller = controller
1920
self.device = device

0 commit comments

Comments
 (0)