7768b3f3d6b3bf5e64e7404a2b7054d372df7967
[platform/upstream/iotivity.git] / resource / examples / roomserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 ///
22 /// This sample shows how one could create a resource (collection) with children.
23 ///
24
25 #include <functional>
26
27 #include <mutex>
28 #include <condition_variable>
29
30 #include "OCPlatform.h"
31 #include "OCApi.h"
32
33 using namespace OC;
34 using namespace std;
35
36
37 // Forward declaring the entityHandler (room)
38 OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request);
39 OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request);
40 OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request);
41
42 /// Specifies whether default collection entity handler is used or not
43 bool useDefaultCollectionEH = false;
44
45 class RoomResource
46 {
47 public:
48
49     // Room members
50     std::string m_roomUri;
51     std::string m_roomName;
52     std::vector<std::string> m_roomTypes;
53     std::vector<std::string> m_roomInterfaces;
54     OCResourceHandle m_roomHandle;
55     OCRepresentation m_roomRep;
56
57     // light members
58     bool m_lightState;
59     int m_lightColor;
60     std::string m_lightUri;
61     std::vector<std::string> m_lightTypes;
62     std::vector<std::string> m_lightInterfaces;
63     OCResourceHandle m_lightHandle;
64     OCRepresentation m_lightRep;
65
66     // fan members
67     bool m_fanState;
68     int m_fanSpeed;
69     std::string m_fanUri;
70     std::vector<std::string> m_fanTypes;
71     std::vector<std::string> m_fanInterfaces;
72     OCResourceHandle m_fanHandle;
73     OCRepresentation m_fanRep;
74
75 public:
76     /// Constructor
77     RoomResource(): m_roomName("John's Room"), m_roomHandle(nullptr), m_lightState(false),
78                     m_lightColor(0),m_lightHandle(nullptr),  m_fanState(false), m_fanSpeed(0),
79                     m_fanHandle(nullptr)
80     {
81         m_lightUri = "/a/light"; // URI of the resource
82         m_lightTypes.push_back("core.light"); // resource type name. In this case, it is light
83         m_lightInterfaces.push_back(DEFAULT_INTERFACE); // resource interface.
84
85         m_lightRep.setUri(m_lightUri);
86         m_lightRep.setResourceTypes(m_lightTypes);
87         m_lightRep.setResourceInterfaces(m_lightInterfaces);
88         m_lightRep.setValue("state", m_lightState);
89         m_lightRep.setValue("color", m_lightColor);
90
91         m_fanUri = "/a/fan"; // URI of the resource
92         m_fanTypes.push_back("core.fan"); // resource type name. In this case, it is light
93         m_fanInterfaces.push_back(DEFAULT_INTERFACE); // resource interface.
94
95         m_fanRep.setUri(m_fanUri);
96         m_fanRep.setResourceTypes(m_fanTypes);
97         m_fanRep.setResourceInterfaces(m_fanInterfaces);
98         m_fanRep.setValue("state", m_fanState);
99         m_fanRep.setValue("speed", m_fanSpeed);
100
101         m_roomUri = "/a/room"; // URI of the resource
102         m_roomTypes.push_back("core.room"); // resource type name. In this case, it is light
103         m_roomInterfaces.push_back(DEFAULT_INTERFACE); // resource interface.
104         m_roomInterfaces.push_back(BATCH_INTERFACE); // resource interface.
105         m_roomInterfaces.push_back(LINK_INTERFACE); // resource interface.
106         m_roomRep.setValue("name", m_roomName);
107         m_roomRep.setUri(m_roomUri);
108         m_roomRep.setResourceTypes(m_roomTypes);
109         m_roomRep.setResourceInterfaces(m_roomInterfaces);
110     }
111
112     /// This function internally calls registerResource API.
113     void createResources()
114     {
115         // This function internally creates and registers the resource.
116         using namespace OC::OCPlatform;
117         OCStackResult result = OC_STACK_ERROR;
118
119         // Based on the case, we will use default collection EH (by passing NULL in entity handler
120         // parameter) or use application entity handler.
121         if(useDefaultCollectionEH)
122         {
123             result = registerResource(
124                                     m_roomHandle, m_roomUri, m_roomTypes[0],
125                                     m_roomInterfaces[0], NULL,
126                                     OC_DISCOVERABLE | OC_OBSERVABLE);
127         }
128         else
129         {
130             result = registerResource(
131                                     m_roomHandle, m_roomUri, m_roomTypes[0],
132                                     m_roomInterfaces[0], entityHandlerRoom,
133                                     OC_DISCOVERABLE | OC_OBSERVABLE);
134         }
135
136         if (OC_STACK_OK != result)
137         {
138             cout << "Resource creation (room) was unsuccessful\n";
139         }
140
141         result = bindInterfaceToResource(m_roomHandle, m_roomInterfaces[1]);
142         if (OC_STACK_OK != result)
143         {
144             cout << "Binding TypeName to Resource was unsuccessful\n";
145         }
146
147         result = bindInterfaceToResource(m_roomHandle, m_roomInterfaces[2]);
148         if (OC_STACK_OK != result)
149         {
150             cout << "Binding TypeName to Resource was unsuccessful\n";
151         }
152
153         result = registerResource(m_lightHandle, m_lightUri, m_lightTypes[0],
154                                   m_lightInterfaces[0], entityHandlerLight,
155                                   OC_DISCOVERABLE | OC_OBSERVABLE);
156
157         if (OC_STACK_OK != result)
158         {
159             cout << "Resource creation (light) was unsuccessful\n";
160         }
161
162         result = registerResource(m_fanHandle, m_fanUri, m_fanTypes[0],
163                                   m_fanInterfaces[0], entityHandlerFan,
164                                   OC_DISCOVERABLE | OC_OBSERVABLE);
165
166         if (OC_STACK_OK != result)
167         {
168             cout << "Resource creation (fan) was unsuccessful\n";
169         }
170
171         result = bindResource(m_roomHandle, m_lightHandle);
172         if (OC_STACK_OK != result)
173         {
174             cout << "Binding fan resource to room was unsuccessful\n";
175         }
176
177         result = bindResource(m_roomHandle, m_fanHandle);
178         if (OC_STACK_OK != result)
179         {
180             cout << "Binding light resource to room was unsuccessful\n";
181         }
182
183     }
184
185     void setLightRepresentation(OCRepresentation& rep)
186     {
187         bool tempState = false;
188         int tempColor = 0;
189
190         // If both entries exist
191         if(rep.getValue("state", tempState) && rep.getValue("color", tempColor))
192         {
193             m_lightState = tempState;
194             m_lightColor= tempColor;
195
196             cout << "\t\t\t\t" << "state: " << m_lightState << endl;
197             cout << "\t\t\t\t" << "color: " << m_lightColor << endl;
198         }
199     }
200
201     void setFanRepresentation(OCRepresentation& rep)
202     {
203         bool tempState = false;
204         int tempSpeed = 0;
205
206         // If both entries exist
207         if(rep.getValue("state", tempState) && rep.getValue("speed", tempSpeed))
208         {
209             m_fanState = tempState;
210             m_fanSpeed = tempSpeed;
211
212             cout << "\t\t\t\t" << "state: " << m_fanState << endl;
213             cout << "\t\t\t\t" << "speed: " << m_fanSpeed << endl;
214         }
215     }
216
217
218     OCRepresentation getLightRepresentation()
219     {
220         m_lightRep.setValue("state", m_lightState);
221         m_lightRep.setValue("color", m_lightColor);
222
223         return m_lightRep;
224     }
225
226     OCRepresentation getFanRepresentation()
227     {
228         m_fanRep.setValue("state", m_fanState);
229         m_fanRep.setValue("speed", m_fanSpeed);
230         return m_fanRep;
231     }
232
233     OCRepresentation getRoomRepresentation(void)
234     {
235         m_roomRep.clearChildren();
236
237         m_roomRep.addChild(getLightRepresentation());
238         m_roomRep.addChild(getFanRepresentation());
239         return m_roomRep;
240     }
241
242 };
243
244 // Create the instance of the resource class (in this case instance of class 'RoomResource').
245 RoomResource myRoomResource;
246
247 OCStackResult sendRoomResponse(std::shared_ptr<OCResourceRequest> pRequest)
248 {
249     auto pResponse = std::make_shared<OC::OCResourceResponse>();
250     pResponse->setRequestHandle(pRequest->getRequestHandle());
251     pResponse->setResourceHandle(pRequest->getResourceHandle());
252
253     // Check for query params (if any)
254     QueryParamsMap queryParamsMap = pRequest->getQueryParameters();
255
256     cout << "\t\t\tquery params: \n";
257     for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
258     {
259         cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
260     }
261
262     OCRepresentation rep;
263     rep = myRoomResource.getRoomRepresentation();
264
265     auto findRes = queryParamsMap.find("if");
266
267     if(findRes != queryParamsMap.end())
268     {
269         pResponse->setResourceRepresentation(rep, findRes->second);
270     }
271     else
272     {
273         pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
274     }
275
276     pResponse->setErrorCode(200);
277     pResponse->setResponseResult(OC_EH_OK);
278
279     return OCPlatform::sendResponse(pResponse);
280 }
281
282 // This function prepares a response for any incoming request to Light resource.
283 bool prepareLightResponse(std::shared_ptr<OCResourceRequest> request)
284 {
285     cout << "\tIn Server CPP (Light) prepareLightResponse:\n";
286     bool result = false;
287     if(request)
288     {
289         // Get the request type and request flag
290         std::string requestType = request->getRequestType();
291         int requestFlag = request->getRequestHandlerFlag();
292
293         if(requestFlag == RequestHandlerFlag::RequestFlag)
294         {
295             cout << "\t\trequestFlag : Request\n";
296
297             // If the request type is GET
298             if(requestType == "GET")
299             {
300                 cout << "\t\t\trequestType : GET\n";
301                 // GET operations are directly handled while sending the response
302                 // in the sendLightResponse function
303                 result = true;
304             }
305             else if(requestType == "PUT")
306             {
307                 cout << "\t\t\trequestType : PUT\n";
308                 OCRepresentation rep = request->getResourceRepresentation();
309
310                 // Do related operations related to PUT request
311                 myRoomResource.setLightRepresentation(rep);
312                 result= true;
313             }
314             else if(requestType == "POST")
315             {
316                 // POST request operations
317             }
318             else if(requestType == "DELETE")
319             {
320                 // DELETE request operations
321             }
322         }
323         else if(requestFlag == RequestHandlerFlag::ObserverFlag)
324         {
325             cout << "\t\trequestFlag : Observer\n";
326         }
327     }
328     else
329     {
330         std::cout << "Request invalid" << std::endl;
331     }
332
333     return result;
334 }
335
336 // This function prepares a response for any incoming request to Fan resource.
337 bool prepareFanResponse(std::shared_ptr<OCResourceRequest> request)
338 {
339     cout << "\tIn Server CPP (Fan) prepareFanResponse:\n";
340     bool result = false;
341
342     if(request)
343     {
344         // Get the request type and request flag
345         std::string requestType = request->getRequestType();
346         int requestFlag = request->getRequestHandlerFlag();
347
348         if(requestFlag == RequestHandlerFlag::RequestFlag)
349         {
350             cout << "\t\trequestFlag : Request\n";
351
352             // If the request type is GET
353             if(requestType == "GET")
354             {
355                 cout << "\t\t\trequestType : GET\n";
356                 // GET operations are directly handled while sending the response
357                 // in the sendLightResponse function
358                 result = true;
359             }
360             else if(requestType == "PUT")
361             {
362                 cout << "\t\t\trequestType : PUT\n";
363
364                 OCRepresentation rep = request->getResourceRepresentation();
365
366                 // Do related operations related to PUT request
367                 myRoomResource.setFanRepresentation(rep);
368                 result = true;
369             }
370             else if(requestType == "POST")
371             {
372                 // POST request operations
373             }
374             else if(requestType == "DELETE")
375             {
376                 // DELETE request operations
377             }
378         }
379         else if(requestFlag == RequestHandlerFlag::ObserverFlag)
380         {
381             cout << "\t\trequestFlag : Observer\n";
382         }
383     }
384     else
385     {
386         std::cout << "Request invalid" << std::endl;
387     }
388
389     return result;
390 }
391
392 OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request)
393 {
394     cout << "\tIn Server CPP entity handler:\n";
395     OCEntityHandlerResult ehResult = OC_EH_ERROR;
396
397     if(request)
398     {
399         // Get the request type and request flag
400         std::string requestType = request->getRequestType();
401         int requestFlag = request->getRequestHandlerFlag();
402
403         if(requestFlag == RequestHandlerFlag::RequestFlag)
404         {
405             cout << "\t\trequestFlag : Request\n";
406
407             // If the request type is GET
408             if(requestType == "GET")
409             {
410                 cout << "\t\t\trequestType : GET\n";
411                 if(OC_STACK_OK == sendRoomResponse(request))
412                 {
413                     ehResult = OC_EH_OK;
414                 }
415             }
416             else if(requestType == "PUT")
417             {
418                 cout << "\t\t\trequestType : PUT\n";
419                 // Call these functions to prepare the response for child resources and
420                 // then send the final response using sendRoomResponse function
421                 prepareLightResponse(request);
422                 prepareFanResponse(request);
423                 if(OC_STACK_OK == sendRoomResponse(request))
424                 {
425                     ehResult = OC_EH_OK;
426                 }
427             }
428             else if(requestType == "POST")
429             {
430                 // POST request operations
431             }
432             else if(requestType == "DELETE")
433             {
434                 // DELETE request operations
435             }
436         }
437         else if(requestFlag == RequestHandlerFlag::ObserverFlag)
438         {
439             cout << "\t\trequestFlag : Observer\n";
440         }
441     }
442     else
443     {
444         std::cout << "Request invalid" << std::endl;
445     }
446
447     return ehResult;
448 }
449
450 OCStackResult sendLightResponse(std::shared_ptr<OCResourceRequest> pRequest)
451 {
452     auto pResponse = std::make_shared<OC::OCResourceResponse>();
453     pResponse->setRequestHandle(pRequest->getRequestHandle());
454     pResponse->setResourceHandle(pRequest->getResourceHandle());
455     pResponse->setResourceRepresentation(myRoomResource.getLightRepresentation());
456     pResponse->setErrorCode(200);
457     pResponse->setResponseResult(OC_EH_OK);
458
459     return OCPlatform::sendResponse(pResponse);
460 }
461
462
463
464 OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request)
465 {
466     cout << "\tIn Server CPP (Light) entity handler:\n";
467     OCEntityHandlerResult ehResult = OC_EH_ERROR;
468
469     if(prepareLightResponse(request))
470     {
471         if(OC_STACK_OK == sendLightResponse(request))
472         {
473             ehResult = OC_EH_OK;
474         }
475         else
476         {
477             std::cout << "sendLightResponse failed." << std::endl;
478         }
479     }
480     else
481     {
482         std::cout << "PrepareLightResponse failed." << std::endl;
483     }
484     return ehResult;
485 }
486
487 OCStackResult sendFanResponse(std::shared_ptr<OCResourceRequest> pRequest)
488 {
489     auto pResponse = std::make_shared<OC::OCResourceResponse>();
490     pResponse->setRequestHandle(pRequest->getRequestHandle());
491     pResponse->setResourceHandle(pRequest->getResourceHandle());
492     pResponse->setResourceRepresentation(myRoomResource.getFanRepresentation());
493     pResponse->setErrorCode(200);
494     pResponse->setResponseResult(OC_EH_OK);
495
496     return OCPlatform::sendResponse(pResponse);
497 }
498
499
500 OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request)
501 {
502     cout << "\tIn Server CPP (Fan) entity handler:\n";
503     OCEntityHandlerResult ehResult = OC_EH_ERROR;
504     if(prepareFanResponse(request))
505     {
506         if(OC_STACK_OK == sendFanResponse(request))
507         {
508             ehResult = OC_EH_OK;
509         }
510         else
511         {
512             std::cout << "sendFanResponse failed." << std::endl;
513         }
514     }
515     else
516     {
517         std::cout << "PrepareFanResponse failed." << std::endl;
518     }
519
520     return ehResult;
521 }
522
523 void printUsage()
524 {
525     std::cout << std::endl;
526     std::cout << "Usage : roomserver <value>\n";
527     std::cout << "1 : Create room resource with default collection entity handler.\n";
528     std::cout << "2 : Create room resource with application collection entity handler.\n";
529 }
530
531 int main(int argc, char* argv[])
532 {
533     printUsage();
534
535     if(argc == 2)
536     {
537         int value = atoi(argv[1]);
538         switch (value)
539         {
540             case 1:
541                 useDefaultCollectionEH = true;
542                 break;
543             case 2:
544             default:
545                 break;
546        }
547     }
548     else
549     {
550         return -1;
551     }
552
553     // Create PlatformConfig object
554     PlatformConfig cfg {
555         OC::ServiceType::InProc,
556         OC::ModeType::Server,
557         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
558         0,         // Uses randomly available port
559         OC::QualityOfService::LowQos
560     };
561
562     OCPlatform::Configure(cfg);
563     try
564     {
565
566         myRoomResource.createResources();
567
568         // A condition variable will free the mutex it is given, then do a non-
569         // intensive block until 'notify' is called on it.  In this case, since we
570         // don't ever call cv.notify, this should be a non-processor intensive version
571         // of while(true);
572         std::mutex blocker;
573         std::condition_variable cv;
574         std::unique_lock<std::mutex> lock(blocker);
575         cv.wait(lock);
576
577     }
578     catch(OCException &e)
579     {
580         std::cout << "Exception in main: " << e.what();
581     }
582
583     // No explicit call to stop the platform.
584     // When OCPlatform destructor is invoked, internally we do platform cleanup
585
586     return 0;
587 }
588