Imported Upstream version 1.0.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 "RCSRemoteResourceObject.h"
25 #include "RCSResourceAttributes.h"
26 #include "RCSAddress.h"
27
28 #include "OCPlatform.h"
29
30 using namespace OC;
31 using namespace OIC::Service;
32
33 #define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC, __VA_ARGS__ }
34
35 void startMonitoring();
36 void startMonitoring();
37 void stopMonitoring();
38 void getAttributeFromRemoteServer();
39 void setAttributeToRemoteServer();
40 void startCachingWithoutCallback();
41 void startCachingWithCallback();
42 void getResourceCacheState();
43 void getCachedAttributes();
44 void getCachedAttribute();
45 void stopCaching();
46 void discoverResource();
47 void cancelDiscovery();
48 int processUserInput();
49 void selectResource();
50 void printAttributes(const RCSResourceAttributes& attributes);
51
52 class MenuList;
53
54 class MenuItem
55 {
56 private:
57     typedef void(*MenuHandler)();
58
59 public:
60     MenuItem(const char* funcName, MenuHandler handler = nullptr,
61             MenuHandler optionHandler = nullptr, MenuList* state = nullptr)
62         : m_name(funcName), m_handler(handler), m_optionHandler(optionHandler),
63           m_nextState(state)
64     {
65     }
66
67     MenuList* command() const
68     {
69         std::cout << m_name << " start.." << std::endl;
70         if(m_handler) m_handler();
71
72         if(m_optionHandler != nullptr) m_optionHandler();
73
74         return m_nextState;
75     }
76
77     const char* getTitle() const
78     {
79         return m_name.c_str();
80     }
81
82 private:
83     const std::string m_name;
84     const MenuHandler m_handler;
85     const MenuHandler m_optionHandler;
86     MenuList* const m_nextState ;
87 };
88
89 class MenuList
90 {
91 public:
92     MenuList(std::initializer_list<MenuItem> il)
93         :m_menuItemList(std::move(il))
94     {
95     }
96
97     void display() const
98     {
99         std::cout << std::endl;
100         int menuNum = 1;
101
102         for(const auto& menuItem : m_menuItemList)
103         {
104             std::cout.width(2);
105             std::cout << std::right << menuNum++ <<  ". ";
106             std::cout << menuItem.getTitle() << std::endl;
107         }
108     }
109
110     MenuList* select()
111     {
112         int input = processUserInput();
113
114         if(input == static_cast<int>(m_menuItemList.size())) return nullptr;
115
116         if(input > static_cast<int>(m_menuItemList.size()) || input <= 0)
117         {
118             std::cout << "Invalid input, please try again" << std::endl;
119             return this;
120         }
121         auto nextMenuList = m_menuItemList[input-1].command();
122
123         return nextMenuList == nullptr ? this : nextMenuList;
124     }
125
126 private:
127     const std::vector<MenuItem> m_menuItemList;
128 };
129
130 constexpr int REQUEST_TEMP = 1;
131 constexpr int REQUEST_LIGHT = 2;
132
133 const std::string TEMP = "oic.r.temperaturesensor";
134 const std::string LIGHT = "oic.r.light";
135
136 std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> discoveryTask;
137
138 std::vector<RCSRemoteResourceObject::Ptr> resourceList;
139 RCSRemoteResourceObject::Ptr selectedResource;
140
141 std::string defaultKey;
142
143 MenuList* currentMenuList;
144
145 MenuList resourceMenu = {
146     DECLARE_MENU(startMonitoring),
147     DECLARE_MENU(stopMonitoring),
148     DECLARE_MENU(getAttributeFromRemoteServer),
149     DECLARE_MENU(setAttributeToRemoteServer),
150     DECLARE_MENU(startCachingWithoutCallback),
151     DECLARE_MENU(startCachingWithCallback),
152     DECLARE_MENU(getResourceCacheState),
153     DECLARE_MENU(getCachedAttributes),
154     DECLARE_MENU(getCachedAttribute),
155     DECLARE_MENU(stopCaching),
156     { "quit" }
157 };
158
159 MenuList cancelDiscoveryMenu = {
160     DECLARE_MENU(cancelDiscovery, selectResource, &resourceMenu),
161     { "quit" }
162 };
163
164 MenuList discoveryMenu = {
165     DECLARE_MENU(discoverResource, nullptr, &cancelDiscoveryMenu),
166     { "quit" }
167 };
168
169 void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> discoveredResource)
170 {
171     std::cout << "onResourceDiscovered callback :: " << std::endl;
172
173     std::cout << "resourceURI : " << discoveredResource->getUri() << std::endl;
174     std::cout << "hostAddress : " << discoveredResource->getAddress() << std::endl;
175
176     resourceList.push_back(discoveredResource);
177 }
178
179 void onResourceStateChanged(const ResourceState& resourceState)
180 {
181     std::cout << "onResourceStateChanged callback" << std::endl;
182
183     switch(resourceState)
184     {
185         case ResourceState::NONE:
186             std::cout << "\tState changed to : NOT_MONITORING" << std::endl;
187             break;
188
189         case ResourceState::ALIVE:
190             std::cout << "\tState changed to : ALIVE" << std::endl;
191             break;
192
193         case ResourceState::REQUESTED:
194             std::cout << "\tState changed to : REQUESTED" << std::endl;
195             break;
196
197         case ResourceState::LOST_SIGNAL:
198             std::cout << "\tState changed to : LOST_SIGNAL" << std::endl;
199             break;
200
201         case ResourceState::DESTROYED:
202             std::cout << "\tState changed to : DESTROYED" << std::endl;
203             break;
204     }
205 }
206
207 void onCacheUpdated(const RCSResourceAttributes& attributes)
208 {
209     std::cout << "onCacheUpdated callback" << std::endl;
210
211     printAttributes(attributes);
212 }
213
214 void onRemoteAttributesReceived(const RCSResourceAttributes& attributes, int)
215 {
216     std::cout << "onRemoteAttributesReceived callback" << std::endl;
217
218     printAttributes(attributes);
219 }
220
221 void startMonitoring()
222 {
223     if (!selectedResource->isMonitoring())
224     {
225         selectedResource->startMonitoring(&onResourceStateChanged);
226         std::cout << "\tHosting Started..." << std::endl;
227     }
228     else
229     {
230         std::cout << "\tAlready Started..." << std::endl;
231     }
232 }
233
234 void stopMonitoring()
235 {
236     if (selectedResource->isMonitoring())
237     {
238         selectedResource->stopMonitoring();
239         std::cout << "\tHosting stopped..." << std::endl;
240     }
241     else
242     {
243        std::cout << "\tHosting not started..." << std::endl;
244     }
245 }
246
247 void getAttributeFromRemoteServer()
248 {
249     selectedResource->getRemoteAttributes(&onRemoteAttributesReceived);
250 }
251
252 void setAttributeToRemoteServer()
253 {
254     std::string key;
255     RCSResourceAttributes setAttribute;
256
257     std::cout << "\tEnter the Key you want to set : ";
258     std::cin >> key;
259     std::cout << "\tEnter the value(INT) you want to set :";
260
261     setAttribute[key] = processUserInput();
262     selectedResource->setRemoteAttributes(setAttribute,
263                                   &onRemoteAttributesReceived);
264 }
265
266 void startCaching(RCSRemoteResourceObject::CacheUpdatedCallback cb)
267 {
268     if (!selectedResource->isCaching())
269     {
270         selectedResource->startCaching(std::move(cb));
271         std::cout << "\tCaching Started..." << std::endl;
272     }
273     else
274     {
275         std::cout << "\tAlready Started Caching..." << std::endl;
276     }
277 }
278
279 void startCachingWithoutCallback()
280 {
281     startCaching(nullptr);
282 }
283
284 void startCachingWithCallback()
285 {
286     startCaching(onCacheUpdated);
287 }
288
289 void getResourceCacheState()
290 {
291     switch(selectedResource->getCacheState())
292     {
293         case CacheState::READY:
294             std::cout << "\tCurrent Cache State : CACHE_STATE::READY" << std::endl;
295             break;
296
297         case CacheState::UNREADY:
298             std::cout << "\tCurrent Cache State : CACHE_STATE::UNREADY" << std::endl;
299             break;
300
301         case CacheState::LOST_SIGNAL:
302             std::cout << "\tCurrent Cache State : CACHE_STATE::LOST_SIGNAL" << std::endl;
303             break;
304
305         case CacheState::NONE:
306             std::cout << "\tCurrent Cache State : CACHE_STATE::NONE" << std::endl;
307             break;
308     }
309 }
310
311 void getCachedAttributes()
312 {
313     try
314     {
315         printAttributes(selectedResource->getCachedAttributes());
316     }
317     catch (const RCSBadRequestException& e)
318     {
319         std::cout << "Exception in getCachedAttributes : " << e.what() << std::endl;
320     }
321 }
322
323 void getCachedAttribute()
324 {
325     try
326     {
327         std::cout << "\tkey : " << defaultKey << std::endl
328                   << "\tvalue : " << selectedResource->getCachedAttribute(defaultKey).get< int >()
329                   << std::endl;
330     }
331     catch (const RCSBadRequestException& e)
332     {
333         std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
334     }
335     catch (const RCSBadGetException& e)
336     {
337         std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
338     }
339 }
340
341 void stopCaching()
342 {
343     if(selectedResource->isCaching())
344     {
345         selectedResource->stopCaching();
346         std::cout << "\tCaching stopped..." << std::endl;
347     }
348     else
349     {
350         std::cout << "\tCaching not started..." << std::endl;
351     }
352 }
353
354 void platFormConfigure()
355 {
356     PlatformConfig config
357     {
358         OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
359     };
360     OCPlatform::Configure(config);
361 }
362
363 int processUserInput()
364 {
365     int userInput;
366
367     while(true)
368     {
369         std::cin >> userInput;
370         if (std::cin.fail())
371         {
372             std::cin.clear();
373             std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
374             std::cout << "Invalid Input, please try again" << std::endl;
375         }
376         else break;
377     }
378     return userInput;
379 }
380
381 bool selectResourceType(std::string& resourceType)
382 {
383     std::cout << "========================================================" << std::endl;
384     std::cout << "1. Temperature Resource Discovery" << std::endl;
385     std::cout << "2. Light Resource Discovery" << std::endl;
386     std::cout << "========================================================" << std::endl;
387
388     switch (processUserInput())
389     {
390     case REQUEST_TEMP:
391         resourceType = TEMP;
392         defaultKey = "Temperature";
393         return true;
394     case REQUEST_LIGHT:
395         resourceType = LIGHT;
396         defaultKey = "Light";
397         return true;
398     default :
399         std::cout << "Invalid input, please try again" << std::endl;
400         return false;
401     }
402 }
403
404 RCSAddress inputAddress()
405 {
406     std::cout << "========================================================" << std::endl;
407     std::cout << "Please input address" << std::endl;
408     std::cout << "(default is multicast. when you want to use unicast, input address" << std::endl;
409     std::cout << "========================================================" << std::endl;
410
411     std::string address;
412
413     if(std::cin.peek() != '\n') std::cin >> address;
414
415     return address.empty() ? RCSAddress::multicast() : RCSAddress::unicast(address);
416 }
417
418 void discoverResource()
419 {
420     std::string resourceType = "";
421
422     while(!selectResourceType(resourceType)) {}
423
424     while(!discoveryTask)
425     {
426         try
427         {
428             discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(
429                     inputAddress(), resourceType, &onResourceDiscovered);
430         }
431         catch (const RCSPlatformException& e)
432         {
433             std::cout << e.what() << std::endl;
434         }
435     }
436 }
437
438 void displayResourceList()
439 {
440     int cnt = 1;
441     for(const auto& resource : resourceList)
442     {
443         std::cout << cnt++ << ".\tresourceURI : " << resource->getUri() << std::endl <<
444                               "\thostAddress : " << resource->getAddress() << std::endl;
445     }
446 }
447
448 void selectResource()
449 {
450     displayResourceList();
451
452     std::cout << "select Resource..." << std::endl;
453
454     selectedResource = resourceList[processUserInput()-1];
455
456     resourceList.clear();
457 }
458
459 void cancelDiscovery()
460 {
461     if(!discoveryTask)
462     {
463         std::cout << "There is no discovery request..." << std::endl;
464         return;
465     }
466     discoveryTask->cancel();
467 }
468
469 void printAttribute(const std::string key, const RCSResourceAttributes::Value& value)
470 {
471     std::cout << "\tkey : " << key << std::endl
472               << "\tvalue : " << value.toString() << std::endl;
473 }
474
475 void printAttributes(const RCSResourceAttributes& attributes)
476 {
477     if (attributes.empty())
478     {
479        std::cout << "\tattributes is empty" << std::endl;
480     }
481     for(const auto& attr : attributes)
482     {
483         printAttribute(attr.key(), attr.value());
484     }
485 }
486
487 int main()
488 {
489     platFormConfigure();
490
491     currentMenuList = &discoveryMenu;
492
493     try
494     {
495         while(currentMenuList)
496         {
497             currentMenuList->display();
498
499             currentMenuList = currentMenuList->select();
500         }
501     }
502     catch (const std::exception& e)
503     {
504         std::cout << "main exception : " << e.what() << std::endl;
505     }
506
507     std::cout << "Stopping the Client" << std::endl;
508
509     return 0;
510 }