Beispiel #1
0
    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)
Beispiel #2
0
 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 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)
Beispiel #5
0
    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)
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
    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)
Beispiel #10
0
 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)
Beispiel #11
0
 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)
Beispiel #12
0
    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 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)
Beispiel #14
0
    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)
Beispiel #15
0
    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
Beispiel #16
0
    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)
Beispiel #17
0
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 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)
Beispiel #19
0
    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 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)
Beispiel #21
0
 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 requests(self):
     global tag_list, this_application, tag_keys, count
     for item in tag_list:
         tag_keys[item["device_address"] + "#" + item["object_types"] +
                  "#" + item["object_instance"] + "#" + item["prop"]] = {
                      "tag": item["tag"],
                      "prop": item["prop"]
                  }
         request = ReadPropertyRequest(
             destination=Address(item["device_address"]),
             objectIdentifier=(item["object_types"],
                               int(item["object_instance"])),
             propertyIdentifier=item["prop"])
         iocb = IOCB(request)
         iocb.add_callback(self.callback)
         this_application.request_io(iocb)
Beispiel #23
0
    def write_bac_set(self):

        addr = point_list[0][0]
        obj_type = self.obj
        obj_inst = self.inst
        prop_id = self.prop

        tags = self.response_bacset[0]
        proxy_ip = self.proxyIP
        print tags
        print proxy_ip

        try:

            # build a request
            request = WritePropertyRequest(
                objectIdentifier=(obj_type, obj_inst),
                propertyIdentifier=prop_id,
            )
            request.pduDestination = Address(addr)
            request.propertyArrayIndex = self.idx

            # build a custom datastructure... BACnet settings IP net or bcp
            tag_list = contextTagsToWrite.build_list(self.response_bacset,
                                                     proxy_ip)

            #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)

            # set a callback for the response
            iocb.add_callback(self.simple_ack)

            # give it to the application
            this_application.request_io(iocb)

        except Exception as error:
            #WriteSomethingConsoleCmd._exception("exception: %r", error)
            print error
 def indication(self, apdu: APDU):
     if isinstance(apdu, IAmRequest):
         log.debug("Received IAmRequest from device with ID: %i and address %s:%i",
                   apdu.iAmDeviceIdentifier[1],
                   apdu.pduSource.addrTuple[0],
                   apdu.pduSource.addrTuple[1]
                   )
         log.debug(apdu.pduSource)
         request = ReadPropertyRequest(
             destination=apdu.pduSource,
             objectIdentifier=apdu.iAmDeviceIdentifier,
             propertyIdentifier='objectName',
         )
         iocb = IOCB(request)
         deferred(self.request_io, iocb)
         iocb.add_callback(self.__iam_cb, vendor_id=apdu.vendorID)
         self.requests_in_progress.update({iocb: {"callback": self.__iam_cb}})
Beispiel #25
0
    def request_values(
        self,
        device_address_str: str,
        objects: Sequence[Tuple[Union[int, str], int]],
        chunk_size: Optional[int] = None,
        request_timeout: Optional[Timedelta] = None,
    ):
        device_address = Address(device_address_str)
        device_info: DeviceInfo = self.deviceInfoCache.get_device_info(
            device_address)

        # we adjusted chunking for object property request, which requested 3 properties per object
        # here we request only 1 property so scale
        chunk_scale = 3

        if not chunk_size:
            chunk_size = 20 * chunk_scale
            if device_info and device_info.segmentationSupported == "noSegmentation":
                chunk_size = 4 * chunk_scale

        logger.debug(
            f"Chunking for device {device_address_str} is {chunk_size}")

        for objects_chunk in chunks(objects, chunk_size):
            prop_reference_list = [
                PropertyReference(propertyIdentifier="presentValue")
            ]

            read_access_specs = [
                ReadAccessSpecification(
                    objectIdentifier=ObjectIdentifier(object_identifier),
                    listOfPropertyReferences=prop_reference_list,
                ) for object_identifier in objects_chunk
            ]

            request = ReadPropertyMultipleRequest(
                listOfReadAccessSpecs=read_access_specs)
            request.pduDestination = device_address

            iocb = IOCB(request)
            iocb.add_callback(self._iocb_callback)
            if request_timeout:
                iocb.set_timeout(request_timeout.s)

            deferred(self.request_io, iocb)
Beispiel #26
0
    def _get_prop_for_obj(self, obj_id):

        props_to_get = ['objectName', 'description', 'presentValue', 'units']

        prop_ref_list = []

        for prop in props_to_get:
            ref = PropertyReference(propertyIdentifier=prop)
            prop_ref_list.append(ref)

        read_access_spec = ReadAccessSpecification(
            objectIdentifier=obj_id,
            listOfPropertyReferences=prop_ref_list,
        )

        request = ReadPropertyMultipleRequest(
            listOfReadAccessSpecs=[read_access_spec],
            destination=self.device.source)

        iocb = IOCB(request)
        iocb.add_callback(self._got_properties_for_object, obj_id)
        self.bacnet_adapter.request_io(iocb)
Beispiel #27
0
    def next_request(self):
        if _debug: PrairieDog._debug("next_request")

        # check to see if we're done
        if not self.point_queue:
            if _debug: PrairieDog._debug("    - done")

            # dump out the results
            for request, response in zip(point_list, self.response_values):
                print(request, response)

            # no longer busy
            self.is_busy = False

            return

        # get the next request
        addr, obj_id, prop_id = self.point_queue.popleft()
        obj_id = ObjectIdentifier(obj_id).value

        # build a request
        request = ReadPropertyRequest(
            objectIdentifier=obj_id,
            propertyIdentifier=prop_id,
        )
        request.pduDestination = Address(addr)
        if _debug: PrairieDog._debug("    - request: %r", request)

        # make an IOCB
        iocb = IOCB(request)
        if _debug: PrairieDog._debug("    - iocb: %r", iocb)

        # set a callback for the response
        iocb.add_callback(self.complete_request)

        # give it to the application
        self.request_io(iocb)
Beispiel #28
0
    def next_request(self):
        if _debug: WhoIsIAmApplication._debug("next_request")

        # check to see if we're done
        if not self.point_queue:
            if _debug: WhoIsIAmApplication._debug("    - done")

            # dump out the results... ici caller fonction qui analyse quel type de panneau et ensuite faire read du IP Proxy..
            for request, response in zip(point_list, self.response_values):
                print(request, response)

            # Adjust depending on object type NET or BCP and also version dependent 3.33 or 3.40
            # Here is NET object DSC-xxxx 3.40
            self.net_obj_id(278, 1, 1101, 5)

            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: WhoIsIAmApplication._debug("    - request: %r", request)

        # make an IOCB
        iocb = IOCB(request)

        # set a callback for the response
        iocb.add_callback(self.complete_request)
        if _debug: WhoIsIAmApplication._debug("    - iocb: %r", iocb)

        # send the request
        this_application.request_io(iocb)
Beispiel #29
0
    def process_task(self):
        if _debug:
            PrairieDog._debug("process_task")
        global args, this_application

        if _debug:
            PrairieDog._debug("    - args.values: %r", args.values)

        # pick up the next value
        value = args.values.pop(0)
        args.values.append(value)

        # make a primitive value out of it
        value = Real(float(value))

        # build a request
        request = WritePropertyRequest(
            destination=args.daddr,
            objectIdentifier=args.objid,
            propertyIdentifier=args.propid,
        )

        # save the value, application tagged
        request.propertyValue = Any()
        request.propertyValue.cast_in(value)
        if _debug:
            PrairieDog._debug("    - request: %r", request)

        # make an IOCB
        iocb = IOCB(request)
        iocb.add_callback(self.write_complete)
        if _debug:
            PrairieDog._debug("    - iocb: %r", iocb)

        # give it to the application to process
        deferred(this_application.request_io, iocb)
Beispiel #30
0
    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
        point_info = self.point_queue.popleft()
        if _debug:
            ReadPointListApplication._debug("    - point_info: %r", point_info)

        # build a request
        request = ReadPropertyRequest(
            destination=Address(point_info["address"]),
            objectIdentifier=ObjectIdentifier(point_info["objectIdentifier"]).value,
            propertyIdentifier=point_info.get("propertyIdentifier", "presentValue"),
        )
        if _debug:
            ReadPointListApplication._debug("    - request: %r", request)

        # make an IOCB
        iocb = IOCB(request)
        iocb.point_info = point_info

        # 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 confirmation(self, pdu):
        if _debug: WritePropertyClient._debug('confirmation %r', pdu)
        global this_application

        # decode the bytes into a string and strip off the end-of-line
        args = pdu.pduData.decode('utf-8').strip().split()
        if _debug: WritePropertyClient._debug("    - args: %r", args)

        try:
            addr, obj_type, obj_inst, prop_id = args[:4]
            if obj_type.isdigit():
                obj_type = int(obj_type)
            obj_inst = int(obj_inst)
            value = args[4]

            indx = None
            if len(args) >= 6:
                if args[5] != "-":
                    indx = int(args[5])
            if _debug: WritePropertyClient._debug("    - indx: %r", indx)

            priority = None
            if len(args) >= 7:
                priority = int(args[6])
            if _debug: WritePropertyClient._debug("    - priority: %r", priority)

            # get the datatype
            datatype = get_datatype(obj_type, prop_id)
            if _debug: WritePropertyClient._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: WritePropertyClient._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:
                WritePropertyClient._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: WritePropertyClient._debug("    - request: %r", request)

            # make an IOCB
            iocb = IOCB(request)
            if _debug: WritePropertyClient._debug("    - iocb: %r", iocb)

            # reference the original request so the response goes back to the
            # correct client
            iocb.request_pdu = pdu

            # add ourselves to be called back for the response
            iocb.add_callback(self.complete)

            # give it to the application
            this_application.request_io(iocb)
        except Exception as error:
            WritePropertyClient._exception("exception: %r", error)

            # send it back to the client
            error_str = "exception: " + str(error) + '\r\n'
            self.request(PDU(error_str.encode('utf-8'), destination=pdu.pduSource))
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)