07d55f0dba9bde41aed250a1acca08381a9eacfa
[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 <string>
24 #include <map>
25 #include <cstdlib>
26 #include <pthread.h>
27 #include <mutex>
28 #include <condition_variable>
29 #include "OCPlatform.h"
30 #include "OCApi.h"
31
32 using namespace OC;
33
34 static const char* SVR_DB_FILE_NAME = "./oic_svr_db_client.dat";
35 typedef std::map<OCResourceIdentifier, std::shared_ptr<OCResource>> DiscoveredResourceMap;
36
37 DiscoveredResourceMap discoveredResources;
38 std::shared_ptr<OCResource> curResource;
39 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
40 std::mutex curResourceLock;
41
42 class Light
43 {
44 public:
45
46     bool m_state;
47     int m_power;
48     std::string m_name;
49
50     Light() : m_state(false), m_power(0), m_name("")
51     {
52     }
53 };
54
55 Light mylight;
56
57 int observe_count()
58 {
59     static int oc = 0;
60     return ++oc;
61 }
62
63 void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
64                     const int& eCode, const int& sequenceNumber)
65 {
66     try
67     {
68         if(eCode == OC_STACK_OK && sequenceNumber != OC_OBSERVE_NO_OPTION)
69         {
70             if(sequenceNumber == OC_OBSERVE_REGISTER)
71             {
72                 std::cout << "Observe registration action is successful" << std::endl;
73             }
74             else if(sequenceNumber == OC_OBSERVE_DEREGISTER)
75             {
76                 std::cout << "Observe De-registration action is successful" << std::endl;
77             }
78
79             std::cout << "OBSERVE RESULT:"<<std::endl;
80             std::cout << "\tSequenceNumber: "<< sequenceNumber << std::endl;
81             rep.getValue("state", mylight.m_state);
82             rep.getValue("power", mylight.m_power);
83             rep.getValue("name", mylight.m_name);
84
85             std::cout << "\tstate: " << mylight.m_state << std::endl;
86             std::cout << "\tpower: " << mylight.m_power << std::endl;
87             std::cout << "\tname: " << mylight.m_name << std::endl;
88
89             if(observe_count() == 11)
90             {
91                 std::cout<<"Cancelling Observe..."<<std::endl;
92                 OCStackResult result = curResource->cancelObserve();
93
94                 std::cout << "Cancel result: "<< result <<std::endl;
95                 sleep(10);
96                 std::cout << "DONE"<<std::endl;
97                 std::exit(0);
98             }
99         }
100         else
101         {
102             if(sequenceNumber == OC_OBSERVE_NO_OPTION)
103             {
104                 std::cout << "Observe registration or de-registration action is failed" << std::endl;
105             }
106             else
107             {
108                 std::cout << "onObserve Response error: " << eCode << std::endl;
109                 std::exit(-1);
110             }
111         }
112     }
113     catch(std::exception& e)
114     {
115         std::cout << "Exception: " << e.what() << " in onObserve" << std::endl;
116     }
117
118 }
119
120 void onPost2(const HeaderOptions& /*headerOptions*/,
121         const OCRepresentation& rep, const int eCode)
122 {
123     try
124     {
125         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)
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
150             curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
151
152         }
153         else
154         {
155             std::cout << "onPost2 Response error: " << eCode << std::endl;
156             std::exit(-1);
157         }
158     }
159     catch(std::exception& e)
160     {
161         std::cout << "Exception: " << e.what() << " in onPost2" << std::endl;
162     }
163
164 }
165
166 void onPost(const HeaderOptions& /*headerOptions*/,
167         const OCRepresentation& rep, const int eCode)
168 {
169     try
170     {
171         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)
172         {
173             std::cout << "POST request was successful" << std::endl;
174
175             if(rep.hasAttribute("createduri"))
176             {
177                 std::cout << "\tUri of the created resource: "
178                     << rep.getValue<std::string>("createduri") << std::endl;
179             }
180             else
181             {
182                 rep.getValue("state", mylight.m_state);
183                 rep.getValue("power", mylight.m_power);
184                 rep.getValue("name", mylight.m_name);
185
186                 std::cout << "\tstate: " << mylight.m_state << std::endl;
187                 std::cout << "\tpower: " << mylight.m_power << std::endl;
188                 std::cout << "\tname: " << mylight.m_name << std::endl;
189             }
190
191             OCRepresentation rep2;
192
193             std::cout << "Posting light representation..."<<std::endl;
194
195             mylight.m_state = true;
196             mylight.m_power = 55;
197
198             rep2.setValue("state", mylight.m_state);
199             rep2.setValue("power", mylight.m_power);
200
201             curResource->post(rep2, QueryParamsMap(), &onPost2);
202         }
203         else
204         {
205             std::cout << "onPost Response error: " << eCode << std::endl;
206             std::exit(-1);
207         }
208     }
209     catch(std::exception& e)
210     {
211         std::cout << "Exception: " << e.what() << " in onPost" << std::endl;
212     }
213 }
214
215 // Local function to put a different state for this resource
216 void postLightRepresentation(std::shared_ptr<OCResource> resource)
217 {
218     if(resource)
219     {
220         OCRepresentation rep;
221
222         std::cout << "Posting light representation..."<<std::endl;
223
224         mylight.m_state = false;
225         mylight.m_power = 105;
226
227         rep.setValue("state", mylight.m_state);
228         rep.setValue("power", mylight.m_power);
229
230         // Invoke resource's post API with rep, query map and the callback parameter
231         resource->post(rep, QueryParamsMap(), &onPost);
232     }
233 }
234
235 // callback handler on PUT request
236 void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
237 {
238     try
239     {
240         if(eCode == OC_STACK_OK)
241         {
242             std::cout << "PUT request was successful" << std::endl;
243
244             rep.getValue("state", mylight.m_state);
245             rep.getValue("power", mylight.m_power);
246             rep.getValue("name", mylight.m_name);
247
248             std::cout << "\tstate: " << mylight.m_state << std::endl;
249             std::cout << "\tpower: " << mylight.m_power << std::endl;
250             std::cout << "\tname: " << mylight.m_name << std::endl;
251
252             postLightRepresentation(curResource);
253         }
254         else
255         {
256             std::cout << "onPut Response error: " << eCode << std::endl;
257             std::exit(-1);
258         }
259     }
260     catch(std::exception& e)
261     {
262         std::cout << "Exception: " << e.what() << " in onPut" << std::endl;
263     }
264 }
265
266 // Local function to put a different state for this resource
267 void putLightRepresentation(std::shared_ptr<OCResource> resource)
268 {
269     if(resource)
270     {
271         OCRepresentation rep;
272
273         std::cout << "Putting light representation..."<<std::endl;
274
275         mylight.m_state = true;
276         mylight.m_power = 15;
277
278         rep.setValue("state", mylight.m_state);
279         rep.setValue("power", mylight.m_power);
280
281         // Invoke resource's put API with rep, query map and the callback parameter
282         resource->put(rep, QueryParamsMap(), &onPut);
283     }
284 }
285
286 // Callback handler on GET request
287 void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
288 {
289     try
290     {
291         if(eCode == OC_STACK_OK)
292         {
293             std::cout << "GET request was successful" << std::endl;
294             std::cout << "Resource URI: " << rep.getUri() << std::endl;
295
296             rep.getValue("state", mylight.m_state);
297             rep.getValue("power", mylight.m_power);
298             rep.getValue("name", mylight.m_name);
299
300             std::cout << "\tstate: " << mylight.m_state << std::endl;
301             std::cout << "\tpower: " << mylight.m_power << std::endl;
302             std::cout << "\tname: " << mylight.m_name << std::endl;
303
304             putLightRepresentation(curResource);
305         }
306         else
307         {
308             std::cout << "onGET Response error: " << eCode << std::endl;
309             std::exit(-1);
310         }
311     }
312     catch(std::exception& e)
313     {
314         std::cout << "Exception: " << e.what() << " in onGet" << std::endl;
315     }
316 }
317
318 // Local function to get representation of light resource
319 void getLightRepresentation(std::shared_ptr<OCResource> resource)
320 {
321     if(resource)
322     {
323         std::cout << "Getting Light Representation..."<<std::endl;
324         // Invoke resource's get API with the callback parameter
325
326         QueryParamsMap test;
327         resource->get(test, &onGet);
328     }
329 }
330
331 // Callback to found resources
332 void foundResource(std::shared_ptr<OCResource> resource)
333 {
334     std::cout << "In foundResource\n";
335     std::string resourceURI;
336     std::string hostAddress;
337     try
338     {
339         {
340             std::lock_guard<std::mutex> lock(curResourceLock);
341             if(discoveredResources.find(resource->uniqueIdentifier()) == discoveredResources.end())
342             {
343                 std::cout << "Found resource " << resource->uniqueIdentifier() <<
344                     " for the first time on server with ID: "<< resource->sid()<<std::endl;
345                 discoveredResources[resource->uniqueIdentifier()] = resource;
346             }
347             else
348             {
349                 std::cout<<"Found resource "<< resource->uniqueIdentifier() << " again!"<<std::endl;
350             }
351
352             if(curResource)
353             {
354                 std::cout << "Found another resource, ignoring"<<std::endl;
355                 return;
356             }
357         }
358
359         // Do some operations with resource object.
360         if(resource)
361         {
362             std::cout<<"DISCOVERED Resource:"<<std::endl;
363             // Get the resource URI
364             resourceURI = resource->uri();
365             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
366
367             // Get the resource host address
368             hostAddress = resource->host();
369             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
370
371             // Get the resource types
372             std::cout << "\tList of resource types: " << std::endl;
373             for(auto &resourceTypes : resource->getResourceTypes())
374             {
375                 std::cout << "\t\t" << resourceTypes << std::endl;
376             }
377
378             // Get the resource interfaces
379             std::cout << "\tList of resource interfaces: " << std::endl;
380             for(auto &resourceInterfaces : resource->getResourceInterfaces())
381             {
382                 std::cout << "\t\t" << resourceInterfaces << std::endl;
383             }
384
385             if(resourceURI == "/a/light")
386             {
387                 curResource = resource;
388                 // Call a local function which will internally invoke get API on the resource pointer
389                 getLightRepresentation(resource);
390             }
391         }
392         else
393         {
394             // Resource is invalid
395             std::cout << "Resource is invalid" << std::endl;
396         }
397
398     }
399     catch(std::exception& e)
400     {
401         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
402     }
403 }
404
405 void printUsage()
406 {
407     std::cout << std::endl;
408     std::cout << "---------------------------------------------------------------------\n";
409     std::cout << "Usage : simpleclient <ObserveType>" << std::endl;
410     std::cout << "   ObserveType : 1 - Observe" << std::endl;
411     std::cout << "   ObserveType : 2 - ObserveAll" << std::endl;
412     std::cout << "---------------------------------------------------------------------\n\n";
413 }
414
415 void checkObserverValue(int value)
416 {
417     if (value == 1)
418     {
419         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
420         std::cout << "<===Setting ObserveType to Observe===>\n\n";
421     }
422     else if (value == 2)
423     {
424         OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
425         std::cout << "<===Setting ObserveType to ObserveAll===>\n\n";
426     }
427     else
428     {
429         std::cout << "<===Invalid ObserveType selected."
430                   <<" Setting ObserveType to Observe===>\n\n";
431     }
432 }
433
434 static FILE* client_open(const char* /*path*/, const char *mode)
435 {
436     return fopen(SVR_DB_FILE_NAME, mode);
437 }
438
439 int main(int argc, char* argv[]) {
440
441     std::ostringstream requestURI;
442     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
443     try
444     {
445         printUsage();
446         if (argc == 1)
447         {
448             std::cout << "<===Setting ObserveType to Observe and ConnectivityType to IP===>\n\n";
449         }
450         else if (argc == 2)
451         {
452             checkObserverValue(std::stoi(argv[1]));
453         }
454         else
455         {
456             std::cout << "<===Invalid number of command line arguments===>\n\n";
457             return -1;
458         }
459     }
460     catch(std::exception& )
461     {
462         std::cout << "<===Invalid input arguments===>\n\n";
463         return -1;
464     }
465
466     // Create PlatformConfig object
467     PlatformConfig cfg {
468         OC::ServiceType::InProc,
469         OC::ModeType::Both,
470         "0.0.0.0",
471         0,
472         OC::QualityOfService::LowQos,
473         &ps
474     };
475
476     OCPlatform::Configure(cfg);
477     try
478     {
479         // makes it so that all boolean values are printed as 'true/false' in this stream
480         std::cout.setf(std::ios::boolalpha);
481         // Find all resources
482         requestURI << OC_RSRVD_WELL_KNOWN_URI;// << "?rt=core.light";
483
484         OCPlatform::findResource("", requestURI.str(),
485                 CT_DEFAULT, &foundResource);
486         std::cout<< "Finding Resource... " <<std::endl;
487
488         // Find resource is done twice so that we discover the original resources a second time.
489         // These resources will have the same uniqueidentifier (yet be different objects), so that
490         // we can verify/show the duplicate-checking code in foundResource(above);
491         OCPlatform::findResource("", requestURI.str(),
492                 CT_DEFAULT, &foundResource);
493         std::cout<< "Finding Resource for second time..." << std::endl;
494
495         // A condition variable will free the mutex it is given, then do a non-
496         // intensive block until 'notify' is called on it.  In this case, since we
497         // don't ever call cv.notify, this should be a non-processor intensive version
498         // of while(true);
499         std::mutex blocker;
500         std::condition_variable cv;
501         std::unique_lock<std::mutex> lock(blocker);
502         cv.wait(lock);
503
504     }catch(OCException& e)
505     {
506         oclog() << "Exception in main: "<<e.what();
507     }
508
509     return 0;
510 }
511
512