def main():
    """
    Example application that shows how to handle attach/detach events generated
    by the USB devices.

    In this case we open the device and listen for messages when it is attached.
    And when it is detached we remove it from our list of monitored devices.
    """
    try:
        # Start up the detection thread such that handle_attached and handle_detached will
        # be called when devices are attached and detached, respectively.
        USBDevice.start_detection(on_attached=handle_attached, on_detached=handle_detached)

        # Wait for events.
        while True:
            time.sleep(1)

    except Exception as ex:
        print('Exception:', ex)

    finally:
        # Close all devices and stop detection.
        for sn, device in __devices.items():
            device.close()

        USBDevice.stop_detection()
Example #2
0
        def test_find_with_param(self):
            with patch.object(Ftdi, 'find_all', return_value=[(0, 0, 'AD2-1', 1, 'AD2'), (0, 0, 'AD2-2', 1, 'AD2')]):
                device = USBDevice.find((0, 0, 'AD2-1', 1, 'AD2'))
                self.assertEquals(device.interface, 'AD2-1')

                device = USBDevice.find((0, 0, 'AD2-2', 1, 'AD2'))
                self.assertEquals(device.interface, 'AD2-2')
Example #3
0
        def test_find_all_exception(self):
            with patch.object(Ftdi, 'find_all', side_effect=[USBError('testing'), FtdiError]) as mock:
                with self.assertRaises(CommError):
                    devices = USBDevice.find_all()

                with self.assertRaises(CommError):
                    devices = USBDevice.find_all()
Example #4
0
        def setUp(self):
            self._device = USBDevice()
            self._device._device = Mock(spec=Ftdi)
            self._device._device.usb_dev = Mock(spec=USBCoreDevice)
            self._device._device.usb_dev.bus = 0
            self._device._device.usb_dev.address = 0

            self._attached = False
            self._detached = False
Example #5
0
    def test_find_default_param(self):
        with patch.object(Ftdi,
                          'find_all',
                          return_value=[(0, 0, 'AD2', 1, 'AD2')]):
            device = USBDevice.find()

            self.assertEqual(device.interface, 'AD2')
        def setUp(self):
            self._device = USBDevice()
            self._device._device = Mock(spec=Ftdi)
            self._device._device.usb_dev = Mock(spec=USBCoreDevice)
            self._device._device.usb_dev.bus = 0
            self._device._device.usb_dev.address = 0

            self._attached = False
            self._detached = False
def create_device(device_args):
    """
    Creates an AlarmDecoder from the specified USB device arguments.

    :param device_args: Tuple containing information on the USB device to open.
    :type device_args: Tuple (vid, pid, serialnumber, interface_count, description)
    """
    device = AlarmDecoder(USBDevice.find(device_args))
    device.on_message += handle_message
    device.open()

    return device
Example #8
0
def main():
    """
    Example application that prints messages from the panel to the terminal.
    """
    try:
        # Retrieve the first USB device
        device = AlarmDecoder(USBDevice.find())

        # Set up an event handler and open the device
        device.on_lrr_message += handle_lrr_message
        with device.open():
            while True:
                time.sleep(1)

    except Exception, ex:
        print "Exception:", ex
Example #9
0
def main():
    """
    Example application that prints messages from the panel to the terminal.
    """
    try:
        # Retrieve the first USB device
        device = AlarmDecoder(USBDevice.find())

        # Set up an event handler and open the device
        device.on_message += handle_message
        with device.open():
            while True:
                time.sleep(1)

    except Exception as ex:
        print('Exception:', ex)
Example #10
0
def main():
    """
    Example application that sends an email when an alarm event is
    detected.
    """
    try:
        # Retrieve the first USB device
        device = AlarmDecoder(USBDevice.find())

        # Set up an event handler and open the device
        device.on_alarm += handle_alarm
        with device.open():
            while True:
                time.sleep(1)

    except Exception, ex:
        print 'Exception:', ex
Example #11
0
        def test_events(self):
            self.assertFalse(self._attached)
            self.assertFalse(self._detached)

            # this is ugly, but it works.
            with patch.object(USBDevice, 'find_all', return_value=[(0, 0, 'AD2-1', 1, 'AD2'), (0, 0, 'AD2-2', 1, 'AD2')]):
                USBDevice.start_detection(on_attached=self.attached_event, on_detached=self.detached_event)

                with patch.object(USBDevice, 'find_all', return_value=[(0, 0, 'AD2-2', 1, 'AD2')]):
                    USBDevice.find_all()
                    time.sleep(1)
                    USBDevice.stop_detection()

            self.assertTrue(self._attached)
            self.assertTrue(self._detached)
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 pyhysical 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(USBDevice.find())

        # 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():
            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
Example #13
0
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(USBDevice.find())

        # Set up an event handler and open the device
        device.on_rfx_message += handle_rfx
        with device.open():
            while True:
                time.sleep(1)

    except Exception, ex:
        print 'Exception:', ex
Example #14
0
        USBDevice.start_detection(on_attached=handle_attached,
                                  on_detached=handle_detached)

        # Wait for events.
        while True:
            time.sleep(1)

    except Exception, ex:
        print 'Exception:', ex

    finally:
        # Close all devices and stop detection.
        for sn, device in __devices.iteritems():
            device.close()

        USBDevice.stop_detection()


def create_device(device_args):
    """
    Creates an AlarmDecoder from the specified USB device arguments.

    :param device_args: Tuple containing information on the USB device to open.
    :type device_args: Tuple (vid, pid, serialnumber, interface_count, description)
    """
    device = AlarmDecoder(USBDevice.find(device_args))
    device.on_message += handle_message
    device.open()

    return device
Example #15
0
    class TestUSBDevice(TestCase):
        def setUp(self):
            self._device = USBDevice()
            self._device._device = Mock(spec=Ftdi)
            self._device._device.usb_dev = Mock(spec=USBCoreDevice)
            self._device._device.usb_dev.bus = 0
            self._device._device.usb_dev.address = 0

            self._attached = False
            self._detached = False

        def tearDown(self):
            self._device.close()

        def attached_event(self, sender, *args, **kwargs):
            self._attached = True

        def detached_event(self, sender, *args, **kwargs):
            self._detached = True

        def test_find_default_param(self):
            with patch.object(Ftdi,
                              'find_all',
                              return_value=[(0, 0, 'AD2', 1, 'AD2')]):
                device = USBDevice.find()

                self.assertEquals(device.interface, 'AD2')

        def test_find_with_param(self):
            with patch.object(Ftdi,
                              'find_all',
                              return_value=[(0, 0, 'AD2-1', 1, 'AD2'),
                                            (0, 0, 'AD2-2', 1, 'AD2')]):
                device = USBDevice.find((0, 0, 'AD2-1', 1, 'AD2'))
                self.assertEquals(device.interface, 'AD2-1')

                device = USBDevice.find((0, 0, 'AD2-2', 1, 'AD2'))
                self.assertEquals(device.interface, 'AD2-2')

        def test_events(self):
            self.assertEquals(self._attached, False)
            self.assertEquals(self._detached, False)

            # this is ugly, but it works.
            with patch.object(USBDevice,
                              'find_all',
                              return_value=[(0, 0, 'AD2-1', 1, 'AD2'),
                                            (0, 0, 'AD2-2', 1, 'AD2')]):
                USBDevice.start_detection(on_attached=self.attached_event,
                                          on_detached=self.detached_event)

                with patch.object(USBDevice,
                                  'find_all',
                                  return_value=[(0, 0, 'AD2-2', 1, 'AD2')]):
                    USBDevice.find_all()
                    time.sleep(1)
                    USBDevice.stop_detection()

            self.assertEquals(self._attached, True)
            self.assertEquals(self._detached, True)

        def test_find_all(self):
            with patch.object(USBDevice, 'find_all', return_value=[]) as mock:
                devices = USBDevice.find_all()

            self.assertEquals(devices, [])

        def test_find_all_exception(self):
            with patch.object(Ftdi,
                              'find_all',
                              side_effect=[USBError('testing'),
                                           FtdiError]) as mock:
                with self.assertRaises(CommError):
                    devices = USBDevice.find_all()

                with self.assertRaises(CommError):
                    devices = USBDevice.find_all()

        def test_interface_serial_number(self):
            self._device.interface = 'AD2USB'

            self.assertEquals(self._device.interface, 'AD2USB')
            self.assertEquals(self._device.serial_number, 'AD2USB')
            self.assertEquals(self._device._device_number, 0)

        def test_interface_index(self):
            self._device.interface = 1

            self.assertEquals(self._device.interface, 1)
            self.assertEquals(self._device.serial_number, None)
            self.assertEquals(self._device._device_number, 1)

        def test_open(self):
            self._device.interface = 'AD2USB'

            with patch.object(self._device._device, 'open') as mock:
                self._device.open(no_reader_thread=True)

                mock.assert_any_calls()

        def test_open_failed(self):
            self._device.interface = 'AD2USB'

            with patch.object(self._device._device,
                              'open',
                              side_effect=[USBError('testing'), FtdiError]):
                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 = 'AD2USB'
            self._device.open(no_reader_thread=True)

            with patch.object(self._device._device, 'write_data') 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_data',
                              side_effect=FtdiError):
                with self.assertRaises(CommError):
                    self._device.write(b'test')

        def test_read(self):
            self._device.interface = 'AD2USB'
            self._device.open(no_reader_thread=True)

            with patch.object(self._device._device, 'read_data') as mock:
                self._device.read()

                mock.assert_called_with(1)

        def test_read_exception(self):
            with patch.object(self._device._device,
                              'read_data',
                              side_effect=[USBError('testing'), FtdiError]):
                with self.assertRaises(CommError):
                    self._device.read()

                with self.assertRaises(CommError):
                    self._device.read()

        def test_read_line(self):
            with patch.object(self._device._device,
                              'read_data',
                              side_effect=list("testing\r\n")):
                ret = None
                try:
                    ret = self._device.read_line()
                except StopIteration:
                    pass

                self.assertEquals(ret, b"testing")

        def test_read_line_timeout(self):
            with patch.object(self._device._device,
                              'read_data',
                              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_data',
                              side_effect=[USBError('testing'), FtdiError]):
                with self.assertRaises(CommError):
                    self._device.read_line()

                with self.assertRaises(CommError):
                    self._device.read_line()
Example #16
0
        # be called when devices are attached and detached, respectively.
        USBDevice.start_detection(on_attached=handle_attached, on_detached=handle_detached)

        # Wait for events.
        while True:
            time.sleep(1)

    except Exception, ex:
        print 'Exception:', ex

    finally:
        # Close all devices and stop detection.
        for sn, device in __devices.iteritems():
            device.close()

        USBDevice.stop_detection()

def create_device(device_args):
    """
    Creates an AlarmDecoder from the specified USB device arguments.

    :param device_args: Tuple containing information on the USB device to open.
    :type device_args: Tuple (vid, pid, serialnumber, interface_count, description)
    """
    device = AlarmDecoder(USBDevice.find(device_args))
    device.on_message += handle_message
    device.open()

    return device

def handle_message(sender, message):
        def test_find_all(self):
            with patch.object(USBDevice, 'find_all', return_value=[]) as mock:
                devices = USBDevice.find_all()

            self.assertEquals(devices, [])
Example #18
0
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_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
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)

    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")
        controller.close()

    def handle_message(sender, message):
        """Handle message from AlarmDecoder."""
        hass.helpers.dispatcher.dispatcher_send(
            SIGNAL_PANEL_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)

    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_zone_fault += zone_fault_callback
    controller.on_zone_restore += zone_restore_callback

    hass.data[DATA_AD] = controller

    controller.open(baud)

    _LOGGER.debug("Established a connection with the alarmdecoder")
    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
Example #20
0
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
Example #21
0
    def test_find_all(self):
        with patch.object(USBDevice, 'find_all', return_value=[]) as mock:
            devices = USBDevice.find_all()

        self.assertEqual(devices, [])
Example #22
0
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
Example #23
0
def async_setup(hass, config):
    """Common setup for 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):
        """Callback for a 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):
        """Callback to handle shutdown alarmdecoder."""
        _LOGGER.debug("Shutting down alarmdecoder.")
        controller.close()

    @callback
    def handle_message(sender, message):
        """Callback to handle message from alarmdecoder."""
        async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message)

    def zone_fault_callback(sender, zone):
        """Callback to handle zone fault from alarmdecoder."""
        async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone)

    def zone_restore_callback(sender, zone):
        """Callback to 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
Example #24
0
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
    class TestUSBDevice(TestCase):
        def setUp(self):
            self._device = USBDevice()
            self._device._device = Mock(spec=Ftdi)
            self._device._device.usb_dev = Mock(spec=USBCoreDevice)
            self._device._device.usb_dev.bus = 0
            self._device._device.usb_dev.address = 0

            self._attached = False
            self._detached = False

        def tearDown(self):
            self._device.close()

        ### Library events
        def attached_event(self, sender, *args, **kwargs):
            self._attached = True

        def detached_event(self, sender, *args, **kwargs):
            self._detached = True

        ### Tests
        def test_find_default_param(self):
            with patch.object(Ftdi, 'find_all', return_value=[(0, 0, 'AD2', 1, 'AD2')]):
                device = USBDevice.find()

                self.assertEquals(device.interface, 'AD2')

        def test_find_with_param(self):
            with patch.object(Ftdi, 'find_all', return_value=[(0, 0, 'AD2-1', 1, 'AD2'), (0, 0, 'AD2-2', 1, 'AD2')]):
                device = USBDevice.find((0, 0, 'AD2-1', 1, 'AD2'))
                self.assertEquals(device.interface, 'AD2-1')

                device = USBDevice.find((0, 0, 'AD2-2', 1, 'AD2'))
                self.assertEquals(device.interface, 'AD2-2')

        def test_events(self):
            self.assertFalse(self._attached)
            self.assertFalse(self._detached)

            # this is ugly, but it works.
            with patch.object(USBDevice, 'find_all', return_value=[(0, 0, 'AD2-1', 1, 'AD2'), (0, 0, 'AD2-2', 1, 'AD2')]):
                USBDevice.start_detection(on_attached=self.attached_event, on_detached=self.detached_event)

                with patch.object(USBDevice, 'find_all', return_value=[(0, 0, 'AD2-2', 1, 'AD2')]):
                    USBDevice.find_all()
                    time.sleep(1)
                    USBDevice.stop_detection()

            self.assertTrue(self._attached)
            self.assertTrue(self._detached)

        def test_find_all(self):
            with patch.object(USBDevice, 'find_all', return_value=[]) as mock:
                devices = USBDevice.find_all()

            self.assertEquals(devices, [])

        def test_find_all_exception(self):
            with patch.object(Ftdi, 'find_all', side_effect=[USBError('testing'), FtdiError]) as mock:
                with self.assertRaises(CommError):
                    devices = USBDevice.find_all()

                with self.assertRaises(CommError):
                    devices = USBDevice.find_all()

        def test_interface_serial_number(self):
            self._device.interface = 'AD2USB'

            self.assertEquals(self._device.interface, 'AD2USB')
            self.assertEquals(self._device.serial_number, 'AD2USB')
            self.assertEquals(self._device._device_number, 0)

        def test_interface_index(self):
            self._device.interface = 1

            self.assertEquals(self._device.interface, 1)
            self.assertEquals(self._device.serial_number, None)
            self.assertEquals(self._device._device_number, 1)

        def test_open(self):
            self._device.interface = 'AD2USB'

            with patch.object(self._device._device, 'open') as mock:
                self._device.open(no_reader_thread=True)

                mock.assert_called()

        def test_open_failed(self):
            self._device.interface = 'AD2USB'

            with patch.object(self._device._device, 'open', side_effect=[USBError('testing'), FtdiError]):
                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 = 'AD2USB'
            self._device.open(no_reader_thread=True)

            with patch.object(self._device._device, 'write_data') 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_data', side_effect=FtdiError):
                with self.assertRaises(CommError):
                    self._device.write(b'test')

        def test_read(self):
            self._device.interface = 'AD2USB'
            self._device.open(no_reader_thread=True)

            with patch.object(self._device._device, 'read_data') as mock:
                self._device.read()

                mock.assert_called_with(1)

        def test_read_exception(self):
            with patch.object(self._device._device, 'read_data', side_effect=[USBError('testing'), FtdiError]):
                with self.assertRaises(CommError):
                    self._device.read()

                with self.assertRaises(CommError):
                    self._device.read()

        def test_read_line(self):
            with patch.object(self._device._device, 'read_data', side_effect=list("testing\r\n")):
                ret = None
                try:
                    ret = self._device.read_line()
                except StopIteration:
                    pass

                self.assertEquals(ret, b"testing")

        def test_read_line_timeout(self):
            with patch.object(self._device._device, 'read_data', 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_data', side_effect=[USBError('testing'), FtdiError]):
                with self.assertRaises(CommError):
                    self._device.read_line()

                with self.assertRaises(CommError):
                    self._device.read_line()