mirror of
https://github.com/home-assistant/core
synced 2024-08-02 23:40:32 +02:00
11f80762ea
* Upgrade ness alarm dependencies to fix #74571 * Update requirements
152 lines
4.5 KiB
Python
152 lines
4.5 KiB
Python
"""Support for Ness D8X/D16X devices."""
|
|
from collections import namedtuple
|
|
import datetime
|
|
|
|
from nessclient import ArmingState, Client
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components.binary_sensor import (
|
|
DEVICE_CLASSES_SCHEMA as BINARY_SENSOR_DEVICE_CLASSES_SCHEMA,
|
|
BinarySensorDeviceClass,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_CODE,
|
|
ATTR_STATE,
|
|
CONF_HOST,
|
|
CONF_SCAN_INTERVAL,
|
|
EVENT_HOMEASSISTANT_STOP,
|
|
Platform,
|
|
)
|
|
from homeassistant.core import HomeAssistant, ServiceCall
|
|
from homeassistant.helpers import config_validation as cv
|
|
from homeassistant.helpers.discovery import async_load_platform
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|
from homeassistant.helpers.typing import ConfigType
|
|
|
|
DOMAIN = "ness_alarm"
|
|
DATA_NESS = "ness_alarm"
|
|
|
|
CONF_DEVICE_PORT = "port"
|
|
CONF_INFER_ARMING_STATE = "infer_arming_state"
|
|
CONF_ZONES = "zones"
|
|
CONF_ZONE_NAME = "name"
|
|
CONF_ZONE_TYPE = "type"
|
|
CONF_ZONE_ID = "id"
|
|
ATTR_OUTPUT_ID = "output_id"
|
|
DEFAULT_SCAN_INTERVAL = datetime.timedelta(minutes=1)
|
|
DEFAULT_INFER_ARMING_STATE = False
|
|
|
|
SIGNAL_ZONE_CHANGED = "ness_alarm.zone_changed"
|
|
SIGNAL_ARMING_STATE_CHANGED = "ness_alarm.arming_state_changed"
|
|
|
|
ZoneChangedData = namedtuple("ZoneChangedData", ["zone_id", "state"])
|
|
|
|
DEFAULT_ZONE_TYPE = BinarySensorDeviceClass.MOTION
|
|
ZONE_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Required(CONF_ZONE_NAME): cv.string,
|
|
vol.Required(CONF_ZONE_ID): cv.positive_int,
|
|
vol.Optional(
|
|
CONF_ZONE_TYPE, default=DEFAULT_ZONE_TYPE
|
|
): BINARY_SENSOR_DEVICE_CLASSES_SCHEMA,
|
|
}
|
|
)
|
|
|
|
CONFIG_SCHEMA = vol.Schema(
|
|
{
|
|
DOMAIN: vol.Schema(
|
|
{
|
|
vol.Required(CONF_HOST): cv.string,
|
|
vol.Required(CONF_DEVICE_PORT): cv.port,
|
|
vol.Optional(
|
|
CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL
|
|
): cv.positive_time_period,
|
|
vol.Optional(CONF_ZONES, default=[]): vol.All(
|
|
cv.ensure_list, [ZONE_SCHEMA]
|
|
),
|
|
vol.Optional(
|
|
CONF_INFER_ARMING_STATE, default=DEFAULT_INFER_ARMING_STATE
|
|
): cv.boolean,
|
|
}
|
|
)
|
|
},
|
|
extra=vol.ALLOW_EXTRA,
|
|
)
|
|
|
|
SERVICE_PANIC = "panic"
|
|
SERVICE_AUX = "aux"
|
|
|
|
SERVICE_SCHEMA_PANIC = vol.Schema({vol.Required(ATTR_CODE): cv.string})
|
|
SERVICE_SCHEMA_AUX = vol.Schema(
|
|
{
|
|
vol.Required(ATTR_OUTPUT_ID): cv.positive_int,
|
|
vol.Optional(ATTR_STATE, default=True): cv.boolean,
|
|
}
|
|
)
|
|
|
|
|
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
"""Set up the Ness Alarm platform."""
|
|
|
|
conf = config[DOMAIN]
|
|
|
|
zones = conf[CONF_ZONES]
|
|
host = conf[CONF_HOST]
|
|
port = conf[CONF_DEVICE_PORT]
|
|
scan_interval = conf[CONF_SCAN_INTERVAL]
|
|
infer_arming_state = conf[CONF_INFER_ARMING_STATE]
|
|
|
|
client = Client(
|
|
host=host,
|
|
port=port,
|
|
update_interval=scan_interval.total_seconds(),
|
|
infer_arming_state=infer_arming_state,
|
|
)
|
|
hass.data[DATA_NESS] = client
|
|
|
|
async def _close(event):
|
|
await client.close()
|
|
|
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _close)
|
|
|
|
hass.async_create_task(
|
|
async_load_platform(
|
|
hass, Platform.BINARY_SENSOR, DOMAIN, {CONF_ZONES: zones}, config
|
|
)
|
|
)
|
|
hass.async_create_task(
|
|
async_load_platform(hass, Platform.ALARM_CONTROL_PANEL, DOMAIN, {}, config)
|
|
)
|
|
|
|
def on_zone_change(zone_id: int, state: bool):
|
|
"""Receives and propagates zone state updates."""
|
|
async_dispatcher_send(
|
|
hass, SIGNAL_ZONE_CHANGED, ZoneChangedData(zone_id=zone_id, state=state)
|
|
)
|
|
|
|
def on_state_change(arming_state: ArmingState):
|
|
"""Receives and propagates arming state updates."""
|
|
async_dispatcher_send(hass, SIGNAL_ARMING_STATE_CHANGED, arming_state)
|
|
|
|
client.on_zone_change(on_zone_change)
|
|
client.on_state_change(on_state_change)
|
|
|
|
# Force update for current arming status and current zone states
|
|
hass.loop.create_task(client.keepalive())
|
|
hass.loop.create_task(client.update())
|
|
|
|
async def handle_panic(call: ServiceCall) -> None:
|
|
await client.panic(call.data[ATTR_CODE])
|
|
|
|
async def handle_aux(call: ServiceCall) -> None:
|
|
await client.aux(call.data[ATTR_OUTPUT_ID], call.data[ATTR_STATE])
|
|
|
|
hass.services.async_register(
|
|
DOMAIN, SERVICE_PANIC, handle_panic, schema=SERVICE_SCHEMA_PANIC
|
|
)
|
|
hass.services.async_register(
|
|
DOMAIN, SERVICE_AUX, handle_aux, schema=SERVICE_SCHEMA_AUX
|
|
)
|
|
|
|
return True
|