replace : iotivity -> iotivity-sec
[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 // Callback to found resources
342 void foundResource(std::shared_ptr<OCResource> resource)
343 {
344     std::cout << "In foundResource\n";
345     std::string resourceURI;
346     std::string hostAddress;
347     try
348     {
349         {
350             std::lock_guard<std::mutex> lock(curResourceLock);
351             if(discoveredResources.find(resource->uniqueIdentifier()) == discoveredResources.end())
352             {
353                 std::cout << "Found resource " << resource->uniqueIdentifier() <<
354                     " for the first time on server with ID: "<< resource->sid()<<std::endl;
355                 discoveredResources[resource->uniqueIdentifier()] = resource;
356             }
357             else
358             {
359                 std::cout<<"Found resource "<< resource->uniqueIdentifier() << " again!"<<std::endl;
360             }
361
362             if(curResource)
363             {
364                 std::cout << "Found another resource, ignoring"<<std::endl;
365                 return;
366             }
367         }
368
369         // Do some operations with resource object.
370         if(resource)
371         {
372             std::cout<<"DISCOVERED Resource:"<<std::endl;
373             // Get the resource URI
374             resourceURI = resource->uri();
375             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
376
377             // Get the resource host address
378             hostAddress = resource->host();
379             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
380
381             // Get the resource types
382             std::cout << "\tList of resource types: " << std::endl;
383             for(auto &resourceTypes : resource->getResourceTypes())
384             {
385                 std::cout << "\t\t" << resourceTypes << std::endl;
386             }
387
388             // Get the resource interfaces
389             std::cout << "\tList of resource interfaces: " << std::endl;
390             for(auto &resourceInterfaces : resource->getResourceInterfaces())
391             {
392                 std::cout << "\t\t" << resourceInterfaces << std::endl;
393             }
394
395             if(resourceURI == "/a/light")
396             {
397                 if (resource->connectivityType() & TRANSPORT_TYPE_TO_USE)
398                 {
399                     curResource = resource;
400                     // Get the resource host address
401                     std::cout << "\tAddress of selected resource: " << resource->host() << std::endl;
402
403                     // Call a local function which will internally invoke get API on the resource pointer
404                     getLightRepresentation(resource);
405                 }
406             }
407         }
408         else
409         {
410             // Resource is invalid
411             std::cout << "Resource is invalid" << std::endl;
412         }
413
414     }
415     catch(std::exception& e)
416     {
417         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
418     }
419 }
420
421 void printUsage()
422 {
423     std::cout << std::endl;
424     std::cout << "---------------------------------------------------------------------\n";
425     std::cout << "Usage : simpleclient <ObserveType> <TransportType>" << std::endl;
426     std::cout << "   ObserveType : 1 - Observe" << std::endl;
427     std::cout << "   ObserveType : 2 - ObserveAll" << std::endl;
428     std::cout << "   TransportType : 1 - IP" << std::endl;
429     std::cout << "   TransportType : 2 - TCP" << std::endl;
430     std::cout << "---------------------------------------------------------------------\n\n";
431 }
432
433 void checkObserverValue(int value)
434 {
435     if (value == 1)
436     {
437         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
438         std::cout << "<===Setting ObserveType to Observe===>\n\n";
439     }
440     else if (value == 2)
441     {
442         OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
443         std::cout << "<===Setting ObserveType to ObserveAll===>\n\n";
444     }
445     else
446     {
447         std::cout << "<===Invalid ObserveType selected."
448                   <<" Setting ObserveType to Observe===>\n\n";
449     }
450 }
451
452 void checkTransportValue(int value)
453 {
454     if (1 == value)
455     {
456         TRANSPORT_TYPE_TO_USE = OCConnectivityType::CT_ADAPTER_IP;
457         std::cout << "<===Setting TransportType to IP===>\n\n";
458     }
459     else if (2 == value)
460     {
461         TRANSPORT_TYPE_TO_USE = OCConnectivityType::CT_ADAPTER_TCP;
462         std::cout << "<===Setting TransportType to TCP===>\n\n";
463     }
464     else
465     {
466         std::cout << "<===Invalid TransportType selected."
467                   <<" Setting TransportType to IP===>\n\n";
468     }
469 }
470
471 static FILE* client_open(const char* /*path*/, const char *mode)
472 {
473     return fopen(SVR_DB_FILE_NAME, mode);
474 }
475
476 int main(int argc, char* argv[]) {
477
478     std::ostringstream requestURI;
479     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink, NULL, NULL};
480     try
481     {
482         printUsage();
483         if (argc == 1)
484         {
485             std::cout << "<===Setting ObserveType to Observe and ConnectivityType to IP===>\n\n";
486         }
487         else if (argc == 2)
488         {
489             checkObserverValue(std::stoi(argv[1]));
490         }
491         else if (argc == 3)
492         {
493             checkObserverValue(std::stoi(argv[1]));
494             checkTransportValue(std::stoi(argv[2]));
495         }
496         else
497         {
498             std::cout << "<===Invalid number of command line arguments===>\n\n";
499             return -1;
500         }
501     }
502     catch(std::exception& )
503     {
504         std::cout << "<===Invalid input arguments===>\n\n";
505         return -1;
506     }
507
508     // Create PlatformConfig object
509     PlatformConfig cfg {
510         OC::ServiceType::InProc,
511         OC::ModeType::Both,
512         OCConnectivityType::CT_ADAPTER_IP,
513         OCConnectivityType::CT_ADAPTER_IP,
514         (OCTransportAdapter)(OCTransportAdapter::OC_ADAPTER_IP|OCTransportAdapter::OC_ADAPTER_TCP),
515         OC::QualityOfService::HighQos,
516         &ps
517     };
518
519     OCPlatform::Configure(cfg);
520     try
521     {
522         // makes it so that all boolean values are printed as 'true/false' in this stream
523         std::cout.setf(std::ios::boolalpha);
524         // Find all resources
525         requestURI << OC_RSRVD_WELL_KNOWN_URI;// << "?rt=core.light";
526
527         OCPlatform::findResource("", requestURI.str(),
528                 CT_DEFAULT, &foundResource);
529         std::cout<< "Finding Resource... " <<std::endl;
530
531         // Find resource is done twice so that we discover the original resources a second time.
532         // These resources will have the same uniqueidentifier (yet be different objects), so that
533         // we can verify/show the duplicate-checking code in foundResource(above);
534         OCPlatform::findResource("", requestURI.str(),
535                 CT_DEFAULT, &foundResource);
536         std::cout<< "Finding Resource for second time..." << std::endl;
537
538         // A condition variable will free the mutex it is given, then do a non-
539         // intensive block until 'notify' is called on it.  In this case, since we
540         // don't ever call cv.notify, this should be a non-processor intensive version
541         // of while(true);
542         std::mutex blocker;
543         std::condition_variable cv;
544         std::unique_lock<std::mutex> lock(blocker);
545         cv.wait(lock);
546
547     }catch(OCException& e)
548     {
549         oclog() << "Exception in main: "<<e.what();
550     }
551
552     return 0;
553 }
554
555