bf03576a2087b44dcce3ad7f0466a766c9525d63
[platform/upstream/iotivity.git] / service / easy-setup / sampleapp / mediator / linux-samsung / richsdk_sample / mediator_sc.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.hpp"
27
28 #include "EasySetup.hpp"
29 #include "ESSCCommon.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
46 typedef void (*Runner)();
47
48 Runner g_currentRun;
49
50 int processUserInput(int min = std::numeric_limits<int>::min(),
51         int max = std::numeric_limits<int>::max())
52 {
53     assert(min <= max);
54
55     int input = 0;
56
57     std::cin >> input;
58     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
59
60     if (!std::cin.fail() && min <= input && input <= max)
61     {
62         return input;
63     }
64
65     std::cin.clear();
66     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
67
68     throw std::runtime_error("Invalid Input, please try again");
69 }
70
71 void printConfiguration(const SCEnrolleeConf& conf)
72 {
73     cout << "===========================================" << endl;
74     cout << "\tDevice Name : " << conf.getDeviceName() << endl;
75     cout << "\tModel Number : " << conf.getModelNumber() << endl;
76
77     for(auto it : conf.getWiFiModes())
78     {
79         cout << "\tSupported WiFi modes : " << it << endl;
80     }
81
82     cout << "\tSupported WiFi freq : " << static_cast<int>(conf.getWiFiFreq()) << endl;
83     cout << "\tCloud accessibility: " << conf.isCloudAccessible() << endl;
84     cout << "\tDevice Type: " << conf.getDeviceType() << endl;
85     cout << "\tDevice Sub-Type: " << conf.getDeviceSubType() << endl;
86     cout << "\tRegister Set Device: " << conf.getRegisterSetDevice() << endl;
87     cout << "\tNetwork Provisioning Info: " << conf.getNetworkProvisioningInfo() << endl;
88     cout << "\tSSOList: " << conf.getSSOList() << endl;
89     cout << "\tPnP Pin: " << conf.getPnpPin() << endl;
90     cout << "\tNetwork Connection State : " << conf.getNetConnectionState() << endl;
91     cout << "\tBSSID : " << conf.getBSSID() << endl;
92     cout << "\tUTC time: " << conf.getUTCDatetime() << endl;
93     cout << "\tRegional time: " << conf.getRegionalDatetime() << endl;
94     cout << "\tEasy Setup Protocol Version: " << conf.getESProtocolVersion() << endl;
95     std::vector<SCCandidateAPInfo> candidateInfo = conf.getCandidateAPList();
96     int  size = candidateInfo.size();
97     for(int i=0;i< size;i++)
98     {
99           cout << "[SC] Candidate Bssid :" << candidateInfo[i].bssid << endl;
100           cout << "[SC] Candidate Channel :" << candidateInfo[i].channel << endl;
101           cout << "[SC] Candidate Passphrase :" << candidateInfo[i].passphrase << endl;
102           cout << "[SC] Candidate SSID :" << candidateInfo[i].ssid << endl;
103     }
104     cout << "===========================================" << endl;
105 }
106
107 void printStatus(const SCEnrolleeStatus& status)
108 {
109     cout << "===========================================" << endl;
110     cout << "\tProvStatus : " << status.getProvStatus() << endl;
111     cout << "\tLastErrCode : " << status.getLastErrCode() << endl;
112     cout << "\tNetwork Connection State : " << status.getNetConnectionState() << endl;
113     cout << "===========================================" << endl;
114 }
115
116 void provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
117 {
118     if(secProvisioningStatus->getESResult() != ES_OK)
119     {
120       cout << "provisionSecurity is failed." << endl;
121       return;
122     }
123     else
124     {
125       cout << "provisionSecurity is success." << endl;
126       cout << "uuid : " << secProvisioningStatus->getDeviceUUID()<< endl;
127     }
128 }
129
130 void provisionSecurity()
131 {
132     try
133     {
134     remoteEnrollee->provisionSecurity((SecurityProvStatusCb)provisionSecurityStatusCallback);
135     }
136     catch (OCException &e)
137     {
138         std::cout << "Exception during provisionSecurity call" << e.reason();
139         return;
140     }
141 }
142
143 void getStatusCallback(std::shared_ptr< GetEnrolleeStatus > getEnrolleeStatus)
144 {
145     if(getEnrolleeStatus->getESResult() != ES_OK)
146     {
147       cout << "getStatus is failed." << endl;
148       return;
149     }
150     else
151     {
152       cout << "getStatus is success." << endl;
153       printStatus(std::move(getEnrolleeStatus->getEnrolleeStatus()));
154     }
155 }
156
157
158 void getStatus()
159 {
160     if(!remoteEnrollee)
161     {
162         return;
163     }
164
165     try
166     {
167         remoteEnrollee->getStatus(getStatusCallback);
168     }
169     catch (OCException &e)
170     {
171         std::cout << "Exception during getConfiguration call" << e.reason();
172         return;
173     }
174 }
175
176 void getConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
177 {
178     if(getConfigurationStatus->getESResult() != ES_OK)
179     {
180       cout << "GetConfigurationStatus is failed." << endl;
181       return;
182     }
183     else
184     {
185       cout << "GetConfigurationStatus is success." << endl;
186       printConfiguration(std::move(getConfigurationStatus->getEnrolleeConf()));
187     }
188 }
189
190 void getConfiguration()
191 {
192     if(!remoteEnrollee)
193     {
194         return;
195     }
196
197     try
198     {
199         remoteEnrollee->getConfiguration(getConfigurationCallback);
200     }
201     catch (OCException &e)
202     {
203         std::cout << "Exception during getConfiguration call" << e.reason();
204         return;
205     }
206 }
207
208 void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
209 {
210     if(provStatus->getESResult() != ES_OK)
211     {
212       cout << "Device Provisioning is failed." << endl;
213       return;
214     }
215     else
216     {
217       cout << "Device Provisioning is success." << endl;
218     }
219 }
220
221 void provisionDeviceProperty()
222 {
223     if(!remoteEnrollee)
224     {
225         return;
226     }
227
228     SCDeviceProp scDevProp;
229     scDevProp.setWiFiProp("Iotivity_SSID", "Iotivity_PWD", WPA2_PSK, TKIP_AES);
230     scDevProp.setDevConfProp("korean", "Korea", "Location");
231     scDevProp.setDiscoveryChannel(11);
232     scDevProp.setBSSID("aa:aa:aa:aa:aa:aa");
233
234     std::vector<std::string> locations;
235     locations.push_back("addr=Seoul, Rep. of Korea");
236     locations.push_back("zip=02848");
237     locations.push_back("bd=apartment");
238     scDevProp.setSCLocation(locations);
239     scDevProp.setRegisterMobileDevice("{\"wm\":\"00:11:22:33:44:55\",\"pm\":\"00:11:22:33:44:55\",\"bm\":\"00:11:22:33:44:55\",\"dt\":\"0\",\"it\":\"0\"}");
240     scDevProp.setSSOList("[{\"AvailableCount\" : \"1\", \"RegisteredCount\" : \"3\", \"AccountList\" : {\"aaa@samsung.com\", \"bbb@samsung.com\",\"ccc@samsung.com\"} }] ");
241
242     SCCandidateAPInfo candidateAPInfo[2];
243     candidateAPInfo[0].ssid = "x_5GHz";
244     candidateAPInfo[0].passphrase= "12345678";
245     candidateAPInfo[0].channel = 149;
246     candidateAPInfo[0].bssid = "aa:bb:cc:dd:ee:01";
247     candidateAPInfo[1].ssid = "y_5GHz";
248     candidateAPInfo[1].passphrase= "12345678";
249     candidateAPInfo[1].channel = 161;
250     candidateAPInfo[1].bssid = "aa:bb:cc:dd:ee:02";
251     scDevProp.setCandidateAPList(candidateAPInfo,2);
252
253     // Set UTC and regional date
254     time_t t = time(NULL);
255
256     char utcTimeStr[33] = {0};
257     struct tm *utcTime = gmtime(&t);
258     snprintf(utcTimeStr, 33, "[%04d]-[%02d]-[%02d]T[%02d]:[%02d]:[%02d]Z",
259         utcTime->tm_year+1900, utcTime->tm_mon+1, utcTime->tm_mday, utcTime->tm_hour, utcTime->tm_min, utcTime->tm_sec);
260
261     char localTimeStr[33] = {0};
262     struct tm *localTime = localtime(&t);
263     snprintf(localTimeStr, 33, "[%04d]-[%02d]-[%02d]T[%02d]:[%02d]:[%02d]Z",
264         localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
265
266     scDevProp.setUTCDatetime(utcTimeStr);
267     scDevProp.setRegionalDatetime(localTimeStr);
268
269     try
270     {
271         remoteEnrollee->provisionDeviceProperties(scDevProp, deviceProvisioningStatusCallback);
272     }
273     catch (OCException &e)
274     {
275         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
276         return;
277     }
278 }
279
280 void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
281 {
282     switch (provStatus->getESResult())
283     {
284         case ES_OK:
285             cout << "Cloud Provisioning is success." << endl;
286             break;
287         case ES_SECURE_RESOURCE_DISCOVERY_FAILURE:
288             cout << "Enrollee is not found in a given network." << endl;
289             break;
290         case ES_ACL_PROVISIONING_FAILURE:
291             cout << "ACL provisioning is failed." << endl;
292             break;
293         case ES_CERT_PROVISIONING_FAILURE:
294             cout << "CERT provisioning is failed." << endl;
295             break;
296         default:
297             cout << "Cloud Provisioning is failed." << endl;
298             break;
299     }
300 }
301
302 void provisionCloudProperty()
303 {
304     if(!remoteEnrollee)
305     {
306         return;
307     }
308
309     SCCloudProp cloudProp;
310     cloudProp.setCloudProp("authCode", "authProvider", "ciServer");
311     cloudProp.setCloudID("f002ae8b-c42c-40d3-8b8d-1927c17bd1b3");
312     cloudProp.setCredID(1);
313     cloudProp.setClientID("166135d296");
314
315     try
316     {
317         remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
318     }
319     catch (OCException &e)
320     {
321         std::cout << "Exception during provisionCloudProperties call" << e.reason();
322         return;
323     }
324 }
325
326 void DisplayMenu()
327 {
328     constexpr int PROVISION_SECURITY = 1;
329     constexpr int GET_STATUS = 2;
330     constexpr int GET_CONFIGURATION = 3;
331     constexpr int PROVISION_DEVICE_PROPERTY = 4;
332     constexpr int PROVISION_CLOUD_PROPERTY = 5;
333
334     std::cout << "========================================================\n";
335     std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
336     std::cout << GET_STATUS << ". Get Status from Enrollee  \n";
337     std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
338     std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
339     std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
340     std::cout << "========================================================\n";
341
342     int selection = processUserInput(PROVISION_SECURITY, PROVISION_CLOUD_PROPERTY);
343
344     switch (selection)
345     {
346         case PROVISION_SECURITY:
347             provisionSecurity();
348             break;
349         case GET_STATUS:
350             getStatus();
351             break;
352         case GET_CONFIGURATION:
353             getConfiguration();
354             break;
355         case PROVISION_DEVICE_PROPERTY:
356             provisionDeviceProperty();
357             break;
358         case PROVISION_CLOUD_PROPERTY:
359             provisionCloudProperty();
360             break;
361         default:
362             break;
363     };
364 }
365
366 // Callback to found resources
367 void foundResource(std::shared_ptr<OC::OCResource> resource)
368 {
369     std::string resourceURI;
370     std::string hostAddress;
371     try
372     {
373         // Do some operations with resource object.
374         if(resource &&
375            !curResource &&
376            resource->getResourceTypes().at(0) == OC_RSRVD_ES_RES_TYPE_EASYSETUP)
377         {
378             std::cout<<"DISCOVERED Resource:"<<std::endl;
379             // Get the resource URI
380             resourceURI = resource->uri();
381             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
382
383             // Get the resource host address
384             hostAddress = resource->host();
385             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
386
387             // Get the resource types
388             std::cout << "\tList of resource types: " << std::endl;
389             for(auto &resourceTypes : resource->getResourceTypes())
390             {
391                 std::cout << "\t\t" << resourceTypes << std::endl;
392             }
393
394             // Get the resource interfaces
395             std::cout << "\tList of resource interfaces: " << std::endl;
396             for(auto &resourceInterfaces : resource->getResourceInterfaces())
397             {
398                 std::cout << "\t\t" << resourceInterfaces << std::endl;
399             }
400
401             if(curResource == nullptr)
402             {
403                 remoteEnrollee = EasySetup::getInstance()->createRemoteEnrollee(resource);
404                 if(!remoteEnrollee)
405                 {
406                     std::cout << "RemoteEnrollee object is failed for some reasons!" << std::endl;
407                 }
408                 else
409                 {
410                     curResource = resource;
411                     std::cout << "RemoteEnrollee object is successfully created!" << std::endl;
412                     g_cond.notify_all();
413                 }
414             }
415         }
416     }
417     catch(std::exception &e)
418     {
419         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
420     }
421 }
422
423 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
424 {
425     (void)UNUSED_PARAM;
426     return fopen(JSON_DB_PATH, mode);
427 }
428
429 int main()
430 {
431     std::ostringstream requestURI;
432     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
433
434     PlatformConfig config
435     {
436         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::HighQos, &ps
437     };
438
439     OCPlatform::Configure(config);
440
441     try
442     {
443 #ifdef __WITH_DTLS__
444         //Initializing the provisioning client stack using the db path provided by the application.
445         OCStackResult result = OCSecure::provisionInit("");
446
447         if (result != OC_STACK_OK)
448         {
449             return -1;
450         }
451 #endif
452
453         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_EASYSETUP;
454
455         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
456         std::cout<< "Finding Resource... " <<std::endl;
457
458         std::unique_lock<std::mutex> lck(g_discoverymtx);
459         g_cond.wait_for(lck, std::chrono::seconds(4));
460
461     }
462     catch(...)
463     {
464         oclog() << "Exception in main";
465     }
466
467     while (true)
468     {
469         try
470         {
471             DisplayMenu();
472         }
473         catch (...)
474         {
475             std::cout << "Exception caught in main";
476         }
477     }
478
479     std::cout << "Stopping the client" << std::endl;
480
481     return 0;
482 }
483