From 4eb58b6238c762cbf748770e9db92a8b69e1ff53 Mon Sep 17 00:00:00 2001 From: Joel Bender Date: Wed, 31 Aug 2016 10:27:00 -0400 Subject: [PATCH] update samples to use services --- samples/ReadPropertyMultiple.py | 155 +++++++++----------- samples/ReadPropertyMultipleServer.py | 203 ++------------------------ 2 files changed, 80 insertions(+), 278 deletions(-) diff --git a/samples/ReadPropertyMultiple.py b/samples/ReadPropertyMultiple.py index 7febd6a..54b9794 100755 --- a/samples/ReadPropertyMultiple.py +++ b/samples/ReadPropertyMultiple.py @@ -18,7 +18,7 @@ from bacpypes.pdu import Address from bacpypes.object import get_object_class, get_datatype from bacpypes.apdu import ReadPropertyMultipleRequest, PropertyReference, \ - ReadAccessSpecification, Error, AbortPDU, ReadPropertyMultipleACK + ReadAccessSpecification, ReadPropertyMultipleACK from bacpypes.primitivedata import Unsigned from bacpypes.constructeddata import Array from bacpypes.basetypes import PropertyIdentifier @@ -31,91 +31,7 @@ _debug = 0 _log = ModuleLogger(globals()) # globals -this_device = None this_application = None -this_console = None - -# -# ReadPropertyMultipleApplication -# - -@bacpypes_debugging -class ReadPropertyMultipleApplication(BIPSimpleApplication): - - def __init__(self, *args): - if _debug: ReadPropertyMultipleApplication._debug("__init__ %r", args) - BIPSimpleApplication.__init__(self, *args) - - # keep track of requests to line up responses - self._request = None - - def request(self, apdu): - if _debug: ReadPropertyMultipleApplication._debug("request %r", apdu) - - # save a copy of the request - self._request = apdu - - # forward it along - BIPSimpleApplication.request(self, apdu) - - def confirmation(self, apdu): - if _debug: ReadPropertyMultipleApplication._debug("confirmation %r", apdu) - - if isinstance(apdu, Error): - sys.stdout.write("error: %s\n" % (apdu.errorCode,)) - sys.stdout.flush() - - elif isinstance(apdu, AbortPDU): - apdu.debug_contents() - - elif (isinstance(self._request, ReadPropertyMultipleRequest)) and (isinstance(apdu, ReadPropertyMultipleACK)): - # loop through the results - for result in apdu.listOfReadAccessResults: - # here is the object identifier - objectIdentifier = result.objectIdentifier - if _debug: ReadPropertyMultipleApplication._debug(" - objectIdentifier: %r", objectIdentifier) - - # now come the property values per object - for element in result.listOfResults: - # get the property and array index - propertyIdentifier = element.propertyIdentifier - if _debug: ReadPropertyMultipleApplication._debug(" - propertyIdentifier: %r", propertyIdentifier) - propertyArrayIndex = element.propertyArrayIndex - if _debug: ReadPropertyMultipleApplication._debug(" - propertyArrayIndex: %r", propertyArrayIndex) - - # here is the read result - readResult = element.readResult - - sys.stdout.write(propertyIdentifier) - if propertyArrayIndex is not None: - sys.stdout.write("[" + str(propertyArrayIndex) + "]") - - # check for an error - if readResult.propertyAccessError is not None: - sys.stdout.write(" ! " + str(readResult.propertyAccessError) + '\n') - - else: - # here is the value - propertyValue = readResult.propertyValue - - # find the datatype - datatype = get_datatype(objectIdentifier[0], propertyIdentifier) - if _debug: ReadPropertyMultipleApplication._debug(" - datatype: %r", datatype) - if not datatype: - raise TypeError("unknown datatype") - - # special case for array parts, others are managed by cast_out - if issubclass(datatype, Array) and (propertyArrayIndex is not None): - if propertyArrayIndex == 0: - value = propertyValue.cast_out(Unsigned) - else: - value = propertyValue.cast_out(datatype.subtype) - else: - value = propertyValue.cast_out(datatype) - if _debug: ReadPropertyMultipleApplication._debug(" - value: %r", value) - - sys.stdout.write(" = " + str(value) + '\n') - sys.stdout.flush() # # ReadPropertyMultipleConsoleCmd @@ -199,7 +115,72 @@ class ReadPropertyMultipleConsoleCmd(ConsoleCmd): if _debug: ReadPropertyMultipleConsoleCmd._debug(" - request: %r", request) # give it to the application - this_application.request(request) + iocb = this_application.request(request) + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - iocb: %r", iocb) + + # wait for it to complete + iocb.wait() + + # do something for success + if iocb.ioResponse: + apdu = iocb.ioResponse + + # should be an ack + if not isinstance(apdu, ReadPropertyMultipleACK): + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - not an ack") + return + + # loop through the results + for result in apdu.listOfReadAccessResults: + # here is the object identifier + objectIdentifier = result.objectIdentifier + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - objectIdentifier: %r", objectIdentifier) + + # now come the property values per object + for element in result.listOfResults: + # get the property and array index + propertyIdentifier = element.propertyIdentifier + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - propertyIdentifier: %r", propertyIdentifier) + propertyArrayIndex = element.propertyArrayIndex + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - propertyArrayIndex: %r", propertyArrayIndex) + + # here is the read result + readResult = element.readResult + + sys.stdout.write(propertyIdentifier) + if propertyArrayIndex is not None: + sys.stdout.write("[" + str(propertyArrayIndex) + "]") + + # check for an error + if readResult.propertyAccessError is not None: + sys.stdout.write(" ! " + str(readResult.propertyAccessError) + '\n') + + else: + # here is the value + propertyValue = readResult.propertyValue + + # find the datatype + datatype = get_datatype(objectIdentifier[0], propertyIdentifier) + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - datatype: %r", datatype) + if not datatype: + raise TypeError("unknown datatype") + + # special case for array parts, others are managed by cast_out + if issubclass(datatype, Array) and (propertyArrayIndex is not None): + if propertyArrayIndex == 0: + value = propertyValue.cast_out(Unsigned) + else: + value = propertyValue.cast_out(datatype.subtype) + else: + value = propertyValue.cast_out(datatype) + if _debug: ReadPropertyMultipleConsoleCmd._debug(" - value: %r", value) + + sys.stdout.write(" = " + str(value) + '\n') + sys.stdout.flush() + + # do something for error/reject/abort + if iocb.ioError: + sys.stdout.write(str(iocb.ioError) + '\n') except Exception as error: ReadPropertyMultipleConsoleCmd._exception("exception: %r", error) @@ -227,7 +208,7 @@ def main(): ) # make a simple application - this_application = ReadPropertyMultipleApplication(this_device, args.ini.address) + this_application = BIPSimpleApplication(this_device, args.ini.address) # get the services supported services_supported = this_application.get_services_supported() diff --git a/samples/ReadPropertyMultipleServer.py b/samples/ReadPropertyMultipleServer.py index d87420c..134ff1b 100755 --- a/samples/ReadPropertyMultipleServer.py +++ b/samples/ReadPropertyMultipleServer.py @@ -12,21 +12,26 @@ from bacpypes.consolelogging import ConfigArgumentParser from bacpypes.core import run -from bacpypes.primitivedata import Atomic, Real, Unsigned -from bacpypes.constructeddata import Array, Any -from bacpypes.basetypes import ErrorType -from bacpypes.apdu import ReadPropertyMultipleACK, ReadAccessResult, ReadAccessResultElement, ReadAccessResultElementChoice -from bacpypes.object import AnalogValueObject, Property, PropertyError, register_object_type -from bacpypes.apdu import Error +from bacpypes.primitivedata import Real +from bacpypes.object import AnalogValueObject, Property, register_object_type from bacpypes.errors import ExecutionError from bacpypes.app import BIPSimpleApplication -from bacpypes.service.device import LocalDeviceObject +from bacpypes.service.device import ReadWritePropertyMultipleServices, \ + LocalDeviceObject # some debugging _debug = 0 _log = ModuleLogger(globals()) +# +# ReadPropertyMultipleApplication +# + +@bacpypes_debugging +class ReadPropertyMultipleApplication(BIPSimpleApplication, ReadWritePropertyMultipleServices): + pass + # # RandomValueProperty # @@ -72,190 +77,6 @@ class RandomAnalogValueObject(AnalogValueObject): register_object_type(RandomAnalogValueObject) -# -# ReadPropertyToAny -# - -@bacpypes_debugging -def ReadPropertyToAny(obj, propertyIdentifier, propertyArrayIndex=None): - """Read the specified property of the object, with the optional array index, - and cast the result into an Any object.""" - if _debug: ReadPropertyToAny._debug("ReadPropertyToAny %s %r %r", obj, propertyIdentifier, propertyArrayIndex) - - # get the datatype - datatype = obj.get_datatype(propertyIdentifier) - if _debug: ReadPropertyToAny._debug(" - datatype: %r", datatype) - if datatype is None: - raise ExecutionError(errorClass='property', errorCode='datatypeNotSupported') - - # get the value - value = obj.ReadProperty(propertyIdentifier, propertyArrayIndex) - if _debug: ReadPropertyToAny._debug(" - value: %r", value) - if value is None: - raise ExecutionError(errorClass='property', errorCode='unknownProperty') - - # change atomic values into something encodeable - if issubclass(datatype, Atomic): - value = datatype(value) - elif issubclass(datatype, Array) and (propertyArrayIndex is not None): - if propertyArrayIndex == 0: - value = Unsigned(value) - elif issubclass(datatype.subtype, Atomic): - value = datatype.subtype(value) - elif not isinstance(value, datatype.subtype): - raise TypeError("invalid result datatype, expecting %s and got %s" \ - % (datatype.subtype.__name__, type(value).__name__)) - elif not isinstance(value, datatype): - raise TypeError("invalid result datatype, expecting %s and got %s" \ - % (datatype.__name__, type(value).__name__)) - if _debug: ReadPropertyToAny._debug(" - encodeable value: %r", value) - - # encode the value - result = Any() - result.cast_in(value) - if _debug: ReadPropertyToAny._debug(" - result: %r", result) - - # return the object - return result - -# -# ReadPropertyToResultElement -# - -@bacpypes_debugging -def ReadPropertyToResultElement(obj, propertyIdentifier, propertyArrayIndex=None): - """Read the specified property of the object, with the optional array index, - and cast the result into an Any object.""" - if _debug: ReadPropertyToResultElement._debug("ReadPropertyToResultElement %s %r %r", obj, propertyIdentifier, propertyArrayIndex) - - # save the result in the property value - read_result = ReadAccessResultElementChoice() - - try: - read_result.propertyValue = ReadPropertyToAny(obj, propertyIdentifier, propertyArrayIndex) - if _debug: ReadPropertyToResultElement._debug(" - success") - except PropertyError as error: - if _debug: ReadPropertyToResultElement._debug(" - error: %r", error) - read_result.propertyAccessError = ErrorType(errorClass='property', errorCode='unknownProperty') - except ExecutionError as error: - if _debug: ReadPropertyToResultElement._debug(" - error: %r", error) - read_result.propertyAccessError = ErrorType(errorClass=error.errorClass, errorCode=error.errorCode) - - # make an element for this value - read_access_result_element = ReadAccessResultElement( - propertyIdentifier=propertyIdentifier, - propertyArrayIndex=propertyArrayIndex, - readResult=read_result, - ) - if _debug: ReadPropertyToResultElement._debug(" - read_access_result_element: %r", read_access_result_element) - - # fini - return read_access_result_element - -# -# ReadPropertyMultipleApplication -# - -@bacpypes_debugging -class ReadPropertyMultipleApplication(BIPSimpleApplication): - - def __init__(self, *args, **kwargs): - if _debug: ReadPropertyMultipleApplication._debug("__init__ %r %r", args, kwargs) - BIPSimpleApplication.__init__(self, *args, **kwargs) - - def do_ReadPropertyMultipleRequest(self, apdu): - """Respond to a ReadPropertyMultiple Request.""" - if _debug: ReadPropertyMultipleApplication._debug("do_ReadPropertyMultipleRequest %r", apdu) - - # response is a list of read access results (or an error) - resp = None - read_access_result_list = [] - - # loop through the request - for read_access_spec in apdu.listOfReadAccessSpecs: - # get the object identifier - objectIdentifier = read_access_spec.objectIdentifier - if _debug: ReadPropertyMultipleApplication._debug(" - objectIdentifier: %r", objectIdentifier) - - # check for wildcard - if (objectIdentifier == ('device', 4194303)): - if _debug: ReadPropertyMultipleApplication._debug(" - wildcard device identifier") - objectIdentifier = self.localDevice.objectIdentifier - - # get the object - obj = self.get_object_id(objectIdentifier) - if _debug: ReadPropertyMultipleApplication._debug(" - object: %r", obj) - - # make sure it exists - if not obj: - resp = Error(errorClass='object', errorCode='unknownObject', context=apdu) - if _debug: ReadPropertyMultipleApplication._debug(" - unknown object error: %r", resp) - break - - # build a list of result elements - read_access_result_element_list = [] - - # loop through the property references - for prop_reference in read_access_spec.listOfPropertyReferences: - # get the property identifier - propertyIdentifier = prop_reference.propertyIdentifier - if _debug: ReadPropertyMultipleApplication._debug(" - propertyIdentifier: %r", propertyIdentifier) - - # get the array index (optional) - propertyArrayIndex = prop_reference.propertyArrayIndex - if _debug: ReadPropertyMultipleApplication._debug(" - propertyArrayIndex: %r", propertyArrayIndex) - - # check for special property identifiers - if propertyIdentifier in ('all', 'required', 'optional'): - for propId, prop in obj._properties.items(): - if _debug: ReadPropertyMultipleApplication._debug(" - checking: %r %r", propId, prop.optional) - - if (propertyIdentifier == 'all'): - pass - elif (propertyIdentifier == 'required') and (prop.optional): - if _debug: ReadPropertyMultipleApplication._debug(" - not a required property") - continue - elif (propertyIdentifier == 'optional') and (not prop.optional): - if _debug: ReadPropertyMultipleApplication._debug(" - not an optional property") - continue - - # read the specific property - read_access_result_element = ReadPropertyToResultElement(obj, propId, propertyArrayIndex) - - # check for undefined property - if read_access_result_element.readResult.propertyAccessError \ - and read_access_result_element.readResult.propertyAccessError.errorCode == 'unknownProperty': - continue - - # add it to the list - read_access_result_element_list.append(read_access_result_element) - - else: - # read the specific property - read_access_result_element = ReadPropertyToResultElement(obj, propertyIdentifier, propertyArrayIndex) - - # add it to the list - read_access_result_element_list.append(read_access_result_element) - - # build a read access result - read_access_result = ReadAccessResult( - objectIdentifier=objectIdentifier, - listOfResults=read_access_result_element_list - ) - if _debug: ReadPropertyMultipleApplication._debug(" - read_access_result: %r", read_access_result) - - # add it to the list - read_access_result_list.append(read_access_result) - - # this is a ReadPropertyMultiple ack - if not resp: - resp = ReadPropertyMultipleACK(context=apdu) - resp.listOfReadAccessResults = read_access_result_list - if _debug: ReadPropertyMultipleApplication._debug(" - resp: %r", resp) - - # return the result - self.response(resp) - # # __main__ #