From d3833af2ef37d167840165c82dbb46a1fcfc55ba Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Fri, 22 Dec 2017 11:07:11 -0500 Subject: [PATCH] bring branch up-to-date --- BACpypes~.ini | 1 - py25/bacpypes/bvllservice.py | 2 +- py25/bacpypes/core.py | 3 + py27/bacpypes/bvllservice.py | 2 +- py27/bacpypes/core.py | 3 + py34/bacpypes/bvllservice.py | 2 +- py34/bacpypes/core.py | 3 + samples/COVServer.py | 217 ++++++++++++++++++++++++++++++++--- samples/WhoIsIAmForeign.py | 14 ++- setup.py | 2 + 10 files changed, 228 insertions(+), 21 deletions(-) diff --git a/BACpypes~.ini b/BACpypes~.ini index 6740dc4..dc8bac0 100644 --- a/BACpypes~.ini +++ b/BACpypes~.ini @@ -5,7 +5,6 @@ objectIdentifier: 599 maxApduLengthAccepted: 1024 segmentationSupported: segmentedBoth vendorIdentifier: 15 -foreignPort: 0 foreignBBMD: 128.253.109.254 foreignTTL: 30 diff --git a/py25/bacpypes/bvllservice.py b/py25/bacpypes/bvllservice.py index af4128c..e195d39 100755 --- a/py25/bacpypes/bvllservice.py +++ b/py25/bacpypes/bvllservice.py @@ -542,7 +542,7 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents): self.bbmdTimeToLive = ttl # install this task to run when it gets a chance - self.install_task(delta=0) + self.install_task(when=0) def unregister(self): """Drop the registration with a BBMD.""" diff --git a/py25/bacpypes/core.py b/py25/bacpypes/core.py index 5e52db4..1614a53 100755 --- a/py25/bacpypes/core.py +++ b/py25/bacpypes/core.py @@ -144,6 +144,9 @@ def run(spin=SPIN, sigterm=stop, sigusr1=print_stack): time.sleep(sleeptime) delta -= sleeptime + # delta should be no more than the spin value + delta = min(delta, spin) + # if there are deferred functions, use a small delta if deferredFns: delta = min(delta, 0.001) diff --git a/py27/bacpypes/bvllservice.py b/py27/bacpypes/bvllservice.py index 5abb24e..8c01f05 100755 --- a/py27/bacpypes/bvllservice.py +++ b/py27/bacpypes/bvllservice.py @@ -538,7 +538,7 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents): self.bbmdTimeToLive = ttl # install this task to run when it gets a chance - self.install_task(delta=0) + self.install_task(when=0) def unregister(self): """Drop the registration with a BBMD.""" diff --git a/py27/bacpypes/core.py b/py27/bacpypes/core.py index b57bf79..b2c46e3 100755 --- a/py27/bacpypes/core.py +++ b/py27/bacpypes/core.py @@ -142,6 +142,9 @@ def run(spin=SPIN, sigterm=stop, sigusr1=print_stack): time.sleep(sleeptime) delta -= sleeptime + # delta should be no more than the spin value + delta = min(delta, spin) + # if there are deferred functions, use a small delta if deferredFns: delta = min(delta, 0.001) diff --git a/py34/bacpypes/bvllservice.py b/py34/bacpypes/bvllservice.py index 6abb5d7..2a6285c 100755 --- a/py34/bacpypes/bvllservice.py +++ b/py34/bacpypes/bvllservice.py @@ -537,7 +537,7 @@ class BIPForeign(BIPSAP, Client, Server, OneShotTask, DebugContents): self.bbmdTimeToLive = ttl # install this task to run when it gets a chance - self.install_task(delta=0) + self.install_task(when=0) def unregister(self): """Drop the registration with a BBMD.""" diff --git a/py34/bacpypes/core.py b/py34/bacpypes/core.py index b57bf79..b2c46e3 100755 --- a/py34/bacpypes/core.py +++ b/py34/bacpypes/core.py @@ -142,6 +142,9 @@ def run(spin=SPIN, sigterm=stop, sigusr1=print_stack): time.sleep(sleeptime) delta -= sleeptime + # delta should be no more than the spin value + delta = min(delta, spin) + # if there are deferred functions, use a small delta if deferredFns: delta = min(delta, 0.001) diff --git a/samples/COVServer.py b/samples/COVServer.py index 68ef311..c1c2de8 100755 --- a/samples/COVServer.py +++ b/samples/COVServer.py @@ -6,11 +6,15 @@ The console accepts commands that change the properties of an object that triggers the notifications. """ +import time +from threading import Thread + from bacpypes.debugging import bacpypes_debugging, ModuleLogger from bacpypes.consolelogging import ConfigArgumentParser from bacpypes.consolecmd import ConsoleCmd -from bacpypes.core import run, enable_sleeping +from bacpypes.core import run, deferred, enable_sleeping +from bacpypes.task import RecurringTask from bacpypes.app import BIPSimpleApplication from bacpypes.object import AnalogValueObject, BinaryValueObject @@ -22,6 +26,8 @@ _debug = 0 _log = ModuleLogger(globals()) # test globals +test_av = None +test_bv = None test_application = None # @@ -180,8 +186,147 @@ class COVConsoleCmd(ConsoleCmd): print("exception: %s" % (err,)) +@bacpypes_debugging +class TestAnalogValueTask(RecurringTask): + + """ + An instance of this class is created when '--avtask ' is + specified as a command line argument. Every seconds it + changes the value of the test_av present value. + """ + + def __init__(self, interval): + if _debug: TestAnalogValueTask._debug("__init__ %r", interval) + RecurringTask.__init__(self, interval * 1000) + + # make a list of test values + self.test_values = list(float(i * 10) for i in range(10)) + + def process_task(self): + if _debug: TestAnalogValueTask._debug("process_task") + global test_av + + # pop the next value + next_value = self.test_values.pop(0) + self.test_values.append(next_value) + if _debug: TestAnalogValueTask._debug(" - next_value: %r", next_value) + + # change the point + test_av.presentValue = next_value + + +@bacpypes_debugging +class TestAnalogValueThread(Thread): + + """ + An instance of this class is created when '--avthread ' is + specified as a command line argument. Every seconds it + changes the value of the test_av present value. + """ + + def __init__(self, interval): + if _debug: TestAnalogValueThread._debug("__init__ %r", interval) + Thread.__init__(self) + + # runs as a daemon + self.daemon = True + + # save the interval + self.interval = interval + + # make a list of test values + self.test_values = list(100.0 + float(i * 10) for i in range(10)) + + def run(self): + if _debug: TestAnalogValueThread._debug("run") + global test_av + + while True: + # pop the next value + next_value = self.test_values.pop(0) + self.test_values.append(next_value) + if _debug: TestAnalogValueThread._debug(" - next_value: %r", next_value) + + # change the point + test_av.presentValue = next_value + + # sleep + time.sleep(self.interval) + + +@bacpypes_debugging +class TestBinaryValueTask(RecurringTask): + + """ + An instance of this class is created when '--bvtask ' is + specified as a command line argument. Every seconds it + changes the value of the test_bv present value. + """ + + def __init__(self, interval): + if _debug: TestBinaryValueTask._debug("__init__ %r", interval) + RecurringTask.__init__(self, interval * 1000) + + # save the interval + self.interval = interval + + # make a list of test values + self.test_values = [True, False] + + def process_task(self): + if _debug: TestBinaryValueTask._debug("process_task") + global test_bv + + # pop the next value + next_value = self.test_values.pop(0) + self.test_values.append(next_value) + if _debug: TestBinaryValueTask._debug(" - next_value: %r", next_value) + + # change the point + test_bv.presentValue = next_value + + +@bacpypes_debugging +class TestBinaryValueThread(RecurringTask, Thread): + + """ + An instance of this class is created when '--bvthread ' is + specified as a command line argument. Every seconds it + changes the value of the test_bv present value. + """ + + def __init__(self, interval): + if _debug: TestBinaryValueThread._debug("__init__ %r", interval) + Thread.__init__(self) + + # runs as a daemon + self.daemon = True + + # save the interval + self.interval = interval + + # make a list of test values + self.test_values = [True, False] + + def run(self): + if _debug: TestBinaryValueThread._debug("run") + global test_bv + + while True: + # pop the next value + next_value = self.test_values.pop(0) + self.test_values.append(next_value) + if _debug: TestBinaryValueThread._debug(" - next_value: %r", next_value) + + # change the point + test_bv.presentValue = next_value + + # sleep + time.sleep(self.interval) + + def main(): - global test_application + global test_av, test_bv, test_application # make a parser parser = ConfigArgumentParser(description=__doc__) @@ -191,6 +336,28 @@ def main(): help="create a console", ) + # analog value task and thread + parser.add_argument("--avtask", type=float, + help="analog value recurring task", + ) + parser.add_argument("--avthread", type=float, + help="analog value thread", + ) + + # analog value task and thread + parser.add_argument("--bvtask", type=float, + help="binary value recurring task", + ) + parser.add_argument("--bvthread", type=float, + help="binary value thread", + ) + + # provide a different spin value + parser.add_argument("--spin", type=float, + help="spin time", + default=1.0, + ) + # parse the command line arguments args = parser.parse_args() @@ -209,18 +376,6 @@ def main(): # make a sample application test_application = SubscribeCOVApplication(test_device, args.ini.address) - # make a binary value object - test_bv = BinaryValueObject( - objectIdentifier=('binaryValue', 1), - objectName='bv', - presentValue='inactive', - statusFlags=[0, 0, 0, 0], - ) - _log.debug(" - test_bv: %r", test_bv) - - # add it to the device - test_application.add_object(test_bv) - # make an analog value object test_av = AnalogValueObject( objectIdentifier=('analogValue', 1), @@ -235,6 +390,18 @@ def main(): test_application.add_object(test_av) _log.debug(" - object list: %r", test_device.objectList) + # make a binary value object + test_bv = BinaryValueObject( + objectIdentifier=('binaryValue', 1), + objectName='bv', + presentValue='inactive', + statusFlags=[0, 0, 0, 0], + ) + _log.debug(" - test_bv: %r", test_bv) + + # add it to the device + test_application.add_object(test_bv) + # get the services supported services_supported = test_application.get_services_supported() if _debug: _log.debug(" - services_supported: %r", services_supported) @@ -250,9 +417,29 @@ def main(): # enable sleeping will help with threads enable_sleeping() + # analog value task + if args.avtask: + test_av_task = TestAnalogValueTask(args.avtask) + test_av_task.install_task() + + # analog value thread + if args.avthread: + test_av_thread = TestAnalogValueThread(args.avthread) + deferred(test_av_thread.start) + + # binary value task + if args.bvtask: + test_bv_task = TestBinaryValueTask(args.bvtask) + test_bv_task.install_task() + + # binary value thread + if args.bvthread: + test_bv_thread = TestBinaryValueThread(args.bvthread) + deferred(test_bv_thread.start) + _log.debug("running") - run() + run(args.spin) _log.debug("fini") diff --git a/samples/WhoIsIAmForeign.py b/samples/WhoIsIAmForeign.py index 38e2917..a2eb613 100755 --- a/samples/WhoIsIAmForeign.py +++ b/samples/WhoIsIAmForeign.py @@ -4,6 +4,16 @@ This application presents a 'console' prompt to the user asking for Who-Is and I-Am commands which create the related APDUs, then lines up the coorresponding I-Am for incoming traffic and prints out the contents. + +In addition to the usual INI parameters that are common to BACpypes applications, +this application references two additional parameters: + + foreignBBMD: the BACpypes IP Address of the BBMD to register + foreignTTL: the time-to-live to keep the registration alive + +The BBMDForeign class will send the BVLL registration request after the core +starts up and maintain it. If the device does not get an 'ack' then it will +not send requests, even to devices that it would be able to talk otherwise. """ import sys @@ -115,7 +125,7 @@ class WhoIsIAmConsoleCmd(ConsoleCmd): # make an IOCB iocb = IOCB(request) - if _debug: WriteSomethingConsoleCmd._debug(" - iocb: %r", iocb) + if _debug: WhoIsIAmConsoleCmd._debug(" - iocb: %r", iocb) # give it to the application this_application.request_io(iocb) @@ -142,7 +152,7 @@ class WhoIsIAmConsoleCmd(ConsoleCmd): # make an IOCB iocb = IOCB(request) - if _debug: WriteSomethingConsoleCmd._debug(" - iocb: %r", iocb) + if _debug: WhoIsIAmConsoleCmd._debug(" - iocb: %r", iocb) # give it to the application this_application.request_io(iocb) diff --git a/setup.py b/setup.py index 8386d4e..9d73295 100644 --- a/setup.py +++ b/setup.py @@ -18,6 +18,7 @@ source_folder = { (2, 7): 'py27', (3, 4): 'py34', (3, 5): 'py34', + (3, 6): 'py34', }.get(version_info, None) if not source_folder: raise EnvironmentError("unsupported version of Python") @@ -75,6 +76,7 @@ setup( 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ], setup_requires=setup_requirements,