Browse Source

Intermediate commit: Client can create/destroy monitoredItems (including handler function on change). Still missing cyclic publish and sub/mon modification capability.

ichrispa 9 years ago
parent
commit
613116b730
3 changed files with 180 additions and 20 deletions
  1. 16 0
      examples/client.c
  2. 18 12
      include/ua_client.h
  3. 146 8
      src/client/ua_client.c

+ 16 - 0
examples/client.c

@@ -10,6 +10,12 @@
 
 #include <stdio.h>
 
+void handler_TheAnswerChanged(UA_UInt32 handle, UA_DataValue *value);
+void handler_TheAnswerChanged(UA_UInt32 handle, UA_DataValue *value) {
+    printf("Handler called");
+    return;
+}
+
 int main(int argc, char *argv[]) {
     UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout_new());
     UA_StatusCode retval = UA_Client_connect(client, ClientNetworkLayerTCP_connect,
@@ -98,6 +104,16 @@ int main(int argc, char *argv[]) {
     UA_Int32 subId = UA_Client_newSubscription(client);
     if (subId)
         printf("Create subscription succeeded, id %u\n", subId);
+    
+    // Monitor TheAnswer
+    UA_NodeId monitorThis;
+    monitorThis = UA_NODEID_STRING_ALLOC(1, "the.answer");
+    UA_UInt32 monId = UA_Client_monitorItemChanges(client, subId, monitorThis, UA_ATTRIBUTEID_VALUE, &handler_TheAnswerChanged );
+    if (monId)
+        printf("Monitoring 'the.answer', id %u\n", subId);
+    UA_NodeId_deleteMembers(&monitorThis);
+    UA_Client_unMonitorItemChanges(client, subId, monId);
+    
     if(!UA_Client_removeSubscription(client, subId))
         printf("Subscription removed\n");
     

+ 18 - 12
include/ua_client.h

@@ -65,8 +65,7 @@ UA_DeleteReferencesResponse UA_EXPORT
 #ifdef ENABLE_SUBSCRIPTIONS
 
 typedef struct UA_Client_MonitoredItem_s {
-    UA_UInt32          ItemId;
-    UA_UInt32          TimestampsToReturn;
+    UA_UInt32          MonitoredItemId;
     UA_UInt32          MonitoringMode;
     UA_NodeId          monitoredNodeId; 
     UA_UInt32          AttributeID;
@@ -74,6 +73,7 @@ typedef struct UA_Client_MonitoredItem_s {
     UA_UInt32          SamplingInterval;
     UA_UInt32          QueueSize;
     UA_Boolean         DiscardOldest;
+    void               (*handler)(UA_UInt32 handle, UA_DataValue *value);
     LIST_ENTRY(UA_Client_MonitoredItem_s)  listEntry;
 } UA_Client_MonitoredItem;
 
@@ -81,23 +81,29 @@ typedef struct UA_Client_Subscription_s {
     UA_UInt32    LifeTime;
     UA_Int32     KeepAliveCount;
     UA_DateTime  PublishingInterval;
-    UA_Int32     SubscriptionID;
+    UA_UInt32    SubscriptionID;
     UA_Int32     NotificationsPerPublish;
     UA_UInt32    Priority;
-    LIST_ENTRY(UA_Client_Subscription_s) listEntry; //?
-    LIST_HEAD(UA_ListOfUAMonitoredItems, UA_MonitoredItem_s) MonitoredItems;
+    LIST_ENTRY(UA_Client_Subscription_s) listEntry; 
+    LIST_HEAD(UA_ListOfUAMonitoredItems, UA_Client_MonitoredItem_s) MonitoredItems;
 } UA_Client_Subscription;
 
-UA_CreateSubscriptionResponse UA_EXPORT UA_Client_createSubscription(UA_Client *client, UA_CreateSubscriptionRequest *request);
-UA_DeleteSubscriptionsResponse UA_Client_deleteSubscriptions(UA_Client *client, UA_DeleteSubscriptionsRequest *request);
+UA_CreateSubscriptionResponse   UA_Client_createSubscription(UA_Client *client, UA_CreateSubscriptionRequest *request);
+UA_DeleteSubscriptionsResponse  UA_Client_deleteSubscriptions(UA_Client *client, UA_DeleteSubscriptionsRequest *request);
+UA_CreateMonitoredItemsResponse UA_Client_createMonitoredItems(UA_Client *client, UA_CreateMonitoredItemsRequest *request);
+UA_DeleteMonitoredItemsResponse UA_Client_deleteMonitoredItems(UA_Client *client, UA_DeleteMonitoredItemsRequest *request);
 
-UA_Int32 UA_EXPORT UA_Client_newSubscription(UA_Client *client);
-UA_StatusCode UA_EXPORT UA_Client_removeSubscription(UA_Client *client, UA_Int32 subscriptionId);
+UA_Int32      UA_EXPORT UA_Client_newSubscription(UA_Client *client);
+UA_StatusCode UA_EXPORT UA_Client_removeSubscription(UA_Client *client, UA_UInt32 subscriptionId);
+void          UA_EXPORT UA_Client_modifySubscription(UA_Client *client);
+
+UA_UInt32     UA_EXPORT UA_Client_monitorItemChanges(UA_Client *client, UA_UInt32 subscriptionId, 
+                                                     UA_NodeId nodeId, UA_UInt32 attributeID, 
+                                                     void *handlingFunction);
+UA_StatusCode UA_EXPORT UA_Client_unMonitorItemChanges(UA_Client *client, UA_UInt32 subscriptionId, 
+                                                       UA_UInt32 monitoredItemId );
 
-void UA_EXPORT UA_Client_modifySubscription(UA_Client *client);
-void UA_EXPORT UA_Client_addMonitoredItem(UA_Client *client);
 void UA_EXPORT UA_Client_publish(UA_Client *client);
-void UA_EXPORT UA_Client_removeMonitoredItem(UA_Client *client);
 
 
 #endif

+ 146 - 8
src/client/ua_client.c

@@ -18,6 +18,7 @@ struct UA_Client {
     UA_NodeId authenticationToken;
     
 #ifdef ENABLE_SUBSCRIPTIONS
+    UA_Int32 monitoredItemHandles;
     LIST_HEAD(UA_ListOfClientSubscriptionItems, UA_Client_Subscription_s) subscriptions;
 #endif
     
@@ -50,6 +51,7 @@ UA_Client * UA_Client_new(UA_ClientConfig config, UA_Logger logger) {
     client->scExpiresAt = 0;
 
 #ifdef ENABLE_SUBSCRIPTIONS
+    client->monitoredItemHandles = 0;
     LIST_INIT(&client->subscriptions);
 #endif
     return client;
@@ -576,6 +578,20 @@ UA_DeleteSubscriptionsResponse UA_Client_deleteSubscriptions(UA_Client *client,
     return response;
 }
 
+UA_CreateMonitoredItemsResponse UA_Client_createMonitoredItems(UA_Client *client, UA_CreateMonitoredItemsRequest *request) {
+    UA_CreateMonitoredItemsResponse response;
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
+    return response;
+}
+
+UA_DeleteMonitoredItemsResponse UA_Client_deleteMonitoredItems(UA_Client *client, UA_DeleteMonitoredItemsRequest *request) {
+    UA_DeleteMonitoredItemsResponse response;
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
+    return response;
+}
+
 UA_Int32 UA_Client_newSubscription(UA_Client *client) {
     UA_Int32 retval;
     UA_CreateSubscriptionRequest aReq;
@@ -592,7 +608,7 @@ UA_Int32 UA_Client_newSubscription(UA_Client *client) {
     
     aRes = UA_Client_createSubscription(client, &aReq);
     
-    if (!aRes.responseHeader.serviceResult) {
+    if (aRes.responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
         UA_Client_Subscription *newSub = UA_malloc(sizeof(UA_Client_Subscription));
         LIST_INIT(&newSub->MonitoredItems);
         
@@ -614,12 +630,7 @@ UA_Int32 UA_Client_newSubscription(UA_Client *client) {
     return retval;
 }
 
-void UA_Client_modifySubscription(UA_Client *client) {}
-void UA_Client_addMonitoredItem(UA_Client *client) {}
-void UA_Client_publish(UA_Client *client) {}
-void UA_Client_removeMonitoredItem(UA_Client *client) {}
-
-UA_StatusCode UA_Client_removeSubscription(UA_Client *client, UA_Int32 subscriptionId) {
+UA_StatusCode UA_Client_removeSubscription(UA_Client *client, UA_UInt32 subscriptionId) {
     UA_Client_Subscription *sub;
     UA_StatusCode retval;
     
@@ -649,7 +660,7 @@ UA_StatusCode UA_Client_removeSubscription(UA_Client *client, UA_Int32 subscript
     else
         retval = response.responseHeader.serviceResult;
     
-    if (!retval) {
+    if (retval == UA_STATUSCODE_GOOD) {
         LIST_REMOVE(sub, listEntry);
         // FIXME: On the serverside, monitoredItems are deleted along with the
         // subscription... on the clientside not yet.
@@ -659,4 +670,131 @@ UA_StatusCode UA_Client_removeSubscription(UA_Client *client, UA_Int32 subscript
     UA_DeleteSubscriptionsResponse_deleteMembers(&response);
     return retval;
 }
+
+UA_UInt32 UA_Client_monitorItemChanges(UA_Client *client, UA_UInt32 subscriptionId, UA_NodeId nodeId, UA_UInt32 attributeID, void *handlingFunction) {
+    UA_Client_Subscription *sub;
+    UA_StatusCode retval = 0;
+    
+    LIST_FOREACH(sub, &(client->subscriptions), listEntry) {
+        if (sub->SubscriptionID == subscriptionId)
+            break;
+    }
+    
+    // Maybe the same problem as in DeleteSubscription... ask the server?
+    if (sub == NULL)
+        return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+    
+    UA_CreateMonitoredItemsRequest request;
+    UA_CreateMonitoredItemsResponse response;
+    UA_CreateMonitoredItemsRequest_init(&request);
+    UA_CreateMonitoredItemsResponse_init(&response);
+    request.subscriptionId = subscriptionId;
+    request.itemsToCreateSize = 1;
+    request.itemsToCreate = UA_MonitoredItemCreateRequest_new();
+    UA_NodeId_copy(&nodeId, &((request.itemsToCreate[0]).itemToMonitor.nodeId));
+    (request.itemsToCreate[0]).itemToMonitor.attributeId = attributeID;
+    (request.itemsToCreate[0]).monitoringMode = UA_MONITORINGMODE_REPORTING;
+    (request.itemsToCreate[0]).requestedParameters.clientHandle = ++(client->monitoredItemHandles);
+    (request.itemsToCreate[0]).requestedParameters.samplingInterval = sub->PublishingInterval;
+    (request.itemsToCreate[0]).requestedParameters.discardOldest = UA_TRUE;
+    (request.itemsToCreate[0]).requestedParameters.queueSize = 1;
+    // Filter can be left void for now, only changes are supported (UA_Expert does the same with changeItems)
+    
+    response = UA_Client_createMonitoredItems(client, &request);
+    
+    // slight misuse of retval here to check if the deletion was successfull.
+    if (response.resultsSize == 0)
+        retval = response.responseHeader.serviceResult;
+    else
+        retval = response.results[0].statusCode;
+    
+    if (retval == UA_STATUSCODE_GOOD) {
+        UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *) UA_malloc(sizeof(UA_Client_MonitoredItem));
+        newMon->MonitoringMode = UA_MONITORINGMODE_REPORTING;
+        UA_NodeId_copy(&nodeId, &(newMon->monitoredNodeId)); 
+        newMon->AttributeID = attributeID;
+        newMon->ClientHandle = client->monitoredItemHandles;
+        newMon->SamplingInterval = sub->PublishingInterval;
+        newMon->QueueSize = 1;
+        newMon->DiscardOldest = UA_TRUE;
+        newMon->handler = handlingFunction;
+        newMon->MonitoredItemId = response.results[0].monitoredItemId;
+        
+        LIST_INSERT_HEAD(&(sub->MonitoredItems), newMon, listEntry);
+        retval = newMon->MonitoredItemId ;
+    }
+    else {
+        retval = 0;
+    }
+    
+    UA_CreateMonitoredItemsRequest_deleteMembers(&request);
+    UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+    
+    return retval;
+}
+
+UA_StatusCode UA_Client_unMonitorItemChanges(UA_Client *client, UA_UInt32 subscriptionId, UA_UInt32 monitoredItemId ) {
+    UA_Client_Subscription *sub;
+    UA_StatusCode retval = 0;
+    
+    LIST_FOREACH(sub, &(client->subscriptions), listEntry) {
+        if (sub->SubscriptionID == subscriptionId)
+            break;
+    }
+    // Maybe the same problem as in DeleteSubscription... ask the server?
+    if (sub == NULL)
+        return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+    
+    UA_Client_MonitoredItem *mon;
+    LIST_FOREACH(mon, &(sub->MonitoredItems), listEntry) {
+        if (mon->MonitoredItemId == monitoredItemId)
+            break;
+    }
+    // Also... ask the server?
+    if(mon==NULL) {
+        return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+    }
+    
+    UA_DeleteMonitoredItemsRequest request;
+    UA_DeleteMonitoredItemsResponse response;
+    UA_DeleteMonitoredItemsRequest_init(&request);
+    UA_DeleteMonitoredItemsResponse_init(&response);
+    
+    request.subscriptionId = sub->SubscriptionID;
+    request.monitoredItemIdsSize = 1;
+    request.monitoredItemIds = (UA_UInt32 *) UA_malloc(sizeof(UA_UInt32));
+    request.monitoredItemIds[0] = mon->MonitoredItemId;
+    
+    response = UA_Client_deleteMonitoredItems(client, &request);
+    if (response.resultsSize > 1)
+        retval = response.results[0];
+    else
+        retval = response.responseHeader.serviceResult;
+    
+    if (retval == 0) {
+        LIST_REMOVE(mon, listEntry);
+        UA_free(mon);
+    }
+    
+    UA_DeleteMonitoredItemsRequest_deleteMembers(&request);
+    UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+    
+    return retval;
+}
+
+void UA_Client_modifySubscription(UA_Client *client) {}
+
+void UA_Client_publish(UA_Client *client) {
+    UA_PublishRequest request;
+    UA_PublishResponse response;
+    UA_PublishRequest_init(&request);
+    UA_PublishResponse_init(&response);
+    
+    UA_PublishRequest_deleteMembers(&request);
+    UA_PublishResponse_deleteMembers(&response);
+    return;
+}
+
+
+
 #endif