Imported Upstream version 1.2.0
[platform/upstream/iotivity.git] / cloud / samples / client / airconditioner / aircon_controlee.cpp
1 #include <memory>
2 #include <iostream>
3 #include <stdexcept>
4 #include <condition_variable>
5 #include <map>
6 #include <vector>
7 #include <string>
8 #include <unistd.h>
9
10 #include "ocstack.h"
11 #include "ocpayload.h"
12 #include "rd_client.h"
13
14 #include <OCApi.h>
15 #include <OCPlatform.h>
16
17 using namespace OC;
18 using namespace std;
19
20 class Resource
21 {
22     public:
23         OCResourceHandle m_handle;
24         Resource(string uri, vector<string> rt, vector<string> itf)
25         {
26             m_representation.setUri(uri);
27             m_representation.setResourceTypes(rt);
28             m_representation.setResourceInterfaces(itf);
29         }
30
31         string getResourceUri()
32         {
33             return m_representation.getUri();
34         }
35
36         vector<string> getResourceType()
37         {
38             return m_representation.getResourceTypes();
39         }
40
41         vector<string> getInterfaces()
42         {
43             return m_representation.getResourceInterfaces();
44         }
45
46         OCRepresentation getRepresentation(void)
47         {
48             m_representation.clearChildren();
49             for (auto it = m_childResources.begin(); it != m_childResources.end(); it++)
50             {
51                 m_representation.addChild((*it)->getRepresentation());
52             }
53             return m_representation;
54         }
55
56         OCStackResult addChildResource(Resource  *childResource)
57         {
58             m_childResources.push_back(childResource);
59             return OCPlatform::bindResource(m_handle, childResource->m_handle);
60         }
61
62         OCStackResult sendRepresentation(shared_ptr<OCResourceRequest> pRequest)
63         {
64             auto pResponse = make_shared<OC::OCResourceResponse>();
65             pResponse->setRequestHandle(pRequest->getRequestHandle());
66             pResponse->setResourceHandle(pRequest->getResourceHandle());
67
68             // Check for query params (if any)
69             QueryParamsMap queryParamsMap = pRequest->getQueryParameters();
70
71             cout << "\t\t\tquery params: \n";
72             for (auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
73             {
74                 cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
75             }
76
77             auto findRes = queryParamsMap.find("if");
78
79             if (findRes != queryParamsMap.end())
80             {
81                 pResponse->setResourceRepresentation(getRepresentation(), findRes->second);
82             }
83             else
84             {
85                 pResponse->setResourceRepresentation(getRepresentation(), DEFAULT_INTERFACE);
86             }
87
88             pResponse->setErrorCode(200);
89             pResponse->setResponseResult(OC_EH_OK);
90
91             return OCPlatform::sendResponse(pResponse);
92         }
93
94         OCStackResult propagate()
95         {
96             if (m_interestedObservers.size() > 0)
97             {
98                 shared_ptr<OCResourceResponse> resourceResponse =
99                 { make_shared<OCResourceResponse>() };
100
101                 resourceResponse->setErrorCode(200);
102                 resourceResponse->setResourceRepresentation(getRepresentation(), DEFAULT_INTERFACE);
103
104                 return OCPlatform::notifyListOfObservers(m_handle,
105                         m_interestedObservers,
106                         resourceResponse);
107             }
108
109             return OC_STACK_OK;
110         }
111
112         virtual OCEntityHandlerResult entityHandler(shared_ptr<OCResourceRequest> request) = 0;
113
114     protected:
115         OCRepresentation    m_representation;
116         vector<Resource *>  m_childResources;
117         ObservationIds      m_interestedObservers;
118 };
119
120 class BinarySwitchResource : public Resource //oic.r.switch.binary
121 {
122     private:
123         bool m_value;
124
125     public:
126         BinarySwitchResource(string uri, vector<string> rt, vector<string> itf)
127             : Resource(uri, rt, itf)
128         {
129             m_value = false;
130             m_representation.setValue("value", m_value);
131         }
132
133         void setBinarySwitchRepresentation(OCRepresentation &rep)
134         {
135             bool value;
136             if (rep.getValue("value", value))
137             {
138                 m_value = value;
139                 m_representation.setValue("value", m_value);
140                 cout << "\t\t\t\t" << "value: " << m_value << endl;
141
142                 propagate();
143             }
144         }
145
146         OCEntityHandlerResult entityHandler(shared_ptr<OCResourceRequest> request)
147         {
148             cout << "\tIn Server Binaryswitch entity handler:\n";
149             OCEntityHandlerResult ehResult = OC_EH_ERROR;
150
151             if (request)
152             {
153                 // Get the request type and request flag
154                 string requestType = request->getRequestType();
155                 int requestFlag = request->getRequestHandlerFlag();
156
157                 if (requestFlag & RequestHandlerFlag::RequestFlag)
158                 {
159                     cout << "\t\trequestFlag : Request\n";
160
161                     // If the request type is GET
162                     if (requestType == "GET")
163                     {
164                         cout << "\t\t\trequestType : GET\n";
165                         if (OC_STACK_OK == sendRepresentation(request))
166                         {
167                             ehResult = OC_EH_OK;
168                         }
169                     }
170                     else if (requestType == "PUT")
171                     {
172                         cout << "\t\t\trequestType : PUT\n";
173                         // PUT request operations
174                     }
175                     else if (requestType == "POST")
176                     {
177                         cout << "\t\t\trequestType : POST\n";
178                         // POST request operations
179                         OCRepresentation    rep = request->getResourceRepresentation();
180                         setBinarySwitchRepresentation(rep);
181
182                         if (OC_STACK_OK == sendRepresentation(request))
183                         {
184                             ehResult = OC_EH_OK;
185                         }
186                     }
187                     else if (requestType == "DELETE")
188                     {
189                         cout << "\t\t\trequestType : DELETE\n";
190                         // DELETE request operations
191                     }
192                 }
193
194                 if (requestFlag & RequestHandlerFlag::ObserverFlag)
195                 {
196                     cout << "\t\trequestFlag : Observer\n";
197
198                     ObservationInfo observationInfo = request->getObservationInfo();
199                     if (ObserveAction::ObserveRegister == observationInfo.action)
200                     {
201                         m_interestedObservers.push_back(observationInfo.obsId);
202                     }
203                     else if (ObserveAction::ObserveUnregister == observationInfo.action)
204                     {
205                         m_interestedObservers.erase(remove(
206                                                         m_interestedObservers.begin(),
207                                                         m_interestedObservers.end(),
208                                                         observationInfo.obsId),
209                                                     m_interestedObservers.end());
210                     }
211                 }
212             }
213             else
214             {
215                 cout << "Request invalid" << endl;
216             }
217
218             return ehResult;
219         }
220 };
221
222 class TemperatureResource : public Resource //oic.r.temperature
223 {
224     private:
225         int m_temperature;
226         string m_range;
227         string m_units;
228
229     public:
230         TemperatureResource(string uri, vector<string> rt, vector<string> itf)
231             : Resource(uri, rt, itf)
232         {
233             m_temperature = 0;
234             m_range = "";
235             m_units = "";
236             m_representation.setValue("temperature", m_temperature);
237             m_representation.setValue("range", m_range);
238             m_representation.setValue("units", m_units);
239         }
240
241         void setTemperatureRepresentation(OCRepresentation &rep)
242         {
243             int temperature;
244             string range;
245             int units;
246
247             if (rep.getValue("temperature", temperature) &&
248                 rep.getValue("range", range) &&
249                 rep.getValue("units", units))
250             {
251                 m_temperature = temperature;
252                 m_range = range;
253                 m_units = units;
254                 m_representation.setValue("temperature", m_temperature);
255                 m_representation.setValue("range", m_range);
256                 m_representation.setValue("units", m_units);
257                 cout << "\t\t\t\t" << "temperature: " << m_temperature << endl;
258                 cout << "\t\t\t\t" << "range: " << m_range << endl;
259                 cout << "\t\t\t\t" << "units: " << m_units << endl;
260
261                 propagate();
262             }
263         }
264
265         OCEntityHandlerResult entityHandler(shared_ptr<OCResourceRequest> request)
266         {
267             cout << "\tIn Server Temperature entity handler:\n";
268             OCEntityHandlerResult ehResult = OC_EH_ERROR;
269
270             if (request)
271             {
272                 // Get the request type and request flag
273                 string requestType = request->getRequestType();
274                 int requestFlag = request->getRequestHandlerFlag();
275
276                 if (requestFlag & RequestHandlerFlag::RequestFlag)
277                 {
278                     cout << "\t\trequestFlag : Request\n";
279
280                     // If the request type is GET
281                     if (requestType == "GET")
282                     {
283                         cout << "\t\t\trequestType : GET\n";
284                         if (OC_STACK_OK == sendRepresentation(request))
285                         {
286                             ehResult = OC_EH_OK;
287                         }
288                     }
289                     else if (requestType == "PUT")
290                     {
291                         cout << "\t\t\trequestType : PUT\n";
292                         // PUT requeist operations
293                     }
294                     else if (requestType == "POST")
295                     {
296                         cout << "\t\t\trequestType : POST\n";
297                         // POST request operations
298                         OCRepresentation    rep = request->getResourceRepresentation();
299                         setTemperatureRepresentation(rep);
300
301                         if (OC_STACK_OK == sendRepresentation(request))
302                         {
303                             ehResult = OC_EH_OK;
304                         }
305                     }
306                     else if (requestType == "DELETE")
307                     {
308                         cout << "\t\t\trequestType : DELETE\n";
309                         // DELETE request operations
310                     }
311                 }
312
313                 if (requestFlag & RequestHandlerFlag::ObserverFlag)
314                 {
315                     cout << "\t\trequestFlag : Observer\n";
316
317                     ObservationInfo observationInfo = request->getObservationInfo();
318                     if (ObserveAction::ObserveRegister == observationInfo.action)
319                     {
320                         m_interestedObservers.push_back(observationInfo.obsId);
321                     }
322                     else if (ObserveAction::ObserveUnregister == observationInfo.action)
323                     {
324                         m_interestedObservers.erase(remove(
325                                                         m_interestedObservers.begin(),
326                                                         m_interestedObservers.end(),
327                                                         observationInfo.obsId),
328                                                     m_interestedObservers.end());
329                     }
330                 }
331             }
332             else
333             {
334                 cout << "Request invalid" << endl;
335             }
336
337             return ehResult;
338         }
339 };
340
341 class AirConditionerResource : public Resource // oic.d.airconditioner
342 {
343     private:
344
345     public:
346         AirConditionerResource(string uri, vector<string> rt, vector<string> itf)
347             : Resource(uri, rt, itf)
348         {
349
350         }
351
352         OCEntityHandlerResult entityHandler(shared_ptr<OCResourceRequest> request)
353         {
354             cout << "\tIn Server Airconditioner entity handler:\n";
355             OCEntityHandlerResult ehResult = OC_EH_ERROR;
356
357             if (request)
358             {
359                 // Get the request type and request flag
360                 string requestType = request->getRequestType();
361                 int requestFlag = request->getRequestHandlerFlag();
362
363                 if (requestFlag & RequestHandlerFlag::RequestFlag)
364                 {
365                     cout << "\t\trequestFlag : Request\n";
366
367                     // If the request type is GET
368                     if (requestType == "GET")
369                     {
370                         cout << "\t\t\trequestType : GET\n";
371                         string findRes = request->getQueryParameters().find("if")->second;
372                         if (findRes.compare(LINK_INTERFACE) == 0)
373                         {
374                             if (OC_STACK_OK == sendRepresentation(request))
375                             {
376                                 ehResult = OC_EH_OK;
377                             }
378                         }
379                         else
380                         {
381                             ehResult = OC_EH_FORBIDDEN;
382                         }
383                     }
384                     else if (requestType == "PUT")
385                     {
386                         cout << "\t\t\trequestType : PUT\n";
387                         // Call these functions to prepare the response for child resources and
388                         // then send the final response using sendRoomResponse function
389
390                         /*
391                         for (auto it = m_childResources.begin();
392                              it != m_childResources.end(); it++)
393                         {
394                             (*it)->entityHandler(request);
395                         }
396
397                         if (OC_STACK_OK == sendRepresentation(request))
398                         {
399                             ehResult = OC_EH_OK;
400                         }
401                         */
402                     }
403                     else if (requestType == "POST")
404                     {
405                         // POST request operations
406                     }
407                     else if (requestType == "DELETE")
408                     {
409                         // DELETE request operations
410                     }
411                 }
412
413                 if (requestFlag & RequestHandlerFlag::ObserverFlag)
414                 {
415                     cout << "\t\trequestFlag : Observer\n";
416                 }
417             }
418             else
419             {
420                 cout << "Request invalid" << endl;
421             }
422
423             return ehResult;
424         }
425 };
426
427 condition_variable g_callbackLock;
428 string             g_uid;
429 string             g_accesstoken;
430
431 void onPublish(const OCRepresentation &, const int &eCode)
432 {
433     cout << "Publish resource response received, code: " << eCode << endl;
434
435     g_callbackLock.notify_all();
436 }
437
438 void printRepresentation(OCRepresentation rep)
439 {
440     for (auto itr = rep.begin(); itr != rep.end(); ++itr)
441     {
442         cout << "\t" << itr->attrname() << ":\t" << itr->getValueToString() << endl;
443         if (itr->type() == AttributeType::Vector)
444         {
445             switch (itr->base_type())
446             {
447                 case AttributeType::OCRepresentation:
448                     for (auto itr2 : (*itr).getValue<vector<OCRepresentation> >())
449                     {
450                         printRepresentation(itr2);
451                     }
452                     break;
453
454                 case AttributeType::Integer:
455                     for (auto itr2 : (*itr).getValue<vector<int> >())
456                     {
457                         cout << "\t\t" << itr2 << endl;
458                     }
459                     break;
460
461                 case AttributeType::String:
462                     for (auto itr2 : (*itr).getValue<vector<string> >())
463                     {
464                         cout << "\t\t" << itr2 << endl;
465                     }
466                     break;
467
468                 default:
469                     cout << "Unhandled base type " << itr->base_type() << endl;
470                     break;
471             }
472         }
473         else if (itr->type() == AttributeType::OCRepresentation)
474         {
475             printRepresentation((*itr).getValue<OCRepresentation>());
476         }
477     }
478 }
479
480 void handleLoginoutCB(const HeaderOptions &,
481                       const OCRepresentation &rep, const int ecode)
482 {
483     cout << "Auth response received code: " << ecode << endl;
484
485     if (rep.getPayload() != NULL)
486     {
487         printRepresentation(rep);
488     }
489
490     if (ecode == 4)
491     {
492         g_accesstoken = rep.getValueToString("accesstoken");
493
494         g_uid = rep.getValueToString("uid");
495     }
496
497     g_callbackLock.notify_all();
498 }
499
500 static FILE *client_open(const char * /*path*/, const char *mode)
501 {
502     return fopen("./aircon_controlee.dat", mode);
503 }
504
505 int main(int argc, char *argv[])
506 {
507     if (argc != 4 && argc != 5)
508     {
509         cout << "Put \"[host-ipaddress:port] [authprovider] [authcode]\" for sign-up and sign-in and publish resources"
510              << endl;
511         cout << "Put \"[host-ipaddress:port] [uid] [accessToken] 1\" for sign-in and publish resources" <<
512              endl;
513         return 0;
514     }
515
516     OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink };
517
518     PlatformConfig cfg
519     {
520         ServiceType::InProc,
521         ModeType::Both,
522         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
523         0,         // Uses randomly available port
524         QualityOfService::LowQos,
525         &ps
526     };
527
528     OCPlatform::Configure(cfg);
529
530     OCStackResult result = OC_STACK_ERROR;
531
532     string host = "coap+tcp://";
533     host += argv[1];
534
535     OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(host,
536                                        CT_ADAPTER_TCP);
537
538     mutex blocker;
539     unique_lock<mutex> lock(blocker);
540
541     if (argc == 5)
542     {
543         accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB);
544         g_callbackLock.wait(lock);
545     }
546     else
547     {
548         accountMgr->signUp(argv[2], argv[3], &handleLoginoutCB);
549         g_callbackLock.wait(lock);
550         accountMgr->signIn(g_uid, g_accesstoken, &handleLoginoutCB);
551         g_callbackLock.wait(lock);
552     }
553
554
555     cout << "Registering resources to platform..." << endl;
556
557     AirConditionerResource  airConditioner("/sec/aircon/0", { "x.com.samsung.da.device" }, { DEFAULT_INTERFACE, BATCH_INTERFACE, LINK_INTERFACE });
558
559     BinarySwitchResource    binarySwitch("/power/0", { "oic.r.switch.binary" }, { DEFAULT_INTERFACE });
560
561     TemperatureResource     temperature("/temperature/0", { "oic.r.temperature" }, { DEFAULT_INTERFACE });
562
563     string uri = airConditioner.getResourceUri();
564     string rt = airConditioner.getResourceType()[0];
565     string itf = airConditioner.getInterfaces()[0];
566
567     result = OCPlatform::registerResource(airConditioner.m_handle,
568                                           uri,
569                                           rt,
570                                           itf,
571                                           bind(&AirConditionerResource::entityHandler
572                                                   , &airConditioner, placeholders::_1),
573                                           OC_DISCOVERABLE);
574
575     if (result != OC_STACK_OK)
576     {
577         cout << "Resource registration was unsuccessful" << endl;
578     }
579
580
581     itf = airConditioner.getInterfaces()[1];
582     result = OCPlatform::bindInterfaceToResource(airConditioner.m_handle, itf);
583
584     if (result != OC_STACK_OK)
585     {
586         cout << "Binding second interface was unsuccessful" << endl;
587     }
588
589
590     itf = airConditioner.getInterfaces()[2];
591     result = OCPlatform::bindInterfaceToResource(airConditioner.m_handle, itf);
592
593     if (result != OC_STACK_OK)
594     {
595         cout << "Binding third interface was unsuccessful" << endl;
596     }
597
598
599     uri = binarySwitch.getResourceUri();
600     rt = binarySwitch.getResourceType()[0];
601     itf = binarySwitch.getInterfaces()[0];
602
603     result = OCPlatform::registerResource(binarySwitch.m_handle,
604                                           uri,
605                                           rt,
606                                           itf,
607                                           bind(&BinarySwitchResource::entityHandler
608                                                   , &binarySwitch, placeholders::_1),
609                                           OC_OBSERVABLE);
610
611     uri = temperature.getResourceUri();
612     rt = temperature.getResourceType()[0];
613     itf = temperature.getInterfaces()[0];
614
615     result = OCPlatform::registerResource(temperature.m_handle,
616                                           uri,
617                                           rt,
618                                           itf,
619                                           bind(&TemperatureResource::entityHandler
620                                                   , &temperature, placeholders::_1),
621                                           OC_OBSERVABLE);
622
623     result = airConditioner.addChildResource(&binarySwitch);
624
625     result = airConditioner.addChildResource(&temperature);
626
627     cout << "Publishing resources to cloud ";
628
629
630     ResourceHandles resourceHandles;
631
632     OCDeviceInfo        devInfoAirConditioner;
633     OCStringLL          deviceType;
634
635     deviceType.value = "oic.d.airconditioner";
636     deviceType.next = NULL;
637     devInfoAirConditioner.deviceName = "FAC_2016";
638     devInfoAirConditioner.types = &deviceType;
639     devInfoAirConditioner.specVersion = NULL;
640     devInfoAirConditioner.dataModelVersions = NULL;
641
642     OCPlatform::registerDeviceInfo(devInfoAirConditioner);
643
644     result = OCPlatform::publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP,
645              resourceHandles,
646              &onPublish);
647
648     cout << " result: " << result << " Waiting Publish default resource response from cloud" << endl;
649
650     resourceHandles.push_back(airConditioner.m_handle);
651
652     result = OCPlatform::publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP,
653              resourceHandles,
654              &onPublish);
655
656     cout << " result: " << result << " Waiting Publish user resource response from cloud" << endl;
657
658     g_callbackLock.wait(lock);
659
660
661     cout << "PUT 1/0 to turn on/off air conditioner for observe testing, q to terminate" << endl;
662
663     string cmd;
664
665     while (true)
666     {
667         cin >> cmd;
668         OCRepresentation    rep;
669
670         switch (cmd[0])
671         {
672             case '1':
673                 rep.setValue(string("value"), true);
674                 binarySwitch.setBinarySwitchRepresentation(rep);
675                 break;
676
677             case '0':
678                 rep.setValue(string("value"), false);
679                 binarySwitch.setBinarySwitchRepresentation(rep);
680                 break;
681
682             case 'q':
683                 goto exit;
684                 break;
685         }
686     }
687
688 exit:
689     return 0;
690 }