1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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,
197 OCEntityHandlerRequest *entityHandlerRequest )
199 OCEntityHandlerResult ehRet = OC_EH_OK;
200 OCEntityHandlerResponse response = {0};
201 char payload[MAX_RESPONSE_LENGTH] = {0};
203 if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
205 OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
206 if (OC_REST_GET == entityHandlerRequest->method)
208 if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
216 if (OC_REST_PUT == entityHandlerRequest->method)
218 //Do something with the 'put' payload
219 if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
228 if (ehRet == OC_EH_OK)
230 // Format the response. Note this requires some info about the request
231 response.requestHandle = entityHandlerRequest->requestHandle;
232 response.resourceHandle = entityHandlerRequest->resource;
233 response.ehResult = ehRet;
234 response.payload = (unsigned char *)payload;
235 response.payloadSize = strlen(payload);
236 response.numSendVendorSpecificHeaderOptions = 0;
237 memset(response.sendVendorSpecificHeaderOptions, 0,
238 sizeof response.sendVendorSpecificHeaderOptions);
239 memset(response.resourceUri, 0, sizeof response.resourceUri);
240 // Indicate that response is NOT in a persistent buffer
241 response.persistentBufferFlag = 0;
244 if (OCDoResponse(&response) != OC_STACK_OK)
246 OC_LOG(ERROR, TAG, "Error sending response");
251 if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
253 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
255 OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
256 g_THUnderObservation = 1;
258 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
260 OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
267 // This method is used to display 'Observe' functionality of OC Stack.
268 static uint8_t modCounter = 0;
269 void *ChangeTHRepresentation (void *param)
272 OCStackResult result = OC_STACK_ERROR;
274 if (modCounter % 10 ==
275 0) // Matching the timing that the Linux Sample Server App uses for the same functionality.
279 byte i;// start condition
281 digitalWrite(dht11_pin, LOW);
283 digitalWrite(dht11_pin, HIGH);
284 delayMicroseconds(1);
285 pinMode(dht11_pin, INPUT);
286 delayMicroseconds(40);
288 if (digitalRead(dht11_pin))
290 Serial.println("dht11 start condition 1 not met"); // wait for DHT response signal: LOW
294 delayMicroseconds(80);
295 if (!digitalRead(dht11_pin))
297 Serial.println("dht11 start condition 2 not met"); //wair for second response signal:HIGH
301 delayMicroseconds(80);// now ready for data reception
302 for (i = 0; i < 5; i++)
304 dht11_dat[i] = read_dht11_dat();
305 } //recieved 40 bits data. Details are described in datasheet
307 pinMode(dht11_pin, OUTPUT);
308 digitalWrite(dht11_pin, HIGH);
309 byte dht11_check_sum = dht11_dat[0] + dht11_dat[2]; // check check_sum
310 if (dht11_dat[4] != dht11_check_sum)
312 Serial.println("DHT11 checksum error");
314 Serial.print("Current humdity = ");
315 Serial.print(dht11_dat[0], DEC);
317 Serial.print("temperature = ");
318 Serial.print(dht11_dat[2], DEC);
319 Serial.println("C ");
321 TH.m_humid = dht11_dat[0];
322 TH.m_temp = dht11_dat[2];
324 if (g_THUnderObservation)
326 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new humid level %d\n", TH.m_humid);
327 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new temp level %d\n", TH.m_temp);
329 result = OCNotifyAllObservers (TH.m_handle, OC_NA_QOS);
331 if (OC_STACK_NO_OBSERVERS == result)
333 g_THUnderObservation = 0;
342 //The setup function is called once at startup of the sketch
345 pinMode(dht11_pin, OUTPUT);
346 digitalWrite(dht11_pin, HIGH);
348 // Add your initialization code here
351 OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
352 uint16_t port = OC_WELL_KNOWN_PORT;
354 // Connect to Ethernet or WiFi network
355 if (ConnectToNetwork() != 0)
357 OC_LOG(ERROR, TAG, "Unable to connect to network");
361 // Initialize the OC Stack in Server mode
362 if (OCInit(NULL, port, OC_SERVER) != OC_STACK_OK)
364 OC_LOG(ERROR, TAG, PCF("OCStack init error"));
368 // Declare and create the example resource: TH
373 // The loop function is called in an endless loop
376 // This artificial delay is kept here to avoid endless spinning
377 // of Arduino microcontroller. Modify it as per specfic application needs.
380 // This call displays the amount of free SRAM available on Arduino
381 PrintArduinoMemoryStats();
383 if (OCProcess() != OC_STACK_OK)
385 OC_LOG(ERROR, TAG, PCF("OCStack process error"));
388 ChangeTHRepresentation(NULL);
391 void createTHResource()
396 OCStackResult res = OCCreateResource(&TH.m_handle,
398 OC_RSRVD_INTERFACE_DEFAULT,
399 "/Thing_TempHumSensor1",
401 OC_DISCOVERABLE | OC_OBSERVABLE);
402 OC_LOG_V(INFO, TAG, "Created TH resource with result: %s", getResult(res));
405 const char *getResult(OCStackResult result)
410 return "OC_STACK_OK";
411 case OC_STACK_INVALID_URI:
412 return "OC_STACK_INVALID_URI";
413 case OC_STACK_INVALID_QUERY:
414 return "OC_STACK_INVALID_QUERY";
415 case OC_STACK_INVALID_IP:
416 return "OC_STACK_INVALID_IP";
417 case OC_STACK_INVALID_PORT:
418 return "OC_STACK_INVALID_PORT";
419 case OC_STACK_INVALID_CALLBACK:
420 return "OC_STACK_INVALID_CALLBACK";
421 case OC_STACK_INVALID_METHOD:
422 return "OC_STACK_INVALID_METHOD";
423 case OC_STACK_NO_MEMORY:
424 return "OC_STACK_NO_MEMORY";
425 case OC_STACK_COMM_ERROR:
426 return "OC_STACK_COMM_ERROR";
427 case OC_STACK_INVALID_PARAM:
428 return "OC_STACK_INVALID_PARAM";
429 case OC_STACK_NOTIMPL:
430 return "OC_STACK_NOTIMPL";
431 case OC_STACK_NO_RESOURCE:
432 return "OC_STACK_NO_RESOURCE";
433 case OC_STACK_RESOURCE_ERROR:
434 return "OC_STACK_RESOURCE_ERROR";
435 case OC_STACK_SLOW_RESOURCE:
436 return "OC_STACK_SLOW_RESOURCE";
437 case OC_STACK_NO_OBSERVERS:
438 return "OC_STACK_NO_OBSERVERS";
440 return "OC_STACK_ERROR";