Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / service / things-manager / sampleapp / linux / groupaction / lightserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 // Copyright 2014 Samsung Electronics All Rights Reserved.
5 //
6 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 //      http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 //
20 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21
22 ///
23 /// This sample provides steps to define an interface for a resource
24 /// (properties and methods) and host this resource on the server.
25 ///
26
27 #include <functional>
28
29 #include <pthread.h>
30 #include <mutex>
31 #include <condition_variable>
32
33 #include "OCPlatform.h"
34 #include "OCApi.h"
35
36 using namespace OC;
37 using namespace std;
38 namespace PH = std::placeholders;
39
40 int gObservation = 0;
41 void * ChangeLightRepresentation(void *param);
42 void * handleSlowResponse(void *param, std::shared_ptr< OCResourceRequest > pRequest);
43
44 // Specifies secure or non-secure
45 // false: non-secure resource
46 // true: secure resource
47 bool isSecure = false;
48
49 /// Specifies whether Entity handler is going to do slow response or not
50 bool isSlowResponse = false;
51
52 // Forward declaring the entityHandler
53
54 /// This class represents a single resource named 'lightResource'. This resource has
55 /// two simple properties named 'state' and 'power'
56
57 class LightResource
58 {
59
60 public:
61     /// Access this property from a TB client
62     std::string m_power;
63     std::string m_lightUri;
64     OCResourceHandle m_resourceHandle;
65     OCRepresentation m_lightRep;
66
67 public:
68     /// Constructor
69     LightResource() :
70             m_power(""), m_lightUri("/a/light"), m_resourceHandle(0)
71     {
72         // Initialize representation
73         m_lightRep.setUri(m_lightUri);
74
75         m_lightRep.setValue("power", m_power);
76     }
77
78     /* Note that this does not need to be a member function: for classes you do not have
79      access to, you can accomplish this with a free function: */
80
81     /// This function internally calls registerResource API.
82     void createResource()
83     {
84         std::string resourceURI = m_lightUri; //URI of the resource
85         std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light
86         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
87
88         EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
89
90         // This will internally create and register the resource.
91         OCStackResult result = OCPlatform::registerResource(m_resourceHandle, resourceURI,
92                 resourceTypeName, resourceInterface, cb, OC_DISCOVERABLE | OC_OBSERVABLE);
93
94         if (OC_STACK_OK != result)
95         {
96             cout << "Resource creation was unsuccessful\n";
97         }
98         else
99         {
100             cout << "Resource URI : " << resourceURI << endl;
101             cout << "\tResource Type Name : " << resourceTypeName << endl;
102             cout << "\tResource Interface : " << DEFAULT_INTERFACE << endl;
103             cout << "\tResource creation is successful with resource handle : " << m_resourceHandle
104                     << endl;
105         }
106     }
107
108     OCResourceHandle getHandle()
109     {
110         return m_resourceHandle;
111     }
112
113     // Puts representation.
114     // Gets values from the representation and
115     // updates the internal state
116     void put(OCRepresentation& rep)
117     {
118         try
119         {
120             if (rep.getValue("power", m_power))
121             {
122                 cout << "\t\t\t\t" << "power: " << m_power << endl;
123             }
124             else
125             {
126                 cout << "\t\t\t\t" << "power not found in the representation" << endl;
127             }
128         }
129         catch (exception& e)
130         {
131             cout << e.what() << endl;
132         }
133
134     }
135
136     // Post representation.
137     // Post can create new resource or simply act like put.
138     // Gets values from the representation and
139     // updates the internal state
140     OCRepresentation post(OCRepresentation& rep)
141     {
142         put(rep);
143         return get();
144     }
145
146     // gets the updated representation.
147     // Updates the representation with latest internal state before
148     // sending out.
149     OCRepresentation get()
150     {
151         m_lightRep.setValue("power", m_power);
152
153         return m_lightRep;
154     }
155
156     void addType(const std::string& type) const
157     {
158         OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type);
159         if (OC_STACK_OK != result)
160         {
161             cout << "Binding TypeName to Resource was unsuccessful\n";
162         }
163     }
164
165     void addInterface(const std::string& interface) const
166     {
167         OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface);
168         if (OC_STACK_OK != result)
169         {
170             cout << "Binding TypeName to Resource was unsuccessful\n";
171         }
172     }
173
174 private:
175 // This is just a sample implementation of entity handler.
176 // Entity handler can be implemented in several ways by the manufacturer
177     OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request)
178     {
179         cout << "\tIn Server CPP entity handler:\n";
180         OCEntityHandlerResult ehResult = OC_EH_ERROR;
181         if (request)
182         {
183             // Get the request type and request flag
184             std::string requestType = request->getRequestType();
185             int requestFlag = request->getRequestHandlerFlag();
186
187             if (requestFlag & RequestHandlerFlag::RequestFlag)
188             {
189                 cout << "\t\trequestFlag : Request\n";
190                 auto pResponse = std::make_shared< OC::OCResourceResponse >();
191                 pResponse->setRequestHandle(request->getRequestHandle());
192                 pResponse->setResourceHandle(request->getResourceHandle());
193
194                 // If the request type is GET
195                 if (requestType == "GET")
196                 {
197                     cout << "\t\t\trequestType : GET\n";
198                     if (isSlowResponse) // Slow response case
199                     {
200                         static int startedThread = 0;
201                         if (!startedThread)
202                         {
203                             std::thread t(handleSlowResponse, (void *) this, request);
204                             startedThread = 1;
205                             t.detach();
206                         }
207                         ehResult = OC_EH_SLOW;
208                     }
209                     else // normal response case.
210                     {
211                         pResponse->setErrorCode(200);
212                         pResponse->setResponseResult(OC_EH_OK);
213                         pResponse->setResourceRepresentation(get());
214                         if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
215                         {
216                             ehResult = OC_EH_OK;
217                         }
218                     }
219                 }
220                 else if (requestType == "PUT")
221                 {
222                     cout << "\t\t\trequestType : PUT\n";
223                     OCRepresentation rep = request->getResourceRepresentation();
224
225                     // Do related operations related to PUT request
226                     // Update the lightResource
227                     put(rep);
228                     pResponse->setErrorCode(200);
229                     pResponse->setResponseResult(OC_EH_OK);
230                     pResponse->setResourceRepresentation(get());
231                     if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
232                     {
233                         ehResult = OC_EH_OK;
234                     }
235                 }
236                 else if (requestType == "POST")
237                 {
238                     cout << "\t\t\trequestType : POST\n";
239
240                     OCRepresentation rep = request->getResourceRepresentation();
241
242                     // Do related operations related to POST request
243                     OCRepresentation rep_post = post(rep);
244                     pResponse->setResourceRepresentation(rep_post);
245                     pResponse->setErrorCode(200);
246                     if (rep_post.hasAttribute("createduri"))
247                     {
248                         pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
249                         pResponse->setNewResourceUri(
250                                 rep_post.getValue< std::string >("createduri"));
251                     }
252
253                     if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
254                     {
255                         ehResult = OC_EH_OK;
256                     }
257                 }
258                 else if (requestType == "DELETE")
259                 {
260                     // DELETE request operations
261                 }
262             }
263         }
264         else
265         {
266             std::cout << "Request invalid" << std::endl;
267         }
268
269         return ehResult;
270     }
271 };
272
273 void * handleSlowResponse(void *param, std::shared_ptr< OCResourceRequest > pRequest)
274 {
275     // This function handles slow response case
276     LightResource* lightPtr = (LightResource*) param;
277     // Induce a case for slow response by using sleep
278     std::cout << "SLOW response" << std::endl;
279     sleep(10);
280
281     auto pResponse = std::make_shared< OC::OCResourceResponse >();
282     pResponse->setRequestHandle(pRequest->getRequestHandle());
283     pResponse->setResourceHandle(pRequest->getResourceHandle());
284     pResponse->setResourceRepresentation(lightPtr->get());
285     pResponse->setErrorCode(200);
286     pResponse->setResponseResult(OC_EH_OK);
287
288     // Set the slow response flag back to false
289     isSlowResponse = false;
290     OCPlatform::sendResponse(pResponse);
291     return NULL;
292 }
293
294 int main()
295 {
296     // Create PlatformConfig object
297     PlatformConfig cfg
298     { OC::ServiceType::InProc, OC::ModeType::Server, "0.0.0.0",
299     // By setting to "0.0.0.0", it binds to all available interfaces
300             0,// Uses randomly available port
301             OC::QualityOfService::LowQos };
302
303     OCPlatform::Configure(cfg);
304     try
305     {
306         // Create the instance of the resource class
307         // (in this case instance of class 'LightResource').
308         LightResource myLight;
309
310         // Invoke createResource function of class light.
311         myLight.createResource();
312
313         // A condition variable will free the mutex it is given, then do a non-
314         // intensive block until 'notify' is called on it.  In this case, since we
315         // don't ever call cv.notify, this should be a non-processor intensive version
316         // of while(true);
317         std::mutex blocker;
318         std::condition_variable cv;
319         std::unique_lock < std::mutex > lock(blocker);
320         cv.wait(lock);
321     }
322     catch (OCException e)
323     {
324         //log(e.what());
325     }
326
327     // No explicit call to stop the platform.
328     // When OCPlatform::destructor is invoked, internally we do platform cleanup
329
330     return 0;
331 }