Browse Source

Add callback for subscription inactivity

StalderT 7 years ago
parent
commit
39d12d3451

+ 6 - 0
examples/client_subscription_loop.c

@@ -59,6 +59,11 @@ deleteSubscriptionCallback(UA_Client *client, UA_UInt32 subscriptionId, void *su
     UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "Subscription Id %u was deleted", subscriptionId);
 }
 
+static void
+subscriptionInactivityCallback (UA_Client *client, UA_UInt32 subId, void *subContext) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "Inactivity for subscription %u", subId);
+}
+
 static void
 stateCallback (UA_Client *client, UA_ClientState clientState) {
     switch(clientState) {
@@ -110,6 +115,7 @@ int main(void) {
     UA_ClientConfig config = UA_ClientConfig_default;
     /* Set stateCallback */
     config.stateCallback = stateCallback;
+    config.subscriptionInactivityCallback = subscriptionInactivityCallback;
 
     UA_Client *client = UA_Client_new(config);
 

+ 11 - 0
include/ua_client.h

@@ -63,6 +63,14 @@ typedef struct UA_Client UA_Client;
 
 typedef void (*UA_ClientStateCallback)(UA_Client *client, UA_ClientState clientState);
 
+/**
+ * Subscription Inactivity callback
+ * ------------------------- */
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+typedef void (*UA_SubscriptionInactivityCallback)(UA_Client *client, UA_UInt32 subscriptionId, void *subContext);
+#endif
+
 /**
  * Client Configuration
  * -------------------- */
@@ -81,6 +89,9 @@ typedef struct UA_ClientConfig {
 
     /* Callback function */
     UA_ClientStateCallback stateCallback;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+    UA_SubscriptionInactivityCallback subscriptionInactivityCallback;
+#endif
 
     void *clientContext;
 

+ 2 - 0
plugins/ua_config_default.c

@@ -468,6 +468,8 @@ const UA_ClientConfig UA_ClientConfig_default = {
     NULL, /*.customDataTypes */
 
     NULL, /*.stateCallback */
+    NULL, /*.subscriptionInactivityCallback */
+
     NULL,  /*.clientContext */
 
     10 /* .outStandingPublishRequests */

+ 7 - 1
src/client/ua_client_subscriptions.c

@@ -713,9 +713,15 @@ UA_Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client) {
         UA_DateTime maxSilence = (UA_DateTime)
             ((sub->publishingInterval * sub->maxKeepAliveCount) +
              client->config.timeout) * UA_DATETIME_MSEC;
-        if(maxSilence + sub->lastActivity < UA_DateTime_nowMonotonic())
+        if(maxSilence + sub->lastActivity < UA_DateTime_nowMonotonic()) {
+            /* Reset activity */
+            sub->lastActivity = UA_DateTime_nowMonotonic();
+
+            if (client->config.subscriptionInactivityCallback)
+                client->config.subscriptionInactivityCallback(client, sub->subscriptionId, sub->context);
             UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
                          "Inactivity for Subscription %d.", sub->subscriptionId);
+        }
     }
 }
 

+ 12 - 2
tests/client/check_client_subscriptions.c

@@ -395,10 +395,19 @@ stateCallback (UA_Client *client, UA_ClientState clientState){
     }
 }
 
+static UA_Boolean inactivityCallbackCalled = false;
+
+static void
+subscriptionInactivityCallback (UA_Client *client, UA_UInt32 subId, void *subContext) {
+    inactivityCallbackCalled = true;
+}
+
 START_TEST(Client_subscription_async_sub) {
     UA_ClientConfig clientConfig = UA_ClientConfig_default;
     /* Set stateCallback */
     clientConfig.stateCallback = stateCallback;
+    clientConfig.subscriptionInactivityCallback = subscriptionInactivityCallback;
+    inactivityCallbackCalled = false;
 
     /* Activate background publish request */
     clientConfig.outStandingPublishRequests = 10;
@@ -452,10 +461,11 @@ START_TEST(Client_subscription_async_sub) {
     ck_assert_uint_eq(callbackClientState, UA_CLIENTSTATE_SESSION);
 
     /* Simulate network cable unplugged (no response from server) */
+    ck_assert_uint_eq(inactivityCallbackCalled, false);
     UA_Client_recvTesting_result = UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
     UA_Client_runAsync(client, (UA_UInt16)clientConfig.timeout);
-    ck_assert_uint_eq(notificationReceived, false);
-    ck_assert_uint_eq(callbackClientState, UA_CLIENTSTATE_DISCONNECTED);
+    ck_assert_uint_eq(inactivityCallbackCalled, true);
+    ck_assert_uint_eq(callbackClientState, UA_CLIENTSTATE_SESSION);
 
     UA_Client_delete(client);
 }