Modified connectivityType on calling getDeviceInfo API at CPP Sample
[platform/upstream/iotivity.git] / resource / examples / simpleclient.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 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_PTHREAD_H
28 #include <pthread.h>
29 #endif
30 #ifdef HAVE_WINDOWS_H
31 #include <Windows.h>
32 #endif
33 #include <string>
34 #include <map>
35 #include <cstdlib>
36 #include <mutex>
37 #include <condition_variable>
38 #include "OCPlatform.h"
39 #include "OCApi.h"
40
41 using namespace OC;
42
43 static const char* SVR_DB_FILE_NAME = "./oic_svr_db_client.dat";
44 typedef std::map<OCResourceIdentifier, std::shared_ptr<OCResource>> DiscoveredResourceMap;
45
46 DiscoveredResourceMap discoveredResources;
47 std::shared_ptr<OCResource> curResource;
48 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
49 static OCConnectivityType TRANSPORT_TYPE_TO_USE = OCConnectivityType::CT_ADAPTER_IP;
50 std::mutex curResourceLock;
51
52 class Light
53 {
54 public:
55
56     bool m_state;
57     int m_power;
58     std::string m_name;
59
60     Light() : m_state(false), m_power(0), m_name("")
61     {
62     }
63 };
64
65 Light mylight;
66
67 int observe_count()
68 {
69     static int oc = 0;
70     return ++oc;
71 }
72
73 void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
74                     const int& eCode, const int& sequenceNumber)
75 {
76     try
77     {
78         if(eCode == OC_STACK_OK && sequenceNumber <= MAX_SEQUENCE_NUMBER)
79         {
80             if(sequenceNumber == OC_OBSERVE_REGISTER)
81             {
82                 std::cout << "Observe registration action is successful" << std::endl;
83             }
84
85             std::cout << "OBSERVE RESULT:"<<std::endl;
86             std::cout << "\tSequenceNumber: "<< sequenceNumber << std::endl;
87             rep.getValue("state", mylight.m_state);
88             rep.getValue("power", mylight.m_power);
89             rep.getValue("name", mylight.m_name);
90
91             std::cout << "\tstate: " << mylight.m_state << std::endl;
92             std::cout << "\tpower: " << mylight.m_power << std::endl;
93             std::cout << "\tname: " << mylight.m_name << std::endl;
94
95             if(observe_count() == 11)
96             {
97                 std::cout<<"Cancelling Observe..."<<std::endl;
98                 OCStackResult result = curResource->cancelObserve();
99
100                 std::cout << "Cancel result: "<< result <<std::endl;
101                 sleep(10);
102                 std::cout << "DONE"<<std::endl;
103                 std::exit(0);
104             }
105         }
106         else
107         {
108             if(eCode == OC_STACK_OK)
109             {
110                 std::cout << "No observe option header is returned in the response." << std::endl;
111                 std::cout << "For a registration request, it means the registration failed"
112                         << std::endl;
113             }
114             else
115             {
116                 std::cout << "onObserve Response error: " << eCode << std::endl;
117                 std::exit(-1);
118             }
119         }
120     }
121     catch(std::exception& e)
122     {
123         std::cout << "Exception: " << e.what() << " in onObserve" << std::endl;
124     }
125
126 }
127
128 void onPost2(const HeaderOptions& /*headerOptions*/,
129         const OCRepresentation& rep, const int eCode)
130 {
131     try
132     {
133         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED
134                 || eCode == OC_STACK_RESOURCE_CHANGED)
135         {
136             std::cout << "POST request was successful" << std::endl;
137
138             if(rep.hasAttribute("createduri"))
139             {
140                 std::cout << "\tUri of the created resource: "
141                     << rep.getValue<std::string>("createduri") << std::endl;
142             }
143             else
144             {
145                 rep.getValue("state", mylight.m_state);
146                 rep.getValue("power", mylight.m_power);
147                 rep.getValue("name", mylight.m_name);
148
149                 std::cout << "\tstate: " << mylight.m_state << std::endl;
150                 std::cout << "\tpower: " << mylight.m_power << std::endl;
151                 std::cout << "\tname: " << mylight.m_name << std::endl;
152             }
153
154             if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
155                 std::cout << std::endl << "Observe is used." << std::endl << std::endl;
156             else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
157                 std::cout << std::endl << "ObserveAll is used." << std::endl << std::endl;
158
159             curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
160
161         }
162         else
163         {
164             std::cout << "onPost2 Response error: " << eCode << std::endl;
165             std::exit(-1);
166         }
167     }
168     catch(std::exception& e)
169     {
170         std::cout << "Exception: " << e.what() << " in onPost2" << std::endl;
171     }
172
173 }
174
175 void onPost(const HeaderOptions& /*headerOptions*/,
176         const OCRepresentation& rep, const int eCode)
177 {
178     try
179     {
180         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED
181                 || eCode == OC_STACK_RESOURCE_CHANGED)
182         {
183             std::cout << "POST request was successful" << std::endl;
184
185             if(rep.hasAttribute("createduri"))
186             {
187                 std::cout << "\tUri of the created resource: "
188                     << rep.getValue<std::string>("createduri") << std::endl;
189             }
190             else
191             {
192                 rep.getValue("state", mylight.m_state);
193                 rep.getValue("power", mylight.m_power);
194                 rep.getValue("name", mylight.m_name);
195
196                 std::cout << "\tstate: " << mylight.m_state << std::endl;
197                 std::cout << "\tpower: " << mylight.m_power << std::endl;
198                 std::cout << "\tname: " << mylight.m_name << std::endl;
199             }
200
201             OCRepresentation rep2;
202
203             std::cout << "Posting light representation..."<<std::endl;
204
205             mylight.m_state = true;
206             mylight.m_power = 55;
207
208             rep2.setValue("state", mylight.m_state);
209             rep2.setValue("power", mylight.m_power);
210
211             curResource->post(rep2, QueryParamsMap(), &onPost2);
212         }
213         else
214         {
215             std::cout << "onPost Response error: " << eCode << std::endl;
216             std::exit(-1);
217         }
218     }
219     catch(std::exception& e)
220     {
221         std::cout << "Exception: " << e.what() << " in onPost" << std::endl;
222     }
223 }
224
225 // Local function to put a different state for this resource
226 void postLightRepresentation(std::shared_ptr<OCResource> resource)
227 {
228     if(resource)
229     {
230         OCRepresentation rep;
231
232         std::cout << "Posting light representation..."<<std::endl;
233
234         mylight.m_state = false;
235         mylight.m_power = 105;
236
237         rep.setValue("state", mylight.m_state);
238         rep.setValue("power", mylight.m_power);
239
240         // Invoke resource's post API with rep, query map and the callback parameter
241         resource->post(rep, QueryParamsMap(), &onPost);
242     }
243 }
244
245 // callback handler on PUT request
246 void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
247 {
248     try
249     {
250         if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CHANGED)
251         {
252             std::cout << "PUT request was successful" << std::endl;
253
254             rep.getValue("state", mylight.m_state);
255             rep.getValue("power", mylight.m_power);
256             rep.getValue("name", mylight.m_name);
257
258             std::cout << "\tstate: " << mylight.m_state << std::endl;
259             std::cout << "\tpower: " << mylight.m_power << std::endl;
260             std::cout << "\tname: " << mylight.m_name << std::endl;
261
262             postLightRepresentation(curResource);
263         }
264         else
265         {
266             std::cout << "onPut Response error: " << eCode << std::endl;
267             std::exit(-1);
268         }
269     }
270     catch(std::exception& e)
271     {
272         std::cout << "Exception: " << e.what() << " in onPut" << std::endl;
273     }
274 }
275
276 // Local function to put a different state for this resource
277 void putLightRepresentation(std::shared_ptr<OCResource> resource)
278 {
279     if(resource)
280     {
281         OCRepresentation rep;
282
283         std::cout << "Putting light representation..."<<std::endl;
284
285         mylight.m_state = true;
286         mylight.m_power = 15;
287
288         rep.setValue("state", mylight.m_state);
289         rep.setValue("power", mylight.m_power);
290
291         // Invoke resource's put API with rep, query map and the callback parameter
292         resource->put(rep, QueryParamsMap(), &onPut);
293     }
294 }
295
296 // Callback handler on GET request
297 void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
298 {
299     try
300     {
301         if(eCode == OC_STACK_OK)
302         {
303             std::cout << "GET request was successful" << std::endl;
304             std::cout << "Resource URI: " << rep.getUri() << std::endl;
305
306             rep.getValue("state", mylight.m_state);
307             rep.getValue("power", mylight.m_power);
308             rep.getValue("name", mylight.m_name);
309
310             std::cout << "\tstate: " << mylight.m_state << std::endl;
311             std::cout << "\tpower: " << mylight.m_power << std::endl;
312             std::cout << "\tname: " << mylight.m_name << std::endl;
313
314             putLightRepresentation(curResource);
315         }
316         else
317         {
318             std::cout << "onGET Response error: " << eCode << std::endl;
319             std::exit(-1);
320         }
321     }
322     catch(std::exception& e)
323     {
324         std::cout << "Exception: " << e.what() << " in onGet" << std::endl;
325     }
326 }
327
328 // Local function to get representation of light resource
329 void getLightRepresentation(std::shared_ptr<OCResource> resource)
330 {
331     if(resource)
332     {
333         std::cout << "Getting Light Representation..."<<std::endl;
334         // Invoke resource's get API with the callback parameter
335
336         QueryParamsMap test;
337         resource->get(test, &onGet);
338     }
339 }
340
341 void receivedPlatformInfo(const OCRepresentation& rep)
342 {
343     std::cout << "\nPlatform Information received ---->\n";
344     std::string value;
345     std::string values[] =
346     {
347         "pi",   "Platform ID                    ",
348         "mnmn", "Manufacturer name              ",
349         "mnml", "Manufacturer url               ",
350         "mnmo", "Manufacturer Model No          ",
351         "mndt", "Manufactured Date              ",
352         "mnpv", "Manufacturer Platform Version  ",
353         "mnos", "Manufacturer OS version        ",
354         "mnhw", "Manufacturer hardware version  ",
355         "mnfv", "Manufacturer firmware version  ",
356         "mnsl", "Manufacturer support url       ",
357         "st",   "Manufacturer system time       "
358     };
359
360     for (unsigned int i = 0; i < sizeof(values) / sizeof(values[0]) ; i += 2)
361     {
362         if(rep.getValue(values[i], value))
363         {
364             std::cout << values[i + 1] << " : "<< value << std::endl;
365         }
366     }
367 }
368
369 void receivedDeviceInfo(const OCRepresentation& rep)
370 {
371     std::cout << "\nDevice Information received ---->\n";
372     std::string value;
373     std::string values[] =
374     { 
375         "di",  "Device ID        ",
376         "n",   "Device name      ",
377         "lcv", "Spec version url ",
378         "dmv", "Data Model Model ", 
379     };
380
381     for (unsigned int i = 0; i < sizeof(values) / sizeof(values[0]); i += 2)
382     {
383         if (rep.getValue(values[i], value))
384         {
385             std::cout << values[i + 1] << " : " << value << std::endl;
386         }
387     }
388 }
389
390 // Callback to found resources
391 void foundResource(std::shared_ptr<OCResource> resource)
392 {
393     std::cout << "In foundResource\n";
394     std::string resourceURI;
395     std::string hostAddress;
396
397     std::string platformDiscoveryURI = "/oic/p";
398     std::string deviceDiscoveryURI   = "/oic/d";
399
400     try
401     {
402         {
403             std::lock_guard<std::mutex> lock(curResourceLock);
404             if(discoveredResources.find(resource->uniqueIdentifier()) == discoveredResources.end())
405             {
406                 std::cout << "Found resource " << resource->uniqueIdentifier() <<
407                     " for the first time on server with ID: "<< resource->sid()<<std::endl;
408                 discoveredResources[resource->uniqueIdentifier()] = resource;
409             }
410             else
411             {
412                 std::cout<<"Found resource "<< resource->uniqueIdentifier() << " again!"<<std::endl;
413             }
414
415             if(curResource)
416             {
417                 std::cout << "Found another resource, ignoring"<<std::endl;
418                 return;
419             }
420         }
421
422         // Do some operations with resource object.
423         if(resource)
424         {
425             std::cout<<"DISCOVERED Resource:"<<std::endl;
426             // Get the resource URI
427             resourceURI = resource->uri();
428             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
429
430             // Get the resource host address
431             hostAddress = resource->host();
432             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
433
434             OCStackResult ret;
435
436             std::cout << "Querying for platform information... " << std::endl;
437
438             ret = OCPlatform::getPlatformInfo("", platformDiscoveryURI, CT_ADAPTER_IP,
439                     &receivedPlatformInfo);
440
441             if (ret == OC_STACK_OK)
442             {
443                 std::cout << "Get platform information is done." << std::endl;
444             }
445             else
446             {
447                 std::cout << "Get platform information failed." << std::endl;
448             }
449
450             std::cout << "Querying for device information... " << std::endl;
451
452             ret = OCPlatform::getDeviceInfo(resource->host(), deviceDiscoveryURI,
453                         resource->connectivityType(), &receivedDeviceInfo);
454
455             if (ret == OC_STACK_OK)
456             {
457                 std::cout << "Getting device information is done." << std::endl;
458             }
459             else
460             {
461                 std::cout << "Getting device information failed." << std::endl;
462             }
463
464             // Get the resource types
465             std::cout << "\tList of resource types: " << std::endl;
466             for(auto &resourceTypes : resource->getResourceTypes())
467             {
468                 std::cout << "\t\t" << resourceTypes << std::endl;
469             }
470
471             // Get the resource interfaces
472             std::cout << "\tList of resource interfaces: " << std::endl;
473             for(auto &resourceInterfaces : resource->getResourceInterfaces())
474             {
475                 std::cout << "\t\t" << resourceInterfaces << std::endl;
476             }
477
478             if(resourceURI == "/a/light")
479             {
480                 if (resource->connectivityType() & TRANSPORT_TYPE_TO_USE)
481                 {
482                     curResource = resource;
483                     // Get the resource host address
484                     std::cout << "\tAddress of selected resource: " << resource->host() << std::endl;
485
486                     // Call a local function which will internally invoke get API on the resource pointer
487                     getLightRepresentation(resource);
488                 }
489             }
490         }
491         else
492         {
493             // Resource is invalid
494             std::cout << "Resource is invalid" << std::endl;
495         }
496
497     }
498     catch(std::exception& e)
499     {
500         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
501     }
502 }
503
504 void printUsage()
505 {
506     std::cout << std::endl;
507     std::cout << "---------------------------------------------------------------------\n";
508     std::cout << "Usage : simpleclient <ObserveType> <TransportType>" << std::endl;
509     std::cout << "   ObserveType : 1 - Observe" << std::endl;
510     std::cout << "   ObserveType : 2 - ObserveAll" << std::endl;
511     std::cout << "   TransportType : 1 - IP" << std::endl;
512     std::cout << "   TransportType : 2 - TCP" << std::endl;
513     std::cout << "---------------------------------------------------------------------\n\n";
514 }
515
516 void checkObserverValue(int value)
517 {
518     if (value == 1)
519     {
520         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
521         std::cout << "<===Setting ObserveType to Observe===>\n\n";
522     }
523     else if (value == 2)
524     {
525         OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
526         std::cout << "<===Setting ObserveType to ObserveAll===>\n\n";
527     }
528     else
529     {
530         std::cout << "<===Invalid ObserveType selected."
531                   <<" Setting ObserveType to Observe===>\n\n";
532     }
533 }
534
535 void checkTransportValue(int value)
536 {
537     if (1 == value)
538     {
539         TRANSPORT_TYPE_TO_USE = OCConnectivityType::CT_ADAPTER_IP;
540         std::cout << "<===Setting TransportType to IP===>\n\n";
541     }
542     else if (2 == value)
543     {
544         TRANSPORT_TYPE_TO_USE = OCConnectivityType::CT_ADAPTER_TCP;
545         std::cout << "<===Setting TransportType to TCP===>\n\n";
546     }
547     else
548     {
549         std::cout << "<===Invalid TransportType selected."
550                   <<" Setting TransportType to IP===>\n\n";
551     }
552 }
553
554 static FILE* client_open(const char* /*path*/, const char *mode)
555 {
556     return fopen(SVR_DB_FILE_NAME, mode);
557 }
558
559 int main(int argc, char* argv[]) {
560
561     std::ostringstream requestURI;
562     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
563     try
564     {
565         printUsage();
566         if (argc == 1)
567         {
568             std::cout << "<===Setting ObserveType to Observe and ConnectivityType to IP===>\n\n";
569         }
570         else if (argc == 2)
571         {
572             checkObserverValue(std::stoi(argv[1]));
573         }
574         else if (argc == 3)
575         {
576             checkObserverValue(std::stoi(argv[1]));
577             checkTransportValue(std::stoi(argv[2]));
578         }
579         else
580         {
581             std::cout << "<===Invalid number of command line arguments===>\n\n";
582             return -1;
583         }
584     }
585     catch(std::exception& )
586     {
587         std::cout << "<===Invalid input arguments===>\n\n";
588         return -1;
589     }
590
591     // Create PlatformConfig object
592     PlatformConfig cfg {
593         OC::ServiceType::InProc,
594         OC::ModeType::Both,
595         "0.0.0.0",
596         0,
597         OC::QualityOfService::HighQos,
598         &ps
599     };
600
601     OCPlatform::Configure(cfg);
602     try
603     {
604         // makes it so that all boolean values are printed as 'true/false' in this stream
605         std::cout.setf(std::ios::boolalpha);
606         // Find all resources
607         requestURI << OC_RSRVD_WELL_KNOWN_URI;// << "?rt=core.light";
608
609         OCPlatform::findResource("", requestURI.str(),
610                 CT_DEFAULT, &foundResource);
611         std::cout<< "Finding Resource... " <<std::endl;
612
613         // Find resource is done twice so that we discover the original resources a second time.
614         // These resources will have the same uniqueidentifier (yet be different objects), so that
615         // we can verify/show the duplicate-checking code in foundResource(above);
616         OCPlatform::findResource("", requestURI.str(),
617                 CT_DEFAULT, &foundResource);
618         std::cout<< "Finding Resource for second time..." << std::endl;
619
620         // A condition variable will free the mutex it is given, then do a non-
621         // intensive block until 'notify' is called on it.  In this case, since we
622         // don't ever call cv.notify, this should be a non-processor intensive version
623         // of while(true);
624         std::mutex blocker;
625         std::condition_variable cv;
626         std::unique_lock<std::mutex> lock(blocker);
627         cv.wait(lock);
628
629     }catch(OCException& e)
630     {
631         oclog() << "Exception in main: "<<e.what();
632     }
633
634     return 0;
635 }
636
637