1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-10-05 22:18:16 +08:00
bacpypes/doc/source/samples/sample003.rst
2016-09-19 17:16:49 -07:00

97 lines
3.5 KiB
ReStructuredText

Sample 3 - Who-Has/I-Have Counter
=================================
This sample application is very similar to the second sample. It has the
same basic structure and initialization, it counts the number of Who-Has and
I-Have messages it receives, and prints out a summary after the application
has been signalled to terminate (<ctrl-C> - KeyboardInterrupt).
Processing Service Requests
---------------------------
The beginning is going to be standard boiler plate function header::
def do_WhoHasRequest(self, apdu):
"""Respond to a Who-Has request."""
if _debug: SampleApplication._debug("do_WhoHasRequest %r", apdu)
Unlike the Who-Is request, Who-Has can come in two different flavors, one
checking for an object by its identifier and one checking by its name. Both
cannot appear in the APDU at the same time::
key = (str(apdu.pduSource),)
if apdu.object.objectIdentifier is not None:
key += (str(apdu.object.objectIdentifier),)
elif apdu.object.objectName is not None:
key += (apdu.object.objectName,)
else:
print "(rejected APDU:"
apdu.debug_contents()
print ")"
return
# count the times this has been received
who_has_counter[key] += 1
When an optional parameter is not specified in a PDU then the corresponding
attribute is ``None``. With this particular APDU the *object*
parameter is required, and one of its child attributes *objectIdentifier*
or *objectName* will be not ``None``. If both are ``None`` then the
request is not properly formed.
.. note::
The encoding and decoding layer does not understand all
the combinations of required and optional parameters in an APDU, so
verify the validity of the request is the responsibility of the application.
The application can rely on the fact that the APDU is well-formed - meaning
it has the appropriate opening and closing tags and the data
types of the parameters are correct. Watch out for parameters of type Any!
The I-Am function is much simpler because all of the parameters are required::
key = (
str(apdu.pduSource),
str(apdu.deviceIdentifier),
str(apdu.objectIdentifier),
apdu.objectName
)
# count the times this has been received
i_have_counter[key] += 1
Dumping the contents of the counters is simple.
Just like Who-Is and I-Am, pairing up the requests and responses can be a
useful exercize, but in most cases the I-Am response from a device will be a
unicast message directly back to the requestor, so relying on broadcast traffic
to analyze object binding is not as useful as it used to be.
Running the Application
-----------------------
::
$ python WhoHasIHaveApplication.py --debug __main__
DEBUG:__main__:initialization
DEBUG:__main__: - args: Namespace(buggers=False, color=False, debug=['__main__'], ini=<class 'bacpypes.consolelogging.ini'>)
DEBUG:__main__.WhoHasIHaveApplication:__init__ <bacpypes.app.LocalDeviceObject object at 0x7f887e83ca90> '192.168.87.59/24'
DEBUG:__main__: - services_supported: <bacpypes.basetypes.ServicesSupported object at 0x7f887c5f0f50>
DEBUG:__main__:running
Allow the application to run for a few minutes. Then end it so it will output its results.::
^CDEBUG:__main__:fini
----- Who Has -----
----- I Have -----
.. note::
The Who-Has and I-Have services are not widely used.