Updated sample apps to show use of multiple presence RT filters.
authorJoseph Morrow <joseph.l.morrow@intel.com>
Fri, 19 Dec 2014 18:59:12 +0000 (13:59 -0500)
committerJoseph Morrow <joseph.l.morrow@intel.com>
Fri, 19 Dec 2014 19:01:03 +0000 (14:01 -0500)
Updated C sample apps and C++ sample apps to display a simple multi-
resource presence use-case. This shows a few cases which automatically
generate presence notifications.

Change-Id: Id6e5a9de6d7ed06bd3a03291bb0eade74154b7f2
Signed-off-by: Joseph Morrow <joseph.l.morrow@intel.com>
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp
resource/examples/presenceclient.cpp
resource/examples/presenceserver.cpp

index ed5f054..9965a22 100644 (file)
@@ -79,12 +79,17 @@ static void PrintUsage()
 
     #ifdef WITH_PRESENCE
     OC_LOG(INFO, TAG, "-t 12 :  Discover Resources and Initiate Nonconfirmable presence");
-    OC_LOG(INFO, TAG, "-t 13 :  Discover Resources and Initiate Nonconfirmable presence with filter");
+    OC_LOG(INFO, TAG, "-t 13 :  Discover Resources and Initiate Nonconfirmable presence with "\
+            "filter");
+    OC_LOG(INFO, TAG, "-t 14 :  Discover Resources and Initiate Nonconfirmable presence with "\
+            "2 filters");
     #endif
 
-    OC_LOG(INFO, TAG, "-t 14 :  Discover Resources and Initiate Nonconfirmable Observe Requests then cancel immediately");
-    OC_LOG(INFO, TAG, "-t 15 :  Discover Resources and Initiate Nonconfirmable Get Request and add  vendor specific header options");
-    OC_LOG(INFO, TAG, "-t 16  :  Discover Devices");
+    OC_LOG(INFO, TAG, "-t 15 :  Discover Resources and Initiate Nonconfirmable Observe Requests "\
+            "then cancel immediately");
+    OC_LOG(INFO, TAG, "-t 16 :  Discover Resources and Initiate Nonconfirmable Get Request and "\
+            "add  vendor specific header options");
+    OC_LOG(INFO, TAG, "-t 17 :  Discover Devices");
 }
 
 OCStackResult InvokeOCDoResource(std::ostringstream &query,
@@ -327,6 +332,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
             #ifdef WITH_PRESENCE
             case TEST_OBS_PRESENCE:
             case TEST_OBS_PRESENCE_WITH_FILTER:
+            case TEST_OBS_PRESENCE_WITH_FILTERS:
                 InitPresence();
                 break;
             #endif
@@ -367,14 +373,34 @@ OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle,
 #ifdef WITH_PRESENCE
 int InitPresence()
 {
+    OCStackResult result = OC_STACK_OK;
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
     std::ostringstream query;
+    std::ostringstream querySuffix;
     query << "coap://" << coapServerIP << ":" << coapServerPort << OC_PRESENCE_URI;
-    if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTER)
+    if(TEST_CASE == TEST_OBS_PRESENCE)
     {
-        query << "?rt=core.light";
+        result = InvokeOCDoResource(query, OC_REST_PRESENCE, OC_LOW_QOS,
+                presenceCB, NULL, 0);
     }
-    return (InvokeOCDoResource(query, OC_REST_PRESENCE, OC_LOW_QOS, presenceCB, NULL, 0));
+    if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTER || TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS)
+    {
+        querySuffix.str("");
+        querySuffix << query.str() << "?rt=core.light";
+        result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS,
+                presenceCB, NULL, 0);
+    }
+    if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS)
+    {
+        if(result == OC_STACK_OK)
+        {
+            querySuffix.str("");
+            querySuffix << query.str() << "?rt=core.fan";
+            result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS,
+                    presenceCB, NULL, 0);
+        }
+    }
+    return result;
 }
 #endif
 int InitGetRequestToUnavailableResource()
index f106f7b..96444ca 100644 (file)
@@ -55,6 +55,7 @@ typedef enum {
 #ifdef WITH_PRESENCE
     TEST_OBS_PRESENCE,
     TEST_OBS_PRESENCE_WITH_FILTER,
+    TEST_OBS_PRESENCE_WITH_FILTERS,
 #endif
     TEST_OBS_REQ_NON_CANCEL_IMM,
     TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS,
index 0311507..6131cd0 100644 (file)
 
 #include <stdio.h>
 #include <string.h>
+#include <string>
 #include <stdlib.h>
 #include <unistd.h>
 #include <signal.h>
 #include <pthread.h>
+#include <array>
 #include "ocstack.h"
 #include "logger.h"
 #include "cJSON.h"
@@ -50,6 +52,7 @@ Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
 
 #ifdef WITH_PRESENCE
 static int stopPresenceCount = 10;
+#define numPresenceResources (2)
 #endif
 
 //TODO: Follow the pattern used in constructJsonResponse() when the payload is decided.
@@ -480,6 +483,14 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
     return ehResult;
 }
 
+OCEntityHandlerResult
+OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest)
+{
+    // This is callback is associated with the 2 presence notification
+    // resources. They are non-operational.
+    return OC_EH_OK;
+}
 
 OCEntityHandlerResult
 OCEntityHandlerCb (OCEntityHandlerFlag flag,
@@ -685,6 +696,57 @@ void *ChangeLightRepresentation (void *param)
     return NULL;
 }
 
+void *presenceNotificationGenerator(void *param)
+{
+    sleep(5);
+    (void)param;
+    OCDoHandle presenceNotificationHandles[numPresenceResources];
+    OCStackResult res = OC_STACK_OK;
+
+    std::array<std::string, numPresenceResources> presenceNotificationResources { {
+        std::string("core.fan"),
+        std::string("core.led") } };
+    std::array<std::string, numPresenceResources> presenceNotificationUris { {
+        std::string("/a/fan"),
+        std::string("/a/led") } };
+
+    for(int i=0; i<numPresenceResources; i++)
+    {
+        if(res == OC_STACK_OK)
+        {
+            sleep(1);
+            res = OCCreateResource(&presenceNotificationHandles[i],
+                    presenceNotificationResources.at(i).c_str(),
+                    "oc.mi.def",
+                    presenceNotificationUris.at(i).c_str(),
+                    OCNOPEntityHandlerCb,
+                    OC_DISCOVERABLE|OC_OBSERVABLE);
+        }
+        if(res != OC_STACK_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
+                    "%s with result %s.", presenceNotificationResources.at(i).c_str(),
+                    getResult(res));
+            break;
+        }
+    }
+    sleep(5);
+    for(int i=0; i<numPresenceResources; i++)
+    {
+        if(res == OC_STACK_OK)
+        {
+            res = OCDeleteResource(presenceNotificationHandles[i]);
+        }
+        if(res != OC_STACK_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
+                    "resource %s.", presenceNotificationResources.at(i).c_str());
+            break;
+        }
+    }
+    return NULL;
+}
+
 static void PrintUsage()
 {
     OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
@@ -699,6 +761,7 @@ int main(int argc, char* argv[])
     uint16_t port = OC_WELL_KNOWN_PORT;
     uint8_t ifname[] = "eth0";
     pthread_t threadId;
+    pthread_t threadId_presence;
     int opt;
 
     while ((opt = getopt(argc, argv, "o:")) != -1)
@@ -777,6 +840,12 @@ int main(int argc, char* argv[])
      */
     pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
 
+    /*
+     * Create a thread for generating changes that cause presence notifications
+     * to be sent to clients
+     */
+    pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
+
     // Break from loop with Ctrl-C
     OC_LOG(INFO, TAG, "Entering ocserver main loop...");
     DeleteDeviceInfo();
@@ -795,6 +864,8 @@ int main(int argc, char* argv[])
      */
     pthread_cancel(threadId);
     pthread_join(threadId, NULL);
+    pthread_cancel(threadId_presence);
+    pthread_join(threadId_presence, NULL);
 
     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
 
index 6bd79fe..857d0f4 100644 (file)
@@ -41,8 +41,10 @@ static int TEST_CASE = 0;
 typedef enum {
     TEST_UNICAST_PRESENCE_NORMAL = 1,
     TEST_UNICAST_PRESENCE_WITH_FILTER,
+    TEST_UNICAST_PRESENCE_WITH_FILTERS,
     TEST_MULTICAST_PRESENCE_NORMAL,
     TEST_MULTICAST_PRESENCE_WITH_FILTER,
+    TEST_MULTICAST_PRESENCE_WITH_FILTERS,
     MAX_TESTS
 } CLIENT_TEST;
 
@@ -52,9 +54,13 @@ void printUsage()
     std::cout << "-t 1 : Discover Resources and Initiate Unicast Presence" << std::endl;
     std::cout << "-t 2 : Discover Resources and Initiate Unicast Presence with Filter"
               << std::endl;
-    std::cout << "-t 3 : Discover Resources and Initiate Multicast Presence" << std::endl;
-    std::cout << "-t 4 : Discover Resources and Initiate Multicast Presence with Filter"
+    std::cout << "-t 3 : Discover Resources and Initiate Unicast Presence with Two Filters"
+            << std::endl;
+    std::cout << "-t 4 : Discover Resources and Initiate Multicast Presence" << std::endl;
+    std::cout << "-t 5 : Discover Resources and Initiate Multicast Presence with Filter"
               << std::endl;
+    std::cout << "-t 6 : Discover Resources and Initiate Multicast Presence with two Filters"
+                  << std::endl;
 }
 
 // Callback to presence
@@ -123,21 +129,52 @@ void foundResource(std::shared_ptr<OCResource> resource)
 
             if(resourceURI == "/a/light")
             {
+                OCStackResult result = OC_STACK_OK;
                 curResource = resource;
                 OCPlatform::OCPresenceHandle presenceHandle = nullptr;
 
                 if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
                 {
-                    OCPlatform::subscribePresence(presenceHandle, hostAddress,
+                    result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
                             &presenceHandler);
-                    std::cout<< "Subscribed to unicast address:" << hostAddress <<std::endl;
+                    if(result == OC_STACK_OK)
+                    {
+                        std::cout<< "Subscribed to unicast address: " << hostAddress << std::endl;
+                    }
+                    else
+                    {
+                        std::cout<< "Failed to subscribe to unicast address:" << hostAddress
+                                << std::endl;
+                    }
                 }
-                else if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTER)
+                if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTER ||
+                        TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS)
                 {
-                    OCPlatform::subscribePresence(presenceHandle, hostAddress, "core.light",
+                    result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
+                            "core.light", &presenceHandler);
+                    if(result == OC_STACK_OK)
+                    {
+                        std::cout<< "Subscribed to unicast address: " << hostAddress;
+                    }
+                    else
+                    {
+                        std::cout<< "Failed to subscribe to unicast address: " << hostAddress;
+                    }
+                    std::cout << " with resource type \"core.light\"." << std::endl;
+                }
+                if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS)
+                {
+                    result = OCPlatform::subscribePresence(presenceHandle, hostAddress, "core.fan",
                             &presenceHandler);
-                    std::cout<< "Subscribed (with resource type) to unicast address:"
-                                << hostAddress << std::endl;
+                    if(result == OC_STACK_OK)
+                    {
+                        std::cout<< "Subscribed to unicast address: " << hostAddress;
+                    }
+                    else
+                    {
+                        std::cout<< "Failed to subscribe to unicast address: " << hostAddress;
+                    }
+                    std::cout << " with resource type \"core.fan\"." << std::endl;
                 }
             }
         }
@@ -191,23 +228,73 @@ int main(int argc, char* argv[]) {
         std::cout << "Created Platform..."<<std::endl;
 
         OCPlatform::OCPresenceHandle presenceHandle = nullptr;
+        OCStackResult result = OC_STACK_OK;
 
         if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
         {
-            OCPlatform::subscribePresence(presenceHandle, OC_MULTICAST_IP, presenceHandler);
-            std::cout<< "Subscribed to multicast" <<std::endl;
+            result = OCPlatform::subscribePresence(presenceHandle,
+                    OC_MULTICAST_IP, presenceHandler);
+            if(result == OC_STACK_OK)
+            {
+                std::cout << "Subscribed to multicast presence." << std::endl;
+            }
+            else
+            {
+                std::cout << "Failed to subscribe to multicast presence." << std::endl;
+            }
         }
         else if(TEST_CASE == TEST_MULTICAST_PRESENCE_WITH_FILTER)
         {
-            OCPlatform::subscribePresence(presenceHandle, OC_MULTICAST_IP, "core.light",
+            result = OCPlatform::subscribePresence(presenceHandle, OC_MULTICAST_IP, "core.light",
                     &presenceHandler);
-            std::cout<< "Subscribed to multicast with resource type" <<std::endl;
+            if(result == OC_STACK_OK)
+            {
+                std::cout << "Subscribed to multicast presence with resource type";
+            }
+            else
+            {
+                std::cout << "Failed to subscribe to multicast presence with resource type";
+            }
+            std::cout << "\"core.light\"." << std::endl;
+        }
+        else if(TEST_CASE == TEST_MULTICAST_PRESENCE_WITH_FILTERS)
+        {
+            result = OCPlatform::subscribePresence(presenceHandle, OC_MULTICAST_IP, "core.light",
+                    &presenceHandler);
+            if(result == OC_STACK_OK)
+            {
+                std::cout << "Subscribed to multicast presence with resource type";
+            }
+            else
+            {
+                std::cout << "Failed to subscribe to multicast presence with resource type";
+            }
+            std::cout << "\"core.light\"." << std::endl;
+
+            result = OCPlatform::subscribePresence(presenceHandle, OC_MULTICAST_IP, "core.fan",
+                    &presenceHandler);
+            if(result == OC_STACK_OK)
+            {
+                std::cout<< "Subscribed to multicast presence with resource type";
+            }
+            else
+            {
+                std::cout << "Failed to subscribe to multicast presence with resource type.";
+            }
+            std::cout << "\"core.fan\"." << std::endl;
         }
         else
         {
             // Find all resources
-            OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
-            std::cout<< "Finding Resource... " <<std::endl;
+            result = OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
+            if(result == OC_STACK_OK)
+            {
+                std::cout << "Finding Resource... " << std::endl;
+            }
+            else
+            {
+                std::cout << "Failed to request to find resource(s)." << std::endl;
+            }
         }
         //
         // A condition variable will free the mutex it is given, then do a non-
index 63d63da..18e0d7e 100644 (file)
@@ -26,6 +26,7 @@
 #include <functional>
 
 #include <pthread.h>
+#include <array>
 #include <mutex>
 #include <condition_variable>
 
@@ -35,6 +36,8 @@
 using namespace OC;
 using namespace std;
 
+#define numPresenceResources (2)
+
 // Forward declaring the entityHandler
 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
@@ -149,6 +152,35 @@ public:
 
 };
 
+void createPresenceResources()
+{
+    std::array<std::string, numPresenceResources> resourceURI { {
+        "/a/fan",
+        "/a/led" } };
+    std::array<std::string, numPresenceResources> resourceTypeName { {
+        "core.fan",
+        "core.led" } };
+
+    std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
+    OCResourceHandle handle;
+    // OCResourceProperty is defined ocstack.h
+    uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+    // This will internally create and register the resource.
+    OCStackResult result = OC_STACK_OK;
+    for(int i=0; i<numPresenceResources; i++)
+    {
+        result = OCPlatform::registerResource(handle,
+                resourceURI.at(i), resourceTypeName.at(i), resourceInterface,
+                &entityHandler, resourceProperty);
+        if (result != OC_STACK_OK)
+        {
+            cout << "Resource creation was unsuccessful with resource URI "
+                    << resourceURI.at(i);
+        }
+    }
+}
+
 // Create the instance of the resource class (in this case instance of class 'LightResource').
 LightResource myLightResource;
 
@@ -178,8 +210,9 @@ int main()
 
         // Invoke createResource function of class light.
         myLightResource.createResource();
+        printf("Created first resource of type \"core.light\"");
 
-        printf("\nEnter a key to create the second resource\n");
+        printf("\nEnter a key to create the second resource of type \"core.light\"\n");
         getchar();
 
         myLightResource.createResource2();
@@ -193,11 +226,16 @@ int main()
 
         startPresence(30);
 
-        printf("\nEnter a key to create the third resource\n");
+        printf("\nEnter a key to create the third resource of type \"core.light\"\n");
         getchar();
 
         myLightResource.createResource3();
 
+        printf("\nEnter a key to create two non-operational resources.\"\n");
+        getchar();
+
+        createPresenceResources();
+
         // A condition variable will free the mutex it is given, then do a non-
         // intensive block until 'notify' is called on it.  In this case, since we
         // don't ever call cv.notify, this should be a non-processor intensive version