mirror of
https://github.com/JoelBender/bacpypes
synced 2025-09-28 22:15:23 +08:00
75 lines
2.8 KiB
ReStructuredText
75 lines
2.8 KiB
ReStructuredText
.. BACpypes tutorial lesson 1
|
|
|
|
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 signaled to terminate, such as a KeyboardInterrupt raised.
|
|
|
|
|
|
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
|
|
whoHasCounter[key] += 1
|
|
|
|
When an optional parameter is not specified in a PDU then the corrisponding
|
|
attribute will be ``None``. With this particular APDU the *object*
|
|
parameter is required, but only 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 will not completely understand all of
|
|
the combinations of required and optional parameters in an APDU, so
|
|
verify the validity of the reuest is the responsibility of the application.
|
|
|
|
The application can rely on the fact that the APDU is well-formed, which
|
|
is to say it has teh appropriate opening and closing tags and the data
|
|
types of the parameters are correct. Watch out for 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
|
|
iHaveCounter[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 excersize, 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.
|
|
|
|
The Who-Has and I-Have services are not widely used.
|