Update a mediator sample application for linux platform
[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     DeviceConfig devConfig = conf.getDevConf();
73     WiFiConfig wifiConfig = conf.getWiFiConf();
74
75     cout << "\tDeviceConfig.name : " << devConfig.name << endl;
76     cout << "\tDeviceConfig.language : " << devConfig.language << endl;
77     cout << "\tDeviceConfig.country : " << devConfig.country << endl;
78
79     for(auto mode = wifiConfig.modes.begin(); mode != wifiConfig.modes.end(); ++mode)
80     {
81         cout << "\tnetInfo.modes : " << static_cast<int>(*mode) << endl;
82     }
83     cout << "\tnetInfo.freq : " << static_cast<int>(wifiConfig.freq) << endl;
84     cout << "===========================================" << endl;
85 }
86
87 void provisionSecurity()
88 {
89     // TODO
90 }
91
92 void GetConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
93 {
94     if(getConfigurationStatus->getESResult() != ES_OK)
95     {
96       cout << "GetConfigurationStatus is failed." << endl;
97       return;
98     }
99     else
100     {
101       cout << "GetConfigurationStatus is success." << endl;
102       printConfiguration(getConfigurationStatus->getEnrolleeConf());
103     }
104 }
105
106 void getConfiguration()
107 {
108     if(!remoteEnrollee)
109         return;
110
111     try
112     {
113         remoteEnrollee->getConfiguration(GetConfigurationCallback);
114     }
115     catch (OCException &e)
116     {
117         std::cout << "Exception during getConfiguration call" << e.reason();
118         return;
119     }
120 }
121
122 void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
123 {
124     if(provStatus->getESResult() != ES_OK)
125     {
126       cout << "Device Provisioning is failed." << endl;
127       return;
128     }
129     else
130     {
131       cout << "Device Provisioning is success." << endl;
132     }
133 }
134
135 void provisionDeviceProperty()
136 {
137     if(!remoteEnrollee)
138         return;
139
140     DeviceProp deviceProp;
141     deviceProp.WIFI.ssid = "Iotivity_SSID";
142     deviceProp.WIFI.pwd = "Iotivity_PWD";
143     deviceProp.WIFI.authtype = WPA2_PSK;
144     deviceProp.WIFI.enctype = TKIP_AES;
145     deviceProp.Device.language = "korean";
146     deviceProp.Device.country = "Korea";
147
148     try
149     {
150         remoteEnrollee->provisionDeviceProperties(deviceProp, deviceProvisioningStatusCallback);
151     }
152     catch (OCException &e)
153     {
154         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
155         return;
156     }
157 }
158
159 void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
160 {
161     switch (provStatus->getESCloudState())
162     {
163         case ES_CLOUD_PROVISIONING_ERROR:
164             cout << "Cloud Provisioning is failed." << endl;
165             break;
166         case ES_CLOUD_PROVISIONING_SUCCESS:
167             cout << "Cloud Provisioning is success." << endl;
168             break;
169         case ES_CLOUD_ENROLLEE_FOUND:
170             cout << "Enrollee is found in a given network." << endl;
171             break;
172         case ES_CLOUD_ENROLLEE_NOT_FOUND:
173             cout << "Enrollee is not found in a given network." << endl;
174             break;
175     }
176 }
177
178 void provisionCloudProperty()
179 {
180     if(!remoteEnrollee)
181         return;
182
183     CloudProp cloudProp;
184     cloudProp.authCode = "authCode";
185     cloudProp.authProvider = "authProvider";
186     cloudProp.ciServer = "ciServer";
187
188     try
189     {
190         remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
191     }
192     catch (OCException &e)
193     {
194         std::cout << "Exception during provisionCloudProperties call" << e.reason();
195         return;
196     }
197 }
198
199 void DisplayMenu()
200 {
201     constexpr int PROVISION_SECURITY = 1;
202     constexpr int GET_CONFIGURATION = 2;
203     constexpr int PROVISION_DEVICE_PROPERTY = 3;
204     constexpr int PROVISION_CLOUD_PROPERTY = 4;
205
206     std::cout << "========================================================\n";
207     std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
208     std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
209     std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
210     std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
211     std::cout << "========================================================\n";
212
213     int selection = processUserInput(PROVISION_SECURITY, PROVISION_CLOUD_PROPERTY);
214
215     switch (selection)
216     {
217         case PROVISION_SECURITY:
218             provisionSecurity();
219             break;
220         case GET_CONFIGURATION:
221             getConfiguration();
222             break;
223         case PROVISION_DEVICE_PROPERTY:
224             provisionDeviceProperty();
225             break;
226         case PROVISION_CLOUD_PROPERTY:
227             provisionCloudProperty();
228             break;
229         default:
230             break;
231     };
232 }
233
234 // Callback to found resources
235 void foundResource(std::shared_ptr<OC::OCResource> resource)
236 {
237     std::string resourceURI;
238     std::string hostAddress;
239     try
240     {
241         // Do some operations with resource object.
242         if(resource &&
243            !curResource &&
244            resource->getResourceTypes().at(0) == PROV_RESOURCE_TYPE)
245         {
246             std::cout<<"DISCOVERED Resource:"<<std::endl;
247             // Get the resource URI
248             resourceURI = resource->uri();
249             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
250
251             // Get the resource host address
252             hostAddress = resource->host();
253             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
254
255             // Get the resource types
256             std::cout << "\tList of resource types: " << std::endl;
257             for(auto &resourceTypes : resource->getResourceTypes())
258             {
259                 std::cout << "\t\t" << resourceTypes << std::endl;
260             }
261
262             // Get the resource interfaces
263             std::cout << "\tList of resource interfaces: " << std::endl;
264             for(auto &resourceInterfaces : resource->getResourceInterfaces())
265             {
266                 std::cout << "\t\t" << resourceInterfaces << std::endl;
267             }
268
269             if(curResource == nullptr)
270             {
271                 remoteEnrollee = EasySetup::getInstance()->createRemoteEnrollee(resource);
272                 if(!remoteEnrollee)
273                 {
274                     std::cout << "RemoteEnrollee object is failed for some reasons!" << std::endl;
275                 }
276                 else
277                 {
278                     curResource = resource;
279                     std::cout << "RemoteEnrollee object is successfully created!" << std::endl;
280                     g_cond.notify_all();
281                 }
282             }
283         }
284     }
285     catch(std::exception& e)
286     {
287         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
288     }
289 }
290
291 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
292 {
293     (void)UNUSED_PARAM;
294     return fopen(JSON_DB_PATH, mode);
295 }
296
297 int main()
298 {
299     std::ostringstream requestURI;
300     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
301
302     PlatformConfig config
303     {
304         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos, &ps
305     };
306
307     OCPlatform::Configure(config);
308
309 #ifdef __WITH_DTLS__
310     //Initializing the provisioning client stack using the db path provided by the application.
311     OCStackResult result = OCSecure::provisionInit("");
312
313     if (result != OC_STACK_OK)
314     {
315         return -1;
316     }
317 #endif
318
319     try
320     {
321         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << PROV_RESOURCE_TYPE;
322
323         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
324         std::cout<< "Finding Resource... " <<std::endl;
325
326         std::unique_lock<std::mutex> lck(g_discoverymtx);
327         g_cond.wait_for(lck, std::chrono::seconds(4));
328
329     }catch(OCException& e)
330     {
331         oclog() << "Exception in main: "<<e.what();
332     }
333
334     while (true)
335     {
336         try
337         {
338             DisplayMenu();
339         }
340         catch (const std::exception& e)
341         {
342             std::cout << "Exception caught in main " << e.what() << std::endl;
343         }
344     }
345
346     std::cout << "Stopping the client" << std::endl;
347
348     return 0;
349 }
350