您的位置:首页 > 产品设计 > UI/UE

初探物联网 - 基于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中路由部分的代码实现为:

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上看完整代码.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客户端发送出去即可,代码片段如下:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: