Imported Upstream version 1.1.1
[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 #define maxSequenceNumber 0xFFFFFF
33
34 using namespace OC;
35
36 static const char* SVR_DB_FILE_NAME = "./oic_svr_db_client.dat";
37 typedef std::map<OCResourceIdentifier, std::shared_ptr<OCResource>> DiscoveredResourceMap;
38
39 DiscoveredResourceMap discoveredResources;
40 std::shared_ptr<OCResource> curResource;
41 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
42 std::mutex curResourceLock;
43
44 class Light
45 {
46 public:
47
48     bool m_state;
49     int m_power;
50     std::string m_name;
51
52     Light() : m_state(false), m_power(0), m_name("")
53     {
54     }
55 };
56
57 Light mylight;
58
59 int observe_count()
60 {
61     static int oc = 0;
62     return ++oc;
63 }
64
65 void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
66                     const int& eCode, const int& sequenceNumber)
67 {
68     try
69     {
70         if(eCode == OC_STACK_OK && sequenceNumber != maxSequenceNumber + 1)
71         {
72             if(sequenceNumber == OC_OBSERVE_REGISTER)
73             {
74                 std::cout << "Observe registration action is successful" << std::endl;
75             }
76
77             std::cout << "OBSERVE RESULT:"<<std::endl;
78             std::cout << "\tSequenceNumber: "<< sequenceNumber << std::endl;
79             rep.getValue("state", mylight.m_state);
80             rep.getValue("power", mylight.m_power);
81             rep.getValue("name", mylight.m_name);
82
83             std::cout << "\tstate: " << mylight.m_state << std::endl;
84             std::cout << "\tpower: " << mylight.m_power << std::endl;
85             std::cout << "\tname: " << mylight.m_name << std::endl;
86
87             if(observe_count() == 11)
88             {
89                 std::cout<<"Cancelling Observe..."<<std::endl;
90                 OCStackResult result = curResource->cancelObserve();
91
92                 std::cout << "Cancel result: "<< result <<std::endl;
93                 sleep(10);
94                 std::cout << "DONE"<<std::endl;
95                 std::exit(0);
96             }
97         }
98         else
99         {
100             if(eCode == OC_STACK_OK)
101             {
102                 std::cout << "Observe registration failed or de-registration action failed/succeeded" << std::endl;
103             }
104             else
105             {
106                 std::cout << "onObserve Response error: " << eCode << std::endl;
107                 std::exit(-1);
108             }
109         }
110     }
111     catch(std::exception& e)
112     {
113         std::cout << "Exception: " << e.what() << " in onObserve" << std::endl;
114     }
115
116 }
117
118 void onPost2(const HeaderOptions& /*headerOptions*/,
119         const OCRepresentation& rep, const int eCode)
120 {
121     try
122     {
123         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED
124                 || eCode == OC_STACK_RESOURCE_CHANGED)
125         {
126             std::cout << "POST request was successful" << std::endl;
127
128             if(rep.hasAttribute("createduri"))
129             {
130                 std::cout << "\tUri of the created resource: "
131                     << rep.getValue<std::string>("createduri") << std::endl;
132             }
133             else
134             {
135                 rep.getValue("state", mylight.m_state);
136                 rep.getValue("power", mylight.m_power);
137                 rep.getValue("name", mylight.m_name);
138
139                 std::cout << "\tstate: " << mylight.m_state << std::endl;
140                 std::cout << "\tpower: " << mylight.m_power << std::endl;
141                 std::cout << "\tname: " << mylight.m_name << std::endl;
142             }
143
144             if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
145                 std::cout << std::endl << "Observe is used." << std::endl << std::endl;
146             else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
147                 std::cout << std::endl << "ObserveAll is used." << std::endl << std::endl;
148
149             curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
150
151         }
152         else
153         {
154             std::cout << "onPost2 Response error: " << eCode << std::endl;
155             std::exit(-1);
156         }
157     }
158     catch(std::exception& e)
159     {
160         std::cout << "Exception: " << e.what() << " in onPost2" << std::endl;
161     }
162
163 }
164
165 void onPost(const HeaderOptions& /*headerOptions*/,
166         const OCRepresentation& rep, const int eCode)
167 {
168     try
169     {
170         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED
171                 || eCode == OC_STACK_RESOURCE_CHANGED)
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 || eCode == OC_STACK_RESOURCE_CHANGED)
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::HighQos,
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