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
31 // Arduino WiFi Shield
36 // Arduino Ethernet Shield
37 #include <EthernetServer.h>
40 #include <EthernetClient.h>
42 #include <EthernetUdp.h>
46 const char *getResult(OCStackResult result);
48 PROGMEM const char TAG[] = "ArduinoServer";
50 int g_THUnderObservation = 0;
51 void createTHResource();
52 typedef struct THRESOURCE
54 OCResourceHandle m_handle;
61 /// This is the port which Arduino Server will use for all unicast communication with it's peers
62 static uint16_t OC_WELL_KNOWN_PORT = 5683;
64 #define JSON_BASE00 "{\"href\":\"\",\"rep\":{"
65 #define JSON_BASE01 "\"0\":\"temperature\",\"1\":\"int\",\"2\":\""
66 #define JSON_BASE02 "\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\""
67 #define JSON_BASE03 "\"}}"
71 #define LENGTH_VAR 100
72 static int base_length = 0;
74 bool JsonGenerator( THResource& th, char* jsonBuf, uint16_t buf_length )
76 if( (buf_length - base_length) < LENGTH_VAR )
78 OC_LOG_V(ERROR, TAG, "Error : length is very long.");
82 sprintf(jsonBuf, JSON_BASE00 JSON_BASE01"%d",th.m_temp);
83 sprintf(jsonBuf+strlen(jsonBuf), JSON_BASE02"%d"JSON_BASE03, th.m_humid);
85 Serial.println(jsonBuf);
94 for (i = 0; i < 8; i++)
96 while (!digitalRead(dht11_pin));
97 delayMicroseconds(30);
98 if (digitalRead(dht11_pin) != 0 )
99 bitSet(result, 7 - i);
100 while (digitalRead(dht11_pin));
106 // Arduino WiFi Shield
107 // Note : Arduino WiFi Shield currently does NOT support multicast and therefore
108 // this server will NOT be listening on 224.0.1.187 multicast address.
110 /// WiFi Shield firmware with Intel patches
111 static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0";
113 /// WiFi network info and credentials
114 char ssid[] = "SoftSensor_AP";
115 char pass[] = "1234567890";
117 //char ssid[] = "Iotivity-1";
118 //char pass[] = "1234567890";
120 int ConnectToNetwork()
123 int status = WL_IDLE_STATUS;
124 // check for the presence of the shield:
125 if (WiFi.status() == WL_NO_SHIELD)
127 OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
131 // Verify that WiFi Shield is running the firmware with all UDP fixes
132 fwVersion = WiFi.firmwareVersion();
133 OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
134 if ( strncmp(fwVersion, INTEL_WIFI_SHIELD_FW_VER, sizeof(INTEL_WIFI_SHIELD_FW_VER)) != 0 )
136 OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
140 // attempt to connect to Wifi network:
141 while (status != WL_CONNECTED)
143 OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid);
144 status = WiFi.begin(ssid, pass);
146 // wait 10 seconds for connection:
149 OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
151 IPAddress ip = WiFi.localIP();
152 OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
156 // Arduino Ethernet Shield
157 int ConnectToNetwork()
159 // Note: ****Update the MAC address here with your shield's MAC address****
160 uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0E, 0xB8, 0xAC};
162 uint8_t error = Ethernet.begin(ETHERNET_MAC);
165 OC_LOG_V(ERROR, TAG, "error is: %d", error);
168 IPAddress ip = Ethernet.localIP();
169 OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
174 // On Arduino Atmel boards with Harvard memory architecture, the stack grows
175 // downwards from the top and the heap grows upwards. This method will print
176 // the distance(in terms of bytes) between those two.
177 // See here for more details :
178 // http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
179 void PrintArduinoMemoryStats()
181 #ifdef ARDUINO_AVR_MEGA2560
182 //This var is declared in avr-libc/stdlib/malloc.c
183 //It keeps the largest address not allocated for heap
184 extern char *__brkval;
185 //address of tmp gives us the current stack boundry
187 OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
188 OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
189 ((unsigned int)&tmp - (unsigned int)__brkval));
194 // This is the entity handler for the registered resource.
195 // This is invoked by OCStack whenever it recevies a request for this resource.
196 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest )
198 OCEntityHandlerResult ehRet = OC_EH_OK;
199 OCEntityHandlerResponse response = {0};
200 char payload[MAX_RESPONSE_LENGTH] = {0};
202 if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
204 OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
205 if(OC_REST_GET == entityHandlerRequest->method)
207 if(JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
215 if(OC_REST_PUT == entityHandlerRequest->method)
217 //Do something with the 'put' payload
218 if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
227 if (ehRet == OC_EH_OK)
229 // Format the response. Note this requires some info about the request
230 response.requestHandle = entityHandlerRequest->requestHandle;
231 response.resourceHandle = entityHandlerRequest->resource;
232 response.ehResult = ehRet;
233 response.payload = (unsigned char *)payload;
234 response.payloadSize = strlen(payload);
235 response.numSendVendorSpecificHeaderOptions = 0;
236 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
237 memset(response.resourceUri, 0, sizeof response.resourceUri);
238 // Indicate that response is NOT in a persistent buffer
239 response.persistentBufferFlag = 0;
242 if (OCDoResponse(&response) != OC_STACK_OK)
244 OC_LOG(ERROR, TAG, "Error sending response");
249 if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
251 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
253 OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
254 g_THUnderObservation = 1;
256 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
258 OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
265 // This method is used to display 'Observe' functionality of OC Stack.
266 static uint8_t modCounter = 0;
267 void *ChangeTHRepresentation (void *param)
270 OCStackResult result = OC_STACK_ERROR;
272 if (modCounter % 10 ==
273 0) // Matching the timing that the Linux Sample Server App uses for the same functionality.
277 byte i;// start condition
279 digitalWrite(dht11_pin, LOW);
281 digitalWrite(dht11_pin, HIGH);
282 delayMicroseconds(1);
283 pinMode(dht11_pin, INPUT);
284 delayMicroseconds(40);
286 if (digitalRead(dht11_pin))
288 Serial.println("dht11 start condition 1 not met"); // wait for DHT response signal: LOW
292 delayMicroseconds(80);
293 if (!digitalRead(dht11_pin))
295 Serial.println("dht11 start condition 2 not met"); //wair for second response signal:HIGH
299 delayMicroseconds(80);// now ready for data reception
300 for (i = 0; i < 5; i++)
302 dht11_dat[i] = read_dht11_dat();
303 } //recieved 40 bits data. Details are described in datasheet
305 pinMode(dht11_pin, OUTPUT);
306 digitalWrite(dht11_pin, HIGH);
307 byte dht11_check_sum = dht11_dat[0] + dht11_dat[2]; // check check_sum
308 if (dht11_dat[4] != dht11_check_sum)
310 Serial.println("DHT11 checksum error");
312 Serial.print("Current humdity = ");
313 Serial.print(dht11_dat[0], DEC);
315 Serial.print("temperature = ");
316 Serial.print(dht11_dat[2], DEC);
317 Serial.println("C ");
319 TH.m_humid = dht11_dat[0];
320 TH.m_temp = dht11_dat[2];
322 if (g_THUnderObservation)
324 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new humid level %d\n", TH.m_humid);
325 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new temp level %d\n", TH.m_temp);
327 result = OCNotifyAllObservers (TH.m_handle, OC_NA_QOS);
329 if (OC_STACK_NO_OBSERVERS == result)
331 g_THUnderObservation = 0;
340 //The setup function is called once at startup of the sketch
343 pinMode(dht11_pin, OUTPUT);
344 digitalWrite(dht11_pin, HIGH);
346 // Add your initialization code here
349 OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
350 uint16_t port = OC_WELL_KNOWN_PORT;
352 // Connect to Ethernet or WiFi network
353 if (ConnectToNetwork() != 0)
355 OC_LOG(ERROR, TAG, "Unable to connect to network");
359 // Initialize the OC Stack in Server mode
360 if (OCInit(NULL, port, OC_SERVER) != OC_STACK_OK)
362 OC_LOG(ERROR, TAG, PCF("OCStack init error"));
366 // Declare and create the example resource: TH
371 // The loop function is called in an endless loop
374 // This artificial delay is kept here to avoid endless spinning
375 // of Arduino microcontroller. Modify it as per specfic application needs.
378 // This call displays the amount of free SRAM available on Arduino
379 PrintArduinoMemoryStats();
381 if (OCProcess() != OC_STACK_OK)
383 OC_LOG(ERROR, TAG, PCF("OCStack process error"));
386 ChangeTHRepresentation(NULL);
389 void createTHResource()
394 OCStackResult res = OCCreateResource(&TH.m_handle,
395 "SoftSensorManager.Sensor",
397 "/Thing_TempHumSensor1",
399 OC_DISCOVERABLE | OC_OBSERVABLE);
400 OC_LOG_V(INFO, TAG, "Created TH resource with result: %s", getResult(res));
403 const char *getResult(OCStackResult result)
408 return "OC_STACK_OK";
409 case OC_STACK_INVALID_URI:
410 return "OC_STACK_INVALID_URI";
411 case OC_STACK_INVALID_QUERY:
412 return "OC_STACK_INVALID_QUERY";
413 case OC_STACK_INVALID_IP:
414 return "OC_STACK_INVALID_IP";
415 case OC_STACK_INVALID_PORT:
416 return "OC_STACK_INVALID_PORT";
417 case OC_STACK_INVALID_CALLBACK:
418 return "OC_STACK_INVALID_CALLBACK";
419 case OC_STACK_INVALID_METHOD:
420 return "OC_STACK_INVALID_METHOD";
421 case OC_STACK_NO_MEMORY:
422 return "OC_STACK_NO_MEMORY";
423 case OC_STACK_COMM_ERROR:
424 return "OC_STACK_COMM_ERROR";
425 case OC_STACK_INVALID_PARAM:
426 return "OC_STACK_INVALID_PARAM";
427 case OC_STACK_NOTIMPL:
428 return "OC_STACK_NOTIMPL";
429 case OC_STACK_NO_RESOURCE:
430 return "OC_STACK_NO_RESOURCE";
431 case OC_STACK_RESOURCE_ERROR:
432 return "OC_STACK_RESOURCE_ERROR";
433 case OC_STACK_SLOW_RESOURCE:
434 return "OC_STACK_SLOW_RESOURCE";
435 case OC_STACK_NO_OBSERVERS:
436 return "OC_STACK_NO_OBSERVERS";
438 return "OC_STACK_ERROR";