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