Пример #1
0
def main():
    """
    Example application that opens a device that has been exposed to the network
    with ser2sock and SSL encryption and authentication.
    """
    try:
        # Retrieve an AD2 device that has been exposed with ser2sock on localhost:10000.
        ssl_device = SocketDevice(interface=('localhost', 10000))

        # Enable SSL and set the certificates to be used.
        #
        # The key/cert attributes can either be a filesystem path or an X509/PKey
        # object from pyopenssl.
        ssl_device.ssl = True
        ssl_device.ssl_ca = SSL_CA              # CA certificate
        ssl_device.ssl_key = SSL_KEY            # Client private key
        ssl_device.ssl_certificate = SSL_CERT   # Client certificate

        device = AlarmDecoder(ssl_device)

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

    except Exception, ex:
        print 'Exception:', ex
Пример #2
0
    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,
        )
Пример #3
0
def main():
    """
    Example application that opens a device that has been exposed to the network
    with ser2sock and SSL encryption and authentication.
    """
    try:
        # Retrieve an AD2 device that has been exposed with ser2sock on localhost:10000.
        ssl_device = SocketDevice(interface=('localhost', 10000))

        # Enable SSL and set the certificates to be used.
        #
        # The key/cert attributes can either be a filesystem path or an X509/PKey
        # object from pyopenssl.
        ssl_device.ssl = True
        ssl_device.ssl_ca = SSL_CA  # CA certificate
        ssl_device.ssl_key = SSL_KEY  # Client private key
        ssl_device.ssl_certificate = SSL_CERT  # Client certificate

        device = AlarmDecoder(ssl_device)

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

    except Exception, ex:
        print 'Exception:', ex
Пример #4
0
def main():
    """
    Example application that opens a device that has been exposed to the network
    with ser2sock or similar serial-to-IP software.
    """
    try:
        # Retrieve an AD2 device that has been exposed with ser2sock on localhost:10000.
        device = AlarmDecoder(SocketDevice(interface=(HOSTNAME, PORT)))

        # 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)
Пример #5
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
Пример #6
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
Пример #7
0
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
Пример #8
0
 def setUp(self):
     self._device = SocketDevice()
     self._device._device = Mock(spec=socket.socket)
Пример #9
0
class TestSocketDevice(TestCase):
    def setUp(self):
        self._device = SocketDevice()
        self._device._device = Mock(spec=socket.socket)

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

    def test_open(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect',
                              return_value=None) as mock:
                self._device.open(no_reader_thread=True)

        mock.assert_called_with(self._device.interface)

    def test_open_failed(self):
        with patch.object(socket.socket, 'connect', side_effect=socket.error):
            with self.assertRaises(NoDeviceError):
                self._device.open(no_reader_thread=True)

    def test_write(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None):
                self._device.open(no_reader_thread=True)

            with patch.object(socket.socket, 'send') as mock:
                self._device.write(b'test')

            mock.assert_called_with(b'test')

    def test_write_exception(self):
        side_effects = [socket.error]
        if (have_openssl):
            side_effects.append(SSL.Error)

        with patch.object(self._device._device,
                          'send',
                          side_effect=side_effects):
            with self.assertRaises(CommError):
                self._device.write(b'test')

    def test_read(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None):
                self._device.open(no_reader_thread=True)

            with patch('socket.socket.fileno', return_value=1):
                with patch.object(select, 'select', return_value=[[1], [],
                                                                  []]):
                    with patch.object(socket.socket, 'recv') as mock:
                        self._device.read()

            mock.assert_called_with(1)

    def test_read_exception(self):
        with patch('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device,
                                  'recv',
                                  side_effect=socket.error):
                    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('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device,
                                  'recv',
                                  side_effect=side_effect):
                    ret = None
                    try:
                        ret = self._device.read_line()
                    except StopIteration:
                        pass

            self.assertEquals(ret, "testing")

    def test_read_line_timeout(self):
        with patch('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device,
                                  'recv',
                                  return_value=b'a') as mock:
                    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('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device,
                                  'recv',
                                  side_effect=socket.error):
                    with self.assertRaises(CommError):
                        self._device.read_line()

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

    def test_ssl(self):
        if not have_openssl:
            return

        ssl_key = crypto.PKey()
        ssl_key.generate_key(crypto.TYPE_RSA, 2048)
        ssl_cert = crypto.X509()
        ssl_cert.set_pubkey(ssl_key)
        ssl_ca_key = crypto.PKey()
        ssl_ca_key.generate_key(crypto.TYPE_RSA, 2048)
        ssl_ca_cert = crypto.X509()
        ssl_ca_cert.set_pubkey(ssl_ca_key)

        self._device.ssl = True
        self._device.ssl_key = ssl_key
        self._device.ssl_certificate = ssl_cert
        self._device.ssl_ca = ssl_ca_cert

        fileno, path = tempfile.mkstemp()

        # ..there has to be a better way..
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect',
                              return_value=None) as mock:
                with patch.object(socket.socket, '_sock'):
                    with patch.object(socket.socket,
                                      'fileno',
                                      return_value=fileno):
                        try:
                            self._device.open(no_reader_thread=True)
                        except SSL.SysCallError as ex:
                            pass

        os.close(fileno)
        os.unlink(path)

        mock.assert_called_with(self._device.interface)
        self.assertIsInstance(self._device._device, SSL.Connection)

    def test_ssl_exception(self):
        if not have_openssl:
            return

        self._device.ssl = True
        self._device.ssl_key = 'None'
        self._device.ssl_certificate = 'None'
        self._device.ssl_ca = 'None'

        fileno, path = tempfile.mkstemp()

        # ..there has to be a better way..
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect',
                              return_value=None) as mock:
                with patch.object(socket.socket, '_sock'):
                    with patch.object(socket.socket,
                                      'fileno',
                                      return_value=fileno):
                        with self.assertRaises(CommError):
                            try:
                                self._device.open(no_reader_thread=True)
                            except SSL.SysCallError as ex:
                                pass

        os.close(fileno)
        os.unlink(path)
Пример #10
0
 def setUp(self):
     self._device = SocketDevice()
     self._device._device = Mock(spec=socket.socket)
Пример #11
0
class TestSocketDevice(TestCase):
    def setUp(self):
        self._device = SocketDevice()
        self._device._device = Mock(spec=socket.socket)

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

    ### Tests
    def test_open(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None) as mock:
                self._device.open(no_reader_thread=True)

        mock.assert_called_with(self._device.interface)

    def test_open_failed(self):
        with patch.object(socket.socket, 'connect', side_effect=socket.error):
            with self.assertRaises(NoDeviceError):
                self._device.open(no_reader_thread=True)

    def test_write(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None):
                self._device.open(no_reader_thread=True)

            with patch.object(socket.socket, 'send') as mock:
                self._device.write(b'test')

            mock.assert_called_with(b'test')

    def test_write_exception(self):
        side_effects = [socket.error]
        if (have_openssl):
            side_effects.append(SSL.Error)

        with patch.object(self._device._device, 'send', side_effect=side_effects):
            with self.assertRaises(CommError):
                self._device.write(b'test')

    def test_read(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None):
                self._device.open(no_reader_thread=True)

            with patch('socket.socket.fileno', return_value=1):
                with patch.object(select, 'select', return_value=[[1], [], []]):
                    with patch.object(socket.socket, 'recv') as mock:
                        self._device.read()

            mock.assert_called_with(1)

    def test_read_exception(self):
        with patch('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device, 'recv', side_effect=socket.error):
                    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('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device, 'recv', side_effect=side_effect):
                    ret = None
                    try:
                        ret = self._device.read_line()
                    except StopIteration:
                        pass

            self.assertEquals(ret, "testing")

    def test_read_line_timeout(self):
        with patch('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device, 'recv', return_value=b'a') as mock:
                    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('socket.socket.fileno', return_value=1):
            with patch.object(select, 'select', return_value=[[1], [], []]):
                with patch.object(self._device._device, 'recv', side_effect=socket.error):
                    with self.assertRaises(CommError):
                        self._device.read_line()

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

    def test_ssl(self):
        if not have_openssl:
            return

        ssl_key = crypto.PKey()
        ssl_key.generate_key(crypto.TYPE_RSA, 2048)
        ssl_cert = crypto.X509()
        ssl_cert.set_pubkey(ssl_key)
        ssl_ca_key = crypto.PKey()
        ssl_ca_key.generate_key(crypto.TYPE_RSA, 2048)
        ssl_ca_cert = crypto.X509()
        ssl_ca_cert.set_pubkey(ssl_ca_key)

        self._device.ssl = True
        self._device.ssl_key = ssl_key
        self._device.ssl_certificate = ssl_cert
        self._device.ssl_ca = ssl_ca_cert

        fileno, path = tempfile.mkstemp()

        # ..there has to be a better way..
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None) as mock:
                with patch.object(socket.socket, '_sock'):
                    with patch.object(socket.socket, 'fileno', return_value=fileno):
                        try:
                            self._device.open(no_reader_thread=True)
                        except SSL.SysCallError as ex:
                            pass

        os.close(fileno)
        os.unlink(path)

        mock.assert_called_with(self._device.interface)
        self.assertIsInstance(self._device._device, SSL.Connection)

    def test_ssl_exception(self):
        if not have_openssl:
            return

        self._device.ssl = True
        self._device.ssl_key = 'None'
        self._device.ssl_certificate = 'None'
        self._device.ssl_ca = 'None'

        fileno, path = tempfile.mkstemp()

        # ..there has to be a better way..
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None) as mock:
                with patch.object(socket.socket, '_sock'):
                    with patch.object(socket.socket, 'fileno', return_value=fileno):
                        with self.assertRaises(CommError):
                            try:
                                self._device.open(no_reader_thread=True)
                            except SSL.SysCallError as ex:
                                pass

        os.close(fileno)
        os.unlink(path)
Пример #12
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
Пример #13
0
class TestSocketDevice(TestCase):
    def setUp(self):
        self._device = SocketDevice()
        self._device._device = Mock(spec=socket.socket)

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

    def test_open(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None) as mock:
                self._device.open(no_reader_thread=True)

        mock.assert_called_with(self._device.interface)

    def test_open_failed(self):
        with patch.object(socket.socket, 'connect', side_effect=socket.error):
            with self.assertRaises(NoDeviceError):
                self._device.open(no_reader_thread=True)

    def test_write(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None):
                self._device.open(no_reader_thread=True)

            with patch.object(socket.socket, 'send') as mock:
                self._device.write('test')

            mock.assert_called_with('test')

    def test_write_exception(self):
        with patch.object(self._device._device, 'send', side_effect=[SSL.Error, socket.error]):
            with self.assertRaises(CommError):
                self._device.write('test')

    def test_read(self):
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None):
                self._device.open(no_reader_thread=True)

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

            mock.assert_called_with(1)

    def test_read_exception(self):
        with patch.object(self._device._device, 'recv', side_effect=socket.error):
            with self.assertRaises(CommError):
                self._device.read()

    def test_read_line(self):
        with patch.object(self._device._device, 'recv', 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, 'recv', 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, 'recv', side_effect=socket.error):
            with self.assertRaises(CommError):
                self._device.read_line()

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

    def test_ssl(self):
        ssl_key = crypto.PKey()
        ssl_key.generate_key(crypto.TYPE_RSA, 2048)
        ssl_cert = crypto.X509()
        ssl_cert.set_pubkey(ssl_key)
        ssl_ca_key = crypto.PKey()
        ssl_ca_key.generate_key(crypto.TYPE_RSA, 2048)
        ssl_ca_cert = crypto.X509()
        ssl_ca_cert.set_pubkey(ssl_ca_key)

        self._device.ssl = True
        self._device.ssl_key = ssl_key
        self._device.ssl_certificate = ssl_cert
        self._device.ssl_ca = ssl_ca_cert

        fileno, path = tempfile.mkstemp()

        # ..there has to be a better way..
        with patch.object(socket.socket, '__init__', return_value=None):
            with patch.object(socket.socket, 'connect', return_value=None) as mock:
                with patch.object(socket.socket, '_sock'):
                    with patch.object(socket.socket, 'fileno', return_value=fileno):
                        try:
                            self._device.open(no_reader_thread=True)
                        except SSL.SysCallError, ex:
                            pass

        os.close(fileno)
        os.unlink(path)

        mock.assert_called_with(self._device.interface)
        self.assertIsInstance(self._device._device, SSL.Connection)