Merge branch 'easysetup'
[platform/upstream/iotivity.git] / service / resource-encapsulation / examples / linux / NestedAttributesClient.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 <mutex>
24 #include <condition_variable>
25
26 #include "RCSDiscoveryManager.h"
27 #include "RCSRemoteResourceObject.h"
28 #include "RCSResourceAttributes.h"
29 #include "RCSAddress.h"
30
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 enum Menu
41 {
42     GET_ATTRIBUTE = 1,
43     SET_ATTRIBUTE,
44     QUIT,
45     END_OF_MENU
46 };
47
48 typedef void(*ClientMenuHandler)();
49 typedef int ReturnValue;
50
51 struct ClientMenu
52 {
53     Menu m_menu;
54     ClientMenuHandler m_handler;
55     ReturnValue m_result;
56 };
57
58 void getAttributeFromRemoteServer();
59 void setAttributeToRemoteServer();
60
61 ClientMenu clientMenu[] =
62 {
63     {Menu::GET_ATTRIBUTE, getAttributeFromRemoteServer, CORRECT_INPUT},
64     {Menu::SET_ATTRIBUTE, setAttributeToRemoteServer, CORRECT_INPUT},
65     {Menu::QUIT, [](){}, QUIT_INPUT},
66     {Menu::END_OF_MENU, nullptr, INCORRECT_INPUT}
67 };
68
69 const std::string defaultKey = "deviceInfo";
70 const std::string resourceType = "core.ac";
71
72 std::mutex mtx;
73 std::condition_variable cond;
74
75 RCSRemoteResourceObject::Ptr g_resource;
76
77 void displayMenu()
78 {
79     std::cout << std::endl;
80     std::cout << "1 :: Get Attribute" << std::endl;
81     std::cout << "2 :: Set Attribute" << std::endl;
82 }
83
84 void onResourceDiscovered(RCSRemoteResourceObject::Ptr foundResource)
85 {
86     std::cout << "onResourceDiscovered callback" << std::endl;
87
88     std::cout << "\t\tResource URI : " << foundResource->getUri() << std::endl;
89     std::cout << "\t\tResource Host : " << foundResource->getAddress() << std::endl;
90
91     g_resource = foundResource;
92
93     cond.notify_all();
94 }
95
96 void onRemoteAttributesReceivedCallback(const RCSResourceAttributes &attributes, int /*eCode*/)
97 {
98     std::cout << "onRemoteAttributesReceivedCallback callback\n" << std::endl;
99
100     if (attributes.empty())
101     {
102         std::cout << "\tAttribute is Empty" << std::endl;
103         return;
104     }
105
106     for (const auto & attr : attributes)
107     {
108         std::cout << "\tkey : " << attr.key() << "\n\tvalue : "
109                   << attr.value().toString() << std::endl;
110         std::cout << "=============================================\n" << std::endl;
111
112         const auto& doubleVector = attr.value().
113                 get< std::vector< std::vector< RCSResourceAttributes > > >();
114
115         for (const auto& vector : doubleVector)
116         {
117             for (const auto& attrs : vector)
118             {
119                 for (const auto & kvPair : attrs)
120                 {
121                     std::cout << "\t" << kvPair.key() << " : "  <<
122                             kvPair.value().toString() << std::endl;
123                 }
124             }
125             std::cout << std::endl;
126         }
127         std::cout << "=============================================\n" << std::endl;
128     }
129     displayMenu();
130 }
131
132 std::vector< std::vector< RCSResourceAttributes > > createNestedAttribute(int speedValue,
133         int aircValue)
134 {
135     RCSResourceAttributes model;
136     RCSResourceAttributes weight;
137     RCSResourceAttributes dimensions;
138
139     model["model"] = "SamsungAC";
140     weight["weight"] = 3;
141     dimensions["dimensions"] = "10x25x35";
142
143     RCSResourceAttributes speed;
144     RCSResourceAttributes airCirculation;
145
146     speed["speed"] = speedValue;
147     airCirculation["air"] = aircValue;
148
149     RCSResourceAttributes temperature;
150     RCSResourceAttributes humidity;
151
152     temperature["temp"] = 30;
153     humidity["humidity"] = 30;
154
155     RCSResourceAttributes power;
156     RCSResourceAttributes capacity;
157
158     power["power"] = 1600;
159     capacity["capacity"] = 1;
160
161     RCSResourceAttributes red;
162     RCSResourceAttributes green;
163
164     red["red"] = 50;
165     green["green"] = 60;
166
167     std::vector< RCSResourceAttributes > generalInfo{ model, weight, dimensions };
168     std::vector< RCSResourceAttributes > fan{ speed, airCirculation } ;
169     std::vector< RCSResourceAttributes > tempSensor{ temperature, humidity } ;
170     std::vector< RCSResourceAttributes > efficiency{ power, capacity };
171     std::vector< RCSResourceAttributes > light{ red, green };
172
173     std::vector< std::vector< RCSResourceAttributes > > acServer;
174
175     acServer.push_back(generalInfo);
176     acServer.push_back(fan);
177     acServer.push_back(tempSensor);
178     acServer.push_back(efficiency);
179     acServer.push_back(light);
180
181     return acServer;
182 }
183
184 int processUserInput()
185 {
186     int userInput;
187     std::cin >> userInput;
188     if (std::cin.fail())
189     {
190         std::cin.clear();
191         std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
192         return -1;
193     }
194     return userInput;
195 }
196
197 void getAttributeFromRemoteServer()
198 {
199     g_resource->getRemoteAttributes(&onRemoteAttributesReceivedCallback);
200 }
201
202 void setAttributeToRemoteServer()
203 {
204     int speed, airc;
205
206     std::cout << "\tEnter the Fan Speed you want to set : ";
207     std::cin >> speed;
208     std::cout << "\tEnter the Air circulation value you want to set :";
209     std::cin >> airc;
210
211     RCSResourceAttributes setAttribute;
212     setAttribute[defaultKey] = createNestedAttribute(speed, airc);
213
214     g_resource->setRemoteAttributes(setAttribute,
215                                   &onRemoteAttributesReceivedCallback);
216 }
217
218 int selectClientMenu(int selectedMenu)
219 {
220     for (int i = 0; clientMenu[i].m_menu != Menu::END_OF_MENU; i++)
221     {
222         if (clientMenu[i].m_menu == selectedMenu)
223         {
224             clientMenu[i].m_handler();
225             return clientMenu[i].m_result;
226         }
227     }
228
229     std::cout << "Invalid input, please try again" << std::endl;
230
231     return INCORRECT_INPUT;
232 }
233
234 void process()
235 {
236     while (true)
237     {
238         displayMenu();
239
240         if (selectClientMenu(processUserInput()) == QUIT_INPUT)
241             break;
242     }
243 }
244
245 void platFormConfigure()
246 {
247     PlatformConfig config
248     {
249         OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
250     };
251     OCPlatform::Configure(config);
252 }
253
254 bool discoverResource()
255 {
256     std::cout << "Wait 2 seconds until discovered." << std::endl;
257
258     try
259     {
260         RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(),
261                 resourceType, &onResourceDiscovered);
262     }
263     catch(const RCSPlatformException& e)
264     {
265          std::cout << e.what() << std::endl;
266     }
267     std::unique_lock<std::mutex> lck(mtx);
268     cond.wait_for(lck, std::chrono::seconds(2));
269
270     return g_resource != nullptr;
271 }
272
273 int main()
274 {
275     platFormConfigure();
276
277     if (!discoverResource())
278     {
279         std::cout << "Can't discovered Server... Exiting the Client." << std::endl;
280         return -1;
281     }
282
283     try
284     {
285         process();
286     }
287     catch (const std::exception &e)
288     {
289         std::cout << "main exception : " << e.what() << std::endl;
290     }
291
292     std::cout << "Stopping the client" << std::endl;
293
294     return 0;
295 }