Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / arduino / SimpleClientServer / ocserver / ocserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH 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 // Do not remove the include below
22 #include "Arduino.h"
23
24 #include "logger.h"
25 #include "ocstack.h"
26 #include "ocpayload.h"
27 #include <string.h>
28
29 #ifdef ARDUINOWIFI
30 // Arduino WiFi Shield
31 #include <SPI.h>
32 #include <WiFi.h>
33 #include <WiFiUdp.h>
34 #else
35 // Arduino Ethernet Shield
36 #include <EthernetServer.h>
37 #include <Ethernet.h>
38 #include <Dns.h>
39 #include <EthernetClient.h>
40 #include <util.h>
41 #include <EthernetUdp.h>
42 #include <Dhcp.h>
43 #endif
44
45 const char *getResult(OCStackResult result);
46
47 #define TAG "ArduinoServer"
48
49 int gLightUnderObservation = 0;
50 void createLightResource();
51
52 /* Structure to represent a Light resource */
53 typedef struct LIGHTRESOURCE{
54     OCResourceHandle handle;
55     bool state;
56     int power;
57 } LightResource;
58
59 static LightResource Light;
60
61 #ifdef ARDUINOWIFI
62 // Arduino WiFi Shield
63 // Note : Arduino WiFi Shield currently does NOT support multicast and therefore
64 // this server will NOT be listening on 224.0.1.187 multicast address.
65
66 static const char ARDUINO_WIFI_SHIELD_UDP_FW_VER[] = "1.1.0";
67
68 /// WiFi Shield firmware with Intel patches
69 static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0";
70
71 /// WiFi network info and credentials
72 char ssid[] = "mDNSAP";
73 char pass[] = "letmein9";
74
75 int ConnectToNetwork()
76 {
77     char *fwVersion;
78     int status = WL_IDLE_STATUS;
79     // check for the presence of the shield:
80     if (WiFi.status() == WL_NO_SHIELD)
81     {
82         OC_LOG(ERROR, TAG, ("WiFi shield not present"));
83         return -1;
84     }
85
86     // Verify that WiFi Shield is running the firmware with all UDP fixes
87     fwVersion = WiFi.firmwareVersion();
88     OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
89     if ( strncmp(fwVersion, ARDUINO_WIFI_SHIELD_UDP_FW_VER, sizeof(ARDUINO_WIFI_SHIELD_UDP_FW_VER)) !=0 )
90     {
91         OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
92         return -1;
93     }
94
95     // attempt to connect to Wifi network:
96     while (status != WL_CONNECTED)
97     {
98         OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid);
99         status = WiFi.begin(ssid,pass);
100
101         // wait 10 seconds for connection:
102         delay(10000);
103     }
104     OC_LOG(DEBUG, TAG, ("Connected to wifi"));
105
106     IPAddress ip = WiFi.localIP();
107     OC_LOG_V(INFO, TAG, "IP Address:  %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
108     return 0;
109 }
110 #else
111 // Arduino Ethernet Shield
112 int ConnectToNetwork()
113 {
114     // Note: ****Update the MAC address here with your shield's MAC address****
115     uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0E, 0xC4, 0x05};
116     uint8_t error = Ethernet.begin(ETHERNET_MAC);
117     if (error  == 0)
118     {
119         OC_LOG_V(ERROR, TAG, "error is: %d", error);
120         return -1;
121     }
122
123     IPAddress ip = Ethernet.localIP();
124     OC_LOG_V(INFO, TAG, "IP Address:  %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
125     return 0;
126 }
127 #endif //ARDUINOWIFI
128
129 // On Arduino Atmel boards with Harvard memory architecture, the stack grows
130 // downwards from the top and the heap grows upwards. This method will print
131 // the distance(in terms of bytes) between those two.
132 // See here for more details :
133 // http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
134 void PrintArduinoMemoryStats()
135 {
136     #ifdef ARDUINO_AVR_MEGA2560
137     //This var is declared in avr-libc/stdlib/malloc.c
138     //It keeps the largest address not allocated for heap
139     extern char *__brkval;
140     //address of tmp gives us the current stack boundry
141     int tmp;
142     OC_LOG_V(INFO, TAG, "Stack: %u         Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
143     OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
144             ((unsigned int)&tmp - (unsigned int)__brkval));
145     #endif
146 }
147
148 // This is the entity handler for the registered resource.
149 // This is invoked by OCStack whenever it recevies a request for this resource.
150 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest,
151                                         void *callbackParam)
152 {
153     OCEntityHandlerResult ehRet = OC_EH_OK;
154     OCEntityHandlerResponse response = {0};
155     OCRepPayload* payload = OCRepPayloadCreate();
156     if(!payload)
157     {
158         OC_LOG(ERROR, TAG, ("Failed to allocate Payload"));
159         return OC_EH_ERROR;
160     }
161
162     if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
163     {
164         OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
165
166         if(OC_REST_GET == entityHandlerRequest->method)
167         {
168             OCRepPayloadSetUri(payload, "/a/light");
169             OCRepPayloadSetPropBool(payload, "state", true);
170             OCRepPayloadSetPropInt(payload, "power", 10);
171         }
172         else if(OC_REST_PUT == entityHandlerRequest->method)
173         {
174             //Do something with the 'put' payload
175             OCRepPayloadSetUri(payload, "/a/light");
176             OCRepPayloadSetPropBool(payload, "state", false);
177             OCRepPayloadSetPropInt(payload, "power", 0);
178         }
179
180         if (ehRet == OC_EH_OK)
181         {
182             // Format the response.  Note this requires some info about the request
183             response.requestHandle = entityHandlerRequest->requestHandle;
184             response.resourceHandle = entityHandlerRequest->resource;
185             response.ehResult = ehRet;
186             response.payload = (OCPayload*) payload;
187             response.numSendVendorSpecificHeaderOptions = 0;
188             memset(response.sendVendorSpecificHeaderOptions, 0,
189                     sizeof response.sendVendorSpecificHeaderOptions);
190             memset(response.resourceUri, 0, sizeof response.resourceUri);
191             // Indicate that response is NOT in a persistent buffer
192             response.persistentBufferFlag = 0;
193
194             // Send the response
195             if (OCDoResponse(&response) != OC_STACK_OK)
196             {
197                 OC_LOG(ERROR, TAG, "Error sending response");
198                 ehRet = OC_EH_ERROR;
199             }
200         }
201     }
202     if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
203     {
204         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
205         {
206             OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
207             gLightUnderObservation = 1;
208         }
209         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
210         {
211             OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
212             gLightUnderObservation = 0;
213         }
214     }
215     OCRepPayloadDestroy(payload);
216     return ehRet;
217 }
218
219 // This method is used to display 'Observe' functionality of OC Stack.
220 static uint8_t modCounter = 0;
221 void *ChangeLightRepresentation (void *param)
222 {
223     (void)param;
224     OCStackResult result = OC_STACK_ERROR;
225     modCounter += 1;
226     // Matching the timing that the Linux Sample Server App uses for the same functionality.
227     if(modCounter % 10 == 0)
228     {
229         Light.power += 5;
230         if (gLightUnderObservation)
231         {
232             OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
233             result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
234             if (OC_STACK_NO_OBSERVERS == result)
235             {
236                 gLightUnderObservation = 0;
237             }
238         }
239     }
240     return NULL;
241 }
242
243 //The setup function is called once at startup of the sketch
244 void setup()
245 {
246     // Add your initialization code here
247     // Note : This will initialize Serial port on Arduino at 115200 bauds
248     OC_LOG_INIT();
249     OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
250
251     // Connect to Ethernet or WiFi network
252     if (ConnectToNetwork() != 0)
253     {
254         OC_LOG(ERROR, TAG, ("Unable to connect to network"));
255         return;
256     }
257
258     // Initialize the OC Stack in Server mode
259     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
260     {
261         OC_LOG(ERROR, TAG, ("OCStack init error"));
262         return;
263     }
264
265     // Declare and create the example resource: Light
266     createLightResource();
267 }
268
269 // The loop function is called in an endless loop
270 void loop()
271 {
272     // This artificial delay is kept here to avoid endless spinning
273     // of Arduino microcontroller. Modify it as per specific application needs.
274     delay(2000);
275
276     // This call displays the amount of free SRAM available on Arduino
277     PrintArduinoMemoryStats();
278
279     // Give CPU cycles to OCStack to perform send/recv and other OCStack stuff
280     if (OCProcess() != OC_STACK_OK)
281     {
282         OC_LOG(ERROR, TAG, ("OCStack process error"));
283         return;
284     }
285     ChangeLightRepresentation(NULL);
286 }
287
288 void createLightResource()
289 {
290     Light.state = false;
291     OCStackResult res = OCCreateResource(&Light.handle,
292             "core.light",
293             OC_RSRVD_INTERFACE_DEFAULT,
294             "/a/light",
295             OCEntityHandlerCb,
296             NULL,
297             OC_DISCOVERABLE|OC_OBSERVABLE);
298     OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
299 }
300
301 const char *getResult(OCStackResult result) {
302     switch (result) {
303     case OC_STACK_OK:
304         return "OC_STACK_OK";
305     case OC_STACK_INVALID_URI:
306         return "OC_STACK_INVALID_URI";
307     case OC_STACK_INVALID_QUERY:
308         return "OC_STACK_INVALID_QUERY";
309     case OC_STACK_INVALID_IP:
310         return "OC_STACK_INVALID_IP";
311     case OC_STACK_INVALID_PORT:
312         return "OC_STACK_INVALID_PORT";
313     case OC_STACK_INVALID_CALLBACK:
314         return "OC_STACK_INVALID_CALLBACK";
315     case OC_STACK_INVALID_METHOD:
316         return "OC_STACK_INVALID_METHOD";
317     case OC_STACK_NO_MEMORY:
318         return "OC_STACK_NO_MEMORY";
319     case OC_STACK_COMM_ERROR:
320         return "OC_STACK_COMM_ERROR";
321     case OC_STACK_INVALID_PARAM:
322         return "OC_STACK_INVALID_PARAM";
323     case OC_STACK_NOTIMPL:
324         return "OC_STACK_NOTIMPL";
325     case OC_STACK_NO_RESOURCE:
326         return "OC_STACK_NO_RESOURCE";
327     case OC_STACK_RESOURCE_ERROR:
328         return "OC_STACK_RESOURCE_ERROR";
329     case OC_STACK_SLOW_RESOURCE:
330         return "OC_STACK_SLOW_RESOURCE";
331     case OC_STACK_NO_OBSERVERS:
332         return "OC_STACK_NO_OBSERVERS";
333     case OC_STACK_ERROR:
334         return "OC_STACK_ERROR";
335     default:
336         return "UNKNOWN";
337     }
338 }
339