Browse Source

Initial pass.

pyserial_fix
Scott Petersen 10 years ago
parent
commit
f4fe9be40b
5 changed files with 63 additions and 54 deletions
  1. +21
    -15
      alarmdecoder/decoder.py
  2. +35
    -35
      alarmdecoder/devices.py
  3. +5
    -3
      alarmdecoder/messages.py
  4. +1
    -0
      alarmdecoder/util.py
  5. +1
    -1
      alarmdecoder/zonetracking.py

+ 21
- 15
alarmdecoder/decoder.py View File

@@ -9,6 +9,8 @@ Provides the main AlarmDecoder class.
import time import time
import re import re


from builtins import chr

from .event import event from .event import event
from .util import InvalidMessageError from .util import InvalidMessageError
from .messages import Message, ExpanderMessage, RFMessage, LRRMessage from .messages import Message, ExpanderMessage, RFMessage, LRRMessage
@@ -51,15 +53,15 @@ class AlarmDecoder(object):
on_write = event.Event("This event is called when data has been written to the device.\n\n**Callback definition:** *def callback(device, data)*") on_write = event.Event("This event is called when data has been written to the device.\n\n**Callback definition:** *def callback(device, data)*")


# Constants # Constants
KEY_F1 = unichr(1) + unichr(1) + unichr(1)
KEY_F1 = chr(1) + chr(1) + chr(1)
"""Represents panel function key #1""" """Represents panel function key #1"""
KEY_F2 = unichr(2) + unichr(2) + unichr(2)
KEY_F2 = chr(2) + chr(2) + chr(2)
"""Represents panel function key #2""" """Represents panel function key #2"""
KEY_F3 = unichr(3) + unichr(3) + unichr(3)
KEY_F3 = chr(3) + chr(3) + chr(3)
"""Represents panel function key #3""" """Represents panel function key #3"""
KEY_F4 = unichr(4) + unichr(4) + unichr(4)
KEY_F4 = chr(4) + chr(4) + chr(4)
"""Represents panel function key #4""" """Represents panel function key #4"""
KEY_PANIC = unichr(5) + unichr(5) + unichr(5)
KEY_PANIC = chr(5) + chr(5) + chr(5)
"""Represents a panic keypress""" """Represents a panic keypress"""


BATTERY_TIMEOUT = 30 BATTERY_TIMEOUT = 30
@@ -74,9 +76,9 @@ class AlarmDecoder(object):
"""The configuration bits set on the device.""" """The configuration bits set on the device."""
address_mask = 0xFFFFFFFF address_mask = 0xFFFFFFFF
"""The address mask configured on the device.""" """The address mask configured on the device."""
emulate_zone = [False for _ in range(5)]
emulate_zone = [False for _ in list(range(5))]
"""List containing the devices zone emulation status.""" """List containing the devices zone emulation status."""
emulate_relay = [False for _ in range(4)]
emulate_relay = [False for _ in list(range(4))]
"""List containing the devices relay emulation status.""" """List containing the devices relay emulation status."""
emulate_lrr = False emulate_lrr = False
"""The status of the devices LRR emulation.""" """The status of the devices LRR emulation."""
@@ -87,7 +89,7 @@ class AlarmDecoder(object):


def __init__(self, device): def __init__(self, device):
""" """
Constructor
Constructora


:param device: The low-level device used for this `AlarmDecoder`_ :param device: The low-level device used for this `AlarmDecoder`_
interface. interface.
@@ -110,8 +112,8 @@ class AlarmDecoder(object):
self.address = 18 self.address = 18
self.configbits = 0xFF00 self.configbits = 0xFF00
self.address_mask = 0x00000000 self.address_mask = 0x00000000
self.emulate_zone = [False for x in range(5)]
self.emulate_relay = [False for x in range(4)]
self.emulate_zone = [False for x in list(range(5))]
self.emulate_relay = [False for x in list(range(4))]
self.emulate_lrr = False self.emulate_lrr = False
self.deduplicate = False self.deduplicate = False
self.mode = ADEMCO self.mode = ADEMCO
@@ -211,13 +213,13 @@ class AlarmDecoder(object):
""" """


if self._device: if self._device:
self._device.write(str(data))
self._device.write(data)


def get_config(self): def get_config(self):
""" """
Retrieves the configuration from the device. Called automatically by :py:meth:`_on_open`. Retrieves the configuration from the device. Called automatically by :py:meth:`_on_open`.
""" """
self.send("C\r")
self.send(b"C\r")


def save_config(self): def save_config(self):
""" """
@@ -236,7 +238,7 @@ class AlarmDecoder(object):
''.join(['Y' if r else 'N' for r in self.emulate_relay]))) ''.join(['Y' if r else 'N' for r in self.emulate_relay])))
config_entries.append(('LRR', 'Y' if self.emulate_lrr else 'N')) config_entries.append(('LRR', 'Y' if self.emulate_lrr else 'N'))
config_entries.append(('DEDUPLICATE', 'Y' if self.deduplicate else 'N')) config_entries.append(('DEDUPLICATE', 'Y' if self.deduplicate else 'N'))
config_entries.append(('MODE', PANEL_TYPES.keys()[PANEL_TYPES.values().index(self.mode)]))
config_entries.append(('MODE', list(PANEL_TYPES)[list(PANEL_TYPES.values()).index(self.mode)]))


config_string = '&'.join(['='.join(t) for t in config_entries]) config_string = '&'.join(['='.join(t) for t in config_entries])


@@ -301,6 +303,8 @@ class AlarmDecoder(object):
:returns: :py:class:`~alarmdecoder.messages.Message` :returns: :py:class:`~alarmdecoder.messages.Message`
""" """


data = str(data)

if data is not None: if data is not None:
data = data.lstrip('\0') data = data.lstrip('\0')


@@ -310,6 +314,8 @@ class AlarmDecoder(object):
msg = None msg = None
header = data[0:4] header = data[0:4]


#print('header', header, type(header), type(header[0]))

if header[0] != '!' or header == '!KPM': if header[0] != '!' or header == '!KPM':
msg = self._handle_keypad_message(data) msg = self._handle_keypad_message(data)


@@ -424,9 +430,9 @@ class AlarmDecoder(object):
elif key == 'MASK': elif key == 'MASK':
self.address_mask = int(val, 16) self.address_mask = int(val, 16)
elif key == 'EXP': elif key == 'EXP':
self.emulate_zone = [val[z] == 'Y' for z in range(5)]
self.emulate_zone = [val[z] == 'Y' for z in list(range(5))]
elif key == 'REL': elif key == 'REL':
self.emulate_relay = [val[r] == 'Y' for r in range(4)]
self.emulate_relay = [val[r] == 'Y' for r in list(range(4))]
elif key == 'LRR': elif key == 'LRR':
self.emulate_lrr = (val == 'Y') self.emulate_lrr = (val == 'Y')
elif key == 'DEDUPLICATE': elif key == 'DEDUPLICATE':


+ 35
- 35
alarmdecoder/devices.py View File

@@ -61,7 +61,7 @@ class Device(object):
Constructor Constructor
""" """
self._id = '' self._id = ''
self._buffer = ''
self._buffer = b''
self._device = None self._device = None
self._running = False self._running = False
self._read_thread = None self._read_thread = None
@@ -171,10 +171,10 @@ class Device(object):
except SSL.WantReadError: except SSL.WantReadError:
pass pass


except CommError, err:
except CommError:
self._device.close() self._device.close()


except Exception, err:
except Exception:
self._device.close() self._device.close()
self._running = False self._running = False
raise raise
@@ -226,7 +226,7 @@ class USBDevice(Device):
try: try:
cls.__devices = Ftdi.find_all(query, nocache=True) cls.__devices = Ftdi.find_all(query, nocache=True)


except (usb.core.USBError, FtdiError), err:
except (usb.core.USBError, FtdiError) as err:
raise CommError('Error enumerating AD2USB devices: {0}'.format(str(err)), err) raise CommError('Error enumerating AD2USB devices: {0}'.format(str(err)), err)


return cls.__devices return cls.__devices
@@ -433,10 +433,10 @@ class USBDevice(Device):


self._id = self._serial_number self._id = self._serial_number


except (usb.core.USBError, FtdiError), err:
except (usb.core.USBError, FtdiError) as err:
raise NoDeviceError('Error opening device: {0}'.format(str(err)), err) raise NoDeviceError('Error opening device: {0}'.format(str(err)), err)


except KeyError, err:
except KeyError as err:
raise NoDeviceError('Unsupported device. ({0:04x}:{1:04x}) You probably need a newer version of pyftdi.'.format(err[0][0], err[0][1])) raise NoDeviceError('Unsupported device. ({0:04x}:{1:04x}) You probably need a newer version of pyftdi.'.format(err[0][0], err[0][1]))


else: else:
@@ -478,7 +478,7 @@ class USBDevice(Device):


self.on_write(data=data) self.on_write(data=data)


except FtdiError, err:
except FtdiError as err:
raise CommError('Error writing to device: {0}'.format(str(err)), err) raise CommError('Error writing to device: {0}'.format(str(err)), err)


def read(self): def read(self):
@@ -493,7 +493,7 @@ class USBDevice(Device):
try: try:
ret = self._device.read_data(1) ret = self._device.read_data(1)


except (usb.core.USBError, FtdiError), err:
except (usb.core.USBError, FtdiError) as err:
raise CommError('Error reading from device: {0}'.format(str(err)), err) raise CommError('Error reading from device: {0}'.format(str(err)), err)


return ret return ret
@@ -518,7 +518,7 @@ class USBDevice(Device):
timeout_event.reading = True timeout_event.reading = True


if purge_buffer: if purge_buffer:
self._buffer = ''
self._buffer = b''


got_line, ret = False, None got_line, ret = False, None


@@ -530,11 +530,11 @@ class USBDevice(Device):
while timeout_event.reading: while timeout_event.reading:
buf = self._device.read_data(1) buf = self._device.read_data(1)


if buf != '':
if buf != b'':
self._buffer += buf self._buffer += buf


if buf == "\n":
self._buffer = self._buffer.rstrip("\r\n")
if buf == b"\n":
self._buffer = self._buffer.rstrip(b"\r\n")


if len(self._buffer) > 0: if len(self._buffer) > 0:
got_line = True got_line = True
@@ -542,12 +542,12 @@ class USBDevice(Device):
else: else:
time.sleep(0.01) time.sleep(0.01)


except (usb.core.USBError, FtdiError), err:
except (usb.core.USBError, FtdiError) as err:
raise CommError('Error reading from device: {0}'.format(str(err)), err) raise CommError('Error reading from device: {0}'.format(str(err)), err)


else: else:
if got_line: if got_line:
ret, self._buffer = self._buffer, ''
ret, self._buffer = self._buffer, b''


self.on_read(data=ret) self.on_read(data=ret)


@@ -653,7 +653,7 @@ class SerialDevice(Device):
else: else:
devices = serial.tools.list_ports.comports() devices = serial.tools.list_ports.comports()


except serial.SerialException, err:
except serial.SerialException as err:
raise CommError('Error enumerating serial devices: {0}'.format(str(err)), err) raise CommError('Error enumerating serial devices: {0}'.format(str(err)), err)


return devices return devices
@@ -724,7 +724,7 @@ class SerialDevice(Device):
# all issues with it. # all issues with it.
self._device.baudrate = baudrate self._device.baudrate = baudrate


except (serial.SerialException, ValueError, OSError), err:
except (serial.SerialException, ValueError, OSError) as err:
raise NoDeviceError('Error opening device on {0}.'.format(self._port), err) raise NoDeviceError('Error opening device on {0}.'.format(self._port), err)


else: else:
@@ -764,7 +764,7 @@ class SerialDevice(Device):
except serial.SerialTimeoutException: except serial.SerialTimeoutException:
pass pass


except serial.SerialException, err:
except serial.SerialException as err:
raise CommError('Error writing to device.', err) raise CommError('Error writing to device.', err)


else: else:
@@ -782,7 +782,7 @@ class SerialDevice(Device):
try: try:
ret = self._device.read(1) ret = self._device.read(1)


except serial.SerialException, err:
except serial.SerialException as err:
raise CommError('Error reading from device: {0}'.format(str(err)), err) raise CommError('Error reading from device: {0}'.format(str(err)), err)


return ret return ret
@@ -807,7 +807,7 @@ class SerialDevice(Device):
timeout_event.reading = True timeout_event.reading = True


if purge_buffer: if purge_buffer:
self._buffer = ''
self._buffer = b''


got_line, ret = False, None got_line, ret = False, None


@@ -820,11 +820,11 @@ class SerialDevice(Device):
buf = self._device.read(1) buf = self._device.read(1)


# NOTE: AD2SERIAL apparently sends down \xFF on boot. # NOTE: AD2SERIAL apparently sends down \xFF on boot.
if buf != '' and buf != "\xff":
if buf != b'' and buf != b"\xff":
self._buffer += buf self._buffer += buf


if buf == "\n":
self._buffer = self._buffer.rstrip("\r\n")
if buf == b"\n":
self._buffer = self._buffer.rstrip(b"\r\n")


if len(self._buffer) > 0: if len(self._buffer) > 0:
got_line = True got_line = True
@@ -832,12 +832,12 @@ class SerialDevice(Device):
else: else:
time.sleep(0.01) time.sleep(0.01)


except (OSError, serial.SerialException), err:
except (OSError, serial.SerialException) as err:
raise CommError('Error reading from device: {0}'.format(str(err)), err) raise CommError('Error reading from device: {0}'.format(str(err)), err)


else: else:
if got_line: if got_line:
ret, self._buffer = self._buffer, ''
ret, self._buffer = self._buffer, b''


self.on_read(data=ret) self.on_read(data=ret)


@@ -1001,7 +1001,7 @@ class SocketDevice(Device):


self._id = '{0}:{1}'.format(self._host, self._port) self._id = '{0}:{1}'.format(self._host, self._port)


except socket.error, err:
except socket.error as err:
raise NoDeviceError('Error opening device at {0}:{1}'.format(self._host, self._port), err) raise NoDeviceError('Error opening device at {0}:{1}'.format(self._host, self._port), err)


else: else:
@@ -1054,7 +1054,7 @@ class SocketDevice(Device):


self.on_write(data=data) self.on_write(data=data)


except (SSL.Error, socket.error), err:
except (SSL.Error, socket.error) as err:
raise CommError('Error writing to device.', err) raise CommError('Error writing to device.', err)


return data_sent return data_sent
@@ -1071,7 +1071,7 @@ class SocketDevice(Device):
try: try:
data = self._device.recv(1) data = self._device.recv(1)


except socket.error, err:
except socket.error as err:
raise CommError('Error while reading from device: {0}'.format(str(err)), err) raise CommError('Error while reading from device: {0}'.format(str(err)), err)


return data return data
@@ -1096,7 +1096,7 @@ class SocketDevice(Device):
timeout_event.reading = True timeout_event.reading = True


if purge_buffer: if purge_buffer:
self._buffer = ''
self._buffer = b''


got_line, ret = False, None got_line, ret = False, None


@@ -1108,11 +1108,11 @@ class SocketDevice(Device):
while timeout_event.reading: while timeout_event.reading:
buf = self._device.recv(1) buf = self._device.recv(1)


if buf != '':
if buf != b'':
self._buffer += buf self._buffer += buf


if buf == "\n":
self._buffer = self._buffer.rstrip("\r\n")
if buf == b"\n":
self._buffer = self._buffer.rstrip(b"\r\n")


if len(self._buffer) > 0: if len(self._buffer) > 0:
got_line = True got_line = True
@@ -1120,10 +1120,10 @@ class SocketDevice(Device):
else: else:
time.sleep(0.01) time.sleep(0.01)


except socket.error, err:
except socket.error as err:
raise CommError('Error reading from device: {0}'.format(str(err)), err) raise CommError('Error reading from device: {0}'.format(str(err)), err)


except SSL.SysCallError, err:
except SSL.SysCallError as err:
errno, msg = err errno, msg = err
raise CommError('SSL error while reading from device: {0} ({1})'.format(msg, errno)) raise CommError('SSL error while reading from device: {0} ({1})'.format(msg, errno))


@@ -1132,7 +1132,7 @@ class SocketDevice(Device):


else: else:
if got_line: if got_line:
ret, self._buffer = self._buffer, ''
ret, self._buffer = self._buffer, b''


self.on_read(data=ret) self.on_read(data=ret)


@@ -1177,7 +1177,7 @@ class SocketDevice(Device):


self._device = SSL.Connection(ctx, self._device) self._device = SSL.Connection(ctx, self._device)


except SSL.Error, err:
except SSL.Error as err:
raise CommError('Error setting up SSL connection.', err) raise CommError('Error setting up SSL connection.', err)


def _verify_ssl_callback(self, connection, x509, errnum, errdepth, ok): def _verify_ssl_callback(self, connection, x509, errnum, errdepth, ok):


+ 5
- 3
alarmdecoder/messages.py View File

@@ -15,6 +15,8 @@ devices.
import re import re
import datetime import datetime


from reprlib import repr

from .util import InvalidMessageError from .util import InvalidMessageError
from .panels import PANEL_TYPES, ADEMCO, DSC from .panels import PANEL_TYPES, ADEMCO, DSC


@@ -136,7 +138,7 @@ class Message(BaseMessage):


:raises: :py:class:`~alarmdecoder.util.InvalidMessageError` :raises: :py:class:`~alarmdecoder.util.InvalidMessageError`
""" """
match = self._regex.match(data)
match = self._regex.match(str(data))


if match is None: if match is None:
raise InvalidMessageError('Received invalid message: {0}'.format(data)) raise InvalidMessageError('Received invalid message: {0}'.format(data))
@@ -163,7 +165,7 @@ class Message(BaseMessage):
self.check_zone = is_bit_set(15) self.check_zone = is_bit_set(15)
self.perimeter_only = is_bit_set(16) self.perimeter_only = is_bit_set(16)
self.system_fault = is_bit_set(17) self.system_fault = is_bit_set(17)
if self.bitfield[18] in PANEL_TYPES.keys():
if self.bitfield[18] in list(PANEL_TYPES):
self.panel_type = PANEL_TYPES[self.bitfield[18]] self.panel_type = PANEL_TYPES[self.bitfield[18]]
# pos 20-21 - Unused. # pos 20-21 - Unused.
self.text = alpha.strip('"') self.text = alpha.strip('"')
@@ -292,7 +294,7 @@ class RFMessage(BaseMessage):
"""Low battery indication""" """Low battery indication"""
supervision = False supervision = False
"""Supervision required indication""" """Supervision required indication"""
loop = [False for _ in range(4)]
loop = [False for _ in list(range(4))]
"""Loop indicators""" """Loop indicators"""


def __init__(self, data=None): def __init__(self, data=None):


+ 1
- 0
alarmdecoder/util.py View File

@@ -8,6 +8,7 @@ Provides utility classes for the `AlarmDecoder`_ (AD2) devices.


import time import time
import threading import threading
from io import open




class NoDeviceError(Exception): class NoDeviceError(Exception):


+ 1
- 1
alarmdecoder/zonetracking.py View File

@@ -294,7 +294,7 @@ class Zonetracker(object):
""" """
zones = [] zones = []


for z in self._zones.keys():
for z in list(self._zones):
zones += [z] zones += [z]


for z in zones: for z in zones:


Loading…
Cancel
Save