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