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