1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/ness_alarm/__init__.py
Nick Whyte 11f80762ea
Upgrade ness_alarm dependencies (#75298)
* Upgrade ness alarm dependencies to fix #74571

* Update requirements
2022-07-18 12:17:25 +02:00

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