Home Assistant Unofficial Reference 2024.12.1
device.py
Go to the documentation of this file.
1 """API interface to get an Insteon device."""
2 
3 from typing import Any
4 
5 from pyinsteon import devices
6 from pyinsteon.address import Address
7 from pyinsteon.constants import DeviceAction
8 import voluptuous as vol
9 
10 from homeassistant.components import websocket_api
11 from homeassistant.core import HomeAssistant, callback
12 from homeassistant.helpers import device_registry as dr
13 from homeassistant.helpers.dispatcher import async_dispatcher_send
14 
15 from ..const import (
16  DEVICE_ADDRESS,
17  DEVICE_ID,
18  DOMAIN,
19  HA_DEVICE_NOT_FOUND,
20  ID,
21  INSTEON_DEVICE_NOT_FOUND,
22  MULTIPLE,
23  SIGNAL_REMOVE_HA_DEVICE,
24  SIGNAL_REMOVE_INSTEON_DEVICE,
25  SIGNAL_REMOVE_X10_DEVICE,
26  TYPE,
27 )
28 from ..schemas import build_x10_schema
29 from ..utils import compute_device_name
30 from .config import add_x10_device, remove_device_override, remove_x10_device
31 
32 X10_DEVICE = "x10_device"
33 X10_DEVICE_SCHEMA = build_x10_schema()
34 REMOVE_ALL_REFS = "remove_all_refs"
35 
36 
37 async def async_add_devices(address, multiple):
38  """Add one or more Insteon devices."""
39  async for _ in devices.async_add_device(address=address, multiple=multiple):
40  pass
41 
42 
44  """Return the Insteon device from an HA device."""
45  for identifier in ha_device.identifiers:
46  if len(identifier) > 1 and identifier[0] == DOMAIN and devices[identifier[1]]:
47  return devices[identifier[1]]
48  return None
49 
50 
51 def notify_device_not_found(connection, msg, text):
52  """Notify the caller that the device was not found."""
53  connection.send_message(
54  websocket_api.error_message(msg[ID], websocket_api.const.ERR_NOT_FOUND, text)
55  )
56 
57 
58 @websocket_api.websocket_command( {vol.Required(TYPE): "insteon/device/get", vol.Required(DEVICE_ID): str}
59 )
60 @websocket_api.require_admin
61 @websocket_api.async_response
62 async def websocket_get_device(
63  hass: HomeAssistant,
65  msg: dict[str, Any],
66 ) -> None:
67  """Get an Insteon device."""
68  dev_registry = dr.async_get(hass)
69  if not (ha_device := dev_registry.async_get(msg[DEVICE_ID])):
70  notify_device_not_found(connection, msg, HA_DEVICE_NOT_FOUND)
71  return
72  if not (device := get_insteon_device_from_ha_device(ha_device)):
73  notify_device_not_found(connection, msg, INSTEON_DEVICE_NOT_FOUND)
74  return
75  ha_name = compute_device_name(ha_device)
76  device_info = {
77  "name": ha_name,
78  "address": str(device.address),
79  "is_battery": device.is_battery,
80  "aldb_status": str(device.aldb.status),
81  }
82  connection.send_result(msg[ID], device_info)
83 
84 
85 @websocket_api.websocket_command( { vol.Required(TYPE): "insteon/device/add",
86  vol.Required(MULTIPLE): bool,
87  vol.Optional(DEVICE_ADDRESS): str,
88  }
89 )
90 @websocket_api.require_admin
91 @websocket_api.async_response
92 async def websocket_add_device(
93  hass: HomeAssistant,
95  msg: dict[str, Any],
96 ) -> None:
97  """Add one or more Insteon devices."""
98 
99  @callback
100  def linking_complete(address: str, action: DeviceAction):
101  """Forward device events to websocket."""
102  if action == DeviceAction.COMPLETED:
103  forward_data = {"type": "linking_stopped", "address": ""}
104  else:
105  return
106  connection.send_message(websocket_api.event_message(msg["id"], forward_data))
107 
108  @callback
109  def async_cleanup() -> None:
110  """Remove signal listeners."""
111  devices.unsubscribe(linking_complete)
112 
113  connection.subscriptions[msg["id"]] = async_cleanup
114  devices.subscribe(linking_complete)
115 
116  async for address in devices.async_add_device(
117  address=msg.get(DEVICE_ADDRESS), multiple=msg[MULTIPLE]
118  ):
119  forward_data = {"type": "device_added", "address": str(address)}
120  connection.send_message(websocket_api.event_message(msg["id"], forward_data))
121 
122  connection.send_result(msg[ID])
123 
124 
125 @websocket_api.websocket_command({vol.Required(TYPE): "insteon/device/add/cancel"})
126 @websocket_api.require_admin
127 @websocket_api.async_response
129  hass: HomeAssistant,
131  msg: dict[str, Any],
132 ) -> None:
133  """Cancel the Insteon all-linking process."""
134  await devices.async_cancel_all_linking()
135  connection.send_result(msg[ID])
136 
137 
138 @websocket_api.websocket_command( { vol.Required(TYPE): "insteon/device/remove",
139  vol.Required(DEVICE_ADDRESS): str,
140  vol.Required(REMOVE_ALL_REFS): bool,
141  }
142 )
143 @websocket_api.require_admin
144 @websocket_api.async_response
145 async def websocket_remove_device(
146  hass: HomeAssistant,
148  msg: dict[str, Any],
149 ) -> None:
150  """Remove an Insteon device."""
151 
152  address = msg[DEVICE_ADDRESS]
153  remove_all_refs = msg[REMOVE_ALL_REFS]
154  if address.startswith("X10"):
155  _, housecode, unitcode = address.split(".")
156  unitcode = int(unitcode)
157  async_dispatcher_send(hass, SIGNAL_REMOVE_X10_DEVICE, housecode, unitcode)
158  remove_x10_device(hass, housecode, unitcode)
159  else:
160  address = Address(address)
161  remove_device_override(hass, address)
162  async_dispatcher_send(hass, SIGNAL_REMOVE_HA_DEVICE, address)
164  hass, SIGNAL_REMOVE_INSTEON_DEVICE, address, remove_all_refs
165  )
166 
167  connection.send_result(msg[ID])
168 
169 
170 @websocket_api.websocket_command( { vol.Required(TYPE): "insteon/device/add_x10",
171  vol.Required(X10_DEVICE): X10_DEVICE_SCHEMA,
172  }
173 )
174 @websocket_api.require_admin
175 @websocket_api.async_response
176 async def websocket_add_x10_device(
177  hass: HomeAssistant,
179  msg: dict[str, Any],
180 ) -> None:
181  """Get the schema for the X10 devices configuration."""
182  x10_device = msg[X10_DEVICE]
183  try:
184  add_x10_device(hass, x10_device)
185  except ValueError:
186  connection.send_error(msg[ID], code="duplicate", message="Duplicate X10 device")
187  return
188 
189  connection.send_result(msg[ID])
190 
def remove_x10_device(HomeAssistant hass, str housecode, int unitcode)
Definition: config.py:91
def remove_device_override(HomeAssistant hass, Address address)
Definition: config.py:126
def add_x10_device(HomeAssistant hass, X10DeviceConfig x10_device)
Definition: config.py:72
None websocket_cancel_add_device(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
Definition: device.py:135
None websocket_add_x10_device(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
Definition: device.py:187
def async_add_devices(address, multiple)
Definition: device.py:37
def get_insteon_device_from_ha_device(ha_device)
Definition: device.py:43
None websocket_add_device(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
Definition: device.py:99
None websocket_get_device(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
Definition: device.py:67
def notify_device_not_found(connection, msg, text)
Definition: device.py:51
None websocket_remove_device(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
Definition: device.py:154
def build_x10_schema(housecode=vol.UNDEFINED, unitcode=vol.UNDEFINED, platform=vol.UNDEFINED, dim_steps=22)
Definition: schemas.py:96
None async_cleanup(HomeAssistant hass, DeviceRegistry dev_reg, entity_registry.EntityRegistry ent_reg)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
Definition: dispatcher.py:193