mirror of https://github.com/home-assistant/core
197 lines
6.0 KiB
Python
197 lines
6.0 KiB
Python
"""API interface to get an Insteon device."""
|
|
|
|
from typing import Any
|
|
|
|
from pyinsteon import devices
|
|
from pyinsteon.address import Address
|
|
from pyinsteon.constants import DeviceAction
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components import websocket_api
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers import device_registry as dr
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|
|
|
from ..const import (
|
|
DEVICE_ADDRESS,
|
|
DEVICE_ID,
|
|
DOMAIN,
|
|
HA_DEVICE_NOT_FOUND,
|
|
ID,
|
|
INSTEON_DEVICE_NOT_FOUND,
|
|
MULTIPLE,
|
|
SIGNAL_REMOVE_HA_DEVICE,
|
|
SIGNAL_REMOVE_INSTEON_DEVICE,
|
|
SIGNAL_REMOVE_X10_DEVICE,
|
|
TYPE,
|
|
)
|
|
from ..schemas import build_x10_schema
|
|
from ..utils import compute_device_name
|
|
from .config import add_x10_device, remove_device_override, remove_x10_device
|
|
|
|
X10_DEVICE = "x10_device"
|
|
X10_DEVICE_SCHEMA = build_x10_schema()
|
|
REMOVE_ALL_REFS = "remove_all_refs"
|
|
|
|
|
|
async def async_add_devices(address, multiple):
|
|
"""Add one or more Insteon devices."""
|
|
async for _ in devices.async_add_device(address=address, multiple=multiple):
|
|
pass
|
|
|
|
|
|
def get_insteon_device_from_ha_device(ha_device):
|
|
"""Return the Insteon device from an HA device."""
|
|
for identifier in ha_device.identifiers:
|
|
if len(identifier) > 1 and identifier[0] == DOMAIN and devices[identifier[1]]:
|
|
return devices[identifier[1]]
|
|
return None
|
|
|
|
|
|
def notify_device_not_found(connection, msg, text):
|
|
"""Notify the caller that the device was not found."""
|
|
connection.send_message(
|
|
websocket_api.error_message(msg[ID], websocket_api.const.ERR_NOT_FOUND, text)
|
|
)
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{vol.Required(TYPE): "insteon/device/get", vol.Required(DEVICE_ID): str}
|
|
)
|
|
@websocket_api.require_admin
|
|
@websocket_api.async_response
|
|
async def websocket_get_device(
|
|
hass: HomeAssistant,
|
|
connection: websocket_api.connection.ActiveConnection,
|
|
msg: dict[str, Any],
|
|
) -> None:
|
|
"""Get an Insteon device."""
|
|
dev_registry = dr.async_get(hass)
|
|
if not (ha_device := dev_registry.async_get(msg[DEVICE_ID])):
|
|
notify_device_not_found(connection, msg, HA_DEVICE_NOT_FOUND)
|
|
return
|
|
if not (device := get_insteon_device_from_ha_device(ha_device)):
|
|
notify_device_not_found(connection, msg, INSTEON_DEVICE_NOT_FOUND)
|
|
return
|
|
ha_name = compute_device_name(ha_device)
|
|
device_info = {
|
|
"name": ha_name,
|
|
"address": str(device.address),
|
|
"is_battery": device.is_battery,
|
|
"aldb_status": str(device.aldb.status),
|
|
}
|
|
connection.send_result(msg[ID], device_info)
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "insteon/device/add",
|
|
vol.Required(MULTIPLE): bool,
|
|
vol.Optional(DEVICE_ADDRESS): str,
|
|
}
|
|
)
|
|
@websocket_api.require_admin
|
|
@websocket_api.async_response
|
|
async def websocket_add_device(
|
|
hass: HomeAssistant,
|
|
connection: websocket_api.connection.ActiveConnection,
|
|
msg: dict[str, Any],
|
|
) -> None:
|
|
"""Add one or more Insteon devices."""
|
|
|
|
@callback
|
|
def linking_complete(address: str, action: DeviceAction):
|
|
"""Forward device events to websocket."""
|
|
if action == DeviceAction.COMPLETED:
|
|
forward_data = {"type": "linking_stopped", "address": ""}
|
|
else:
|
|
return
|
|
connection.send_message(websocket_api.event_message(msg["id"], forward_data))
|
|
|
|
@callback
|
|
def async_cleanup() -> None:
|
|
"""Remove signal listeners."""
|
|
devices.unsubscribe(linking_complete)
|
|
|
|
connection.subscriptions[msg["id"]] = async_cleanup
|
|
devices.subscribe(linking_complete)
|
|
|
|
async for address in devices.async_add_device(
|
|
address=msg.get(DEVICE_ADDRESS), multiple=msg[MULTIPLE]
|
|
):
|
|
forward_data = {"type": "device_added", "address": str(address)}
|
|
connection.send_message(websocket_api.event_message(msg["id"], forward_data))
|
|
|
|
connection.send_result(msg[ID])
|
|
|
|
|
|
@websocket_api.websocket_command({vol.Required(TYPE): "insteon/device/add/cancel"})
|
|
@websocket_api.require_admin
|
|
@websocket_api.async_response
|
|
async def websocket_cancel_add_device(
|
|
hass: HomeAssistant,
|
|
connection: websocket_api.connection.ActiveConnection,
|
|
msg: dict[str, Any],
|
|
) -> None:
|
|
"""Cancel the Insteon all-linking process."""
|
|
await devices.async_cancel_all_linking()
|
|
connection.send_result(msg[ID])
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "insteon/device/remove",
|
|
vol.Required(DEVICE_ADDRESS): str,
|
|
vol.Required(REMOVE_ALL_REFS): bool,
|
|
}
|
|
)
|
|
@websocket_api.require_admin
|
|
@websocket_api.async_response
|
|
async def websocket_remove_device(
|
|
hass: HomeAssistant,
|
|
connection: websocket_api.connection.ActiveConnection,
|
|
msg: dict[str, Any],
|
|
) -> None:
|
|
"""Remove an Insteon device."""
|
|
|
|
address = msg[DEVICE_ADDRESS]
|
|
remove_all_refs = msg[REMOVE_ALL_REFS]
|
|
if address.startswith("X10"):
|
|
_, housecode, unitcode = address.split(".")
|
|
unitcode = int(unitcode)
|
|
async_dispatcher_send(hass, SIGNAL_REMOVE_X10_DEVICE, housecode, unitcode)
|
|
remove_x10_device(hass, housecode, unitcode)
|
|
else:
|
|
address = Address(address)
|
|
remove_device_override(hass, address)
|
|
async_dispatcher_send(hass, SIGNAL_REMOVE_HA_DEVICE, address)
|
|
async_dispatcher_send(
|
|
hass, SIGNAL_REMOVE_INSTEON_DEVICE, address, remove_all_refs
|
|
)
|
|
|
|
connection.send_result(msg[ID])
|
|
|
|
|
|
@websocket_api.websocket_command(
|
|
{
|
|
vol.Required(TYPE): "insteon/device/add_x10",
|
|
vol.Required(X10_DEVICE): X10_DEVICE_SCHEMA,
|
|
}
|
|
)
|
|
@websocket_api.require_admin
|
|
@websocket_api.async_response
|
|
async def websocket_add_x10_device(
|
|
hass: HomeAssistant,
|
|
connection: websocket_api.connection.ActiveConnection,
|
|
msg: dict[str, Any],
|
|
) -> None:
|
|
"""Get the schema for the X10 devices configuration."""
|
|
x10_device = msg[X10_DEVICE]
|
|
try:
|
|
add_x10_device(hass, x10_device)
|
|
except ValueError:
|
|
connection.send_error(msg[ID], code="duplicate", message="Duplicate X10 device")
|
|
return
|
|
|
|
connection.send_result(msg[ID])
|