def send_subscription(self, context): if _debug: SubscribeCOVApplication._debug("send_subscription %r", context) # build a request request = SubscribeCOVRequest( subscriberProcessIdentifier=context.subscriberProcessIdentifier, monitoredObjectIdentifier=context.monitoredObjectIdentifier, ) request.pduDestination = context.address # optional parameters if context.issueConfirmedNotifications is not None: request.issueConfirmedNotifications = context.issueConfirmedNotifications if context.lifetime is not None: request.lifetime = context.lifetime # make an IOCB iocb = IOCB(request) if _debug: SubscribeCOVApplication._debug(" - iocb: %r", iocb) # callback when it is acknowledged iocb.add_callback(self.subscription_acknowledged) # give it to the application this_application.request_io(iocb)
def read_object_list(self, device_id, device_addr): if _debug: ReadAllObjectPropertiesApplication._debug("read_object_list %r %r", device_id, device_addr) # create a context to hold the results context = ObjectPropertyContext(device_id, device_addr) # build a request for the object name request = ReadPropertyRequest( destination=context.device_addr, objectIdentifier=context.device_id, propertyIdentifier='objectList', ) if _debug: ReadAllObjectPropertiesApplication._debug(" - request: %r", request) # make an IOCB, reference the context iocb = IOCB(request) iocb.context = context if _debug: ReadAllObjectPropertiesApplication._debug(" - iocb: %r", iocb) # let us know when its complete iocb.add_callback(self.object_list_results) # give it to the application self.request_io(iocb)
def next_request(self): if _debug: ReadPropertyApplication._debug("next_request") global device_address, object_identifier, property_list # check to see if we're done if not property_list: if _debug: ReadPropertyApplication._debug(" - done") stop() return # get the next request self.property_identifier = property_list.popleft() if _debug: ReadPropertyApplication._debug(" - property_identifier: %r", self.property_identifier) # build a request request = ReadPropertyRequest( destination=device_address, objectIdentifier=object_identifier, propertyIdentifier=self.property_identifier, ) if _debug: ReadPropertyApplication._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) # set a callback for the response iocb.add_callback(self.complete_request) if _debug: ReadPropertyApplication._debug(" - iocb: %r", iocb) # send the request this_application.request_io(iocb)
def _discovery(self): global device_address # build a request obj_type, prop_id = ('device', 'objectList') # build a request request = ReadPropertyRequest( objectIdentifier=(obj_type, self._device_id), propertyIdentifier=prop_id, ) request.pduSource = Address(this_device._address) request.pduDestination = Address(int(self._addr)) request.propertyArrayIndex = self._instance_list.pop(0) if _debug: BacnetClientConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) # set a callback for the response iocb.add_callback(self._discovery_response) if _debug: BacnetClientConsoleCmd._debug(" - iocb: %r", iocb) # send the request this_application.request_io(iocb)
def iam(self, destination=None): """ Build an IAm response. IAm are sent in response to a WhoIs request that; matches our device ID, whose device range includes us, or is a broadcast. Content is defined by the script (deviceId, vendor, etc...) :returns: bool Example:: iam() """ self._log.debug("do_iam") try: # build a response request = self._iam_request(destination=destination) iocb = IOCB(request) # make an IOCB deferred(self.this_application.request_io, iocb) iocb.wait() return True except Exception as error: self._log.error("exception: {!r}".format(error)) return False
def next_request(self): if _debug: ReadPointListApplication._debug("next_request") # check to see if we're done if not self.point_queue: if _debug: ReadPointListApplication._debug(" - done") stop() return # get the next request addr, obj_type, obj_inst, prop_id = self.point_queue.popleft() # build a request request = ReadPropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id, ) request.pduDestination = Address(addr) if _debug: ReadPointListApplication._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) # set a callback for the response iocb.add_callback(self.complete_request) if _debug: ReadPointListApplication._debug(" - iocb: %r", iocb) # send the request this_application.request_io(iocb)
def next_request(self): # check to see if we're done if not self.point_queue: stop() return # get the next request point_id, addr, obj_type, obj_inst, prop_id, idx = self.point_queue.popleft() # build a request request = ReadPropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id, propertyArrayIndex=idx ) request.pduDestination = Address(addr) # make an IOCB iocb = IOCB(request) # set a callback for the response iocb.add_callback(self.complete_request) # send the request self.request_io(iocb)
def _get_value_for_prop(self, prop): request = ReadPropertyRequest(destination=self.device.source, objectIdentifier=self.object, propertyIdentifier=prop) iocb = IOCB(request) iocb.add_callback(self._got_prop, prop) self.bacnet_adapter.request_io(iocb)
def read_next_object(self, context): if _debug: ReadObjectListApplication._debug("read_next_object %r", context) # if there's nothing more to do, we're done if not context._object_list_queue: if _debug: ReadObjectListApplication._debug(" - all done") context.completed() return # pop off the next object identifier object_id = context._object_list_queue.popleft() if _debug: ReadObjectListApplication._debug(" - object_id: %r", object_id) # build a request for the object name request = ReadPropertyRequest( destination=context.device_addr, objectIdentifier=object_id, propertyIdentifier='objectName', ) if _debug: ReadObjectListApplication._debug(" - request: %r", request) # make an IOCB, reference the context iocb = IOCB(request) iocb.context = context if _debug: ReadObjectListApplication._debug(" - iocb: %r", iocb) # let us know when its complete iocb.add_callback(self.object_name_results) # give it to the application self.request_io(iocb)
def do_request(self): if _debug: ReadPointListApplication._debug('do_request') request = SubscribeCOVRequest(subscriberProcessIdentifier=1234, monitoredObjectIdentifier=('analogInput', 0), issueConfirmedNotifications=False, lifetime=100) request.pduDestination = Address('192.168.2.70') if _debug: ReadPointListApplication._debug(' - request: %r', request) # make an IOCB iocb = IOCB(request) # set a callback for the response # iocb.add_callback(self.complete_request) if _debug: ReadPointListApplication._debug(" - iocb: %r", iocb) # send the request this_application.request_io(iocb) iocb.wait() # do something for success if iocb.ioResponse: if _debug: ReadPointListApplication._debug(" - response: %r", iocb.ioResponse) # do something for error/reject/abort if iocb.ioError: if _debug: ReadPointListApplication._debug(" - error: %r", iocb.ioError)
def _get_device_info(self): request = ReadPropertyRequest(destination=self.source, objectIdentifier=self.id, propertyIdentifier='objectName') iocb = IOCB(request) iocb.add_callback(self._got_object_name) self.bacnet_adapter.request_io(iocb)
def _get_new_sensors_for_new_device(self, source, device_id): request = ReadPropertyRequest(destination=source, objectIdentifier=device_id, propertyIdentifier="objectList") iocb = IOCB(request) iocb.add_callback(self._got_sensors_for_device) self.bacnet_adapter.request_io(iocb)
def do_save(self, args): """save <addr> <device instance>""" args = args.split() if _debug: SaveToFlashConsoleCmd._debug("do_save %r", args) try: addr, obj_inst = args[:2] # object type = 8 (device). property = 1151 (SaveToFlash) obj_type = 8 obj_inst = int(obj_inst) prop_id = 1151 # build a request request = WritePropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id, ) request.pduDestination = Address(addr) if len(args) == 5: request.propertyArrayIndex = int(args[4]) # send an Enumerated value of 1 means SaveToFlash tag_list = TagList([ApplicationTag(9, xtob('01'))]) if _debug: SaveToFlashConsoleCmd._debug(" - tag_list: %r", tag_list) # stuff the tag list into an Any request.propertyValue = Any() request.propertyValue.decode(tag_list) if _debug: SaveToFlashConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: SaveToFlashConsoleCmd._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: # should be an ack if not isinstance(iocb.ioResponse, SimpleAckPDU): if _debug: SaveToFlashConsoleCmd._debug(" - not an ack") return sys.stdout.write("ack\n") # do something for error/reject/abort if iocb.ioError: sys.stdout.write(str(iocb.ioError) + '\n') except Exception as error: SaveToFlashConsoleCmd._exception("exception: %r", error)
def __init__(self, *args): BIPSimpleApplication.__init__(Mock()) self.elementService = Mock() #self.ResponseQueue = Mock() #self.ResponseQueue.get.return_value = ([21, 'degreesCelcius'], Event()) iocb = IOCB() apdu = ReadPropertyMultipleACK(listOfReadAccessResults=[ ReadAccessResult( objectIdentifier=('analogValue', 1), listOfResults=[ ReadAccessResultElement( propertyIdentifier='presentValue', readResult=ReadAccessResultElementChoice( propertyValue=Any(Real(21.0)), )), ReadAccessResultElement( propertyIdentifier='units', readResult=ReadAccessResultElementChoice( propertyValue=Any(Enumerated(62)), )), ], ) ]) iocb.complete(apdu) self.request = Mock() self.request.return_value = iocb
def _get_prop_for_obj(self, obj_id): request = ReadPropertyRequest(destination=self.device.source, objectIdentifier=obj_id, propertyIdentifier='propertyList') iocb = IOCB(request) iocb.add_callback(self._got_properties_for_object, obj_id) self.bacnet_adapter.request_io(iocb)
def read_prop_vendor(self): #get bacnet source pdu from point_list array. point_list has been override by next_request method addr = point_list[0][0] obj_type = self.obj obj_inst = self.inst prop_id = self.prop # build a request request = ReadPropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=int(prop_id), ) request.pduDestination = Address(addr) request.propertyArrayIndex = self.idx #if _debug: ReadPropertyAnyConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) #if _debug: ReadPropertyAnyConsoleCmd._debug(" - iocb: %r", iocb) # set a callback for the response iocb.add_callback(self.prop_vendor_ack) # give it to the application this_application.request_io(iocb)
def whois(self, *args, global_broadcast=False): """ Build a WhoIs request :param args: string built as [ <addr>] [ <lolimit> <hilimit> ] **optional** :returns: discoveredDevices as a defaultdict(int) Example:: whois(global_broadcast=True) # WhoIs broadcast globally. Every device will respond with an IAm whois('2:5') # WhoIs looking for the device at (Network 2, Address 5) whois('10 1000') # WhoIs looking for devices in the ID range (10 - 1000) """ if not self._started: raise ApplicationNotStarted( "BACnet stack not running - use startApp()") if args: args = args[0].split() msg = args if args else "any" self._log.debug("do_whois {!r}".format(msg)) # build a request request = WhoIsRequest() if (len(args) == 1) or (len(args) == 3): request.pduDestination = Address(args[0]) del args[0] else: if global_broadcast: request.pduDestination = GlobalBroadcast() else: request.pduDestination = LocalBroadcast() if len(args) == 2: try: request.deviceInstanceRangeLowLimit = int(args[0]) request.deviceInstanceRangeHighLimit = int(args[1]) except ValueError: pass self._log.debug("{:>12} {}".format("- request:", request)) iocb = IOCB(request) # make an IOCB self.this_application._last_i_am_received = [] # pass to the BACnet stack deferred(self.this_application.request_io, iocb) iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response apdu = iocb.ioResponse if iocb.ioError: # unsuccessful: error/reject/abort pass time.sleep(3) self.discoveredDevices = self.this_application.i_am_counter return self.this_application._last_i_am_received
def get_object_list(self): request = ReadPropertyRequest(destination=self.source, objectIdentifier=self.id, propertyIdentifier="objectList") iocb = IOCB(request) iocb.add_callback(self._got_object_list) self.bacnet_adapter.request_io(iocb)
def prepare(self): if _debug: SomethingToDo._debug("prepare(%d)", self.args[0]) # build an IOCB and add the completion callback iocb = IOCB(*self.args, **self.kwargs) iocb.add_callback(self.complete) if _debug: SomethingToDo._debug(" - iocb: %r", iocb) return iocb
def do_saverl(self, args): """saverl <addr> <inst>""" args = args.split() if _debug: EventNotificationConsoleCmd._debug("do_saverl %r", args) global saved_recipent_list try: addr, obj_inst = args obj_inst = int(obj_inst) # build a request request = ReadPropertyRequest( objectIdentifier=('notificationClass', obj_inst), propertyIdentifier='recipientList', ) request.pduDestination = Address(addr) # make an IOCB iocb = IOCB(request) if _debug: EventNotificationConsoleCmd._debug(" - iocb: %r", iocb) # give it to the application deferred(this_application.request_io, iocb) # wait for it to complete iocb.wait() # 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: EventNotificationConsoleCmd._debug(" - not an ack") return # turn the property tag list blob into a list of destinations saved_recipent_list = apdu.propertyValue.cast_out( ListOfDestination) for destination in saved_recipent_list: destination.debug_contents(file=sys.stdout) # do something with nothing? else: if _debug: EventNotificationConsoleCmd._debug( " - ioError or ioResponse expected") except Exception as error: EventNotificationConsoleCmd._exception("exception: %r", error)
def run(self): if _debug: ReadPointListThread._debug("run") global this_application # loop through the points for obj_id, prop_id in self.point_list: obj_id = ObjectIdentifier(obj_id).value # build a request request = ReadPropertyRequest( destination=self.device_address, objectIdentifier=obj_id, propertyIdentifier=prop_id, ) if _debug: ReadPointListThread._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadPointListThread._debug(" - iocb: %r", iocb) # give it to the application deferred(this_application.request_io, iocb) # wait for the response iocb.wait() if iocb.ioResponse: apdu = iocb.ioResponse # find the datatype datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier) if _debug: ReadPointListThread._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 (apdu.propertyArrayIndex is not None): if apdu.propertyArrayIndex == 0: value = apdu.propertyValue.cast_out(Unsigned) else: value = apdu.propertyValue.cast_out(datatype.subtype) else: value = apdu.propertyValue.cast_out(datatype) if _debug: ReadPointListThread._debug(" - value: %r", value) # save the value self.response_values.append(value) if iocb.ioError: if _debug: ReadPointListThread._debug(" - error: %r", iocb.ioError) self.response_values.append(iocb.ioError) if _debug: ReadPointListThread._debug(" - fini")
def send_cov_subscription(self, request): self._log.debug("Request : {}".format(request)) iocb = IOCB(request) self._log.debug("IOCB : {}".format(iocb)) iocb.add_callback(self.subscription_acknowledged) # pass to the BACnet stack deferred(self.this_application.request_io, iocb)
def do_dcc(self, args): """dcc <addr> [ <duration> ] <enable> [ <password> ]""" args = args.split() if _debug: DCCConsoleCmd._debug("do_dcc %r", args) try: addr = args[0] if len(args) == 2: enable_disable = args[1] time_duration = password = None elif len(args) == 3: if args[1].isdigit(): time_duration = int(args[1]) enable_disable = args[2] password = None else: time_duration = None enable_disable = args[1] password = args[2] else: time_duration = int(args[1]) enable_disable = args[2] password = args[3] # build a request request = DeviceCommunicationControlRequest( enableDisable=enable_disable, ) request.pduDestination = Address(addr) if time_duration is not None: request.timeDuration = time_duration if password is not None: request.password = password if _debug: DCCConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: DCCConsoleCmd._debug(" - iocb: %r", iocb) # give it to the application this_application.request_io(iocb) # wait for it to complete iocb.wait() # do something for error/reject/abort if iocb.ioError: sys.stdout.write(str(iocb.ioError) + '\n') else: if _debug: DCCConsoleCmd._debug(" - ack") except Exception as error: DCCConsoleCmd._exception("exception: %r", error)
def main(): # parse the command line arguments args = ArgumentParser(description=__doc__).parse_args() if _debug: _log.debug("initialization") if _debug: _log.debug(" - args: %r", args) # create a controller some_controller = SomeController() if _debug: _log.debug(" - some_controller: %r", some_controller) # test set tests = [ (( 1, 2, ), { 'a': 3 }), (( 4, 5, ), {}), ((6, ), { 'a': 7 }), ] for test_args, test_kwargs in tests: print("test_args, test_kwargs: %r, %r" % (test_args, test_kwargs)) # create a request with some args and kwargs iocb = IOCB(*test_args, **test_kwargs) # add a callback function , called when the request has been processed iocb.add_callback(call_me) # give the request to the controller some_controller.request_io(iocb) # wait for the request to be processed iocb.ioComplete.wait() if _debug: _log.debug(" - iocb: %r", iocb) # dump the contents print("iocb completion event set: %r" % (iocb.ioComplete.is_set(), )) print("") print("iocb successful: %r" % (iocb.ioState == COMPLETED, )) print("iocb response: %r" % (iocb.ioResponse, )) print("") print("iocb aborted: %r" % (iocb.ioState == ABORTED, )) print("iocb error: %r" % (iocb.ioError, )) print("")
def read_next_object_properties(self, context): if _debug: ReadAllObjectPropertiesApplication._debug("read_next_object %r", context) # if there's nothing more to do, we're done if all([ len(context.properties_dict_queue[element]) == 0 for element in context.properties_dict_queue ]): if _debug: ReadAllObjectPropertiesApplication._debug(" - all done") context.completed() return # pop off the next object identifier if context.current_object_id is None or len( context.properties_dict_queue[context.current_object_id]) == 0: context.current_object_id = context._object_list_queue.popleft() context.property_result_dict.update({ context.current_object_id[0] + str(context.current_object_id[1]): dict() }) context.current_property = context.properties_dict_queue[ context.current_object_id].popleft() if _debug: ReadAllObjectPropertiesApplication._debug( " - object_id: %r", context.current_object_id) # build a request for the object name request = ReadPropertyRequest( destination=context.device_addr, objectIdentifier=context.current_object_id, propertyIdentifier=context.current_property[0], ) if _debug: ReadAllObjectPropertiesApplication._debug(" - request: %r", request) # make an IOCB, reference the context iocb = IOCB(request) iocb.context = context if _debug: ReadAllObjectPropertiesApplication._debug(" - iocb: %r", iocb) # let us know when its complete iocb.add_callback(self.object_properties_results) # give it to the application self.request_io(iocb)
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 dcc(self, address=None, duration=None, password=None, state=None): """ Will send DeviceCommunicationControl request """ if not self._started: raise ApplicationNotStarted( "BACnet stack not running - use startApp()") if not address: raise ValueError("Provide address for request") if not state: raise ValueError( "Provide state ('enable', 'disable', 'disableInitiation'") # build a request request = DeviceCommunicationControlRequest() request.enableDisable = DeviceCommunicationControlRequestEnableDisable.enumerations[ state] request.pduDestination = Address(address) if duration: request.duration = Unsigned16(duration) request.password = CharacterString(password) self._log.debug("{:>12} {}".format("- request:", request)) iocb = IOCB(request) # make an IOCB # pass to the BACnet stack deferred(self.this_application.request_io, iocb) # Unconfirmed request...so wait until complete iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response apdu = iocb.ioResponse if not isinstance(apdu, SimpleAckPDU): # expect an ACK self._log.warning("Not an ack, see debug for more infos.") self._log.debug("Not an ack. | APDU : {} / {}".format( (apdu, type(apdu)))) return if iocb.ioError: # unsuccessful: error/reject/abort apdu = iocb.ioError reason = find_reason(apdu) raise NoResponseFromController( "APDU Abort Reason : {}".format(reason)) self._log.info( "DeviceCommunicationControl request sent to device : {}".format( address))
def run(self): if _debug: ReadPointListThread._debug("run") global this_application # loop through the points for addr, obj_type, obj_inst, prop_id in self.point_queue: # build a request request = ReadPropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id, ) request.pduDestination = Address(addr) if _debug: ReadPointListThread._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadPointListThread._debug(" - iocb: %r", iocb) # give it to the application this_application.request_io(iocb) # wait for the response iocb.wait() if iocb.ioResponse: apdu = iocb.ioResponse # find the datatype datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier) if _debug: ReadPointListThread._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 (apdu.propertyArrayIndex is not None): if apdu.propertyArrayIndex == 0: value = apdu.propertyValue.cast_out(Unsigned) else: value = apdu.propertyValue.cast_out(datatype.subtype) else: value = apdu.propertyValue.cast_out(datatype) if _debug: ReadPointListThread._debug(" - value: %r", value) # save the value self.response_values.append(value) if iocb.ioError: if _debug: ReadPointListThread._debug(" - error: %r", iocb.ioError) self.response_values.append(iocb.ioError) # done stop()
def send_request( target_args, app ): # build a request request = ReadPropertyRequest( objectIdentifier=( target_args['type'], target_args['instance'] ), propertyIdentifier=target_args['property'] ) request.pduDestination = Address( target_args['address'] ) # make an IOCB iocb = IOCB( request ) # give it to the application app.request_io( iocb ) # wait for it to complete iocb.wait() # Handle completion: error, success, neither if iocb.ioError: # Error success = False message = str( iocb.ioError ) result = '' elif iocb.ioResponse: # Success success = True message = '' # Get the response PDU apdu = iocb.ioResponse # Extract the returned value datatype = get_datatype( apdu.objectIdentifier[0], apdu.propertyIdentifier ) if issubclass( datatype, Array ) and (apdu.propertyArrayIndex is not None): if apdu.propertyArrayIndex == 0: result = apdu.propertyValue.cast_out( Unsigned ) else: result = apdu.propertyValue.cast_out( datatype.subtype ) else: result = apdu.propertyValue.cast_out( datatype ) else: # Neither success = False message = 'Request terminated unexpectedly' result = '' rsp = { target_args['property']: result } return success, message, rsp
def whois(self, *args): """ Build a WhoIs request :param args: string built as [ <addr>] [ <lolimit> <hilimit> ] **optional** :returns: discoveredDevices as a defaultdict(int) Example:: whois() # WhoIs broadcast globally. Every device will respond with an IAm whois('2:5') # WhoIs looking for the device at (Network 2, Address 5) whois('10 1000') # WhoIs looking for devices in the ID range (10 - 1000) """ if not self._started: raise ApplicationNotStarted("BACnet stack not running - use startApp()") if args: args = args[0].split() msg = args if args else "any" self._log.debug("do_whois {!r}".format(msg)) # build a request request = WhoIsRequest() if (len(args) == 1) or (len(args) == 3): request.pduDestination = Address(args[0]) del args[0] else: request.pduDestination = GlobalBroadcast() if len(args) == 2: request.deviceInstanceRangeLowLimit = int(args[0]) request.deviceInstanceRangeHighLimit = int(args[1]) self._log.debug("{:>12} {}".format("- request:", request)) iocb = IOCB(request) # make an IOCB # pass to the BACnet stack self.this_application.request_io(iocb) iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response apdu = iocb.ioResponse if iocb.ioError: # unsuccessful: error/reject/abort pass self.discoveredDevices = self.this_application.i_am_counter return self.discoveredDevices
def got_new_device_who_is_response(self, apdu): # first check that this new device is one we actually care about (some times we get whois responses from other devices, even though the request was targeted to a specific ip rather than a global address) if not str(apdu.pduSource) in self.devices: print "got who is response from a device we don't care about" return # now we need to get the device name using the identifier we just got request = ReadPropertyRequest( destination=apdu.pduSource, objectIdentifier=apdu.iAmDeviceIdentifier, propertyIdentifier='objectName') iocb = IOCB(request) iocb.add_callback(self._got_device_object_name, apdu.iAmDeviceIdentifier) self.bacnet_adapter.request_io(iocb)
def read(self,pduSource,obj_id,key,device,read=None): #function.log('request',pduSource,obj_id,key,device) if isinstance(obj_id,str): obj_id=obj_id.split(':') obj_id[1]=int(obj_id[1]) request=ReadPropertyRequest( objectIdentifier=tuple(obj_id), propertyIdentifier=key, destination=RemoteStation(pduSource[0] or 0,bytearray(pduSource[1])) ) iocb = IOCB(request) iocb.context=device,key iocb.add_callback(read or self.readBack) self.request_io(iocb)
def write(self, args, vendor_id=0): """ Build a WriteProperty request, wait for an answer, and return status [True if ok, False if not]. :param args: String with <addr> <type> <inst> <prop> <value> [ <indx> ] [ <priority> ] :returns: data read from device (str representing data like 10 or True) *Example*:: import BAC0 myIPAddr = '192.168.1.10' bacnet = BAC0.ReadWriteScript(localIPAddr = myIPAddr) bacnet.write('2:5 analogValue 1 presentValue 100') Direct the controller at (Network 2, address 5) to write 100 to the presentValues of its analogValue 1 (AV:1) """ if not self._started: raise ApplicationNotStarted("BACnet stack not running - use startApp()") args = args.split() self.log_title("Write property", args) try: # build a WriteProperty request iocb = IOCB(self.build_wp_request(args, vendor_id=vendor_id)) # pass to the BACnet stack deferred(self.this_application.request_io, iocb) self._log.debug("{:<20} {!r}".format("iocb", iocb)) except WritePropertyException as error: # construction error self._log.exception("exception: {!r}".format(error)) iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response apdu = iocb.ioResponse if not isinstance(iocb.ioResponse, SimpleAckPDU): # expect an ACK self._log.warning("Not an ack, see debug for more infos.") self._log.debug( "Not an ack. | APDU : {} / {}".format((apdu, type(apdu))) ) return if iocb.ioError: # unsuccessful: error/reject/abort raise NoResponseFromController()
def do_write(self, args): """write <addr> <unitID> <register> <value> :param addr: IP address of the MODBUS/TCP device or gateway :param unitID: unit identifier :param register: register in 5-digit or 6-digit format :param value: value to write This command generates a :class:`WriteSingleCoil`, or :class:`WriteSingleRegisterRequest` depending on the address prefix; 0 or 4. """ args = args.split() if _debug: ConsoleClient._debug("do_write %r", args) if (len(args) < 3): print("address, unit and register required") return # get the address and unit addr, unitID, register, value = args # address might have a port if ':' in addr: addr, port = addr.split(':') server_address = (addr, int(port)) else: server_address = (addr, 502) # unit identifier unitID = int(unitID) if _debug: ConsoleClient._debug(" - addr, unitID: %r, %r", server_address, unitID) # get the register and count register = int(register) if _debug: ConsoleClient._debug(" - register: %r", register) # decode the register into a type digits = int(math.log10(register)) + 1 if digits <= 4: # must be a coil registerType = 0 elif digits == 5: registerType = register // 10000 register = register % 10000 elif digits == 6: registerType = register // 100000 register = register % 100000 else: print("5 or 6 digit addresses please") return if _debug: ConsoleClient._debug(" - registerType, register: %r, %r", registerType, register) # value value = int(value) if _debug: ConsoleClient._debug(" - value: %r", value) # build a request if registerType == 0: # coil req = WriteSingleCoilRequest(register - 1, value) elif registerType == 4: # holding register req = WriteSingleRegisterRequest(register - 1, value) else: print("unsupported register type") return # set the destination req.pduDestination = server_address req.mpduUnitID = unitID if _debug: ConsoleClient._debug(" - req: %r", req) # make an IOCB iocb = IOCB(req) if _debug: ConsoleClient._debug(" - iocb: %r", iocb) # submit the request via the main thread deferred(self.controller.request_io, iocb) # wait for the response iocb.wait() # exceptions if iocb.ioError: print("error: %r" % (iocb.ioError,)) return # extract the response resp = iocb.ioResponse if _debug: ConsoleClient._debug(" - resp: %r", resp) # write responses if isinstance(iocb.ioResponse, WriteSingleCoilResponse): print(" ::= " + str(iocb.ioResponse.value)) elif isinstance(iocb.ioResponse, WriteSingleRegisterResponse): print(" ::= " + str(iocb.ioResponse.value)) else: raise TypeError("unsupported response")
def do_read(self, args): """read <addr> <unitID> <register> [ <count> ] :param addr: IP address of the MODBUS/TCP device or gateway :param unitID: unit identifier :param register: register in 5-digit or 6-digit format :param count: number of registers to read, defaults to one This command generates a :class:`ReadCoilsRequest`, :class:`ReadDiscreteInputsRequest`, :class:`ReadInputRegistersRequest`, or :class:`ReadMultipleRegistersRequest` depending on the address prefix; 0, 1, 3, or 4. """ args = args.split() if _debug: ConsoleClient._debug("do_read %r", args) if (len(args) < 3): print("address, unit and register required") return # get the address and unit, and register addr, unitID, register = args[:3] # address might have a port if ':' in addr: addr, port = addr.split(':') server_address = (addr, int(port)) else: server_address = (addr, 502) # unit identifier unitID = int(unitID) if _debug: ConsoleClient._debug(" - addr, unitID: %r, %r", addr, unitID) # get the register and count register = int(register) if len(args) == 4: rcount = int(args[3]) else: rcount = 1 if _debug: ConsoleClient._debug(" - register, rcount: %r, %r", register, rcount) # decode the register into a type digits = int(math.log10(register)) + 1 if digits <= 4: # must be a coil registerType = 0 elif digits == 5: registerType = register // 10000 register = register % 10000 elif digits == 6: registerType = register // 100000 register = register % 100000 else: print("5 or 6 digit addresses please") return if _debug: ConsoleClient._debug(" - registerType, register: %r, %r", registerType, register) # build a request if registerType == 0: # coil req = ReadCoilsRequest(register - 1, rcount) elif registerType == 1: # discrete inputs req = ReadDiscreteInputsRequest(register - 1, rcount) elif registerType == 3: # input register req = ReadInputRegistersRequest(register - 1, rcount) elif registerType == 4: # holding register req = ReadMultipleRegistersRequest(register - 1, rcount) else: print("unsupported register type") return # set the destination req.pduDestination = server_address req.mpduUnitID = unitID if _debug: ConsoleClient._debug(" - req: %r", req) # make an IOCB iocb = IOCB(req) if _debug: ConsoleClient._debug(" - iocb: %r", iocb) # submit the request via the main thread deferred(self.controller.request_io, iocb) # wait for the response iocb.wait() # exceptions if iocb.ioError: print("error: %r" % (iocb.ioError,)) return # extract the response resp = iocb.ioResponse if _debug: ConsoleClient._debug(" - resp: %r", resp) # read responses if isinstance(resp, ExceptionResponse): print(" ::= " + str(resp)) elif isinstance(resp, ReadCoilsResponse): print(" ::= " + str(resp.bits)) elif isinstance(resp, ReadDiscreteInputsResponse): print(" ::= " + str(resp.bits)) elif isinstance(resp, ReadInputRegistersResponse): print(" ::= " + str(resp.registers)) for dtype, codec in ModbusStruct.items(): try: value = codec.unpack(resp.registers) print(" " + dtype + " ::= " + str(value)) except Exception as err: if _debug: ConsoleClient._debug("unpack exception %r: %r", codec, err) elif isinstance(resp, ReadMultipleRegistersResponse): print(" ::= " + str(resp.registers)) for dtype, codec in ModbusStruct.items(): try: value = codec.unpack(resp.registers) print(" " + dtype + " ::= " + str(value)) except Exception as err: if _debug: ConsoleClient._debug("unpack exception %r: %r", codec, err) else: raise TypeError("unsupported response")
def do_read(self, args): """read <addr> ( <type> <inst> ( <prop> [ <indx> ] )... )...""" args = args.split() if _debug: ReadPropertyMultipleConsoleCmd._debug("do_read %r", args) try: i = 0 addr = args[i] i += 1 read_access_spec_list = [] while i < len(args): obj_type = args[i] i += 1 if obj_type.isdigit(): obj_type = int(obj_type) elif not get_object_class(obj_type): raise ValueError("unknown object type") obj_inst = int(args[i]) i += 1 prop_reference_list = [] while i < len(args): prop_id = args[i] if prop_id not in PropertyIdentifier.enumerations: break i += 1 if prop_id in ('all', 'required', 'optional'): pass else: datatype = get_datatype(obj_type, prop_id) if not datatype: raise ValueError("invalid property for object type") # build a property reference prop_reference = PropertyReference( propertyIdentifier=prop_id, ) # check for an array index if (i < len(args)) and args[i].isdigit(): prop_reference.propertyArrayIndex = int(args[i]) i += 1 # add it to the list prop_reference_list.append(prop_reference) # check for at least one property if not prop_reference_list: raise ValueError("provide at least one property") # build a read access specification read_access_spec = ReadAccessSpecification( objectIdentifier=(obj_type, obj_inst), listOfPropertyReferences=prop_reference_list, ) # add it to the list read_access_spec_list.append(read_access_spec) # check for at least one if not read_access_spec_list: raise RuntimeError("at least one read access specification required") # build the request request = ReadPropertyMultipleRequest( listOfReadAccessSpecs=read_access_spec_list, ) request.pduDestination = Address(addr) if _debug: ReadPropertyMultipleConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadPropertyMultipleConsoleCmd._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 # 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)
def do_read(self, args): """read <addr> <type> <inst> <prop> [ <indx> ]""" args = args.split() if _debug: ReadPropertyConsoleCmd._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) datatype = get_datatype(obj_type, prop_id) if not datatype: raise ValueError("invalid property for object type") # 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: ReadPropertyConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadPropertyConsoleCmd._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 # should be an ack if not isinstance(apdu, ReadPropertyACK): if _debug: ReadPropertyConsoleCmd._debug(" - not an ack") return # find the datatype datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier) if _debug: ReadPropertyConsoleCmd._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 (apdu.propertyArrayIndex is not None): if apdu.propertyArrayIndex == 0: value = apdu.propertyValue.cast_out(Unsigned) else: value = apdu.propertyValue.cast_out(datatype.subtype) else: value = apdu.propertyValue.cast_out(datatype) if _debug: ReadPropertyConsoleCmd._debug(" - value: %r", value) sys.stdout.write(str(value) + '\n') if hasattr(value, 'debug_contents'): value.debug_contents(file=sys.stdout) sys.stdout.flush() # do something for error/reject/abort if iocb.ioError: sys.stdout.write(str(iocb.ioError) + '\n') except Exception, error: ReadPropertyConsoleCmd._exception("exception: %r", error)
def read(self, args, arr_index=None, vendor_id=0, bacoid=None): """ Build a ReadProperty request, wait for the answer and return the value :param args: String with <addr> <type> <inst> <prop> [ <indx> ] :returns: data read from device (str representing data like 10 or True) *Example*:: import BAC0 myIPAddr = '192.168.1.10/24' bacnet = BAC0.connect(ip = myIPAddr) bacnet.read('2:5 analogInput 1 presentValue') Requests the controller at (Network 2, address 5) for the presentValue of its analog input 1 (AI:1). """ if not self._started: raise ApplicationNotStarted("BACnet stack not running - use startApp()") args_split = args.split() self.log_title("Read property", args_split) vendor_id = vendor_id bacoid = bacoid try: # build ReadProperty request iocb = IOCB( self.build_rp_request( args_split, arr_index=arr_index, vendor_id=vendor_id, bacoid=bacoid ) ) # pass to the BACnet stack deferred(self.this_application.request_io, iocb) self._log.debug("{:<20} {!r}".format("iocb", iocb)) except ReadPropertyException as error: # construction error self._log.exception("exception: {!r}".format(error)) iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response apdu = iocb.ioResponse if not isinstance(apdu, ReadPropertyACK): # expecting an ACK self._log.warning("Not an ack, see debug for more infos.") self._log.debug( "Not an ack. | APDU : {} / {}".format((apdu, type(apdu))) ) return # find the datatype datatype = get_datatype( apdu.objectIdentifier[0], apdu.propertyIdentifier, vendor_id=vendor_id ) if not datatype: raise TypeError("unknown datatype") # special case for array parts, others are managed by cast_out if issubclass(datatype, Array) and (apdu.propertyArrayIndex is not None): if apdu.propertyArrayIndex == 0: value = apdu.propertyValue.cast_out(Unsigned) else: value = apdu.propertyValue.cast_out(datatype.subtype) else: value = apdu.propertyValue.cast_out(datatype) self._log.debug("{:<20} {:<20}".format("value", "datatype")) self._log.debug("{!r:<20} {!r:<20}".format(value, datatype)) return value if iocb.ioError: # unsuccessful: error/reject/abort apdu = iocb.ioError reason = find_reason(apdu) if reason == "segmentationNotSupported": self._log.warning( "Segmentation not supported... will read properties one by one..." ) self._log.debug("The Request was : {}".format(args_split)) value = self._split_the_read_request(args, arr_index) return value else: if reason == "unknownProperty": # if "priorityArray" in args: # self._log.debug("Unknown property {}".format(args)) # else: # self._log.warning("Unknown property {}".format(args)) if "description" in args: return "Not Implemented" elif "inactiveText" in args: return "Off" elif "activeText" in args: return "On" else: raise UnknownPropertyError("Unknown property {}".format(args)) elif reason == "unknownObject": self._log.warning("Unknown object {}".format(args)) raise UnknownObjectError("Unknown object {}".format(args)) else: # Other error... consider NoResponseFromController (65) # even if the realy reason is another one raise NoResponseFromController( "APDU Abort Reason : {}".format(reason) )
def do_write(self, args): """write <addr> <type> <inst> <prop> [ <indx> ]""" args = args.split() if _debug: WriteSomethingConsoleCmd._debug("do_write %r", args) try: addr, obj_type, obj_inst, prop_id = args[:4] obj_type = int(obj_type) obj_inst = int(obj_inst) prop_id = int(prop_id) # build a request request = WritePropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id, ) request.pduDestination = Address(addr) if len(args) == 5: request.propertyArrayIndex = int(args[4]) # build a custom datastructure tag_list = TagList([ OpeningTag(1), ContextTag(0, xtob('9c40')), ContextTag(1, xtob('02')), ContextTag(2, xtob('02')), ClosingTag(1) ]) if _debug: WriteSomethingConsoleCmd._debug(" - tag_list: %r", tag_list) # stuff the tag list into an Any request.propertyValue = Any() request.propertyValue.decode(tag_list) if _debug: WriteSomethingConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: WriteSomethingConsoleCmd._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: # should be an ack if not isinstance(iocb.ioResponse, SimpleAckPDU): if _debug: WriteSomethingConsoleCmd._debug(" - not an ack") return sys.stdout.write("ack\n") # do something for error/reject/abort if iocb.ioError: sys.stdout.write(str(iocb.ioError) + '\n') except Exception as error: WriteSomethingConsoleCmd._exception("exception: %r", error)
def do_subscribe(self, args): """subscribe addr proc_id obj_type obj_inst [ confirmed ] [ lifetime ] Generate a SubscribeCOVRequest and wait for the response. """ args = args.split() if _debug: SubscribeCOVConsoleCmd._debug("do_subscribe %r", args) try: addr, proc_id, obj_type, obj_inst = args[:4] proc_id = int(proc_id) 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) if len(args) >= 5: issue_confirmed = args[4] if issue_confirmed == '-': issue_confirmed = None else: issue_confirmed = issue_confirmed.lower() == 'true' if _debug: SubscribeCOVConsoleCmd._debug(" - issue_confirmed: %r", issue_confirmed) else: issue_confirmed = None if len(args) >= 6: lifetime = args[5] if lifetime == '-': lifetime = None else: lifetime = int(lifetime) if _debug: SubscribeCOVConsoleCmd._debug(" - lifetime: %r", lifetime) else: lifetime = None # build a request request = SubscribeCOVRequest( subscriberProcessIdentifier=proc_id, monitoredObjectIdentifier=(obj_type, obj_inst), ) request.pduDestination = Address(addr) # optional parameters if issue_confirmed is not None: request.issueConfirmedNotifications = issue_confirmed if lifetime is not None: request.lifetime = lifetime if _debug: SubscribeCOVConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: SubscribeCOVConsoleCmd._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: if _debug: SubscribeCOVConsoleCmd._debug(" - response: %r", iocb.ioResponse) # do something for error/reject/abort if iocb.ioError: if _debug: SubscribeCOVConsoleCmd._debug(" - error: %r", iocb.ioError) except Exception as e: SubscribeCOVConsoleCmd._exception("exception: %r", e)
def do_readrecord(self, args): """readrecord <addr> <inst> <start> <count>""" args = args.split() if _debug: TestConsoleCmd._debug("do_readrecord %r", args) try: addr, obj_inst, start_record, record_count = args obj_type = 'file' obj_inst = int(obj_inst) start_record = int(start_record) record_count = int(record_count) # build a request request = AtomicReadFileRequest( fileIdentifier=(obj_type, obj_inst), accessMethod=AtomicReadFileRequestAccessMethodChoice( recordAccess=AtomicReadFileRequestAccessMethodChoiceRecordAccess( fileStartRecord=start_record, requestedRecordCount=record_count, ), ), ) request.pduDestination = Address(addr) if _debug: TestConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: TestConsoleCmd._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 # should be an ack if not isinstance(apdu, AtomicReadFileACK): if _debug: TestConsoleCmd._debug(" - not an ack") return # suck out the record data if apdu.accessMethod.recordAccess: value = apdu.accessMethod.recordAccess.fileRecordData elif apdu.accessMethod.streamAccess: value = apdu.accessMethod.streamAccess.fileData if _debug: TestConsoleCmd._debug(" - value: %r", value) sys.stdout.write(repr(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: TestConsoleCmd._exception("exception: %r", error)
def do_write(self, args): """write <addr> <type> <inst> <prop> <value> [ <indx> ] [ <priority> ]""" args = args.split() ReadWritePropertyConsoleCmd._debug("do_write %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, VendorAVObject.vendor_id): raise ValueError("unknown object type") if _debug: ReadWritePropertyConsoleCmd._debug(" - obj_type: %r", obj_type) obj_inst = int(obj_inst) if _debug: ReadWritePropertyConsoleCmd._debug(" - obj_inst: %r", obj_inst) if prop_id.isdigit(): prop_id = int(prop_id) if _debug: ReadWritePropertyConsoleCmd._debug(" - prop_id: %r", prop_id) value = args[4] indx = None if len(args) >= 6: if args[5] != "-": indx = int(args[5]) if _debug: ReadWritePropertyConsoleCmd._debug(" - indx: %r", indx) priority = None if len(args) >= 7: priority = int(args[6]) if _debug: ReadWritePropertyConsoleCmd._debug(" - priority: %r", priority) # get the datatype datatype = get_datatype(obj_type, prop_id, VendorAVObject.vendor_id) if _debug: ReadWritePropertyConsoleCmd._debug(" - datatype: %r", datatype) # change atomic values into something encodeable, null is a special case if (value == 'null'): value = Null() elif issubclass(datatype, Atomic): if datatype is Integer: value = int(value) elif datatype is Real: value = float(value) elif datatype is Unsigned: value = int(value) value = datatype(value) elif issubclass(datatype, Array) and (indx is not None): if indx == 0: value = Integer(value) elif issubclass(datatype.subtype, Atomic): value = datatype.subtype(value) elif not isinstance(value, datatype.subtype): raise TypeError("invalid result datatype, expecting %s" % (datatype.subtype.__name__,)) elif not isinstance(value, datatype): raise TypeError("invalid result datatype, expecting %s" % (datatype.__name__,)) if _debug: ReadWritePropertyConsoleCmd._debug(" - encodeable value: %r %s", value, type(value)) # build a request request = WritePropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id ) request.pduDestination = Address(addr) # save the value request.propertyValue = Any() try: request.propertyValue.cast_in(value) except Exception as error: ReadWritePropertyConsoleCmd._exception("WriteProperty cast error: %r", error) # optional array index if indx is not None: request.propertyArrayIndex = indx # optional priority if priority is not None: request.priority = priority if _debug: ReadWritePropertyConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadWritePropertyConsoleCmd._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: sys.stdout.write("ack\n") # do something for error/reject/abort if iocb.ioError: sys.stdout.write(str(iocb.ioError) + '\n') except Exception as error: ReadWritePropertyConsoleCmd._exception("exception: %r", error)
def do_writestream(self, args): """writestream <addr> <inst> <start> <data>""" args = args.split() if _debug: TestConsoleCmd._debug("do_writestream %r", args) try: addr, obj_inst, start_position, data = args obj_type = 'file' obj_inst = int(obj_inst) start_position = int(start_position) data = data.encode('utf-8') # build a request request = AtomicWriteFileRequest( fileIdentifier=(obj_type, obj_inst), accessMethod=AtomicWriteFileRequestAccessMethodChoice( streamAccess=AtomicWriteFileRequestAccessMethodChoiceStreamAccess( fileStartPosition=start_position, fileData=data, ), ), ) request.pduDestination = Address(addr) if _debug: TestConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: TestConsoleCmd._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 # should be an ack if not isinstance(apdu, AtomicWriteFileACK): if _debug: TestConsoleCmd._debug(" - not an ack") return # suck out the record data if apdu.fileStartPosition is not None: value = apdu.fileStartPosition elif apdu.fileStartRecord is not None: value = apdu.fileStartRecord TestConsoleCmd._debug(" - value: %r", value) sys.stdout.write(repr(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: TestConsoleCmd._exception("exception: %r", error)
The IOController processes the IOCBs it is given and returns the IOCB back to the caller. """ import bacpypes from bacpypes.iocb import IOCB, IOController class SomeController(IOController): def process_io(self, iocb): self.complete_io(iocb, iocb.args[0] + iocb.args[1] * iocb.kwargs['a']) def call_me(iocb): """ When a controller completes the processing of a request, the IOCB can contain one or more functions to be called. """ print("call me, %r or %r" % (iocb.ioResponse, iocb.ioError)) if __name__ == '__main__': iocb = IOCB(1, 2, a=3) iocb.add_callback(call_me) some_controller = SomeController() some_controller.request_io(iocb) iocb.ioComplete.wait() print(iocb.ioComplete) print(iocb.ioComplete.is_set()) print(iocb.ioState == bacpypes.iocb.COMPLETED) print(iocb.ioState == bacpypes.iocb.ABORTED) print(iocb.ioResponse)
def do_read(self, args): """read <addr> <type> <inst> <prop> [ <indx> ]""" args = args.split() if _debug: ReadWritePropertyConsoleCmd._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, VendorAVObject.vendor_id): raise ValueError("unknown object type") if _debug: ReadWritePropertyConsoleCmd._debug(" - obj_type: %r", obj_type) obj_inst = int(obj_inst) if _debug: ReadWritePropertyConsoleCmd._debug(" - obj_inst: %r", obj_inst) if prop_id.isdigit(): prop_id = int(prop_id) if _debug: ReadWritePropertyConsoleCmd._debug(" - prop_id: %r", prop_id) datatype = get_datatype(obj_type, prop_id, VendorAVObject.vendor_id) if not datatype: raise ValueError("invalid property for object type") # 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: ReadWritePropertyConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReadWritePropertyConsoleCmd._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: ReadWritePropertyConsoleCmd._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: ReadWritePropertyConsoleCmd._debug(" - datatype: %r", datatype) if not datatype: raise TypeError("unknown datatype") # cast out the value value = apdu.propertyValue.cast_out(datatype) if _debug: ReadWritePropertyConsoleCmd._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: ReadWritePropertyConsoleCmd._exception("exception: %r", error)
def readMultiple(self, args): """ Build a ReadPropertyMultiple request, wait for the answer and return the values :param args: String with <addr> ( <type> <inst> ( <prop> [ <indx> ] )... )... :returns: data read from device (str representing data like 10 or True) *Example*:: import BAC0 myIPAddr = '192.168.1.10/24' bacnet = BAC0.connect(ip = myIPAddr) bacnet.readMultiple('2:5 analogInput 1 presentValue units') Requests the controller at (Network 2, address 5) for the (presentValue and units) of its analog input 1 (AI:1). """ if not self._started: raise ApplicationNotStarted("BACnet stack not running - use startApp()") args = args.split() values = [] self.log_title("Read Multiple", args) try: # build an ReadPropertyMultiple request iocb = IOCB(self.build_rpm_request(args)) # pass to the BACnet stack deferred(self.this_application.request_io, iocb) self._log.debug("{:<20} {!r}".format("iocb", iocb)) except ReadPropertyMultipleException as error: # construction error self._log.exception("exception: {!r}".format(error)) iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response apdu = iocb.ioResponse if not isinstance(apdu, ReadPropertyMultipleACK): # expecting an ACK self._log.debug("{:<20}".format("not an ack")) self._log.warning( "Not an Ack. | APDU : {} / {}".format((apdu, type(apdu))) ) return # loop through the results for result in apdu.listOfReadAccessResults: # here is the object identifier objectIdentifier = result.objectIdentifier self.log_subtitle( "{!r} : {!r}".format(objectIdentifier[0], objectIdentifier[1]), width=114, ) self._log.debug( "{:<20} {:<20} {:<30} {:<20}".format( "propertyIdentifier", "propertyArrayIndex", "value", "datatype" ) ) self._log.debug("-" * 114) # now come the property values per object for element in result.listOfResults: # get the property and array index propertyIdentifier = element.propertyIdentifier propertyArrayIndex = element.propertyArrayIndex readResult = element.readResult if readResult.propertyAccessError is not None: self._log.debug( "Property Access Error for {}".format( readResult.propertyAccessError ) ) values.append(None) else: # here is the value propertyValue = readResult.propertyValue # find the datatype datatype = get_datatype(objectIdentifier[0], propertyIdentifier) 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) self._log.debug( "{!r:<20} {!r:<20} {!r:<30} {!r:<20}".format( propertyIdentifier, propertyArrayIndex, value, datatype ) ) values.append(value) return values if iocb.ioError: # unsuccessful: error/reject/abort apdu = iocb.ioError reason = find_reason(apdu) self._log.warning("APDU Abort Reject Reason : {}".format(reason)) self._log.debug("The Request was : {}".format(args)) if reason == "unrecognizedService": raise UnrecognizedService() elif reason == "segmentationNotSupported": raise SegmentationNotSupported() elif reason == "unknownObject": self._log.warning("Unknown object {}".format(args)) raise UnknownObjectError("Unknown object {}".format(args)) elif reason == "unknownProperty": self._log.warning("325 Unknown property {}".format(args)) values.append("") return values else: self._log.warning("No response from controller") values.append("") return values