Browse Source

Initial rename.

pyserial_fix
Scott Petersen 11 years ago
parent
commit
fa1eef5758
26 changed files with 205 additions and 203 deletions
  1. +12
    -12
      README.md
  2. +9
    -9
      bin/ad2-firmwareupload
  3. +2
    -2
      bin/ad2-sslterm
  4. +4
    -4
      docs/Makefile
  5. +14
    -14
      docs/conf.py
  6. +3
    -3
      docs/index.rst
  7. +2
    -2
      docs/make.bat
  8. +3
    -3
      docs/modules.rst
  9. +2
    -2
      docs/pyad2.event.rst
  10. +9
    -9
      docs/pyad2.rst
  11. +4
    -4
      examples/alarm_email.py
  12. +4
    -4
      examples/basics.py
  13. +5
    -5
      examples/detection.py
  14. +4
    -4
      examples/rf_device.py
  15. +4
    -4
      examples/serialport.py
  16. +4
    -4
      examples/socket_example.py
  17. +4
    -4
      examples/ssl_socket.py
  18. +9
    -9
      examples/virtual_zone_expander.py
  19. +2
    -2
      pyad2/__init__.py
  20. +8
    -8
      pyad2/ad2.py
  21. +8
    -6
      pyad2/devices.py
  22. +2
    -1
      pyad2/messages.py
  23. +77
    -77
      pyad2/tests/test_ad2.py
  24. +4
    -5
      pyad2/util.py
  25. +1
    -1
      pyad2/zonetracking.py
  26. +5
    -5
      setup.py

+ 12
- 12
README.md View File

@@ -1,31 +1,31 @@
pyAD2 - Python library for the AD2 device family
================================================
alarmdecoder - Python library for the Alarm Decoder (AD2) device family
=======================================================================


This Python module aims to provide a consistent interface for all of the AD2
product line, including the AD2USB, AD2SERIAL and AD2PI devices. This also
includes devices that have been exposed via [ser2sock](http://github.com/nutechsoftware/ser2sock) and supports encryption
via SSL/TLS.
This Python module aims to provide a consistent interface for all of the Alarm
Decoder product line, including the AD2USB, AD2SERIAL and AD2PI devices. This
also includes devices that have been exposed via [ser2sock](http://github.com/nutechsoftware/ser2sock) and supports
encryption via SSL/TLS.


Installation Installation
------------ ------------


pyAD2 can be installed through pip:
pip install pyad2
alarmdecoder can be installed through pip:
pip install alarmdecoder


or from source: or from source:
python setup.py install python setup.py install


Requirements Requirements
------------ ------------
* [pyopenssl](https://launchpad.net/pyopenssl)
* [pyftdi](https://github.com/eblot/pyftdi) >= 0.9.0
* [pyusb](http://sourceforge.net/apps/trac/pyusb/) >= 1.0.0b1 * [pyusb](http://sourceforge.net/apps/trac/pyusb/) >= 1.0.0b1
* [pyserial](http://pyserial.sourceforge.net/) >= 2.7 * [pyserial](http://pyserial.sourceforge.net/) >= 2.7
* [pyftdi](https://github.com/eblot/pyftdi) >= 0.9.0
* [pyopenssl](https://launchpad.net/pyopenssl)


Documentation Documentation
------------- -------------


API documentation can be found [here](http://github.com/nutechsoftware/pyad2/tree/master/docs/_build/html).
API documentation can be found [here](http://github.com/nutechsoftware/alarmdecoder/tree/master/docs/_build/html).


Examples Examples
-------- --------
@@ -36,4 +36,4 @@ Basic usage:


``` ```


Please see the [examples](http://github.com/nutechsoftware/pyad2/tree/master/examples) directory for more.
Please see the [examples](http://github.com/nutechsoftware/alarmdecoder/tree/master/examples) directory for more.

+ 9
- 9
bin/ad2-firmwareupload View File

@@ -1,25 +1,25 @@
#!/usr/bin/env python #!/usr/bin/env python


import sys, time import sys, time
import pyad2
import alarmdecoder


def handle_firmware(stage): def handle_firmware(stage):
if stage == pyad2.util.Firmware.STAGE_START:
if stage == alarmdecoder.util.Firmware.STAGE_START:
handle_firmware.wait_tick = 0 handle_firmware.wait_tick = 0
handle_firmware.upload_tick = 0 handle_firmware.upload_tick = 0
elif stage == pyad2.util.Firmware.STAGE_WAITING:
elif stage == alarmdecoder.util.Firmware.STAGE_WAITING:
if handle_firmware.wait_tick == 0: if handle_firmware.wait_tick == 0:
sys.stdout.write('Waiting for device.') sys.stdout.write('Waiting for device.')
handle_firmware.wait_tick += 1 handle_firmware.wait_tick += 1


sys.stdout.write('.') sys.stdout.write('.')
sys.stdout.flush() sys.stdout.flush()
elif stage == pyad2.util.Firmware.STAGE_BOOT:
elif stage == alarmdecoder.util.Firmware.STAGE_BOOT:
if handle_firmware.wait_tick > 0: print "" if handle_firmware.wait_tick > 0: print ""
print "Rebooting device.." print "Rebooting device.."
elif stage == pyad2.util.Firmware.STAGE_LOAD:
elif stage == alarmdecoder.util.Firmware.STAGE_LOAD:
print 'Waiting for boot loader..' print 'Waiting for boot loader..'
elif stage == pyad2.util.Firmware.STAGE_UPLOADING:
elif stage == alarmdecoder.util.Firmware.STAGE_UPLOADING:
if handle_firmware.upload_tick == 0: if handle_firmware.upload_tick == 0:
sys.stdout.write('Uploading firmware.') sys.stdout.write('Uploading firmware.')


@@ -28,7 +28,7 @@ def handle_firmware(stage):
if handle_firmware.upload_tick % 30 == 0: if handle_firmware.upload_tick % 30 == 0:
sys.stdout.write('.') sys.stdout.write('.')
sys.stdout.flush() sys.stdout.flush()
elif stage == pyad2.util.Firmware.STAGE_DONE:
elif stage == alarmdecoder.util.Firmware.STAGE_DONE:
print "\r\nDone!" print "\r\nDone!"


def main(): def main():
@@ -45,11 +45,11 @@ def main():


print "Flashing device: {0}\r\nFirmware: {1}".format(device, firmware) print "Flashing device: {0}\r\nFirmware: {1}".format(device, firmware)


dev = pyad2.devices.SerialDevice(interface=device)
dev = alarmdecoder.devices.SerialDevice(interface=device)
dev.open(baudrate=19200) dev.open(baudrate=19200)


time.sleep(3) time.sleep(3)
pyad2.util.Firmware.upload(dev, firmware, handle_firmware)
alarmdecoder.util.Firmware.upload(dev, firmware, handle_firmware)


dev.close() dev.close()




+ 2
- 2
bin/ad2-sslterm View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python


import pyad2
import alarmdecoder
import sys, select import sys, select
import termios, tty import termios, tty
import time import time
@@ -23,7 +23,7 @@ def main():
try: try:
print "Opening connection to {0}:{1}\r".format(host, port) print "Opening connection to {0}:{1}\r".format(host, port)


dev = pyad2.devices.SocketDevice(interface=(host, int(port)))
dev = alarmdecoder.devices.SocketDevice(interface=(host, int(port)))
dev.ssl = True dev.ssl = True
dev.ssl_certificate = client_cert dev.ssl_certificate = client_cert
dev.ssl_key = client_key dev.ssl_key = client_key


+ 4
- 4
docs/Makefile View File

@@ -85,17 +85,17 @@ qthelp:
@echo @echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:" ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyad2.qhcp"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/alarmdecoder.qhcp"
@echo "To view the help file:" @echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyad2.qhc"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/alarmdecoder.qhc"


devhelp: devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo @echo
@echo "Build finished." @echo "Build finished."
@echo "To view the help file:" @echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/pyad2"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyad2"
@echo "# mkdir -p $$HOME/.local/share/devhelp/alarmdecoder"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/alarmdecoder"
@echo "# devhelp" @echo "# devhelp"


epub: epub:


+ 14
- 14
docs/conf.py View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# pyad2 documentation build configuration file, created by
# alarmdecoder documentation build configuration file, created by
# sphinx-quickstart on Sat Jun 8 14:38:46 2013. # sphinx-quickstart on Sat Jun 8 14:38:46 2013.
# #
# This file is execfile()d with the current directory set to its containing dir. # This file is execfile()d with the current directory set to its containing dir.
@@ -40,8 +40,8 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'


# General information about the project. # General information about the project.
project = u'pyad2'
copyright = u'2013, Author'
project = u'alarmdecoder'
copyright = u'2013, Nu Tech Software Solutions, Inc.'


# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@@ -167,7 +167,7 @@ html_static_path = ['_static']
#html_file_suffix = None #html_file_suffix = None


# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'pyad2doc'
htmlhelp_basename = 'alarmdecoderdoc'




# -- Options for LaTeX output -------------------------------------------------- # -- Options for LaTeX output --------------------------------------------------
@@ -186,8 +186,8 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'pyad2.tex', u'pyad2 Documentation',
u'Author', 'manual'),
('index', 'alarmdecoder.tex', u'AlarmDecoder Documentation',
u'Nu Tech Software Solutions, Inc.', 'manual'),
] ]


# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
@@ -216,8 +216,8 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'pyad2', u'pyad2 Documentation',
[u'Author'], 1)
('index', 'alarmdecoder', u'AlarmDecoder Documentation',
[u'Nu Tech Software Solutions, Inc.'], 1)
] ]


# If true, show URL addresses after external links. # If true, show URL addresses after external links.
@@ -230,8 +230,8 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
('index', 'pyad2', u'pyad2 Documentation',
u'Author', 'pyad2', 'One line description of project.',
('index', 'alarmdecoder', u'AlarmDecoder Documentation',
u'Nu Tech Software Solutions, Inc.', 'alarmdecoder', 'Python library for the Alarm Decoder (AD2) device family.',
'Miscellaneous'), 'Miscellaneous'),
] ]


@@ -251,10 +251,10 @@ texinfo_documents = [
# -- Options for Epub output --------------------------------------------------- # -- Options for Epub output ---------------------------------------------------


# Bibliographic Dublin Core info. # Bibliographic Dublin Core info.
epub_title = u'pyad2'
epub_author = u'Author'
epub_publisher = u'Author'
epub_copyright = u'2013, Author'
epub_title = u'alarmdecoder'
epub_author = u'Nu Tech Software Solutions, Inc.'
epub_publisher = u'Nu Tech Software Solutions, Inc.'
epub_copyright = u'2013, Nu Tech Software Solutions, Inc.'


# The language of the text. It defaults to the language option # The language of the text. It defaults to the language option
# or en if the language is not set. # or en if the language is not set.


+ 3
- 3
docs/index.rst View File

@@ -1,9 +1,9 @@
.. pyad2 documentation master file, created by
.. alarmdecoder documentation master file, created by
sphinx-quickstart on Sat Jun 8 14:38:46 2013. sphinx-quickstart on Sat Jun 8 14:38:46 2013.
You can adapt this file completely to your liking, but it should at least You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive. contain the root `toctree` directive.


Welcome to pyad2's documentation!
Welcome to alarmdecoder's documentation!
==================================== ====================================


Contents: Contents:
@@ -11,7 +11,7 @@ Contents:
.. toctree:: .. toctree::
:maxdepth: 4 :maxdepth: 4


pyad2
alarmdecoder




Indices and tables Indices and tables


+ 2
- 2
docs/make.bat View File

@@ -115,9 +115,9 @@ if "%1" == "qthelp" (
echo. echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^ echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this: .qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pyad2.qhcp
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\alarmdecoder.qhcp
echo.To view the help file: echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pyad2.ghc
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\alarmdecoder.ghc
goto end goto end
) )


+ 3
- 3
docs/modules.rst View File

@@ -1,7 +1,7 @@
pyad2
========
alarmdecoder
============


.. toctree:: .. toctree::
:maxdepth: 4 :maxdepth: 4


pyad2
alarmdecoder

+ 2
- 2
docs/pyad2.event.rst View File

@@ -4,7 +4,7 @@ event Package
:mod:`event` Package :mod:`event` Package
-------------------- --------------------


.. automodule:: pyad2.event
.. automodule:: alarmdecoder.event
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -12,7 +12,7 @@ event Package
:mod:`event` Module :mod:`event` Module
------------------- -------------------


.. automodule:: pyad2.event.event
.. automodule:: alarmdecoder.event.event
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:


+ 9
- 9
docs/pyad2.rst View File

@@ -1,10 +1,10 @@
pyad2 Package
alarmdecoder Package
================ ================


:mod:`ad2` Module
:mod:`alarmdecoder` Module
-------------------- --------------------


.. automodule:: pyad2.ad2
.. automodule:: alarmdecoder.alarmdecoder
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -12,7 +12,7 @@ pyad2 Package
:mod:`devices` Module :mod:`devices` Module
--------------------- ---------------------


.. automodule:: pyad2.devices
.. automodule:: alarmdecoder.devices
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -20,7 +20,7 @@ pyad2 Package
:mod:`util` Module :mod:`util` Module
------------------ ------------------


.. automodule:: pyad2.util
.. automodule:: alarmdecoder.util
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -28,7 +28,7 @@ pyad2 Package
:mod:`zonetracking` Module :mod:`zonetracking` Module
-------------------------- --------------------------


.. automodule:: pyad2.zonetracking
.. automodule:: alarmdecoder.zonetracking
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -36,7 +36,7 @@ pyad2 Package
:mod:`panels` Module :mod:`panels` Module
-------------------- --------------------


.. automodule:: pyad2.panels
.. automodule:: alarmdecoder.panels
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -44,7 +44,7 @@ pyad2 Package
:mod:`messages` Module :mod:`messages` Module
---------------------- ----------------------


.. automodule:: pyad2.messages
.. automodule:: alarmdecoder.messages
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
@@ -54,5 +54,5 @@ Subpackages


.. toctree:: .. toctree::


pyad2.event
alarmdecoder.event



+ 4
- 4
examples/alarm_email.py View File

@@ -1,8 +1,8 @@
import time import time
import smtplib import smtplib
from email.mime.text import MIMEText from email.mime.text import MIMEText
from pyad2 import AD2
from pyad2.devices import USBDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import USBDevice


# Configuration values # Configuration values
SUBJECT = "Alarm Decoder - ALARM" SUBJECT = "Alarm Decoder - ALARM"
@@ -20,7 +20,7 @@ def main():
""" """
try: try:
# Retrieve the first USB device # Retrieve the first USB device
device = AD2(USBDevice.find())
device = AlarmDecoder(USBDevice.find())


# Set up an event handler and open the device # Set up an event handler and open the device
device.on_alarm += handle_alarm device.on_alarm += handle_alarm
@@ -33,7 +33,7 @@ def main():


def handle_alarm(sender, *args, **kwargs): def handle_alarm(sender, *args, **kwargs):
""" """
Handles alarm events from the AD2.
Handles alarm events from the AlarmDecoder.
""" """
status = kwargs['status'] status = kwargs['status']
text = "Alarm status: {0}".format(status) text = "Alarm status: {0}".format(status)


+ 4
- 4
examples/basics.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import USBDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import USBDevice


def main(): def main():
""" """
@@ -8,7 +8,7 @@ def main():
""" """
try: try:
# Retrieve the first USB device # Retrieve the first USB device
device = AD2(USBDevice.find())
device = AlarmDecoder(USBDevice.find())


# Set up an event handler and open the device # Set up an event handler and open the device
device.on_message += handle_message device.on_message += handle_message
@@ -21,7 +21,7 @@ def main():


def handle_message(sender, *args, **kwargs): def handle_message(sender, *args, **kwargs):
""" """
Handles message events from the AD2.
Handles message events from the AlarmDecoder.
""" """
msg = kwargs['message'] msg = kwargs['message']




+ 5
- 5
examples/detection.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import USBDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import USBDevice


__devices = {} __devices = {}


@@ -33,12 +33,12 @@ def main():


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


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


@@ -46,7 +46,7 @@ def create_device(device_args):


def handle_message(sender, *args, **kwargs): def handle_message(sender, *args, **kwargs):
""" """
Handles message events from the AD2.
Handles message events from the AlarmDecoder.
""" """
msg = kwargs['message'] msg = kwargs['message']




+ 4
- 4
examples/rf_device.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import USBDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import USBDevice


RF_DEVICE_SERIAL_NUMBER = '0252254' RF_DEVICE_SERIAL_NUMBER = '0252254'


@@ -18,7 +18,7 @@ def main():
""" """
try: try:
# Retrieve the first USB device # Retrieve the first USB device
device = AD2(USBDevice.find())
device = AlarmDecoder(USBDevice.find())


# Set up an event handler and open the device # Set up an event handler and open the device
device.on_rfx_message += handle_rfx device.on_rfx_message += handle_rfx
@@ -31,7 +31,7 @@ def main():


def handle_rfx(sender, *args, **kwargs): def handle_rfx(sender, *args, **kwargs):
""" """
Handles RF message events from the AD2.
Handles RF message events from the AlarmDecoder.
""" """
msg = kwargs['message'] msg = kwargs['message']




+ 4
- 4
examples/serialport.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import SerialDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import SerialDevice


# Configuration values # Configuration values
SERIAL_DEVICE = '/dev/ttyUSB0' SERIAL_DEVICE = '/dev/ttyUSB0'
@@ -12,7 +12,7 @@ def main():
""" """
try: try:
# Retrieve the specified serial device. # Retrieve the specified serial device.
device = AD2(SerialDevice(interface=SERIAL_DEVICE))
device = AlarmDecoder(SerialDevice(interface=SERIAL_DEVICE))


# Set up an event handler and open the device # Set up an event handler and open the device
device.on_message += handle_message device.on_message += handle_message
@@ -28,7 +28,7 @@ def main():


def handle_message(sender, *args, **kwargs): def handle_message(sender, *args, **kwargs):
""" """
Handles message events from the AD2.
Handles message events from the AlarmDecoder.
""" """
msg = kwargs['message'] msg = kwargs['message']




+ 4
- 4
examples/socket_example.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import SocketDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import SocketDevice


# Configuration values # Configuration values
HOSTNAME = 'localhost' HOSTNAME = 'localhost'
@@ -13,7 +13,7 @@ def main():
""" """
try: try:
# Retrieve an AD2 device that has been exposed with ser2sock on localhost:10000. # Retrieve an AD2 device that has been exposed with ser2sock on localhost:10000.
device = AD2(SocketDevice(interface=(HOSTNAME, PORT)))
device = AlarmDecoder(SocketDevice(interface=(HOSTNAME, PORT)))


# Set up an event handler and open the device # Set up an event handler and open the device
device.on_message += handle_message device.on_message += handle_message
@@ -26,7 +26,7 @@ def main():


def handle_message(sender, *args, **kwargs): def handle_message(sender, *args, **kwargs):
""" """
Handles message events from the AD2.
Handles message events from the AlarmDecoder.
""" """
msg = kwargs['message'] msg = kwargs['message']




+ 4
- 4
examples/ssl_socket.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import SocketDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import SocketDevice


# Configuration values # Configuration values
HOSTNAME = 'localhost' HOSTNAME = 'localhost'
@@ -27,7 +27,7 @@ def main():
ssl_device.ssl_key = SSL_KEY # Client private key ssl_device.ssl_key = SSL_KEY # Client private key
ssl_device.ssl_certificate = SSL_CERT # Client certificate ssl_device.ssl_certificate = SSL_CERT # Client certificate


device = AD2(ssl_device)
device = AlarmDecoder(ssl_device)


# Set up an event handler and open the device # Set up an event handler and open the device
device.on_message += handle_message device.on_message += handle_message
@@ -40,7 +40,7 @@ def main():


def handle_message(sender, *args, **kwargs): def handle_message(sender, *args, **kwargs):
""" """
Handles message events from the AD2.
Handles message events from the AlarmDecoder.
""" """
msg = kwargs['message'] msg = kwargs['message']




+ 9
- 9
examples/virtual_zone_expander.py View File

@@ -1,6 +1,6 @@
import time import time
from pyad2 import AD2
from pyad2.devices import USBDevice
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import USBDevice


# Configuration values # Configuration values
TARGET_ZONE = 41 TARGET_ZONE = 41
@@ -12,23 +12,23 @@ def main():
restores it. restores it.


This is an advanced feature that allows you to emulate a virtual zone. When This is an advanced feature that allows you to emulate a virtual zone. When
the AD2 is configured to emulate a relay 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.
the Alarm Decoder is configured to emulate a relay 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 For example, you could connect a ZigBee device and receiver and fault or
restore it's zone(s) based on the data received. restore it's zone(s) based on the data received.


In order for this to happen you need to perform a couple configuration steps: In order for this to happen you need to perform a couple configuration steps:


1. Enable zone expander emulation on your AD2 device by hitting '!' in a
terminal and going through the prompts.
1. Enable zone expander emulation on your Alarm Decoder device by hitting '!'
in a terminal and going through the prompts.
2. Enable the zone expander in your panel programming. 2. Enable the zone expander in your panel programming.
""" """
try: try:
# Retrieve the first USB device # Retrieve the first USB device
device = AD2(USBDevice.find())
device = AlarmDecoder(USBDevice.find())


# Set up an event handlers and open the device # Set up an event handlers and open the device
device.on_zone_fault += handle_zone_fault device.on_zone_fault += handle_zone_fault


+ 2
- 2
pyad2/__init__.py View File

@@ -1,7 +1,7 @@
from ad2 import AD2
from decoder import AlarmDecoder
import devices import devices
import util import util
import messages import messages
import zonetracking import zonetracking


__all__ = ['ad2', 'devices', 'util', 'messages', 'zonetracking']
__all__ = ['decoder', 'devices', 'util', 'messages', 'zonetracking']

+ 8
- 8
pyad2/ad2.py View File

@@ -1,5 +1,5 @@
""" """
Provides the full AD2 class and factory.
Provides the full AlarmDecoder class.


.. moduleauthor:: Scott Petersen <scott@nutech.com> .. moduleauthor:: Scott Petersen <scott@nutech.com>
""" """
@@ -12,9 +12,9 @@ from .util import CommError, NoDeviceError
from .messages import Message, ExpanderMessage, RFMessage, LRRMessage from .messages import Message, ExpanderMessage, RFMessage, LRRMessage
from .zonetracking import Zonetracker from .zonetracking import Zonetracker


class AD2(object):
class AlarmDecoder(object):
""" """
High-level wrapper around AD2 devices.
High-level wrapper around Alarm Decoder (AD2) devices.
""" """


# High-level Events # High-level Events
@@ -62,7 +62,7 @@ class AD2(object):
""" """
Constructor Constructor


:param device: The low-level device used for this AD2 interface.
:param device: The low-level device used for this Alarm Decoder interface.
:type device: Device :type device: Device
""" """
self._device = device self._device = device
@@ -102,7 +102,7 @@ class AD2(object):
@property @property
def id(self): def id(self):
""" """
The ID of the AD2 device.
The ID of the Alarm Decoder device.


:returns: The identification string for the device. :returns: The identification string for the device.
""" """
@@ -134,7 +134,7 @@ class AD2(object):


def send(self, data): def send(self, data):
""" """
Sends data to the AD2 device.
Sends data to the Alarm Decoder device.


:param data: The data to send. :param data: The data to send.
:type data: str :type data: str
@@ -371,14 +371,14 @@ class AD2(object):
if message.battery_low == self._battery_status[0]: if message.battery_low == self._battery_status[0]:
self._battery_status = (self._battery_status[0], time.time()) self._battery_status = (self._battery_status[0], time.time())
else: else:
if message.battery_low == True or time.time() > self._battery_status[1] + AD2.BATTERY_TIMEOUT:
if message.battery_low == True or time.time() > self._battery_status[1] + AlarmDecoder.BATTERY_TIMEOUT:
self._battery_status = (message.battery_low, time.time()) self._battery_status = (message.battery_low, time.time())
self.on_low_battery(status=self._battery_status) self.on_low_battery(status=self._battery_status)


if message.fire_alarm == self._fire_status[0]: if message.fire_alarm == self._fire_status[0]:
self._fire_status = (self._fire_status[0], time.time()) self._fire_status = (self._fire_status[0], time.time())
else: else:
if message.fire_alarm == True or time.time() > self._fire_status[1] + AD2.FIRE_TIMEOUT:
if message.fire_alarm == True or time.time() > self._fire_status[1] + AlarmDecoder.FIRE_TIMEOUT:
self._fire_status = (message.fire_alarm, time.time()) self._fire_status = (message.fire_alarm, time.time())
self.on_fire(status=self._fire_status) self.on_fire(status=self._fire_status)




+ 8
- 6
pyad2/devices.py View File

@@ -1,5 +1,5 @@
""" """
Contains different types of devices belonging to the AD2 family.
Contains different types of devices belonging to the Alarm Decoder (AD2) family.


.. moduleauthor:: Scott Petersen <scott@nutech.com> .. moduleauthor:: Scott Petersen <scott@nutech.com>
""" """
@@ -18,7 +18,7 @@ from .event import event


class Device(object): class Device(object):
""" """
Generic parent device to all AD2 products.
Generic parent device to all Alarm Decoder (AD2) products.
""" """


# Generic device events # Generic device events
@@ -494,8 +494,10 @@ class USBDevice(Device):
""" """
Constructor Constructor


:param factory: AD2Factory object to use with the thread.
:type factory: AD2Factory
:param on_attached: Function to call when a device is attached.
:type on_attached: function
:param on_detached: Function to call when a device is detached.
:type on_detached: function
""" """
threading.Thread.__init__(self) threading.Thread.__init__(self)


@@ -763,8 +765,8 @@ class SerialDevice(Device):


class SocketDevice(Device): class SocketDevice(Device):
""" """
Device that supports communication with an AD2 that is exposed via ser2sock or another
Serial to IP interface.
Device that supports communication with an Alarm Decoder (AD2) that is
exposed via ser2sock or another Serial to IP interface.
""" """


@property @property


+ 2
- 1
pyad2/messages.py View File

@@ -1,5 +1,6 @@
""" """
Message representations received from the panel through the AD2 devices.
Message representations received from the panel through the Alarm Decoder (AD2)
devices.


.. moduleauthor:: Scott Petersen <scott@nutech.com> .. moduleauthor:: Scott Petersen <scott@nutech.com>
""" """


+ 77
- 77
pyad2/tests/test_ad2.py View File

@@ -3,13 +3,13 @@ import time
from unittest import TestCase from unittest import TestCase
from mock import Mock, MagicMock, patch from mock import Mock, MagicMock, patch


from ..ad2 import AD2
from ..decoder import AlarmDecoder
from ..devices import USBDevice from ..devices import USBDevice
from ..messages import Message, RFMessage, LRRMessage, ExpanderMessage from ..messages import Message, RFMessage, LRRMessage, ExpanderMessage
from ..event.event import Event, EventHandler from ..event.event import Event, EventHandler
from ..zonetracking import Zonetracker from ..zonetracking import Zonetracker


class TestAD2(TestCase):
class TestAlarmDecoder(TestCase):
def setUp(self): def setUp(self):
self._panicked = False self._panicked = False
self._relay_changed = False self._relay_changed = False
@@ -30,28 +30,28 @@ class TestAD2(TestCase):
self._device.on_read = EventHandler(Event(), self._device) self._device.on_read = EventHandler(Event(), self._device)
self._device.on_write = EventHandler(Event(), self._device) self._device.on_write = EventHandler(Event(), self._device)


self._ad2 = AD2(self._device)
self._ad2._zonetracker = Mock(spec=Zonetracker)
self._ad2._zonetracker.on_fault = EventHandler(Event(), self._ad2._zonetracker)
self._ad2._zonetracker.on_restore = EventHandler(Event(), self._ad2._zonetracker)
self._ad2.on_panic += self.on_panic
self._ad2.on_relay_changed += self.on_relay_changed
self._ad2.on_power_changed += self.on_power_changed
self._ad2.on_alarm += self.on_alarm
self._ad2.on_bypass += self.on_bypass
self._ad2.on_low_battery += self.on_battery
self._ad2.on_fire += self.on_fire
self._ad2.on_arm += self.on_arm
self._ad2.on_disarm += self.on_disarm
self._ad2.on_config_received += self.on_config
self._ad2.on_message += self.on_message
self._ad2.on_rfx_message += self.on_rfx_message
self._ad2.on_lrr_message += self.on_lrr_message
self._ad2.address_mask = int('ffffffff', 16)
self._ad2.open()
self._decoder = AlarmDecoder(self._device)
self._decoder._zonetracker = Mock(spec=Zonetracker)
self._decoder._zonetracker.on_fault = EventHandler(Event(), self._decoder._zonetracker)
self._decoder._zonetracker.on_restore = EventHandler(Event(), self._decoder._zonetracker)
self._decoder.on_panic += self.on_panic
self._decoder.on_relay_changed += self.on_relay_changed
self._decoder.on_power_changed += self.on_power_changed
self._decoder.on_alarm += self.on_alarm
self._decoder.on_bypass += self.on_bypass
self._decoder.on_low_battery += self.on_battery
self._decoder.on_fire += self.on_fire
self._decoder.on_arm += self.on_arm
self._decoder.on_disarm += self.on_disarm
self._decoder.on_config_received += self.on_config
self._decoder.on_message += self.on_message
self._decoder.on_rfx_message += self.on_rfx_message
self._decoder.on_lrr_message += self.on_lrr_message
self._decoder.address_mask = int('ffffffff', 16)
self._decoder.open()


def tearDown(self): def tearDown(self):
pass pass
@@ -96,170 +96,170 @@ class TestAD2(TestCase):
self._lrr_message_received = True self._lrr_message_received = True


def test_open(self): def test_open(self):
self._ad2.open()
self._decoder.open()
self._device.open.assert_any_calls() self._device.open.assert_any_calls()


def test_close(self): def test_close(self):
self._ad2.open()
self._decoder.open()


self._ad2.close()
self._decoder.close()
self._device.close.assert_any_calls() self._device.close.assert_any_calls()


def test_send(self): def test_send(self):
self._ad2.send('test')
self._decoder.send('test')
self._device.write.assert_called_with('test') self._device.write.assert_called_with('test')


def test_get_config(self): def test_get_config(self):
self._ad2.get_config()
self._decoder.get_config()
self._device.write.assert_called_with("C\r") self._device.write.assert_called_with("C\r")


def test_save_config(self): def test_save_config(self):
self._ad2.save_config()
self._decoder.save_config()
self._device.write.assert_any_calls() self._device.write.assert_any_calls()


def test_reboot(self): def test_reboot(self):
self._ad2.reboot()
self._decoder.reboot()
self._device.write.assert_called_with('=') self._device.write.assert_called_with('=')


def test_fault(self): def test_fault(self):
self._ad2.fault_zone(1)
self._decoder.fault_zone(1)
self._device.write.assert_called_with("L{0:02}{1}\r".format(1, 1)) self._device.write.assert_called_with("L{0:02}{1}\r".format(1, 1))


def test_fault_wireproblem(self): def test_fault_wireproblem(self):
self._ad2.fault_zone(1, simulate_wire_problem=True)
self._decoder.fault_zone(1, simulate_wire_problem=True)
self._device.write.assert_called_with("L{0:02}{1}\r".format(1, 2)) self._device.write.assert_called_with("L{0:02}{1}\r".format(1, 2))


def test_clear_zone(self): def test_clear_zone(self):
self._ad2.clear_zone(1)
self._decoder.clear_zone(1)
self._device.write.assert_called_with("L{0:02}0\r".format(1)) self._device.write.assert_called_with("L{0:02}0\r".format(1))


def test_message(self): def test_message(self):
msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertIsInstance(msg, Message) self.assertIsInstance(msg, Message)


self._ad2._on_read(self, data='[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self._decoder._on_read(self, data='[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertTrue(self._message_received) self.assertTrue(self._message_received)


def test_message_kpe(self): def test_message_kpe(self):
msg = self._ad2._handle_message('!KPE:[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('!KPE:[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertIsInstance(msg, Message) self.assertIsInstance(msg, Message)


self._ad2._on_read(self, data='[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self._decoder._on_read(self, data='[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertTrue(self._message_received) self.assertTrue(self._message_received)


def test_expander_message(self): def test_expander_message(self):
msg = self._ad2._handle_message('!EXP:07,01,01')
msg = self._decoder._handle_message('!EXP:07,01,01')
self.assertIsInstance(msg, ExpanderMessage) self.assertIsInstance(msg, ExpanderMessage)


def test_relay_message(self): def test_relay_message(self):
self._ad2.open()
msg = self._ad2._handle_message('!REL:12,01,01')
self._decoder.open()
msg = self._decoder._handle_message('!REL:12,01,01')
self.assertIsInstance(msg, ExpanderMessage) self.assertIsInstance(msg, ExpanderMessage)
self.assertEquals(self._relay_changed, True) self.assertEquals(self._relay_changed, True)


def test_rfx_message(self): def test_rfx_message(self):
msg = self._ad2._handle_message('!RFX:0180036,80')
msg = self._decoder._handle_message('!RFX:0180036,80')
self.assertIsInstance(msg, RFMessage) self.assertIsInstance(msg, RFMessage)
self.assertTrue(self._rfx_message_received) self.assertTrue(self._rfx_message_received)


def test_panic(self): def test_panic(self):
self._ad2.open()
self._decoder.open()


msg = self._ad2._handle_message('!LRR:012,1,ALARM_PANIC')
msg = self._decoder._handle_message('!LRR:012,1,ALARM_PANIC')
self.assertEquals(self._panicked, True) self.assertEquals(self._panicked, True)


msg = self._ad2._handle_message('!LRR:012,1,CANCEL')
msg = self._decoder._handle_message('!LRR:012,1,CANCEL')
self.assertEquals(self._panicked, False) self.assertEquals(self._panicked, False)
self.assertIsInstance(msg, LRRMessage) self.assertIsInstance(msg, LRRMessage)


def test_config_message(self): def test_config_message(self):
self._ad2.open()
self._decoder.open()


msg = self._ad2._handle_message('!CONFIG>ADDRESS=18&CONFIGBITS=ff00&LRR=N&EXP=NNNNN&REL=NNNN&MASK=ffffffff&DEDUPLICATE=N')
self.assertEquals(self._ad2.address, 18)
self.assertEquals(self._ad2.configbits, int('ff00', 16))
self.assertEquals(self._ad2.address_mask, int('ffffffff', 16))
self.assertEquals(self._ad2.emulate_zone, [False for x in range(5)])
self.assertEquals(self._ad2.emulate_relay, [False for x in range(4)])
self.assertEquals(self._ad2.emulate_lrr, False)
self.assertEquals(self._ad2.deduplicate, False)
msg = self._decoder._handle_message('!CONFIG>ADDRESS=18&CONFIGBITS=ff00&LRR=N&EXP=NNNNN&REL=NNNN&MASK=ffffffff&DEDUPLICATE=N')
self.assertEquals(self._decoder.address, 18)
self.assertEquals(self._decoder.configbits, int('ff00', 16))
self.assertEquals(self._decoder.address_mask, int('ffffffff', 16))
self.assertEquals(self._decoder.emulate_zone, [False for x in range(5)])
self.assertEquals(self._decoder.emulate_relay, [False for x in range(4)])
self.assertEquals(self._decoder.emulate_lrr, False)
self.assertEquals(self._decoder.deduplicate, False)


self.assertEquals(self._got_config, True) self.assertEquals(self._got_config, True)


def test_power_changed_event(self): def test_power_changed_event(self):
msg = self._ad2._handle_message('[0000000100000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000100000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._power_changed, False) # Not set first time we hit it. self.assertEquals(self._power_changed, False) # Not set first time we hit it.


msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._power_changed, False) self.assertEquals(self._power_changed, False)


msg = self._ad2._handle_message('[0000000100000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000100000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._power_changed, True) self.assertEquals(self._power_changed, True)


def test_alarm_event(self): def test_alarm_event(self):
msg = self._ad2._handle_message('[0000000000100000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000100000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._alarmed, False) # Not set first time we hit it. self.assertEquals(self._alarmed, False) # Not set first time we hit it.


msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._alarmed, False) self.assertEquals(self._alarmed, False)


msg = self._ad2._handle_message('[0000000000100000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000100000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._alarmed, True) self.assertEquals(self._alarmed, True)


def test_zone_bypassed_event(self): def test_zone_bypassed_event(self):
msg = self._ad2._handle_message('[0000001000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000001000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._bypassed, False) # Not set first time we hit it. self.assertEquals(self._bypassed, False) # Not set first time we hit it.


msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._bypassed, False) self.assertEquals(self._bypassed, False)


msg = self._ad2._handle_message('[0000001000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000001000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._bypassed, True) self.assertEquals(self._bypassed, True)


def test_armed_away_event(self): def test_armed_away_event(self):
msg = self._ad2._handle_message('[0100000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0100000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._armed, False) # Not set first time we hit it. self.assertEquals(self._armed, False) # Not set first time we hit it.


msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._armed, False) self.assertEquals(self._armed, False)


msg = self._ad2._handle_message('[0100000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0100000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._armed, True) self.assertEquals(self._armed, True)


self._armed = False self._armed = False


msg = self._ad2._handle_message('[0010000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0010000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._armed, False) # Not set first time we hit it. self.assertEquals(self._armed, False) # Not set first time we hit it.


msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._armed, False) self.assertEquals(self._armed, False)


msg = self._ad2._handle_message('[0010000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0010000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._armed, True) self.assertEquals(self._armed, True)


def test_battery_low_event(self): def test_battery_low_event(self):
msg = self._ad2._handle_message('[0000000000010000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000010000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._battery[0], True) self.assertEquals(self._battery[0], True)


# force the timeout to expire. # force the timeout to expire.
with patch.object(time, 'time', return_value=self._battery[1] + 35): with patch.object(time, 'time', return_value=self._battery[1] + 35):
msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._battery[0], False) self.assertEquals(self._battery[0], False)


def test_fire_alarm_event(self): def test_fire_alarm_event(self):
msg = self._ad2._handle_message('[0000000000000100----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000100----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._fire[0], True) self.assertEquals(self._fire[0], True)


# force the timeout to expire. # force the timeout to expire.
with patch.object(time, 'time', return_value=self._fire[1] + 35): with patch.object(time, 'time', return_value=self._fire[1] + 35):
msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._fire[0], False) self.assertEquals(self._fire[0], False)


def test_hit_for_faults(self): def test_hit_for_faults(self):
self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000],"Hit * for faults "')
self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000],"Hit * for faults "')


self._ad2._device.write.assert_called_with('*')
self._decoder._device.write.assert_called_with('*')


def test_zonetracker_update(self): def test_zonetracker_update(self):
msg = self._ad2._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self._ad2._zonetracker.update.assert_called_with(msg)
msg = self._decoder._handle_message('[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self._decoder._zonetracker.update.assert_called_with(msg)

+ 4
- 5
pyad2/util.py View File

@@ -1,10 +1,9 @@
""" """
Provides utility classes for the AD2 devices.
Provides utility classes for the Alarm Decoder (AD2) devices.


.. moduleauthor:: Scott Petersen <scott@nutech.com> .. moduleauthor:: Scott Petersen <scott@nutech.com>
""" """


import ad2
import time import time
import threading import threading


@@ -34,7 +33,7 @@ class InvalidMessageError(Exception):


class Firmware(object): class Firmware(object):
""" """
Represents firmware for the AD2 devices.
Represents firmware for the Alarm Decoder devices.
""" """


# Constants # Constants
@@ -48,14 +47,14 @@ class Firmware(object):
@staticmethod @staticmethod
def upload(dev, filename, progress_callback=None): def upload(dev, filename, progress_callback=None):
""" """
Uploads firmware to an AD2 device.
Uploads firmware to an Alarm Decoder device.


:param filename: The firmware filename :param filename: The firmware filename
:type filename: str :type filename: str
:param progress_callback: Callback function used to report progress. :param progress_callback: Callback function used to report progress.
:type progress_callback: function :type progress_callback: function


:raises: util.NoDeviceError, util.TimeoutError
:raises: NoDeviceError, TimeoutError
""" """


def do_upload(): def do_upload():


+ 1
- 1
pyad2/zonetracking.py View File

@@ -1,5 +1,5 @@
""" """
Provides zone tracking functionality for the AD2 device family.
Provides zone tracking functionality for the Alarm Decoder (AD2) device family.


.. moduleauthor:: Scott Petersen <scott@nutech.com> .. moduleauthor:: Scott Petersen <scott@nutech.com>
""" """


+ 5
- 5
setup.py View File

@@ -4,9 +4,9 @@ def readme():
with open('README.md') as f: with open('README.md') as f:
return f.read() return f.read()


setup(name='pyad2',
setup(name='alarmdecoder',
version='0.5', version='0.5',
description='Python interface library for the AD2 family of alarm devices.',
description='Python interface library for the Alarm Decoder (AD2) family of alarm devices, including: the AD2USB, AD2SERIAL and AD2PI.',
long_description=readme(), long_description=readme(),
classifiers=[ classifiers=[
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',
@@ -17,12 +17,12 @@ setup(name='pyad2',
'Topic :: Home Automation', 'Topic :: Home Automation',
'Topic :: Security', 'Topic :: Security',
], ],
keywords='alarm data ad2 ad2usb ad2serial ad2pi security ademco dsc',
url='http://github.com/nutechsoftware/pyad2',
keywords='alarmdecoder alarm decoder ad2 ad2usb ad2serial ad2pi security ademco dsc',
url='http://github.com/nutechsoftware/alarmdecoder',
author='Nu Tech Software Solutions, Inc.', author='Nu Tech Software Solutions, Inc.',
author_email='general@support.nutech.com', author_email='general@support.nutech.com',
license='MIT', license='MIT',
packages=['pyad2', 'pyad2.event'],
packages=['alarmdecoder', 'alarmdecoder.event'],
install_requires=[ install_requires=[
'pyopenssl', 'pyopenssl',
'pyusb>=1.0.0b1', 'pyusb>=1.0.0b1',


Loading…
Cancel
Save