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