Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The Fjäråskupan integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 import logging
8 
9 from fjaraskupan import Device
10 
12  BluetoothCallbackMatcher,
13  BluetoothChange,
14  BluetoothScanningMode,
15  BluetoothServiceInfoBleak,
16  async_rediscover_address,
17  async_register_callback,
18 )
19 from homeassistant.config_entries import ConfigEntry
20 from homeassistant.const import Platform
21 from homeassistant.core import HomeAssistant, callback
22 from homeassistant.helpers import device_registry as dr
23 from homeassistant.helpers.device_registry import DeviceInfo
25  async_dispatcher_connect,
26  async_dispatcher_send,
27 )
28 from homeassistant.helpers.entity import Entity
29 from homeassistant.helpers.entity_platform import AddEntitiesCallback
30 
31 from .const import DISPATCH_DETECTION, DOMAIN
32 from .coordinator import FjaraskupanCoordinator
33 
34 PLATFORMS = [
35  Platform.BINARY_SENSOR,
36  Platform.FAN,
37  Platform.LIGHT,
38  Platform.NUMBER,
39  Platform.SENSOR,
40 ]
41 
42 _LOGGER = logging.getLogger(__name__)
43 
44 
45 @dataclass
46 class EntryState:
47  """Store state of config entry."""
48 
49  coordinators: dict[str, FjaraskupanCoordinator]
50 
51 
52 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
53  """Set up Fjäråskupan from a config entry."""
54 
55  state = EntryState({})
56  hass.data.setdefault(DOMAIN, {})
57  hass.data[DOMAIN][entry.entry_id] = state
58 
59  def detection_callback(
60  service_info: BluetoothServiceInfoBleak, change: BluetoothChange
61  ) -> None:
62  if change != BluetoothChange.ADVERTISEMENT:
63  return
64  if data := state.coordinators.get(service_info.address):
65  _LOGGER.debug("Update: %s", service_info)
66  data.detection_callback(service_info)
67  else:
68  _LOGGER.debug("Detected: %s", service_info)
69 
70  device = Device(service_info.device.address)
71  device_info = DeviceInfo(
72  connections={(dr.CONNECTION_BLUETOOTH, service_info.address)},
73  identifiers={(DOMAIN, service_info.address)},
74  manufacturer="Fjäråskupan",
75  name="Fjäråskupan",
76  )
77 
78  coordinator: FjaraskupanCoordinator = FjaraskupanCoordinator(
79  hass, device, device_info
80  )
81  coordinator.detection_callback(service_info)
82 
83  state.coordinators[service_info.address] = coordinator
85  hass, f"{DISPATCH_DETECTION}.{entry.entry_id}", coordinator
86  )
87 
88  entry.async_on_unload(
90  hass,
91  detection_callback,
93  manufacturer_id=20296,
94  manufacturer_data_start=[79, 68, 70, 74, 65, 82],
95  connectable=False,
96  ),
97  BluetoothScanningMode.ACTIVE,
98  )
99  )
100 
101  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
102  return True
103 
104 
105 @callback
107  hass: HomeAssistant,
108  entry: ConfigEntry,
109  async_add_entities: AddEntitiesCallback,
110  constructor: Callable[[FjaraskupanCoordinator], list[Entity]],
111 ) -> None:
112  """Set up a platform with added entities."""
113 
114  entry_state: EntryState = hass.data[DOMAIN][entry.entry_id]
116  entity
117  for coordinator in entry_state.coordinators.values()
118  for entity in constructor(coordinator)
119  )
120 
121  @callback
122  def _detection(coordinator: FjaraskupanCoordinator) -> None:
123  async_add_entities(constructor(coordinator))
124 
125  entry.async_on_unload(
127  hass, f"{DISPATCH_DETECTION}.{entry.entry_id}", _detection
128  )
129  )
130 
131 
132 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
133  """Unload a config entry."""
134  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
135  if unload_ok:
136  hass.data[DOMAIN].pop(entry.entry_id)
137 
138  for device_entry in dr.async_entries_for_config_entry(
139  dr.async_get(hass), entry.entry_id
140  ):
141  for conn in device_entry.connections:
142  if conn[0] == dr.CONNECTION_BLUETOOTH:
143  async_rediscover_address(hass, conn[1])
144 
145  return unload_ok
None async_rediscover_address(HomeAssistant hass, str address)
Definition: api.py:171
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:52
None async_setup_entry_platform(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities, Callable[[FjaraskupanCoordinator], list[Entity]] constructor)
Definition: __init__.py:111
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:132
Callable[[], None] async_register_callback(HomeAssistant hass, Callable[[SsdpServiceInfo, SsdpChange], Coroutine[Any, Any, None]|None] callback, dict[str, str]|None match_dict=None)
Definition: __init__.py:153
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
Definition: dispatcher.py:193