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 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 what_is_network_number(self, args=""): """ winn [ <addr> ] Send a What-Is-Network-Number message. If the address is unspecified the message is locally broadcast. """ args = args.split() # build a request try: request = WhatIsNetworkNumber() if len(args) > 0: request.pduDestination = Address(args[0]) else: request.pduDestination = LocalBroadcast() except: self._log.error( "Cannot build request (invalid arguments) : {}".format(args)) return iocb = IOCB((self.this_application.nsap.local_adapter, request)) # make an IOCB iocb.set_timeout(2) deferred(self.this_application.nse.request_io, iocb) iocb.wait()
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 whois_router_to_network(self, args=None): # build a request try: request = WhoIsRouterToNetwork() if not args: request.pduDestination = LocalBroadcast() elif args[0].isdigit(): request.pduDestination = LocalBroadcast() request.wirtnNetwork = int(args[0]) else: request.pduDestination = Address(args[0]) if len(args) > 1: request.wirtnNetwork = int(args[1]) except: self._log.error("WhoIsRouterToNetwork : invalid arguments") return iocb = IOCB((self.this_application.nsap.local_adapter, request)) # make an IOCB iocb.set_timeout(2) deferred(self.this_application.nse.request_io, iocb) iocb.wait() try: self.init_routing_table(str( self.this_application.nse._iartn.pop())) except IndexError: pass
def whois_router_to_network(self, network=None, *, destination=None): # build a request try: request = WhoIsRouterToNetwork() if network: request.wirtnNetwork = int(network) if destination: request.pduDestination = Address(destination) self._log.debug("WhoIsRouterToNetwork Destination : {}".format( destination)) else: request.pduDestination = LocalBroadcast() except: self._log.error("WhoIsRouterToNetwork : invalid arguments") return iocb = IOCB((self.this_application.nsap.local_adapter, request)) # make an IOCB iocb.set_timeout(2) deferred(self.this_application.nse.request_io, iocb) iocb.wait() try: self.init_routing_table(str( self.this_application.nse._iartn.pop())) except IndexError: pass
def write_text_value(self, request, timeout=10): try: iocb = IOCB(request) iocb.set_timeout(timeout) # 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 not isinstance(apdu, SimpleAckPDU): # expect an ACK self._log.error("Not an ack, see debug for more infos.") return if iocb.ioError: # unsuccessful: error/reject/abort apdu = iocb.ioError reason = find_reason(apdu) raise NoResponseFromController( "APDU Abort Reason : {}".format(reason)) except WritePropertyException as error: # construction error self._log.error(("exception: {!r}".format(error)))
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 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 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 whohas( self, object_id=None, object_name=None, instance_range_low_limit=0, instance_range_high_limit=4194303, destination=None, global_broadcast=False, ): """ Object ID : analogInput:1 Object Name : string Instance Range Low Limit : 0 Instance Range High Limit : 4194303 destination (optional) : If empty, local broadcast will be used. global_broadcast : False """ obj_id = ObjectIdentifier(object_id) if object_name and not object_id: obj_name = CharacterString(object_name) obj = WhoHasObject(objectName=obj_name) elif object_id and not object_name: obj = WhoHasObject(objectIdentifier=obj_id) else: obj = WhoHasObject(objectIdentifier=obj_id, objectName=obj_name) limits = WhoHasLimits( deviceInstanceRangeLowLimit=instance_range_low_limit, deviceInstanceRangeHighLimit=instance_range_high_limit, ) request = WhoHasRequest(object=obj, limits=limits) if destination: request.pduDestination = Address(destination) else: if global_broadcast: request.pduDestination = GlobalBroadcast() else: request.pduDestination = LocalBroadcast() iocb = IOCB(request) # make an IOCB iocb.set_timeout(2) deferred(self.this_application.request_io, iocb) iocb.wait() iocb = IOCB(request) # make an IOCB self.this_application._last_i_have_received = [] if iocb.ioResponse: # successful response apdu = iocb.ioResponse if iocb.ioError: # unsuccessful: error/reject/abort pass time.sleep(3) # self.discoveredObjects = self.this_application.i_am_counter return self.this_application._last_i_have_received
def writeMultiple(self, addr=None, args=None, vendor_id=0, timeout=10): """ Build a WritePropertyMultiple request, wait for an answer, and return status [True if ok, False if not]. :param addr: destination of request (ex. '2:3' or '192.168.1.2') :param args: list of String with <type> <inst> <prop> <value> [ <indx> ] - [ <priority> ] :param vendor_id: Mandatory for registered proprietary object and properties :param timeout: used by IOCB to discard request if timeout reached :returns: return status [True if ok, False if not] *Example*:: import BAC0 bacnet = BAC0.lite() r = ['analogValue 1 presentValue 100','analogValue 2 presentValue 100','analogValue 3 presentValue 100 - 8','@obj_142 1 @prop_1042 True'] bacnet.writeMultiple(addr='2:5',args=r,vendor_id=842) # or # bacnet.writeMultiple('2:5',r) """ if not self._started: raise ApplicationNotStarted( "BACnet stack not running - use startApp()") self.log_title("Write property multiple", args) try: # build a WritePropertyMultiple request iocb = IOCB( self.build_wpm_request(args, vendor_id=vendor_id, addr=addr)) iocb.set_timeout(timeout) # 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 apdu = iocb.ioError reason = find_reason(apdu) raise NoResponseFromController( "APDU Abort Reason : {}".format(reason))
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 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 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 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 write(self, args, vendor_id=0, timeout=10): """ 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: return status [True if ok, False if not] *Example*:: import BAC0 bacnet = BAC0.lite() bacnet.write('2:5 analogValue 1 presentValue 100 - 8') Direct the controller at (Network 2, address 5) to write 100 to the presentValues of its analogValue 1 (AV:1) at priority 8 """ 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)) iocb.set_timeout(timeout) # 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 apdu = iocb.ioError reason = find_reason(apdu) raise NoResponseFromController( "APDU Abort Reason : {}".format(reason))
def write_recipient_list(addr, obj_inst, recipent_list): if _debug: EventNotificationConsoleCmd._debug("write_recipient_list %r %r %r", addr, obj_inst, recipent_list) # the new list has just us recipient_list = ListOfDestination(recipent_list) if _debug: EventNotificationConsoleCmd._debug(" - recipient_list: %r", recipient_list) # build a request request = WritePropertyRequest( objectIdentifier=('notificationClass', obj_inst), propertyIdentifier='recipientList', propertyValue=Any(), ) request.pduDestination = Address(addr) # save the value request.propertyValue.cast_in(recipient_list) if _debug: EventNotificationConsoleCmd._debug(" - request: %r", request) # 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 success if iocb.ioResponse: # should be an ack if not isinstance(iocb.ioResponse, SimpleAckPDU): if _debug: EventNotificationConsoleCmd._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')
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 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 discover_devices(self, timeout=5): """ Send a WhoIsRequest and wait for timeout seconds to receive all responses. """ self.devices = {} req = WhoIsRequest( ) # How does this know it needs to store at devices? req.pduDestination = Address( "255.255.255.255") # Global Broadcast address iocb = IOCB(req) self.request_io(iocb) iocb.set_timeout(5) iocb.wait() time.sleep( timeout) # wait for 5 seconds so all the responses are received. self.update_device_metadata(self.devices) return self.devices
def write(self, args): """ 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()') #with self.this_application._lock: # time.sleep(0.5) #self.this_application._lock = True args = args.split() log_debug(WriteProperty, "do_write %r", args) try: iocb = IOCB( self.build_wp_request(args)) # build a WriteProperty request self.this_application.request_io(iocb) # pass to the BACnet stack except WritePropertyException as error: log_exception("exception: %r", error) # construction error iocb.wait() # Wait for BACnet response if iocb.ioResponse: # successful response if not isinstance(iocb.ioResponse, SimpleAckPDU): # expect an ACK log_debug(WriteProperty, " - not an ack") return if iocb.ioError: # unsuccessful: error/reject/abort raise NoResponseFromController()
def do_reinit(self, args): """reinit <addr> <state> Example state is coldstart...""" args = args.split() if _debug: ReinitDeviceConsoleCmd._debug("do_reinit %r", args) try: addr, state = args[:2] # build a request request = ReinitializeDeviceRequest( reinitializedStateOfDevice=state) request.pduDestination = Address(addr) if _debug: ReinitDeviceConsoleCmd._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: ReinitDeviceConsoleCmd._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: ReinitDeviceConsoleCmd._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: ReinitDeviceConsoleCmd._exception("exception: %r", error)
def what_is_network_number(self, destination=None): """ winn [ <addr> ] Send a What-Is-Network-Number message. If the address is unspecified the message is locally broadcast. """ # build a request request = WhatIsNetworkNumber() if destination: request.pduDestination = Address(destination) else: request.pduDestination = LocalBroadcast() iocb = IOCB((self.this_application.nsap.local_adapter, request)) # make an IOCB iocb.set_timeout(2) deferred(self.this_application.nse.request_io, iocb) iocb.wait()
def init_routing_table(self, address): """ irt <addr> Send an empty Initialize-Routing-Table message to an address, a router will return an acknowledgement with its routing table configuration. """ # build a request self._log.info("Addr : {}".format(address)) try: request = InitializeRoutingTable() request.pduDestination = Address(address) except: self._log.error("invalid arguments") return iocb = IOCB((self.this_application.nsap.local_adapter, request)) # make an IOCB iocb.set_timeout(2) deferred(self.this_application.nse.request_io, iocb) iocb.wait()
def send_weeklyschedule_request(self, request): iocb = IOCB(request) iocb.set_timeout(10) deferred(self.this_application.request_io, iocb) iocb.wait() 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("Schedule Write request sent to device : {}".format( request.pduDestination))
def do_write(self, args): """ write <indx> <value> write 0 <len> write [ <value> ]... """ args = args.split() ReadWritePropertyConsoleCmd._debug("do_write %r", args) try: addr, obj_type, obj_inst = context prop_id = 'eventMessageTexts' indx = None if args and args[0].isdigit(): indx = int(args[0]) if indx == 0: value = Unsigned(int(args[1])) else: value = CharacterString(args[1]) else: value = ArrayOf(CharacterString)(args[0:]) # 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 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: # should be an ack if not isinstance(iocb.ioResponse, SimpleAckPDU): if _debug: ReadWritePropertyConsoleCmd._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: ReadWritePropertyConsoleCmd._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_read(self, args): """read [ <indx> ]""" args = args.split() if _debug: ReadWritePropertyConsoleCmd._debug("do_read %r", args) global context try: addr, obj_type, obj_inst = context prop_id = 'eventMessageTexts' 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) == 1: request.propertyArrayIndex = int(args[0]) 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 # should be an ack if not isinstance(apdu, ReadPropertyACK): if _debug: ReadWritePropertyConsoleCmd._debug(" - not an ack") return # find the datatype datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier) if _debug: ReadWritePropertyConsoleCmd._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: ReadWritePropertyConsoleCmd._debug(" - value: %r", value) sys.stdout.write(str(value) + '\n') if hasattr(value, 'debug_contents'): value.debug_contents(stream=sys.stdout) 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 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 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
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 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 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.info( "{:<20} {:<20}".format( 'value', 'datatype')) self._log.info( "{!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': self._log.warning('Unknown property {}'.format(args)) if 'description' in args: return '' 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_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)
def do_write(self, args): """write <addr> <objid> <prop> [ <indx> ]""" args = args.split() if _debug: WriteSomethingConsoleCmd._debug("do_write %r", args) try: addr, obj_id, prop_id = args[:3] obj_id = ObjectIdentifier(obj_id).value if prop_id.isdigit(): prop_id = int(prop_id) # build a request request = WritePropertyRequest( objectIdentifier=obj_id, propertyIdentifier=prop_id, ) request.pduDestination = Address(addr) if len(args) == 4: request.propertyArrayIndex = int(args[3]) # 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 deferred(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_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 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.info( "{:<20} {:<20} {:<30} {:<20}".format( 'propertyIdentifier', 'propertyArrayIndex', 'value', 'datatype')) self._log.info( "-"*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.info( "{!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('Unknown property {}'.format(args)) values.append("") return values else: self._log.warning("No response from controller") values.append("") return values
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_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_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")