Merge branch 'cloud-interface'
[platform/upstream/iotivity.git] / cloud / samples / client / thin_light / thin_room_light.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 #include "oicresourcedirectory.h"
37
38 #define DEFAULT_CONTEXT_VALUE 0x99
39 #define DEFAULT_AUTH_SIGNUP "/oic/account"
40 #define DEFAULT_AUTH_SESSION "/oic/account/session"
41 #define DEFAULT_AUTH_REFRESH "/oic/account/tokenrefresh"
42
43
44 OCStackResult OCCloudSignup(const char *host, const char *deviceId,
45                             const char *authprovider,
46                             const char *authcode, OCClientResponseHandler response)
47 {
48     char    targetUri[MAX_URI_LENGTH * 2] = { 0, };
49     snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, DEFAULT_AUTH_SIGNUP);
50
51     OCCallbackData cbData;
52     memset(&cbData, 0, sizeof(OCCallbackData));
53     cbData.cb = response;
54     cbData.cd = NULL;
55     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
56
57     OCRepPayload *registerPayload = OCRepPayloadCreate();
58     if (!registerPayload)
59     {
60         goto no_memory;
61     }
62
63     OCRepPayloadSetPropString(registerPayload, "di", deviceId);
64     OCRepPayloadSetPropString(registerPayload, "authprovider", authprovider);
65     OCRepPayloadSetPropString(registerPayload, "authcode", authcode);
66
67     return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)registerPayload,
68                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
69
70 no_memory:
71     OCRepPayloadDestroy(registerPayload);
72     return OC_STACK_NO_MEMORY;
73 }
74
75 OCStackResult OCCloudSession(const char *host, const char *query, const char *uId,
76                              const char *deviceId,
77                              const char *accesstoken,
78                              bool isLogin, OCClientResponseHandler response)
79 {
80     char    targetUri[MAX_URI_LENGTH * 2] = { 0, };
81     snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, query);
82
83     OCCallbackData cbData;
84     memset(&cbData, 0, sizeof(OCCallbackData));
85     cbData.cb = response;
86     cbData.cd = NULL;
87     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
88
89     OCRepPayload *loginoutPayload = OCRepPayloadCreate();
90     if (!loginoutPayload)
91     {
92         goto no_memory;
93     }
94
95     if (uId != NULL)
96     {
97         OCRepPayloadSetPropString(loginoutPayload, "uid", uId);
98     }
99
100     if (deviceId != NULL)
101     {
102         OCRepPayloadSetPropString(loginoutPayload, "di", deviceId);
103     }
104
105     if (accesstoken != NULL)
106     {
107         OCRepPayloadSetPropString(loginoutPayload, "accesstoken", accesstoken);
108     }
109     OCRepPayloadSetPropBool(loginoutPayload, "login", isLogin);
110
111     return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)loginoutPayload,
112                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
113
114 no_memory:
115     OCRepPayloadDestroy(loginoutPayload);
116     return OC_STACK_NO_MEMORY;
117 }
118
119 //Client should call refresh before expiresin or when receive 4.01 during sign-in
120 OCStackResult OCCloudRefresh(const char *host, const char *query, const char *uId,
121                              const char *deviceId, const char *refreshtoken, OCClientResponseHandler response)
122 {
123     char    targetUri[MAX_URI_LENGTH * 2] = { 0, };
124     snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, query);
125
126     OCCallbackData cbData;
127     memset(&cbData, 0, sizeof(OCCallbackData));
128     cbData.cb = response;
129     cbData.cd = NULL;
130     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
131
132     OCRepPayload *refreshPayload = OCRepPayloadCreate();
133     if (!refreshPayload)
134     {
135         goto no_memory;
136     }
137
138     OCRepPayloadSetPropString(refreshPayload, "uid", uId);
139     OCRepPayloadSetPropString(refreshPayload, "di", deviceId);
140     OCRepPayloadSetPropString(refreshPayload, "granttype", "refresh_token");
141     OCRepPayloadSetPropString(refreshPayload, "refreshtoken", refreshtoken);
142
143     return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)refreshPayload,
144                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
145
146 no_memory:
147     OCRepPayloadDestroy(refreshPayload);
148     return OC_STACK_NO_MEMORY;
149 }
150
151 OCStackResult OCCloudLogin(const char *host, const char *uId, const char *deviceId,
152                            const char *accesstoken, OCClientResponseHandler response)
153 {
154     return OCCloudSession(host, DEFAULT_AUTH_SESSION, uId, deviceId, accesstoken, true, response);
155 }
156
157 OCStackResult OCCloudLogout(const char *host, OCClientResponseHandler response)
158 {
159     return OCCloudSession(host, DEFAULT_AUTH_SESSION, NULL, NULL, NULL, false, response);
160 }
161
162 ////////////////////////////////////////Device Sample
163
164 #define SAMPLE_MAX_NUM_POST_INSTANCE  1
165 typedef struct LIGHTRESOURCE
166 {
167     OCResourceHandle handle;
168     bool state;
169     int power;
170 } LightResource;
171 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
172
173
174 OCRepPayload *responsePayload(int64_t power, bool state)
175 {
176     OCRepPayload *payload = OCRepPayloadCreate();
177     if (!payload)
178     {
179         std::cout << "Failed to allocate Payload" << std::endl;
180         return nullptr;
181     }
182
183     OCRepPayloadSetPropBool(payload, "state", state);
184     OCRepPayloadSetPropInt(payload, "power", power);
185
186     return payload;
187 }
188
189 OCRepPayload *constructResponse(OCEntityHandlerRequest *ehRequest)
190 {
191     if (ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
192     {
193         std::cout << "Incoming payload not a representation" << std::endl;
194         return nullptr;
195     }
196
197     LightResource *currLightResource = NULL;
198
199     if (ehRequest->resource == gLightInstance[0].handle)
200     {
201         currLightResource = &gLightInstance[0];
202     }
203     else if (ehRequest->resource == gLightInstance[1].handle)
204     {
205         currLightResource = &gLightInstance[1];
206     }
207
208     if (OC_REST_PUT == ehRequest->method)
209     {
210         // Get pointer to query
211         int64_t pow;
212         OCRepPayload *input = reinterpret_cast<OCRepPayload *>(ehRequest->payload);
213
214         if (OCRepPayloadGetPropInt(input, "power", &pow))
215         {
216             currLightResource->power = pow;
217         }
218
219         bool state;
220         if (OCRepPayloadGetPropBool(input, "state", &state))
221         {
222             currLightResource->state = state;
223         }
224     }
225
226     return responsePayload(currLightResource->power, currLightResource->state);
227 }
228
229 OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest,
230                                         OCRepPayload **payload)
231 {
232     OCRepPayload *getResp = constructResponse(ehRequest);
233     if (!getResp)
234     {
235         std::cout << "constructResponse failed" << std::endl;
236         return OC_EH_ERROR;
237     }
238
239     *payload = getResp;
240
241     return OC_EH_OK;
242 }
243
244 OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest,
245                                         OCRepPayload **payload)
246 {
247     OCEntityHandlerResult ehResult;
248     OCRepPayload *putResp = constructResponse(ehRequest);
249
250     if (!putResp)
251     {
252         std::cout << "Failed to construct Json response" << std::endl;
253         return OC_EH_ERROR;
254     }
255
256     *payload = putResp;
257     ehResult = OC_EH_OK;
258
259     return ehResult;
260 }
261
262 #define SAMPLE_MAX_NUM_OBSERVATIONS  2
263 static bool observeThreadStarted = false;
264 int gLightUnderObservation = 0;
265 pthread_t threadId_observe;
266 typedef struct
267 {
268     OCObservationId observationId;
269     bool valid;
270     OCResourceHandle resourceHandle;
271 } Observers;
272 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
273
274 void *ChangeLightRepresentation(void *param)
275 {
276     (void)param;
277     OCStackResult result = OC_STACK_ERROR;
278
279     while (true)
280     {
281         sleep(3);
282         gLightInstance[0].power += 1;
283         gLightInstance[1].power += 3;
284
285         if (gLightUnderObservation)
286         {
287             std::cout << " =====> Notifying stack of new power level " << gLightInstance[0].power << std::endl;
288             std::cout << " =====> Notifying stack of new power level " << gLightInstance[1].power << std::endl;
289             // Notifying all observers
290             result = OCNotifyAllObservers(gLightInstance[0].handle, OC_NA_QOS);
291             result = OCNotifyAllObservers(gLightInstance[1].handle, OC_NA_QOS);
292
293             std::cout << " =====> Notifying result " << result << std::endl;
294         }
295     }
296     return NULL;
297 }
298
299 void ProcessObserveRegister(OCEntityHandlerRequest *ehRequest)
300 {
301     std::cout << "Received observation registration request with observation Id " <<
302               ehRequest->obsInfo.obsId << std::endl;
303
304     if (!observeThreadStarted)
305     {
306         pthread_create(&threadId_observe, NULL, ChangeLightRepresentation, (void *)NULL);
307         observeThreadStarted = 1;
308     }
309     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
310     {
311         if (interestedObservers[i].valid == false)
312         {
313             interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
314             interestedObservers[i].valid = true;
315             gLightUnderObservation = 1;
316             break;
317         }
318     }
319 }
320
321 void ProcessObserveDeregister(OCEntityHandlerRequest *ehRequest)
322 {
323     bool clientStillObserving = false;
324
325     std::cout << "Received observation deregistration request for observation Id " <<
326               ehRequest->obsInfo.obsId << std::endl;
327     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
328     {
329         if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
330         {
331             interestedObservers[i].valid = false;
332         }
333         if (interestedObservers[i].valid == true)
334         {
335             // Even if there is one single client observing we continue notifying entity handler
336             clientStillObserving = true;
337         }
338     }
339     if (clientStillObserving == false)
340         gLightUnderObservation = 0;
341 }
342
343 OCEntityHandlerResult
344 OCEntityHandlerCb(OCEntityHandlerFlag flag,
345                   OCEntityHandlerRequest *entityHandlerRequest, void * /*callback*/)
346 {
347     OCEntityHandlerResult ehResult = OC_EH_OK;
348     OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, {}, { 0 }, false };
349
350     // Validate pointer
351     if (!entityHandlerRequest)
352     {
353         std::cout << "Invalid request pointer" << std::endl;
354         return OC_EH_ERROR;
355     }
356
357     // Initialize certain response fields
358     response.numSendVendorSpecificHeaderOptions = 0;
359     memset(response.sendVendorSpecificHeaderOptions,
360            0, sizeof response.sendVendorSpecificHeaderOptions);
361     memset(response.resourceUri, 0, sizeof response.resourceUri);
362     OCRepPayload *payload = nullptr;
363
364     if (flag & OC_REQUEST_FLAG)
365     {
366         std::cout << "Flag includes OC_REQUEST_FLAG" << std::endl;
367
368         if (OC_REST_GET == entityHandlerRequest->method)
369         {
370             std::cout << "Received OC_REST_GET from client" << std::endl;
371             ehResult = ProcessGetRequest(entityHandlerRequest, &payload);
372         }
373         else if (OC_REST_PUT == entityHandlerRequest->method)
374         {
375             std::cout << "Received OC_REST_PUT from client" << std::endl;
376             ehResult = ProcessPutRequest(entityHandlerRequest, &payload);
377         }
378         else
379         {
380             std::cout << "Received unsupported method %d from client " << entityHandlerRequest->method <<
381                       std::endl;
382             ehResult = OC_EH_ERROR;
383         }
384         // If the result isn't an error or forbidden, send response
385         if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
386         {
387             // Format the response.  Note this requires some info about the request
388             response.requestHandle = entityHandlerRequest->requestHandle;
389             response.resourceHandle = entityHandlerRequest->resource;
390             response.ehResult = ehResult;
391             response.payload = reinterpret_cast<OCPayload *>(payload);
392             // Indicate that response is NOT in a persistent buffer
393             response.persistentBufferFlag = 0;
394
395             // Send the response
396             if (OCDoResponse(&response) != OC_STACK_OK)
397             {
398                 std::cout << "Error sending response" << std::endl;
399                 ehResult = OC_EH_ERROR;
400             }
401         }
402     }
403
404     if (flag & OC_OBSERVE_FLAG)
405     {
406         std::cout << "Flag includes OC_OBSERVE_FLAG" << std::endl;
407         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
408         {
409             std::cout << "Received OC_OBSERVE_REGISTER from client" << std::endl;
410             ProcessObserveRegister(entityHandlerRequest);
411         }
412         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
413         {
414             std::cout << "Received OC_OBSERVE_DEREGISTER from client" << std::endl;
415             ProcessObserveDeregister(entityHandlerRequest);
416         }
417     }
418
419     OCPayloadDestroy(response.payload);
420     return ehResult;
421 }
422
423 int createLightResource(char *uri, LightResource *lightResource)
424 {
425     if (!uri)
426     {
427         std::cout << "Resource URI cannot be NULL" << std::endl;
428         return -1;
429     }
430
431     lightResource->state = false;
432     lightResource->power = 0;
433     OCStackResult res = OCCreateResource(&(lightResource->handle),
434                                          "core.light",
435                                          "oc.mi.def",
436                                          uri,
437                                          OCEntityHandlerCb,
438                                          NULL,
439                                          OC_DISCOVERABLE | OC_OBSERVABLE);
440     std::cout << "Created Light resource with result:" << res << std::endl;
441
442     return res;
443 }
444
445 OCStackApplicationResult handlePublishCB(void *ctx,
446         OCDoHandle /*handle*/,
447         OCClientResponse *clientResponse)
448 {
449     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
450     {
451         std::cout << "Invalid Publish callback received" << std::endl;
452     }
453
454     std::cout << "Publish resource response received, code: " << clientResponse->result << std::endl;
455
456     return OC_STACK_KEEP_TRANSACTION;
457 }
458
459 void PublishResources(std::string host)
460 {
461     std::cout << "Publishing resources..." << std::endl;
462
463     if (createLightResource((char *)"/a/light/0", &gLightInstance[0]) != 0)
464     {
465         std::cout << "Unable to create sample resource" << std::endl;
466     }
467
468     OCResourceHandle    resourceHandles[1] = { gLightInstance[0].handle,
469                                              };
470     OCCallbackData cbData;
471     cbData.cb = handlePublishCB;
472     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
473     cbData.cd = NULL;
474
475     std::cout << "Publish default resources" << std::endl;
476
477     OCDeviceInfo        devInfoRoomLight;
478     OCStringLL          deviceType;
479
480     deviceType.value = "oic.d.light";
481     deviceType.next = NULL;
482     devInfoRoomLight.deviceName = "Living Room Light";
483     devInfoRoomLight.types = &deviceType;
484     devInfoRoomLight.specVersion = NULL;
485     devInfoRoomLight.dataModelVersions = NULL;
486
487     OCStackResult res = OCSetDeviceInfo(devInfoRoomLight);
488
489     if (res != OC_STACK_OK)
490     {
491         std::cout << "Setting device info failed" << std::endl;
492     }
493
494     res = OCRDPublish(host.c_str(), CT_ADAPTER_TCP, NULL, 0, &cbData,
495                       OC_LOW_QOS);
496     if (res != OC_STACK_OK)
497     {
498         std::cout << "Unable to publish default resources to cloud" << std::endl;
499     }
500
501     std::cout << "Publish user resources" << std::endl;
502
503     res = OCRDPublish(host.c_str(), CT_ADAPTER_TCP, resourceHandles, 1, &cbData,
504                       OC_LOW_QOS);
505     if (res != OC_STACK_OK)
506     {
507         std::cout << "Unable to publish user resources to cloud" << std::endl;
508     }
509 }
510
511 /////////////////////////////////////////////Common sample
512 void printRepresentation(OCRepPayloadValue *value)
513 {
514     while (value)
515     {
516         std::cout << "Key: " << value->name;
517         switch (value->type)
518         {
519             case OCREP_PROP_NULL:
520                 std::cout << " Value: None" << std::endl;
521                 break;
522             case OCREP_PROP_INT:
523                 std::cout << " Value: " << value->i << std::endl;
524                 break;
525             case OCREP_PROP_DOUBLE:
526                 std::cout << " Value: " << value->d << std::endl;
527                 break;
528             case OCREP_PROP_BOOL:
529                 std::cout << " Value: " << value->b << std::endl;
530                 break;
531             case OCREP_PROP_STRING:
532                 std::cout << " Value: " << value->str << std::endl;
533                 break;
534             case OCREP_PROP_BYTE_STRING:
535                 std::cout << " Value: Byte String" << std::endl;
536                 break;
537             case OCREP_PROP_OBJECT:
538                 std::cout << " Value: Object" << std::endl;
539                 break;
540             case OCREP_PROP_ARRAY:
541                 std::cout << " Value: Array" << std::endl;
542                 break;
543         }
544         value = value->next;
545     }
546 }
547
548 std::string g_host = "coap+tcp://";
549
550 OCStackApplicationResult handleLoginoutCB(void *ctx,
551         OCDoHandle /*handle*/,
552         OCClientResponse *clientResponse)
553 {
554     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
555     {
556         std::cout << "Invalid Login/out callback received" << std::endl;
557     }
558
559     std::cout << "Login/out response received code: " << clientResponse->result << std::endl;
560
561     if (clientResponse->payload != NULL &&
562         clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION)
563     {
564         std::cout << "PAYLOAD_TYPE_REPRESENTATION received" << std::endl;
565
566         OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
567
568         printRepresentation(val);
569     }
570
571     if (clientResponse->result < 5)
572     {
573         PublishResources(g_host);
574     }
575
576     return OC_STACK_KEEP_TRANSACTION;
577 }
578
579 OCStackApplicationResult handleRegisterCB(void *ctx,
580         OCDoHandle /*handle*/,
581         OCClientResponse *clientResponse)
582 {
583     if (ctx != (void *)DEFAULT_CONTEXT_VALUE)
584     {
585         std::cout << "Invalid Register callback received" << std::endl;
586     }
587
588     std::cout << "Register response received code: " << clientResponse->result << std::endl;
589
590     if (clientResponse->payload != NULL &&
591         clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION)
592     {
593         std::cout << "PAYLOAD_TYPE_REPRESENTATION received" << std::endl;
594         std::cout << "You can Sign-In using retrieved accesstoken when disconnected or reboot" <<
595                   std::endl;
596
597         OCRepPayloadValue *val = ((OCRepPayload *)clientResponse->payload)->values;
598
599         printRepresentation(val);
600     }
601
602     return OC_STACK_KEEP_TRANSACTION;
603 }
604
605 void PrintUsage()
606 {
607     std::cout << std::endl;
608     std::cout << "Usage : thin_cloud_device <addr:port> <uid> <accesstoken>\n";
609     std::cout << "<addr:port>: Cloud Address, \"127.0.0.1:5683\"\n";
610     std::cout <<
611               "<accesstoken>: String value, Provided by response of onboarding scenario\n\tor kind of registration portal\n\n";
612     std::cout <<
613               "sample: \"cloud_device 127.0.0.1:5683\"\n\t-Sign-Up mode\n\n";
614     std::cout <<
615               "sample: \"cloud_device 127.0.0.1:5683 abcdefg 1234567890123456\"\n\t-Sign-in and Publish resource to registered account\n\n";
616 }
617
618 static FILE *client_open(const char * /*path*/, const char *mode)
619 {
620     return fopen("./thin_resource_server.dat", mode);
621 }
622
623 int main(int argc, char *argv[])
624 {
625     std::string uId;
626     std::string accessToken;
627
628     std::string authProvider;
629     std::string authCode;
630
631     OCMode      stackMode = OC_CLIENT_SERVER;
632
633     switch (argc)
634     {
635         case 2:
636             std::cout << "Put auth provider name(ex: github)" << std::endl;
637             std::cin >> authProvider;
638             std::cout << "Put auth code(provided by auth provider)" << std::endl;
639             std::cin >> authCode;
640             break;
641
642         case 4:
643             uId = argv[2];
644             accessToken = argv[3];
645             break;
646
647         default:
648             PrintUsage();
649             return 0;
650     }
651
652     g_host += argv[1];
653
654     std::cout << "Host " << g_host.c_str() << std::endl;
655
656     OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink };
657     if (OCRegisterPersistentStorageHandler(&ps) != OC_STACK_OK)
658     {
659         std::cout << "OCStack init persistent storage error" << std::endl;
660         return 0;
661     }
662
663     if (OCInit(NULL, 0, stackMode) != OC_STACK_OK)
664     {
665         std::cout << "OCStack init error" << std::endl;
666         return 0;
667     }
668
669     OCStackResult   res = OC_STACK_ERROR;
670
671     switch (argc)
672     {
673         case 2:
674             std::cout << "Sign-Up to cloud using " << authProvider << " " << authCode << std::endl;
675             res = OCCloudSignup(g_host.c_str(), OCGetServerInstanceIDString(), authProvider.c_str(),
676                                 authCode.c_str(), handleRegisterCB);
677             std::cout << "OCCloudSignup return " << res << std::endl;
678             break;
679
680         case 4:
681             std::cout << "Sign-In to cloud using " << accessToken << std::endl;
682             res = OCCloudLogin(g_host.c_str(), uId.c_str(), OCGetServerInstanceIDString(), accessToken.c_str(),
683                                handleLoginoutCB);
684             std::cout << "OCCloudLogin return " << res << std::endl;
685             break;
686
687         default:
688             PrintUsage();
689             return 0;
690     }
691
692
693
694     std::cout << "Waiting response.." << std::endl;
695
696     while (true)
697     {
698         if (OCProcess() != OC_STACK_OK)
699         {
700             std::cout << "OCProcess process error" << std::endl;
701         }
702
703         sleep(1);
704     }
705
706     if (OCStop() != OC_STACK_OK)
707     {
708         std::cout << "OCStop process error" << std::endl;
709     }
710
711     return 0;
712 }