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