#!/usr/bin/env python """ This application presents a 'console' prompt to the user asking for read commands which create ReadPropertyRequest PDUs, waits for the response, then decodes the value if it is application encoded. This is useful for reading the values of propietary properties when the datatype isn't known. """ 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 from bacpypes.object import get_object_class from bacpypes.apdu import ReadPropertyRequest from bacpypes.primitivedata import Tag from bacpypes.app import BIPSimpleApplication from bacpypes.local.device import LocalDeviceObject # some debugging _debug = 0 _log = ModuleLogger(globals()) # globals this_application = None # # ReadPropertyAnyConsoleCmd # @bacpypes_debugging class ReadPropertyAnyConsoleCmd(ConsoleCmd): def do_read(self, args): """read [ ]""" args = args.split() if _debug: ReadPropertyAnyConsoleCmd._debug("do_read %r", args) try: addr, obj_type, obj_inst, prop_id = args[:4] if obj_type.isdigit(): obj_type = int(obj_type) elif not get_object_class(obj_type): raise ValueError("unknown object type") obj_inst = int(obj_inst) # build a request request = ReadPropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id, ) request.pduDestination = Address(addr) if len(args) == 5: request.propertyArrayIndex = int(args[4]) if _debug: ReadPropertyAnyConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadPropertyAnyConsoleCmd._debug(" - iocb: %r", iocb) # give it to the application this_application.request_io(iocb) # wait for it to complete iocb.wait() # do something for success if iocb.ioResponse: apdu = iocb.ioResponse # peek at the value tag value_tag = apdu.propertyValue.tagList.Peek() if _debug: ReadPropertyAnyConsoleCmd._debug(" - value_tag: %r", value_tag) # make sure that it is application tagged if value_tag.tagClass != Tag.applicationTagClass: sys.stdout.write("value is not application encoded\n") else: # find the datatype datatype = Tag._app_tag_class[value_tag.tagNumber] if _debug: ReadPropertyAnyConsoleCmd._debug(" - datatype: %r", datatype) if not datatype: raise TypeError("unknown datatype") # cast out the value value = apdu.propertyValue.cast_out(datatype) if _debug: ReadPropertyAnyConsoleCmd._debug(" - value: %r", value) sys.stdout.write("%s (%s)\n" % (value, datatype)) sys.stdout.flush() # do something for error/reject/abort if iocb.ioError: sys.stdout.write(str(iocb.ioError) + '\n') except Exception as error: ReadPropertyAnyConsoleCmd._exception("exception: %r", error) # # __main__ # def main(): 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(ini=args.ini) if _debug: _log.debug(" - this_device: %r", this_device) # provide max segments accepted if any kind of segmentation supported if args.ini.segmentationsupported != 'noSegmentation': this_device.maxSegmentsAccepted = int(args.ini.maxsegmentsaccepted) # make a simple application this_application = BIPSimpleApplication(this_device, args.ini.address) if _debug: _log.debug(" - this_application: %r", this_application) # make a console this_console = ReadPropertyAnyConsoleCmd() 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()