Fix cloud client sample build failure
[platform/upstream/iotivity.git] / cloud / samples / client / sample_device.cpp
1 //******************************************************************
2 //
3 // Copyright 2016 Samsung Electronics 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 provides the way to create cloud sample
23 ///
24 #include <memory>
25 #include <iostream>
26 #include <stdexcept>
27 #include <condition_variable>
28 #include <map>
29 #include <vector>
30 #include <string>
31 #include <pthread.h>
32 #include <unistd.h>
33
34 #include "ocstack.h"
35 #include "ocpayload.h"
36
37 #include "cloud_connector.h"
38
39 #define DEFAULT_CONTEXT_VALUE 0x99
40 #define DEFAULT_PUBLISH_QUERY "/oic/rd?rt=oic.wk.rdpub"
41 #define DEFAULT_DISCOVER_QUERY "/oic/res?rt=core.light"
42
43 ////////////////////////////////////////Device Sample
44 #define SAMPLE_MAX_NUM_POST_INSTANCE  2
45 typedef struct LIGHTRESOURCE
46 {
47     OCResourceHandle handle;
48     bool state;
49     int power;
50 } LightResource;
51 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
52
53
54 OCRepPayload *responsePayload(int64_t power, bool state)
55 {
56     OCRepPayload *payload = OCRepPayloadCreate();
57     if (!payload)
58     {
59         std::cout << "Failed to allocate Payload" << std::endl;
60         return nullptr;
61     }
62
63     OCRepPayloadSetPropBool(payload, "state", state);
64     OCRepPayloadSetPropInt(payload, "power", power);
65
66     return payload;
67 }
68
69 OCRepPayload *constructResponse(OCEntityHandlerRequest *ehRequest)
70 {
71     if (ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
72     {
73         std::cout << "Incoming payload not a representation" << std::endl;
74         return nullptr;
75     }
76
77     LightResource *currLightResource = NULL;
78
79     if (ehRequest->resource == gLightInstance[0].handle)
80     {
81         currLightResource = &gLightInstance[0];
82     }
83     else if (ehRequest->resource == gLightInstance[1].handle)
84     {
85         currLightResource = &gLightInstance[1];
86     }
87
88     if (OC_REST_PUT == ehRequest->method)
89     {
90         // Get pointer to query
91         int64_t pow;
92         OCRepPayload *input = reinterpret_cast<OCRepPayload *>(ehRequest->payload);
93
94         if (OCRepPayloadGetPropInt(input, "power", &pow))
95         {
96             currLightResource->power = pow;
97         }
98
99         bool state;
100         if (OCRepPayloadGetPropBool(input, "state", &state))
101         {
102             currLightResource->state = state;
103         }
104     }
105
106     return responsePayload(currLightResource->power, currLightResource->state);
107 }
108
109 OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest,
110                                         OCRepPayload **payload)
111 {
112     OCRepPayload *getResp = constructResponse(ehRequest);
113     if (!getResp)
114     {
115         std::cout << "constructResponse failed" << std::endl;
116         return OC_EH_ERROR;
117     }
118
119     *payload = getResp;
120
121     return OC_EH_OK;
122 }
123
124 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest,
125                                         OCRepPayload **payload)
126 {
127     OCEntityHandlerResult ehResult;
128     OCRepPayload *putResp = constructResponse(ehRequest);
129
130     if (!putResp)
131     {
132         std::cout << "Failed to construct Json response" << std::endl;
133         return OC_EH_ERROR;
134     }
135
136     *payload = putResp;
137     ehResult = OC_EH_OK;
138
139     return ehResult;
140 }
141
142 #define SAMPLE_MAX_NUM_OBSERVATIONS  2
143 static bool observeThreadStarted = false;
144 int gLightUnderObservation = 0;
145 pthread_t threadId_observe;
146 typedef struct
147 {
148     OCObservationId observationId;
149     bool valid;
150     OCResourceHandle resourceHandle;
151 } Observers;
152 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
153
154 void *ChangeLightRepresentation(void *param)
155 {
156     (void)param;
157     OCStackResult result = OC_STACK_ERROR;
158
159     while (true)
160     {
161         sleep(3);
162         gLightInstance[0].power += 1;
163         gLightInstance[1].power += 3;
164
165         if (gLightUnderObservation)
166         {
167             std::cout << " =====> Notifying stack of new power level " << gLightInstance[0].power << std::endl;
168             std::cout << " =====> Notifying stack of new power level " << gLightInstance[1].power << std::endl;
169             // Notifying all observers
170             result = OCNotifyAllObservers(gLightInstance[0].handle, OC_NA_QOS);
171             result = OCNotifyAllObservers(gLightInstance[1].handle, OC_NA_QOS);
172
173             std::cout << " =====> Notifying result " << result << std::endl;
174         }
175     }
176     return NULL;
177 }
178
179 void ProcessObserveRegister(OCEntityHandlerRequest *ehRequest)
180 {
181     std::cout << "Received observation registration request with observation Id " <<
182               ehRequest->obsInfo.obsId << std::endl;
183
184     if (!observeThreadStarted)
185     {
186         pthread_create(&threadId_observe, NULL, ChangeLightRepresentation, (void *)NULL);
187         observeThreadStarted = 1;
188     }
189     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
190     {
191         if (interestedObservers[i].valid == false)
192         {
193             interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
194             interestedObservers[i].valid = true;
195             gLightUnderObservation = 1;
196             break;
197         }
198     }
199 }
200
201 void ProcessObserveDeregister(OCEntityHandlerRequest *ehRequest)
202 {
203     bool clientStillObserving = false;
204
205     std::cout << "Received observation deregistration request for observation Id " <<
206               ehRequest->obsInfo.obsId << std::endl;
207     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
208     {
209         if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
210         {
211             interestedObservers[i].valid = false;
212         }
213         if (interestedObservers[i].valid == true)
214         {
215             // Even if there is one single client observing we continue notifying entity handler
216             clientStillObserving = true;
217         }
218     }
219     if (clientStillObserving == false)
220         gLightUnderObservation = 0;
221 }
222
223 OCEntityHandlerResult
224 OCEntityHandlerCb(OCEntityHandlerFlag flag,
225                   OCEntityHandlerRequest *entityHandlerRequest, void * /*callback*/)
226 {
227     OCEntityHandlerResult ehResult = OC_EH_OK;
228     OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, {}, { 0 }, false };
229
230     // Validate pointer
231     if (!entityHandlerRequest)
232     {
233         std::cout << "Invalid request pointer" << std::endl;
234         return OC_EH_ERROR;
235     }
236
237     // Initialize certain response fields
238     response.numSendVendorSpecificHeaderOptions = 0;
239     memset(response.sendVendorSpecificHeaderOptions,
240            0, sizeof response.sendVendorSpecificHeaderOptions);
241     memset(response.resourceUri, 0, sizeof response.resourceUri);
242     OCRepPayload *payload = nullptr;
243
244     if (flag & OC_REQUEST_FLAG)
245     {
246         std::cout << "Flag includes OC_REQUEST_FLAG" << std::endl;
247
248         if (OC_REST_GET == entityHandlerRequest->method)
249         {
250             std::cout << "Received OC_REST_GET from client" << std::endl;
251             ehResult = ProcessGetRequest(entityHandlerRequest, &payload);
252         }
253         else if (OC_REST_PUT == entityHandlerRequest->method)
254         {
255             std::cout << "Received OC_REST_PUT from client" << std::endl;
256             ehResult = ProcessPutRequest(entityHandlerRequest, &payload);
257         }
258         else
259         {
260             std::cout << "Received unsupported method %d from client " << entityHandlerRequest->method <<
261                       std::endl;
262             ehResult = OC_EH_ERROR;
263         }
264         // If the result isn't an error or forbidden, send response
265         if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
266         {
267             // Format the response.  Note this requires some info about the request
268             response.requestHandle = entityHandlerRequest->requestHandle;
269             response.resourceHandle = entityHandlerRequest->resource;
270             response.ehResult = ehResult;
271             response.payload = reinterpret_cast<OCPayload *>(payload);
272             // Indicate that response is NOT in a persistent buffer
273             response.persistentBufferFlag = 0;
274
275             // Send the response
276             if (OCDoResponse(&response) != OC_STACK_OK)
277             {
278                 std::cout << "Error sending response" << std::endl;
279                 ehResult = OC_EH_ERROR;
280             }
281         }
282     }
283
284     if (flag & OC_OBSERVE_FLAG)
285     {
286         std::cout << "Flag includes OC_OBSERVE_FLAG" << std::endl;
287         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
288         {
289             std::cout << "Received OC_OBSERVE_REGISTER from client" << std::endl;
290             ProcessObserveRegister(entityHandlerRequest);
291         }
292         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
293         {
294             std::cout << "Received OC_OBSERVE_DEREGISTER from client" << std::endl;
295             ProcessObserveDeregister(entityHandlerRequest);
296         }
297     }
298
299     OCPayloadDestroy(response.payload);
300     return ehResult;
301 }
302
303 int createLightResource(char *uri, LightResource *lightResource)
304 {
305     if (!uri)
306     {
307         std::cout << "Resource URI cannot be NULL" << std::endl;
308         return -1;
309     }
310
311     lightResource->state = false;
312     lightResource->power = 0;
313     OCStackResult res = OCCreateResource(&(lightResource->handle),
314                                          "core.light",
315                                          "oc.mi.def",
316                                          uri,
317                                          OCEntityHandlerCb,
318                                          NULL,
319                                          OC_DISCOVERABLE | OC_OBSERVABLE);
320     std::cout << "Created Light resource with result:" << res << std::endl;
321
322     return res;
323 }
324
325 OCStackApplicationResult handlePublishCB(void *ctx,
326         OCDoHandle /*handle*/,
327         OCClientResponse *clientResponse)
328 {
329     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
330     {
331         std::cout << "Invalid Publish callback received" << std::endl;
332     }
333
334     std::cout << "Publish resource response received, code: " << clientResponse->result << std::endl;
335
336     return OC_STACK_KEEP_TRANSACTION;
337 }
338
339 void PublishResources(std::string host, std::string additionalQuery)
340 {
341     std::cout << "Running as Server mode" << std::endl;
342
343     std::string requestQuery = DEFAULT_PUBLISH_QUERY;
344     requestQuery += additionalQuery;
345
346     std::cout << "Publishing resources..." << std::endl;
347     std::cout << host.c_str() << requestQuery.c_str() << std::endl;
348
349     if (createLightResource((char *)"/a/light/0", &gLightInstance[0]) != 0)
350     {
351         std::cout << "Unable to create sample resource" << std::endl;
352     }
353
354     if (createLightResource((char *)"/a/light/1", &gLightInstance[1]) != 0)
355     {
356         std::cout << "Unable to create sample resource" << std::endl;
357     }
358
359     if (OCCloudPublish(host.c_str(), requestQuery.c_str(), &handlePublishCB, 2,
360                        gLightInstance[0].handle, gLightInstance[1].handle) != OC_STACK_OK)
361     {
362         std::cout << "Unable to publish resources to cloud" << std::endl;
363     }
364 }
365
366 ////////////////////////////////////////Client Sample
367 std::string g_host = "coap+tcp://";
368
369 void PrintRepresentation(OCRepPayloadValue *val)
370 {
371     while (val)
372     {
373         std::cout << "Key: " << val->name << " Value: ";
374         switch (val->type)
375         {
376             case OCREP_PROP_NULL:
377                 std::cout << "NULL" << std::endl;
378                 break;
379
380             case OCREP_PROP_INT:
381                 std::cout << val->i << std::endl;
382                 break;
383
384             case OCREP_PROP_DOUBLE:
385                 std::cout << val->d << std::endl;
386                 break;
387
388             case OCREP_PROP_BOOL:
389                 std::cout << val->b << std::endl;
390                 break;
391
392             case OCREP_PROP_STRING:
393                 std::cout << val->str << std::endl;
394                 break;
395
396             case OCREP_PROP_BYTE_STRING:
397                 std::cout << "[ByteString]" << std::endl;
398                 break;
399
400             case OCREP_PROP_OBJECT:
401                 std::cout << "[Object]" << std::endl;
402                 break;
403
404             case OCREP_PROP_ARRAY:
405                 std::cout << "[Array]" << std::endl;
406                 break;
407         }
408
409         val = val->next;
410     }
411 }
412
413
414 int gNumObserveNotifies = 0;
415
416 OCStackApplicationResult obsReqCB(void *ctx, OCDoHandle handle,
417                                   OCClientResponse *clientResponse)
418 {
419     std::cout << "Observe response received from " << clientResponse->resourceUri << std::endl;
420
421     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
422     {
423         std::cout << "Invalid Put callback received" << std::endl;
424     }
425
426     if (clientResponse)
427     {
428         if (clientResponse->payload == NULL)
429         {
430             std::cout << "No payload received" << std::endl;
431         }
432
433         OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
434
435         PrintRepresentation(val);
436
437         gNumObserveNotifies++;
438         if (gNumObserveNotifies > 5) //large number to test observing in DELETE case.
439         {
440             std::cout << "Cancelling with OC_HIGH_QOS" << std::endl;
441             if (OCCancel(handle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
442             {
443                 std::cout << "Observe cancel error" << std::endl;
444             }
445         }
446         if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
447         {
448             std::cout << "This also serves as a registration confirmation" << std::endl;
449         }
450         else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
451         {
452             std::cout << "This also serves as a deregistration confirmation" << std::endl;
453             return OC_STACK_DELETE_TRANSACTION;
454         }
455         else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
456         {
457             std::cout << "This also tells you that registration/deregistration failed" << std::endl;
458             return OC_STACK_DELETE_TRANSACTION;
459         }
460     }
461     else
462     {
463         std::cout << "obsReqCB received Null clientResponse" << std::endl;
464     }
465
466     return OC_STACK_KEEP_TRANSACTION;
467 }
468
469 void ObserveResource(std::string uri, std::string additionalQuery)
470 {
471     OCCallbackData cbData;
472     cbData.cb = obsReqCB;
473     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
474     cbData.cd = NULL;
475
476     uri += additionalQuery;
477
478     std::cout << "Request OBSERVE to resource " << uri.c_str() << std::endl;
479
480     OCStackResult res = OCDoResource(NULL, OC_REST_OBSERVE, uri.c_str(), NULL, NULL,
481                                      CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
482
483     std::cout << "Requesting OBSERVE res=" << res << std::endl;
484 }
485
486 OCStackApplicationResult putReqCB(void *ctx, OCDoHandle /*handle*/,
487                                   OCClientResponse *clientResponse)
488 {
489     std::cout << "Put response received from " << clientResponse->resourceUri << std::endl;
490
491     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
492     {
493         std::cout << "Invalid Put callback received" << std::endl;
494     }
495
496     if (clientResponse->payload == NULL)
497     {
498         std::cout << "No payload received" << std::endl;
499     }
500
501     OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
502
503     PrintRepresentation(val);
504
505     std::string requestUri = g_host;
506     requestUri += clientResponse->resourceUri;
507
508     ObserveResource(requestUri, "");
509
510     return OC_STACK_KEEP_TRANSACTION;
511 }
512
513 OCPayload *putRequestPayload()
514 {
515     OCRepPayload *payload = OCRepPayloadCreate();
516
517     if (!payload)
518     {
519         std::cout << "Failed to create put payload object" << std::endl;
520         std::exit(1);
521     }
522
523     OCRepPayloadSetPropInt(payload, "power", 15);
524     OCRepPayloadSetPropBool(payload, "state", true);
525
526     return (OCPayload *)payload;
527 }
528
529 void PutResource(std::string uri, std::string additionalQuery)
530 {
531     OCCallbackData cbData;
532     cbData.cb = putReqCB;
533     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
534     cbData.cd = NULL;
535
536     uri += additionalQuery;
537
538     std::cout << "Request PUT to resource " << uri.c_str() << std::endl;
539
540     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, uri.c_str(), NULL, putRequestPayload(),
541                                      CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
542
543     std::cout << "Requesting PUT res=" << res << std::endl;
544 }
545
546 OCStackApplicationResult handleGetCB(void *ctx,
547                                      OCDoHandle /*handle*/,
548                                      OCClientResponse *clientResponse)
549 {
550     std::cout << "Get response received from " << clientResponse->resourceUri << std::endl;
551
552     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
553     {
554         std::cout << "Invalid Get callback received" << std::endl;
555     }
556
557     if (clientResponse->payload == NULL)
558     {
559         std::cout << "No payload received" << std::endl;
560     }
561
562     if (clientResponse->payload != NULL &&
563         clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION)
564     {
565         OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
566
567         PrintRepresentation(val);
568
569         std::string requestUri = g_host;
570         requestUri += clientResponse->resourceUri;
571
572         PutResource(requestUri, "");
573     }
574
575     return OC_STACK_KEEP_TRANSACTION;
576 }
577
578 void GetResource(std::string uri, std::string additionalQuery)
579 {
580     OCCallbackData cbData;
581     cbData.cb = handleGetCB;
582     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
583     cbData.cd = NULL;
584
585     uri += additionalQuery;
586
587     std::cout << "Request GET to resource " << uri.c_str() << std::endl;
588
589     OCStackResult res = OCDoResource(NULL, OC_REST_GET, uri.c_str(), NULL, NULL,
590                                      CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
591
592     std::cout << "Requesting GET res=" << res << std::endl;
593 }
594
595 // This is a function called back when a device is discovered
596 OCStackApplicationResult discoveryReqCB(void *ctx, OCDoHandle /*handle*/,
597                                         OCClientResponse *clientResponse)
598 {
599     if (ctx == (void *)DEFAULT_CONTEXT_VALUE)
600     {
601         std::cout << "Callback Context for DISCOVER query recvd successfully" << std::endl;
602     }
603
604     if (clientResponse)
605     {
606         std::cout << "StackResult: " << clientResponse->result << std::endl;
607
608         OCDiscoveryPayload *payload = (OCDiscoveryPayload *)clientResponse->payload;
609         if (!payload)
610         {
611             std::cout << "Empty payload" << std::endl;
612             return OC_STACK_DELETE_TRANSACTION;
613         }
614
615         OCResourcePayload *resource = (OCResourcePayload *)payload->resources;
616         if (!resource)
617         {
618             std::cout << "No resources in payload" << std::endl;
619             return OC_STACK_DELETE_TRANSACTION;
620         }
621
622         while (resource)
623         {
624             std::cout << "Found Resource " << resource->uri << std::endl;
625
626             std::string requestUri = g_host;
627             requestUri += resource->uri;
628
629             GetResource(requestUri, "");
630
631             resource = resource->next;
632         }
633     }
634     else
635     {
636         std::cout << "discoveryReqCB received Null clientResponse" << std::endl;
637     }
638     return OC_STACK_KEEP_TRANSACTION;
639 }
640
641 void DiscoverResources(std::string host, std::string additionalQuery)
642 {
643     std::cout << "Running as Client mode" << std::endl;
644
645     std::string requestQuery = host;
646     requestQuery += DEFAULT_DISCOVER_QUERY;
647     requestQuery += additionalQuery;
648
649     std::cout << "Finding resources..." << std::endl;
650     std::cout << requestQuery.c_str() << std::endl;
651
652     OCCallbackData cbData;
653
654     cbData.cb = discoveryReqCB;
655     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
656     cbData.cd = NULL;
657
658     if (OCDoResource(NULL, OC_REST_DISCOVER, requestQuery.c_str(), NULL, 0, CT_ADAPTER_TCP,
659                      OC_LOW_QOS, &cbData, NULL, 0) != OC_STACK_OK)
660     {
661         std::cout << "Unable to find resources from cloud" << std::endl;
662     }
663 }
664
665
666
667 /////////////////////////////////////////////Common sample
668
669 int g_runningMode = 0;
670
671 OCStackApplicationResult handleLoginoutCB(void *ctx,
672         OCDoHandle /*handle*/,
673         OCClientResponse *clientResponse)
674 {
675     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
676     {
677         std::cout << "Invalid Login/out callback received" << std::endl;
678     }
679
680     std::cout << "Login/out response received code: " << clientResponse->result << std::endl;
681
682     if (clientResponse->payload != NULL &&
683         clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION)
684     {
685         std::cout << "PAYLOAD_TYPE_REPRESENTATION received" << std::endl;
686
687         OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
688
689         while (val)
690         {
691             std::cout << "Key: " << val->name << " Value: " << val->str << std::endl;
692             val = val->next;
693         }
694
695         if (g_runningMode == 1)
696         {
697             PublishResources(g_host, "");
698         }
699         else if (g_runningMode == 2)
700         {
701             DiscoverResources(g_host, "");
702         }
703
704     }
705
706     return OC_STACK_KEEP_TRANSACTION;
707 }
708
709 OCStackApplicationResult handleRegisterCB(void *ctx,
710         OCDoHandle /*handle*/,
711         OCClientResponse *clientResponse)
712 {
713     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
714     {
715         std::cout << "Invalid Register callback received" << std::endl;
716     }
717
718     std::cout << "Register response received code: " << clientResponse->result << std::endl;
719
720     if (clientResponse->payload != NULL &&
721         clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION)
722     {
723         std::cout << "PAYLOAD_TYPE_REPRESENTATION received" << std::endl;
724         std::cout << "You can login using received session variable after disconnected or reboot" <<
725                   std::endl;
726
727         OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
728
729         while (val)
730         {
731             std::cout << "Key: " << val->name << " Value: " << val->str << std::endl;
732             val = val->next;
733         }
734     }
735
736     return OC_STACK_KEEP_TRANSACTION;
737 }
738
739 void PrintUsage()
740 {
741     std::cout << std::endl;
742     std::cout << "Usage : cloud_device <addr:port> <session> <mode>\n";
743     std::cout << "<addr:port>: Cloud Address, \"127.0.0.1:5683\"\n";
744     std::cout <<
745               "<session>: String value, Provided by response of onboarding scenario\n\tor kind of registration portal\n\n";
746     std::cout <<
747               "<mode>: String value, 's' for publish resource, 'c' for start discovery\n\n";
748     std::cout <<
749               "If you want to get session key using OAuth 2 auth code,\n\tleave blank to <session>, <mode> fields\n";
750     std::cout <<
751               "sample: \"cloud_device 127.0.0.1:5683\"\n\t-OAuth 2 registration mode\n\n";
752     std::cout <<
753               "sample: \"cloud_device 127.0.0.1:5683 1234567890123456 s\"\n\t-Publish resource under registered session\n\n";
754     std::cout <<
755               "sample: \"cloud_device 127.0.0.1:5683 1234567890123456 c\"\n\t-Discover resource under registered session\n\n";
756 }
757
758 int main(int argc, char *argv[])
759 {
760     std::string session;
761
762     std::string authProvider;
763     std::string authCode;
764
765     OCMode      stackMode = OC_CLIENT;
766
767     switch (argc)
768     {
769         case 2:
770             std::cout << "Put auth provider name(ex: github)" << std::endl;
771             std::cin >> authProvider;
772             std::cout << "Put auth code(provided by auth provider)" << std::endl;
773             std::cin >> authCode;
774             break;
775
776         case 4:
777             session = argv[2];
778             if (argv[3][0] == 's')
779             {
780                 stackMode = OC_CLIENT_SERVER;
781                 g_runningMode = 1;
782             }
783             else if (argv[3][0] == 'c')
784             {
785                 g_runningMode = 2;
786             }
787             break;
788
789         default:
790             PrintUsage();
791             return 0;
792     }
793
794     g_host += argv[1];
795
796     std::cout << "Host " << g_host.c_str() << std::endl;
797
798     if (OCInit(NULL, 0, stackMode) != OC_STACK_OK)
799     {
800         std::cout << "OCStack init error" << std::endl;
801         return 0;
802     }
803
804     OCStackResult   res = OC_STACK_ERROR;
805
806     switch (argc)
807     {
808         case 2:
809             std::cout << "Register account to cloud using " << authProvider << " " << authCode << std::endl;
810             res = OCCloudRegisterLogin(g_host.c_str(), authProvider.c_str(), authCode.c_str(),
811                                        handleRegisterCB);
812             std::cout << "OCCloudRegisterLogin return " << res << std::endl;
813             break;
814
815         case 4:
816             res = OCCloudLogin(g_host.c_str(), session.c_str(), handleLoginoutCB);
817             std::cout << "OCCloudLogin return " << res << std::endl;
818             break;
819
820         default:
821             PrintUsage();
822             return 0;
823     }
824
825     std::cout << "Waiting response.." << std::endl;
826
827     while (true)
828     {
829         if (OCProcess() != OC_STACK_OK)
830         {
831             std::cout << "OCProcess process error" << std::endl;
832         }
833
834         sleep(1);
835     }
836
837     if (OCStop() != OC_STACK_OK)
838     {
839         std::cout << "OCStop process error" << std::endl;
840     }
841
842     return 0;
843 }