By Daniel Du
After a long time break, I need to speed up blogging what I learned with IoT. I’ve learned how to setup the environment of Arduino and how to do the same in Autodesk 123D circuits without a real device, and then I learned how to get the temperature with a LM35 temperature sensor. My next step is to send the temperature value to the cloud, so that it can be shared/used by other users or applications.
I created a sample with this idea, integrating the Arduino weather station with View and Data API. Here is the live demo : http://arduiview.herokuapp.com/ (this line char may be empty as the sensor is not connected all the time). The viewer shows 3D model of a building, let’s say the Arduino based weather station is setup on the roof, and keep sending temperature to the cloud periodically. The web page client get the temperature data and shows up a line chart in the viewer. When the temperature is too high( higher than 40 ℃), There will be a high temperature alarm, and the viewer zoom to the sensor. It is just a simple sample for demo, but you can applied to more practical scenario.
Here is the architecture, the Arduino based weather station and the viewer communicate with cloud via REST API.
The Arduino itself cannot connect to the network, to communicate with cloud, I need another device. I choose CC3000 WiFi Shield, which can be used with Arduino together, so that Arduino can connect to internet with WiFi. I put CC3000 WiFi shield on top of Arduino and connect to the LM35 temperature sensor, it looks like below:
The software side, I use Adafruite CC3000 Library to drive the shield. In Arduino IDE, I go to “Project” –> “Include Libraries” –> “Manage Libraries”, and search “CC3000”, and installed it as screen-shot below:
Once the library is installed, you can find many example projects in Arduino IDE, which is lovely . You can take a look at the example files to understand how the library is used.
Now I need to create a server which is supposed to be running on cloud as a data center. I use node.js to create a simple website which expose some REST APIs, so that the Arduino can send temperature data to the server on Cloud with REST. Here are some code snippet.
The server exposes a REST API to receive data, the URL is similar like :
PUT /sensors/somesensorId/values
body:
{
value : 22
}
The node.js code snippet is like below:
router.route('/sensors/:sensorId/values')
.get(sensorController.getSensorValues)
.put(sensorController.appendSensorValues);
And here is the code of sensorController. Actually I am using mongoose and MongoDb at back end to save the data into database. Just for demo, I did not save all the temperature data as it can be huge since the sensor will be uploading data to cloud serve all the time, I just keep the latest piece. For the practical system, you may want to save all the data to make it possible to do big data analysis latter.
exports.appendSensorValues = function(req,res){ //append //we just save 50 + 1 values items to save db spaces var MAX_VAULE_ITEM_COUNT = 50; var sensorId = req.params.sensorId; Sensor.findById(sensorId, function(err, sensor){ if(err) res.json(err); var sensorValueItem = {}; sensorValueItem.timestamp = new Date().getTime(); sensorValueItem.value = req.body.value; //console.log(sensorValueItem); var len = sensor.values.length; sensor.values = sensor.values.slice(len - MAX_VAULE_ITEM_COUNT ); sensor.values = sensor.values.concat(sensorValueItem); sensor.save(function(err){ if(err) res.send(err); res.json(sensorValueItem); }) }); }
Please refer to following link to see the complete source code.https://github.com/duchangyu/project-arduivew/tree/v0.1,
Now let’s go to the Arduino side. Since we can connect to internet with CC3000 WiFi shield, we can send the temperature value to our cloud server by REST call. The REST call is basically sending raw http content, according to our REST API defined by the server:
PUT /api/sensors/somesensorid/value HTTP/1.1
HOST: arduiview.heroku.com
content-type : application/json
Content-Length : 19
{
value : 22
}
Here is the code snippet:
void postTemperatureToCloudServer() { //connectToCloudServer Serial.println(F("trying to connect to cloud server.....")); //client.close(); client = cc3000.connectTCP(ip, 80); Serial.println(F("connected to cloud server - ")); Serial.println(WEBSITE ); Serial.println(F("begin uploading...")); float temp = 0.0; // get the current temperature from sensor int reading = analogRead(0); temp = reading * 0.0048828125 * 100; Serial.print(F("Current temp")); Serial.println(temp); int length; char sTemp[5] = ""; //convert float to char*, dtostrf(temp, 2, 2, sTemp); //val, integer part width, precise, result char array //itoa(temp, sTemp,10); Serial.println(sTemp); char sLength[3]; //prepare the http body // //{ // "value" : 55.23 //} // char httpPackage[20] = ""; strcat(httpPackage, "{\"value\": \""); strcat(httpPackage, sTemp); strcat(httpPackage, "\" }"); // get the length of data package length = strlen(httpPackage); // convert int to char array for posting itoa(length, sLength, 10); Serial.print(F("body lenght=")); Serial.println(sLength); //prepare the http header Serial.println(F("Sending headers...")); client.fastrprint(F("PUT /api/sensors/")); char *sensorId = SENSOR_ID; client.fastrprint(sensorId); //client.fastrprint(SENSOR_ID); client.fastrprint(F("/values")); client.fastrprintln(F(" HTTP/1.1")); Serial.print(F(".")); client.fastrprint(F("Host: ")); client.fastrprintln(WEBSITE); Serial.print(F(".")); client.fastrprint(F("content-type: ")); client.fastrprintln(F("application/json")); Serial.print(F(".")); client.fastrprint(F("Content-Length: ")); client.fastrprintln(sLength); client.fastrprintln(F("")); Serial.print(F(".")); Serial.println(F("header done.")); //send data Serial.println(F("Sending data")); client.fastrprintln(httpPackage); Serial.println(F("===upload completed.")); // Get the http page feedback unsigned long rTimer = millis(); Serial.println(F("Reading Cloud Response!!!\r\n")); while (millis() - rTimer < 2000) { while (client.connected() && client.available()) { char c = client.read(); Serial.print(c); } } delay(1000); // Wait for 1s to finish posting the data stream client.close(); // Close the service connection Serial.println(F("upload completed\n")); }
You can get the complete code from github :
https://github.com/duchangyu/project-arduivew/blob/v0.1/arduino/arduiview-lm35-2/arduiview-lm35-2.ino
Comments
You can follow this conversation by subscribing to the comment feed for this post.