Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / service / soft-sensor-manager / SampleApp / arduino / THSensorApp1 / src / thserver.cpp
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics 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 #define dht11_pin 12
25
26 #include "logger.h"
27 #include "ocstack.h"
28 #include <string.h>
29
30 #ifdef ARDUINOWIFI
31 // Arduino WiFi Shield
32 #include <SPI.h>
33 #include <WiFi.h>
34 #include <WiFiUdp.h>
35 #else
36 // Arduino Ethernet Shield
37 #include <EthernetServer.h>
38 #include <Ethernet.h>
39 #include <Dns.h>
40 #include <EthernetClient.h>
41 #include <util.h>
42 #include <EthernetUdp.h>
43 #include <Dhcp.h>
44 #endif
45
46 const char *getResult(OCStackResult result);
47
48 PROGMEM const char TAG[] = "ArduinoServer";
49
50 int g_THUnderObservation = 0;
51 void createTHResource();
52 typedef struct THRESOURCE
53 {
54     OCResourceHandle m_handle;
55     int m_temp;
56     int m_humid;
57 } THResource;
58
59 static THResource TH;
60
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;
63
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 "\"}}"
68
69 char temp[100];
70
71 #define LENGTH_VAR      100
72 static int base_length = 0;
73
74 bool JsonGenerator( THResource &th, char *jsonBuf, uint16_t buf_length )
75 {
76     if ( (buf_length - base_length) < LENGTH_VAR )
77     {
78         OC_LOG_V(ERROR, TAG, "Error : length is very long.");
79         return false;
80     }
81
82     sprintf(jsonBuf, JSON_BASE00 JSON_BASE01"%d", th.m_temp);
83     sprintf(jsonBuf + strlen(jsonBuf), JSON_BASE02"%d"JSON_BASE03, th.m_humid);
84
85     Serial.println(jsonBuf);
86
87     return true;
88 }
89
90 byte read_dht11_dat()
91 {
92     byte i = 0;
93     byte result = 0;
94     for (i = 0; i < 8; i++)
95     {
96         while (!digitalRead(dht11_pin));
97         delayMicroseconds(30);
98         if (digitalRead(dht11_pin) != 0 )
99             bitSet(result, 7 - i);
100         while (digitalRead(dht11_pin));
101     }
102     return result;
103 }
104
105 #ifdef ARDUINOWIFI
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.
109
110 /// WiFi Shield firmware with Intel patches
111 static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0";
112
113 /// WiFi network info and credentials
114 char ssid[] = "SoftSensor_AP";
115 char pass[] = "1234567890";
116
117 //char ssid[] = "Iotivity-1";
118 //char pass[] = "1234567890";
119
120 int ConnectToNetwork()
121 {
122     char *fwVersion;
123     int status = WL_IDLE_STATUS;
124     // check for the presence of the shield:
125     if (WiFi.status() == WL_NO_SHIELD)
126     {
127         OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
128         return -1;
129     }
130
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 )
135     {
136         OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
137         return -1;
138     }
139
140     // attempt to connect to Wifi network:
141     while (status != WL_CONNECTED)
142     {
143         OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid);
144         status = WiFi.begin(ssid, pass);
145
146         // wait 10 seconds for connection:
147         delay(10000);
148     }
149     OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
150
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]);
153     return 0;
154 }
155 #else
156 // Arduino Ethernet Shield
157 int ConnectToNetwork()
158 {
159     // Note: ****Update the MAC address here with your shield's MAC address****
160     uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0E, 0xB8, 0xAC};
161
162     uint8_t error = Ethernet.begin(ETHERNET_MAC);
163     if (error  == 0)
164     {
165         OC_LOG_V(ERROR, TAG, "error is: %d", error);
166         return -1;
167     }
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]);
170     return 0;
171 }
172 #endif //ARDUINOWIFI
173
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()
180 {
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
186     int tmp;
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));
190 #endif
191 }
192
193
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 )
198 {
199     OCEntityHandlerResult ehRet = OC_EH_OK;
200     OCEntityHandlerResponse response = {0};
201     char payload[MAX_RESPONSE_LENGTH] = {0};
202
203     if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
204     {
205         OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
206         if (OC_REST_GET == entityHandlerRequest->method)
207         {
208             if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
209             {
210             }
211             else
212             {
213                 ehRet = OC_EH_ERROR;
214             }
215         }
216         if (OC_REST_PUT == entityHandlerRequest->method)
217         {
218             //Do something with the 'put' payload
219             if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
220             {
221             }
222             else
223             {
224                 ehRet = OC_EH_ERROR;
225             }
226         }
227
228         if (ehRet == OC_EH_OK)
229         {
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;
242
243             // Send the response
244             if (OCDoResponse(&response) != OC_STACK_OK)
245             {
246                 OC_LOG(ERROR, TAG, "Error sending response");
247                 ehRet = OC_EH_ERROR;
248             }
249         }
250     }
251     if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
252     {
253         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
254         {
255             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
256             g_THUnderObservation = 1;
257         }
258         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
259         {
260             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
261         }
262     }
263
264     return ehRet;
265 }
266
267 // This method is used to display 'Observe' functionality of OC Stack.
268 static uint8_t modCounter = 0;
269 void *ChangeTHRepresentation (void *param)
270 {
271     (void)param;
272     OCStackResult result = OC_STACK_ERROR;
273     modCounter += 1;
274     if (modCounter % 10 ==
275         0) // Matching the timing that the Linux Sample Server App uses for the same functionality.
276     {
277
278         byte dht11_dat[5];
279         byte i;// start condition
280
281         digitalWrite(dht11_pin, LOW);
282         delay(18);
283         digitalWrite(dht11_pin, HIGH);
284         delayMicroseconds(1);
285         pinMode(dht11_pin, INPUT);
286         delayMicroseconds(40);
287
288         if (digitalRead(dht11_pin))
289         {
290             Serial.println("dht11 start condition 1 not met"); // wait for DHT response signal: LOW
291             delay(1000);
292             return NULL;
293         }
294         delayMicroseconds(80);
295         if (!digitalRead(dht11_pin))
296         {
297             Serial.println("dht11 start condition 2 not met");  //wair for second response signal:HIGH
298             return NULL;
299         }
300
301         delayMicroseconds(80);// now ready for data reception
302         for (i = 0; i < 5; i++)
303         {
304             dht11_dat[i] = read_dht11_dat();
305         }  //recieved 40 bits data. Details are described in datasheet
306
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)
311         {
312             Serial.println("DHT11 checksum error");
313         }
314         Serial.print("Current humdity = ");
315         Serial.print(dht11_dat[0], DEC);
316         Serial.print("%  ");
317         Serial.print("temperature = ");
318         Serial.print(dht11_dat[2], DEC);
319         Serial.println("C  ");
320
321         TH.m_humid = dht11_dat[0];
322         TH.m_temp = dht11_dat[2];
323
324         if (g_THUnderObservation)
325         {
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);
328
329             result = OCNotifyAllObservers (TH.m_handle, OC_NA_QOS);
330
331             if (OC_STACK_NO_OBSERVERS == result)
332             {
333                 g_THUnderObservation = 0;
334             }
335         }
336     }
337     return NULL;
338 }
339
340
341
342 //The setup function is called once at startup of the sketch
343 void setup()
344 {
345     pinMode(dht11_pin, OUTPUT);
346     digitalWrite(dht11_pin, HIGH);
347
348     // Add your initialization code here
349     OC_LOG_INIT();
350
351     OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
352     uint16_t port = OC_WELL_KNOWN_PORT;
353
354     // Connect to Ethernet or WiFi network
355     if (ConnectToNetwork() != 0)
356     {
357         OC_LOG(ERROR, TAG, "Unable to connect to network");
358         return;
359     }
360
361     // Initialize the OC Stack in Server mode
362     if (OCInit(NULL, port, OC_SERVER) != OC_STACK_OK)
363     {
364         OC_LOG(ERROR, TAG, PCF("OCStack init error"));
365         return;
366     }
367     OCStartPresence(60);
368     // Declare and create the example resource: TH
369     createTHResource();
370
371 }
372
373 // The loop function is called in an endless loop
374 void loop()
375 {
376     // This artificial delay is kept here to avoid endless spinning
377     // of Arduino microcontroller. Modify it as per specfic application needs.
378     delay(2000);
379
380     // This call displays the amount of free SRAM available on Arduino
381     PrintArduinoMemoryStats();
382
383     if (OCProcess() != OC_STACK_OK)
384     {
385         OC_LOG(ERROR, TAG, PCF("OCStack process error"));
386         return;
387     }
388     ChangeTHRepresentation(NULL);
389 }
390
391 void createTHResource()
392 {
393     TH.m_humid = 0;
394     TH.m_temp = 0;
395
396     OCStackResult res = OCCreateResource(&TH.m_handle,
397                                          "SSManager.Sensor",
398                                          OC_RSRVD_INTERFACE_DEFAULT,
399                                          "/Thing_TempHumSensor1",
400                                          OCEntityHandlerCb,
401                                          OC_DISCOVERABLE | OC_OBSERVABLE);
402     OC_LOG_V(INFO, TAG, "Created TH resource with result: %s", getResult(res));
403 }
404
405 const char *getResult(OCStackResult result)
406 {
407     switch (result)
408     {
409         case OC_STACK_OK:
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";
439         case OC_STACK_ERROR:
440             return "OC_STACK_ERROR";
441         default:
442             return "UNKNOWN";
443     }
444 }