1 """Support for Envisalink devices."""
6 from pyenvisalink
import EnvisalinkAlarmPanel
7 import voluptuous
as vol
13 EVENT_HOMEASSISTANT_STOP,
22 _LOGGER = logging.getLogger(__name__)
26 DATA_EVL =
"envisalink"
28 CONF_EVL_KEEPALIVE =
"keepalive_interval"
29 CONF_EVL_PORT =
"port"
30 CONF_EVL_VERSION =
"evl_version"
31 CONF_PANEL_TYPE =
"panel_type"
32 CONF_PANIC =
"panic_type"
33 CONF_PARTITIONNAME =
"name"
34 CONF_PARTITIONS =
"partitions"
35 CONF_PASS =
"password"
36 CONF_USERNAME =
"user_name"
37 CONF_ZONEDUMP_INTERVAL =
"zonedump_interval"
38 CONF_ZONENAME =
"name"
40 CONF_ZONETYPE =
"type"
42 PANEL_TYPE_HONEYWELL =
"HONEYWELL"
43 PANEL_TYPE_DSC =
"DSC"
46 DEFAULT_EVL_VERSION = 3
47 DEFAULT_KEEPALIVE = 60
48 DEFAULT_ZONEDUMP_INTERVAL = 30
49 DEFAULT_ZONETYPE =
"opening"
50 DEFAULT_PANIC =
"Police"
53 SIGNAL_ZONE_UPDATE =
"envisalink.zones_updated"
54 SIGNAL_PARTITION_UPDATE =
"envisalink.partition_updated"
55 SIGNAL_KEYPAD_UPDATE =
"envisalink.keypad_updated"
56 SIGNAL_ZONE_BYPASS_UPDATE =
"envisalink.zone_bypass_updated"
58 ZONE_SCHEMA = vol.Schema(
60 vol.Required(CONF_ZONENAME): cv.string,
61 vol.Optional(CONF_ZONETYPE, default=DEFAULT_ZONETYPE): cv.string,
65 PARTITION_SCHEMA = vol.Schema({vol.Required(CONF_PARTITIONNAME): cv.string})
67 CONFIG_SCHEMA = vol.Schema(
71 vol.Required(CONF_HOST): cv.string,
72 vol.Required(CONF_PANEL_TYPE): vol.All(
73 cv.string, vol.In([PANEL_TYPE_HONEYWELL, PANEL_TYPE_DSC])
75 vol.Required(CONF_USERNAME): cv.string,
76 vol.Required(CONF_PASS): cv.string,
77 vol.Optional(CONF_CODE): cv.string,
78 vol.Optional(CONF_PANIC, default=DEFAULT_PANIC): cv.string,
79 vol.Optional(CONF_ZONES): {vol.Coerce(int): ZONE_SCHEMA},
80 vol.Optional(CONF_PARTITIONS): {vol.Coerce(int): PARTITION_SCHEMA},
81 vol.Optional(CONF_EVL_PORT, default=DEFAULT_PORT): cv.port,
82 vol.Optional(CONF_EVL_VERSION, default=DEFAULT_EVL_VERSION): vol.All(
83 vol.Coerce(int), vol.Range(min=3, max=4)
85 vol.Optional(CONF_EVL_KEEPALIVE, default=DEFAULT_KEEPALIVE): vol.All(
86 vol.Coerce(int), vol.Range(min=15)
89 CONF_ZONEDUMP_INTERVAL, default=DEFAULT_ZONEDUMP_INTERVAL
91 vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.Coerce(int),
95 extra=vol.ALLOW_EXTRA,
98 SERVICE_CUSTOM_FUNCTION =
"invoke_custom_function"
99 ATTR_CUSTOM_FUNCTION =
"pgm"
100 ATTR_PARTITION =
"partition"
102 SERVICE_SCHEMA = vol.Schema(
104 vol.Required(ATTR_CUSTOM_FUNCTION): cv.string,
105 vol.Required(ATTR_PARTITION): cv.string,
110 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
111 """Set up for Envisalink devices."""
112 conf = config[DOMAIN]
114 host = conf.get(CONF_HOST)
115 port = conf.get(CONF_EVL_PORT)
116 code = conf.get(CONF_CODE)
117 panel_type = conf.get(CONF_PANEL_TYPE)
118 panic_type = conf.get(CONF_PANIC)
119 version = conf.get(CONF_EVL_VERSION)
120 user = conf.get(CONF_USERNAME)
121 password = conf.get(CONF_PASS)
122 keep_alive = conf.get(CONF_EVL_KEEPALIVE)
123 zone_dump = conf.get(CONF_ZONEDUMP_INTERVAL)
124 zones = conf.get(CONF_ZONES)
125 partitions = conf.get(CONF_PARTITIONS)
126 connection_timeout = conf.get(CONF_TIMEOUT)
127 sync_connect: asyncio.Future[bool] = hass.loop.create_future()
129 controller = EnvisalinkAlarmPanel(
142 hass.data[DATA_EVL] = controller
145 def async_login_fail_callback(data):
146 """Handle when the evl rejects our login."""
147 _LOGGER.error(
"The Envisalink rejected your credentials")
148 if not sync_connect.done():
149 sync_connect.set_result(
False)
152 def async_connection_fail_callback(data):
153 """Network failure callback."""
154 _LOGGER.error(
"Could not establish a connection with the Envisalink- retrying")
155 if not sync_connect.done():
156 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_envisalink)
157 sync_connect.set_result(
True)
160 def async_connection_success_callback(data):
161 """Handle a successful connection."""
162 _LOGGER.debug(
"Established a connection with the Envisalink")
163 if not sync_connect.done():
164 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_envisalink)
165 sync_connect.set_result(
True)
168 def async_zones_updated_callback(data):
169 """Handle zone timer updates."""
170 _LOGGER.debug(
"Envisalink sent a zone update event. Updating zones")
174 def async_alarm_data_updated_callback(data):
175 """Handle non-alarm based info updates."""
176 _LOGGER.debug(
"Envisalink sent new alarm info. Updating alarms")
180 def async_partition_updated_callback(data):
181 """Handle partition changes thrown by evl (including alarms)."""
182 _LOGGER.debug(
"The envisalink sent a partition update event")
186 def stop_envisalink(event):
187 """Shutdown envisalink connection and thread on exit."""
188 _LOGGER.debug(
"Shutting down Envisalink")
191 async
def handle_custom_function(call: ServiceCall) ->
None:
192 """Handle custom/PGM service."""
193 custom_function = call.data.get(ATTR_CUSTOM_FUNCTION)
194 partition = call.data.get(ATTR_PARTITION)
195 controller.command_output(code, partition, custom_function)
197 controller.callback_zone_timer_dump = async_zones_updated_callback
198 controller.callback_zone_state_change = async_zones_updated_callback
199 controller.callback_partition_state_change = async_partition_updated_callback
200 controller.callback_keypad_update = async_alarm_data_updated_callback
201 controller.callback_login_failure = async_login_fail_callback
202 controller.callback_login_timeout = async_connection_fail_callback
203 controller.callback_login_success = async_connection_success_callback
205 _LOGGER.debug(
"Start envisalink")
208 if not await sync_connect:
213 hass.async_create_task(
216 Platform.ALARM_CONTROL_PANEL,
218 {CONF_PARTITIONS: partitions, CONF_CODE: code, CONF_PANIC: panic_type},
222 hass.async_create_task(
227 {CONF_PARTITIONS: partitions, CONF_CODE: code},
232 hass.async_create_task(
234 hass, Platform.BINARY_SENSOR,
"envisalink", {CONF_ZONES: zones}, config
241 hass.services.async_register(
242 DOMAIN, SERVICE_CUSTOM_FUNCTION, handle_custom_function, schema=SERVICE_SCHEMA
bool async_setup(HomeAssistant hass, ConfigType config)
None async_load_platform(core.HomeAssistant hass, Platform|str component, str platform, DiscoveryInfoType|None discovered, ConfigType hass_config)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)