@@ -434,6 +434,157 @@ START_TEST(Client_subscription_createDataChanges) {
434
434
}
435
435
END_TEST
436
436
437
+ /* An unchanged value shall not be published after a ModifyMonitoredItem */
438
+ START_TEST (Client_subscription_modifyMonitoredItem ) {
439
+ UA_Client * client = UA_Client_new ();
440
+ UA_ClientConfig_setDefault (UA_Client_getConfig (client ));
441
+ UA_StatusCode retval = UA_Client_connect (client , "opc.tcp://localhost:4840" );
442
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
443
+
444
+ UA_Client_recv = client -> connection .recv ;
445
+ client -> connection .recv = UA_Client_recvTesting ;
446
+
447
+ UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default ();
448
+ UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create (client , request ,
449
+ NULL , NULL , NULL );
450
+ ck_assert_uint_eq (response .responseHeader .serviceResult , UA_STATUSCODE_GOOD );
451
+ UA_UInt32 subId = response .subscriptionId ;
452
+
453
+ UA_MonitoredItemCreateRequest items [1 ];
454
+ UA_UInt32 newMonitoredItemIds [1 ];
455
+ UA_Client_DataChangeNotificationCallback callbacks [1 ];
456
+ UA_Client_DeleteMonitoredItemCallback deleteCallbacks [1 ];
457
+ void * contexts [1 ];
458
+
459
+ /* Monitor the server state. Does not change during the unit test. */
460
+ items [0 ] = UA_MonitoredItemCreateRequest_default (UA_NODEID_NUMERIC (0 , UA_NS0ID_SERVER_SERVERSTATUS_STATE ));
461
+ items [0 ].requestedParameters .samplingInterval = publishingInterval * 0.2 ;
462
+ callbacks [0 ] = dataChangeHandler ;
463
+ contexts [0 ] = NULL ;
464
+ deleteCallbacks [0 ] = NULL ;
465
+
466
+ UA_CreateMonitoredItemsRequest createRequest ;
467
+ UA_CreateMonitoredItemsRequest_init (& createRequest );
468
+ createRequest .subscriptionId = subId ;
469
+ createRequest .timestampsToReturn = UA_TIMESTAMPSTORETURN_NEITHER ;
470
+ createRequest .itemsToCreate = items ;
471
+ createRequest .itemsToCreateSize = 1 ;
472
+ UA_CreateMonitoredItemsResponse createResponse =
473
+ UA_Client_MonitoredItems_createDataChanges (client , createRequest , contexts ,
474
+ callbacks , deleteCallbacks );
475
+
476
+ ck_assert_uint_eq (createResponse .responseHeader .serviceResult , UA_STATUSCODE_GOOD );
477
+ ck_assert_uint_eq (createResponse .resultsSize , 1 );
478
+ ck_assert_uint_eq (createResponse .results [0 ].statusCode , UA_STATUSCODE_GOOD );
479
+ newMonitoredItemIds [0 ] = createResponse .results [0 ].monitoredItemId ;
480
+ UA_CreateMonitoredItemsResponse_deleteMembers (& createResponse );
481
+
482
+ UA_fakeSleep ((UA_UInt32 )publishingInterval + 1 );
483
+
484
+ /* Receive the initial value */
485
+ notificationReceived = false;
486
+ countNotificationReceived = 0 ;
487
+ retval = UA_Client_run_iterate (client , (UA_UInt16 )(publishingInterval + 1 ));
488
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
489
+ ck_assert_uint_eq (notificationReceived , true);
490
+ ck_assert_uint_eq (countNotificationReceived , 1 );
491
+
492
+ /* No further update */
493
+ notificationReceived = false;
494
+ retval = UA_Client_run_iterate (client , (UA_UInt16 )(publishingInterval + 1 ));
495
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
496
+ ck_assert_uint_eq (notificationReceived , false);
497
+ ck_assert_uint_eq (countNotificationReceived , 1 );
498
+
499
+ /* Modify the MonitoredItem and change the sampling interval */
500
+ UA_MonitoredItemModifyRequest modify1 ;
501
+ UA_MonitoredItemModifyRequest_init (& modify1 );
502
+ modify1 .monitoredItemId = newMonitoredItemIds [0 ];
503
+ modify1 .requestedParameters .samplingInterval = publishingInterval * 1.5 ;
504
+
505
+ UA_ModifyMonitoredItemsRequest modifyRequest ;
506
+ UA_ModifyMonitoredItemsRequest_init (& modifyRequest );
507
+ modifyRequest .subscriptionId = subId ;
508
+ modifyRequest .itemsToModify = & modify1 ;
509
+ modifyRequest .itemsToModifySize = 1 ;
510
+
511
+ UA_ModifyMonitoredItemsResponse modifyResponse =
512
+ UA_Client_MonitoredItems_modify (client , modifyRequest );
513
+ ck_assert_uint_eq (modifyResponse .resultsSize , 1 );
514
+ ck_assert_uint_eq (modifyResponse .results [0 ].statusCode , UA_STATUSCODE_GOOD );
515
+ UA_ModifyMonitoredItemsResponse_deleteMembers (& modifyResponse );
516
+
517
+ /* Sleep longer than the publishing interval */
518
+ UA_fakeSleep ((UA_UInt32 )publishingInterval + 1 );
519
+
520
+ /* Don't receive an immediate update */
521
+ notificationReceived = false;
522
+ countNotificationReceived = 0 ;
523
+ retval = UA_Client_run_iterate (client , (UA_UInt16 )(publishingInterval + 1 ));
524
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
525
+ ck_assert_uint_eq (notificationReceived , false);
526
+ ck_assert_uint_eq (countNotificationReceived , 0 );
527
+
528
+ /* Modify the MonitoredItem and change the trigger. We want to see an
529
+ * update. But not immediately. */
530
+ UA_DataChangeFilter filter ;
531
+ UA_DataChangeFilter_init (& filter );
532
+ filter .trigger = UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP ;
533
+ modify1 .requestedParameters .filter .content .decoded .data = & filter ;
534
+ modify1 .requestedParameters .filter .content .decoded .type =
535
+ & UA_TYPES [UA_TYPES_DATACHANGEFILTER ];
536
+ modify1 .requestedParameters .filter .encoding = UA_EXTENSIONOBJECT_DECODED ;
537
+
538
+ modifyResponse = UA_Client_MonitoredItems_modify (client , modifyRequest );
539
+ ck_assert_uint_eq (modifyResponse .resultsSize , 1 );
540
+ ck_assert_uint_eq (modifyResponse .results [0 ].statusCode , UA_STATUSCODE_GOOD );
541
+ UA_ModifyMonitoredItemsResponse_deleteMembers (& modifyResponse );
542
+
543
+ /* Sleep longer than the publishing interval */
544
+ UA_fakeSleep ((UA_UInt32 )publishingInterval + 1 );
545
+ UA_realSleep ((UA_UInt32 )publishingInterval + 1 );
546
+
547
+ notificationReceived = false;
548
+ countNotificationReceived = 0 ;
549
+ retval = UA_Client_run_iterate (client , (UA_UInt16 )(publishingInterval + 1 ));
550
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
551
+ ck_assert_uint_eq (notificationReceived , false);
552
+ ck_assert_uint_eq (countNotificationReceived , 0 );
553
+
554
+ /* Sleep long enough to trigger the next sampling.
555
+ * This should now generate a value with the timestamp. */
556
+ UA_fakeSleep ((UA_UInt32 )(publishingInterval * 0.6 ));
557
+ UA_realSleep ((UA_UInt32 )(publishingInterval * 0.6 ));
558
+
559
+ /* Sleep long enough to trigger the publish callback */
560
+ UA_fakeSleep ((UA_UInt32 )publishingInterval + 1 );
561
+ retval = UA_Client_run_iterate (client , (UA_UInt16 )(publishingInterval + 1 ));
562
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
563
+ ck_assert_uint_eq (notificationReceived , true);
564
+ ck_assert_uint_eq (countNotificationReceived , 1 );
565
+
566
+ /* Delete and clean up */
567
+ UA_DeleteMonitoredItemsRequest deleteRequest ;
568
+ UA_DeleteMonitoredItemsRequest_init (& deleteRequest );
569
+ deleteRequest .subscriptionId = subId ;
570
+ deleteRequest .monitoredItemIds = newMonitoredItemIds ;
571
+ deleteRequest .monitoredItemIdsSize = 1 ;
572
+
573
+ UA_DeleteMonitoredItemsResponse deleteResponse =
574
+ UA_Client_MonitoredItems_delete (client , deleteRequest );
575
+
576
+ ck_assert_uint_eq (deleteResponse .responseHeader .serviceResult , UA_STATUSCODE_GOOD );
577
+ ck_assert_uint_eq (deleteResponse .resultsSize , 1 );
578
+ UA_DeleteMonitoredItemsResponse_deleteMembers (& deleteResponse );
579
+
580
+ retval = UA_Client_Subscriptions_deleteSingle (client , subId );
581
+ ck_assert_uint_eq (retval , UA_STATUSCODE_GOOD );
582
+
583
+ UA_Client_disconnect (client );
584
+ UA_Client_delete (client );
585
+ }
586
+ END_TEST
587
+
437
588
START_TEST (Client_subscription_createDataChanges_async ) {
438
589
UA_UInt32 reqId = 0 ;
439
590
UA_Client * client = UA_Client_new ();
@@ -1099,6 +1250,7 @@ static Suite* testSuite_Client(void) {
1099
1250
tcase_add_test (tc_client , Client_subscription_timeout );
1100
1251
tcase_add_test (tc_client , Client_subscription_connectionClose );
1101
1252
tcase_add_test (tc_client , Client_subscription_createDataChanges );
1253
+ tcase_add_test (tc_client , Client_subscription_modifyMonitoredItem );
1102
1254
tcase_add_test (tc_client , Client_subscription_createDataChanges_async );
1103
1255
tcase_add_test (tc_client , Client_subscription_keepAlive );
1104
1256
tcase_add_test (tc_client , Client_subscription_without_notification );
0 commit comments