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