From b4ec42ffd1f919a50af405020f47f866f0e43859 Mon Sep 17 00:00:00 2001 From: Scott Petersen Date: Fri, 22 Nov 2013 15:10:01 -0800 Subject: [PATCH] Bugfixes, naming changes, error handling. --- pyad2/ad2.py | 12 +++++----- pyad2/devices.py | 21 +++++++++-------- pyad2/messages.py | 58 +++++++++++++++++++++++++++++------------------ 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/pyad2/ad2.py b/pyad2/ad2.py index 49db928..4a0b119 100644 --- a/pyad2/ad2.py +++ b/pyad2/ad2.py @@ -65,9 +65,9 @@ class Overseer(object): device = cls.__devices[0] vendor, product, sernum, ifcount, description = device - device = devices.USBDevice(serial=sernum, description=description) + device = devices.USBDevice((sernum, ifcount - 1)) - return AD2USB(device) + return AD2(device) def __init__(self, attached_event=None, detached_event=None): """ @@ -169,7 +169,7 @@ class Overseer(object): time.sleep(0.25) -class AD2USB(object): +class AD2(object): """ High-level wrapper around AD2USB/AD2SERIAL devices. """ @@ -329,6 +329,7 @@ class AD2USB(object): :param simulate_wire_problem: Whether or not to simulate a wire fault. :type simulate_wire_problem: bool """ + # Allow ourselves to also be passed an address/channel combination # for zone expanders. # @@ -418,7 +419,6 @@ class AD2USB(object): """ msg = messages.LRRMessage(data) - args = (msg.partition, msg.event_type, msg.event_data) if msg.event_type == 'ALARM_PANIC': self._panic_status = True self.on_panic(True) @@ -500,14 +500,14 @@ class AD2USB(object): if message.battery_low == self._battery_status[0]: self._battery_status = (self._battery_status[0], time.time()) else: - if message.battery_low == True or time.time() > self._battery_status[1] + AD2USB.BATTERY_TIMEOUT: + if message.battery_low == True or time.time() > self._battery_status[1] + AD2.BATTERY_TIMEOUT: self._battery_status = (message.battery_low, time.time()) self.on_low_battery(self._battery_status) if message.fire_alarm == self._fire_status[0]: self._fire_status = (self._fire_status[0], time.time()) else: - if message.fire_alarm == True or time.time() > self._fire_status[1] + AD2USB.FIRE_TIMEOUT: + if message.fire_alarm == True or time.time() > self._fire_status[1] + AD2.FIRE_TIMEOUT: self._fire_status = (message.fire_alarm, time.time()) self.on_fire(self._fire_status) diff --git a/pyad2/devices.py b/pyad2/devices.py index 1fecb33..af74a67 100644 --- a/pyad2/devices.py +++ b/pyad2/devices.py @@ -166,17 +166,17 @@ class USBDevice(Device): :returns: the interface used to connect to the device. """ - return (self._device_number, self._endpoint) + return (self._serial_number, self._endpoint) @interface.setter def interface(self, value): """ Sets the interface used to connect to the device. - :param value: Tuple containing the device number and endpoint number to use. + :param value: Tuple containing the serial number and endpoint number to use. :type value: tuple """ - self._device_number = value[0] + self._serial_number = value[0] self._endpoint = value[1] @property @@ -218,7 +218,7 @@ class USBDevice(Device): """ self._description = value - def __init__(self, interface=(0, 0)): + def __init__(self, interface=(None, 0)): """ Constructor @@ -228,11 +228,11 @@ class USBDevice(Device): Device.__init__(self) self._device = Ftdi() - self._device_number = interface[0] + self._serial_number = interface[0] self._endpoint = interface[1] self._vendor_id = USBDevice.FTDI_VENDOR_ID self._product_id = USBDevice.FTDI_PRODUCT_ID - self._serial_number = None + self._device_number = None self._description = None def open(self, baudrate=BAUDRATE, no_reader_thread=False): @@ -369,7 +369,8 @@ class USBDevice(Device): self._buffer = self._buffer[:-1] except (usb.core.USBError, FtdiError), err: - timer.cancel() + if timer: + timer.cancel() raise util.CommError('Error reading from device: {0}'.format(str(err)), err) @@ -587,7 +588,8 @@ class SerialDevice(Device): self._buffer = self._buffer[:-1] except (OSError, serial.SerialException), err: - timer.cancel() + if timer: + timer.cancel() raise util.CommError('Error reading from device: {0}'.format(str(err)), err) @@ -862,7 +864,8 @@ class SocketDevice(Device): self._buffer = self._buffer[:-1] except socket.error, err: - timer.cancel() + if timer: + timer.cancel() raise util.CommError('Error reading from device: {0}'.format(str(err)), err) diff --git a/pyad2/messages.py b/pyad2/messages.py index 1028519..36b29e6 100644 --- a/pyad2/messages.py +++ b/pyad2/messages.py @@ -5,6 +5,7 @@ Message representations received from the panel through the AD2USB. """ import re +from . import util class BaseMessage(object): """ @@ -145,13 +146,17 @@ class ExpanderMessage(BaseMessage): :param data: The message data :type data: str """ - header, values = data.split(':') - address, channel, value = values.split(',') + try: + header, values = data.split(':') + address, channel, value = values.split(',') - self.raw = data - self.address = int(address) - self.channel = int(channel) - self.value = int(value) + self.raw = data + self.address = int(address) + self.channel = int(channel) + self.value = int(value) + + except ValueError: + raise util.InvalidMessageError('Received invalid message: {0}'.format(data)) if header == '!EXP': self.type = ExpanderMessage.ZONE @@ -193,22 +198,27 @@ class RFMessage(BaseMessage): :param data: The message data. :type data: str """ - self.raw = data + try: + self.raw = data + + _, values = data.split(':') + self.serial_number, self.value = values.split(',') + self.value = int(self.value, 16) - _, values = data.split(':') - self.serial_number, self.value = values.split(',') - self.value = int(self.value, 16) + is_bit_set = lambda b: self.value & (1 << b) > 0 - is_bit_set = lambda b: self.value & (1 << b) > 0 + # Bit 1 = unknown + self.battery = is_bit_set(2) + self.supervision = is_bit_set(3) + # Bit 8 = unknown + self.loop[0] = is_bit_set(5) + self.loop[1] = is_bit_set(6) + self.loop[2] = is_bit_set(7) + self.loop[3] = is_bit_set(8) + + except ValueError: + raise util.InvalidMessageError('Received invalid message: {0}'.format(data)) - # Bit 1 = unknown - self.battery = is_bit_set(2) - self.supervision = is_bit_set(3) - # Bit 8 = unknown - self.loop[0] = is_bit_set(5) - self.loop[1] = is_bit_set(6) - self.loop[2] = is_bit_set(7) - self.loop[3] = is_bit_set(8) class LRRMessage(BaseMessage): """ @@ -243,7 +253,11 @@ class LRRMessage(BaseMessage): :param data: The message data. :type data: str """ - self.raw = data + try: + self.raw = data - _, values = data.split(':') - self.event_data, self.partition, self.event_type = values.split(',') + _, values = data.split(':') + self.event_data, self.partition, self.event_type = values.split(',') + + except ValueError: + raise util.InvalidMessageError('Received invalid message: {0}'.format(data))