def create_COV_subscription(self, target_address, point_name, object_type, instance_number, lifetime=None): # TODO check that the device supports cov subscription = None for sub in self.this_application.sub_cov_contexts: check_sub = self.this_application.sub_cov_contexts[sub] if check_sub.point_name == point_name and \ check_sub.monitoredObjectIdentifier == (object_type, instance_number): subscription = check_sub if not subscription: subscription = SubscriptionContext( target_address, point_name, object_type, instance_number, self.this_application.cov_sub_process_ID, lifetime) self.this_application.sub_cov_contexts[ self.this_application.cov_sub_process_ID] = subscription self.this_application.cov_sub_process_ID += 1 cov_request = SubscribeCOVRequest( subscriberProcessIdentifier=subscription. subscriberProcessIdentifier, monitoredObjectIdentifier=subscription.monitoredObjectIdentifier, issueConfirmedNotifications=True, lifetime=subscription.lifetime) cov_request.pduDestination = Address(subscription.address) iocb = self.iocb_class(cov_request) self.this_application.submit_request(iocb) _log.debug("COV subscription sent to device {} for {}".format( target_address, point_name))
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)
def send_cov_subscription(self, address, subscriberProcessIdentifier, monitoredObjectIdentifier, lifetime, point_name): """ :param address: address of the device to which the subscription request will be sent :param subscriberProcessIdentifier: arbitrarily set value for tracking cov subscriptions :param monitoredObjectIdentifier: (object_type, instance_number) from the subscription context :param lifetime: lifetime in seconds for the device to maintain the subscription :param point_name:point name for which we would like to establish the subscription :return: """ subscribe_cov_request = SubscribeCOVRequest( subscriberProcessIdentifier=subscriberProcessIdentifier, monitoredObjectIdentifier=monitoredObjectIdentifier, issueConfirmedNotifications=True, lifetime=lifetime ) subscribe_cov_request.pduDestination = address iocb = self.iocb_class(subscribe_cov_request) self.this_application.submit_request(iocb) _log.debug("COV subscription sent to device at {} for {}" .format(address, point_name))
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 send_subscription(self, addr, proc_id, objid, confirmed=None, lifetime=None): if _debug: logger.debug("send_subscription") # build a request request = SubscribeCOVRequest( subscriberProcessIdentifier=proc_id, monitoredObjectIdentifier=objid, ) request.pduDestination = Address(addr) # optional parameters if confirmed is not None: request.issueConfirmedNotifications = confirmed if lifetime is not None: request.lifetime = lifetime self._request = request # make an IOCB iocb = IOCB(request) if _debug: logger.debug(" - iocb: %r", iocb) # callback when it is acknowledged #iocb.add_callback(self.subscription_acknowledged) # give it to the application self.request_io(iocb)
def test_8_10_3(self): """Canceling a Subscription""" if _debug: TestBinaryValue._debug("test_8_10_3") # create a network anet = ApplicationNetwork("test_8_10_3") # add the service capability to the IUT anet.td.add_capability(COVTestClientServices) anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # an easy way to change the present value write_test_bv = lambda v: setattr(test_bv, 'presentValue', v) # add it to the implementation anet.iut.add_object(test_bv) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # wait for the subscription, then for the cancelation anet.iut.start_state.doc("8.10.3-1-0") \ .receive(SubscribeCOVRequest).doc("8.10.3-1-1") \ .receive(SubscribeCOVRequest).doc("8.10.3-1-2") \ .success() # send the subscription, wait for the ack, then send the cancelation # and wait for the ack. Ignore the notification that is sent when # after the subscription subscription_acked = anet.td.start_state.doc("8.10.3-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("8.10.3-2-1") \ .ignore(UnconfirmedCOVNotificationRequest) \ .receive(SimpleAckPDU).doc("8.10.3-2-2") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), )).doc("8.10.3-2-1") \ .ignore(UnconfirmedCOVNotificationRequest) \ .receive(SimpleAckPDU).doc("8.10.3-2-2") \ .success() # run the group anet.run()
def send_cov_subscription(self, address, subscriber_process_identifier, monitored_object_identifier, lifetime, point_name): """ Send request to remote BACnet device to create subscription for COV on a point. :param address: address of the device to which the subscription request will be sent :param subscriber_process_identifier: arbitrarily set value for tracking cov subscriptions :param monitored_object_identifier: (object_type, instance_number) from the subscription context :param lifetime: lifetime in seconds for the device to maintain the subscription :param point_name:point name for which we would like to establish the subscription :return: """ subscribe_cov_request = SubscribeCOVRequest( subscriberProcessIdentifier=subscriber_process_identifier, monitoredObjectIdentifier=monitored_object_identifier, issueConfirmedNotifications=True, lifetime=lifetime) subscribe_cov_request.pduDestination = address iocb = self.iocb_class(subscribe_cov_request) self.bacnet_application.submit_request(iocb) _log.debug("COV subscription sent to device at {} for {}".format( address, point_name))
def do_subscribe(self, args): """subscribe addr proc_id obj_type obj_inst [ confirmed ] [ lifetime ] """ 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) # give it to the application this_application.request(request) except Exception as e: SubscribeCOVConsoleCmd._exception("exception: %r", e)
def _build_cov_request(self, context): 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 return request
def test_simple_transition_unconfirmed(self): if _debug: TestAnalogValue._debug("test_simple_transition_unconfirmed") # create a network anet = ApplicationNetwork("test_simple_transition_unconfirmed") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make an analog value object test_av = AnalogValueObject( objectIdentifier=('analogValue', 1), objectName='av', presentValue=0.0, statusFlags=[0, 0, 0, 0], covIncrement=10.0, ) # an easy way to change the present value write_test_av = lambda v: setattr(test_av, 'presentValue', v) # add it to the implementation anet.iut.add_object(test_av) # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("3-1-0") \ .receive(SubscribeCOVRequest).doc("3-1-1") \ .wait_event("e1").doc("3-1-2") \ .call(write_test_av, 100.0).doc("3-1-3") \ .timeout(10).doc("3-2-4") \ .success() # test device is quiet anet.td.start_state.doc("3-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('analogValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("3-2-1") \ .receive(SimpleAckPDU).doc("3-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("3-2-3") \ .set_event("e1").doc("3-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("3-2-5") \ .timeout(10).doc("3-2-6") \ .success() # run the group anet.run()
def test_9_10_1_1(self): if _debug: TestBinaryValue._debug("test_9_10_1_1") notification_fail_time = 0.5 # create a network anet = ApplicationNetwork("test_9_10_1_1") # add the service capability to the IUT anet.td.add_capability(COVTestClientServices) anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # add it to the implementation anet.iut.add_object(test_bv) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # wait for the subscription, wait for the notification ack anet.iut.start_state.doc("9.10.1.1-1-0") \ .receive(SubscribeCOVRequest).doc("9.10.1.1-1-1") \ .receive(SimpleAckPDU).doc("9.10.1.1-1-2") \ .timeout(10).doc("9.10.1.1-1-3") \ .success() # test device is quiet wait_for_notification = \ anet.td.start_state.doc("9.10.1.1-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=True, lifetime=30, )).doc("9.10.1.1-2-1") \ .receive(SimpleAckPDU).doc("9.10.1.1-2-2") # after the ack, don't wait too long for the notification wait_for_notification \ .timeout(notification_fail_time).doc("9.10.1.1-2-3").fail() # if the notification is received, success wait_for_notification \ .receive(ConfirmedCOVNotificationRequest).doc("9.10.1.1-2-4") \ .timeout(10).doc("9.10.1.1-2-5") \ .success() # run the group anet.run()
def test_changing_properties(self): """This test changes the value of multiple properties to verify that only one COV notification is sent.""" if _debug: TestBinaryValue._debug("test_changing_properties") # create a network anet = ApplicationNetwork("test_changing_properties") # add the service capability to the IUT anet.td.add_capability(COVTestClientServices) anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # an easy way to change the present value def test_bv_fault(): if _debug: TestBinaryValue._debug("test_bv_fault") test_bv.presentValue = 'active' test_bv.statusFlags = [0, 0, 1, 0] # add it to the implementation anet.iut.add_object(test_bv) # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("5-1-0") \ .receive(SubscribeCOVRequest).doc("5-1-1") \ .wait_event("e1").doc("5-1-2") \ .call(test_bv_fault).doc("5-1-3") \ .timeout(10).doc("5-2-4") \ .success() # test device is quiet anet.td.start_state.doc("5-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("5-2-1") \ .receive(SimpleAckPDU).doc("5-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("5-2-3") \ .set_event("e1").doc("5-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("5-2-5") \ .timeout(10).doc("5-2-6") \ .success() # run the group anet.run()
def test_8_10_1(self): """Confirmed Notifications Subscription""" if _debug: TestPulseConverter._debug("test_8_10_1") # create a network anet = ApplicationNetwork("test_8_10_1") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make a pulse converter object test_pc = PulseConverterObject( objectIdentifier=('pulseConverter', 1), objectName='pc', presentValue=0.0, statusFlags=[0, 0, 0, 0], updateTime=DateTime(date=Date().now().value, time=Time().now().value), covIncrement=10.0, covPeriod=10, ) # add it to the implementation anet.iut.add_object(test_pc) # wait for the subscription anet.iut.start_state.doc("8.10.1-1-0") \ .receive(SubscribeCOVRequest).doc("8.10.1-1-1") \ .success() # send the subscription, wait for the ack anet.td.start_state.doc("8.10.1-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('pulseConverter', 1), issueConfirmedNotifications=True, lifetime=30, )).doc("8.10.1-2-1") \ .receive(SimpleAckPDU).doc("8.10.1-2-2") \ .success() # run the group anet.run()
def test_8_10_4(self): """Requests 8 Hour Lifetimes""" if _debug: TestAnalogValue._debug("test_8_10_4") # create a network anet = ApplicationNetwork("test_8_10_4") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make an analog value object test_av = AnalogValueObject( objectIdentifier=('analogValue', 1), objectName='av', presentValue=0.0, statusFlags=[0, 0, 0, 0], covIncrement=10.0, ) # add it to the implementation anet.iut.add_object(test_av) # wait for the subscription anet.iut.start_state.doc("8.10.4-1-0") \ .receive(SubscribeCOVRequest).doc("8.10.4-1-1") \ .success() # send the subscription, wait for the ack anet.td.start_state.doc("8.10.4-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('analogValue', 1), issueConfirmedNotifications=True, lifetime=28800, )).doc("8.10.4-2-1") \ .receive(SimpleAckPDU).doc("8.10.4-2-2") \ .success() # run the group anet.run()
def test_8_10_2(self): """Unconfirmed Notifications Subscription""" if _debug: TestPulseConverter._debug("test_8_10_2") # create a network anet = ApplicationNetwork("test_8_10_2") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make a pulse converter object test_pc = PulseConverterObject( objectIdentifier=('pulseConverter', 1), objectName='pc', presentValue=0.0, statusFlags=[0, 0, 0, 0], updateTime=DateTime(date=Date().now().value, time=Time().now().value), covIncrement=10.0, covPeriod=10, ) # add it to the implementation anet.iut.add_object(test_pc) # wait for the subscription anet.iut.start_state.doc("8.10.2-1-0") \ .receive(SubscribeCOVRequest).doc("8.10.2-1-1") \ .success() # send the subscription, wait for the ack anet.td.start_state.doc("8.10.2-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('pulseConverter', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("8.10.2-2-1") \ .receive(SimpleAckPDU).doc("8.10.2-2-2") \ .success() # run the group, cut the time limit short anet.run(time_limit=5.0) # check that the IUT still has the detection if _debug: TestPulseConverter._debug(" - detections: %r", anet.iut.cov_detections) assert len(anet.iut.cov_detections) == 1 # pop out the subscription list and criteria obj_ref, criteria = anet.iut.cov_detections.popitem() if _debug: TestPulseConverter._debug(" - criteria: %r", criteria) # get the list of subscriptions from the criteria subscriptions = criteria.cov_subscriptions.cov_subscriptions if _debug: TestPulseConverter._debug(" - subscriptions: %r", subscriptions) assert len(subscriptions) == 1
def test_multiple_subscribers(self): """This has more than one subscriber for the object.""" if _debug: TestPulseConverter._debug("test_multiple_subscribers") # create a network anet = ApplicationNetwork("test_multiple_subscribers") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make a pulse converter object test_pc = PulseConverterObject( objectIdentifier=('pulseConverter', 1), objectName='pc', presentValue=0.0, statusFlags=[0, 0, 0, 0], updateTime=DateTime(date=Date().now().value, time=Time().now().value), covIncrement=10.0, covPeriod=10, ) # an easy way to change both the present value and status flags # which should trigger only one notification def test_pc_fault(): if _debug: TestPulseConverter._debug("test_pc_fault") test_pc.presentValue = 100.0 test_pc.statusFlags = [0, 0, 1, 0] # add it to the implementation anet.iut.add_object(test_pc) # add another test device object anet.td2_device_object = LocalDeviceObject( objectName="td2", objectIdentifier=('device', 30), maxApduLengthAccepted=1024, segmentationSupported='noSegmentation', vendorIdentifier=999, ) # another test device anet.td2 = ApplicationStateMachine(anet.td2_device_object, anet.vlan) anet.td2.add_capability(COVTestClientServices) anet.append(anet.td2) # receive the subscription requests, wait until both clients have # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("6-1-0") \ .receive(SubscribeCOVRequest, pduSource=anet.td.address).doc("6-1-1") \ .receive(SubscribeCOVRequest, pduSource=anet.td2.address).doc("6-1-2") \ .wait_event("e2").doc("6-1-3") \ .call(test_pc_fault).doc("6-1-4") \ .timeout(10).doc("6-2-5") \ .success() # first test device; send the subscription request, get an ack # followed by the 'instant' notification anet.td.start_state.doc("6-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('pulseConverter', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("6-2-1") \ .receive(SimpleAckPDU).doc("6-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-2-3") \ .set_event("e1").doc("6-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-2-5") \ .timeout(10).doc("6-2-6") \ .success() # same pattern for the other test device anet.td2.start_state.doc("6-3-0") \ .wait_event("e1").doc("6-3-1") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('pulseConverter', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("6-3-2") \ .receive(SimpleAckPDU).doc("6-3-3") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-3-4") \ .set_event("e2").doc("6-3-5") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-3-6") \ .timeout(10).doc("6-3-7") \ .success() # run the group anet.run()
def test_changing_properties(self): """This test changes the value of multiple properties to verify that only one COV notification is sent.""" if _debug: TestPulseConverter._debug("test_changing_properties") # create a network anet = ApplicationNetwork("test_changing_properties") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make a pulse converter object test_pc = PulseConverterObject( objectIdentifier=('pulseConverter', 1), objectName='pc', presentValue=0.0, statusFlags=[0, 0, 0, 0], updateTime=DateTime(date=Date().now().value, time=Time().now().value), covIncrement=10.0, covPeriod=10, ) # an easy way to change the present value def test_pc_fault(): if _debug: TestPulseConverter._debug("test_pc_fault") test_pc.presentValue = 100.0 test_pc.statusFlags = [0, 0, 1, 0] # add it to the implementation anet.iut.add_object(test_pc) # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("5-1-0") \ .receive(SubscribeCOVRequest).doc("5-1-1") \ .wait_event("e1").doc("5-1-2") \ .call(test_pc_fault).doc("5-1-3") \ .timeout(10).doc("5-2-4") \ .success() # test device is quiet anet.td.start_state.doc("5-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('pulseConverter', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("5-2-1") \ .receive(SimpleAckPDU).doc("5-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("5-2-3") \ .set_event("e1").doc("5-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("5-2-5") \ .timeout(10).doc("5-2-6") \ .success() # run the group anet.run()
def test_8_2_1(self): """To verify that the IUT can initiate ConfirmedCOVNotification service requests conveying a change of the Present_Value property of Analog Input, Analog Output, and Analog Value objects.""" if _debug: TestPulseConverter._debug("test_8_2_1") # create a network anet = ApplicationNetwork("test_8_2_1") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make a pulse converter object test_pc = PulseConverterObject( objectIdentifier=('pulseConverter', 1), objectName='pc', presentValue=0.0, statusFlags=[0, 0, 0, 0], updateTime=DateTime(date=Date().now().value, time=Time().now().value), covIncrement=10.0, covPeriod=10, ) # an easy way to change the present value def write_test_pc(v): if _debug: TestPulseConverter._debug("=== marco %r", v) setattr(test_pc, 'presentValue', v) if _debug: TestPulseConverter._debug("=== polo") # add it to the implementation anet.iut.add_object(test_pc) # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value a little bit and nothing should be sent. Change it some more # and wait for the notification ack. anet.iut.start_state.doc("2-1-0") \ .receive(SubscribeCOVRequest).doc("2-1-1") \ .receive(SimpleAckPDU).doc("2-1-2") \ .wait_event("e1").doc("2-1-3") \ .call(write_test_pc, 5.0).doc("2-1-4") \ .timeout(5).doc("2-1-5") \ .call(write_test_pc, 10.0).doc("2-1-6") \ .receive(SimpleAckPDU).doc("2-1-7") \ .receive(SimpleAckPDU).doc("2-1-8") \ .timeout(10).doc("2-1-9") \ .success() # send the subscription request, wait for the ack and the 'instant' # notification, set the event so the IUT can continue, then wait # for the next notification anet.td.start_state.doc("2-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('pulseConverter', 1), issueConfirmedNotifications=True, lifetime=30, )).doc("2-2-1") \ .receive(SimpleAckPDU).doc("2-2-2") \ .receive(ConfirmedCOVNotificationRequest).doc("2-2-3") \ .set_event("e1").doc("2-2-4") \ .receive(ConfirmedCOVNotificationRequest).doc("2-2-5") \ .receive(ConfirmedCOVNotificationRequest).doc("2-2-6") \ .timeout(10).doc("2-2-7") \ .success() # run the group anet.run()
def do_subscribe(self, args): """subscribe addr proc_id obj_type obj_inst [ confirmed ] [ lifetime ] """ args = args.split() if _debug: COVConsoleCmd._debug("do_subscribe %r", args) global test_application try: addr, proc_id, obj_type, obj_inst = args[:4] client_addr = Address(addr) if _debug: COVConsoleCmd._debug(" - client_addr: %r", client_addr) proc_id = int(proc_id) if _debug: COVConsoleCmd._debug(" - proc_id: %r", 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) obj_id = (obj_type, obj_inst) if _debug: COVConsoleCmd._debug(" - obj_id: %r", obj_id) obj = test_application.get_object_id(obj_id) if not obj: print("object not found") return if len(args) >= 5: issue_confirmed = args[4] if issue_confirmed == '-': issue_confirmed = None else: issue_confirmed = issue_confirmed.lower() == 'true' if _debug: COVConsoleCmd._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: COVConsoleCmd._debug(" - lifetime: %r", lifetime) else: lifetime = None # can a match be found? cov = obj._cov_subscriptions.find(client_addr, proc_id, obj_id) if _debug: COVConsoleCmd._debug(" - cov: %r", cov) # build a request request = SubscribeCOVRequest( subscriberProcessIdentifier=proc_id, monitoredObjectIdentifier=obj_id, ) # spoof that it came from the client request.pduSource = client_addr # optional parameters if issue_confirmed is not None: request.issueConfirmedNotifications = issue_confirmed if lifetime is not None: request.lifetime = lifetime if _debug: COVConsoleCmd._debug(" - request: %r", request) # give it to the application test_application.do_SubscribeCOVRequest(request) except Exception as err: COVConsoleCmd._exception("exception: %r", err)
def test_changing_status_flags(self): """This test changes the status flags of binary value point to verify that the detection picks up other changes, most tests just change the present value.""" if _debug: TestAnalogValue._debug("test_changing_status_flags") # create a network anet = ApplicationNetwork("test_changing_status_flags") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make an analog value object test_av = AnalogValueObject( objectIdentifier=('analogValue', 1), objectName='av', presentValue=0.0, statusFlags=[0, 0, 0, 0], covIncrement=10.0, ) # an easy way to change the present value def test_av_fault(): if _debug: TestAnalogValue._debug("test_av_fault") test_av.statusFlags = [0, 1, 0, 0] # add it to the implementation anet.iut.add_object(test_av) # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("4-1-0") \ .receive(SubscribeCOVRequest).doc("4-1-1") \ .wait_event("e1").doc("4-1-2") \ .call(test_av_fault).doc("4-1-3") \ .timeout(10).doc("4-2-4") \ .success() # test device is quiet anet.td.start_state.doc("4-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('analogValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("4-2-1") \ .receive(SimpleAckPDU).doc("4-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("4-2-3") \ .set_event("e1").doc("4-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("4-2-5") \ .timeout(10).doc("4-2-6") \ .success() # run the group anet.run()
def test_multiple_subscribers(self): """This has more than one subscriber for the object.""" if _debug: TestBinaryValue._debug("test_multiple_subscribers") # create a network anet = ApplicationNetwork("test_multiple_subscribers") # add the service capability to the IUT anet.td.add_capability(COVTestClientServices) anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # an easy way to change both the present value and status flags # which should trigger only one notification def test_bv_fault(): if _debug: TestBinaryValue._debug("test_bv_fault") test_bv.presentValue = 'active' test_bv.statusFlags = [0, 0, 1, 0] # add it to the implementation anet.iut.add_object(test_bv) # add another test device object anet.td2_device_object = LocalDeviceObject( objectName="td2", objectIdentifier=("device", 30), maxApduLengthAccepted=1024, segmentationSupported='noSegmentation', vendorIdentifier=999, ) # another test device anet.td2 = ApplicationStateMachine(anet.td2_device_object, anet.vlan) anet.td2.add_capability(COVTestClientServices) anet.append(anet.td2) # receive the subscription requests, wait until both clients have # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("6-1-0") \ .receive(SubscribeCOVRequest, pduSource=anet.td.address).doc("6-1-1") \ .receive(SubscribeCOVRequest, pduSource=anet.td2.address).doc("6-1-2") \ .wait_event("e2").doc("6-1-3") \ .call(test_bv_fault).doc("6-1-4") \ .timeout(10).doc("6-2-5") \ .success() # first test device; send the subscription request, get an ack # followed by the 'instant' notification anet.td.start_state.doc("6-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("6-2-1") \ .receive(SimpleAckPDU).doc("6-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-2-3") \ .set_event("e1").doc("6-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-2-5") \ .timeout(10).doc("6-2-6") \ .success() # same pa anet.td2.start_state.doc("6-3-0") \ .wait_event("e1").doc("6-3-1") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("6-3-2") \ .receive(SimpleAckPDU).doc("6-3-3") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-3-4") \ .set_event("e2").doc("6-3-5") \ .receive(UnconfirmedCOVNotificationRequest).doc("6-3-6") \ .timeout(10).doc("6-3-7") \ .success() # run the group anet.run()
def run(self): while True: self.inicio = time.time() for ids in Dispositivos: for obj in Dispositivos[ids]: addr = Dispositivos[ids]["IPort"] if not obj == "IPort": for args in Dispositivos[ids][obj]: RETRY = 0 DONE = False if self.ProcessID > 3000: self.ProcessID = 0 while RETRY < SubRetrys and DONE == False: try: #proc_id = Dispositivos[ids][obj][args]["ProcID"] proc_id = self.ProcessID lifetime = (int(TimeToRefreshSubs) + 30) obj_type, obj_inst = obj.split("_") issue_confirmed = True if obj_type.isdigit(): obj_type = int(obj_type) elif not get_object_class(obj_type): with open("ErrorLog.txt", "a") as myfile: myfile.write( str( time.strftime( "%d-%m-%Y %H:%M:%S")) + " Error trying to subscribe unknown object type.\n" ) obj_inst = int(obj_inst) request = SubscribeCOVRequest( subscriberProcessIdentifier=proc_id, monitoredObjectIdentifier=(obj_type, obj_inst), ) request.pduDestination = Address(addr) if issue_confirmed is not None: request.issueConfirmedNotifications = issue_confirmed if lifetime is not None: request.lifetime = lifetime iocb = IOCB(request) this_application.request_io(iocb) #print "Trying to subscribe to", ids, addr, obj_type, obj_inst iocb.wait(TimeToWaitForSub) state = iocb.ioState ''' IDLE = 0 # has not been submitted PENDING = 1 # queued, waiting for processing ACTIVE = 2 # being processed COMPLETED = 3 # finished ABORTED = 4 # finished in a bad way ''' if state == 0: time.sleep(TimeBetweenSubs) #print "ZZzzzzZZZzzzzZZZzzzzZZZ" elif state == 1: #print "Esta na queue, vai limpar e tentar de novo..." this_application.queue_by_address.clear( ) time.sleep(TimeBetweenSubs) elif state == 2: #print "Esta em processamento..." self.ProcessID += 1 DONE = True elif state == 3: #print "YEIII" self.ProcessID += 1 DONE = True elif state == 4: time.sleep(TimeBetweenSubs) #print "ABORTTTTTTTT, ja deu merdinha" with open("ErrorLog.txt", "a") as myfile: myfile.write( str( time.strftime( "%d-%m-%Y %H:%M:%S")) + "ABORTTTTTTTT") else: time.sleep(TimeBetweenSubs) #print "WATTTT YYYY!!!! NUNCA VISTO" with open("ErrorLog.txt", "a") as myfile: myfile.write( str( time.strftime( "%d-%m-%Y %H:%M:%S")) + "WATTTT YYYY!!!! NUNCA VISTO") except Exception as e: with open("ErrorLog.txt", "a") as myfile: myfile.write( str( time.strftime( "%d-%m-%Y %H:%M:%S")) + " Error while trying to subscribe, proc_id:" + str(proc_id) + " Addr:" + str(addr) + "\n") myfile.write("Error -> " + str(e) + "\n") RETRY += 1 self.fim = time.time() #print "Levou:", self.fim - self.inicio #print "Refresh Default:", TimeToRefreshSubs #print "Refresh Fixed:" , TimeToRefreshSubs - TimeBetweenSubs - round(self.fim - self.inicio, 1) #print Dispositivos time.sleep( abs(TimeToRefreshSubs - TimeBetweenSubs - round(self.fim - self.inicio, 1)))
def do_subscribe(self, args): """subscribe addr proc_id obj_id [ 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_id = args[:3] obj_id = ObjectIdentifier(obj_id).value proc_id = int(proc_id) if len(args) >= 4: issue_confirmed = args[3] 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) >= 5: lifetime = args[4] 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_id) 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 deferred(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 test_8_2_4(self): """To verify that the IUT can initiate ConfirmedCOVNotification service requests conveying a change of the Status_Flags property of Binary Input, Binary Output, and Binary Value objects.""" if _debug: TestBinaryValue._debug("test_8_2_4") # create a network anet = ApplicationNetwork("test_changing_status_flags") # add the ability to accept COV notifications to the TD anet.td.add_capability(COVTestClientServices) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # add the service capability to the IUT anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # an easy way to change the present value def test_bv_fault(): if _debug: TestBinaryValue._debug("test_bv_fault") test_bv.statusFlags = [0, 1, 0, 0] # add it to the implementation anet.iut.add_object(test_bv) # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value, no ack coming back anet.iut.start_state.doc("4-1-0") \ .receive(SubscribeCOVRequest).doc("4-1-1") \ .wait_event("e1").doc("4-1-2") \ .call(test_bv_fault).doc("4-1-3") \ .timeout(10).doc("4-2-4") \ .success() # test device is quiet anet.td.start_state.doc("4-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("4-2-1") \ .receive(SimpleAckPDU).doc("4-2-2") \ .receive(UnconfirmedCOVNotificationRequest).doc("4-2-3") \ .set_event("e1").doc("4-2-4") \ .receive(UnconfirmedCOVNotificationRequest).doc("4-2-5") \ .timeout(10).doc("4-2-6") \ .success() # run the group anet.run()
def test_8_10_2(self): """Unconfirmed Notifications Subscription""" if _debug: TestBinaryValue._debug("test_8_10_2") # create a network anet = ApplicationNetwork("test_8_10_2") # add the service capability to the IUT anet.td.add_capability(COVTestClientServices) anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # an easy way to change the present value write_test_bv = lambda v: setattr(test_bv, 'presentValue', v) # add it to the implementation anet.iut.add_object(test_bv) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # wait for the subscription anet.iut.start_state.doc("8.10.2-1-0") \ .receive(SubscribeCOVRequest).doc("8.10.2-1-1") \ .success() # send the subscription, wait for the ack anet.td.start_state.doc("8.10.2-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=False, lifetime=30, )).doc("8.10.2-2-1") \ .receive(SimpleAckPDU).doc("8.10.2-2-2") \ .success() # run the group, cut the time limit short anet.run(time_limit=5.0) # check that the IUT still has the detection if _debug: TestBinaryValue._debug(" - detections: %r", anet.iut.cov_detections) assert len(anet.iut.cov_detections) == 1 # pop out the subscription list and criteria obj_ref, criteria = anet.iut.cov_detections.popitem() if _debug: TestBinaryValue._debug(" - criteria: %r", criteria) # get the list of subscriptions from the criteria subscriptions = criteria.cov_subscriptions.cov_subscriptions if _debug: TestBinaryValue._debug(" - subscriptions: %r", subscriptions) assert len(subscriptions) == 1
def test_simple_transition_confirmed(self): if _debug: TestBinaryValue._debug("test_simple_transition_confirmed") # create a network anet = ApplicationNetwork("test_simple_transition_confirmed") # add the service capability to the IUT anet.td.add_capability(COVTestClientServices) anet.iut.add_capability(ChangeOfValueServices) # make a binary value object test_bv = BinaryValueObject( objectIdentifier=('binaryValue', 1), objectName='bv', presentValue='inactive', statusFlags=[0, 0, 0, 0], ) # an easy way to change the present value write_test_bv = lambda v: setattr(test_bv, 'presentValue', v) # add it to the implementation anet.iut.add_object(test_bv) # tell the TD how to respond to confirmed notifications anet.td.test_ack = True anet.td.test_reject = None anet.td.test_abort = None # receive the subscription request, wait until the client has # received the ack and the 'instant' notification. Then change the # value and wait for the ack. anet.iut.start_state.doc("2-1-0") \ .receive(SubscribeCOVRequest).doc("2-1-1") \ .receive(SimpleAckPDU).doc("2-1-2") \ .wait_event("e1").doc("2-1-3") \ .call(write_test_bv, 'active').doc("2-1-4") \ .receive(SimpleAckPDU).doc("2-1-5") \ .timeout(10).doc("2-2-6") \ .success() # send the subscription request, wait for the ack and the 'instant' # notification, set the event so the IUT can continue, then wait # for the next notification anet.td.start_state.doc("2-2-0") \ .send(SubscribeCOVRequest( destination=anet.iut.address, subscriberProcessIdentifier=1, monitoredObjectIdentifier=('binaryValue', 1), issueConfirmedNotifications=True, lifetime=30, )).doc("2-2-1") \ .receive(SimpleAckPDU).doc("2-2-2") \ .receive(ConfirmedCOVNotificationRequest).doc("2-2-4") \ .set_event("e1").doc("2-2-3") \ .receive(ConfirmedCOVNotificationRequest).doc("2-2-4") \ .timeout(10).doc("2-2-5") \ .success() # run the group anet.run()
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)