New APIs : hasAttribute, numberOfAttributes, erase in OCRepresentation.
[platform/upstream/iotivity.git] / examples / simpleserver.cpp
index 0209bac..5afc83a 100644 (file)
@@ -1,6 +1,6 @@
 //******************************************************************
 //
-// Copyright 2014 Intel Corporation All Rights Reserved.
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 //
@@ -35,6 +35,11 @@ using namespace std;
 
 int gObservation = 0;
 
+// Specifies where to notify all observers or list of observers
+// 0 - notifies all observers
+// 1 - notifies list of observers
+int isListOfObservers = 0;
+
 // Forward declaring the entityHandler
 void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
 
@@ -45,13 +50,24 @@ class LightResource
 {
 public:
     /// Access this property from a TB client
+    std::string m_name;
     bool m_state;
     int m_power;
+    std::string m_lightUri;
     OCResourceHandle m_resourceHandle;
+    OCRepresentation m_lightRep;
+    ObservationIds m_interestedObservers;
 
 public:
     /// Constructor
-    LightResource(): m_state(false), m_power(0){}
+    LightResource(): m_name("John's light"), m_state(false), m_power(0), m_lightUri("/a/light") {
+        // Initialize representation
+        m_lightRep.setUri(m_lightUri);
+
+        m_lightRep.setValue("state", m_state);
+        m_lightRep.setValue("power", m_power);
+        m_lightRep.setValue("name", m_name);
+    }
 
     /* Note that this does not need to be a member function: for classes you do not have
     access to, you can accomplish this with a free function: */
@@ -59,9 +75,9 @@ public:
     /// This function internally calls registerResource API.
     void createResource(OC::OCPlatform& platform)
     {
-        std::string resourceURI = "/a/light"; // URI of the resource
+        std::string resourceURI = m_lightUri; // URI of the resource
         std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
-        std::string resourceInterface = PARAMETER_INTERFACE; // resource interface.
+        std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
 
         // OCResourceProperty is defined ocstack.h
         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
@@ -82,33 +98,46 @@ public:
         return m_resourceHandle;
     }
 
-    void setRepresentation(AttributeMap& attributeMap)
+    // Puts representation.
+    // Gets values from the representation and
+    // updates the internal state
+    void put(OCRepresentation& rep)
     {
-        cout << "\t\t\t" << "Received representation: " << endl;
-        cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl;
-        cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
-
-        m_state = attributeMap["state"][0].compare("true") == 0;
-        m_power = std::stoi(attributeMap["power"][0]);
-    }
+        try {
+            if (rep.getValue("state", m_state))
+            {
+                cout << "\t\t\t\t" << "state: " << m_state << endl;
+            }
+            else
+            {
+                cout << "\t\t\t\t" << "state not found in the representation" << endl;
+            }
 
-    void getRepresentation(AttributeMap& attributeMap)
-    {
-        AttributeValues stateVal;
-        if(m_state)
-        {
-            stateVal.push_back("true");
+            if (rep.getValue("power", m_power))
+            {
+                cout << "\t\t\t\t" << "power: " << m_power << endl;
+            }
+            else
+            {
+                cout << "\t\t\t\t" << "power not found in the representation" << endl;
+            }
         }
-        else
+        catch (exception& e)
         {
-            stateVal.push_back("false");
+            cout << e.what() << endl;
         }
 
-        AttributeValues powerVal;
-        powerVal.push_back(to_string(m_power));
+    }
+
+    // gets the updated representation.
+    // Updates the representation with latest internal state before
+    // sending out.
+    OCRepresentation get()
+    {
+        m_lightRep.setValue("state", m_state);
+        m_lightRep.setValue("power", m_power);
 
-        attributeMap["state"] = stateVal;
-        attributeMap["power"] = powerVal;
+        return m_lightRep;
     }
 
     void addType(const OC::OCPlatform& platform, const std::string& type) const
@@ -131,7 +160,7 @@ public:
 };
 
 // Create the instance of the resource class (in this case instance of class 'LightResource').
-LightResource myLightResource;
+LightResource myLight;
 
 // ChangeLightRepresentaion is an observation function,
 // which notifies any changes to the resource to stack
@@ -149,12 +178,28 @@ void * ChangeLightRepresentation (void *param)
             // we call notifyObservors
             //
             // For demostration we are changing the power value and notifying.
-            myLightResource.m_power += 10;
+            myLight.m_power += 10;
 
-            cout << "\nPower updated to : " << myLightResource.m_power << endl;
-            cout << "Notifying observers with resource handle: " << myLightResource.getHandle() << endl;
+            cout << "\nPower updated to : " << myLight.m_power << endl;
+            cout << "Notifying observers with resource handle: " << myLight.getHandle() << endl;
 
-            OCStackResult result = OCPlatform::notifyObservers(myLightResource.getHandle());
+            OCStackResult result = OC_STACK_OK;
+
+            if(isListOfObservers)
+            {
+                std::shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
+
+                resourceResponse->setErrorCode(200);
+                resourceResponse->setResourceRepresentation(myLight.get(), DEFAULT_INTERFACE);
+
+                result = OCPlatform::notifyListOfObservers(  myLight.getHandle(),
+                                                             myLight.m_interestedObservers,
+                                                             resourceResponse);
+            }
+            else
+            {
+                result = OCPlatform::notifyAllObservers(myLight.getHandle());
+            }
 
             if(OC_STACK_NO_OBSERVERS == result)
             {
@@ -167,7 +212,6 @@ void * ChangeLightRepresentation (void *param)
     return NULL;
 }
 
-
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
 void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
@@ -178,15 +222,15 @@ void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<O
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if(requestFlag == RequestHandlerFlag::InitFlag)
+        if(requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
 
             // entity handler to perform resource initialization operations
         }
-        else if(requestFlag == RequestHandlerFlag::RequestFlag)
+        if(requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
 
@@ -195,46 +239,33 @@ void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<O
             {
                 cout << "\t\t\trequestType : GET\n";
 
-                // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
-                // Process query params and do required operations ..
-
-                // Get the representation of this resource at this point and send it as response
-                AttributeMap attributeMap;
-
-                myLightResource.getRepresentation(attributeMap);
-
                 if(response)
                 {
                     // TODO Error Code
                     response->setErrorCode(200);
-                    response->setResourceRepresentation(attributeMap);
+
+                    response->setResourceRepresentation(myLight.get());
                 }
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
 
-                // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
-                // Check queryParamsMap and do required operations ..
-
-                // Get the representation from the request
-                AttributeMap attributeMap = request->getResourceRepresentation();
-
-                myLightResource.setRepresentation(attributeMap);
+                OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to PUT request
 
-                myLightResource.getRepresentation(attributeMap);
+                // Update the lightResource
+                myLight.put(rep);
 
                 if(response)
                 {
+                    // TODO Error Code
                     response->setErrorCode(200);
-                    response->setResourceRepresentation(attributeMap);
+
+                    response->setResourceRepresentation(myLight.get());
                 }
+
             }
             else if(requestType == "POST")
             {
@@ -245,8 +276,22 @@ void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<O
                 // DELETE request operations
             }
         }
-        else if(requestFlag == RequestHandlerFlag::ObserverFlag)
+        if(requestFlag & RequestHandlerFlag::ObserverFlag)
         {
+            ObservationInfo observationInfo = request->getObservationInfo();
+            if(ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                myLight.m_interestedObservers.push_back(observationInfo.obsId);
+            }
+            else if(ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                myLight.m_interestedObservers.erase(std::remove(
+                                                            myLight.m_interestedObservers.begin(),
+                                                            myLight.m_interestedObservers.end(),
+                                                            observationInfo.obsId),
+                                                            myLight.m_interestedObservers.end());
+            }
+
             pthread_t threadId;
 
             cout << "\t\trequestFlag : Observer\n";
@@ -261,7 +306,6 @@ void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<O
                 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
                 startedThread = 1;
             }
-
         }
     }
     else
@@ -270,15 +314,44 @@ void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<O
     }
 }
 
-int main()
+void PrintUsage()
 {
-    // Create PlatformConfig object
+    std::cout << std::endl;
+    std::cout << "Usage : simplserver <isListOfObservers>\n";
+    std::cout << "   ObserveType : 0 - Observe All\n";
+    std::cout << "   ObserveType : 1 - Observe List of observers\n\n";
+}
+
 
-    PlatformConfig cfg;
-    cfg.ipAddress = "134.134.161.33";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;
+int main(int argc, char* argv[1])
+{
+    PrintUsage();
+
+    if (argc == 1)
+    {
+        isListOfObservers = 0;
+    }
+    else if (argc == 2)
+    {
+        int value = atoi(argv[1]);
+        if (value == 1)
+            isListOfObservers = 1;
+        else
+            isListOfObservers = 0;
+    }
+    else
+    {
+        return -1;
+    }
+
+    // Create PlatformConfig object
+    PlatformConfig cfg {
+        OC::ServiceType::InProc,
+        OC::ModeType::Server,
+        "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
+        0,         // Uses randomly available port
+        OC::QualityOfService::NonConfirmable
+    };
 
     // Create a OCPlatform instance.
     // Note: Platform creation is synchronous call.
@@ -287,10 +360,10 @@ int main()
         OCPlatform platform(cfg);
 
         // Invoke createResource function of class light.
+        myLight.createResource(platform);
 
-        myLightResource.createResource(platform);
-        myLightResource.addType(platform, std::string("core.brightlight"));
-        myLightResource.addInterface(platform, std::string("oc.mi.ll"));
+        myLight.addType(platform, std::string("core.brightlight"));
+        myLight.addInterface(platform, std::string("oc.mi.ll"));
         // Perform app tasks
         while(true)
         {
@@ -302,7 +375,6 @@ int main()
         //log(e.what());
     }
 
-
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
 }