PM2.5采集器(支持微信查询)
本帖最后由 kevinzhang 于 2015-12-21 14:01 编辑该终端设备采集办公室空气质量(包括:PM1、PM2.5、PM10)、温湿度、照明和噪声,并可通过微信公众号实时查询7个数据。
终端设备如下图:
微信查询结果如下图:
拓扑结构图如下图:
终端设备细节如下图:
Arduino Uno代码如下::lol
#include "Arduino.h"
#include "serialReadPMValue.h"
#include <DHT22.h>
#include <stdio.h>
#include <SPI.h>
#include <Ethernet.h>
// 数字PIN 3 --> LED 红
// 数字PIN 7 --> DHT22温湿度
// 数字PIN 9 --> 蜂鸣器
// 模拟PIN 0 --> 模拟声音
// 模拟PIN 3 --> LX1972环境光
uint16_t PM01Value= 0;// PM1.0
uint16_t PM2_5Value = 0;// PM2.5
uint16_t PM10Value= 0;// PM10
#define receiveDatIndex 32
uint8_t receiveDat;
#define DHT22_PIN 7
DHT22 myDHT22(DHT22_PIN);
int valLight = 0;// 光线Value
int valSound = 0;// 声音Value
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(116, 236, 162, 186); // 项目服务器公网IP
IPAddress ip(192, 168, 1, 76); // 内网IP(该终端设备的内网IP)
EthernetClient client;
String myTempPM01= "";
String myTempPM25= "";
String myTempPM10= "";
String myTempLight = "";
String myTempSound = "";
String myTempTemp= "";
String myTempHumi= "";
void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
pinMode(3, OUTPUT);
pinMode(9, OUTPUT);
}
void loop()
{
int length = serialRead(Serial, receiveDat, receiveDatIndex, 5);
int checkSum = checkValue(receiveDat, receiveDatIndex);
if(length&&checkSum)
{
PM01Value= transmitPM01(receiveDat); //取PM1.0
PM2_5Value = transmitPM2_5(receiveDat);//取PM2.5
PM10Value= transmitPM10(receiveDat); //取PM10
}
static unsigned long OledTimer = millis();
if (millis() - OledTimer >= 5000)
{
OledTimer=millis();
cDHT22();
valLight = analogRead(3); // 取光线Value
valSound = analogRead(0); // 取声音Value
digitalWrite(3, HIGH);// LED点亮
digitalWrite(9, HIGH);// 蜂鸣器鸣叫
Serial.println("");
myTempPM01= String(PM01Value); // 将int转换成String
myTempPM25= String(PM2_5Value);
myTempPM10= String(PM10Value);
myTempLight = String(valLight);
myTempSound = String(valSound);
Serial.println("PM01:" + myTempPM01 + "ug/m3, PM25:" + myTempPM25 + "ug/m3, PM10:" + myTempPM10 + "ug/m3");
Serial.println("Temperature:" + myTempTemp + "C, Humidity:" + myTempHumi + "%");
Serial.println("Light:" + myTempLight + ", Sound:" + myTempSound);
if (client.connect(server, 80)) // 提交的项目服务器80端口
{
Serial.println("Connected");
// HTTP请求,携带7个参数
client.println("POST http://116.236.162.186/servlet/mypm?unoVar01=" + myTempPM01 + "&unoVar02=" + myTempPM25 + "&unoVar03=" + myTempPM10 + "&unoVar04=" + myTempTemp + "&unoVar05=" + myTempHumi + "&unoVar06=" + myTempLight + "&unoVar07=" + myTempSound + " HTTP/1.1");
client.println("Host:116.236.162.186");
client.println();
}
else
{
Serial.println("connection failed");
}
Serial.println();
client.stop();
}
digitalWrite(3, LOW);
digitalWrite(9, LOW);
}
void cDHT22()
{
DHT22_ERROR_t errorCode;
errorCode = myDHT22.readData();
if (errorCode == DHT_ERROR_NONE)
{
myTempTemp = String(myDHT22.getTemperatureC());//取温度
myTempHumi = String(myDHT22.getHumidity());//取湿度
}
} 本帖最后由 kevinzhang 于 2015-12-21 14:12 编辑
MySQL数据库,mypm库t01表结构如下图:
本帖最后由 kevinzhang 于 2015-12-21 14:18 编辑
项目服务器验证代码(成为微信开发者前验证用,Java代码,文件名wxtest.java):
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;// 数据用来进行字符串排序
import org.apache.commons.codec.digest.DigestUtils;// 使用Apahce Commons Codec项目,完成SHA1加密
@WebServlet(urlPatterns = {"/wxtest"})
public class wxtest extends HttpServlet
{
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String myToken = "CO1drluxieGlUvoafl9THLawr2aspiAB";
String mySignature= request.getParameter("signature");// 抓取微信服务器送来的4个参数
String myTimestamp= request.getParameter("timestamp");
String myNonce = request.getParameter("nonce");
String myEchostr = request.getParameter("echostr");
String encodeString = "";
String finalString= "";
if(mySignature==null||myTimestamp==null||myNonce==null||myEchostr==null)
{
System.out.println("There is at least one null in pararmeters.");
}
else
{
String[] myString = new String;
myString = myToken;
myString = myTimestamp;
myString = myNonce;
Arrays.sort(myString);// 通过数组,3个字符串按字典序排序
encodeString = myString + myString + myString;
finalString= DigestUtils.sha1Hex(encodeString);// 完成SHA1加密
}
if (mySignature.equals(finalString))// 加密后的字符串与微信传过来的signature字符串比较
{
System.out.println("same...");
out.print(myEchostr);// 两者相同,则证明请求来自微信服务器,原样返回Echostr字符串
out.close();
System.out.println("Sent ok ...");
}
else
{
System.out.println("different...");
}
}
}
只需一次,通过验证后的公众号不需要再次验证。 服务器端,监听终端设备数据并写入数据库,代码如下:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// MySQL connection package
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
@WebServlet(urlPatterns = {"/mypm"})
public class mypm extends HttpServlet
{
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String myPm01 = request.getParameter("unoVar01");// 抓取7个参数
String myPm25 = request.getParameter("unoVar02");
String myPm10 = request.getParameter("unoVar03");
String myTemp = request.getParameter("unoVar04");
String myHumi = request.getParameter("unoVar05");
String myLight = request.getParameter("unoVar06");
String mySound = request.getParameter("unoVar07");
Connection conn = null;
Statement stmt = null;
ResultSet rs1 = null;
int i;
String mySQL = "INSERT INTO t01 (tpm01, tpm25, tpm10, ttemp, thumi, tlight, tsound) VALUES('" +
myPm01 + "','" +
myPm25 + "','" +
myPm10 + "','" +
myTemp + "','" +
myHumi + "','" +
myLight + "','" +
mySound + "')";
try
{
conn = DriverManager.getConnection("jdbc:mysql://localhost/mypm?" +
"user=root&password=15186okia");
stmt = conn.createStatement();
i = stmt.executeUpdate(mySQL);// 写入数据表
System.out.println("inserting...");
}
catch (SQLException ex)
{
System.out.println("Error in connection: " + ex.toString());
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
System.out.println("Written...");
System.out.println("PM 1: " + myPm01);
System.out.println("PM2.5:" + myPm25);
System.out.println("PM10: " + myPm10);
System.out.println("Temperature:" + myTemp + "C");
System.out.println("Humidity: " + myHumi + "%");
System.out.println("Light: " + myLight);
System.out.println("Sound: " + mySound);
System.out.println("==");
}
}
注意XML格式:
<xml>
<ToUserName><!]></ToUserName>
<FromUserName><!]></FromUserName>
<CreateTime><!]></CreateTime>
<MsgType><!]></MsgType>
<Content><!]></Content>
</xml> 项目服务器回复微信服务器的查询(Java,即用户通过微信查询终端数据):
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.dom4j.*;
import org.dom4j.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
@WebServlet(urlPatterns = {"/wxtest"})
public class wxtest extends HttpServlet
{
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String myVal01 = ""; //7个变量对应7个参数
String myVal02 = "";
String myVal03 = "";
String myVal04 = "";
String myVal05 = "";
String myVal06 = "";
String myVal07 = "";
Connection conn = null;// 涉及数据库打交道的变量
Statement stmt = null;
ResultSet rs1 = null;
int i = 0;
String mySQL = "SELECT * FROM t01 ORDER BY tid DESC LIMIT 1;"; // 从数据表里读取最后那条记录的SQL语句
try
{
conn = DriverManager.getConnection("jdbc:mysql://localhost/mypm?" +
"user=root&password=15186okia");
stmt = conn.createStatement();
rs1 = stmt.executeQuery(mySQL);
while(rs1.next())
{
myVal01 = rs1.getString(2); //分别将获得的数据写入7个变量
myVal02 = rs1.getString(3);
myVal03 = rs1.getString(4);
myVal04 = rs1.getString(5);
myVal05 = rs1.getString(6);
myVal06 = rs1.getString(7);
myVal07 = rs1.getString(8);
}
}
catch (SQLException ex)
{
System.out.println("Error in connection: " + ex.toString());
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
InputStreampostIn = request.getInputStream(); //从输入流获取微信服务器传过来的整个字符串
try
{
SAXReader reader = new SAXReader();
Document myDocument = reader.read(postIn); // 转成dom4j可以处理的格式
Element root = myDocument.getRootElement(); // 从XML字符串内获取全部元素,组成一棵树
Element myToUserName = root.element("ToUserName"); // 分别获取需要的值
Element myFromUserName = root.element("FromUserName");
Element myCreateTime = root.element("CreateTime");
Element myMsgType = root.element("MsgType");
Element myContent = root.element("Content");
Element myMsgId = root.element("MsgId");
String sToUserName = myToUserName.getText(); // 转成String类型
String sFromUserName = myFromUserName.getText();
String sCreateTime = myCreateTime.getText();
String sMsgType = myMsgType.getText();
String sContent = myContent.getText();
String sMsgId = myMsgId.getText();
if (sMsgType.equals("text") && sContent.equals("/??")) // 用户发来的是文本消息且是查询数据关键词吗?
{
long lCreateTime = System.currentTimeMillis()/1000L; // 消息创建的时间
String mySendContent = "";
// 以下手工封装回复文本消息的XML字符串
mySendContent = "PM1:" + myVal01 + "ug/m3\nPM2.5:" + myVal02 + "ug/m3\nPM10:" + myVal03 + "ug/m3\n温度:" + myVal04 +
"℃\n湿度:" + myVal05 + "%\n亮度:" + myVal06 + "\n噪声:" + myVal07;
String xmlString01 = "<xml>";
String xmlString02 = "<ToUserName><!]></ToUserName>";
String xmlString03 = "<FromUserName><!]></FromUserName>";
String xmlString04 = "<CreateTime><!]></CreateTime>";
String xmlString05 = "<MsgType><!]></MsgType>";
String xmlString06 = "<Content><!]></Content>";
String xmlString07 = "</xml>";
String xmlAll = xmlString01 + xmlString02 + xmlString03 + xmlString04 + xmlString05 + xmlString06
+ xmlString07;
System.out.println(xmlAll);
out.print(xmlAll); // 回复给微信服务器,由其转发给用户手机
out.close();
}
System.out.println("== Done ==");
}
catch (DocumentException ex)
{
System.out.println("dom4j Document: " + ex.toString());
}
} 这个看着不错,微信现在很流行。 有个公网IP不错:lol mikeliujia 发表于 2015-12-21 21:35 static/image/common/back.gif
有个公网IP不错
现在管得严,不容易搞到。 公众号的回调和传感器数据的存储都可以在arduino 上实现 davidce 发表于 2015-12-21 22:31 static/image/common/back.gif
公众号的回调和传感器数据的存储都可以在arduino 上实现
Uno内存小,有点悬,也没法扩展,外部访问困难 求问楼主用的传感器都哪写啊。
温度用ds18B20?
一个湿度传感器
一个co2传感器
一个激光pm2.5传感器(攀藤G3?)
还有啥?
另外底板是在哪里可以买到呢? yzhkpli 发表于 2015-12-26 17:11 static/image/common/back.gif
求问楼主用的传感器都哪写啊。
温度用ds18B20?
1, DFRduino UNO控制器(78元)
2. DFRobot Ethernet W5100网络板(98元)
3. IO扩展板 V7.1(55元)
4. DHT22温湿度传感器模块(65元)
5.MIC声音传感器(40元)
6.LX1972光传感器(30元)
7.数字蜂鸣器模块(15元)
8.食人鱼LED(10元)
9.PM2.5激光粉尘传感器(215元)
我特懒,这些都在DFrobot买的,其他店里兼容板子都可以完成同样的功能。
页:
[1]
2