Convert a data structure to class object which can be extensible for carrying more...
[platform/upstream/iotivity.git] / service / easy-setup / sampleapp / mediator / linux / richsdk_sample / mediator_cpp.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 <condition_variable>
23
24 #include "OCPlatform.h"
25 #include "OCApi.h"
26 #include "OCProvisioningManager.h"
27
28 #include "EasySetup.h"
29 #include "ESRichCommon.h"
30
31 #define ES_SAMPLE_APP_TAG "ES_SAMPLE_APP_TAG"
32 #define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC }
33
34 #define JSON_DB_PATH "./oic_svr_db_client.dat"
35
36 using namespace OC;
37 using namespace OIC::Service;
38
39 static std::shared_ptr<RemoteEnrollee> remoteEnrollee = nullptr;
40 static std::shared_ptr<OC::OCResource> curResource = nullptr;
41
42 static std::mutex g_discoverymtx;
43 static std::condition_variable g_cond;
44
45 #define PROV_RESOURCE_TYPE "ocf.wk.prov"
46
47 typedef void (*Runner)();
48
49 Runner g_currentRun;
50
51 int processUserInput(int min = std::numeric_limits<int>::min(),
52         int max = std::numeric_limits<int>::max())
53 {
54     assert(min <= max);
55
56     int input;
57
58     std::cin >> input;
59     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
60
61     if (!std::cin.fail() && min <= input && input <= max) return input;
62
63     std::cin.clear();
64     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
65
66     throw std::runtime_error("Invalid Input, please try again");
67 }
68
69 void printConfiguration(EnrolleeConf conf)
70 {
71     cout << "===========================================" << endl;
72     cout << "\tDevice Name : " << conf.getDeviceName() << endl;
73
74     for(auto it : conf.getWiFiModes())
75     {
76         cout << "\tSupported WiFi modes : " << it << endl;
77     }
78
79     cout << "\tSupported WiFi freq : " << static_cast<int>(conf.getWiFiFreq()) << endl;
80     cout << "\tCloud accessibility: " << conf.isCloudAccessible() << endl;
81     cout << "===========================================" << endl;
82 }
83
84 void printStatus(EnrolleeStatus status)
85 {
86     cout << "===========================================" << endl;
87     cout << "\tProvStatus : " << status.getProvStatus() << endl;
88     cout << "\tLastErrCode : " << status.getLastErrCode() << endl;
89     cout << "===========================================" << endl;
90 }
91
92 void provisionSecurity()
93 {
94     // TODO
95 }
96
97 void getStatusCallback(std::shared_ptr< GetEnrolleeStatus > getEnrolleeStatus)
98 {
99     if(getEnrolleeStatus->getESResult() != ES_OK)
100     {
101       cout << "getStatus is failed." << endl;
102       return;
103     }
104     else
105     {
106       cout << "getStatus is success." << endl;
107       printStatus(getEnrolleeStatus->getEnrolleeStatus());
108     }
109 }
110
111
112 void getStatus()
113 {
114     if(!remoteEnrollee)
115         return;
116
117     try
118     {
119         remoteEnrollee->getStatus(getStatusCallback);
120     }
121     catch (OCException &e)
122     {
123         std::cout << "Exception during getConfiguration call" << e.reason();
124         return;
125     }
126 }
127
128 void getConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
129 {
130     if(getConfigurationStatus->getESResult() != ES_OK)
131     {
132       cout << "GetConfigurationStatus is failed." << endl;
133       return;
134     }
135     else
136     {
137       cout << "GetConfigurationStatus is success." << endl;
138       printConfiguration(getConfigurationStatus->getEnrolleeConf());
139     }
140 }
141
142 void getConfiguration()
143 {
144     if(!remoteEnrollee)
145         return;
146
147     try
148     {
149         remoteEnrollee->getConfiguration(getConfigurationCallback);
150     }
151     catch (OCException &e)
152     {
153         std::cout << "Exception during getConfiguration call" << e.reason();
154         return;
155     }
156 }
157
158 void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
159 {
160     if(provStatus->getESResult() != ES_OK)
161     {
162       cout << "Device Provisioning is failed." << endl;
163       return;
164     }
165     else
166     {
167       cout << "Device Provisioning is success." << endl;
168     }
169 }
170
171 void provisionDeviceProperty()
172 {
173     if(!remoteEnrollee)
174         return;
175
176     DeviceProp devProp;
177     devProp.setWiFiProp("Iotivity_SSID", "Iotivity_PWD", WPA2_PSK, TKIP_AES);
178     devProp.setDevConfProp("korean", "Korea");
179
180     try
181     {
182         //remoteEnrollee->provisionDeviceProperties(deviceProp, deviceProvisioningStatusCallback);
183         remoteEnrollee->provisionDeviceProperties(devProp, deviceProvisioningStatusCallback);
184     }
185     catch (OCException &e)
186     {
187         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
188         return;
189     }
190 }
191
192 void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
193 {
194     switch (provStatus->getESCloudState())
195     {
196         case ES_CLOUD_PROVISIONING_ERROR:
197             cout << "Cloud Provisioning is failed." << endl;
198             break;
199         case ES_CLOUD_PROVISIONING_SUCCESS:
200             cout << "Cloud Provisioning is success." << endl;
201             break;
202         case ES_CLOUD_ENROLLEE_FOUND:
203             cout << "Enrollee is found in a given network." << endl;
204             break;
205         case ES_CLOUD_ENROLLEE_NOT_FOUND:
206             cout << "Enrollee is not found in a given network." << endl;
207             break;
208     }
209 }
210
211 void provisionCloudProperty()
212 {
213     if(!remoteEnrollee)
214         return;
215
216     CloudProp cloudProp;
217     cloudProp.setCloudProp("authCode", "authProvider", "ciServer");
218
219     try
220     {
221         remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
222     }
223     catch (OCException &e)
224     {
225         std::cout << "Exception during provisionCloudProperties call" << e.reason();
226         return;
227     }
228 }
229
230 void DisplayMenu()
231 {
232     constexpr int PROVISION_SECURITY = 1;
233     constexpr int GET_STATUS = 2;
234     constexpr int GET_CONFIGURATION = 3;
235     constexpr int PROVISION_DEVICE_PROPERTY = 4;
236     constexpr int PROVISION_CLOUD_PROPERTY = 5;
237
238     std::cout << "========================================================\n";
239     std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
240     std::cout << GET_STATUS << ". Get Status from Enrollee  \n";
241     std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
242     std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
243     std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
244     std::cout << "========================================================\n";
245
246     int selection = processUserInput(PROVISION_SECURITY, PROVISION_CLOUD_PROPERTY);
247
248     switch (selection)
249     {
250         case PROVISION_SECURITY:
251             provisionSecurity();
252             break;
253         case GET_STATUS:
254             getStatus();
255             break;
256         case GET_CONFIGURATION:
257             getConfiguration();
258             break;
259         case PROVISION_DEVICE_PROPERTY:
260             provisionDeviceProperty();
261             break;
262         case PROVISION_CLOUD_PROPERTY:
263             provisionCloudProperty();
264             break;
265         default:
266             break;
267     };
268 }
269
270 // Callback to found resources
271 void foundResource(std::shared_ptr<OC::OCResource> resource)
272 {
273     std::string resourceURI;
274     std::string hostAddress;
275     try
276     {
277         // Do some operations with resource object.
278         if(resource &&
279            !curResource &&
280            resource->getResourceTypes().at(0) == PROV_RESOURCE_TYPE)
281         {
282             std::cout<<"DISCOVERED Resource:"<<std::endl;
283             // Get the resource URI
284             resourceURI = resource->uri();
285             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
286
287             // Get the resource host address
288             hostAddress = resource->host();
289             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
290
291             // Get the resource types
292             std::cout << "\tList of resource types: " << std::endl;
293             for(auto &resourceTypes : resource->getResourceTypes())
294             {
295                 std::cout << "\t\t" << resourceTypes << std::endl;
296             }
297
298             // Get the resource interfaces
299             std::cout << "\tList of resource interfaces: " << std::endl;
300             for(auto &resourceInterfaces : resource->getResourceInterfaces())
301             {
302                 std::cout << "\t\t" << resourceInterfaces << std::endl;
303             }
304
305             if(curResource == nullptr)
306             {
307                 remoteEnrollee = EasySetup::getInstance()->createRemoteEnrollee(resource);
308                 if(!remoteEnrollee)
309                 {
310                     std::cout << "RemoteEnrollee object is failed for some reasons!" << std::endl;
311                 }
312                 else
313                 {
314                     curResource = resource;
315                     std::cout << "RemoteEnrollee object is successfully created!" << std::endl;
316                     g_cond.notify_all();
317                 }
318             }
319         }
320     }
321     catch(std::exception& e)
322     {
323         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
324     }
325 }
326
327 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
328 {
329     (void)UNUSED_PARAM;
330     return fopen(JSON_DB_PATH, mode);
331 }
332
333 int main()
334 {
335     std::ostringstream requestURI;
336     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
337
338     PlatformConfig config
339     {
340         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos, &ps
341     };
342
343     OCPlatform::Configure(config);
344
345 #ifdef __WITH_DTLS__
346     //Initializing the provisioning client stack using the db path provided by the application.
347     OCStackResult result = OCSecure::provisionInit("");
348
349     if (result != OC_STACK_OK)
350     {
351         return -1;
352     }
353 #endif
354
355     try
356     {
357         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << PROV_RESOURCE_TYPE;
358
359         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
360         std::cout<< "Finding Resource... " <<std::endl;
361
362         std::unique_lock<std::mutex> lck(g_discoverymtx);
363         g_cond.wait_for(lck, std::chrono::seconds(4));
364
365     }catch(OCException& e)
366     {
367         oclog() << "Exception in main: "<<e.what();
368     }
369
370     while (true)
371     {
372         try
373         {
374             DisplayMenu();
375         }
376         catch (const std::exception& e)
377         {
378             std::cout << "Exception caught in main " << e.what() << std::endl;
379         }
380     }
381
382     std::cout << "Stopping the client" << std::endl;
383
384     return 0;
385 }
386