1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Do not remove the include below
26 #include "ocpayload.h"
30 // Arduino WiFi Shield
35 // Arduino Ethernet Shield
36 #include <EthernetServer.h>
39 #include <EthernetClient.h>
41 #include <EthernetUdp.h>
45 const char *getResult(OCStackResult result);
47 #define TAG "ArduinoServer"
49 int gLightUnderObservation = 0;
50 void createLightResource();
52 /* Structure to represent a Light resource */
53 typedef struct LIGHTRESOURCE{
54 OCResourceHandle handle;
59 static LightResource Light;
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.
66 static const char ARDUINO_WIFI_SHIELD_UDP_FW_VER[] = "1.1.0";
68 /// WiFi Shield firmware with Intel patches
69 static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0";
71 /// WiFi network info and credentials
72 char ssid[] = "mDNSAP";
73 char pass[] = "letmein9";
75 int ConnectToNetwork()
78 int status = WL_IDLE_STATUS;
79 // check for the presence of the shield:
80 if (WiFi.status() == WL_NO_SHIELD)
82 OC_LOG(ERROR, TAG, ("WiFi shield not present"));
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 )
91 OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
95 // attempt to connect to Wifi network:
96 while (status != WL_CONNECTED)
98 OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid);
99 status = WiFi.begin(ssid,pass);
101 // wait 10 seconds for connection:
104 OC_LOG(DEBUG, TAG, ("Connected to wifi"));
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]);
111 // Arduino Ethernet Shield
112 int ConnectToNetwork()
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);
119 OC_LOG_V(ERROR, TAG, "error is: %d", error);
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]);
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()
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
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));
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,
153 OCEntityHandlerResult ehRet = OC_EH_OK;
154 OCEntityHandlerResponse response = {0};
155 OCRepPayload* payload = OCRepPayloadCreate();
158 OC_LOG(ERROR, TAG, ("Failed to allocate Payload"));
162 if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
164 OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
166 if(OC_REST_GET == entityHandlerRequest->method)
168 OCRepPayloadSetUri(payload, "/a/light");
169 OCRepPayloadSetPropBool(payload, "state", true);
170 OCRepPayloadSetPropInt(payload, "power", 10);
172 else if(OC_REST_PUT == entityHandlerRequest->method)
174 //Do something with the 'put' payload
175 OCRepPayloadSetUri(payload, "/a/light");
176 OCRepPayloadSetPropBool(payload, "state", false);
177 OCRepPayloadSetPropInt(payload, "power", 0);
180 if (ehRet == OC_EH_OK)
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;
195 if (OCDoResponse(&response) != OC_STACK_OK)
197 OC_LOG(ERROR, TAG, "Error sending response");
202 if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
204 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
206 OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
207 gLightUnderObservation = 1;
209 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
211 OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
212 gLightUnderObservation = 0;
215 OCRepPayloadDestroy(payload);
219 // This method is used to display 'Observe' functionality of OC Stack.
220 static uint8_t modCounter = 0;
221 void *ChangeLightRepresentation (void *param)
224 OCStackResult result = OC_STACK_ERROR;
226 // Matching the timing that the Linux Sample Server App uses for the same functionality.
227 if(modCounter % 10 == 0)
230 if (gLightUnderObservation)
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)
236 gLightUnderObservation = 0;
243 //The setup function is called once at startup of the sketch
246 // Add your initialization code here
247 // Note : This will initialize Serial port on Arduino at 115200 bauds
249 OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
251 // Connect to Ethernet or WiFi network
252 if (ConnectToNetwork() != 0)
254 OC_LOG(ERROR, TAG, ("Unable to connect to network"));
258 // Initialize the OC Stack in Server mode
259 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
261 OC_LOG(ERROR, TAG, ("OCStack init error"));
265 // Declare and create the example resource: Light
266 createLightResource();
269 // The loop function is called in an endless loop
272 // This artificial delay is kept here to avoid endless spinning
273 // of Arduino microcontroller. Modify it as per specific application needs.
276 // This call displays the amount of free SRAM available on Arduino
277 PrintArduinoMemoryStats();
279 // Give CPU cycles to OCStack to perform send/recv and other OCStack stuff
280 if (OCProcess() != OC_STACK_OK)
282 OC_LOG(ERROR, TAG, ("OCStack process error"));
285 ChangeLightRepresentation(NULL);
288 void createLightResource()
291 OCStackResult res = OCCreateResource(&Light.handle,
293 OC_RSRVD_INTERFACE_DEFAULT,
297 OC_DISCOVERABLE|OC_OBSERVABLE);
298 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
301 const char *getResult(OCStackResult result) {
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";
334 return "OC_STACK_ERROR";