初探物联网 - 基于Arduino的气象站和View and Data API的结合实例
2015-12-04 16:35
573 查看
如果你参加了上个月在北京的Autodesk开发者日,你应该看到了我做的关于Arduino的物联网实例演示,如果你没看到,欢迎参加14号在上海的开发者日,到时候我会再演(xian)示(bai)一下。
这是个基于这样一个场景的简单演示。我的一个建筑物上面安装了这样一个温度传感器,随时把当前环境温度上传到云端,在浏览器端可以显示这个建筑物的三维模型和温度变化曲线图。如果温度到达一定的高温,比如大于40度,那可能是起火了,就需要发出高温报警,在三维模型中定位出报警的温度传感器的位置,并发出火警警报。
演示地址:http://arduiview.herokuapp.com/
继续之前你可能需要阅读一下我前面的两篇文章:
迈出物联网的第一步,玩儿一下Arduino
使用Arduino和LM35温度传感器监测温度
下面简单介绍一下这个实例系统的实现。下图为系统的架构图,Arduino和Viewer都通过REST的方式和云端的服务器进行通信。Arduino定时把当前温度通过REST的方式上传,Viewer定时取得温度信息并绘制曲线图,如遇高温则报警。貌似相当简单,这种基于HTTP的RESTAPI方式的一个缺点就是实时性不好,需要进行轮询。后面我做了改进,通过WebSocket和MQTT协议,可以实现更好的实时传输,这个我们后面再说。
下图就是Arduino和LM35温度传感器的链接情况。Arduino本身并没有联网功能,所以还需要一个额外的设备,我采用了CC3000WiFiShield模块,在淘宝上也可以买到。把Arduino和CC3000两个套在一起,然后按照前面文章中提到的方式把温度传感器连接起来即可。
然后我们需要写些代码驱动CC3300WiFi模块联网。我们可以使用AdafruiteCC3000Library。在ArduinoIDE里面,“Project”–>“IncludeLibraries”–>“ManageLibraries”,搜索“CC3000”,找到这个类库安装。然后你可以阅读一下自带的例子。这一点Arduino做的非常好,每个类库都有完备的实例,拿过来改一下就可以了。
下面我们需要创建云端的服务器,我用node.js来创建并且暴露了一些RESTAPI。其中一个就是用来解释Arduino上传的温度数据的RESTAPI。如下所示:
PUT/sensors/somesensorId/values
body:
{
value:22
}
node.js中路由部分的代码实现为:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
下面是sensorController控制器的实现代码。这里没有列出的是,其实后端我还使用的mongoose和mongoDb以便把上传的温度数据保存起来,这样以后就可以做大数据分析了。不过这个例子只是为了演示,我也没保存全部数据,只是保存了最近50多个。
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这里的代码还是挂一漏万,如果大家感兴趣还是在github上看完整代码.https://github.com/duchangyu/project-arduivew/tree/v0.1,
下面来实现Arduino的部分,获取温度并通过REST的方式上传。前面提到的CC3000提供的实例已经演示了怎么连接到WiFi并上网,这里略过,如果你感兴趣可以看我的完整代码。这里我们只说说Arduino怎么发送REST请求的部分。在Arduino里面,我没有找到好的REST的client库,不过说起来也不复杂,就是按照HTTP的协议发送原生字符串即可。按照我们的REST接口的定义,上传的REST协议应该是这样的:
PUT/api/sensors/somesensorid/valueHTTP/1.1
HOST:arduiview.heroku.com
content-type:application/json
Content-Length:19
{
value:22
}
下面就是构建这样的字符串,然后通过CC3000客户端发送出去即可,代码片段如下:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这是个基于这样一个场景的简单演示。我的一个建筑物上面安装了这样一个温度传感器,随时把当前环境温度上传到云端,在浏览器端可以显示这个建筑物的三维模型和温度变化曲线图。如果温度到达一定的高温,比如大于40度,那可能是起火了,就需要发出高温报警,在三维模型中定位出报警的温度传感器的位置,并发出火警警报。
演示地址:
继续之前你可能需要阅读一下我前面的两篇文章:
下面简单介绍一下这个实例系统的实现。下图为系统的架构图,Arduino和Viewer都通过REST的方式和云端的服务器进行通信。Arduino定时把当前温度通过REST的方式上传,Viewer定时取得温度信息并绘制曲线图,如遇高温则报警。貌似相当简单,这种基于HTTP的RESTAPI方式的一个缺点就是实时性不好,需要进行轮询。后面我做了改进,通过WebSocket和MQTT协议,可以实现更好的实时传输,这个我们后面再说。
下图就是Arduino和LM35温度传感器的链接情况。Arduino本身并没有联网功能,所以还需要一个额外的设备,我采用了CC3000WiFiShield模块,在淘宝上也可以买到。把Arduino和CC3000两个套在一起,然后按照前面文章中提到的方式把温度传感器连接起来即可。
然后我们需要写些代码驱动CC3300WiFi模块联网。我们可以使用AdafruiteCC3000Library。在ArduinoIDE里面,“Project”–>“IncludeLibraries”–>“ManageLibraries”,搜索“CC3000”,找到这个类库安装。然后你可以阅读一下自带的例子。这一点Arduino做的非常好,每个类库都有完备的实例,拿过来改一下就可以了。
下面我们需要创建云端的服务器,我用node.js来创建并且暴露了一些RESTAPI。其中一个就是用来解释Arduino上传的温度数据的RESTAPI。如下所示:
PUT/sensors/somesensorId/values
body:
{
value:22
}
node.js中路由部分的代码实现为:
router.route('/sensors/:sensorId/values') .get(sensorController.getSensorValues) .put(sensorController.appendSensorValues);
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
下面是sensorController控制器的实现代码。这里没有列出的是,其实后端我还使用的mongoose和mongoDb以便把上传的温度数据保存起来,这样以后就可以做大数据分析了。不过这个例子只是为了演示,我也没保存全部数据,只是保存了最近50多个。
exports.appendSensorValues=function(req,res){//append //wejustsave50+1valuesitemstosavedbspaces varMAX_VAULE_ITEM_COUNT=50; varsensorId=req.params.sensorId; Sensor.findById(sensorId,function(err,sensor){ if(err) res.json(err); varsensorValueItem={}; sensorValueItem.timestamp=newDate().getTime(); sensorValueItem.value=req.body.value; //console.log(sensorValueItem); varlen=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); }) }); }
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这里的代码还是挂一漏万,如果大家感兴趣还是在github上看完整代码.
下面来实现Arduino的部分,获取温度并通过REST的方式上传。前面提到的CC3000提供的实例已经演示了怎么连接到WiFi并上网,这里略过,如果你感兴趣可以看我的完整代码。这里我们只说说Arduino怎么发送REST请求的部分。在Arduino里面,我没有找到好的REST的client库,不过说起来也不复杂,就是按照HTTP的协议发送原生字符串即可。按照我们的REST接口的定义,上传的REST协议应该是这样的:
PUT/api/sensors/somesensorid/valueHTTP/1.1
HOST:arduiview.heroku.com
content-type:application/json
Content-Length:19
{
value:22
}
下面就是构建这样的字符串,然后通过CC3000客户端发送出去即可,代码片段如下:
voidpostTemperatureToCloudServer(){ //connectToCloudServer Serial.println(F("tryingtoconnecttocloudserver.....")); //client.close(); client=cc3000.connectTCP(ip,80); Serial.println(F("connectedtocloudserver-")); Serial.println(WEBSITE); Serial.println(F("beginuploading...")); floattemp=0.0; //getthecurrenttemperaturefromsensor intreading=analogRead(0); temp=reading*0.0048828125*100; Serial.print(F("Currenttemp")); Serial.println(temp); intlength; charsTemp[5]=""; //convertfloattochar*, dtostrf(temp,2,2,sTemp);//val,integerpartwidth,precise,resultchararray //itoa(temp,sTemp,10); Serial.println(sTemp); charsLength[3]; //preparethehttpbody // //{ //"value":55.23 //} // charhttpPackage[20]=""; strcat(httpPackage,"{\"value\":\""); strcat(httpPackage,sTemp); strcat(httpPackage,"\"}"); //getthelengthofdatapackage length=strlen(httpPackage); //convertinttochararrayforposting itoa(length,sLength,10); Serial.print(F("bodylenght=")); Serial.println(sLength); //preparethehttpheader Serial.println(F("Sendingheaders...")); 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("headerdone.")); //senddata Serial.println(F("Sendingdata")); client.fastrprintln(httpPackage); Serial.println(F("===uploadcompleted.")); //Getthehttppagefeedback unsignedlongrTimer=millis(); Serial.println(F("ReadingCloudResponse!!!\r\n")); while(millis()-rTimer<2000){ while(client.connected()&&client.available()){ charc=client.read(); Serial.print(c); } } delay(1000);//Waitfor1stofinishpostingthedatastream client.close();//Closetheserviceconnection Serial.println(F("uploadcompleted\n")); }
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
感兴趣还是看一下完整代码,在这里:
https://github.com/duchangyu/project-arduivew/blob/v0.1/arduino/arduiview-lm35-2/arduiview-lm35-2.ino
相关文章推荐
- iOS上架准备工作(一)--版本号和编译号 (Version Numbers and Build Numbers)
- Builder design pattern in java
- Ubuntu ROS Arduino Gazebo学习镜像iso说明(indigo版)
- Ubuntu ROS Arduino Gazebo学习镜像iso说明(indigo版)
- Ubuntu ROS Arduino Gazebo学习镜像iso说明(indigo版)
- UIImageJPEGRepresentation和UIImagePNGRepresentation
- NSData、 UIImage、ALAsset之间的关系和转化
- ERROR 1269 (HY000): Can't revoke all privileges for one or more of the requested users
- Obtaining, Configuring and Building unixODBC
- 通过实现一个TableView来理解iOS UI编程
- hdu 1159 Common Subsequence
- 关于easyui textbox赋值
- Handler、Looper、MessageQueue
- UI进阶之模拟时钟指针案例
- UITableView最上面tableHeaderView留空间的两种方法
- 你好,色彩 android:background="@color/white" [create file color.xml at res/values/]
- 解决"The server quit without updating PID file."
- iOS开发~UITextView光标不在起始位置问题
- 在iOS 8中使用UIAlertController
- 融云Android 2.0 IMkit UI样式更改