diff --git a/py34/bacpypes/service/cov.py b/py34/bacpypes/service/cov.py index 02887131..cbf87fdb 100644 --- a/py34/bacpypes/service/cov.py +++ b/py34/bacpypes/service/cov.py @@ -90,7 +90,7 @@ class Subscription(OneShotTask, DebugContents): 'lifetime', ) - def __init__(self, obj_ref, client_addr, proc_id, obj_id, confirmed, lifetime): + def __init__(self, obj_ref, client_addr, proc_id, obj_id, confirmed, lifetime, cov_inc): if _debug: Subscription._debug("__init__ %r %r %r %r %r %r", obj_ref, client_addr, proc_id, obj_id, confirmed, lifetime) OneShotTask.__init__(self) @@ -103,6 +103,7 @@ def __init__(self, obj_ref, client_addr, proc_id, obj_id, confirmed, lifetime): self.obj_id = obj_id self.confirmed = confirmed self.lifetime = lifetime + self.covIncrement = cov_inc # if lifetime is non-zero, schedule the subscription to expire if lifetime != 0: @@ -756,3 +757,83 @@ def do_SubscribeCOVRequest(self, apdu): if _debug: ChangeOfValueServices._debug(" - send a notification") deferred(cov_detection.send_cov_notifications, cov) + def do_SubscribeCOVPropertyRequest(self, apdu): + if _debug: ChangeOfValueServices._debug("do_SubscribeCOVPropertyRequest %r", apdu) + + # extract the pieces + client_addr = apdu.pduSource + proc_id = apdu.subscriberProcessIdentifier + obj_id = apdu.monitoredObjectIdentifier + confirmed = apdu.issueConfirmedNotifications + lifetime = apdu.lifetime + prop_id = apdu.monitoredPropertyIdentifier + cov_inc = apdu.covIncrement + + print("Dap: prop_id: {}, cov_inc: {}".format(prop_id,cov_inc)) + # request is to cancel the subscription + cancel_subscription = (confirmed is None) and (lifetime is None) + + # find the object + obj = self.get_object_id(obj_id) + if _debug: ChangeOfValueServices._debug(" - object: %r", obj) + if not obj: + raise ExecutionError(errorClass='object', errorCode='unknownObject') + + # check to see if the object supports COV + if not obj._object_supports_cov: + raise ExecutionError(errorClass='services', errorCode='covSubscriptionFailed') + + # look for an algorithm already associated with this object + cov_detection = self.cov_detections.get(obj, None) + + # if there isn't one, make one and associate it with the object + if not cov_detection: + # look for an associated class and if it's not there it's not supported + criteria_class = criteria_type_map.get(obj_id[0], None) + if not criteria_class: + raise ExecutionError(errorClass='services', errorCode='covSubscriptionFailed') + + # make one of these and bind it to the object + cov_detection = criteria_class(obj) + + # keep track of it for other subscriptions + self.cov_detections[obj] = cov_detection + if _debug: ChangeOfValueServices._debug(" - cov_detection: %r", cov_detection) + + # can a match be found? + cov = cov_detection.cov_subscriptions.find(client_addr, proc_id, obj_id) + if _debug: ChangeOfValueServices._debug(" - cov: %r", cov) + + # if a match was found, update the subscription + if cov: + if cancel_subscription: + if _debug: ChangeOfValueServices._debug(" - cancel the subscription") + self.cancel_subscription(cov) + else: + if _debug: ChangeOfValueServices._debug(" - renew the subscription") + cov.renew_subscription(lifetime) + else: + if cancel_subscription: + if _debug: ChangeOfValueServices._debug(" - cancel a subscription that doesn't exist") + else: + if _debug: ChangeOfValueServices._debug(" - create a subscription") + + # make a subscription + cov = Subscription(obj, client_addr, proc_id, obj_id, + confirmed, lifetime, cov_inc) + if _debug: ChangeOfValueServices._debug(" - cov: %r", cov) + + # add it to our subscriptions lists + self.add_subscription(cov) + + # success + response = SimpleAckPDU(context=apdu) + + # return the result + self.response(response) + + # if the subscription is not being canceled, it is new or renewed, + # so send it a notification when you get a chance. + if not cancel_subscription: + if _debug: ChangeOfValueServices._debug(" - send a notification") + deferred(cov_detection.send_cov_notifications, cov) \ No newline at end of file diff --git a/samples/COVClient.py b/samples/COVClient.py index 41673e79..012c8e52 100755 --- a/samples/COVClient.py +++ b/samples/COVClient.py @@ -15,11 +15,12 @@ from bacpypes.iocb import IOCB from bacpypes.pdu import Address -from bacpypes.apdu import SubscribeCOVRequest, SimpleAckPDU, RejectPDU, AbortPDU +from bacpypes.apdu import SubscribeCOVRequest, SimpleAckPDU, RejectPDU, AbortPDU, SubscribeCOVPropertyRequest from bacpypes.primitivedata import ObjectIdentifier from bacpypes.app import BIPSimpleApplication from bacpypes.local.device import LocalDeviceObject +from bacpypes.basetypes import PropertyReference # some debugging _debug = 0 @@ -145,8 +146,14 @@ def do_subscribe(self, args): lifetime = None # build a request - request = SubscribeCOVRequest( - subscriberProcessIdentifier=proc_id, monitoredObjectIdentifier=obj_id + # request = SubscribeCOVRequest( + # subscriberProcessIdentifier=proc_id, monitoredObjectIdentifier=obj_id + # ) + request = SubscribeCOVPropertyRequest( + subscriberProcessIdentifier=proc_id, + monitoredObjectIdentifier=obj_id, + monitoredPropertyIdentifier=PropertyReference(propertyIdentifier=85), + covIncrement=2 ) request.pduDestination = Address(addr)