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