Removed #ifdef CA_INTs and other code cleanup.
[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 <set>
24 #include <string>
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 struct dereference_compare
35 {
36     bool operator()(std::shared_ptr<OCResource> lhs, std::shared_ptr<OCResource> rhs )const
37     {
38         return *lhs < *rhs;
39     }
40 };
41 typedef std::set<std::shared_ptr<OCResource>, dereference_compare> DiscoveredResourceSet;
42
43 DiscoveredResourceSet discoveredResources;
44 const int SUCCESS_RESPONSE = 0;
45 std::shared_ptr<OCResource> curResource;
46 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
47
48 //TODO-CA: Since CA CON message support is still in progress, this client uses
49 // LowQos messages. This needs to change once Confirmable messages are supported in CA.
50
51 class Light
52 {
53 public:
54
55     bool m_state;
56     int m_power;
57     std::string m_name;
58
59     Light() : m_state(false), m_power(0), m_name("")
60     {
61     }
62 };
63
64 Light mylight;
65
66 int observe_count()
67 {
68     static int oc = 0;
69     return ++oc;
70 }
71
72 void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
73                     const int& eCode, const int& sequenceNumber)
74 {
75     if(eCode == SUCCESS_RESPONSE)
76     {
77         std::cout << "OBSERVE RESULT:"<<std::endl;
78         if(sequenceNumber == (int) ObserveAction::ObserveRegister)
79         {
80             std::cout << "\tObserve Registration Confirmed: "<< endl;
81         }
82         else if (sequenceNumber == (int) ObserveAction::ObserveUnregister)
83         {
84             std::cout << "\tObserve Cancel Confirmed: "<< endl;
85             sleep(10);
86             std::cout << "DONE"<<std::endl;
87             std::exit(0);
88         }
89         else
90         {
91             std::cout << "\tSequenceNumber: "<< sequenceNumber << endl;
92         }
93
94         rep.getValue("state", mylight.m_state);
95         rep.getValue("power", mylight.m_power);
96         rep.getValue("name", mylight.m_name);
97
98         std::cout << "\tstate: " << mylight.m_state << std::endl;
99         std::cout << "\tpower: " << mylight.m_power << std::endl;
100         std::cout << "\tname: " << mylight.m_name << std::endl;
101
102         if(observe_count() > 30)
103         {
104             std::cout<<"Cancelling Observe..."<<std::endl;
105             OCStackResult result = curResource->cancelObserve(OC::QualityOfService::LowQos);
106
107             std::cout << "Cancel result: "<< result << " waiting for confirmation ..." <<std::endl;
108         }
109     }
110     else
111     {
112         std::cout << "onObserve Response error: " << eCode << std::endl;
113         std::exit(-1);
114     }
115 }
116
117 void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
118 {
119     if(eCode == SUCCESS_RESPONSE)
120     {
121         std::cout << "POST request was successful" << std::endl;
122
123         if(rep.hasAttribute("createduri"))
124         {
125             std::cout << "\tUri of the created resource: "
126                       << rep.getValue<std::string>("createduri") << std::endl;
127         }
128         else
129         {
130             rep.getValue("state", mylight.m_state);
131             rep.getValue("power", mylight.m_power);
132             rep.getValue("name", mylight.m_name);
133
134             std::cout << "\tstate: " << mylight.m_state << std::endl;
135             std::cout << "\tpower: " << mylight.m_power << std::endl;
136             std::cout << "\tname: " << mylight.m_name << std::endl;
137         }
138
139         if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
140             std::cout << endl << "Observe is used." << endl << endl;
141         else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
142             std::cout << endl << "ObserveAll is used." << endl << endl;
143         sleep(1);
144         curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve,
145                 OC::QualityOfService::LowQos);
146
147     }
148     else
149     {
150         std::cout << "onPost2 Response error: " << eCode << std::endl;
151         std::exit(-1);
152     }
153 }
154
155 void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
156 {
157     if(eCode == SUCCESS_RESPONSE)
158     {
159         std::cout << "POST request was successful" << std::endl;
160
161         if(rep.hasAttribute("createduri"))
162         {
163             std::cout << "\tUri of the created resource: "
164                       << rep.getValue<std::string>("createduri") << std::endl;
165         }
166         else
167         {
168             rep.getValue("state", mylight.m_state);
169             rep.getValue("power", mylight.m_power);
170             rep.getValue("name", mylight.m_name);
171
172             std::cout << "\tstate: " << mylight.m_state << std::endl;
173             std::cout << "\tpower: " << mylight.m_power << std::endl;
174             std::cout << "\tname: " << mylight.m_name << std::endl;
175         }
176
177         OCRepresentation rep2;
178
179         std::cout << "Posting light representation..."<<std::endl;
180
181         mylight.m_state = true;
182         mylight.m_power = 55;
183
184         rep2.setValue("state", mylight.m_state);
185         rep2.setValue("power", mylight.m_power);
186         sleep(1);
187         curResource->post(rep2, QueryParamsMap(), &onPost2, OC::QualityOfService::LowQos);
188     }
189     else
190     {
191         std::cout << "onPost Response error: " << eCode << std::endl;
192         std::exit(-1);
193     }
194 }
195
196 // Local function to put a different state for this resource
197 void postLightRepresentation(std::shared_ptr<OCResource> resource)
198 {
199     if(resource)
200     {
201         OCRepresentation rep;
202
203         std::cout << "Posting light representation..."<<std::endl;
204
205         mylight.m_state = false;
206         mylight.m_power = 105;
207
208         rep.setValue("state", mylight.m_state);
209         rep.setValue("power", mylight.m_power);
210
211         // Invoke resource's post API with rep, query map and the callback parameter
212         resource->post(rep, QueryParamsMap(), &onPost, OC::QualityOfService::LowQos);
213     }
214 }
215
216 // callback handler on PUT request
217 void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
218 {
219     if(eCode == SUCCESS_RESPONSE)
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         sleep(1);
231         postLightRepresentation(curResource);
232     }
233     else
234     {
235         std::cout << "onPut Response error: " << eCode << std::endl;
236         std::exit(-1);
237     }
238 }
239
240 // Local function to put a different state for this resource
241 void putLightRepresentation(std::shared_ptr<OCResource> resource)
242 {
243     if(resource)
244     {
245         OCRepresentation rep;
246
247         std::cout << "Putting light representation..."<<std::endl;
248
249         mylight.m_state = true;
250         mylight.m_power = 15;
251
252         rep.setValue("state", mylight.m_state);
253         rep.setValue("power", mylight.m_power);
254
255         // Invoke resource's put API with rep, query map and the callback parameter
256         resource->put(rep, QueryParamsMap(), &onPut, OC::QualityOfService::LowQos);
257     }
258 }
259
260 // Callback handler on GET request
261 void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
262 {
263     if(eCode == SUCCESS_RESPONSE)
264     {
265         std::cout << "GET request was successful" << std::endl;
266         std::cout << "Resource URI: " << rep.getUri() << std::endl;
267
268         rep.getValue("state", mylight.m_state);
269         rep.getValue("power", mylight.m_power);
270         rep.getValue("name", mylight.m_name);
271
272         std::cout << "\tstate: " << mylight.m_state << std::endl;
273         std::cout << "\tpower: " << mylight.m_power << std::endl;
274         std::cout << "\tname: " << mylight.m_name << std::endl;
275         sleep(1);
276         putLightRepresentation(curResource);
277     }
278     else
279     {
280         std::cout << "onGET Response error: " << eCode << std::endl;
281         std::exit(-1);
282     }
283 }
284
285 // Local function to get representation of light resource
286 void getLightRepresentation(std::shared_ptr<OCResource> resource)
287 {
288     if(resource)
289     {
290         std::cout << "Getting Light Representation..."<<std::endl;
291         // Invoke resource's get API with the callback parameter
292
293         QueryParamsMap test;
294         resource->get(test, &onGet,OC::QualityOfService::LowQos);
295     }
296 }
297
298 // Callback to found resources
299 void foundResource(std::shared_ptr<OCResource> resource)
300 {
301     std::string resourceURI;
302     std::string hostAddress;
303     try
304     {
305         if(discoveredResources.find(resource) == discoveredResources.end())
306         {
307             std::cout << "Found resource " << resource->uniqueIdentifier() <<
308                 " for the first time on server with ID: "<< resource->sid()<<std::endl;
309             discoveredResources.insert(resource);
310         }
311         else
312         {
313             std::cout<<"Found resource "<< resource->uniqueIdentifier() << " again!"<<std::endl;
314         }
315
316         if(curResource)
317         {
318             std::cout << "Found another resource, ignoring"<<std::endl;
319             return;
320         }
321
322         // Do some operations with resource object.
323         if(resource)
324         {
325             std::cout<<"DISCOVERED Resource:"<<std::endl;
326             // Get the resource URI
327             resourceURI = resource->uri();
328             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
329
330             // Get the resource host address
331             hostAddress = resource->host();
332             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
333
334             // Get the resource types
335             std::cout << "\tList of resource types: " << std::endl;
336             for(auto &resourceTypes : resource->getResourceTypes())
337             {
338                 std::cout << "\t\t" << resourceTypes << std::endl;
339             }
340
341             // Get the resource interfaces
342             std::cout << "\tList of resource interfaces: " << std::endl;
343             for(auto &resourceInterfaces : resource->getResourceInterfaces())
344             {
345                 std::cout << "\t\t" << resourceInterfaces << std::endl;
346             }
347
348             if(resourceURI == "/a/light")
349             {
350                 curResource = resource;
351                 sleep(1);
352                 // Call a local function which will internally invoke get API on the resource pointer
353                 getLightRepresentation(resource);
354             }
355         }
356         else
357         {
358             // Resource is invalid
359             std::cout << "Resource is invalid" << std::endl;
360         }
361
362     }
363     catch(std::exception& e)
364     {
365         //log(e.what());
366     }
367 }
368
369 void PrintUsage()
370 {
371     std::cout << std::endl;
372     std::cout << "Usage : simpleclientHQ <ObserveType> <ConnectivityType>" << std::endl;
373     std::cout << "   ObserveType : 1 - Observe" << std::endl;
374     std::cout << "   ObserveType : 2 - ObserveAll" << std::endl;
375     std::cout<<"    ConnectivityType: Default WIFI" << std::endl;
376     std::cout << "   ConnectivityType : 0 - ETHERNET"<< std::endl;
377     std::cout << "   ConnectivityType : 1 - WIFI"<< std::endl;
378 }
379
380 int main(int argc, char* argv[]) {
381
382     ostringstream requestURI;
383
384     OCConnectivityType connectivityType = OC_WIFI;
385     try
386     {
387         if (argc == 1)
388         {
389             OBSERVE_TYPE_TO_USE = ObserveType::Observe;
390         }
391         else if (argc >= 2)
392         {
393             int value = stoi(argv[1]);
394             if (value == 1)
395                 OBSERVE_TYPE_TO_USE = ObserveType::Observe;
396             else if (value == 2)
397                 OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
398             else
399                 OBSERVE_TYPE_TO_USE = ObserveType::Observe;
400
401             if(argc == 3)
402             {
403                 std::size_t inputValLen;
404                 int optionSelected = stoi(argv[2], &inputValLen);
405
406                 if(inputValLen == strlen(argv[2]))
407                 {
408                     if(optionSelected == 0)
409                     {
410                         connectivityType = OC_ETHERNET;
411                     }
412                     else if(optionSelected == 1)
413                     {
414                         connectivityType = OC_WIFI;
415                     }
416                     else
417                     {
418                         std::cout << "Invalid connectivity type selected. Using default WIFI"
419                             << std::endl;
420                     }
421                 }
422                 else
423                 {
424                     std::cout << "Invalid connectivity type selected. Using default WIFI"
425                     << std::endl;
426                 }
427             }
428         }
429         else
430         {
431             PrintUsage();
432             return -1;
433         }
434     }
435     catch(exception& e)
436     {
437         std::cout << "Invalid input argument. Using WIFI as connectivity type" << std::endl;
438     }
439
440
441     // Create PlatformConfig object
442     PlatformConfig cfg {
443         OC::ServiceType::InProc,
444         OC::ModeType::Client,
445         "0.0.0.0",
446         0,
447         OC::QualityOfService::LowQos
448     };
449
450     OCPlatform::Configure(cfg);
451
452     try
453     {
454         // Find all resources
455         requestURI << OC_WELL_KNOWN_QUERY << "?rt=core.light";
456
457         OCPlatform::findResource("", requestURI.str(),
458                 connectivityType, &foundResource, OC::QualityOfService::LowQos);
459         std::cout<< "Finding Resource... " <<std::endl;
460
461         // Find resource is done twice so that we discover the original resources a second time.
462         // These resources will have the same uniqueidentifier (yet be different objects), so that
463         // we can verify/show the duplicate-checking code in foundResource(above);
464         OCPlatform::findResource("", requestURI.str(),
465                 connectivityType, &foundResource, OC::QualityOfService::LowQos);
466         std::cout<< "Finding Resource for second time... " <<std::endl;
467
468         // A condition variable will free the mutex it is given, then do a non-
469         // intensive block until 'notify' is called on it.  In this case, since we
470         // don't ever call cv.notify, this should be a non-processor intensive version
471         // of while(true);
472         std::mutex blocker;
473         std::condition_variable cv;
474         std::unique_lock<std::mutex> lock(blocker);
475         cv.wait(lock);
476
477     }catch(OCException& e)
478     {
479         //log(e.what());
480     }
481
482     return 0;
483 }
484