Added connectivity files for full code review
[platform/upstream/iotivity.git] / resource / csdk / connectivity / samples / arduino / casample.cpp
1 /******************************************************************
2  *
3  * Copyright 2014 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 <ctype.h>
22 #include <errno.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "cacommon.h"
29 #include "cainterface.h"
30 #include "Arduino.h"
31
32 #ifdef ETHERNET_ADAPTER
33 #include "Ethernet.h"
34 #endif
35
36 #ifdef WIFI_ADAPTER
37 #include "WiFi.h"
38 #endif
39
40 #include "oic_malloc.h"
41
42 #define MAX_BUF_LEN 100 //1024
43 #define MAX_OPT_LEN 16
44
45 static bool g_isLeSelected = false;
46
47 static void PrintMenu();
48 static void Process();
49 static void Initialize();
50 static void StartListeningServer();
51 static void StartDiscoveryServer();
52 static void FindResource();
53 static void SendRequest();
54 static void SendRequestAll();
55 static void SendResponse(CARemoteEndpoint_t *endpoint, const CAInfo_t* info);
56 static void AdvertiseResource();
57 static void SendNotification();
58 static void SelectNetwork();
59 static void UnselectNetwork();
60 static void HandleRequestResponse();
61
62 static void RequestHandler(const CARemoteEndpoint_t *object, const CARequestInfo_t *requestInfo);
63 static void ResponseHandler(const CARemoteEndpoint_t *object, const CAResponseInfo_t *responseInfo);
64 static void Terminate();
65
66 void GetData(char *readInput, size_t bufferLength, size_t *dataLength)
67 {
68     if (!readInput || bufferLength == 0 || !dataLength)
69     {
70         Serial.println("Invalid buffer");
71         return;
72     }
73
74     while (!Serial.available())
75     {
76         delay(500);
77     }
78     int len = 0;
79     while (Serial.available())
80     {
81         delay(100);
82         char c = Serial.read();
83         if ('\n' != c && '\r' != c && len < bufferLength - 1)
84         {
85             readInput[len++] = c;
86         }
87         else
88         {
89             break;
90         }
91     }
92
93     readInput[len] = '\0';
94     Serial.flush();
95     Serial.print("PD:");
96     Serial.println(readInput);
97     (*dataLength) = len;
98 }
99
100 CAConnectivityType_t GetConnectivityType()
101 {
102     char type[2] = {0};
103     Serial.println("Select network");
104     Serial.println("ETHERNET: 0");
105     Serial.println("WIFI: 1");
106     Serial.println("EDR: 2");
107     Serial.println("LE: 3");
108
109     size_t typeLen = 0;
110     GetData(type, sizeof(type), &typeLen);
111     if (0 >= typeLen)
112     {
113         Serial.println("i/p err,default ethernet");
114         return CA_ETHERNET;
115     }
116     switch (type[0])
117     {
118         case '0':
119             return CA_ETHERNET;
120         case '1':
121             return CA_WIFI;
122         case '2':
123             return CA_EDR;
124         case '3':
125             return CA_LE;
126     }
127     return CA_ETHERNET;
128 }
129
130 void setup()
131 {
132     Serial.begin (115200);
133
134     Serial.println("============");
135     Serial.println("CA SAMPLE");
136     Serial.println("============");
137     PrintMenu();
138 }
139
140 void loop()
141 {
142     char buffer[5] = {0};
143     size_t len;
144     if (Serial.available() > 0)
145     {
146         GetData(buffer, sizeof(buffer), &len);
147         if (0 >= len)
148         {
149             Serial.println("i/p err");
150             return;
151         }
152         switch (toupper(buffer[0]))
153         {
154             case 'M': // menu
155                 PrintMenu();
156                 break;
157
158             case 'Q': // quit
159                 Serial.println("quit");
160                 return;
161
162             case 'I': // Initialize interface
163                 Initialize();
164                 break;
165
166             case 'S': // start listening server
167                 StartListeningServer();
168                 break;
169
170             case 'D': // start discovery server
171                 StartDiscoveryServer();
172                 break;
173
174             case 'F': // find resource
175                 FindResource();
176                 break;
177
178             case 'R': // send request
179                 SendRequest();
180                 break;
181             case 'E': //send request to all
182                 SendRequestAll();
183                 break;
184             case 'A': // advertise resource
185                 AdvertiseResource();
186                 break;
187
188             case 'B': // send notification
189                 SendNotification();
190                 break;
191
192             case 'N': // select network
193                 SelectNetwork();
194                 break;
195
196             case 'X': // unselect network
197                 UnselectNetwork();
198                 break;
199
200             case 'H': // handle request response
201                 HandleRequestResponse();
202                 break;
203
204             case 'T': // handle request response
205                 Terminate();
206                 break;
207
208             default:
209                 Serial.println("wrong menu");
210                 break;
211         }
212     }
213     //1:Add check for startserver before calling below api
214     if (g_isLeSelected)
215     {
216         HandleRequestResponse();
217     }
218     delay(1000);
219 }
220
221 void Initialize()
222 {
223     if(CAInitialize() != CA_STATUS_OK)
224     {
225         Serial.println("Initialize failed");
226         return;
227     }
228     SelectNetwork();
229     // set handler.
230     CARegisterHandler(RequestHandler, ResponseHandler);
231 }
232
233 void StartListeningServer()
234 {
235     Serial.println("listening server");
236     CAResult_t ret = CAStartListeningServer();
237     if(ret != CA_STATUS_OK)
238     {
239         Serial.print("listening failed: ");
240         Serial.println(ret);
241         return;
242     }
243 }
244
245 void StartDiscoveryServer()
246 {
247     Serial.println("discovery server");
248     CAResult_t ret = CAStartDiscoveryServer();
249     if(ret != CA_STATUS_OK)
250     {
251         Serial.print("discovery failed: ");
252         Serial.println(ret);
253         return;
254     }
255 }
256
257 void FindResource()
258 {
259     char buf[MAX_BUF_LEN] = {0};
260     Serial.println("============");
261     Serial.println("ex) /a/light");
262     Serial.println("uri: ");
263     size_t len = 0;
264     GetData(buf, sizeof(buf), &len);
265     if (0 >= len)
266     {
267         Serial.println("i/p err");
268         return;
269     }
270     // create token
271     CAToken_t token = NULL;
272     CAResult_t res = CAGenerateToken(&token);
273     if (res != CA_STATUS_OK || token == NULL)
274     {
275         Serial.println("token error");
276         return;
277     }
278
279     Serial.print("token:");
280     Serial.println(token);
281
282     res = CAFindResource(buf, token);
283     if (res != CA_STATUS_OK)
284     {
285         Serial.print("find error: ");
286         Serial.println(res);
287     }
288     else
289     {
290         Serial.println("success: ");
291         Serial.println(buf);
292     }
293     CADestroyToken(token);
294 }
295
296 void SendRequest()
297 {
298     char buf[MAX_BUF_LEN] = {0};
299     CAConnectivityType_t selectedNetwork;
300     selectedNetwork = GetConnectivityType();
301
302     Serial.println("============");
303     Serial.println("10.11.12.13:4545/res_uri (for IP)");
304     Serial.println("10:11:12:13:45:45/res_uri (for BT)");
305     Serial.println("uri: ");
306
307     size_t len = 0;
308     GetData(buf, sizeof(buf), &len);
309     if (0 >= len)
310     {
311         Serial.println("i/p err");
312         return;
313     }
314
315     // create remote endpoint
316     CARemoteEndpoint_t *endpoint = NULL;
317     CAResult_t res = CACreateRemoteEndpoint(buf,selectedNetwork,&endpoint);
318     if (res != CA_STATUS_OK)
319     {
320         Serial.println("Out of memory");
321         CADestroyRemoteEndpoint(endpoint);
322         return;
323     }
324
325     memset(buf, 0, sizeof(buf));
326
327     Serial.println("\n=============================================\n");
328     Serial.println("0:CON, 1:NON\n");
329     Serial.println("select message type : ");
330     GetData(buf, sizeof(buf), &len);
331     CAMessageType_t msgType = CA_MSG_CONFIRM;
332
333     if (0 >= len)
334     {
335         Serial.println("i/p err,default: 0");
336     }
337     else if(buf[0] == '1')
338     {
339         msgType = CA_MSG_NONCONFIRM;
340     }
341
342     // create token
343     CAToken_t token = NULL;
344     res = CAGenerateToken(&token);
345     if (res != CA_STATUS_OK)
346     {
347         Serial.println("token error");
348         token = NULL;
349         return;
350     }
351
352     Serial.println((token != NULL) ? token : "");
353     CAInfo_t requestData = {CA_MSG_RESET};
354     requestData.token = token;
355     requestData.payload = (CAPayload_t)"Json Payload";
356
357     requestData.type = msgType;
358
359     CARequestInfo_t requestInfo = {CA_GET, {CA_MSG_RESET}};
360     requestInfo.method = CA_GET;
361     requestInfo.info = requestData;
362
363     // send request
364     CASendRequest(endpoint, &requestInfo);
365     if (token != NULL)
366     {
367         CADestroyToken(token);
368     }
369
370     // destroy remote endpoint
371     if (endpoint != NULL)
372     {
373         CADestroyRemoteEndpoint(endpoint);
374     }
375
376     Serial.println("============");
377 }
378
379 void SendRequestAll()
380 {
381     char buf[MAX_BUF_LEN] = {0};
382
383     CAConnectivityType_t selectedNetwork;
384     selectedNetwork = GetConnectivityType();
385
386     Serial.println("=========");
387     Serial.println("10.11.12.13:4545/resource_uri ( for IP )");
388     Serial.println("10:11:12:13:45:45/resource_uri ( for BT )");
389     Serial.println("uri : ");
390
391     size_t len = 0;
392     GetData(buf, sizeof(buf), &len);
393     if (0 >= len)
394     {
395         Serial.println("i/p err");
396         return;
397     }
398
399     // create remote endpoint
400     CARemoteEndpoint_t *endpoint = NULL;
401     CAResult_t res = CACreateRemoteEndpoint(buf, selectedNetwork, &endpoint);
402
403     if (res != CA_STATUS_OK)
404     {
405         Serial.println("create remote endpoint error");
406         CADestroyRemoteEndpoint(endpoint);
407         return;
408     }
409
410     CAGroupEndpoint_t *group = NULL;
411     group = (CAGroupEndpoint_t *)OICMalloc(sizeof(CAGroupEndpoint_t));
412     group->connectivityType = endpoint->connectivityType;
413     group->resourceUri = endpoint->resourceUri;
414
415     // create token
416     CAToken_t token = NULL;
417     res = CAGenerateToken(&token);
418     if (res != CA_STATUS_OK)
419     {
420         Serial.println("token error");
421         token = NULL;
422         return;
423     }
424
425     Serial.println((token != NULL) ? token : "");
426
427     CAInfo_t requestData = {CA_MSG_RESET};
428     requestData.token = token;
429     requestData.payload = "Temp Json Payload";
430     requestData.type = CA_MSG_NONCONFIRM;
431
432     CARequestInfo_t requestInfo = {CA_GET, {CA_MSG_RESET}};
433     requestInfo.method = CA_GET;
434     requestInfo.info = requestData;
435
436     // send request
437     // CASendRequest(endpoint, &requestInfo);
438     CASendRequestToAll(group, &requestInfo);
439
440     if (token != NULL)
441     {
442         CADestroyToken(token);
443     }
444
445     // destroy remote endpoint
446     if (endpoint != NULL)
447     {
448         CADestroyRemoteEndpoint(endpoint);
449     }
450
451     OICFree(group);
452     Serial.println("==========");
453 }
454
455 void AdvertiseResource()
456 {
457     char buf[MAX_BUF_LEN] = {0};
458
459     Serial.println("============");
460     Serial.println("uri: ");
461
462     size_t len = 0;
463     GetData(buf, sizeof(buf), &len);
464     if (0 >= len)
465     {
466         Serial.println("no i/p");
467         return;
468     }
469
470     int16_t optionNum = 0;
471     char optionData[MAX_OPT_LEN] = {0};
472     char optionNumBuf[2] = {0};
473
474     Serial.println("Option Num: ");
475     GetData(optionNumBuf, sizeof(optionNumBuf), &len);
476     if (0 >= len)
477     {
478         Serial.println("no i/p,0 option");
479     }
480     else
481     {
482         optionNum = atoi(optionNumBuf);
483         Serial.println(optionNum);
484     }
485
486     CAHeaderOption_t *headerOpt = NULL;
487     if (optionNum > 0)
488     {
489         headerOpt = (CAHeaderOption_t *) OICCalloc(optionNum, sizeof(CAHeaderOption_t));
490         if (NULL == headerOpt)
491         {
492             Serial.println("Out of memory");
493             return;
494         }
495     }
496
497     int i;
498     for (i = 0 ; i < optionNum ; i++)
499     {
500         int optionID = 0;
501         char getOptionID[4];
502         Serial.println("Opt ID:");
503         GetData(getOptionID, sizeof(getOptionID), &len);
504         if (0 >= len)
505         {
506             Serial.println("no i/p");
507             continue;
508         }
509         else
510         {
511             optionID = atoi(getOptionID);
512         }
513
514         memset(optionData, 0, sizeof(optionData));
515         Serial.println("Opt Data:");
516         GetData(optionData, sizeof(optionData), &len);
517         if (0 >= len)
518         {
519             Serial.println("no i/p");
520             continue;
521         }
522
523         headerOpt[i].optionID = optionID;
524         memcpy(headerOpt[i].optionData, optionData, strlen(optionData));
525         Serial.println("ID:");
526         Serial.println(optionID);
527         Serial.println("Data:");
528         Serial.println(optionData);
529
530         headerOpt[i].optionLength = (uint16_t)strlen(optionData);
531     }
532
533     Serial.println("============");
534     // create token
535     CAToken_t token = NULL;
536     CAResult_t res = CAGenerateToken(&token);
537     if (res != CA_STATUS_OK)
538     {
539         Serial.println("token error");
540         token = NULL;
541         return;
542     }
543
544     Serial.println("token");
545     Serial.println((token != NULL) ? token : "");
546
547     CAAdvertiseResource(buf, token, headerOpt, (uint8_t)optionNum);
548     OICFree(headerOpt);
549     CADestroyToken(token);
550 }
551
552 void SendNotification()
553 {
554     char buf[MAX_BUF_LEN] = {0};
555     CAConnectivityType_t selectedNetwork;
556     selectedNetwork = GetConnectivityType();
557
558     Serial.println("============");
559     Serial.println("10.11.12.13:4545/res_uri (for IP)");
560     Serial.println("10:11:12:13:45:45/res_uri (for BT)");
561     Serial.println("uri: ");
562
563     size_t len = 0;
564     GetData(buf, sizeof(buf), &len);
565     if (0 >= len)
566     {
567         Serial.println("i/p err");
568         return;
569     }
570
571     // create remote endpoint
572     CARemoteEndpoint_t *endpoint = NULL;
573     CAResult_t res = CACreateRemoteEndpoint(buf,selectedNetwork,&endpoint);
574     if (CA_STATUS_OK != res)
575     {
576         Serial.println("Out of memory");
577         CADestroyRemoteEndpoint(endpoint);
578         return;
579     }
580
581     CAInfo_t respondeData = {CA_MSG_RESET};
582     respondeData.token = (CAToken_t)"token";
583     respondeData.payload = (CAPayload_t)"Notification Data";
584
585     CAResponseInfo_t responseInfo = {CA_BAD_REQ, {CA_MSG_RESET}};
586     responseInfo.result = CA_SUCCESS;
587     responseInfo.info = respondeData;
588
589     // send request
590     CASendNotification(endpoint, &responseInfo);
591     // destroy remote endpoint
592     if (NULL != endpoint)
593     {
594         CADestroyRemoteEndpoint(endpoint);
595     }
596     Serial.println("============");
597 }
598
599 void SelectNetwork()
600 {
601     char buf[MAX_BUF_LEN] = {0};
602
603     Serial.println("============");
604     Serial.println("Select network");
605     Serial.println("ETHERNET: 0");
606     Serial.println("WIFI: 1");
607     Serial.println("EDR: 2");
608     Serial.println("LE: 3\n");
609
610     size_t len = 0;
611     GetData(buf, sizeof(buf), &len);
612     int number = buf[0] - '0';
613     if (0 >= len || number < 0 || number > 3)
614     {
615         Serial.println("Wrong i/p. WIFI selected");
616         number = 1;
617     }
618
619     switch (number)
620     {
621         case 0:
622             {
623 #ifdef ETHERNET_ADAPTER
624                 // Note: ****Update the MAC address here with your shield's MAC address****
625                 uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0E, 0xC4, 0x05};
626                 uint8_t error = Ethernet.begin(ETHERNET_MAC);
627                 if (error  == 0)
628                 {
629                     Serial.print("Failed: ");
630                     Serial.println(error);
631                     return;
632                 }
633 #endif
634             }
635             break;
636         case 1:
637             {
638 #ifdef WIFI_ADAPTER
639                 const char ssid[] = "SSID";              // your network SSID (name)
640                 const char pass[] = "SSID_Password";     // your network password
641                 int16_t status = WL_IDLE_STATUS;         // the Wifi radio's status
642
643                 if (WiFi.status() == WL_NO_SHIELD)
644                 {
645                     Serial.println("ERROR:No Shield");
646                     return;
647                 }
648
649                 while (status != WL_CONNECTED)
650                 {
651                     Serial.print("connecting: ");
652                     Serial.println(ssid);
653                     // WiFi.begin api is weird. ssid should also be taken as const char *
654                     // Connect to WPA/WPA2 network:
655                     status = WiFi.begin((char *)ssid, pass);
656                 }
657 #endif
658             }
659             break;
660         case 2:
661             // Nothing TBD here
662             break;
663         case 3:
664             g_isLeSelected = true;
665             break;
666     }
667
668     CASelectNetwork(CAConnectivityType_t(1<<number));
669     Serial.println("============");
670 }
671
672 void UnselectNetwork()
673 {
674     char buf[MAX_BUF_LEN] = {0};
675
676     Serial.println("============");
677     Serial.println("Unselect network");
678     Serial.println("ETHERNET: 0");
679     Serial.println("WIFI: 1");
680     Serial.println("EDR: 2");
681     Serial.println("LE: 3\n");
682
683     size_t len = 0;
684     GetData(buf, sizeof(buf), &len);
685     int number = buf[0] - '0';
686     Serial.println(number);
687     if (0 >= len || number < 0 || number > 3)
688     {
689         Serial.println("Wrong i/p. WIFI selected");
690         number = 1;
691     }
692     if (number == 3)
693     {
694         g_isLeSelected = false;
695     }
696     CAUnSelectNetwork(1 << number);
697     Serial.println("Terminate");
698     CATerminate();
699     Serial.println("============");
700 }
701
702 void PrintMenu()
703 {
704
705     Serial.println("============");
706     Serial.println("i: Initialize");
707     Serial.println("s: start listening server");
708     Serial.println("d: start discovery server");
709     Serial.println("f: find resource");
710     Serial.println("r: send request");
711     Serial.println("e: send request to all");
712     Serial.println("a: advertise resource");
713     Serial.println("b: send notification");
714     Serial.println("n: select network");
715     Serial.println("x: unselect network");
716     Serial.println("h: handle request response");
717     Serial.println("t: terminate");
718     Serial.println("q: quit");
719     Serial.println("============");
720 }
721
722 void HandleRequestResponse()
723 {
724     CAHandleRequestResponse();
725 }
726
727 void RequestHandler(const CARemoteEndpoint_t *object, const CARequestInfo_t *requestInfo)
728 {
729     if (!object)
730     {
731         Serial.println("Remote endpoint is NULL!");
732         return;
733     }
734
735     if (!requestInfo)
736     {
737         Serial.println("Request info is NULL!");
738         return;
739     }
740
741     Serial.println("uri: ");
742     Serial.println(object->resourceUri);
743     Serial.println("RAddr: ");
744     Serial.println(object->addressInfo.IP.ipAddress);
745     Serial.println("Port: ");
746     Serial.println(object->addressInfo.IP.port);
747     Serial.println("data: ");
748     Serial.println(requestInfo->info.payload);
749     Serial.println("Type: ");
750     Serial.println(requestInfo->info.type);
751
752     if (requestInfo->info.options)
753     {
754         uint32_t len = requestInfo->info.numOptions;
755         uint32_t i;
756         for (i = 0; i < len; i++)
757         {
758             Serial.println("Option:");
759             Serial.println(i+1);
760             Serial.println("ID:");
761             Serial.println(requestInfo->info.options[i].optionID);
762             Serial.println("Data:");
763             Serial.println((char*)requestInfo->info.options[i].optionData);
764         }
765     }
766     Serial.println("send response");
767     SendResponse((CARemoteEndpoint_t *)object, (requestInfo != NULL) ? &requestInfo->info : NULL);
768 }
769
770 void ResponseHandler(const CARemoteEndpoint_t *object, const CAResponseInfo_t *responseInfo)
771 {
772     if (object && object->resourceUri)
773     {
774         Serial.print("uri: ");
775         Serial.println(object->resourceUri);
776     }
777
778     if (responseInfo)
779     {
780         Serial.print("data: ");
781         Serial.println(responseInfo->info.payload);
782         Serial.print("Type: ");
783         Serial.println(responseInfo->info.type);
784         Serial.print("res result=");
785         Serial.println(responseInfo->result);
786     }
787 }
788
789 void SendResponse(CARemoteEndpoint_t *endpoint, const CAInfo_t* info)
790 {
791     Serial.println("============");
792     CAInfo_t responseData = {CA_MSG_RESET};
793     if(info && info->type == CA_MSG_CONFIRM)
794     {
795         responseData.type = CA_MSG_ACKNOWLEDGE;
796     }
797     else
798     {
799         responseData.type = CA_MSG_NONCONFIRM;
800     }
801
802     responseData.messageId = (info != NULL) ? info->messageId : 0;
803     responseData.token = (info != NULL) ? (CAToken_t)info->token : (CAToken_t)"";
804     responseData.payload = (CAPayload_t)"response payload";
805
806     CAResponseInfo_t responseInfo = {CA_BAD_REQ, {CA_MSG_RESET}};
807     responseInfo.result = (CAResponseResult_t)203;
808     responseInfo.info = responseData;
809
810     // send request (connectivityType from remoteEndpoint of request Info)
811     CAResult_t res = CASendResponse(endpoint, &responseInfo);
812     if(res != CA_STATUS_OK)
813     {
814         Serial.println("Snd Resp error");
815     }
816     else
817     {
818         Serial.println("Snd Resp success");
819     }
820
821     Serial.println("============");
822 }
823
824 void Terminate()
825 {
826     UnselectNetwork();
827 }
828