1 """Web socket API for Insteon devices."""
5 from pyinsteon
import devices
6 from pyinsteon.constants
import ALDBStatus
7 import voluptuous
as vol
13 from ..const
import DEVICE_ADDRESS, ID, INSTEON_DEVICE_NOT_FOUND, TYPE
14 from ..utils
import async_device_name
15 from .device
import notify_device_not_found
17 ALDB_RECORD =
"record"
18 ALDB_RECORD_SCHEMA = vol.Schema(
20 vol.Required(
"mem_addr"): int,
21 vol.Required(
"in_use"): bool,
22 vol.Required(
"group"): vol.Range(0, 255),
23 vol.Required(
"is_controller"): bool,
24 vol.Optional(
"highwater"): bool,
25 vol.Required(
"target"): str,
26 vol.Optional(
"target_name"): str,
27 vol.Required(
"data1"): vol.Range(0, 255),
28 vol.Required(
"data2"): vol.Range(0, 255),
29 vol.Required(
"data3"): vol.Range(0, 255),
30 vol.Optional(
"dirty"): bool,
36 """Convert an ALDB record to a dict."""
39 "mem_addr": record.mem_addr,
40 "in_use": record.is_in_use,
41 "is_controller": record.is_controller,
42 "highwater": record.is_high_water_mark,
43 "group": record.group,
44 "target":
str(record.target),
46 "data1": record.data1,
47 "data2": record.data2,
48 "data3": record.data3,
55 """Add default links to an Insteon device."""
56 if device == devices.modem:
57 await device.aldb.async_load()
59 await device.aldb.async_load(refresh=
True)
60 await devices.async_save(workdir=hass.config.config_dir)
64 """Identify if any All-Link Databases are loading."""
66 device.aldb.status == ALDBStatus.LOADING
for _, device
in devices.items()
70 @websocket_api.websocket_command(
{vol.Required(TYPE):
"insteon/aldb/get", vol.Required(DEVICE_ADDRESS): str}
72 @websocket_api.require_admin
73 @websocket_api.async_response
79 """Get the All-Link Database for an Insteon device."""
80 if not (device := devices[msg[DEVICE_ADDRESS]]):
85 aldb = {mem_addr: device.aldb[mem_addr]
for mem_addr
in device.aldb}
86 aldb.update(device.aldb.pending_changes)
87 changed_records =
list(device.aldb.pending_changes.keys())
89 dev_registry = dr.async_get(hass)
93 dev_registry, aldb[mem_addr], mem_addr
in changed_records
98 connection.send_result(msg[ID], records)
101 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/change",
102 vol.Required(DEVICE_ADDRESS): str,
103 vol.Required(ALDB_RECORD): ALDB_RECORD_SCHEMA,
106 @websocket_api.require_admin
107 @websocket_api.async_response
113 """Change an All-Link Database record for an Insteon device."""
114 if not (device := devices[msg[DEVICE_ADDRESS]]):
118 record = msg[ALDB_RECORD]
120 mem_addr=record[
"mem_addr"],
121 in_use=record[
"in_use"],
122 group=record[
"group"],
123 controller=record[
"is_controller"],
124 target=record[
"target"],
125 data1=record[
"data1"],
126 data2=record[
"data2"],
127 data3=record[
"data3"],
129 connection.send_result(msg[ID])
132 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/create",
133 vol.Required(DEVICE_ADDRESS): str,
134 vol.Required(ALDB_RECORD): ALDB_RECORD_SCHEMA,
137 @websocket_api.require_admin
138 @websocket_api.async_response
144 """Create an All-Link Database record for an Insteon device."""
145 if not (device := devices[msg[DEVICE_ADDRESS]]):
149 record = msg[ALDB_RECORD]
151 group=record[
"group"],
152 controller=record[
"is_controller"],
153 target=record[
"target"],
154 data1=record[
"data1"],
155 data2=record[
"data2"],
156 data3=record[
"data3"],
158 connection.send_result(msg[ID])
161 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/write",
162 vol.Required(DEVICE_ADDRESS): str,
165 @websocket_api.require_admin
166 @websocket_api.async_response
172 """Create an All-Link Database record for an Insteon device."""
173 if not (device := devices[msg[DEVICE_ADDRESS]]):
177 await device.aldb.async_write()
179 connection.send_result(msg[ID])
182 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/load",
183 vol.Required(DEVICE_ADDRESS): str,
186 @websocket_api.require_admin
187 @websocket_api.async_response
193 """Create an All-Link Database record for an Insteon device."""
194 if not (device := devices[msg[DEVICE_ADDRESS]]):
199 connection.send_result(msg[ID])
202 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/reset",
203 vol.Required(DEVICE_ADDRESS): str,
206 @websocket_api.require_admin
207 @websocket_api.async_response
213 """Create an All-Link Database record for an Insteon device."""
214 if not (device := devices[msg[DEVICE_ADDRESS]]):
218 device.aldb.clear_pending()
219 connection.send_result(msg[ID])
222 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/add_default_links",
223 vol.Required(DEVICE_ADDRESS): str,
226 @websocket_api.require_admin
227 @websocket_api.async_response
233 """Add the default All-Link Database records for an Insteon device."""
234 if not (device := devices[msg[DEVICE_ADDRESS]]):
238 device.aldb.clear_pending()
239 await device.async_add_default_links()
241 connection.send_result(msg[ID])
244 @websocket_api.websocket_command(
{
vol.Required(TYPE):
"insteon/aldb/notify",
245 vol.Required(DEVICE_ADDRESS): str,
248 @websocket_api.require_admin
249 @websocket_api.async_response
255 """Tell Insteon a new ALDB record was added."""
256 if not (device := devices[msg[DEVICE_ADDRESS]]):
261 def record_added(record, sender, deleted):
262 """Forward ALDB events to websocket."""
263 forward_data = {
"type":
"record_loaded"}
264 connection.send_message(websocket_api.event_message(msg[
"id"], forward_data))
267 def aldb_loaded(status):
268 """Forward ALDB loaded event to websocket."""
270 "type":
"status_changed",
271 "is_loading": status == ALDBStatus.LOADING,
273 connection.send_message(websocket_api.event_message(msg[
"id"], forward_data))
277 """Remove signal listeners."""
278 device.aldb.unsubscribe_record_changed(record_added)
279 device.aldb.unsubscribe_status_changed(aldb_loaded)
281 forward_data = {
"type":
"unsubscribed"}
282 connection.send_message(websocket_api.event_message(msg[
"id"], forward_data))
284 connection.subscriptions[msg[
"id"]] = async_cleanup
285 device.aldb.subscribe_record_changed(record_added)
286 device.aldb.subscribe_status_changed(aldb_loaded)
288 connection.send_result(msg[ID])
291 @websocket_api.websocket_command({vol.Required(TYPE):
"insteon/aldb/notify_all"})
292 @websocket_api.require_admin
293 @websocket_api.async_response
299 """Tell Insteon all ALDBs are loaded."""
302 def aldb_status_changed(status: ALDBStatus) ->
None:
303 """Forward ALDB loaded event to websocket."""
309 connection.send_message(websocket_api.event_message(msg[
"id"], forward_data))
313 """Remove signal listeners."""
314 for device
in devices.values():
315 device.aldb.unsubscribe_status_changed(aldb_status_changed)
317 forward_data = {
"type":
"unsubscribed"}
318 connection.send_message(websocket_api.event_message(msg[
"id"], forward_data))
320 connection.subscriptions[msg[
"id"]] = async_cleanup
321 for device
in devices.values():
322 device.aldb.subscribe_status_changed(aldb_status_changed)
324 connection.send_result(msg[ID])
330 connection.send_message(websocket_api.event_message(msg[
"id"], forward_data))
331
None websocket_create_aldb_record(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_add_default_links(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_change_aldb_record(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_load_aldb(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
def async_aldb_record_to_dict(dev_registry, record, dirty=False)
None websocket_notify_on_aldb_status(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_reset_aldb(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_notify_on_aldb_status_all(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_write_aldb(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
def async_reload_and_save_aldb(hass, device)
None websocket_get_aldb(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
def notify_device_not_found(connection, msg, text)
str async_device_name(dr.DeviceRegistry dev_registry, Address address)
None async_cleanup(HomeAssistant hass, DeviceRegistry dev_reg, entity_registry.EntityRegistry ent_reg)