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