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:
commit
8662a6efa1
|
@ -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
|
||||
|
|
210
doc/source/tutorial/addressing.rst
Normal file
210
doc/source/tutorial/addressing.rst
Normal 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)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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" ] ;
|
||||
|
|
Loading…
Reference in New Issue
Block a user