Imported Upstream version 1.1.1
[platform/upstream/iotivity.git] / resource / examples / directpairingclient.cpp
1 /* *****************************************************************
2  *
3  * Copyright 2016 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 <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <string>
25 #include <map>
26 #include <cstdlib>
27 #include <pthread.h>
28 #include <mutex>
29 #include <condition_variable>
30
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34 #include "OCPlatform.h"
35 #include "OCApi.h"
36
37 #define MAX_URI_LENGTH (64)
38 #define MAX_PERMISSION_LENGTH (5)
39 #define CREATE (1)
40 #define READ (2)
41 #define UPDATE (4)
42 #define DELETE (8)
43 #define NOTIFY (16)
44 #define DASH '-'
45 #define PREDEFINED_TIMEOUT (10)
46 #define MAX_OWNED_DEVICE (10)
47 #define TAG  "provisioningclient"
48
49 #define JSON_DB_PATH "./oic_svr_db_client.json"
50 #define DAT_DB_PATH "./oic_svr_db_client.dat"
51 #define DEV_STATUS_ON "DEV_STATUS_ON"
52 #define DEV_STATUS_OFF "DEV_STATUS_OFF"
53
54 #define DP_DISCOVERY_TIMEOUT 4
55 #define DP_PIN_LENGTH 8
56
57 #define BOLD_BEGIN    "\033[1m"
58 #define RED_BEGIN     "\033[1;31m"
59 #define GREEN_BEGIN   "\033[1;92m"
60 #define COLOR_END     "\033[0m"
61
62 using namespace OC;
63
64 static int ask = 1;
65 static PairedDevices discoveredDeviceList, pairedDeviceList;
66
67 static FILE* client_open(const char* /*fileName*/, const char *mode)
68 {
69     return fopen(DAT_DB_PATH, mode);
70 }
71
72
73 static void printMenu()
74 {
75     std::cout << GREEN_BEGIN "Choose an option:" COLOR_END<<std::endl;
76     std::cout << GREEN_BEGIN "# 1 (DP device discovery) : discover Direct-Pairing devices"
77         COLOR_END<<std::endl;
78     std::cout << GREEN_BEGIN "# 2 (start Direct-Pairing) : negotiate DP method & start Direct-Pairin"
79         COLOR_END<<std::endl;
80     std::cout << GREEN_BEGIN "# 3 (list all device) : list all discovered/paired devices"
81         COLOR_END<<std::endl;
82     std::cout << GREEN_BEGIN "# 4 (send data) : send data to device" COLOR_END<<std::endl;
83     std::cout << GREEN_BEGIN "# 9 (quit) : quit test " COLOR_END<<std::endl;
84 }
85
86 static void printPrompt()
87 {
88     std::cout << BOLD_BEGIN "IoTivity-DP#" COLOR_END" ";
89 }
90
91 static void printDevices(PairedDevices& list)
92 {
93     for (size_t i = 0; i < list.size(); i++)
94     {
95         std::cout << "["<< i+1 << "]" << " ID: " << list[i]->getDeviceID() << std::endl;
96     }
97 }
98
99 static void findCallback(PairedDevices discoveredDevList)
100 {
101
102     if (0 == discoveredDevList.size())
103     {
104         std::cout<< "No Direct-pairing Support device Found" << std::endl;
105     }
106     else
107     {
108         std::cout << "Discovered Direct-Pairing Support Device"<< std::endl;
109         discoveredDeviceList = discoveredDevList;
110         printDevices(discoveredDevList);
111     }
112
113     printMenu();
114     printPrompt();
115     fflush(NULL);
116 }
117
118 static bool printPairingMethod(int choice)
119 {
120     if (NULL == discoveredDeviceList[choice])// || false == discoveredDeviceList[choice]->edp)
121     {
122         std::cout<< "Invalid device or Not support direct-pairing..\n\n" << std::endl;
123         return false;
124     }
125
126     auto prms = discoveredDeviceList[choice]->getPairingMethods();
127     if (0 == prms.size())
128     {
129         std::cout << "Not exist any support method..\n\n" << std::endl;
130         return false;
131     }
132
133     bool ret = true;
134     std::cout << "\n* List of supported pairing methods *" << std::endl;
135
136     for (unsigned int i = 0; i < prms.size(); i++)
137     {
138         std::cout<< "[" << i+1 << "]";
139         switch (prms[i])
140         {
141             case DP_PRE_CONFIGURED:
142                 std::cout<<"Pre-Configured PIN"<<std::endl;;
143                 break;
144             case DP_RANDOM_PIN:
145                 std::cout<<"Random PIN"<<std::endl;;
146                 break;
147             default:
148                 std::cout<<"NOT Allowed ("<< prms[i]<<")"<<std::endl;
149                 ret = false;
150                 break;
151         }
152         std::cout<<std::endl;
153     }
154
155     return ret;
156 }
157
158 static void resultCallback(std::shared_ptr<OCDirectPairing> ptr, OCStackResult result)
159 {
160
161     if (OC_STACK_OK == result)
162     {
163         std::cout << " Direct-Pairing SUCCESS" << std::endl;
164         std::cout << "Taget Add info:" << ptr->getHost() << std::endl;
165     }
166     else {
167         std::cout <<" Direct-Pairing FAILED" << std::endl;
168     }
169
170     printMenu();
171     printPrompt();
172     fflush(NULL);
173 }
174
175 static void pairedDevListCB(PairedDevices pairedDevList)
176 {
177
178     if (0 == pairedDevList.size())
179     {
180         std::cout << "No Paired Devcie  Found" << std::endl;
181     }
182     else
183     {
184         pairedDeviceList = pairedDevList;
185         printDevices(pairedDevList);
186     }
187
188     printMenu();
189     printPrompt();
190     fflush(NULL);
191 }
192
193 static void getCallback(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
194 {
195     (void)(headerOptions);
196     try
197     {
198         if (OC_STACK_OK == eCode)
199         {
200             std::cout << "Callback Context for GET query recvd successfully" << std::endl;
201             std::cout << "Resource URI: " << rep.getUri() << std::endl;
202
203             bool state = false;
204             int power = 0;
205             rep.getValue("state", state);
206             rep.getValue("power", power);
207
208             std::cout << "\tstate: " << state << std::endl;
209             std::cout << "\tpower: " << power << std::endl;
210         }
211         else
212         {
213             std::cout << "getCallback Response error: " << eCode << std::endl;
214         }
215     }
216     catch(std::exception& e)
217     {
218         std::cout << "Exception: " << e.what() << " in onGet" << std::endl;
219     }
220 }
221
222 static bool InputPIN(std::string& pin)
223 {
224     std::cout <<"   > Enter PIN Number for authentication (ex - '00000000' [8 digit] ):" ;
225
226     std::cin >> pin;
227
228     if (pin.size() != DP_PIN_LENGTH)
229     {
230         std::cout<<"Invalid PIN"<<std::endl;
231         return false;
232     }
233
234     return true;
235 }
236
237 int main(void)
238 {
239     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
240
241     // Create PlatformConfig object
242     PlatformConfig cfg {
243         OC::ServiceType::InProc,
244             OC::ModeType::Both,
245             "0.0.0.0",
246             0,
247             OC::QualityOfService::LowQos,
248             &ps
249     };
250
251     OCPlatform::Configure(cfg);
252
253     try
254     {
255         unsigned int choice;
256         for (int out = 0; !out;)
257         {
258             if (ask)
259             {
260                 printMenu();
261                 printPrompt();
262                 fflush(NULL);
263             }
264             std::cin >> choice;
265
266             switch(choice) {
267                 case 1:
268                     {
269                         OCStackResult result = OC::OCPlatform::findDirectPairingDevices(
270                                 DP_DISCOVERY_TIMEOUT, findCallback);
271
272                         if (OC_STACK_NO_RESOURCE == result)
273                         {
274                             std::cout << "!! No Direct-Pairing Support Device found"<<std::endl;
275                             break;
276                         }
277
278                         if (OC_STACK_OK != result)
279                         {
280                             std::cout << "!!Error - findDirectPairingDevices failed."<<std::endl;
281                         }
282                         ask = 0;
283                         break;
284                     }
285                 case 2:
286                     {
287                         unsigned int pMethodIDx = -1;
288                         std::string pin("");
289
290                         std::cout << "- Negotiate DP method & Start Direct-Pairing - ";
291                         std::cout << "* List of  discovered device" << std::endl;
292                         printDevices(discoveredDeviceList);
293                         std::cout << "   > Enter Peer Device Number to initiate Direct-Pairing:" << std::endl;
294                         printPrompt();
295                         std::cin >> choice;
296                         if (choice < 1 || choice > discoveredDeviceList.size())
297                         {
298                             std::cout << "!!Device Number is incorrect, Try Again" << std::endl;
299                             break;
300                         }
301                         OCPrm_t pmSel = DP_NOT_ALLOWED;
302                         choice--;
303                         if (false == printPairingMethod(choice))
304                         {
305                             std::cout << "Target does not support the Direct-Pairing" << std::endl;
306                             break;
307                         }
308
309                         std::cout << " > Enter pairing method: "<< std::endl;
310                         printPrompt();
311                         std::cin >> pMethodIDx;
312                         auto prms = discoveredDeviceList[choice]->getPairingMethods();
313                         if (0 >= pMethodIDx || prms.size() < pMethodIDx)
314                         {
315                             std::cout <<"Invalid mode selection" << std::endl;
316                             break;
317                         }
318
319                         pmSel =  prms[pMethodIDx - 1];
320                         if (false == InputPIN(pin))
321                         {
322                             break;
323                         }
324
325                         OCStackResult result = OC::OCPlatform::doDirectPairing(discoveredDeviceList[choice], pmSel, pin, resultCallback);
326
327                         if (OC_STACK_OK != result)
328                         {
329                             std::cout << "!!Error - doDirectPairing failed." << std::endl;
330                         }
331                         ask = 0;
332                         break;
333                     }
334                 case 3:
335                     {
336                         std::cout << "- List all discovered and paired devices) -";
337                         std::cout << "  > List of discovered devices" << std::endl;
338                         printDevices(discoveredDeviceList);
339                         std::cout << std::endl;
340
341                         std::cout << "  > List of paired devices" << std::endl;
342                         OCStackResult result = OC::OCPlatform::getDirectPairedDevices(pairedDevListCB);
343                         printDevices(pairedDeviceList);
344                         std::cout << std::endl;
345
346                         if (OC_STACK_NO_RESOURCE == result)
347                         {
348                             std::cout << "!! No Paired device found"<<std::endl;
349                             break;
350                         }
351                         if (OC_STACK_OK != result)
352                         {
353                             std::cout << "!!Error - getDirectPairedDevices failed."<<std::endl;
354                         }
355                         break;
356                     }
357                 case 4:
358                     {
359                         std::cout << "- Send data(GET Request) to device(led server) -" << std::endl;
360                         printDevices(pairedDeviceList);
361                         pairedDeviceList = discoveredDeviceList;
362                         printMenu();
363                         std::cout << "Enter device number to GET data: ";
364                         std::cin >> choice;
365                         choice--;
366
367                         std::vector<std::string> ledTypes = {"core.led"};
368                         std::vector<std::string> ifaces = {DEFAULT_INTERFACE};
369
370                         OCConnectivityType ct = pairedDeviceList[choice]->getConnType();
371
372                         std::cout << "\n\n HOST address is : " << pairedDeviceList[choice]->getHost() << "\n\n";
373                         OCResource::Ptr led = OC::OCPlatform::constructResourceObject(
374                                 pairedDeviceList[choice]->getHost(),
375                                 "/a/led", ct, false, ledTypes, ifaces);
376
377                         if(!led)
378                         {
379                             std::cout << "Error: Led Object construction returned null" << std::endl;
380                             break;
381                         }
382                         OCStackResult res = led->get(QueryParamsMap(), getCallback);
383
384                         if (OC_STACK_OK != res)
385                         {
386                             std::cout << "Error: get Failed for Led" << std::endl;
387                         }
388                         break;
389                     }
390                 case 9:
391                     {
392                         out = 1;
393                         break;
394                     }
395                 default:
396                     {
397                         std::cout << GREEN_BEGIN "Wrong Option : Try Again" COLOR_END << std::endl;
398                         printMenu();
399                         printPrompt();
400                         break;
401                     }
402             }
403         }
404     }
405     catch(OCException& e)
406     {
407         oclog() << "Exception in main: "<< e.what();
408     }
409
410     return 0;
411 }