Merge "Fixed seg fault in simpleclient sample app (Bug IOT-130)"
[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 <cstdlib>
25 #include <pthread.h>
26 #include <mutex>
27 #include <condition_variable>
28
29 #include "OCPlatform.h"
30 #include "OCApi.h"
31
32 using namespace OC;
33
34 std::shared_ptr<OCResource> curResource;
35 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
36 std::mutex curResourceLock;
37
38 class Light
39 {
40 public:
41
42     bool m_state;
43     int m_power;
44     std::string m_name;
45
46     Light() : m_state(false), m_power(0), m_name("")
47     {
48     }
49 };
50
51 Light mylight;
52
53 int observe_count()
54 {
55     static int oc = 0;
56     return ++oc;
57 }
58
59 void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
60                     const int& eCode, const int& sequenceNumber)
61 {
62     try
63     {
64         if(eCode == OC_STACK_OK)
65         {
66             std::cout << "OBSERVE RESULT:"<<std::endl;
67             std::cout << "\tSequenceNumber: "<< sequenceNumber << endl;
68
69             rep.getValue("state", mylight.m_state);
70             rep.getValue("power", mylight.m_power);
71             rep.getValue("name", mylight.m_name);
72
73             std::cout << "\tstate: " << mylight.m_state << std::endl;
74             std::cout << "\tpower: " << mylight.m_power << std::endl;
75             std::cout << "\tname: " << mylight.m_name << std::endl;
76
77             if(observe_count() > 30)
78             {
79                 std::cout<<"Cancelling Observe..."<<std::endl;
80                 OCStackResult result = curResource->cancelObserve();
81
82                 std::cout << "Cancel result: "<< result <<std::endl;
83                 sleep(10);
84                 std::cout << "DONE"<<std::endl;
85                 std::exit(0);
86             }
87         }
88         else
89         {
90             std::cout << "onObserve Response error: " << eCode << std::endl;
91             std::exit(-1);
92         }
93     }
94     catch(std::exception& e)
95     {
96         std::cout << "Exception: " << e.what() << " in onObserve" << std::endl;
97     }
98
99 }
100
101 void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
102 {
103     try
104     {
105         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)
106         {
107             std::cout << "POST request was successful" << std::endl;
108
109             if(rep.hasAttribute("createduri"))
110             {
111                 std::cout << "\tUri of the created resource: "
112                     << rep.getValue<std::string>("createduri") << std::endl;
113             }
114             else
115             {
116                 rep.getValue("state", mylight.m_state);
117                 rep.getValue("power", mylight.m_power);
118                 rep.getValue("name", mylight.m_name);
119
120                 std::cout << "\tstate: " << mylight.m_state << std::endl;
121                 std::cout << "\tpower: " << mylight.m_power << std::endl;
122                 std::cout << "\tname: " << mylight.m_name << std::endl;
123             }
124
125             if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
126                 std::cout << endl << "Observe is used." << endl << endl;
127             else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
128                 std::cout << endl << "ObserveAll is used." << endl << endl;
129
130             curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
131
132         }
133         else
134         {
135             std::cout << "onPost2 Response error: " << eCode << std::endl;
136             std::exit(-1);
137         }
138     }
139     catch(std::exception& e)
140     {
141         std::cout << "Exception: " << e.what() << " in onPost2" << std::endl;
142     }
143
144 }
145
146 void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
147 {
148     try
149     {
150         if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)
151         {
152             std::cout << "POST request was successful" << std::endl;
153
154             if(rep.hasAttribute("createduri"))
155             {
156                 std::cout << "\tUri of the created resource: "
157                     << rep.getValue<std::string>("createduri") << std::endl;
158             }
159             else
160             {
161                 rep.getValue("state", mylight.m_state);
162                 rep.getValue("power", mylight.m_power);
163                 rep.getValue("name", mylight.m_name);
164
165                 std::cout << "\tstate: " << mylight.m_state << std::endl;
166                 std::cout << "\tpower: " << mylight.m_power << std::endl;
167                 std::cout << "\tname: " << mylight.m_name << std::endl;
168             }
169
170             OCRepresentation rep2;
171
172             std::cout << "Posting light representation..."<<std::endl;
173
174             mylight.m_state = true;
175             mylight.m_power = 55;
176
177             rep2.setValue("state", mylight.m_state);
178             rep2.setValue("power", mylight.m_power);
179
180             curResource->post(rep2, QueryParamsMap(), &onPost2);
181         }
182         else
183         {
184             std::cout << "onPost Response error: " << eCode << std::endl;
185             std::exit(-1);
186         }
187     }
188     catch(std::exception& e)
189     {
190         std::cout << "Exception: " << e.what() << " in onPost" << std::endl;
191     }
192 }
193
194 // Local function to put a different state for this resource
195 void postLightRepresentation(std::shared_ptr<OCResource> resource)
196 {
197     if(resource)
198     {
199         OCRepresentation rep;
200
201         std::cout << "Posting light representation..."<<std::endl;
202
203         mylight.m_state = false;
204         mylight.m_power = 105;
205
206         rep.setValue("state", mylight.m_state);
207         rep.setValue("power", mylight.m_power);
208
209         // Invoke resource's post API with rep, query map and the callback parameter
210         resource->post(rep, QueryParamsMap(), &onPost);
211     }
212 }
213
214 // callback handler on PUT request
215 void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
216 {
217     try
218     {
219         if(eCode == OC_STACK_OK)
220         {
221             std::cout << "PUT request was successful" << std::endl;
222
223             rep.getValue("state", mylight.m_state);
224             rep.getValue("power", mylight.m_power);
225             rep.getValue("name", mylight.m_name);
226
227             std::cout << "\tstate: " << mylight.m_state << std::endl;
228             std::cout << "\tpower: " << mylight.m_power << std::endl;
229             std::cout << "\tname: " << mylight.m_name << std::endl;
230
231             postLightRepresentation(curResource);
232         }
233         else
234         {
235             std::cout << "onPut Response error: " << eCode << std::endl;
236             std::exit(-1);
237         }
238     }
239     catch(std::exception& e)
240     {
241         std::cout << "Exception: " << e.what() << " in onPut" << std::endl;
242     }
243 }
244
245 // Local function to put a different state for this resource
246 void putLightRepresentation(std::shared_ptr<OCResource> resource)
247 {
248     if(resource)
249     {
250         OCRepresentation rep;
251
252         std::cout << "Putting light representation..."<<std::endl;
253
254         mylight.m_state = true;
255         mylight.m_power = 15;
256
257         rep.setValue("state", mylight.m_state);
258         rep.setValue("power", mylight.m_power);
259
260         // Invoke resource's put API with rep, query map and the callback parameter
261         resource->put(rep, QueryParamsMap(), &onPut);
262     }
263 }
264
265 // Callback handler on GET request
266 void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
267 {
268     try
269     {
270         if(eCode == OC_STACK_OK)
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
283             putLightRepresentation(curResource);
284         }
285         else
286         {
287             std::cout << "onGET Response error: " << eCode << std::endl;
288             std::exit(-1);
289         }
290     }
291     catch(std::exception& e)
292     {
293         std::cout << "Exception: " << e.what() << " in onGet" << std::endl;
294     }
295 }
296
297 // Local function to get representation of light resource
298 void getLightRepresentation(std::shared_ptr<OCResource> resource)
299 {
300     if(resource)
301     {
302         std::cout << "Getting Light Representation..."<<std::endl;
303         // Invoke resource's get API with the callback parameter
304
305         QueryParamsMap test;
306         resource->get(test, &onGet);
307     }
308 }
309
310 // Callback to found resources
311 void foundResource(std::shared_ptr<OCResource> resource)
312 {
313     std::lock_guard<std::mutex> lock(curResourceLock);
314     if(curResource)
315     {
316         std::cout << "Found another resource, ignoring"<<std::endl;
317         return;
318     }
319
320     std::string resourceURI;
321     std::string hostAddress;
322     try
323     {
324         // Do some operations with resource object.
325         if(resource)
326         {
327             std::cout<<"DISCOVERED Resource:"<<std::endl;
328             // Get the resource URI
329             resourceURI = resource->uri();
330             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
331
332             // Get the resource host address
333             hostAddress = resource->host();
334             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
335
336             // Get the resource types
337             std::cout << "\tList of resource types: " << std::endl;
338             for(auto &resourceTypes : resource->getResourceTypes())
339             {
340                 std::cout << "\t\t" << resourceTypes << std::endl;
341             }
342
343             // Get the resource interfaces
344             std::cout << "\tList of resource interfaces: " << std::endl;
345             for(auto &resourceInterfaces : resource->getResourceInterfaces())
346             {
347                 std::cout << "\t\t" << resourceInterfaces << std::endl;
348             }
349
350             if(resourceURI == "/a/light")
351             {
352                 curResource = resource;
353                 // Call a local function which will internally invoke get API on the resource pointer
354                 getLightRepresentation(resource);
355             }
356         }
357         else
358         {
359             // Resource is invalid
360             std::cout << "Resource is invalid" << std::endl;
361         }
362
363     }
364     catch(std::exception& e)
365     {
366         //log(e.what());
367     }
368 }
369
370 void PrintUsage()
371 {
372     std::cout << std::endl;
373     std::cout << "Usage : simpleclient <ObserveType>" << std::endl;
374     std::cout << "   ObserveType : 1 - Observe" << std::endl;
375     std::cout << "   ObserveType : 2 - ObserveAll" << std::endl;
376 }
377
378 int main(int argc, char* argv[]) {
379     if (argc == 1)
380     {
381         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
382     }
383     else if (argc == 2)
384     {
385         int value = atoi(argv[1]);
386         if (value == 1)
387             OBSERVE_TYPE_TO_USE = ObserveType::Observe;
388         else if (value == 2)
389             OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
390         else
391             OBSERVE_TYPE_TO_USE = ObserveType::Observe;
392     }
393     else
394     {
395         PrintUsage();
396         return -1;
397     }
398
399     // Create PlatformConfig object
400     PlatformConfig cfg {
401         OC::ServiceType::InProc,
402         OC::ModeType::Client,
403         "0.0.0.0",
404         0,
405         OC::QualityOfService::LowQos
406     };
407
408     OCPlatform::Configure(cfg);
409     try
410     {
411         // makes it so that all boolean values are printed as 'true/false' in this stream
412         std::cout.setf(std::ios::boolalpha);
413         // Find all resources
414         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
415         std::cout<< "Finding Resource... " <<std::endl;
416
417         // A condition variable will free the mutex it is given, then do a non-
418         // intensive block until 'notify' is called on it.  In this case, since we
419         // don't ever call cv.notify, this should be a non-processor intensive version
420         // of while(true);
421         std::mutex blocker;
422         std::condition_variable cv;
423         std::unique_lock<std::mutex> lock(blocker);
424         cv.wait(lock);
425
426     }catch(OCException& e)
427     {
428         //log(e.what());
429     }
430
431     return 0;
432 }
433