浏览代码

Subscriptions: Add absolute deadband filter for boolean values

Julius Pfrommer 6 年之前
父节点
当前提交
040c263773
共有 2 个文件被更改,包括 58 次插入4 次删除
  1. 5 1
      src/server/ua_subscription_datachange.c
  2. 53 3
      tests/server/check_monitoreditem_filter.c

+ 5 - 1
src/server/ua_subscription_datachange.c

@@ -22,7 +22,11 @@
 static UA_Boolean
 outOfDeadBand(const void *data1, const void *data2, const size_t arrayPos,
               const UA_DataType *type, const UA_Double deadbandValue) {
-    if(type == &UA_TYPES[UA_TYPES_SBYTE]) {
+    if(type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
+        if(ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Boolean*)data1)[arrayPos],
+                                         ((const UA_Boolean*)data2)[arrayPos]) <= deadbandValue)
+            return false;
+    } else if(type == &UA_TYPES[UA_TYPES_SBYTE]) {
         if(ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_SByte*)data1)[arrayPos],
                                          ((const UA_SByte*)data2)[arrayPos]) <= deadbandValue)
             return false;

+ 53 - 3
tests/server/check_monitoreditem_filter.c

@@ -47,6 +47,7 @@ static void setup(void) {
     server = UA_Server_new(config);
     UA_Server_run_startup(server);
     THREAD_CREATE(server_thread, serverloop);
+
     /* Define the attribute of the double variable node */
     UA_VariableAttributes attr = UA_VariableAttributes_default;
     UA_Double myDouble = 40.0;
@@ -55,8 +56,6 @@ static void setup(void) {
     attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
     attr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
     attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
-
-    /* Add the variable node to the information model */
     UA_NodeId doubleNodeId = UA_NODEID_STRING(1, "the.answer");
     UA_QualifiedName doubleName = UA_QUALIFIEDNAME(1, "the answer");
     parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
@@ -72,6 +71,20 @@ static void setup(void) {
                                                 &outNodeId)
                       , UA_STATUSCODE_GOOD);
 
+    /* Add a boolean node */
+    UA_Boolean myBool = false;
+    UA_Variant_setScalar(&attr.value, &myBool, &UA_TYPES[UA_TYPES_BOOLEAN]);
+    attr.description = UA_LOCALIZEDTEXT("en-US","the answer bool");
+    attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer bool");
+    attr.dataType = UA_TYPES[UA_TYPES_BOOLEAN].typeId;
+    ck_assert_uint_eq(UA_Server_addVariableNode(server,
+                                                UA_NODEID_STRING(1, "the.bool"),
+                                                parentNodeId, parentReferenceNodeId,
+                                                UA_QUALIFIEDNAME(1, "the bool"),
+                                                UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                                                attr, NULL, NULL)
+                      , UA_STATUSCODE_GOOD);
+
     client = UA_Client_new(UA_ClientConfig_default);
     UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
     ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
@@ -109,7 +122,6 @@ static void teardown(void) {
 
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 
-
 static void
 dataChangeHandler(UA_Client *thisClient, UA_UInt32 thisSubId, void *subContext,
                   UA_UInt32 monId, void *monContext, UA_DataValue *value) {
@@ -670,6 +682,43 @@ START_TEST(Server_MonitoredItemsNoFilter) {
 }
 END_TEST
 
+/* Test if an absolute filter can be added for boolean variables */
+START_TEST(Server_MonitoredItemsAbsoluteFilterOnBool) {
+    UA_DataValue_init(&lastValue);
+    /* define a monitored item with an absolute filter with deadbandvalue = 2.0 */
+    UA_MonitoredItemCreateRequest item =
+        UA_MonitoredItemCreateRequest_default(UA_NODEID_STRING(1, "the.bool"));;
+    UA_DataChangeFilter filter;
+    UA_DataChangeFilter_init(&filter);
+    filter.trigger = UA_DATACHANGETRIGGER_STATUSVALUE;
+    filter.deadbandType = UA_DEADBANDTYPE_ABSOLUTE;
+    filter.deadbandValue = 0.5;
+    item.requestedParameters.filter.encoding = UA_EXTENSIONOBJECT_DECODED;
+    item.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGEFILTER];
+    item.requestedParameters.filter.content.decoded.data = &filter;
+    UA_Client_DataChangeNotificationCallback callbacks[1];
+    callbacks[0] = dataChangeHandler;
+    UA_Client_DeleteMonitoredItemCallback deleteCallbacks[1] = {NULL};
+    void *contexts[1];
+    contexts[0] = NULL;
+
+    UA_CreateMonitoredItemsRequest createRequest;
+    UA_CreateMonitoredItemsRequest_init(&createRequest);
+    createRequest.subscriptionId = subId;
+    createRequest.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH;
+    createRequest.itemsToCreate = &item;
+    createRequest.itemsToCreateSize = 1;
+    UA_CreateMonitoredItemsResponse createResponse =
+       UA_Client_MonitoredItems_createDataChanges(client, createRequest, contexts,
+                                                  callbacks, deleteCallbacks);
+
+    ck_assert_uint_eq(createResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
+    ck_assert_uint_eq(createResponse.resultsSize, 1);
+    ck_assert_uint_eq(createResponse.results[0].statusCode, UA_STATUSCODE_GOOD);
+    UA_CreateMonitoredItemsResponse_deleteMembers(&createResponse);
+}
+END_TEST
+
 START_TEST(Server_MonitoredItemsAbsoluteFilterSetOnCreate) {
     UA_DataValue_init(&lastValue);
     /* define a monitored item with an absolute filter with deadbandvalue = 2.0 */
@@ -826,6 +875,7 @@ static Suite* testSuite_Client(void) {
 #ifdef UA_ENABLE_SUBSCRIPTIONS
     tcase_add_test(tc_server, Server_MonitoredItemsNoFilter);
     tcase_add_test(tc_server, Server_MonitoredItemsAbsoluteFilterSetOnCreate);
+    tcase_add_test(tc_server, Server_MonitoredItemsAbsoluteFilterOnBool);
     tcase_add_test(tc_server, Server_MonitoredItemsAbsoluteFilterSetLater);
     tcase_add_test(tc_server, Server_MonitoredItemsAbsoluteFilterSetOnCreateRemoveLater);
     tcase_add_test(tc_server, Server_MonitoredItemsPercentFilterSetOnCreate);