1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-09-28 22:15:23 +08:00

ready for the 0.15.2 release

This commit is contained in:
Joel Bender 2017-03-27 22:39:04 -04:00
commit 8662a6efa1
10 changed files with 429 additions and 237 deletions

View File

@ -66,7 +66,7 @@ essential components of a BACpypes application and how the pieces fit together.
tutorial/tutorial001.rst
tutorial/tutorial002.rst
tutorial/tutorial003.rst
tutorial/tutorial004.rst
tutorial/addressing.rst
tutorial/tutorial006.rst
tutorial/iocb.rst
tutorial/capability.rst

View File

@ -0,0 +1,210 @@
.. BACpypes tutorial lesson 4
Addressing
==========
BACnet addresses come in five delicious flavors:
local station
A message addressed to one device on the same network as the originator.
local broadcast
A message addressed to all devices or nodes on the same network as the originator.
remote station
A message addressed to one device on a different network than the originator.
remote broadcast
A message addressed to all devices or nodes on a different network than the originator.
global broadcast
A message addressed to all devices or nodes on all networks known any device on any network.
BACpypes address objects are used as the source and destination for PDUs and
are also keys to dictionaries for looking up device in information and
organizing requests and responses with devices.
Building an Address
-------------------
The Address class other related classes are in the pdu module.
Local Stations
~~~~~~~~~~~~~~
The Address class is the base class from which the other classes are derived,
but for this tutorial, we'll start with the simplest::
>>> from bacpypes.pdu import LocalStation
Local station addresses are one or more octets of binary data. For the
simplest networks they are a single octet, for Ethernet and BACnet/IP they
are six octets long. There is no restriction on the length of an address in
BACpypes.
A local station address is contructed by passing the octet string as bytes or
a byte array, and their string representation is hex notation::
>>> addr1 = Address(b'123456')
>>> print(addr1)
0x313233343536
For local stations on simple networks the constructor will accept unsigned
integers with the simple string output::
>>> addr2 = Address(12)
>>> print(addr2)
12
The underlying components of the address are always byte strings::
>>> addr1.addrAddr
b'123456'
>>> addr1.addrAddr
b'\x01'
When the byte string is six octets long and the next to last octet is 0xBA and
the last octet is in the range 0xC0 to 0xCF, the string output and repr value
will be presented as an IPv4 address::
>>> LocalStation(b'\1\2\3\4\xba\xc0')
<LocalStation 1.2.3.4>
and it will include the port number if it is not the standard port::
>>> LocalStation(b'\1\2\3\4\xba\xc3')
<LocalStation 1.2.3.4:47811>
Local Broadcast
~~~~~~~~~~~~~~~
The local broadcast address is used in the destination of a PDU that is to be
sent to all of the devices on a network, and if the network layer can detect
if it received a PDU as the result of another station broadcasting it. There
are no parameters for constructing one::
>>> from bacpypes.pdu import LocalBroadcast
>>> print(LocalBroadcast())
*
The string output represents any address.
Remote Station
~~~~~~~~~~~~~~
A remote station address is used in BACnet networking when the source and/or
destination is on a network other than the one considered local. The first
parameter is the network number, which must be a valid BACnet network number,
and the second parameter is a byte string or unsigned integer like the local
station::
>>> from bacpypes.pdu import RemoteStation
>>> print(RemoteStation(15, 75))
15:75
>>> print(RemoteStation(15, b'123456'))
15:0x313233343536
The string output is the network number and address separated by a colon.
Remote Broadcast
~~~~~~~~~~~~~~~~
A remote broadcast station is used as a destination address when sending a PDU
to all of the devices on a remote network. The only constructor parameter is
the network number, which must be a valid BACnet network number:
>>> from bacpypes.pdu import RemoteBroadcast
>>> print(RemoteBroadcast(17))
17:*
The string output is the network number number, a colon, and an asterisk for
any address.
GlobalBroadcast
~~~~~~~~~~~~~~~
The global broadcast address is used to send PDUs to all devices. It has no
constructor parameters::
>>> from bacpypes.pdu import GlobalBroadcast
>>> print(GlobalBroadcast())
*:*
The string output is an asterisk for any network, a colon, and an asterisk for
and address.
Address Parsing
---------------
The basic Address class can parse the string form of all of the address types
and a few more for older applications and notation that has appeared in
other tutorials.
.. note::
The Address class cannot "morph" into an instance of one of its subclasses
so to determine what kind of address it is check the addrType attribute.
For example::
>>> from bacpypes.pdu import Address
>>> Address(1).addrType == Address.localStationAddr
True
And addresses created this way are identical::
>>> Address(1) == LocalStation(b'\01')
True
Unlike the LocalStation, the Address can take the string form of an integer::
>>> Address("2") == LocalStation(b'\02')
True
And can interpret hex strings of various types::
>>> Address("0x0304") == LocalStation(b'\3\4')
True
>>> Address("X'050607'") == LocalStation(b'\5\6\7')
True
It interprets the asterisk as a local broadcast::
>>> Address("*") == LocalBroadcast()
True
And remote stations and remote broadcasts mathing the other output::
>>> Address("1:2") == RemoteStation(1, 2)
True
>>> Address("3:*") == RemoteBroadcast(3)
True
And the global broadcast::
>>> Address("*:*") == GlobalBroadcast()
True
IPv4 Addresses
~~~~~~~~~~~~~~
Because they appear so often, the address parsing has special patterns for
recognizing IPv4 addresses in CIDR notation along with an optional port
number::
>>> Address("192.168.1.2").addrAddr
b'\xc0\xa8\x01\x02\xba\xc0'
>>> Address("192.168.1.2:47809").addrAddr
b'\xc0\xa8\x01\x02\xba\xc1'
For addresses that also include a subnet mask to calculate broadcast addresses,
the CIDR notation is available::
>>> hex(Address("192.168.3.4/24").addrSubnet)
'0xc0a80300'
And for calculating the address tuple for use with socket functions::
>>> Address("192.168.5.6/16").addrBroadcastTuple
('192.168.255.255', 47808)

View File

@ -1,22 +0,0 @@
.. BACpypes tutorial lesson 4
Addressing
==========
BACnet addresses come in five delicious flavors:
local station
A message addressed to one device on the same network as the originator.
local broadcast
A message addressed to all devices or nodes on the same network as the originator.
remote station
A message addressed to one device on a different network than the originator.
remote broadcast
A message addressed to all devices or nodes on a different network than the originator.
global broadcast
A message addressed to all devices or nodes on all networks known any device on any network.

View File

@ -18,7 +18,7 @@ if _sys.platform not in _supported_platforms:
# Project Metadata
#
__version__ = '0.15.1'
__version__ = '0.15.2'
__author__ = 'Joel Bender'
__email__ = 'joel@carrickbender.com'

View File

@ -23,16 +23,82 @@ taskManager = None
deferredFns = []
sleeptime = 0.0
#
# stop
#
def stop(*args):
"""Call to stop running, may be called with a signum and frame
parameter if called as a signal handler."""
if _debug: stop._debug("stop")
global running, taskManager
if args:
sys.stderr.write("===== TERM Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.flush()
running = False
# trigger the task manager event
if taskManager and taskManager.trigger:
if _debug: stop._debug(" - trigger")
taskManager.trigger.set()
bacpypes_debugging(stop)
#
# print_stack
#
def print_stack(sig, frame):
"""Signal handler to print a stack trace and some interesting values."""
if _debug: print_stack._debug("print_stack, %r, %r", sig, frame)
global running, deferredFns, sleeptime
sys.stderr.write("==== USR1 Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.write("---------- globals\n")
sys.stderr.write(" running: %r\n" % (running,))
sys.stderr.write(" deferredFns: %r\n" % (deferredFns,))
sys.stderr.write(" sleeptime: %r\n" % (sleeptime,))
sys.stderr.write("---------- stack\n")
traceback.print_stack(frame)
# make a list of interesting frames
flist = []
f = frame
while f.f_back:
flist.append(f)
f = f.f_back
# reverse the list so it is in the same order as print_stack
flist.reverse()
for f in flist:
sys.stderr.write("---------- frame: %s\n" % (f,))
for k, v in f.f_locals.items():
sys.stderr.write(" %s: %r\n" % (k, v))
sys.stderr.flush()
bacpypes_debugging(print_stack)
#
# run
#
SPIN = 1.0
def run(spin=SPIN):
if _debug: run._debug("run spin=%r", spin)
def run(spin=SPIN, sigterm=stop, sigusr1=print_stack):
if _debug: run._debug("run spin=%r sigterm=%r, sigusr1=%r", spin, sigterm, sigusr1)
global running, taskManager, deferredFns, sleeptime
# install the signal handlers if they have been provided (issue #112)
if (sigterm is not None) and hasattr(signal, 'SIGTERM'):
signal.signal(signal.SIGTERM, sigterm)
if (sigusr1 is not None) and hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, sigusr1)
# reference the task manager (a singleton)
taskManager = TaskManager()
@ -141,75 +207,6 @@ def run_once():
if _debug: run_once._exception("an error has occurred: %s", err)
bacpypes_debugging(run_once)
#
# stop
#
def stop(*args):
"""Call to stop running, may be called with a signum and frame
parameter if called as a signal handler."""
if _debug: stop._debug("stop")
global running, taskManager
if args:
sys.stderr.write("===== TERM Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.flush()
running = False
# trigger the task manager event
if taskManager and taskManager.trigger:
if _debug: stop._debug(" - trigger")
taskManager.trigger.set()
bacpypes_debugging(stop)
# set a TERM signal handler
if hasattr(signal, 'SIGTERM'):
signal.signal(signal.SIGTERM, stop)
#
# print_stack
#
def print_stack(sig, frame):
"""Signal handler to print a stack trace and some interesting values."""
if _debug: print_stack._debug("print_stack, %r, %r", sig, frame)
global running, deferredFns, sleeptime
sys.stderr.write("==== USR1 Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.write("---------- globals\n")
sys.stderr.write(" running: %r\n" % (running,))
sys.stderr.write(" deferredFns: %r\n" % (deferredFns,))
sys.stderr.write(" sleeptime: %r\n" % (sleeptime,))
sys.stderr.write("---------- stack\n")
traceback.print_stack(frame)
# make a list of interesting frames
flist = []
f = frame
while f.f_back:
flist.append(f)
f = f.f_back
# reverse the list so it is in the same order as print_stack
flist.reverse()
for f in flist:
sys.stderr.write("---------- frame: %s\n" % (f,))
for k, v in f.f_locals.items():
sys.stderr.write(" %s: %r\n" % (k, v))
sys.stderr.flush()
bacpypes_debugging(print_stack)
# set a USR1 signal handler to print a stack trace
if hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, print_stack)
#
# deferred
#
@ -242,3 +239,4 @@ def enable_sleeping(stime=0.001):
sleeptime = stime
bacpypes_debugging(enable_sleeping)

View File

@ -18,7 +18,7 @@ if _sys.platform not in _supported_platforms:
# Project Metadata
#
__version__ = '0.15.1'
__version__ = '0.15.2'
__author__ = 'Joel Bender'
__email__ = 'joel@carrickbender.com'

View File

@ -23,6 +23,64 @@ taskManager = None
deferredFns = []
sleeptime = 0.0
#
# stop
#
@bacpypes_debugging
def stop(*args):
"""Call to stop running, may be called with a signum and frame
parameter if called as a signal handler."""
if _debug: stop._debug("stop")
global running, taskManager
if args:
sys.stderr.write("===== TERM Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.flush()
running = False
# trigger the task manager event
if taskManager and taskManager.trigger:
if _debug: stop._debug(" - trigger")
taskManager.trigger.set()
#
# print_stack
#
@bacpypes_debugging
def print_stack(sig, frame):
"""Signal handler to print a stack trace and some interesting values."""
if _debug: print_stack._debug("print_stack, %r, %r", sig, frame)
global running, deferredFns, sleeptime
sys.stderr.write("==== USR1 Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.write("---------- globals\n")
sys.stderr.write(" running: %r\n" % (running,))
sys.stderr.write(" deferredFns: %r\n" % (deferredFns,))
sys.stderr.write(" sleeptime: %r\n" % (sleeptime,))
sys.stderr.write("---------- stack\n")
traceback.print_stack(frame)
# make a list of interesting frames
flist = []
f = frame
while f.f_back:
flist.append(f)
f = f.f_back
# reverse the list so it is in the same order as print_stack
flist.reverse()
for f in flist:
sys.stderr.write("---------- frame: %s\n" % (f,))
for k, v in f.f_locals.items():
sys.stderr.write(" %s: %r\n" % (k, v))
sys.stderr.flush()
#
# run
#
@ -30,10 +88,16 @@ sleeptime = 0.0
SPIN = 1.0
@bacpypes_debugging
def run(spin=SPIN):
if _debug: run._debug("run spin=%r", spin)
def run(spin=SPIN, sigterm=stop, sigusr1=print_stack):
if _debug: run._debug("run spin=%r sigterm=%r, sigusr1=%r", spin, sigterm, sigusr1)
global running, taskManager, deferredFns, sleeptime
# install the signal handlers if they have been provided (issue #112)
if (sigterm is not None) and hasattr(signal, 'SIGTERM'):
signal.signal(signal.SIGTERM, sigterm)
if (sigusr1 is not None) and hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, sigusr1)
# reference the task manager (a singleton)
taskManager = TaskManager()
@ -140,72 +204,6 @@ def run_once():
except Exception as err:
if _debug: run_once._exception("an error has occurred: %s", err)
#
# stop
#
@bacpypes_debugging
def stop(*args):
"""Call to stop running, may be called with a signum and frame
parameter if called as a signal handler."""
if _debug: stop._debug("stop")
global running, taskManager
if args:
sys.stderr.write("===== TERM Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.flush()
running = False
# trigger the task manager event
if taskManager and taskManager.trigger:
if _debug: stop._debug(" - trigger")
taskManager.trigger.set()
# set a TERM signal handler
if hasattr(signal, 'SIGTERM'):
signal.signal(signal.SIGTERM, stop)
#
# print_stack
#
@bacpypes_debugging
def print_stack(sig, frame):
"""Signal handler to print a stack trace and some interesting values."""
if _debug: print_stack._debug("print_stack, %r, %r", sig, frame)
global running, deferredFns, sleeptime
sys.stderr.write("==== USR1 Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.write("---------- globals\n")
sys.stderr.write(" running: %r\n" % (running,))
sys.stderr.write(" deferredFns: %r\n" % (deferredFns,))
sys.stderr.write(" sleeptime: %r\n" % (sleeptime,))
sys.stderr.write("---------- stack\n")
traceback.print_stack(frame)
# make a list of interesting frames
flist = []
f = frame
while f.f_back:
flist.append(f)
f = f.f_back
# reverse the list so it is in the same order as print_stack
flist.reverse()
for f in flist:
sys.stderr.write("---------- frame: %s\n" % (f,))
for k, v in f.f_locals.items():
sys.stderr.write(" %s: %r\n" % (k, v))
sys.stderr.flush()
# set a USR1 signal handler to print a stack trace
if hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, print_stack)
#
# deferred
#
@ -237,3 +235,4 @@ def enable_sleeping(stime=0.001):
# set the sleep time
sleeptime = stime

View File

@ -18,7 +18,7 @@ if _sys.platform not in _supported_platforms:
# Project Metadata
#
__version__ = '0.15.1'
__version__ = '0.15.2'
__author__ = 'Joel Bender'
__email__ = 'joel@carrickbender.com'

View File

@ -23,6 +23,64 @@ taskManager = None
deferredFns = []
sleeptime = 0.0
#
# stop
#
@bacpypes_debugging
def stop(*args):
"""Call to stop running, may be called with a signum and frame
parameter if called as a signal handler."""
if _debug: stop._debug("stop")
global running, taskManager
if args:
sys.stderr.write("===== TERM Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.flush()
running = False
# trigger the task manager event
if taskManager and taskManager.trigger:
if _debug: stop._debug(" - trigger")
taskManager.trigger.set()
#
# print_stack
#
@bacpypes_debugging
def print_stack(sig, frame):
"""Signal handler to print a stack trace and some interesting values."""
if _debug: print_stack._debug("print_stack, %r, %r", sig, frame)
global running, deferredFns, sleeptime
sys.stderr.write("==== USR1 Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.write("---------- globals\n")
sys.stderr.write(" running: %r\n" % (running,))
sys.stderr.write(" deferredFns: %r\n" % (deferredFns,))
sys.stderr.write(" sleeptime: %r\n" % (sleeptime,))
sys.stderr.write("---------- stack\n")
traceback.print_stack(frame)
# make a list of interesting frames
flist = []
f = frame
while f.f_back:
flist.append(f)
f = f.f_back
# reverse the list so it is in the same order as print_stack
flist.reverse()
for f in flist:
sys.stderr.write("---------- frame: %s\n" % (f,))
for k, v in f.f_locals.items():
sys.stderr.write(" %s: %r\n" % (k, v))
sys.stderr.flush()
#
# run
#
@ -30,10 +88,16 @@ sleeptime = 0.0
SPIN = 1.0
@bacpypes_debugging
def run(spin=SPIN):
if _debug: run._debug("run spin=%r", spin)
def run(spin=SPIN, sigterm=stop, sigusr1=print_stack):
if _debug: run._debug("run spin=%r sigterm=%r, sigusr1=%r", spin, sigterm, sigusr1)
global running, taskManager, deferredFns, sleeptime
# install the signal handlers if they have been provided (issue #112)
if (sigterm is not None) and hasattr(signal, 'SIGTERM'):
signal.signal(signal.SIGTERM, sigterm)
if (sigusr1 is not None) and hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, sigusr1)
# reference the task manager (a singleton)
taskManager = TaskManager()
@ -140,72 +204,6 @@ def run_once():
except Exception as err:
if _debug: run_once._exception("an error has occurred: %s", err)
#
# stop
#
@bacpypes_debugging
def stop(*args):
"""Call to stop running, may be called with a signum and frame
parameter if called as a signal handler."""
if _debug: stop._debug("stop")
global running, taskManager
if args:
sys.stderr.write("===== TERM Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.flush()
running = False
# trigger the task manager event
if taskManager and taskManager.trigger:
if _debug: stop._debug(" - trigger")
taskManager.trigger.set()
# set a TERM signal handler
if hasattr(signal, 'SIGTERM'):
signal.signal(signal.SIGTERM, stop)
#
# print_stack
#
@bacpypes_debugging
def print_stack(sig, frame):
"""Signal handler to print a stack trace and some interesting values."""
if _debug: print_stack._debug("print_stack, %r, %r", sig, frame)
global running, deferredFns, sleeptime
sys.stderr.write("==== USR1 Signal, %s\n" % time.strftime("%d-%b-%Y %H:%M:%S"))
sys.stderr.write("---------- globals\n")
sys.stderr.write(" running: %r\n" % (running,))
sys.stderr.write(" deferredFns: %r\n" % (deferredFns,))
sys.stderr.write(" sleeptime: %r\n" % (sleeptime,))
sys.stderr.write("---------- stack\n")
traceback.print_stack(frame)
# make a list of interesting frames
flist = []
f = frame
while f.f_back:
flist.append(f)
f = f.f_back
# reverse the list so it is in the same order as print_stack
flist.reverse()
for f in flist:
sys.stderr.write("---------- frame: %s\n" % (f,))
for k, v in f.f_locals.items():
sys.stderr.write(" %s: %r\n" % (k, v))
sys.stderr.flush()
# set a USR1 signal handler to print a stack trace
if hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, print_stack)
#
# deferred
#
@ -237,3 +235,4 @@ def enable_sleeping(stime=0.001):
# set the sleep time
sleeptime = stime

View File

@ -10,12 +10,20 @@ rm -Rfv build/
# python2.5 setup.py bdist_egg
# rm -Rfv build/
for ver in 2.7 3.4; do
python$ver setup.py bdist_egg
python$ver setup.py bdist_wheel
rm -Rfv build/
for version in 2.7 3.4 3.5 3.6; do
if [ -a "`which python$version`" ]; then
python$version setup.py bdist_egg
python$version setup.py bdist_wheel
rm -Rfv build/
fi
done
echo
echo This is what was built...
echo
ls -1 dist/
echo
read -p "Upload to PyPI? [y/n/x] " yesno || exit 1
if [ "$yesno" = "y" ] ;