Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Connect to a MySensors gateway via pymysensors API."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable, Mapping
6 import logging
7 
8 from mysensors import BaseAsyncGateway
9 
10 from homeassistant.config_entries import ConfigEntry
11 from homeassistant.const import Platform
12 from homeassistant.core import HomeAssistant, callback
13 from homeassistant.helpers.device_registry import DeviceEntry
14 
15 from .const import (
16  ATTR_DEVICES,
17  DOMAIN,
18  MYSENSORS_DISCOVERED_NODES,
19  MYSENSORS_GATEWAYS,
20  MYSENSORS_ON_UNLOAD,
21  PLATFORMS,
22  DevId,
23  DiscoveryInfo,
24  SensorType,
25 )
26 from .entity import MySensorsChildEntity, get_mysensors_devices
27 from .gateway import finish_setup, gw_stop, setup_gateway
28 
29 _LOGGER = logging.getLogger(__name__)
30 
31 DATA_HASS_CONFIG = "hass_config"
32 
33 
34 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
35  """Set up an instance of the MySensors integration.
36 
37  Every instance has a connection to exactly one Gateway.
38  """
39  gateway = await setup_gateway(hass, entry)
40 
41  if not gateway:
42  _LOGGER.error("Gateway setup failed for %s", entry.data)
43  return False
44 
45  mysensors_data = hass.data.setdefault(DOMAIN, {})
46  if MYSENSORS_GATEWAYS not in mysensors_data:
47  mysensors_data[MYSENSORS_GATEWAYS] = {}
48  mysensors_data[MYSENSORS_GATEWAYS][entry.entry_id] = gateway
49 
50  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
51  await finish_setup(hass, entry, gateway)
52 
53  return True
54 
55 
56 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
57  """Remove an instance of the MySensors integration."""
58 
59  gateway: BaseAsyncGateway = hass.data[DOMAIN][MYSENSORS_GATEWAYS][entry.entry_id]
60 
61  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
62  if not unload_ok:
63  return False
64 
65  key = MYSENSORS_ON_UNLOAD.format(entry.entry_id)
66  if key in hass.data[DOMAIN]:
67  for fnct in hass.data[DOMAIN][key]:
68  fnct()
69 
70  hass.data[DOMAIN].pop(key)
71 
72  del hass.data[DOMAIN][MYSENSORS_GATEWAYS][entry.entry_id]
73  hass.data[DOMAIN].pop(MYSENSORS_DISCOVERED_NODES.format(entry.entry_id), None)
74 
75  await gw_stop(hass, entry, gateway)
76  return True
77 
78 
80  hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
81 ) -> bool:
82  """Remove a MySensors config entry from a device."""
83  gateway: BaseAsyncGateway = hass.data[DOMAIN][MYSENSORS_GATEWAYS][
84  config_entry.entry_id
85  ]
86  device_id = next(
87  device_id for domain, device_id in device_entry.identifiers if domain == DOMAIN
88  )
89  node_id = int(device_id.partition("-")[2])
90  gateway.sensors.pop(node_id, None)
91  gateway.tasks.persistence.need_save = True
92 
93  # remove node from discovered nodes
94  hass.data[DOMAIN].setdefault(
95  MYSENSORS_DISCOVERED_NODES.format(config_entry.entry_id), set()
96  ).remove(node_id)
97 
98  return True
99 
100 
101 @callback
103  hass: HomeAssistant,
104  domain: Platform, # hass platform name
105  discovery_info: DiscoveryInfo,
106  device_class: type[MySensorsChildEntity]
107  | Mapping[SensorType, type[MySensorsChildEntity]],
108  device_args: (
109  tuple | None
110  ) = None, # extra arguments that will be given to the entity constructor
111  async_add_entities: Callable | None = None,
112 ) -> list[MySensorsChildEntity] | None:
113  """Set up a MySensors platform.
114 
115  Sets up a bunch of instances of a single platform that is supported by this
116  integration.
117 
118  The function is given a list of device ids, each one describing an instance
119  to set up. The function is also given a class.
120 
121  A new instance of the class is created for every device id, and the device
122  id is given to the constructor of the class.
123  """
124  if device_args is None:
125  device_args = ()
126  new_devices: list[MySensorsChildEntity] = []
127  new_dev_ids: list[DevId] = discovery_info[ATTR_DEVICES]
128  for dev_id in new_dev_ids:
129  devices: dict[DevId, MySensorsChildEntity] = get_mysensors_devices(hass, domain)
130  if dev_id in devices:
131  _LOGGER.debug(
132  "Skipping setup of %s for platform %s as it already exists",
133  dev_id,
134  domain,
135  )
136  continue
137  gateway_id, node_id, child_id, value_type = dev_id
138  gateway: BaseAsyncGateway = hass.data[DOMAIN][MYSENSORS_GATEWAYS][gateway_id]
139 
140  if isinstance(device_class, dict):
141  child = gateway.sensors[node_id].children[child_id]
142  s_type = gateway.const.Presentation(child.type).name
143  device_class_copy = device_class[s_type]
144  else:
145  device_class_copy = device_class
146 
147  args_copy = (*device_args, gateway_id, gateway, node_id, child_id, value_type)
148  devices[dev_id] = device_class_copy(*args_copy)
149  new_devices.append(devices[dev_id])
150  if new_devices:
151  _LOGGER.debug("Adding new devices: %s", new_devices)
152  if async_add_entities is not None:
153  async_add_entities(new_devices)
154  return new_devices
bool remove(self, _T matcher)
Definition: match.py:214
None finish_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:203
dict[DevId, MySensorsChildEntity] get_mysensors_devices(HomeAssistant hass, Platform domain)
Definition: entity.py:139
BaseAsyncGateway|None setup_gateway(HomeAssistant hass, ConfigEntry entry)
Definition: gateway.py:130
None gw_stop(HomeAssistant hass, ConfigEntry entry, BaseAsyncGateway gateway)
Definition: gateway.py:266
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:34
list[MySensorsChildEntity]|None setup_mysensors_platform(HomeAssistant hass, Platform domain, DiscoveryInfo discovery_info, type[MySensorsChildEntity]|Mapping[SensorType, type[MySensorsChildEntity]] device_class,(tuple|None) device_args=None, Callable|None async_add_entities=None)
Definition: __init__.py:112
bool async_remove_config_entry_device(HomeAssistant hass, ConfigEntry config_entry, DeviceEntry device_entry)
Definition: __init__.py:81
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:56