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