Imported Upstream version 1.2.0
[platform/upstream/iotivity.git] / resource / examples / simpleclientHQ.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 // OCClient.cpp : Defines the entry point for the console application.
22 //
23 #include "iotivity_config.h"
24
25 #include <set>
26 #include <string>
27 #include <cstdlib>
28 #include <mutex>
29 #include <condition_variable>
30 #include "OCPlatform.h"
31 #include "OCApi.h"
32
33 #if defined(HAVE_PTHREAD_H)
34 #include <pthread.h>
35 #endif
36 #if defined(HAVE_WINDOWS_H)
37 #include <windows.h>
38 #endif
39
40 using namespace OC;
41
42 struct dereference_compare
43 {
44     bool operator()(std::shared_ptr<OCResource> lhs, std::shared_ptr<OCResource> rhs )const
45     {
46         return *lhs < *rhs;
47     }
48 };
49 typedef std::set<std::shared_ptr<OCResource>, dereference_compare> DiscoveredResourceSet;
50
51 DiscoveredResourceSet discoveredResources;
52 const int SUCCESS_RESPONSE = 0;
53 std::shared_ptr<OCResource> curResource;
54 std::mutex resourceLock;
55 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
56
57 class Light
58 {
59 public:
60
61     bool m_state;
62     int m_power;
63     std::string m_name;
64
65     Light() : m_state(false), m_power(0), m_name("")
66     {
67     }
68 };
69
70 Light mylight;
71
72 int observe_count()
73 {
74     static int oc = 0;
75     return ++oc;
76 }
77
78 void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
79                     const int& eCode, const int& sequenceNumber)
80 {
81     if(eCode == SUCCESS_RESPONSE)
82     {
83         std::cout << "OBSERVE RESULT:"<<std::endl;
84         if(sequenceNumber == (int) ObserveAction::ObserveRegister)
85         {
86             std::cout << "\tObserve Registration Confirmed: "<< std::endl;
87         }
88         else if (sequenceNumber == (int) ObserveAction::ObserveUnregister)
89         {
90             std::cout << "\tObserve Cancel Confirmed: "<< std::endl;
91             sleep(10);
92             std::cout << "DONE"<<std::endl;
93             std::exit(0);
94         }
95         else
96         {
97             std::cout << "\tSequenceNumber: "<< sequenceNumber << std::endl;
98         }
99
100         rep.getValue("state", mylight.m_state);
101         rep.getValue("power", mylight.m_power);
102         rep.getValue("name", mylight.m_name);
103
104         std::cout << "\tstate: " << mylight.m_state << std::endl;
105         std::cout << "\tpower: " << mylight.m_power << std::endl;
106         std::cout << "\tname: " << mylight.m_name << std::endl;
107
108         if(observe_count() == 11)
109         {
110             std::cout<<"Cancelling Observe..."<<std::endl;
111             OCStackResult result = curResource->cancelObserve(OC::QualityOfService::HighQos);
112
113             std::cout << "Cancel result: "<< result << " waiting for confirmation ..." <<std::endl;
114         }
115     }
116     else
117     {
118         std::cout << "onObserve Response error: " << eCode << std::endl;
119         std::exit(-1);
120     }
121 }
122
123 void onPost2(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
124 {
125     if(eCode == SUCCESS_RESPONSE || eCode == OC_STACK_RESOURCE_CHANGED)
126     {
127         std::cout << "POST request was successful" << std::endl;
128
129         if(rep.hasAttribute("createduri"))
130         {
131             std::cout << "\tUri of the created resource: "
132                       << rep.getValue<std::string>("createduri") << std::endl;
133         }
134         else
135         {
136             rep.getValue("state", mylight.m_state);
137             rep.getValue("power", mylight.m_power);
138             rep.getValue("name", mylight.m_name);
139
140             std::cout << "\tstate: " << mylight.m_state << std::endl;
141             std::cout << "\tpower: " << mylight.m_power << std::endl;
142             std::cout << "\tname: " << mylight.m_name << std::endl;
143         }
144
145         if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
146             std::cout << std::endl << "Observe is used." << std::endl << std::endl;
147         else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
148             std::cout << std::endl << "ObserveAll is used." << std::endl << std::endl;
149         sleep(1);
150         curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve,
151                 OC::QualityOfService::HighQos);
152
153     }
154     else
155     {
156         std::cout << "onPost2 Response error: " << eCode << std::endl;
157         std::exit(-1);
158     }
159 }
160
161 void onPost(const HeaderOptions& /*headerOptions*/,
162         const OCRepresentation& rep, const int eCode)
163 {
164     if(eCode == SUCCESS_RESPONSE || eCode == OC_STACK_RESOURCE_CHANGED)
165     {
166         std::cout << "POST request was successful" << std::endl;
167
168         if(rep.hasAttribute("createduri"))
169         {
170             std::cout << "\tUri of the created resource: "
171                       << rep.getValue<std::string>("createduri") << std::endl;
172         }
173         else
174         {
175             rep.getValue("state", mylight.m_state);
176             rep.getValue("power", mylight.m_power);
177             rep.getValue("name", mylight.m_name);
178
179             std::cout << "\tstate: " << mylight.m_state << std::endl;
180             std::cout << "\tpower: " << mylight.m_power << std::endl;
181             std::cout << "\tname: " << mylight.m_name << std::endl;
182         }
183
184         OCRepresentation rep2;
185
186         std::cout << "Posting light representation..."<<std::endl;
187
188         mylight.m_state = true;
189         mylight.m_power = 55;
190
191         rep2.setValue("state", mylight.m_state);
192         rep2.setValue("power", mylight.m_power);
193         sleep(1);
194         curResource->post(rep2, QueryParamsMap(), &onPost2, OC::QualityOfService::HighQos);
195     }
196     else
197     {
198         std::cout << "onPost Response error: " << eCode << std::endl;
199         std::exit(-1);
200     }
201 }
202
203 // Local function to put a different state for this resource
204 void postLightRepresentation(std::shared_ptr<OCResource> resource)
205 {
206     if(resource)
207     {
208         OCRepresentation rep;
209
210         std::cout << "Posting light representation..."<<std::endl;
211
212         mylight.m_state = false;
213         mylight.m_power = 105;
214
215         rep.setValue("state", mylight.m_state);
216         rep.setValue("power", mylight.m_power);
217
218         // Invoke resource's post API with rep, query map and the callback parameter
219         resource->post(rep, QueryParamsMap(), &onPost, OC::QualityOfService::HighQos);
220     }
221 }
222
223 // callback handler on PUT request
224 void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
225 {
226     if(eCode == SUCCESS_RESPONSE || eCode == OC_STACK_RESOURCE_CHANGED)
227     {
228         std::cout << "PUT request was successful" << std::endl;
229
230         rep.getValue("state", mylight.m_state);
231         rep.getValue("power", mylight.m_power);
232         rep.getValue("name", mylight.m_name);
233
234         std::cout << "\tstate: " << mylight.m_state << std::endl;
235         std::cout << "\tpower: " << mylight.m_power << std::endl;
236         std::cout << "\tname: " << mylight.m_name << std::endl;
237         sleep(1);
238         postLightRepresentation(curResource);
239     }
240     else
241     {
242         std::cout << "onPut Response error: " << eCode << std::endl;
243         std::exit(-1);
244     }
245 }
246
247 // Local function to put a different state for this resource
248 void putLightRepresentation(std::shared_ptr<OCResource> resource)
249 {
250     if(resource)
251     {
252         OCRepresentation rep;
253
254         std::cout << "Putting light representation..."<<std::endl;
255
256         mylight.m_state = true;
257         mylight.m_power = 15;
258
259         rep.setValue("state", mylight.m_state);
260         rep.setValue("power", mylight.m_power);
261
262         // Invoke resource's put API with rep, query map and the callback parameter
263         resource->put(rep, QueryParamsMap(), &onPut, OC::QualityOfService::HighQos);
264     }
265 }
266
267 // Callback handler on GET request
268 void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
269 {
270     if(eCode == SUCCESS_RESPONSE)
271     {
272         std::cout << "GET request was successful" << std::endl;
273         std::cout << "Resource URI: " << rep.getUri() << std::endl;
274
275         rep.getValue("state", mylight.m_state);
276         rep.getValue("power", mylight.m_power);
277         rep.getValue("name", mylight.m_name);
278
279         std::cout << "\tstate: " << mylight.m_state << std::endl;
280         std::cout << "\tpower: " << mylight.m_power << std::endl;
281         std::cout << "\tname: " << mylight.m_name << std::endl;
282         sleep(1);
283         putLightRepresentation(curResource);
284     }
285     else
286     {
287         std::cout << "onGET Response error: " << eCode << std::endl;
288         std::exit(-1);
289     }
290 }
291
292 // Local function to get representation of light resource
293 void getLightRepresentation(std::shared_ptr<OCResource> resource)
294 {
295     if(resource)
296     {
297         std::cout << "Getting Light Representation..."<<std::endl;
298         // Invoke resource's get API with the callback parameter
299
300         QueryParamsMap test;
301         resource->get(test, &onGet,OC::QualityOfService::HighQos);
302     }
303 }
304
305 void receivedPlatformInfo(const OCRepresentation& rep)
306 {
307     std::cout << "\nPlatform Information received ---->\n";
308     std::string value;
309     std::string values[] =
310     {
311         "pi",   "Platform ID                    ",
312         "mnmn", "Manufacturer name              ",
313         "mnml", "Manufacturer url               ",
314         "mnmo", "Manufacturer Model No          ",
315         "mndt", "Manufactured Date              ",
316         "mnpv", "Manufacturer Platform Version  ",
317         "mnos", "Manufacturer OS version        ",
318         "mnhw", "Manufacturer hardware version  ",
319         "mnfv", "Manufacturer firmware version  ",
320         "mnsl", "Manufacturer support url       ",
321         "st",   "Manufacturer system time       "
322     };
323
324     for (unsigned int i = 0; i < sizeof(values) / sizeof(values[0]) ; i += 2)
325     {
326         if(rep.getValue(values[i], value))
327         {
328             std::cout << values[i + 1] << " : "<< value << std::endl;
329         }
330     }
331 }
332
333 void receivedDeviceInfo(const OCRepresentation& rep)
334 {
335     std::cout << "\nDevice Information received ---->\n";
336     std::string value;
337     std::string values[] =
338     { 
339         "di",  "Device ID        ",
340         "n",   "Device name      ",
341         "lcv", "Spec version url ",
342         "dmv", "Data Model Model ", 
343     };
344
345     for (unsigned int i = 0; i < sizeof(values) / sizeof(values[0]); i += 2)
346     {
347         if (rep.getValue(values[i], value))
348         {
349             std::cout << values[i + 1] << " : " << value << std::endl;
350         }
351     }
352 }
353
354 // Callback to found resources
355 void foundResource(std::shared_ptr<OCResource> resource)
356 {
357     std::string resourceURI;
358     std::string hostAddress;
359
360     std::string platformDiscoveryURI = "/oic/p";
361     std::string deviceDiscoveryURI   = "/oic/d";
362
363     try
364     {
365         // Do some operations with resource object.
366         if(resource)
367         {
368             std::lock_guard<std::mutex> lk(resourceLock);
369
370             if(discoveredResources.find(resource) == discoveredResources.end())
371             {
372                 std::cout << "Found resource " << resource->uniqueIdentifier() <<
373                     " for the first time on server with ID: "<< resource->sid()<<std::endl;
374                 discoveredResources.insert(resource);
375             }
376             else
377             {
378                 std::cout<<"Found resource "<< resource->uniqueIdentifier() << " again!"<<std::endl;
379             }
380
381             if(curResource)
382             {
383                 std::cout << "Found another resource, ignoring"<<std::endl;
384                 return;
385             }
386
387             std::cout<<"DISCOVERED Resource:"<<std::endl;
388             // Get the resource URI
389             resourceURI = resource->uri();
390             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
391
392             // Get the resource host address
393             hostAddress = resource->host();
394             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
395
396             OCStackResult ret;
397
398             std::cout << "Querying for platform information... " << std::endl;
399
400             ret = OCPlatform::getPlatformInfo("", platformDiscoveryURI, CT_ADAPTER_IP,
401                     &receivedPlatformInfo);
402
403             if (ret == OC_STACK_OK)
404             {
405                 std::cout << "Get platform information is done." << std::endl;
406             }
407             else
408             {
409                 std::cout << "Get platform information failed." << std::endl;
410             }
411
412             std::cout << "Querying for device information... " << std::endl;
413
414             ret = OCPlatform::getDeviceInfo(resource->host(), deviceDiscoveryURI,
415                                        resource->connectivityType(), &receivedDeviceInfo);
416
417             if (ret == OC_STACK_OK)
418             {
419                 std::cout << "Getting device information is done." << std::endl;
420             }
421             else
422             {
423                 std::cout << "Getting device information failed." << std::endl;
424             }
425
426             // Get the resource types
427             std::cout << "\tList of resource types: " << std::endl;
428             for(auto &resourceTypes : resource->getResourceTypes())
429             {
430                 std::cout << "\t\t" << resourceTypes << std::endl;
431             }
432
433             // Get the resource interfaces
434             std::cout << "\tList of resource interfaces: " << std::endl;
435             for(auto &resourceInterfaces : resource->getResourceInterfaces())
436             {
437                 std::cout << "\t\t" << resourceInterfaces << std::endl;
438             }
439
440             if(resourceURI == "/a/light")
441             {
442                 curResource = resource;
443                 sleep(1);
444                 // Call a local function which will internally invoke get
445                 // API on the resource pointer
446                 getLightRepresentation(resource);
447             }
448         }
449         else
450         {
451             // Resource is invalid
452             std::cout << "Resource is invalid" << std::endl;
453         }
454
455     }
456     catch(std::exception& e)
457     {
458         std::cerr << "Exception in foundResource: "<< e.what() <<std::endl;
459     }
460 }
461
462 void PrintUsage()
463 {
464     std::cout << std::endl;
465     std::cout << "Usage : simpleclientHQ <ObserveType> <ConnectivityType>" << std::endl;
466     std::cout << "   ObserveType : 1 - Observe" << std::endl;
467     std::cout << "   ObserveType : 2 - ObserveAll" << std::endl;
468     std::cout << "   ConnectivityType: Default IP" << std::endl;
469     std::cout << "   ConnectivityType : 0 - IP"<< std::endl;
470 }
471
472 int main(int argc, char* argv[]) {
473
474     std::ostringstream requestURI;
475
476     OCConnectivityType connectivityType = CT_ADAPTER_IP;
477     try
478     {
479         if (argc == 1)
480         {
481             OBSERVE_TYPE_TO_USE = ObserveType::Observe;
482         }
483         else if (argc ==2 || argc==3)
484         {
485             int value = std::stoi(argv[1]);
486             if (value == 1)
487                 OBSERVE_TYPE_TO_USE = ObserveType::Observe;
488             else if (value == 2)
489                 OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
490             else
491                 OBSERVE_TYPE_TO_USE = ObserveType::Observe;
492
493             if(argc == 3)
494             {
495                 std::size_t inputValLen;
496                 int optionSelected = std::stoi(argv[2], &inputValLen);
497
498                 if(inputValLen == strlen(argv[2]))
499                 {
500                     if(optionSelected == 0)
501                     {
502                         std::cout << "Using IP."<< std::endl;
503                         connectivityType = CT_ADAPTER_IP;
504                     }
505                     else
506                     {
507                         std::cout << "Invalid connectivity type selected. Using default IP"
508                             << std::endl;
509                     }
510                 }
511                 else
512                 {
513                     std::cout << "Invalid connectivity type selected. Using default IP"
514                             << std::endl;
515                 }
516             }
517         }
518         else
519         {
520             PrintUsage();
521             return -1;
522         }
523     }
524     catch(std::exception&)
525     {
526         std::cout << "Invalid input argument." << std::endl;
527         PrintUsage();
528         return -1;
529     }
530
531
532     // Create PlatformConfig object
533     PlatformConfig cfg {
534         OC::ServiceType::InProc,
535         OC::ModeType::Client,
536         "0.0.0.0",
537         0,
538         OC::QualityOfService::HighQos
539     };
540
541     OCPlatform::Configure(cfg);
542
543     try
544     {
545         // Find all resources
546         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light";
547
548         OCPlatform::findResource("", requestURI.str(),
549                 connectivityType, &foundResource, OC::QualityOfService::LowQos);
550         std::cout<< "Finding Resource... " <<std::endl;
551
552         // Find resource is done twice so that we discover the original resources a second time.
553         // These resources will have the same uniqueidentifier (yet be different objects), so that
554         // we can verify/show the duplicate-checking code in foundResource(above);
555         OCPlatform::findResource("", requestURI.str(),
556                 connectivityType, &foundResource, OC::QualityOfService::LowQos);
557         std::cout<< "Finding Resource for second time... " <<std::endl;
558
559         // A condition variable will free the mutex it is given, then do a non-
560         // intensive block until 'notify' is called on it.  In this case, since we
561         // don't ever call cv.notify, this should be a non-processor intensive version
562         // of while(true);
563         std::mutex blocker;
564         std::condition_variable cv;
565         std::unique_lock<std::mutex> lock(blocker);
566         cv.wait(lock);
567
568     }
569     catch(OCException& e)
570     {
571         oclog() << "Exception in main: "<<e.what();
572     }
573
574     return 0;
575 }
576
577