From 7e544ec637442fdffe6a2342787dc441d78b5b23 Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Mon, 27 Feb 2017 21:24:39 -0500 Subject: [PATCH 1/8] trap invlid tag in sub-elements, needs testing --- py25/bacpypes/constructeddata.py | 2 +- py27/bacpypes/constructeddata.py | 2 +- py34/bacpypes/constructeddata.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/py25/bacpypes/constructeddata.py b/py25/bacpypes/constructeddata.py index cea15ea..0db040a 100755 --- a/py25/bacpypes/constructeddata.py +++ b/py25/bacpypes/constructeddata.py @@ -266,7 +266,7 @@ class Sequence(object): # save the result setattr(self, element.name, value) - except DecodingError: + except DecodingError, InvalidTag: # if the context tag was matched, the substructure has to be decoded # correctly. if element.context is None and element.optional: diff --git a/py27/bacpypes/constructeddata.py b/py27/bacpypes/constructeddata.py index 85922f8..82f7641 100755 --- a/py27/bacpypes/constructeddata.py +++ b/py27/bacpypes/constructeddata.py @@ -267,7 +267,7 @@ class Sequence(object): # save the result setattr(self, element.name, value) - except DecodingError: + except DecodingError, InvalidTag: # if the context tag was matched, the substructure has to be decoded # correctly. if element.context is None and element.optional: diff --git a/py34/bacpypes/constructeddata.py b/py34/bacpypes/constructeddata.py index e9c80be..3f98111 100755 --- a/py34/bacpypes/constructeddata.py +++ b/py34/bacpypes/constructeddata.py @@ -267,7 +267,7 @@ class Sequence(object): # save the result setattr(self, element.name, value) - except DecodingError: + except DecodingError, InvalidTag: # if the context tag was matched, the substructure has to be decoded # correctly. if element.context is None and element.optional: From c795e3b0f059e6916ca8691cb6d064e546e4961a Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Mon, 27 Feb 2017 21:35:03 -0500 Subject: [PATCH 2/8] wrong syntax --- py25/bacpypes/constructeddata.py | 2 +- py27/bacpypes/constructeddata.py | 2 +- py34/bacpypes/constructeddata.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/py25/bacpypes/constructeddata.py b/py25/bacpypes/constructeddata.py index 0db040a..2e589b8 100755 --- a/py25/bacpypes/constructeddata.py +++ b/py25/bacpypes/constructeddata.py @@ -266,7 +266,7 @@ class Sequence(object): # save the result setattr(self, element.name, value) - except DecodingError, InvalidTag: + except (DecodingError, InvalidTag), err: # if the context tag was matched, the substructure has to be decoded # correctly. if element.context is None and element.optional: diff --git a/py27/bacpypes/constructeddata.py b/py27/bacpypes/constructeddata.py index 82f7641..75818ad 100755 --- a/py27/bacpypes/constructeddata.py +++ b/py27/bacpypes/constructeddata.py @@ -267,7 +267,7 @@ class Sequence(object): # save the result setattr(self, element.name, value) - except DecodingError, InvalidTag: + except (DecodingError, InvalidTag) as err: # if the context tag was matched, the substructure has to be decoded # correctly. if element.context is None and element.optional: diff --git a/py34/bacpypes/constructeddata.py b/py34/bacpypes/constructeddata.py index 3f98111..45dc228 100755 --- a/py34/bacpypes/constructeddata.py +++ b/py34/bacpypes/constructeddata.py @@ -267,7 +267,7 @@ class Sequence(object): # save the result setattr(self, element.name, value) - except DecodingError, InvalidTag: + except (DecodingError, InvalidTag) as err: # if the context tag was matched, the substructure has to be decoded # correctly. if element.context is None and element.optional: From 836983a1a40290b6d1a4eb7965cc0266e4b15502 Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Wed, 8 Mar 2017 08:11:59 -0500 Subject: [PATCH 3/8] check for limits parameter (untested) --- py27/bacpypes/service/device.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/py27/bacpypes/service/device.py b/py27/bacpypes/service/device.py index cc257ae..3defb47 100644 --- a/py27/bacpypes/service/device.py +++ b/py27/bacpypes/service/device.py @@ -287,6 +287,28 @@ class WhoHasIHaveServices(Capability): if _debug: WhoIsIAmServices._debug(" - no local device") return + # if this has limits, check them like Who-Is + if apdu.limits is not None: + # extract the parameters + low_limit = apdu.limits.deviceInstanceRangeLowLimit + high_limit = apdu.limits.deviceInstanceRangeHighLimit + + # check for consistent parameters + if (low_limit is None): + raise MissingRequiredParameter("deviceInstanceRangeLowLimit required") + if (low_limit < 0) or (low_limit > 4194303): + raise ParameterOutOfRange("deviceInstanceRangeLowLimit out of range") + if (high_limit is None): + raise MissingRequiredParameter("deviceInstanceRangeHighLimit required") + if (high_limit < 0) or (high_limit > 4194303): + raise ParameterOutOfRange("deviceInstanceRangeHighLimit out of range") + + # see we should respond + if (self.localDevice.objectIdentifier[1] < low_limit): + return + if (self.localDevice.objectIdentifier[1] > high_limit): + return + # find the object if apdu.object.objectIdentifier is not None: obj = self.objectIdentifier.get(apdu.object.objectIdentifier, None) @@ -294,8 +316,10 @@ class WhoHasIHaveServices(Capability): obj = self.objectName.get(apdu.object.objectName, None) else: raise InconsistentParameters("object identifier or object name required") + + # maybe we don't have it if not obj: - raise ExecutionError(errorClass='object', errorCode='unknownObject') + return # send out the response self.i_have(obj, address=apdu.pduSource) From c62477c941a4b4a38803662344758c5765bff335 Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Thu, 9 Mar 2017 10:54:48 -0500 Subject: [PATCH 4/8] sample application for discovering devices --- samples/DeviceDiscovery.py | 235 +++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100755 samples/DeviceDiscovery.py diff --git a/samples/DeviceDiscovery.py b/samples/DeviceDiscovery.py new file mode 100755 index 0000000..7c6b1c8 --- /dev/null +++ b/samples/DeviceDiscovery.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python + +""" +This application presents a 'console' prompt to the user asking for Who-Is and I-Am +commands which create the related APDUs, then for each I-Am that is returned, reads +the object name of the device object (often called simply the device name). +""" + +import sys + +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.iocb import IOCB + +from bacpypes.pdu import Address, GlobalBroadcast +from bacpypes.apdu import WhoIsRequest, IAmRequest, ReadPropertyRequest, ReadPropertyACK +from bacpypes.primitivedata import CharacterString +from bacpypes.basetypes import ServicesSupported +from bacpypes.errors import DecodingError + +from bacpypes.app import BIPSimpleApplication +from bacpypes.service.device import LocalDeviceObject + +# some debugging +_debug = 1 +_log = ModuleLogger(globals()) + +# globals +this_device = None +this_application = None + +# +# DiscoveryApplication +# + +@bacpypes_debugging +class DiscoveryApplication(BIPSimpleApplication): + + def __init__(self, *args): + if _debug: DiscoveryApplication._debug("__init__ %r", args) + BIPSimpleApplication.__init__(self, *args) + + # keep track of requests to line up responses + self.who_is_request = None + + def request(self, apdu): + """Sniff for Who-Is requests going downstream.""" + if _debug: DiscoveryApplication._debug("request %r", apdu) + + # save a copy of just the Who-Is request + if isinstance(apdu, WhoIsRequest): + self.who_is_request = apdu + + # forward it along + BIPSimpleApplication.request(self, apdu) + + def do_IAmRequest(self, apdu): + """Do something with incoming I-Am requests.""" + if _debug: DiscoveryApplication._debug("do_IAmRequest %r", apdu) + + # check for required parameters + if apdu.iAmDeviceIdentifier is None: + raise MissingRequiredParameter("iAmDeviceIdentifier required") + if apdu.maxAPDULengthAccepted is None: + raise MissingRequiredParameter("maxAPDULengthAccepted required") + if apdu.segmentationSupported is None: + raise MissingRequiredParameter("segmentationSupported required") + if apdu.vendorID is None: + raise MissingRequiredParameter("vendorID required") + + # extract the device instance number + device_instance = apdu.iAmDeviceIdentifier[1] + if _debug: DiscoveryApplication._debug(" - device_instance: %r", device_instance) + + # extract the source address + device_address = apdu.pduSource + if _debug: DiscoveryApplication._debug(" - device_address: %r", device_address) + + # we didn't request anything yet + if not self.who_is_request: + return + + if (self.who_is_request.deviceInstanceRangeLowLimit is not None) and \ + (device_instance < self.who_is_request.deviceInstanceRangeLowLimit): + pass + elif (self.who_is_request.deviceInstanceRangeHighLimit is not None) and \ + (device_instance > self.who_is_request.deviceInstanceRangeHighLimit): + pass + else: + # build a request for the object name + request = ReadPropertyRequest( + destination=apdu.pduSource, + objectIdentifier=apdu.iAmDeviceIdentifier, + propertyIdentifier='objectName', + ) + + # make an IOCB + iocb = IOCB(request) + if _debug: DiscoveryApplication._debug(" - iocb: %r", iocb) + + # let us know when its complete + iocb.add_callback(self.device_discovered) + + # give it to the application + self.request_io(iocb) + + def device_discovered(self, iocb): + if _debug: DiscoveryApplication._debug("device_discovered %r", iocb) + + # do something for error/reject/abort + if iocb.ioError: + sys.stdout.write(str(iocb.ioError) + '\n') + + # do something for success + elif iocb.ioResponse: + apdu = iocb.ioResponse + + # should be an ack + if not isinstance(apdu, ReadPropertyACK): + if _debug: DiscoveryApplication._debug(" - not an ack") + return + + # pull out the name + device_name = apdu.propertyValue.cast_out(CharacterString) + if _debug: DiscoveryApplication._debug(" - device_name: %r", device_name) + + # print out the response + sys.stdout.write("%s is at %s named %r\n" % (apdu.objectIdentifier[1], apdu.pduSource, device_name)) + + # do something with nothing? + else: + if _debug: DiscoveryApplication._debug(" - ioError or ioResponse expected") + + +# +# DiscoveryConsoleCmd +# + +@bacpypes_debugging +class DiscoveryConsoleCmd(ConsoleCmd): + + def do_whois(self, args): + """whois [ ] [ ]""" + args = args.split() + if _debug: DiscoveryConsoleCmd._debug("do_whois %r", args) + + try: + # gather the parameters + request = WhoIsRequest() + if (len(args) == 1) or (len(args) == 3): + addr = Address(args[0]) + del args[0] + else: + addr = GlobalBroadcast() + + if len(args) == 2: + lolimit = int(args[0]) + hilimit = int(args[1]) + else: + lolimit = hilimit = None + + # code lives in the device service + this_application.who_is(lolimit, hilimit, addr) + + except Exception as error: + DiscoveryConsoleCmd._exception("exception: %r", error) + + def do_rtn(self, args): + """rtn ... """ + args = args.split() + if _debug: DiscoveryConsoleCmd._debug("do_rtn %r", args) + + # safe to assume only one adapter + adapter = this_application.nsap.adapters[0] + if _debug: DiscoveryConsoleCmd._debug(" - adapter: %r", adapter) + + # provide the address and a list of network numbers + router_address = Address(args[0]) + network_list = [int(arg) for arg in args[1:]] + + # pass along to the service access point + this_application.nsap.add_router_references(adapter, router_address, network_list) + + +# +# __main__ +# + +def main(): + global this_device + global this_application + + # parse the command line arguments + args = ConfigArgumentParser(description=__doc__).parse_args() + + if _debug: _log.debug("initialization") + if _debug: _log.debug(" - args: %r", args) + + # make a device object + this_device = LocalDeviceObject( + objectName=args.ini.objectname, + objectIdentifier=int(args.ini.objectidentifier), + maxApduLengthAccepted=int(args.ini.maxapdulengthaccepted), + segmentationSupported=args.ini.segmentationsupported, + vendorIdentifier=int(args.ini.vendoridentifier), + ) + + # make a simple application + this_application = DiscoveryApplication(this_device, args.ini.address) + + # get the services supported + services_supported = this_application.get_services_supported() + if _debug: _log.debug(" - services_supported: %r", services_supported) + + # let the device object know + this_device.protocolServicesSupported = services_supported.value + + # make a console + this_console = DiscoveryConsoleCmd() + if _debug: _log.debug(" - this_console: %r", this_console) + + # enable sleeping will help with threads + enable_sleeping() + + _log.debug("running") + + run() + + _log.debug("fini") + +if __name__ == "__main__": + main() From d7110ddbb834d90d639715a00e8d3cf7fb8c9d9b Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Thu, 9 Mar 2017 11:18:09 -0500 Subject: [PATCH 5/8] foreign version of the same discovery application --- samples/DeviceDiscoveryForeign.py | 239 ++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100755 samples/DeviceDiscoveryForeign.py diff --git a/samples/DeviceDiscoveryForeign.py b/samples/DeviceDiscoveryForeign.py new file mode 100755 index 0000000..fa315b9 --- /dev/null +++ b/samples/DeviceDiscoveryForeign.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python + +""" +This application presents a 'console' prompt to the user asking for Who-Is and I-Am +commands which create the related APDUs, then for each I-Am that is returned, reads +the object name of the device object (often called simply the device name). +""" + +import sys + +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.iocb import IOCB + +from bacpypes.pdu import Address, GlobalBroadcast +from bacpypes.apdu import WhoIsRequest, IAmRequest, ReadPropertyRequest, ReadPropertyACK +from bacpypes.primitivedata import CharacterString +from bacpypes.basetypes import ServicesSupported +from bacpypes.errors import DecodingError + +from bacpypes.app import BIPForeignApplication +from bacpypes.service.device import LocalDeviceObject + +# some debugging +_debug = 1 +_log = ModuleLogger(globals()) + +# globals +this_device = None +this_application = None + +# +# DiscoveryApplication +# + +@bacpypes_debugging +class DiscoveryApplication(BIPForeignApplication): + + def __init__(self, *args): + if _debug: DiscoveryApplication._debug("__init__ %r", args) + BIPForeignApplication.__init__(self, *args) + + # keep track of requests to line up responses + self.who_is_request = None + + def request(self, apdu): + """Sniff for Who-Is requests going downstream.""" + if _debug: DiscoveryApplication._debug("request %r", apdu) + + # save a copy of just the Who-Is request + if isinstance(apdu, WhoIsRequest): + self.who_is_request = apdu + + # forward it along + BIPForeignApplication.request(self, apdu) + + def do_IAmRequest(self, apdu): + """Do something with incoming I-Am requests.""" + if _debug: DiscoveryApplication._debug("do_IAmRequest %r", apdu) + + # check for required parameters + if apdu.iAmDeviceIdentifier is None: + raise MissingRequiredParameter("iAmDeviceIdentifier required") + if apdu.maxAPDULengthAccepted is None: + raise MissingRequiredParameter("maxAPDULengthAccepted required") + if apdu.segmentationSupported is None: + raise MissingRequiredParameter("segmentationSupported required") + if apdu.vendorID is None: + raise MissingRequiredParameter("vendorID required") + + # extract the device instance number + device_instance = apdu.iAmDeviceIdentifier[1] + if _debug: DiscoveryApplication._debug(" - device_instance: %r", device_instance) + + # extract the source address + device_address = apdu.pduSource + if _debug: DiscoveryApplication._debug(" - device_address: %r", device_address) + + # we didn't request anything yet + if not self.who_is_request: + return + + if (self.who_is_request.deviceInstanceRangeLowLimit is not None) and \ + (device_instance < self.who_is_request.deviceInstanceRangeLowLimit): + pass + elif (self.who_is_request.deviceInstanceRangeHighLimit is not None) and \ + (device_instance > self.who_is_request.deviceInstanceRangeHighLimit): + pass + else: + # build a request for the object name + request = ReadPropertyRequest( + destination=apdu.pduSource, + objectIdentifier=apdu.iAmDeviceIdentifier, + propertyIdentifier='objectName', + ) + + # make an IOCB + iocb = IOCB(request) + if _debug: DiscoveryApplication._debug(" - iocb: %r", iocb) + + # let us know when its complete + iocb.add_callback(self.device_discovered) + + # give it to the application + self.request_io(iocb) + + def device_discovered(self, iocb): + if _debug: DiscoveryApplication._debug("device_discovered %r", iocb) + + # do something for error/reject/abort + if iocb.ioError: + sys.stdout.write(str(iocb.ioError) + '\n') + + # do something for success + elif iocb.ioResponse: + apdu = iocb.ioResponse + + # should be an ack + if not isinstance(apdu, ReadPropertyACK): + if _debug: DiscoveryApplication._debug(" - not an ack") + return + + # pull out the name + device_name = apdu.propertyValue.cast_out(CharacterString) + if _debug: DiscoveryApplication._debug(" - device_name: %r", device_name) + + # print out the response + sys.stdout.write("%s is at %s named %r\n" % (apdu.objectIdentifier[1], apdu.pduSource, device_name)) + + # do something with nothing? + else: + if _debug: DiscoveryApplication._debug(" - ioError or ioResponse expected") + + +# +# DiscoveryConsoleCmd +# + +@bacpypes_debugging +class DiscoveryConsoleCmd(ConsoleCmd): + + def do_whois(self, args): + """whois [ ] [ ]""" + args = args.split() + if _debug: DiscoveryConsoleCmd._debug("do_whois %r", args) + + try: + # gather the parameters + request = WhoIsRequest() + if (len(args) == 1) or (len(args) == 3): + addr = Address(args[0]) + del args[0] + else: + addr = GlobalBroadcast() + + if len(args) == 2: + lolimit = int(args[0]) + hilimit = int(args[1]) + else: + lolimit = hilimit = None + + # code lives in the device service + this_application.who_is(lolimit, hilimit, addr) + + except Exception as error: + DiscoveryConsoleCmd._exception("exception: %r", error) + + def do_rtn(self, args): + """rtn ... """ + args = args.split() + if _debug: DiscoveryConsoleCmd._debug("do_rtn %r", args) + + # safe to assume only one adapter + adapter = this_application.nsap.adapters[0] + if _debug: DiscoveryConsoleCmd._debug(" - adapter: %r", adapter) + + # provide the address and a list of network numbers + router_address = Address(args[0]) + network_list = [int(arg) for arg in args[1:]] + + # pass along to the service access point + this_application.nsap.add_router_references(adapter, router_address, network_list) + + +# +# __main__ +# + +def main(): + global this_device + global this_application + + # parse the command line arguments + args = ConfigArgumentParser(description=__doc__).parse_args() + + if _debug: _log.debug("initialization") + if _debug: _log.debug(" - args: %r", args) + + # make a device object + this_device = LocalDeviceObject( + objectName=args.ini.objectname, + objectIdentifier=int(args.ini.objectidentifier), + maxApduLengthAccepted=int(args.ini.maxapdulengthaccepted), + segmentationSupported=args.ini.segmentationsupported, + vendorIdentifier=int(args.ini.vendoridentifier), + ) + + # make a simple application + this_application = DiscoveryApplication( + this_device, args.ini.address, + Address(args.ini.foreignbbmd), + int(args.ini.foreignttl), + ) + + # get the services supported + services_supported = this_application.get_services_supported() + if _debug: _log.debug(" - services_supported: %r", services_supported) + + # let the device object know + this_device.protocolServicesSupported = services_supported.value + + # make a console + this_console = DiscoveryConsoleCmd() + if _debug: _log.debug(" - this_console: %r", this_console) + + # enable sleeping will help with threads + enable_sleeping() + + _log.debug("running") + + run() + + _log.debug("fini") + +if __name__ == "__main__": + main() From 8db3db25cf53563424f1126a3b15fa879cc2c64c Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Thu, 9 Mar 2017 11:21:22 -0500 Subject: [PATCH 6/8] propagate the device information cache in the `BIPForeignApplication` like it does in the `BIPSimpleApplication`, should fix #109 --- py25/bacpypes/app.py | 4 ++++ py27/bacpypes/app.py | 4 ++++ py34/bacpypes/app.py | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/py25/bacpypes/app.py b/py25/bacpypes/app.py index 2817331..0dc4b46 100755 --- a/py25/bacpypes/app.py +++ b/py25/bacpypes/app.py @@ -534,6 +534,10 @@ class BIPForeignApplication(ApplicationIOController, WhoIsIAmServices, ReadWrite # can know if it should support segmentation self.smap = StateMachineAccessPoint(localDevice) + # the segmentation state machines need access to the same device + # information cache as the application + self.smap.deviceInfoCache = self.deviceInfoCache + # a network service access point will be needed self.nsap = NetworkServiceAccessPoint() diff --git a/py27/bacpypes/app.py b/py27/bacpypes/app.py index 805c0f6..bd35a64 100755 --- a/py27/bacpypes/app.py +++ b/py27/bacpypes/app.py @@ -530,6 +530,10 @@ class BIPForeignApplication(ApplicationIOController, WhoIsIAmServices, ReadWrite # can know if it should support segmentation self.smap = StateMachineAccessPoint(localDevice) + # the segmentation state machines need access to the same device + # information cache as the application + self.smap.deviceInfoCache = self.deviceInfoCache + # a network service access point will be needed self.nsap = NetworkServiceAccessPoint() diff --git a/py34/bacpypes/app.py b/py34/bacpypes/app.py index 805c0f6..bd35a64 100755 --- a/py34/bacpypes/app.py +++ b/py34/bacpypes/app.py @@ -530,6 +530,10 @@ class BIPForeignApplication(ApplicationIOController, WhoIsIAmServices, ReadWrite # can know if it should support segmentation self.smap = StateMachineAccessPoint(localDevice) + # the segmentation state machines need access to the same device + # information cache as the application + self.smap.deviceInfoCache = self.deviceInfoCache + # a network service access point will be needed self.nsap = NetworkServiceAccessPoint() From 3be5db8423c1a412fb9db672addfe2b7020a00aa Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Wed, 15 Mar 2017 01:00:45 -0400 Subject: [PATCH 7/8] patch provided in #111 --- py25/bacpypes/service/object.py | 4 ++-- py27/bacpypes/service/object.py | 4 ++-- py34/bacpypes/service/object.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/py25/bacpypes/service/object.py b/py25/bacpypes/service/object.py index f6cdc40..b755973 100755 --- a/py25/bacpypes/service/object.py +++ b/py25/bacpypes/service/object.py @@ -85,7 +85,7 @@ class ReadWritePropertyServices(Capability): if _debug: ReadWritePropertyServices._debug(" - resp: %r", resp) except PropertyError: - raise ExecutionError(errorClass='object', errorCode='unknownProperty') + raise ExecutionError(errorClass='property', errorCode='unknownProperty') # return the result self.response(resp) @@ -130,7 +130,7 @@ class ReadWritePropertyServices(Capability): if _debug: ReadWritePropertyServices._debug(" - resp: %r", resp) except PropertyError: - raise ExecutionError(errorClass='object', errorCode='unknownProperty') + raise ExecutionError(errorClass='property', errorCode='unknownProperty') # return the result self.response(resp) diff --git a/py27/bacpypes/service/object.py b/py27/bacpypes/service/object.py index e453a5b..efddfd6 100644 --- a/py27/bacpypes/service/object.py +++ b/py27/bacpypes/service/object.py @@ -86,7 +86,7 @@ class ReadWritePropertyServices(Capability): if _debug: ReadWritePropertyServices._debug(" - resp: %r", resp) except PropertyError: - raise ExecutionError(errorClass='object', errorCode='unknownProperty') + raise ExecutionError(errorClass='property', errorCode='unknownProperty') # return the result self.response(resp) @@ -131,7 +131,7 @@ class ReadWritePropertyServices(Capability): if _debug: ReadWritePropertyServices._debug(" - resp: %r", resp) except PropertyError: - raise ExecutionError(errorClass='object', errorCode='unknownProperty') + raise ExecutionError(errorClass='property', errorCode='unknownProperty') # return the result self.response(resp) diff --git a/py34/bacpypes/service/object.py b/py34/bacpypes/service/object.py index e453a5b..efddfd6 100755 --- a/py34/bacpypes/service/object.py +++ b/py34/bacpypes/service/object.py @@ -86,7 +86,7 @@ class ReadWritePropertyServices(Capability): if _debug: ReadWritePropertyServices._debug(" - resp: %r", resp) except PropertyError: - raise ExecutionError(errorClass='object', errorCode='unknownProperty') + raise ExecutionError(errorClass='property', errorCode='unknownProperty') # return the result self.response(resp) @@ -131,7 +131,7 @@ class ReadWritePropertyServices(Capability): if _debug: ReadWritePropertyServices._debug(" - resp: %r", resp) except PropertyError: - raise ExecutionError(errorClass='object', errorCode='unknownProperty') + raise ExecutionError(errorClass='property', errorCode='unknownProperty') # return the result self.response(resp) From 96d26a23a703916d5b19b5f238e9acb2f025d1ce Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Thu, 23 Mar 2017 15:34:42 -0400 Subject: [PATCH 8/8] unpack an address tuple from the destination #114 --- py34/bacpypes/bvllservice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py34/bacpypes/bvllservice.py b/py34/bacpypes/bvllservice.py index 087b88d..2b0c746 100755 --- a/py34/bacpypes/bvllservice.py +++ b/py34/bacpypes/bvllservice.py @@ -118,7 +118,7 @@ class UDPMultiplexer: dest = self.addrBroadcastTuple if _debug: UDPMultiplexer._debug(" - requesting local broadcast: %r", dest) elif pdu.pduDestination.addrType == Address.localStationAddr: - dest = pdu.pduDestination.addrTuple + dest = unpack_ip_addr(pdu.pduDestination.addrAddr) if _debug: UDPMultiplexer._debug(" - requesting local station: %r", dest) else: raise RuntimeError("invalid destination address type")