Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / service / resource-encapsulation / examples / linux / SampleResourceClient.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics 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 #include <iostream>
22
23 #include "RCSDiscoveryManager.h"
24 #include "RCSRepresentation.h"
25 #include "RCSRemoteResourceObject.h"
26 #include "RCSResourceAttributes.h"
27 #include "RCSAddress.h"
28
29 #include "OCPlatform.h"
30
31 #define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC }
32
33 using namespace OC;
34 using namespace OIC::Service;
35
36 struct CloseApp {};
37
38 struct MenuItem
39 {
40 private:
41     typedef void(*Handler)();
42
43 public:
44     const std::string title;
45     const Handler handler;
46 };
47
48 typedef void(*Runner)();
49
50 constexpr int RESOURCE_TEMP = 1;
51 constexpr int RESOURCE_LIGHT = 2;
52
53 const std::string RESOURCE_TYPE_TEMP = "oic.r.temperaturesensor";
54 const std::string RESOURCE_TYPE_LIGHT = "oic.r.light";
55
56 RCSRemoteResourceObject::Ptr g_selectedResource;
57 std::vector<RCSRemoteResourceObject::Ptr> g_discoveredResources;
58
59 std::string g_attrKey;
60
61 Runner g_currentRun;
62
63 std::ostream& operator<<(std::ostream& os, const RCSRemoteResourceObject::Ptr& object)
64 {
65     return os << "\turi : " << object->getUri() << std::endl <<
66             "\thost address : " << object->getAddress();
67 }
68
69 std::ostream& operator<<(std::ostream& os, const MenuItem& item)
70 {
71     return os << item.title;
72 }
73
74 void onSelected(const RCSRemoteResourceObject::Ptr& object)
75 {
76     g_selectedResource = object;
77 }
78
79 void onSelected(const MenuItem& item)
80 {
81     std::cout << item.title << " start.." << std::endl;
82     item.handler();
83 }
84
85 int processUserInput(int min = std::numeric_limits<int>::min(),
86         int max = std::numeric_limits<int>::max())
87 {
88     assert(min <= max);
89
90     int input;
91
92     std::cin >> input;
93     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
94
95     if (!std::cin.fail() && min <= input && input <= max) return input;
96
97     std::cin.clear();
98     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
99
100     throw std::runtime_error("Invalid Input, please try again");
101 }
102
103 template<typename D>
104 void displayItem(int width, int index, const D& data)
105 {
106     std::cout.width(width);
107     std::cout << std::right << index << ". ";
108     std::cout << data << std::endl;
109 }
110
111 template<typename T>
112 void displayItems(const std::vector<T>& items)
113 {
114     std::cout << std::endl;
115
116     const auto width = (items.size() + 1) / 10 + 1;
117
118     for(size_t i = 0; i < items.size(); ++i)
119     {
120         displayItem(width, i + 1, items[i]);
121     }
122     displayItem(width, items.size() + 1, "quit");
123 }
124
125 template<typename T>
126 void selectItem(const std::vector<T>& items)
127 {
128     int selected = processUserInput(1, items.size() + 1) - 1;
129
130     if(selected == static_cast<int>(items.size())) throw CloseApp();
131
132     onSelected(items[selected]);
133 }
134
135 template<typename T>
136 void handleItems(const std::vector<T>& items)
137 {
138     displayItems(items);
139     selectItem(items);
140 }
141
142 std::string inputInterface()
143 {
144     std::string interfaceName;
145
146     std::cout << "\tInput the Interface you want to set : ";
147     std::cin >> interfaceName;
148
149     return interfaceName;
150 }
151
152 RCSResourceAttributes inputKeyValue()
153 {
154     std::string key;
155
156     std::cout << "\tEnter the Key you want to set : ";
157     std::cin >> key;
158
159     std::cout << "\tEnter the value(INT) you want to set :";
160     RCSResourceAttributes attrs;
161     attrs[key] = processUserInput();
162
163     return attrs;
164 }
165
166 void printAttribute(const std::string& key, const RCSResourceAttributes::Value& value)
167 {
168     std::cout << "\tkey : " << key << std::endl
169               << "\tvalue : " << value.toString() << std::endl;
170 }
171
172 void printAttributes(const RCSResourceAttributes& attributes)
173 {
174     if (attributes.empty())
175     {
176        std::cout << "\tattributes is empty" << std::endl;
177     }
178
179     for(const auto& attr : attributes)
180     {
181         printAttribute(attr.key(), attr.value());
182     }
183 }
184
185 void print(const std::string& name, const std::vector< std::string >& elements)
186 {
187     if (elements.empty())
188     {
189        std::cout << "\t" << name << " is empty" << std::endl;
190        return;
191     }
192
193     std::cout << "\t" << name << " : " << std::endl;
194     for(const auto& item : elements)
195     {
196         std::cout << item << " ";
197     }
198     std::cout << std::endl;
199 }
200
201 void printUri(const std::string& uri)
202 {
203     if(uri.empty())
204     {
205         std::cout << "\turi is empty" << std::endl;
206     }
207     else
208     {
209         std::cout << "\turi : " << uri << std::endl;
210     }
211 }
212
213 void printRepresentation(const RCSRepresentation& rep)
214 {
215     printUri(rep.getUri());
216     print("interfaces", rep.getInterfaces());
217     print("resourceTypes", rep.getResourceTypes());
218     printAttributes(rep.getAttributes());
219
220     const auto& children = rep.getChildren();
221
222     if(children.empty())
223     {
224         std::cout << "\tchildren is empty" << std::endl;
225     }
226     else
227     {
228         int cnt = 0;
229         for(const auto& child : children)
230         {
231             std::cout << "========================================================" << std::endl;
232             std::cout << ++cnt << " chlid" << std::endl;
233             printRepresentation(child);
234             std::cout << "========================================================" << std::endl;
235         }
236     }
237 }
238
239 void onResourceStateChanged(ResourceState resourceState)
240 {
241     std::cout << "onResourceStateChanged callback" << std::endl;
242
243     switch(resourceState)
244     {
245         case ResourceState::NONE:
246             std::cout << "\tState changed to : NOT_MONITORING" << std::endl;
247             break;
248
249         case ResourceState::ALIVE:
250             std::cout << "\tState changed to : ALIVE" << std::endl;
251             break;
252
253         case ResourceState::REQUESTED:
254             std::cout << "\tState changed to : REQUESTED" << std::endl;
255             break;
256
257         case ResourceState::LOST_SIGNAL:
258             std::cout << "\tState changed to : LOST_SIGNAL" << std::endl;
259             break;
260
261         case ResourceState::DESTROYED:
262             std::cout << "\tState changed to : DESTROYED" << std::endl;
263             break;
264     }
265 }
266
267 void onCacheUpdated(const RCSResourceAttributes& attributes)
268 {
269     std::cout << "onCacheUpdated callback" << std::endl;
270
271     printAttributes(attributes);
272 }
273
274 void onRemoteAttributesReceived(const RCSResourceAttributes& attributes, int)
275 {
276     std::cout << "onRemoteAttributesReceived callback" << std::endl;
277
278     printAttributes(attributes);
279 }
280
281 void onRemoteGetReceived(const HeaderOpts&, const RCSRepresentation& rep, int)
282 {
283     std::cout << "onRemoteGetReceived callback" << std::endl;
284
285     printRepresentation(rep);
286 }
287
288 void onRemoteSetReceived(const HeaderOpts&, const RCSRepresentation& rep, int)
289 {
290     std::cout << "onRemoteSetReceived callback" << std::endl;
291
292     printRepresentation(rep);
293 }
294
295 void startMonitoring()
296 {
297     if (g_selectedResource->isMonitoring())
298     {
299         std::cout << "\tAlready Started..." << std::endl;
300         return;
301     }
302
303     g_selectedResource->startMonitoring(&onResourceStateChanged);
304     std::cout << "\tMonitoring Started..." << std::endl;
305 }
306
307 void stopMonitoring()
308 {
309     if (!g_selectedResource->isMonitoring())
310     {
311         std::cout << "\tMonitoring not started..." << std::endl;
312         return;
313     }
314
315     g_selectedResource->stopMonitoring();
316     std::cout << "\tMonitoring stopped..." << std::endl;
317 }
318
319 void getRemoteAttributes()
320 {
321     g_selectedResource->getRemoteAttributes(onRemoteAttributesReceived);
322 }
323
324 void setRemoteAttributes()
325 {
326     g_selectedResource->setRemoteAttributes(inputKeyValue(), onRemoteAttributesReceived);
327 }
328
329 void getWithInterface()
330 {
331     RCSQueryParams queryParams;
332     queryParams.setResourceInterface(inputInterface());
333
334     g_selectedResource->get(queryParams, onRemoteGetReceived);
335 }
336
337 void setWithInterface()
338 {
339     RCSQueryParams queryParams;
340     queryParams.setResourceInterface(inputInterface());
341
342     g_selectedResource->set(queryParams, inputKeyValue(), onRemoteSetReceived);
343 }
344
345 void startCaching(RCSRemoteResourceObject::CacheUpdatedCallback cb)
346 {
347     if (g_selectedResource->isCaching())
348     {
349         std::cout << "\tAlready Started Caching..." << std::endl;
350         return;
351     }
352
353     g_selectedResource->startCaching(std::move(cb));
354     std::cout << "\tCaching Started..." << std::endl;
355 }
356
357 void startCachingWithoutCallback()
358 {
359     startCaching(nullptr);
360 }
361
362 void startCachingWithCallback()
363 {
364     startCaching(onCacheUpdated);
365 }
366
367 void getResourceCacheState()
368 {
369     switch(g_selectedResource->getCacheState())
370     {
371         case CacheState::READY:
372             std::cout << "\tCurrent Cache State : CACHE_STATE::READY" << std::endl;
373             break;
374
375         case CacheState::UNREADY:
376             std::cout << "\tCurrent Cache State : CACHE_STATE::UNREADY" << std::endl;
377             break;
378
379         case CacheState::LOST_SIGNAL:
380             std::cout << "\tCurrent Cache State : CACHE_STATE::LOST_SIGNAL" << std::endl;
381             break;
382
383         case CacheState::NONE:
384             std::cout << "\tCurrent Cache State : CACHE_STATE::NONE" << std::endl;
385             break;
386     }
387 }
388
389 void getCachedAttributes()
390 {
391     printAttributes(g_selectedResource->getCachedAttributes());
392 }
393
394 void getCachedAttribute()
395 {
396     printAttribute(g_attrKey, g_selectedResource->getCachedAttribute(g_attrKey));
397 }
398
399 void stopCaching()
400 {
401     if(!g_selectedResource->isCaching())
402     {
403         std::cout << "\tCaching not started..." << std::endl;
404         return;
405     }
406
407     g_selectedResource->stopCaching();
408     std::cout << "\tCaching stopped..." << std::endl;
409 }
410
411 std::string selectResourceType()
412 {
413     std::cout << "========================================================" << std::endl;
414     std::cout << "1. Temperature Resource Discovery" << std::endl;
415     std::cout << "2. Light Resource Discovery" << std::endl;
416     std::cout << "========================================================" << std::endl;
417
418     switch (processUserInput(RESOURCE_TEMP, RESOURCE_LIGHT))
419     {
420     case RESOURCE_TEMP:
421         g_attrKey = "Temperature";
422         return RESOURCE_TYPE_TEMP;
423     case RESOURCE_LIGHT:
424         g_attrKey = "Brightness";
425         return RESOURCE_TYPE_LIGHT;
426     }
427
428     throw std::logic_error("unreachable");
429 }
430
431 RCSAddress inputAddress()
432 {
433     std::cout << "========================================================" << std::endl;
434     std::cout << "Please input address (empty for multicast)" << std::endl;
435     std::cout << "========================================================" << std::endl;
436
437     std::string address;
438
439     if(std::cin.peek() != '\n') std::cin >> address;
440
441     return address.empty() ? RCSAddress::multicast() : RCSAddress::unicast(address);
442 }
443
444 void printDiscoveryInProgress()
445 {
446     std::cout << "Discovery in progress, press '1' to stop." << std::endl;
447 }
448
449 void discoverResource()
450 {
451     auto onResourceDiscovered = [](
452             const RCSRemoteResourceObject::Ptr& discoveredResource)
453     {
454         std::cout << "onResourceDiscovered callback :: " << std::endl;
455
456         std::cout << "uri : " << discoveredResource->getUri() << std::endl;
457         std::cout << "host address : " << discoveredResource->getAddress() << std::endl;
458
459         g_discoveredResources.push_back(discoveredResource);
460
461         printDiscoveryInProgress();
462     };
463
464     auto resourceType = selectResourceType();
465     auto address = inputAddress();
466
467     printDiscoveryInProgress();
468
469     auto discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(address,
470             resourceType, onResourceDiscovered);
471
472     while(processUserInput() != 1);
473
474     discoveryTask->cancel();
475 }
476
477 void runResourceControl()
478 {
479     static std::vector<MenuItem> resourceMenuItems {
480         DECLARE_MENU(startMonitoring),
481         DECLARE_MENU(stopMonitoring),
482         DECLARE_MENU(getRemoteAttributes),
483         DECLARE_MENU(setRemoteAttributes),
484         DECLARE_MENU(getWithInterface),
485         DECLARE_MENU(setWithInterface),
486         DECLARE_MENU(startCachingWithoutCallback),
487         DECLARE_MENU(startCachingWithCallback),
488         DECLARE_MENU(getResourceCacheState),
489         DECLARE_MENU(getCachedAttributes),
490         DECLARE_MENU(getCachedAttribute),
491         DECLARE_MENU(stopCaching),
492     };
493
494     handleItems(resourceMenuItems);
495 }
496
497 void runResourceSelection()
498 {
499     handleItems(g_discoveredResources);
500
501     g_currentRun = runResourceControl;
502 }
503
504 void runDiscovery()
505 {
506     static std::vector<MenuItem> discoveryMenuItems {
507         DECLARE_MENU(discoverResource),
508     };
509
510     handleItems(discoveryMenuItems);
511
512     if (g_discoveredResources.empty()) throw std::runtime_error("No resource found!");
513
514     g_currentRun = runResourceSelection;
515 }
516
517 void configurePlatform()
518 {
519     PlatformConfig config
520     {
521         OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
522     };
523     OCPlatform::Configure(config);
524 }
525
526 int main()
527 {
528     configurePlatform();
529
530     g_currentRun = runDiscovery;
531
532     while (true)
533     {
534         try
535         {
536             g_currentRun();
537         }
538         catch (const std::exception& e)
539         {
540             std::cout << e.what() << std::endl;
541         }
542         catch (const CloseApp&)
543         {
544             break;
545         }
546     }
547
548     std::cout << "Stopping the client" << std::endl;
549
550     return 0;
551 }