fixed the jira IOT-742 Temperature Resource Creation Fail
[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 #include <functional>
23
24 #include "mutex"
25 #include "condition_variable"
26
27 #include "RCSDiscoveryManager.h"
28 #include "RCSRemoteResourceObject.h"
29 #include "RCSResourceAttributes.h"
30 #include "RCSAddress.h"
31 #include "OCPlatform.h"
32
33 using namespace OC;
34 using namespace OIC::Service;
35
36 constexpr int CORRECT_INPUT = 1;
37 constexpr int INCORRECT_INPUT = 2;
38 constexpr int QUIT_INPUT = 3;
39
40 constexpr int REQUEST_TEMP = 1;
41 constexpr int REQUEST_LIGHT = 2;
42
43 std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> discoveryTask = nullptr;
44 std::shared_ptr<RCSRemoteResourceObject>  resource;
45
46 std::string defaultKey = "Temperature";
47 const std::string relativeUri = OC_RSRVD_WELL_KNOWN_URI;
48 const std::string multicastAdd = "multi";
49
50 std::mutex mtx;
51 std::condition_variable cond;
52
53 void startMonitoring();
54 void startMonitoring();
55 void stopMonitoring();
56 void getAttributeFromRemoteServer();
57 void setAttributeToRemoteServer();
58 void startCachingWithoutCallback();
59 void startCachingWithCallback();
60 void getResourceCacheState();
61 void getCachedAttributes();
62 void getCachedAttribute();
63 void stopCaching();
64 void discoverResource();
65 void cancelDiscovery();
66 int processUserInput();
67
68 enum Menu
69 {
70     START_MONITORING = 1,
71     STOP_MONITORING,
72     GET_ATTRIBUTE,
73     SET_ATTRIBUTE,
74     START_CACHING_NO_UPDATE,
75     START_CACHING_UPDATE,
76     GET_RESOURCE_CACHE_STATE,
77     GET_CACHED_ATTRIBUTES,
78     GET_CACHED_ATTRIBUTE,
79     STOP_CACHING,
80     DISCOVERY_RESOURCE,
81     CANCEL_DISCOVERY,
82     QUIT,
83     END_OF_MENU
84 };
85
86 typedef void(*ClientMenuHandler)();
87 typedef int ReturnValue;
88
89 struct ClientMenu
90 {
91     Menu m_menu;
92     ClientMenuHandler m_handler;
93     ReturnValue m_result;
94 };
95
96 ClientMenu clientMenu[] = {
97         {Menu::START_MONITORING, startMonitoring, CORRECT_INPUT},
98         {Menu::STOP_MONITORING, stopMonitoring, CORRECT_INPUT},
99         {Menu::GET_ATTRIBUTE, getAttributeFromRemoteServer, CORRECT_INPUT},
100         {Menu::SET_ATTRIBUTE, setAttributeToRemoteServer, CORRECT_INPUT},
101         {Menu::START_CACHING_NO_UPDATE, startCachingWithoutCallback, CORRECT_INPUT},
102         {Menu::START_CACHING_UPDATE, startCachingWithCallback, CORRECT_INPUT},
103         {Menu::GET_RESOURCE_CACHE_STATE, getResourceCacheState, CORRECT_INPUT},
104         {Menu::GET_CACHED_ATTRIBUTES, getCachedAttributes, CORRECT_INPUT},
105         {Menu::GET_CACHED_ATTRIBUTE, getCachedAttribute, CORRECT_INPUT},
106         {Menu::STOP_CACHING, stopCaching, CORRECT_INPUT},
107         {Menu::DISCOVERY_RESOURCE, discoverResource, CORRECT_INPUT},
108         {Menu::CANCEL_DISCOVERY, cancelDiscovery, CORRECT_INPUT},
109         {Menu::QUIT, [](){}, QUIT_INPUT},
110         {Menu::END_OF_MENU, nullptr, INCORRECT_INPUT}
111     };
112
113 void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> discoveredResource)
114 {
115     std::cout << "onResourceDiscovered callback :: " << std::endl;
116     std::string resourceURI = discoveredResource->getUri();
117     std::string hostAddress = discoveredResource->getAddress();
118
119     std::cout << resourceURI << std::endl;
120     std::cout << hostAddress << std::endl;
121
122     resource = discoveredResource;
123 }
124
125 void onResourceStateChanged(const ResourceState& resourceState)
126 {
127     std::cout << "onResourceStateChanged callback" << std::endl;
128
129     switch(resourceState)
130     {
131         case ResourceState::NONE:
132             std::cout << "\tState changed to : NOT_MONITORING" << std::endl;
133             break;
134
135         case ResourceState::ALIVE:
136             std::cout << "\tState changed to : ALIVE" << std::endl;
137             break;
138
139         case ResourceState::REQUESTED:
140             std::cout << "\tState changed to : REQUESTED" << std::endl;
141             break;
142
143         case ResourceState::LOST_SIGNAL:
144             std::cout << "\tState changed to : LOST_SIGNAL" << std::endl;
145             resource = nullptr;
146             break;
147
148         case ResourceState::DESTROYED:
149             std::cout << "\tState changed to : DESTROYED" << std::endl;
150             break;
151     }
152 }
153
154 void onCacheUpdated(const RCSResourceAttributes& attributes)
155 {
156     std::cout << "onCacheUpdated callback" << std::endl;
157
158     if (attributes.empty())
159     {
160         std::cout << "\tAttribute is Empty" << std::endl;
161         return;
162     }
163
164     for(const auto& attr : attributes)
165     {
166         std::cout << "\tkey : " << attr.key() << std::endl
167                   << "\tvalue : " << attr.value().toString() << std::endl;
168     }
169 }
170
171 void onRemoteAttributesReceivedCallback(const RCSResourceAttributes& attributes, int)
172 {
173     std::cout << "onRemoteAttributesReceivedCallback callback" << std::endl;
174
175     if (attributes.empty())
176     {
177         std::cout << "\tAttribute is Empty" << std::endl;
178         return;
179     }
180
181     for(const auto& attr : attributes)
182     {
183         std::cout << "\tkey : " << attr.key() << std::endl
184                   << "\tvalue : " << attr.value().toString() << std::endl;
185     }
186 }
187
188 void displayMenu()
189 {
190     std::cout << std::endl;
191     std::cout << "1 :: Start Monitoring" << std::endl;
192     std::cout << "2 :: Stop Monitoring" << std::endl;
193     std::cout << "3 :: Get Attribute" << std::endl;
194     std::cout << "4 :: Set Attribute" << std::endl;
195     std::cout << "5 :: Start Caching (No update to Application)" << std::endl;
196     std::cout << "6 :: Start Caching (Update the application when data change)"<< std::endl;
197     std::cout << "7 :: Get Resource cache State" << std::endl;
198     std::cout << "8 :: Get Cached Attributes" << std::endl;
199     std::cout << "9 :: Get Cached Attribute"  << std::endl;
200     std::cout << "10 :: Stop Caching" << std::endl;
201     std::cout << "11 :: Discover Resource" << std::endl;
202     std::cout << "12 :: Cancel Discovery" << std::endl;
203     std::cout << "13 :: Stop Server" << std::endl;
204 }
205
206 int processUserInput()
207 {
208     int userInput;
209     std::cin >> userInput;
210     if (std::cin.fail())
211     {
212         std::cin.clear();
213         std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
214         return -1;
215     }
216     return userInput;
217 }
218
219 void startMonitoring()
220 {
221     if (!resource->isMonitoring())
222     {
223         resource->startMonitoring(&onResourceStateChanged);
224         std::cout << "\tHosting Started..." << std::endl;
225     }
226     else
227     {
228         std::cout << "\tAlready Started..." << std::endl;
229     }
230 }
231
232 void stopMonitoring()
233 {
234     if (resource->isMonitoring())
235     {
236         resource->stopMonitoring();
237         std::cout << "\tHosting stopped..." << std::endl;
238     }
239     else
240     {
241        std::cout << "\tHosting not started..." << std::endl;
242     }
243 }
244
245 void getAttributeFromRemoteServer()
246 {
247     resource->getRemoteAttributes(&onRemoteAttributesReceivedCallback);
248 }
249
250 void setAttributeToRemoteServer()
251 {
252     std::string key;
253     int value;
254
255     RCSResourceAttributes setAttribute;
256
257     std::cout << "\tEnter the Key you want to set : ";
258     std::cin >> key;
259     std::cout << "\tEnter the value you want to set :";
260     std::cin >> value;
261
262     setAttribute[key] = value;
263     resource->setRemoteAttributes(setAttribute,
264                                   &onRemoteAttributesReceivedCallback);
265 }
266
267 void startCaching(std::function <void (const RCSResourceAttributes&)>cb)
268 {
269     if (!resource->isCaching())
270     {
271         if(cb) resource->startCaching(&onCacheUpdated);
272
273         else resource->startCaching();
274
275         std::cout << "\tCaching Started..." << std::endl;
276     }
277     else
278     {
279         std::cout << "\tAlready Started Caching..." << std::endl;
280     }
281 }
282
283 void startCachingWithoutCallback()
284 {
285     startCaching(nullptr);
286 }
287
288 void startCachingWithCallback()
289 {
290     startCaching(onCacheUpdated);
291 }
292
293 void getResourceCacheState()
294 {
295     switch(resource->getCacheState())
296     {
297         case CacheState::READY:
298             std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::READY" << std::endl;
299             break;
300
301         case CacheState::UNREADY:
302             std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::UNREADY" << std::endl;
303             break;
304
305         case CacheState::LOST_SIGNAL:
306             std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::LOST_SIGNAL" << std::endl;
307             break;
308
309         case CacheState::NONE:
310             std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::NONE" << std::endl;
311             break;
312
313         default:
314             break;
315     }
316 }
317
318 void getCachedAttributes()
319 {
320     try
321     {
322         if (resource->getCachedAttributes().empty())
323         {
324             std::cout << "\tReceived cached attribute is empty" << std::endl;
325         }
326         else
327         {
328             for(const auto& attr : resource->getCachedAttributes())
329             {
330                 std::cout << "\tkey : " << attr.key() << std::endl
331                           << "\tvalue : " << attr.value().toString() << std::endl;
332             }
333         }
334     }
335     catch (const RCSBadRequestException& e)
336     {
337         std::cout << "Exception in getCachedAttributes : " << e.what() << std::endl;
338     }
339 }
340
341 void getCachedAttribute()
342 {
343     try
344     {
345         std::cout << "\tkey : " << defaultKey << std::endl
346                   << "\tvalue : " << resource->getCachedAttribute(defaultKey).get< int >()
347                   << std::endl;
348     }
349     catch (const RCSBadRequestException& e)
350     {
351         std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
352     }
353     catch (const RCSBadGetException& e)
354     {
355         std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
356     }
357 }
358
359 void stopCaching()
360 {
361     if(resource->isCaching())
362     {
363         resource->stopCaching();
364         std::cout << "\tCaching stopped..." << std::endl;
365     }
366     else
367     {
368         std::cout << "\tCaching not started..." << std::endl;
369     }
370 }
371
372 int selectClientMenu(int selectedMenu)
373 {
374     for(int i = 0; clientMenu[i].m_menu != Menu::END_OF_MENU; i++)
375     {
376         if(clientMenu[i].m_menu == selectedMenu)
377         {
378             clientMenu[i].m_handler();
379             return clientMenu[i].m_result;
380         }
381     }
382
383     std::cout << "Invalid input, please try again" << std::endl;
384
385     return INCORRECT_INPUT;
386 }
387
388 void process()
389 {
390     while(true)
391     {
392         displayMenu();
393
394         if(selectClientMenu(processUserInput()) == QUIT_INPUT) break;
395     }
396 }
397
398 void platFormConfigure()
399 {
400     PlatformConfig config
401     {
402         OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
403     };
404     OCPlatform::Configure(config);
405 }
406
407 void discoverResource()
408 {
409     std::string resourceType;
410
411     std::cout << "========================================================" << std::endl;
412     std::cout << "1. Temperature Resource Discovery" << std::endl;
413     std::cout << "2. Light Resource Discovery" << std::endl;
414     std::cout << "========================================================" << std::endl;
415
416     switch (processUserInput())
417     {
418     case REQUEST_TEMP:
419         resourceType = "oic.r.temperaturesensor";
420         break;
421     case REQUEST_LIGHT:
422         resourceType = "core.light";
423         defaultKey = "Light";
424         break;
425     default :
426         std::cout << "Invalid input, please try again" << std::endl;
427         return;
428     }
429
430     std::string addressInput;
431     std::cout << "========================================================" << std::endl;
432     std::cout << "Please input address" << std::endl;
433     std::cout << "(want to use multicast -> please input 'multi')" << std::endl;
434     std::cout << "========================================================" << std::endl;
435
436     std::cin >> addressInput;
437
438     try
439     {
440         RCSAddress targetAddress = addressInput == multicastAdd ? RCSAddress::multicast() :
441                 RCSAddress::unicast(addressInput);
442
443         discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(
444                 targetAddress, relativeUri, resourceType, &onResourceDiscovered);
445     }
446     catch (const RCSPlatformException& e)
447     {
448         std::cout << e.what() << std::endl;
449     }
450 }
451
452 void cancelDiscovery()
453 {
454     if(!discoveryTask)
455     {
456         std::cout << "There isn't discovery request..." << std::endl;
457         return;
458     }
459     discoveryTask->cancel();
460 }
461
462 int main()
463 {
464     platFormConfigure();
465
466     try
467     {
468         process();
469     }
470     catch (const std::exception& e)
471     {
472         std::cout << "main exception : " << e.what() << std::endl;
473     }
474
475     std::cout << "Stopping the Client" << std::endl;
476
477     return 0;
478 }