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
29 // Arduino WiFi Shield
34 // Arduino Ethernet Shield
35 #include <EthernetServer.h>
38 #include <EthernetClient.h>
40 #include <EthernetUdp.h>
44 const char *getResult(OCStackResult result);
46 PROGMEM const char TAG[] = "ArduinoServer";
48 int gLightUnderObservation = 0;
49 void createLightResource();
51 /* Structure to represent a Light resource */
52 typedef struct LIGHTRESOURCE{
53 OCResourceHandle handle;
58 static LightResource Light;
60 static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":true,\"power\":10}}";
61 static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":false,\"power\":0}}";
64 // Arduino WiFi Shield
65 // Note : Arduino WiFi Shield currently does NOT support multicast and therefore
66 // this server will NOT be listening on 224.0.1.187 multicast address.
68 static const char ARDUINO_WIFI_SHIELD_UDP_FW_VER[] = "1.1.0";
70 /// WiFi Shield firmware with Intel patches
71 static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0";
73 /// WiFi network info and credentials
74 char ssid[] = "mDNSAP";
75 char pass[] = "letmein9";
77 int ConnectToNetwork()
80 int status = WL_IDLE_STATUS;
81 // check for the presence of the shield:
82 if (WiFi.status() == WL_NO_SHIELD)
84 OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
88 // Verify that WiFi Shield is running the firmware with all UDP fixes
89 fwVersion = WiFi.firmwareVersion();
90 OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
91 if ( strncmp(fwVersion, ARDUINO_WIFI_SHIELD_UDP_FW_VER, sizeof(ARDUINO_WIFI_SHIELD_UDP_FW_VER)) !=0 )
93 OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
97 // attempt to connect to Wifi network:
98 while (status != WL_CONNECTED)
100 OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid);
101 status = WiFi.begin(ssid,pass);
103 // wait 10 seconds for connection:
106 OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
108 IPAddress ip = WiFi.localIP();
109 OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
113 // Arduino Ethernet Shield
114 int ConnectToNetwork()
116 // Note: ****Update the MAC address here with your shield's MAC address****
117 uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0E, 0xC4, 0x05};
118 uint8_t error = Ethernet.begin(ETHERNET_MAC);
121 OC_LOG_V(ERROR, TAG, "error is: %d", error);
125 IPAddress ip = Ethernet.localIP();
126 OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
131 // On Arduino Atmel boards with Harvard memory architecture, the stack grows
132 // downwards from the top and the heap grows upwards. This method will print
133 // the distance(in terms of bytes) between those two.
134 // See here for more details :
135 // http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
136 void PrintArduinoMemoryStats()
138 #ifdef ARDUINO_AVR_MEGA2560
139 //This var is declared in avr-libc/stdlib/malloc.c
140 //It keeps the largest address not allocated for heap
141 extern char *__brkval;
142 //address of tmp gives us the current stack boundry
144 OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
145 OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
146 ((unsigned int)&tmp - (unsigned int)__brkval));
150 // This is the entity handler for the registered resource.
151 // This is invoked by OCStack whenever it recevies a request for this resource.
152 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest )
154 OCEntityHandlerResult ehRet = OC_EH_OK;
155 OCEntityHandlerResponse response = {0};
156 char payload[MAX_RESPONSE_LENGTH] = {0};
158 if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
160 OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
162 if(OC_REST_GET == entityHandlerRequest->method)
164 size_t responsePayloadGetLength = strlen(responsePayloadGet);
165 if (responsePayloadGetLength < (sizeof(payload) - 1))
167 strncpy(payload, responsePayloadGet, responsePayloadGetLength);
174 else if(OC_REST_PUT == entityHandlerRequest->method)
176 //Do something with the 'put' payload
177 size_t responsePayloadPutLength = strlen(responsePayloadPut);
178 if (responsePayloadPutLength < (sizeof(payload) - 1))
180 strncpy((char *)payload, responsePayloadPut, responsePayloadPutLength);
188 if (ehRet == OC_EH_OK)
190 // Format the response. Note this requires some info about the request
191 response.requestHandle = entityHandlerRequest->requestHandle;
192 response.resourceHandle = entityHandlerRequest->resource;
193 response.ehResult = ehRet;
194 response.payload = payload;
195 response.payloadSize = strlen(payload);
196 response.numSendVendorSpecificHeaderOptions = 0;
197 memset(response.sendVendorSpecificHeaderOptions, 0,
198 sizeof response.sendVendorSpecificHeaderOptions);
199 memset(response.resourceUri, 0, sizeof response.resourceUri);
200 // Indicate that response is NOT in a persistent buffer
201 response.persistentBufferFlag = 0;
204 if (OCDoResponse(&response) != OC_STACK_OK)
206 OC_LOG(ERROR, TAG, "Error sending response");
211 if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
213 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
215 OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
216 gLightUnderObservation = 1;
218 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
220 OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
227 // This method is used to display 'Observe' functionality of OC Stack.
228 static uint8_t modCounter = 0;
229 void *ChangeLightRepresentation (void *param)
232 OCStackResult result = OC_STACK_ERROR;
234 // Matching the timing that the Linux Sample Server App uses for the same functionality.
235 if(modCounter % 10 == 0)
238 if (gLightUnderObservation)
240 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
241 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
242 if (OC_STACK_NO_OBSERVERS == result)
244 gLightUnderObservation = 0;
251 //The setup function is called once at startup of the sketch
254 // Add your initialization code here
255 // Note : This will initialize Serial port on Arduino at 115200 bauds
257 OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
259 // Connect to Ethernet or WiFi network
260 if (ConnectToNetwork() != 0)
262 OC_LOG(ERROR, TAG, PCF("Unable to connect to network"));
266 // Initialize the OC Stack in Server mode
267 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
269 OC_LOG(ERROR, TAG, PCF("OCStack init error"));
273 // Declare and create the example resource: Light
274 createLightResource();
277 // The loop function is called in an endless loop
280 // This artificial delay is kept here to avoid endless spinning
281 // of Arduino microcontroller. Modify it as per specific application needs.
284 // This call displays the amount of free SRAM available on Arduino
285 PrintArduinoMemoryStats();
287 // Give CPU cycles to OCStack to perform send/recv and other OCStack stuff
288 if (OCProcess() != OC_STACK_OK)
290 OC_LOG(ERROR, TAG, PCF("OCStack process error"));
293 ChangeLightRepresentation(NULL);
296 void createLightResource()
299 OCStackResult res = OCCreateResource(&Light.handle,
301 OC_RSRVD_INTERFACE_DEFAULT,
304 OC_DISCOVERABLE|OC_OBSERVABLE);
305 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
308 const char *getResult(OCStackResult result) {
311 return "OC_STACK_OK";
312 case OC_STACK_INVALID_URI:
313 return "OC_STACK_INVALID_URI";
314 case OC_STACK_INVALID_QUERY:
315 return "OC_STACK_INVALID_QUERY";
316 case OC_STACK_INVALID_IP:
317 return "OC_STACK_INVALID_IP";
318 case OC_STACK_INVALID_PORT:
319 return "OC_STACK_INVALID_PORT";
320 case OC_STACK_INVALID_CALLBACK:
321 return "OC_STACK_INVALID_CALLBACK";
322 case OC_STACK_INVALID_METHOD:
323 return "OC_STACK_INVALID_METHOD";
324 case OC_STACK_NO_MEMORY:
325 return "OC_STACK_NO_MEMORY";
326 case OC_STACK_COMM_ERROR:
327 return "OC_STACK_COMM_ERROR";
328 case OC_STACK_INVALID_PARAM:
329 return "OC_STACK_INVALID_PARAM";
330 case OC_STACK_NOTIMPL:
331 return "OC_STACK_NOTIMPL";
332 case OC_STACK_NO_RESOURCE:
333 return "OC_STACK_NO_RESOURCE";
334 case OC_STACK_RESOURCE_ERROR:
335 return "OC_STACK_RESOURCE_ERROR";
336 case OC_STACK_SLOW_RESOURCE:
337 return "OC_STACK_SLOW_RESOURCE";
338 case OC_STACK_NO_OBSERVERS:
339 return "OC_STACK_NO_OBSERVERS";
341 return "OC_STACK_ERROR";