[IOT-1420] Solve that if, rt properties ommited
[platform/upstream/iotivity.git] / service / scene-manager / sampleapp / linux / sceneclient.cpp
1 //******************************************************************
2 //
3 // Copyright 2016 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 <vector>
23 #include <algorithm>
24 #include <condition_variable>
25
26 #include "OCPlatform.h"
27 #include "RCSDiscoveryManager.h"
28 #include "RCSRemoteResourceObject.h"
29 #include "RCSAddress.h"
30 #include "RemoteSceneList.h"
31
32 using namespace OC;
33 using namespace OIC::Service;
34
35 constexpr int CREATE_REMOTE_SCENE_LIST = 1;
36
37 constexpr int CREATE_REMOTE_SCENE_COLLECTION = 1;
38 constexpr int SHOW_REMOTE_SCENE_COLLECTION = 2;
39
40 constexpr int CREATE_REMOTE_SCENE = 1;
41 constexpr int CREATE_REMOTE_SCENE_ACTION = 1;
42
43 constexpr int EXECUTE_REMOTE_SCENE = 1;
44
45 constexpr int SCENE_RESULT_OK = 200;
46
47 constexpr int numCreatedSceneAction = 2;
48 static int numRecvSceneActionCreationResp = 0;
49
50 typedef std::function< void() > Run;
51 Run g_currentRun;
52
53 const std::string scene_name = "Night mode";
54 const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI;
55 const std::vector<std::string> resourceTypes{ "oic.wk.sceneList", "core.light", "core.fan" };
56
57 std::mutex g_mtx;
58 std::mutex g_discoverymtx;
59 std::condition_variable g_cond;
60
61 std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> g_discoveryTask;
62
63 RCSRemoteResourceObject::Ptr g_foundListResource;
64 RCSRemoteResourceObject::Ptr g_foundLightResource;
65 RCSRemoteResourceObject::Ptr g_foundFanResource;
66
67 RemoteSceneList::Ptr g_sceneList;
68 RemoteSceneCollection::Ptr g_sceneCollection;
69 RemoteScene::Ptr g_scene;
70
71 void displaySceneList();
72 void runCreateRemoteSceneList();
73 void runRemoteSceneCollection();
74 void runCreateRemoteScene();
75 void runCreateRemoteSceneAction();
76 void runExecuteCreatedRemoteScene();
77 void runExecuteExistingRemoteScene();
78
79 // Scene Manager Remote API sample ---
80 void onRemoteSceneListCreated(RemoteSceneList::Ptr remoteSceneList, int eCode)
81 {
82     std::cout << __func__ << " - error code : " << eCode << std::endl;
83
84     if (eCode == SCENE_RESULT_OK)
85     {
86         g_sceneList = std::move(remoteSceneList);
87         g_currentRun = runRemoteSceneCollection;
88     }
89     else
90     {
91         std::cout << "Create Remote scene list failed." << std::endl;
92         g_currentRun = runCreateRemoteSceneList;
93     }
94     g_currentRun();
95 }
96
97 void onRemoteSceneCollectionCreated(RemoteSceneCollection::Ptr remoteSceneCol, int eCode)
98 {
99     std::cout << __func__ << " - error code : " << eCode << std::endl;
100
101     if (eCode == SCENE_RESULT_OK)
102     {
103         g_sceneCollection = remoteSceneCol;
104         g_currentRun = runCreateRemoteScene;
105     }
106     else
107     {
108         std::cout << "Create Remote scene collection failed." << std::endl;
109         g_currentRun = runRemoteSceneCollection;
110     }
111
112     g_currentRun();
113 }
114
115 void onRemoteSceneCreated(RemoteScene::Ptr remoteScene, int eCode)
116 {
117     std::cout << __func__ << " - error code : " << eCode << std::endl;
118
119     if (eCode == SCENE_RESULT_OK)
120     {
121         g_scene = remoteScene;
122
123         g_currentRun = runCreateRemoteSceneAction;
124     }
125     else
126     {
127         std::cout << "Create Remote scene failed." << std::endl;
128         g_currentRun = runCreateRemoteScene;
129     }
130
131     g_currentRun();
132 }
133
134 void onRemoteSceneActionCreated(RemoteSceneAction::Ptr, int eCode)
135 {
136     std::cout << __func__ << " - error code : " << eCode << std::endl;
137
138     if (eCode == SCENE_RESULT_OK)
139     {
140         g_currentRun = runExecuteCreatedRemoteScene;
141     }
142     else
143     {
144         std::cout << "Create Remote scene action failed." << std::endl;
145         g_currentRun = runCreateRemoteSceneAction;
146     }
147
148     numRecvSceneActionCreationResp++;
149
150     if(numCreatedSceneAction == numRecvSceneActionCreationResp)
151         g_currentRun();
152 }
153
154 void onRemoteSceneExecuted(const std::string &sceneName, int eCode)
155 {
156     std::cout << __func__ << " - scene name : " << sceneName
157               <<  ", error code : " << eCode << std::endl;
158
159     if (eCode != SCENE_RESULT_OK)
160     {
161         std::cout << "Execute scene failed." << std::endl;
162     }
163
164     g_currentRun();
165 }
166
167 // --- Scene Manager Remote API sample
168
169 void createRemoteSceneList()
170 {
171     if (g_foundListResource)
172     {
173         RemoteSceneList::createInstance(g_foundListResource, onRemoteSceneListCreated);
174     }
175     else
176     {
177         std::cout << "Scene List Resource is not discovered." << std::endl;
178         g_currentRun();
179     }
180 }
181
182 void createRemoteSceneCollection()
183 {
184     if (!g_sceneList) return;
185
186     g_sceneList->addNewSceneCollection(onRemoteSceneCollectionCreated);
187 }
188
189 void showRemoteSceneCollection()
190 {
191     if (!g_sceneList) return;
192
193     if (g_sceneList->getRemoteSceneCollections().size() == 0) return;
194
195     g_sceneCollection = g_sceneList->getRemoteSceneCollections().at(0);
196
197     if( g_sceneCollection->getRemoteScenes().size() == 0) return;
198
199     g_scene = g_sceneCollection->getRemoteScenes().begin()->second;
200 }
201
202 void createRemoteScene()
203 {
204     if (!g_sceneCollection) return;
205
206     g_sceneCollection->addNewScene(scene_name, onRemoteSceneCreated);
207 }
208
209 void createRemoteSceneAction(
210     RemoteScene::Ptr scene, RCSRemoteResourceObject::Ptr member,
211     const std::string &key, const std::string &value)
212 {
213     if (scene && member)
214     {
215         g_scene->addNewSceneAction(member, key, RCSResourceAttributes::Value(value),
216             onRemoteSceneActionCreated);
217     }
218 }
219
220 void createRemoteSceneActions()
221 {
222     createRemoteSceneAction(g_scene, g_foundLightResource, "power", "on");
223     createRemoteSceneAction(g_scene, g_foundFanResource, "speed", "50");
224 }
225
226 void executeScene()
227 {
228     displaySceneList();
229
230     if (g_scene)
231     {
232         g_scene->execute(onRemoteSceneExecuted);
233         std::cout << "\n\t'" << g_scene->getName() << "' is executed!\n" << std::endl;
234     }
235 }
236
237 // --- Scene Manager Remote API sample
238 void configurePlatform()
239 {
240     PlatformConfig config
241     {
242         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos
243     };
244     OCPlatform::Configure(config);
245 }
246
247 int processUserInput(int min, int max)
248 {
249     assert(min <= max);
250
251     int input;
252
253     std::cin >> input;
254
255     if (!std::cin.fail())
256     {
257         if (input == max + 1)  exit(0);
258         if (min <= input && input <= max) return input;
259     }
260
261     std::cin.clear();
262     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
263
264     throw std::runtime_error("Invalid Input, please try again");
265 }
266
267 void displaySceneList()
268 {
269     if (!g_sceneList) return;
270
271     std::cout << "\t" << g_sceneList->getName() << "(SceneList)" << std::endl;
272
273     if (!g_sceneCollection) return;
274
275     std::cout << "\t\t   |_ _ _ " << g_sceneCollection->getId() << " (SceneCollection)" << std::endl;
276
277     for( const auto &it_scene : g_sceneCollection->getRemoteScenes() )
278     {
279         std::cout << "\t\t\t   |_ _ _ " << it_scene.first << " (Scene)" << std::endl;
280
281         auto sceneActionList = it_scene.second->getRemoteSceneActions();
282         for (const auto &it : sceneActionList)
283         {
284             auto attr = it->getExecutionParameter();
285             for (const auto &att : attr)
286             {
287                 std::cout << "\t\t\t      \t\t|_ _ _ ";
288                 std::cout << it->getRemoteResourceObject()->getUri() << " : ";
289                 std::cout << att.key() << " - " << att.value().toString() << std::endl;
290             }
291         }
292     }
293 }
294
295 void displayClear(Run runFunc)
296 {
297     auto ret = std::system("/usr/bin/clear");
298     if(ret == -1)
299     {
300         std::cout << "clear error!" << std::endl;
301     }
302     g_currentRun = runFunc;
303 }
304
305 void displayCreateRemoteSceneListMenu()
306 {
307     std::cout << "========================================================\n";
308     std::cout << CREATE_REMOTE_SCENE_LIST  << ". Create a RemoteSceneList \n";
309     std::cout << CREATE_REMOTE_SCENE_LIST + 1  << ". Quit                 \n";
310     std::cout << "========================================================\n";
311 }
312
313 void displayRemoteSceneCollectionMenu()
314 {
315     std::cout << "========================================================               \n";
316     std::cout << CREATE_REMOTE_SCENE_COLLECTION  << ". Create a RemoteSceneCollection    \n";
317     std::cout << SHOW_REMOTE_SCENE_COLLECTION  << ". Show existing RemoteSceneCollection \n";
318     std::cout << SHOW_REMOTE_SCENE_COLLECTION + 1  << ". Quit                            \n";
319     std::cout << "========================================================               \n";
320 }
321
322 void displayRemoteSceneCreationMenu()
323 {
324     std::cout << "========================================================\n";
325     std::cout << CREATE_REMOTE_SCENE  << ". Create a RemoteScene          \n";
326     std::cout << CREATE_REMOTE_SCENE + 1  << ". Quit                      \n";
327     std::cout << "========================================================\n";
328 }
329
330 void displayRemoteSceneActionCreationMenu()
331 {
332     std::cout << "========================================================   \n";
333     std::cout << CREATE_REMOTE_SCENE_ACTION  << ". Create RemoteSceneActions \n";
334     std::cout << CREATE_REMOTE_SCENE_ACTION + 1  << ". Quit                  \n";
335     std::cout << "========================================================   \n";
336 }
337
338 void displayExecuteCreatedRemoteSceneCreationMenu()
339 {
340     std::cout << "========================================================\n";
341     std::cout << EXECUTE_REMOTE_SCENE  << ". Execute RemoteScene          \n";
342     std::cout << EXECUTE_REMOTE_SCENE + 1  << ". Quit                     \n";
343     std::cout << "========================================================\n";
344 }
345
346 void displayExecuteExistingRemoteSceneCreationMenu()
347 {
348     std::cout << "========================================================\n";
349     std::cout << EXECUTE_REMOTE_SCENE  << ". Execute a first RemoteScene  \n";
350     std::cout << EXECUTE_REMOTE_SCENE + 1  << ". Quit                     \n";
351     std::cout << "========================================================\n";
352 }
353
354 void runExecuteExistingRemoteScene()
355 {
356     displaySceneList();
357
358     displayExecuteExistingRemoteSceneCreationMenu();
359
360     try
361     {
362         int command = processUserInput(EXECUTE_REMOTE_SCENE, EXECUTE_REMOTE_SCENE);
363         switch(command)
364         {
365             case EXECUTE_REMOTE_SCENE:
366                 executeScene();
367                 displayClear(runExecuteExistingRemoteScene);
368                 break;
369         }
370     } catch (std::exception &e)
371     {
372         std::cout << e.what() << std::endl;
373         g_currentRun();
374     }
375 }
376
377 void runExecuteCreatedRemoteScene()
378 {
379     displaySceneList();
380
381     displayExecuteCreatedRemoteSceneCreationMenu();
382
383     try
384     {
385         int command = processUserInput(EXECUTE_REMOTE_SCENE, EXECUTE_REMOTE_SCENE);
386         switch(command)
387         {
388             case EXECUTE_REMOTE_SCENE:
389                 executeScene();
390                 displayClear(runExecuteCreatedRemoteScene);
391                 break;
392         }
393     } catch (std::exception &e)
394     {
395         std::cout << e.what() << std::endl;
396         g_currentRun();
397     }
398 }
399
400 void runCreateRemoteSceneAction()
401 {
402     displaySceneList();
403
404     displayRemoteSceneActionCreationMenu();
405
406     try
407     {
408         int command = processUserInput(CREATE_REMOTE_SCENE_ACTION, CREATE_REMOTE_SCENE_ACTION);
409         switch(command)
410         {
411             case CREATE_REMOTE_SCENE_ACTION:
412                 createRemoteSceneActions();
413                 displayClear(runExecuteCreatedRemoteScene);
414                 break;
415         }
416     } catch (std::exception &e)
417     {
418         std::cout << e.what() << std::endl;
419         g_currentRun();
420     }
421 }
422
423 void runCreateRemoteScene()
424 {
425     displaySceneList();
426
427     displayRemoteSceneCreationMenu();
428
429     try
430     {
431         int command = processUserInput(CREATE_REMOTE_SCENE, CREATE_REMOTE_SCENE);
432         switch(command)
433         {
434             case CREATE_REMOTE_SCENE:
435                 createRemoteScene();
436                 displayClear(runCreateRemoteSceneAction);
437                 break;
438         }
439     } catch (std::exception &e)
440     {
441         std::cout << e.what() << std::endl;
442         g_currentRun();
443     }
444 }
445
446 void runRemoteSceneCollection()
447 {
448     displaySceneList();
449
450     displayRemoteSceneCollectionMenu();
451
452     try
453     {
454         int command = processUserInput(CREATE_REMOTE_SCENE_COLLECTION, SHOW_REMOTE_SCENE_COLLECTION);
455         switch(command)
456         {
457             case CREATE_REMOTE_SCENE_COLLECTION:
458                 createRemoteSceneCollection();
459                 displayClear(runCreateRemoteScene);
460                 break;
461             case SHOW_REMOTE_SCENE_COLLECTION:
462                 showRemoteSceneCollection();
463                 displayClear(runExecuteExistingRemoteScene);
464                 g_currentRun();
465                 break;
466         }
467     } catch (std::exception &e)
468     {
469         std::cout << e.what() << std::endl;
470         g_currentRun();
471     }
472 }
473
474 void runCreateRemoteSceneList()
475 {
476     displayCreateRemoteSceneListMenu();
477
478     try
479     {
480         int command = processUserInput(CREATE_REMOTE_SCENE_LIST, CREATE_REMOTE_SCENE_LIST);
481         switch(command)
482         {
483             case CREATE_REMOTE_SCENE_LIST:
484                 createRemoteSceneList();
485                 displayClear(runRemoteSceneCollection);
486                 break;
487         }
488     } catch (std::exception &e)
489     {
490         std::cout << e.what() << std::endl;
491         g_currentRun();
492     }
493 }
494
495 void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
496 {
497     std::lock_guard< std::mutex > lock(g_discoverymtx);
498     std::cout << "onResourceDiscovered callback" << std::endl;
499
500     std::string resourceURI = foundResource->getUri();
501     std::string hostAddress = foundResource->getAddress();
502     std::vector< std::string > vecRTs = foundResource->getTypes();
503
504     std::cout << "\t\tResource URI : " << resourceURI << std::endl;
505     std::cout << "\t\tResource Host : " << hostAddress << std::endl;
506
507     // if the found resource is a scene list resource
508     if (std::find(vecRTs.begin(), vecRTs.end(), "oic.wk.sceneList") != vecRTs.end())
509         g_foundListResource = foundResource;
510
511     // if the found resource is a light resource
512     else if (std::find(vecRTs.begin(), vecRTs.end(), "core.light") != vecRTs.end())
513     {
514         g_foundLightResource = foundResource;
515     }
516
517     // if the found resource is a fan resource
518     else if (std::find(vecRTs.begin(), vecRTs.end(), "core.fan") != vecRTs.end())
519     {
520         g_foundFanResource = foundResource;
521     }
522
523     if (g_foundListResource && g_foundLightResource && g_foundFanResource)
524     {
525         g_discoveryTask->cancel();
526         return;
527     }
528
529     g_cond.notify_all();
530 }
531
532 void discoverResource()
533 {
534     std::cout << "Wait 4 seconds until discovered." << std::endl;
535
536     try
537     {
538         g_discoveryTask
539             = RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
540                     relativetUri, resourceTypes, &onResourceDiscovered);
541     }
542     catch (const RCSPlatformException &e)
543     {
544         std::cout << e.what() << std::endl;
545     }
546     std::unique_lock<std::mutex> lck(g_mtx);
547
548     g_cond.wait_for(lck, std::chrono::seconds(4));
549     return;
550 }
551
552 int main()
553 {
554     configurePlatform();
555
556     try
557     {
558         discoverResource();
559
560         g_currentRun = runCreateRemoteSceneList;
561         g_currentRun();
562     }
563     catch(std::exception &e)
564     {
565         std::cout << e.what() << std::endl;
566         return 0;
567     }
568
569     while (true) { }
570
571     std::cout << "Stopping the scene client" << std::endl;
572
573     return 0;
574 }