async def async_step_protocol(self, user_input=None): """Handle AlarmDecoder protocol setup.""" errors = {} if user_input is not None: if _device_already_added( self._async_current_entries(), user_input, self.protocol ): return self.async_abort(reason="already_configured") connection = {} baud = None if self.protocol == PROTOCOL_SOCKET: host = connection[CONF_HOST] = user_input[CONF_HOST] port = connection[CONF_PORT] = user_input[CONF_PORT] title = f"{host}:{port}" device = SocketDevice(interface=(host, port)) if self.protocol == PROTOCOL_SERIAL: path = connection[CONF_DEVICE_PATH] = user_input[CONF_DEVICE_PATH] baud = connection[CONF_DEVICE_BAUD] = user_input[CONF_DEVICE_BAUD] title = path device = SerialDevice(interface=path) controller = AdExt(device) def test_connection(): controller.open(baud) controller.close() try: await self.hass.async_add_executor_job(test_connection) return self.async_create_entry( title=title, data={CONF_PROTOCOL: self.protocol, **connection} ) except NoDeviceError: errors["base"] = "cannot_connect" except Exception: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception during AlarmDecoder setup") errors["base"] = "unknown" if self.protocol == PROTOCOL_SOCKET: schema = vol.Schema( { vol.Required(CONF_HOST, default=DEFAULT_DEVICE_HOST): str, vol.Required(CONF_PORT, default=DEFAULT_DEVICE_PORT): int, } ) if self.protocol == PROTOCOL_SERIAL: schema = vol.Schema( { vol.Required(CONF_DEVICE_PATH, default=DEFAULT_DEVICE_PATH): str, vol.Required(CONF_DEVICE_BAUD, default=DEFAULT_DEVICE_BAUD): int, } ) return self.async_show_form( step_id="protocol", data_schema=schema, errors=errors, )
def main(): """ Example application that prints messages from the panel to the terminal. """ try: # Retrieve the first USB device device = AlarmDecoder(SerialDevice(interface=SERIAL_DEVICE)) # Set up an event handler and open the device device.on_lrr_message += handle_lrr_message with device.open(baudrate=BAUDRATE): while True: time.sleep(1) except Exception, ex: print 'Exception:', ex
def main(): """ Example application that sends an email when an alarm event is detected. """ try: # Retrieve the first USB device device = AlarmDecoder(SerialDevice(interface=SERIAL_DEVICE)) # Set up an event handler and open the device device.on_alarm += handle_alarm with device.open(baudrate=BAUDRATE): while True: time.sleep(1) except Exception as ex: print('Exception:', ex)
def main(): """ Example application that opens a serial device and prints messages to the terminal. """ try: # Retrieve the specified serial device. device = AlarmDecoder(SerialDevice(interface=SERIAL_DEVICE)) # Set up an event handler and open the device device.on_message += handle_message # Override the default SerialDevice baudrate since we're using a USB device # over serial in this example. with device.open(baudrate=BAUDRATE): while True: time.sleep(1) except Exception, ex: print 'Exception:', ex
def main(): """ Example application that periodically faults a virtual zone and then restores it. This is an advanced feature that allows you to emulate a virtual zone. When the AlarmDecoder is configured to emulate a zone expander we can fault and restore those zones programmatically at will. These events can also be seen by others, such as home automation platforms which allows you to connect other devices or services and monitor them as you would any physical zone. For example, you could connect a ZigBee device and receiver and fault or restore it's zone(s) based on the data received. In order for this to happen you need to perform a couple configuration steps: 1. Enable zone expander emulation on your AlarmDecoder device by hitting '!' in a terminal and going through the prompts. 2. Enable the zone expander in your panel programming. """ try: # Retrieve the first USB device device = AlarmDecoder(SerialDevice(interface=SERIAL_DEVICE)) # Set up an event handlers and open the device device.on_zone_fault += handle_zone_fault device.on_zone_restore += handle_zone_restore with device.open(baudrate=BAUDRATE): last_update = time.time() while True: if time.time() - last_update > WAIT_TIME: last_update = time.time() device.fault_zone(TARGET_ZONE) time.sleep(1) except Exception, ex: print 'Exception:', ex
def main(): """ Example application that watches for an event from a specific RF device. This feature allows you to watch for events from RF devices if you have an RF receiver. This is useful in the case of internal sensors, which don't emit a FAULT if the sensor is tripped and the panel is armed STAY. It also will monitor sensors that aren't configured. NOTE: You must have an RF receiver installed and enabled in your panel for RFX messages to be seen. """ try: # Retrieve the first USB device device = AlarmDecoder(SerialDevice(interface=SERIAL_DEVICE)) # Set up an event handler and open the device device.on_rfx_message += handle_rfx with device.open(baudrate=BAUDRATE): while True: time.sleep(1) except Exception as ex: print('Exception:', ex)
def async_setup(hass, config): """Set up for the AlarmDecoder devices.""" from alarmdecoder import AlarmDecoder from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice) conf = config.get(DOMAIN) device = conf.get(CONF_DEVICE) display = conf.get(CONF_PANEL_DISPLAY) zones = conf.get(CONF_ZONES) device_type = device.get(CONF_DEVICE_TYPE) host = DEFAULT_DEVICE_HOST port = DEFAULT_DEVICE_PORT path = DEFAULT_DEVICE_PATH baud = DEFAULT_DEVICE_BAUD sync_connect = asyncio.Future(loop=hass.loop) def handle_open(device): """Handle the successful connection.""" _LOGGER.info("Established a connection with the alarmdecoder") hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder) sync_connect.set_result(True) @callback def stop_alarmdecoder(event): """Handle the shutdown of AlarmDecoder.""" _LOGGER.debug("Shutting down alarmdecoder") controller.close() @callback def handle_message(sender, message): """Handle message from AlarmDecoder.""" async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message) def zone_fault_callback(sender, zone): """Handle zone fault from AlarmDecoder.""" async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone) def zone_restore_callback(sender, zone): """Handle zone restore from AlarmDecoder.""" async_dispatcher_send(hass, SIGNAL_ZONE_RESTORE, zone) controller = False if device_type == 'socket': host = device.get(CONF_DEVICE_HOST) port = device.get(CONF_DEVICE_PORT) controller = AlarmDecoder(SocketDevice(interface=(host, port))) elif device_type == 'serial': path = device.get(CONF_DEVICE_PATH) baud = device.get(CONF_DEVICE_BAUD) controller = AlarmDecoder(SerialDevice(interface=path)) elif device_type == 'usb': AlarmDecoder(USBDevice.find()) return False controller.on_open += handle_open controller.on_message += handle_message controller.on_zone_fault += zone_fault_callback controller.on_zone_restore += zone_restore_callback hass.data[DATA_AD] = controller controller.open(baud) result = yield from sync_connect if not result: return False hass.async_add_job( async_load_platform(hass, 'alarm_control_panel', DOMAIN, conf, config)) if zones: hass.async_add_job( async_load_platform(hass, 'binary_sensor', DOMAIN, {CONF_ZONES: zones}, config)) if display: hass.async_add_job( async_load_platform(hass, 'sensor', DOMAIN, conf, config)) return True
def setup(hass, config): """Set up for the AlarmDecoder devices.""" from alarmdecoder import AlarmDecoder from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice) conf = config.get(DOMAIN) restart = False device = conf.get(CONF_DEVICE) display = conf.get(CONF_PANEL_DISPLAY) zones = conf.get(CONF_ZONES) device_type = device.get(CONF_DEVICE_TYPE) host = DEFAULT_DEVICE_HOST port = DEFAULT_DEVICE_PORT path = DEFAULT_DEVICE_PATH baud = DEFAULT_DEVICE_BAUD def stop_alarmdecoder(event): """Handle the shutdown of AlarmDecoder.""" _LOGGER.debug("Shutting down alarmdecoder") nonlocal restart restart = False controller.close() def open_connection(now=None): """Open a connection to AlarmDecoder.""" from alarmdecoder.util import NoDeviceError nonlocal restart try: controller.open(baud) except NoDeviceError: _LOGGER.debug("Failed to connect. Retrying in 5 seconds") hass.helpers.event.track_point_in_time( open_connection, dt_util.utcnow() + timedelta(seconds=5)) return _LOGGER.debug("Established a connection with the alarmdecoder") restart = True def handle_closed_connection(event): """Restart after unexpected loss of connection.""" nonlocal restart if not restart: return restart = False _LOGGER.warning("AlarmDecoder unexpectedly lost connection.") hass.add_job(open_connection) def handle_message(sender, message): """Handle message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_PANEL_MESSAGE, message) def handle_rfx_message(sender, message): """Handle RFX message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_RFX_MESSAGE, message) def zone_fault_callback(sender, zone): """Handle zone fault from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_ZONE_FAULT, zone) def zone_restore_callback(sender, zone): """Handle zone restore from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_ZONE_RESTORE, zone) def handle_rel_message(sender, message): """Handle relay message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_REL_MESSAGE, message) controller = False if device_type == 'socket': host = device.get(CONF_DEVICE_HOST) port = device.get(CONF_DEVICE_PORT) controller = AlarmDecoder(SocketDevice(interface=(host, port))) elif device_type == 'serial': path = device.get(CONF_DEVICE_PATH) baud = device.get(CONF_DEVICE_BAUD) controller = AlarmDecoder(SerialDevice(interface=path)) elif device_type == 'usb': AlarmDecoder(USBDevice.find()) return False controller.on_message += handle_message controller.on_rfx_message += handle_rfx_message controller.on_zone_fault += zone_fault_callback controller.on_zone_restore += zone_restore_callback controller.on_close += handle_closed_connection controller.on_relay_changed += handle_rel_message hass.data[DATA_AD] = controller open_connection() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder) load_platform(hass, 'alarm_control_panel', DOMAIN, conf, config) if zones: load_platform(hass, 'binary_sensor', DOMAIN, {CONF_ZONES: zones}, config) if display: load_platform(hass, 'sensor', DOMAIN, conf, config) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up AlarmDecoder config flow.""" undo_listener = entry.add_update_listener(_update_listener) ad_connection = entry.data protocol = ad_connection[CONF_PROTOCOL] def stop_alarmdecoder(event): """Handle the shutdown of AlarmDecoder.""" if not hass.data.get(DOMAIN): return _LOGGER.debug("Shutting down alarmdecoder") hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = False controller.close() async def open_connection(now=None): """Open a connection to AlarmDecoder.""" try: await hass.async_add_executor_job(controller.open, baud) except NoDeviceError: _LOGGER.debug("Failed to connect. Retrying in 5 seconds") hass.helpers.event.async_track_point_in_time( open_connection, dt_util.utcnow() + timedelta(seconds=5)) return _LOGGER.debug("Established a connection with the alarmdecoder") hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = True def handle_closed_connection(event): """Restart after unexpected loss of connection.""" if not hass.data[DOMAIN][entry.entry_id][DATA_RESTART]: return hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = False _LOGGER.warning("AlarmDecoder unexpectedly lost connection") hass.add_job(open_connection) def handle_message(sender, message): """Handle message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_PANEL_MESSAGE, message) def handle_rfx_message(sender, message): """Handle RFX message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_RFX_MESSAGE, message) def zone_fault_callback(sender, zone): """Handle zone fault from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_ZONE_FAULT, zone) def zone_restore_callback(sender, zone): """Handle zone restore from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_ZONE_RESTORE, zone) def handle_rel_message(sender, message): """Handle relay or zone expander message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_REL_MESSAGE, message) baud = ad_connection.get(CONF_DEVICE_BAUD) if protocol == PROTOCOL_SOCKET: host = ad_connection[CONF_HOST] port = ad_connection[CONF_PORT] controller = AdExt(SocketDevice(interface=(host, port))) if protocol == PROTOCOL_SERIAL: path = ad_connection[CONF_DEVICE_PATH] controller = AdExt(SerialDevice(interface=path)) controller.on_message += handle_message controller.on_rfx_message += handle_rfx_message controller.on_zone_fault += zone_fault_callback controller.on_zone_restore += zone_restore_callback controller.on_close += handle_closed_connection controller.on_expander_message += handle_rel_message remove_stop_listener = hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder) hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = { DATA_AD: controller, DATA_REMOVE_UPDATE_LISTENER: undo_listener, DATA_REMOVE_STOP_LISTENER: remove_stop_listener, DATA_RESTART: False, } await open_connection() for platform in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, platform)) return True
def setUp(self): self._device = SerialDevice() self._device._device = Mock(spec=Serial) self._device._device.open = Mock()
class TestSerialDevice(TestCase): def setUp(self): self._device = SerialDevice() self._device._device = Mock(spec=Serial) self._device._device.open = Mock() def tearDown(self): self._device.close() def test_open(self): self._device.interface = '/dev/ttyS0' with patch.object(self._device._device, 'open') as mock: self._device.open(no_reader_thread=True) mock.assert_called_with() def test_open_no_interface(self): with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) self.assertFalse(self._device._running) def test_open_failed(self): self._device.interface = '/dev/ttyS0' with patch.object(self._device._device, 'open', side_effect=[SerialException, ValueError]): with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) def test_write(self): self._device.interface = '/dev/ttyS0' self._device.open(no_reader_thread=True) with patch.object(self._device._device, 'write') as mock: self._device.write(b'test') mock.assert_called_with(b'test') def test_write_exception(self): with patch.object(self._device._device, 'write', side_effect=SerialException): with self.assertRaises(CommError): self._device.write(b'test') def test_read(self): self._device.interface = '/dev/ttyS0' self._device.open(no_reader_thread=True) with patch.object(self._device._device, 'read') as mock: with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): ret = self._device.read() mock.assert_called_with(1) def test_read_exception(self): with patch.object(self._device._device, 'read', side_effect=SerialException): with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): with self.assertRaises(CommError): self._device.read() def test_read_line(self): side_effect = list("testing\r\n") if sys.version_info > (3, ): side_effect = [chr(x).encode('utf-8') for x in b"testing\r\n"] with patch.object(self._device._device, 'read', side_effect=side_effect): with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): ret = None try: ret = self._device.read_line() except StopIteration: pass self.assertEquals(ret, "testing") def test_read_line_timeout(self): with patch.object(self._device._device, 'read', return_value=b'a') as mock: with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): with self.assertRaises(TimeoutError): self._device.read_line(timeout=0.1) self.assertIn('a', self._device._buffer.decode('utf-8')) def test_read_line_exception(self): with patch.object(self._device._device, 'read', side_effect=[OSError, SerialException]): with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): with self.assertRaises(CommError): self._device.read_line() with self.assertRaises(CommError): self._device.read_line()
class TestSerialDevice(TestCase): def setUp(self): self._device = SerialDevice() self._device._device = Mock(spec=Serial) self._device._device.open = Mock() def tearDown(self): self._device.close() ### Tests def test_open(self): self._device.interface = '/dev/ttyS0' with patch.object(self._device._device, 'open') as mock: self._device.open(no_reader_thread=True) mock.assert_called_with() def test_open_no_interface(self): with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) self.assertFalse(self._device._running) def test_open_failed(self): self._device.interface = '/dev/ttyS0' with patch.object(self._device._device, 'open', side_effect=[SerialException, ValueError]): with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) def test_write(self): self._device.interface = '/dev/ttyS0' self._device.open(no_reader_thread=True) with patch.object(self._device._device, 'write') as mock: self._device.write(b'test') mock.assert_called_with(b'test') def test_write_exception(self): with patch.object(self._device._device, 'write', side_effect=SerialException): with self.assertRaises(CommError): self._device.write(b'test') def test_read(self): self._device.interface = '/dev/ttyS0' self._device.open(no_reader_thread=True) with patch.object(self._device._device, 'read') as mock: with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): ret = self._device.read() mock.assert_called_with(1) def test_read_exception(self): with patch.object(self._device._device, 'read', side_effect=SerialException): with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): with self.assertRaises(CommError): self._device.read() def test_read_line(self): side_effect = list("testing\r\n") if sys.version_info > (3,): side_effect = [chr(x).encode('utf-8') for x in b"testing\r\n"] with patch.object(self._device._device, 'read', side_effect=side_effect): with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): ret = None try: ret = self._device.read_line() except StopIteration: pass self.assertEquals(ret, "testing") def test_read_line_timeout(self): with patch.object(self._device._device, 'read', return_value=b'a') as mock: with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): with self.assertRaises(TimeoutError): self._device.read_line(timeout=0.1) self.assertIn('a', self._device._buffer.decode('utf-8')) def test_read_line_exception(self): with patch.object(self._device._device, 'read', side_effect=[OSError, SerialException]): with patch('serial.Serial.fileno', return_value=1): with patch.object(select, 'select', return_value=[[1], [], []]): with self.assertRaises(CommError): self._device.read_line() with self.assertRaises(CommError): self._device.read_line()
class TestSerialDevice(TestCase): def setUp(self): self._device = SerialDevice() self._device._device = Mock(spec=Serial) self._device._device.open = Mock() def tearDown(self): self._device.close() def test_open(self): self._device.interface = '/dev/ttyS0' with patch.object(self._device._device, 'open') as mock: self._device.open(no_reader_thread=True) mock.assert_called_with() def test_open_no_interface(self): with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) self.assertFalse(self._device._running) def test_open_failed(self): self._device.interface = '/dev/ttyS0' with patch.object(self._device._device, 'open', side_effect=[SerialException, ValueError]): with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) with self.assertRaises(NoDeviceError): self._device.open(no_reader_thread=True) def test_write(self): self._device.interface = '/dev/ttyS0' self._device.open(no_reader_thread=True) with patch.object(self._device._device, 'write') as mock: self._device.write('test') mock.assert_called_with('test') def test_write_exception(self): with patch.object(self._device._device, 'write', side_effect=SerialException): with self.assertRaises(CommError): self._device.write('test') def test_read(self): self._device.interface = '/dev/ttyS0' self._device.open(no_reader_thread=True) with patch.object(self._device._device, 'read') as mock: self._device.read() mock.assert_called_with(1) def test_read_exception(self): with patch.object(self._device._device, 'read', side_effect=SerialException): with self.assertRaises(CommError): self._device.read() def test_read_line(self): with patch.object(self._device._device, 'read', side_effect=list("testing\r\n")): ret = None try: ret = self._device.read_line() except StopIteration: pass self.assertEquals(ret, "testing") def test_read_line_timeout(self): with patch.object(self._device._device, 'read', return_value='a') as mock: with self.assertRaises(TimeoutError): self._device.read_line(timeout=0.1) self.assertIn('a', self._device._buffer) def test_read_line_exception(self): with patch.object(self._device._device, 'read', side_effect=[OSError, SerialException]): with self.assertRaises(CommError): self._device.read_line() with self.assertRaises(CommError): self._device.read_line()
def setup(hass, config): """Set up for the AlarmDecoder devices.""" conf = config.get(DOMAIN) restart = False device = conf[CONF_DEVICE] display = conf[CONF_PANEL_DISPLAY] auto_bypass = conf[CONF_AUTO_BYPASS] code_arm_required = conf[CONF_CODE_ARM_REQUIRED] zones = conf.get(CONF_ZONES) device_type = device[CONF_DEVICE_TYPE] host = DEFAULT_DEVICE_HOST port = DEFAULT_DEVICE_PORT path = DEFAULT_DEVICE_PATH baud = DEFAULT_DEVICE_BAUD def stop_alarmdecoder(event): """Handle the shutdown of AlarmDecoder.""" _LOGGER.debug("Shutting down alarmdecoder") nonlocal restart restart = False controller.close() def open_connection(now=None): """Open a connection to AlarmDecoder.""" nonlocal restart try: controller.open(baud) except NoDeviceError: _LOGGER.debug("Failed to connect. Retrying in 5 seconds") hass.helpers.event.track_point_in_time( open_connection, dt_util.utcnow() + timedelta(seconds=5)) return _LOGGER.debug("Established a connection with the alarmdecoder") restart = True def handle_closed_connection(event): """Restart after unexpected loss of connection.""" nonlocal restart if not restart: return restart = False _LOGGER.warning("AlarmDecoder unexpectedly lost connection") hass.add_job(open_connection) def handle_message(sender, message): """Handle message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_PANEL_MESSAGE, message) def handle_rfx_message(sender, message): """Handle RFX message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_RFX_MESSAGE, message) def zone_fault_callback(sender, zone): """Handle zone fault from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_ZONE_FAULT, zone) def zone_restore_callback(sender, zone): """Handle zone restore from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_ZONE_RESTORE, zone) def handle_rel_message(sender, message): """Handle relay or zone expander message from AlarmDecoder.""" hass.helpers.dispatcher.dispatcher_send(SIGNAL_REL_MESSAGE, message) controller = False if device_type == "socket": host = device[CONF_HOST] port = device[CONF_DEVICE_PORT] controller = AdExt(SocketDevice(interface=(host, port))) elif device_type == "serial": path = device[CONF_DEVICE_PATH] baud = device[CONF_DEVICE_BAUD] controller = AdExt(SerialDevice(interface=path)) elif device_type == "usb": AdExt(USBDevice.find()) return False controller.on_message += handle_message controller.on_rfx_message += handle_rfx_message controller.on_zone_fault += zone_fault_callback controller.on_zone_restore += zone_restore_callback controller.on_close += handle_closed_connection controller.on_expander_message += handle_rel_message hass.data[DATA_AD] = controller open_connection() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder) load_platform( hass, "alarm_control_panel", DOMAIN, { CONF_AUTO_BYPASS: auto_bypass, CONF_CODE_ARM_REQUIRED: code_arm_required }, config, ) if zones: load_platform(hass, "binary_sensor", DOMAIN, {CONF_ZONES: zones}, config) if display: load_platform(hass, "sensor", DOMAIN, conf, config) return True