2f55cc2a1648244e634d1e6e8bcbe4de697ad0a1
[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 typedef void (*Runner)();
46
47 Runner g_currentRun;
48
49 int processUserInput(int min = std::numeric_limits<int>::min(),
50         int max = std::numeric_limits<int>::max())
51 {
52     assert(min <= max);
53
54     int input;
55
56     std::cin >> input;
57     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
58
59     if (!std::cin.fail() && min <= input && input <= max) return input;
60
61     std::cin.clear();
62     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
63
64     throw std::runtime_error("Invalid Input, please try again");
65 }
66
67 void printConfiguration(EnrolleeConf conf)
68 {
69     cout << "===========================================" << endl;
70     cout << "\tDevice Name : " << conf.getDeviceName() << endl;
71     cout << "\tModel Number : " << conf.getModelNumber() << endl;
72
73     for(auto it : conf.getWiFiModes())
74     {
75         cout << "\tSupported WiFi modes : " << it << endl;
76     }
77
78     cout << "\tSupported WiFi freq : " << static_cast<int>(conf.getWiFiFreq()) << endl;
79     cout << "\tCloud accessibility: " << conf.isCloudAccessible() << endl;
80     cout << "===========================================" << endl;
81 }
82
83 void printStatus(EnrolleeStatus status)
84 {
85     cout << "===========================================" << endl;
86     cout << "\tProvStatus : " << status.getProvStatus() << endl;
87     cout << "\tLastErrCode : " << status.getLastErrCode() << endl;
88     cout << "===========================================" << endl;
89 }
90
91 void provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
92 {
93     if(secProvisioningStatus->getESResult() != ES_OK)
94     {
95       cout << "provisionSecurity is failed." << endl;
96       return;
97     }
98     else
99     {
100       cout << "provisionSecurity is success." << endl;
101       cout << "uuid : " << secProvisioningStatus->getDeviceUUID()<< endl;
102     }
103 }
104
105 void provisionSecurity()
106 {
107     if(!remoteEnrollee)
108     {
109         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
110         return;
111     }
112
113     try
114     {
115         remoteEnrollee->provisionSecurity(provisionSecurityStatusCallback);
116     }
117     catch (OCException &e)
118     {
119         std::cout << "Exception during provisionSecurity call" << e.reason();
120         return;
121     }
122 }
123
124 void getStatusCallback(std::shared_ptr< GetEnrolleeStatus > getEnrolleeStatus)
125 {
126     if(getEnrolleeStatus->getESResult() != ES_OK)
127     {
128       cout << "getStatus is failed." << endl;
129       return;
130     }
131     else
132     {
133       cout << "getStatus is success." << endl;
134       printStatus(getEnrolleeStatus->getEnrolleeStatus());
135     }
136 }
137
138
139 void getStatus()
140 {
141     if(!remoteEnrollee)
142     {
143         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
144         return;
145     }
146
147     try
148     {
149         remoteEnrollee->getStatus(getStatusCallback);
150     }
151     catch (OCException &e)
152     {
153         std::cout << "Exception during getConfiguration call" << e.reason();
154         return;
155     }
156 }
157
158 void getConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
159 {
160     if(getConfigurationStatus->getESResult() != ES_OK)
161     {
162       cout << "GetConfigurationStatus is failed." << endl;
163       return;
164     }
165     else
166     {
167       cout << "GetConfigurationStatus is success." << endl;
168       printConfiguration(getConfigurationStatus->getEnrolleeConf());
169     }
170 }
171
172 void getConfiguration()
173 {
174     if(!remoteEnrollee)
175     {
176         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
177         return;
178     }
179
180     try
181     {
182         remoteEnrollee->getConfiguration(getConfigurationCallback);
183     }
184     catch (OCException &e)
185     {
186         std::cout << "Exception during getConfiguration call" << e.reason();
187         return;
188     }
189 }
190
191 void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
192 {
193     if(provStatus->getESResult() != ES_OK)
194     {
195       cout << "Device Provisioning is failed." << endl;
196       return;
197     }
198     else
199     {
200       cout << "Device Provisioning is success." << endl;
201     }
202 }
203
204 void provisionDeviceProperty()
205 {
206     if(!remoteEnrollee)
207     {
208         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
209         return;
210     }
211
212     DeviceProp devProp;
213     devProp.setWiFiProp("Iotivity_SSID", "Iotivity_PWD", WPA2_PSK, TKIP_AES);
214     devProp.setDevConfProp("korean", "Korea", "Location");
215
216     try
217     {
218         remoteEnrollee->provisionDeviceProperties(devProp, deviceProvisioningStatusCallback);
219     }
220     catch (OCException &e)
221     {
222         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
223         return;
224     }
225 }
226
227 void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
228 {
229     switch (provStatus->getESResult())
230     {
231         case ES_OK:
232             cout << "Cloud Provisioning is success." << endl;
233             break;
234         case ES_FOUND_ENROLLEE:
235             cout << "Enrollee is found in a given network." << endl;
236             break;
237         case ES_NOT_FOUND_ENROLLEE:
238             cout << "Enrollee is not found in a given network." << endl;
239             break;
240         default:
241             cout << "Cloud Provisioning is failed." << endl;
242             break;
243     }
244 }
245
246 void provisionCloudProperty()
247 {
248     if(!remoteEnrollee)
249     {
250         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
251         return;
252     }
253
254     CloudProp cloudProp;
255     cloudProp.setCloudProp("authCode", "authProvider", "ciServer");
256     cloudProp.setCloudID("f002ae8b-c42c-40d3-8b8d-1927c17bd1b3");
257     cloudProp.setCredID(1);
258
259     try
260     {
261         remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
262     }
263     catch (OCException &e)
264     {
265         std::cout << "Exception during provisionCloudProperties call" << e.reason();
266         return;
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) == OC_RSRVD_ES_RES_TYPE_PROV)
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 void discoveryEnrolleeResource()
328 {
329         try
330         {
331             std::ostringstream requestURI;
332         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_PROV;
333         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
334         std::cout<< "Finding Resource... " <<std::endl;
335
336         std::unique_lock<std::mutex> lck(g_discoverymtx);
337         g_cond.wait_for(lck, std::chrono::seconds(5));
338         }
339         catch (OCException& e)
340         {
341                 std::cout << "Exception in discoveryEnrolleeResource: "<<e.what();
342         }
343 }
344
345 void DisplayMenu()
346 {
347         constexpr int DISCOVERY_ENROLLEE = 1;
348     constexpr int PROVISION_SECURITY = 2;
349     constexpr int GET_STATUS = 3;
350     constexpr int GET_CONFIGURATION = 4;
351     constexpr int PROVISION_DEVICE_PROPERTY = 5;
352     constexpr int PROVISION_CLOUD_PROPERTY = 6;
353
354     std::cout << "========================================================\n";
355     std::cout << DISCOVERY_ENROLLEE << ". Discovery Enrollee Resource \n";
356     std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
357     std::cout << GET_STATUS << ". Get Status from Enrollee  \n";
358     std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
359     std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
360     std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
361     std::cout << "========================================================\n";
362
363     int selection = processUserInput(DISCOVERY_ENROLLEE, PROVISION_CLOUD_PROPERTY);
364
365     switch (selection)
366     {
367         case DISCOVERY_ENROLLEE:
368             discoveryEnrolleeResource();
369             break;
370         case PROVISION_SECURITY:
371             provisionSecurity();
372             break;
373         case GET_STATUS:
374             getStatus();
375             break;
376         case GET_CONFIGURATION:
377             getConfiguration();
378             break;
379         case PROVISION_DEVICE_PROPERTY:
380             provisionDeviceProperty();
381             break;
382         case PROVISION_CLOUD_PROPERTY:
383             provisionCloudProperty();
384             break;
385         default:
386             break;
387     };
388 }
389
390 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
391 {
392     (void)UNUSED_PARAM;
393     return fopen(JSON_DB_PATH, mode);
394 }
395
396 int main()
397 {
398     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
399
400     PlatformConfig config
401     {
402         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos, &ps
403     };
404
405     OCPlatform::Configure(config);
406
407     try
408     {
409 #ifdef __WITH_DTLS__
410         //Initializing the provisioning client stack using the db path provided by the application.
411         OCStackResult result = OCSecure::provisionInit("");
412
413         if (result != OC_STACK_OK)
414         {
415             return -1;
416         }
417 #endif
418     }catch(OCException& e)
419     {
420         std::cout << "Exception in main: "<<e.what();
421     }
422
423     while (true)
424     {
425         try
426         {
427             DisplayMenu();
428         }
429         catch (const std::exception& e)
430         {
431             std::cout << "Exception caught in main " << e.what() << std::endl;
432         }
433     }
434
435     std::cout << "Stopping the client" << std::endl;
436
437     return 0;
438 }
439