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