Переглянути джерело

Added callback to register MonitoredItems in userland

Fabian Arndt 6 роки тому
батько
коміт
ac4392ea2b

+ 18 - 0
include/ua_server_config.h

@@ -171,6 +171,24 @@ struct UA_ServerConfig {
     UA_UInt32 discoveryCleanupTimeout;
 #endif
 
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+    /* Register MonitoredItem in Userland
+     *
+     * @param server Allows the access to the server object
+     * @param sessionId The session id, represented as an node id
+     * @param sessionContext An optional pointer to user-defined data for the specific data source
+     * @param nodeid Id of the node in question
+     * @param nodeidContext An optional pointer to user-defined data, associated
+     *        with the node in the nodestore. Note that, if the node has already been removed,
+     *        this value contains a NULL pointer.
+     * @param attributeId Identifies which attribute (value, data type etc.) is monitored
+     * @param removed Determines if the MonitoredItem was removed or created. */
+    void (*monitoredItemRegisterCallback)(UA_Server *server,
+                                          const UA_NodeId *sessionId, void *sessionContext,
+                                          const UA_NodeId *nodeId, void *nodeContext,
+                                          UA_UInt32 attibuteId, UA_Boolean removed);
+#endif
+
     /* Historical Access */
 #ifdef UA_ENABLE_HISTORIZING
     UA_HistoryDataService historyDataService;

+ 12 - 0
src/server/ua_services_subscription.c

@@ -12,6 +12,7 @@
  *    Copyright 2017 (c) Mattias Bornhager
  *    Copyright 2017 (c) Henrik Norrman
  *    Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ *    Copyright 2018 (c) Fabian Arndt, Root-Core
  */
 
 #include "ua_server_internal.h"
@@ -352,6 +353,17 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct cre
         LIST_INSERT_HEAD(&server->localMonitoredItems, newMon, listEntry);
     }
 
+    /* Register MonitoredItem in userland */
+    if(server->config.monitoredItemRegisterCallback) {
+        void *targetContext = NULL;
+        UA_Server_getNodeContext(server, request->itemToMonitor.nodeId, &targetContext);
+        server->config.monitoredItemRegisterCallback(server, &session->sessionId,
+                                                     session->sessionHandle,
+                                                     &request->itemToMonitor.nodeId,
+                                                     targetContext, newMon->attributeId, false);
+        newMon->registered = true;
+    }
+
     /* Create the first sample */
     if(request->monitoringMode == UA_MONITORINGMODE_REPORTING)
         UA_MonitoredItem_sampleCallback(server, newMon);

+ 2 - 0
src/server/ua_subscription.h

@@ -85,6 +85,8 @@ struct UA_MonitoredItem {
     UA_Subscription *subscription;
     UA_UInt32 monitoredItemId;
     UA_UInt32 clientHandle;
+    UA_Boolean registered; /* Was the MonitoredItem registered in Userland with
+                              the callback? */
 
     /* Settings */
     UA_MonitoredItemType monitoredItemType;

+ 21 - 0
src/server/ua_subscription_datachange.c

@@ -6,6 +6,7 @@
  *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  *    Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
  *    Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
+ *    Copyright 2018 (c) Fabian Arndt, Root-Core
  */
 
 #include "ua_server_internal.h"
@@ -80,6 +81,26 @@ void UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem)
     }
 #endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
 
+    /* Deregister MonitoredItem in userland */
+    if(server->config.monitoredItemRegisterCallback && monitoredItem->registered) {
+        /* Get the session context. Local MonitoredItems don't have a subscription. */
+        UA_Session *session = NULL;
+        if(monitoredItem->subscription)
+            session = monitoredItem->subscription->session;
+        if(!session)
+            session = &server->adminSession;
+
+        /* Get the node context */
+        void *targetContext = NULL;
+        UA_Server_getNodeContext(server, monitoredItem->monitoredNodeId, &targetContext);
+
+        /* Deregister */
+        server->config.monitoredItemRegisterCallback(server,
+                                                     &session->sessionId, session->sessionHandle,
+                                                     &monitoredItem->monitoredNodeId, targetContext,
+                                                     monitoredItem->attributeId, true);
+    }
+
     /* Remove the monitored item */
     if(monitoredItem->listEntry.le_prev != NULL)
         LIST_REMOVE(monitoredItem, listEntry);

+ 16 - 0
tests/server/check_services_subscriptions.c

@@ -15,6 +15,19 @@ static UA_Server *server = NULL;
 static UA_ServerConfig *config = NULL;
 static UA_Session *session = NULL;
 
+UA_UInt32 monitored = 0; /* Number of active MonitoredItems */
+
+static void
+monitoredRegisterCallback(UA_Server *s,
+                          const UA_NodeId *sessionId, void *sessionContext,
+                          const UA_NodeId *nodeId, void *nodeContext,
+                          const UA_UInt32 attrId, const UA_Boolean removed) {
+    if(!removed)
+        monitored++;
+    else
+        monitored--;
+}
+
 static void
 createSession(void) {
     UA_CreateSessionRequest request;
@@ -27,6 +40,7 @@ createSession(void) {
 
 static void setup(void) {
     config = UA_ServerConfig_new_default();
+    config->monitoredItemRegisterCallback = monitoredRegisterCallback;
     server = UA_Server_new(config);
     UA_Server_run_startup(server);
     createSession();
@@ -36,6 +50,8 @@ static void teardown(void) {
     UA_Server_run_shutdown(server);
     UA_Server_delete(server);
     UA_ServerConfig_delete(config);
+
+    ck_assert_uint_eq(monitored, 0); /* All MonitoredItems have been de-registered */
 }
 
 #ifdef UA_ENABLE_SUBSCRIPTIONS