48837f10502132bbe4bc71eca574f3d6ca2e749a
[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
25 #include "OCPlatform.h"
26 #include "RCSDiscoveryManager.h"
27 #include "RCSRemoteResourceObject.h"
28 #include "RCSAddress.h"
29 #include "RemoteSceneList.h"
30
31 using namespace OC;
32 using namespace OIC::Service;
33
34 constexpr int CREATE_REMOTE_SCENE_LIST = 1;
35
36 constexpr int CREATE_REMOTE_SCENE_COLLECTION = 1;
37 constexpr int SHOW_REMOTE_SCENE_COLLECTION = 2;
38
39 constexpr int CREATE_REMOTE_SCENE = 1;
40 constexpr int CREATE_REMOTE_SCENE_ACTION = 1;
41
42 constexpr int EXECUTE_REMOTE_SCENE = 1;
43
44 constexpr int SCENE_RESULT_OK = 200;
45
46 constexpr int numCreatedSceneAction = 2;
47 static int numRecvSceneActionCreationResp = 0;
48
49 typedef std::function< void() > Run;
50 Run g_currentRun;
51
52 const std::string scene_name = "Night mode";
53 const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI;
54 const std::vector<std::string> resourceTypes{ "oic.wk.scenelist", "core.light", "core.fan" };
55
56 std::mutex g_mtx;
57 std::mutex g_discoverymtx;
58 std::condition_variable g_cond;
59
60 std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> g_discoveryTask;
61
62 RCSRemoteResourceObject::Ptr g_foundListResource;
63 RCSRemoteResourceObject::Ptr g_foundLightResource;
64 RCSRemoteResourceObject::Ptr g_foundFanResource;
65
66 RemoteSceneList::Ptr g_sceneList;
67 RemoteSceneCollection::Ptr g_sceneCollection;
68 RemoteScene::Ptr g_scene;
69
70 void displaySceneList();
71 void runCreateRemoteSceneList();
72 void runRemoteSceneCollection();
73 void runCreateRemoteScene();
74 void runCreateRemoteSceneAction();
75 void runExecuteCreatedRemoteScene();
76 void runExecuteExistingRemoteScene();
77
78 // Scene Manager Remote API sample ---
79 void onRemoteSceneListCreated(RemoteSceneList::Ptr remoteSceneList, int eCode)
80 {
81     std::cout << __func__ << " - error code : " << eCode << std::endl;
82
83     if (eCode == SCENE_RESULT_OK)
84     {
85         g_sceneList = std::move(remoteSceneList);
86         g_currentRun = runRemoteSceneCollection;
87     }
88     else
89     {
90         std::cout << "Create Remote scene list failed." << std::endl;
91         g_currentRun = runCreateRemoteSceneList;
92     }
93     g_currentRun();
94 }
95
96 void onRemoteSceneCollectionCreated(RemoteSceneCollection::Ptr remoteSceneCol, int eCode)
97 {
98     std::cout << __func__ << " - error code : " << eCode << std::endl;
99
100     if (eCode == SCENE_RESULT_OK)
101     {
102         g_sceneCollection = remoteSceneCol;
103         g_currentRun = runCreateRemoteScene;
104     }
105     else
106     {
107         std::cout << "Create Remote scene collection failed." << std::endl;
108         g_currentRun = runRemoteSceneCollection;
109     }
110
111     g_currentRun();
112 }
113
114 void onRemoteSceneCreated(RemoteScene::Ptr remoteScene, int eCode)
115 {
116     std::cout << __func__ << " - error code : " << eCode << std::endl;
117
118     if (eCode == SCENE_RESULT_OK)
119     {
120         g_scene = remoteScene;
121
122         g_currentRun = runCreateRemoteSceneAction;
123     }
124     else
125     {
126         std::cout << "Create Remote scene failed." << std::endl;
127         g_currentRun = runCreateRemoteScene;
128     }
129
130     g_currentRun();
131 }
132
133 void onRemoteSceneActionCreated(RemoteSceneAction::Ptr, int eCode)
134 {
135     std::cout << __func__ << " - error code : " << eCode << std::endl;
136
137     if (eCode == SCENE_RESULT_OK)
138     {
139         g_currentRun = runExecuteCreatedRemoteScene;
140     }
141     else
142     {
143         std::cout << "Create Remote scene action failed." << std::endl;
144         g_currentRun = runCreateRemoteSceneAction;
145     }
146
147     numRecvSceneActionCreationResp++;
148
149     if(numCreatedSceneAction == numRecvSceneActionCreationResp)
150         g_currentRun();
151 }
152
153 void onRemoteSceneExecuted(const std::string &sceneName, int eCode)
154 {
155     std::cout << __func__ << " - scene name : " << sceneName
156               <<  ", error code : " << eCode << std::endl;
157
158     if (eCode != SCENE_RESULT_OK)
159     {
160         std::cout << "Execute scene failed." << std::endl;
161     }
162
163     g_currentRun();
164 }
165
166 // --- Scene Manager Remote API sample
167
168 void createRemoteSceneList()
169 {
170     if (g_foundListResource)
171     {
172         RemoteSceneList::createInstance(g_foundListResource, onRemoteSceneListCreated);
173     }
174     else
175     {
176         std::cout << "Scene List Resource is not discovered." << std::endl;
177         g_currentRun();
178     }
179 }
180
181 void createRemoteSceneCollection()
182 {
183     if (!g_sceneList) return;
184
185     g_sceneList->addNewSceneCollection(onRemoteSceneCollectionCreated);
186 }
187
188 void showRemoteSceneCollection()
189 {
190     if (!g_sceneList) return;
191
192     if (g_sceneList->getRemoteSceneCollections().size() == 0) return;
193
194     g_sceneCollection = g_sceneList->getRemoteSceneCollections().at(0);
195
196     if( g_sceneCollection->getRemoteScenes().size() == 0) return;
197
198     g_scene = g_sceneCollection->getRemoteScenes().begin()->second;
199 }
200
201 void createRemoteScene()
202 {
203     if (!g_sceneCollection) return;
204
205     g_sceneCollection->addNewScene(scene_name, onRemoteSceneCreated);
206 }
207
208 void createRemoteSceneAction(
209     RemoteScene::Ptr scene, RCSRemoteResourceObject::Ptr member,
210     const std::string &key, const std::string &value)
211 {
212     if (scene && member)
213     {
214         g_scene->addNewSceneAction(member, key, RCSResourceAttributes::Value(value),
215             onRemoteSceneActionCreated);
216     }
217 }
218
219 void createRemoteSceneActions()
220 {
221     createRemoteSceneAction(g_scene, g_foundLightResource, "power", "on");
222     createRemoteSceneAction(g_scene, g_foundFanResource, "speed", "50");
223 }
224
225 void executeScene()
226 {
227     displaySceneList();
228
229     if (g_scene)
230     {
231         g_scene->execute(onRemoteSceneExecuted);
232         std::cout << "\n\t'" << g_scene->getName() << "' is executed!\n" << std::endl;
233     }
234 }
235
236 // --- Scene Manager Remote API sample
237
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 }