diff --git a/alarmdecoder/decoder.py b/alarmdecoder/decoder.py index 84fa521..0cdee41 100644 --- a/alarmdecoder/decoder.py +++ b/alarmdecoder/decoder.py @@ -152,7 +152,7 @@ class AlarmDecoder(object): self._panic_status = False self._relay_status = {} self._internal_address_mask = 0xFFFFFFFF - + self.last_fault_expansion = 0 self.fault_expansion_time_limit = 30 # Seconds @@ -251,17 +251,26 @@ class AlarmDecoder(object): self._internal_address_mask = value def open(self, baudrate=None, no_reader_thread=False): - """ - Opens the device. + """Opens the device. + + If the device cannot be opened, an except is thrown. In that + case, open() can be called repeatedly to try and open the + connection. :param baudrate: baudrate used for the device. Defaults to the lower-level device default. :type baudrate: int :param no_reader_thread: Specifies whether or not the automatic reader thread should be started. :type no_reader_thread: bool + """ self._wire_events() - self._device.open(baudrate=baudrate, no_reader_thread=no_reader_thread) + try: + self._device.open(baudrate=baudrate, + no_reader_thread=no_reader_thread) + except: + self._unwire_events + raise return self @@ -269,11 +278,8 @@ class AlarmDecoder(object): """ Closes the device. """ - if self._device: - self._device.close() - - del self._device - self._device = None + self._device.close() + self._unwire_events() def send(self, data): """ @@ -387,6 +393,17 @@ class AlarmDecoder(object): self._zonetracker.on_fault += self._on_zone_fault self._zonetracker.on_restore += self._on_zone_restore + def _unwire_events(self): + """ + Wires up the internal device events. + """ + self._device.on_open -= self._on_open + self._device.on_close -= self._on_close + self._device.on_read -= self._on_read + self._device.on_write -= self._on_write + self._zonetracker.on_fault -= self._on_zone_fault + self._zonetracker.on_restore -= self._on_zone_restore + def _handle_message(self, data): """ Parses keypad messages from the panel. @@ -792,7 +809,7 @@ class AlarmDecoder(object): # Handle bouncing status changes and timeout in order to revert back to NONE. if last_status != fire_status or fire_status == True: self._fire_status = (fire_status, time.time()) - + if fire_status == False and time.time() > last_update + self._fire_timeout: self._fire_state = FireState.NONE self.on_fire(status=FireState.NONE) diff --git a/test/test_devices.py b/test/test_devices.py index 604af8d..a46b10a 100644 --- a/test/test_devices.py +++ b/test/test_devices.py @@ -1,11 +1,6 @@ from unittest import TestCase from mock import Mock, MagicMock, patch from serial import Serial, SerialException -try: - from pyftdi.pyftdi.ftdi import Ftdi, FtdiError -except: - from pyftdi.ftdi import Ftdi, FtdiError -from usb.core import USBError, Device as USBCoreDevice import sys import socket import time