极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24214|回复: 18

PM2.5采集器(支持微信查询)

[复制链接]
发表于 2015-12-21 13:50:51 | 显示全部楼层 |阅读模式
本帖最后由 kevinzhang 于 2015-12-21 14:01 编辑

该终端设备采集办公室空气质量(包括:PM1、PM2.5、PM10)、温湿度、照明和噪声,并可通过微信公众号实时查询7个数据。

终端设备如下图:


微信查询结果如下图:


拓扑结构图如下图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2015-12-21 14:03:54 | 显示全部楼层
终端设备细节如下图:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 14:06:55 | 显示全部楼层
Arduino Uno代码如下:

  1. #include "Arduino.h"
  2. #include "serialReadPMValue.h"
  3. #include <DHT22.h>
  4. #include <stdio.h>
  5. #include <SPI.h>
  6. #include <Ethernet.h>

  7. // 数字PIN 3 --> LED 红
  8. // 数字PIN 7 --> DHT22温湿度
  9. // 数字PIN 9 --> 蜂鸣器
  10. // 模拟PIN 0 --> 模拟声音
  11. // 模拟PIN 3 --> LX1972环境光

  12. uint16_t PM01Value  = 0;  // PM1.0
  13. uint16_t PM2_5Value = 0;  // PM2.5
  14. uint16_t PM10Value  = 0;  // PM10
  15. #define receiveDatIndex 32
  16. uint8_t receiveDat[receiveDatIndex];

  17. #define DHT22_PIN 7
  18. DHT22 myDHT22(DHT22_PIN);

  19. int valLight = 0;  // 光线Value
  20. int valSound = 0;  // 声音Value

  21. byte mac[]     = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
  22. IPAddress server(116, 236, 162, 186);   // 项目服务器公网IP
  23. IPAddress      ip(192, 168, 1, 76);   // 内网IP(该终端设备的内网IP)
  24. EthernetClient client;

  25. String myTempPM01  = "";
  26. String myTempPM25  = "";
  27. String myTempPM10  = "";
  28. String myTempLight = "";
  29. String myTempSound = "";
  30. String myTempTemp  = "";
  31. String myTempHumi  = "";

  32. void setup()
  33. {
  34.   Serial.begin(9600);
  35.   Ethernet.begin(mac, ip);
  36.   pinMode(3, OUTPUT);
  37.   pinMode(9, OUTPUT);
  38. }

  39. void loop()
  40. {
  41.   int length   = serialRead(Serial, receiveDat, receiveDatIndex, 5);
  42.   int checkSum = checkValue(receiveDat, receiveDatIndex);
  43.   if(length&&checkSum)
  44.   {
  45.     PM01Value  = transmitPM01(receiveDat);   //取PM1.0
  46.     PM2_5Value = transmitPM2_5(receiveDat);  //取PM2.5
  47.     PM10Value  = transmitPM10(receiveDat);   //取PM10
  48.   }
  49.   static unsigned long OledTimer = millis();
  50.   if (millis() - OledTimer >= 5000)
  51.   {
  52.     OledTimer=millis();
  53.    
  54.     cDHT22();
  55.    
  56.     valLight = analogRead(3);   // 取光线Value
  57.     valSound = analogRead(0);   // 取声音Value
  58.    
  59.     digitalWrite(3, HIGH);  // LED点亮
  60.     digitalWrite(9, HIGH);  // 蜂鸣器鸣叫
  61.     Serial.println("");

  62.     myTempPM01  = String(PM01Value);   // 将int转换成String
  63.     myTempPM25  = String(PM2_5Value);
  64.     myTempPM10  = String(PM10Value);
  65.     myTempLight = String(valLight);
  66.     myTempSound = String(valSound);
  67.    
  68.     Serial.println("PM01:" + myTempPM01 + "ug/m3, PM25:" + myTempPM25 + "ug/m3, PM10:" + myTempPM10 + "ug/m3");
  69.     Serial.println("Temperature:" + myTempTemp + "C, Humidity:" + myTempHumi + "%");
  70.     Serial.println("Light:" + myTempLight + ", Sound:" + myTempSound);
  71.    
  72.     if (client.connect(server, 80))   // 提交的项目服务器80端口
  73.     {
  74.       Serial.println("Connected");
  75.       // HTTP请求,携带7个参数
  76.       client.println("POST [url]http://116.236.162.186/servlet/mypm?unoVar01=[/url]" + myTempPM01 + "&unoVar02=" + myTempPM25 + "&unoVar03=" + myTempPM10 + "&unoVar04=" + myTempTemp + "&unoVar05=" + myTempHumi + "&unoVar06=" + myTempLight + "&unoVar07=" + myTempSound + " HTTP/1.1");
  77.       client.println("Host:116.236.162.186");
  78.       client.println();
  79.     }
  80.     else
  81.     {
  82.       Serial.println("connection failed");
  83.     }
  84.     Serial.println();
  85.     client.stop();
  86.   }
  87.   
  88.   digitalWrite(3, LOW);
  89.   digitalWrite(9, LOW);
  90. }

  91. void cDHT22()
  92. {
  93.     DHT22_ERROR_t errorCode;
  94.     errorCode = myDHT22.readData();
  95.     if (errorCode == DHT_ERROR_NONE)
  96.     {
  97.       myTempTemp = String(myDHT22.getTemperatureC());  //取温度
  98.       myTempHumi = String(myDHT22.getHumidity());  //取湿度
  99.    }
  100. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 14:11:09 | 显示全部楼层
本帖最后由 kevinzhang 于 2015-12-21 14:12 编辑

MySQL数据库,mypm库t01表结构如下图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 14:15:20 | 显示全部楼层
本帖最后由 kevinzhang 于 2015-12-21 14:18 编辑

项目服务器验证代码(成为微信开发者前验证用,Java代码,文件名wxtest.java):

[pre lang="java" line="1"]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[3];
            myString[0] = myToken;
            myString[1] = myTimestamp;
            myString[2] = myNonce;
            
            Arrays.sort(myString);  // 通过数组,3个字符串按字典序排序
            encodeString = myString[0] + myString[1] + myString[2];
            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...");
        }
    }
}[/code]

只需一次,通过验证后的公众号不需要再次验证。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 14:21:00 | 显示全部楼层
服务器端,监听终端设备数据并写入数据库,代码如下:

[pre lang="java" line="1"]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("==");
    }
}[/code]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 14:24:13 | 显示全部楼层
注意XML格式:

[pre lang="xml" line="1"]    <xml>
      <ToUserName><![CDATA[o4v_mtz6brovlFn77_HpgV_0Q39I]]></ToUserName>
      <FromUserName><![CDATA[gh_9b78ebc75c88]]></FromUserName>
      <CreateTime><![CDATA[1449493779]]></CreateTime>
      <MsgType><![CDATA[text]]></MsgType>
      <Content><![CDATA[PM1:20ug/m3\nPM2.5:24ug/m3\nPM10:27ug/m3\n温度:23.80℃\n湿度:33.70%\n亮度:0\n噪声:0]]></Content>
    </xml>[/code]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 14:27:51 | 显示全部楼层
项目服务器回复微信服务器的查询(Java,即用户通过微信查询终端数据):

[pre lang="Java" line="1"]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());
        }
        
        InputStream  postIn = 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><![CDATA[" + sFromUserName + "]]></ToUserName>";
                String xmlString03 = "<FromUserName><![CDATA[" + sToUserName + "]]></FromUserName>";
                String xmlString04 = "<CreateTime><![CDATA[" + lCreateTime + "]]></CreateTime>";
                String xmlString05 = "<MsgType><![CDATA[text]]></MsgType>";
                String xmlString06 = "<Content><![CDATA[" + mySendContent + "]]></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());
        }
}[/code]
回复 支持 反对

使用道具 举报

发表于 2015-12-21 14:41:17 | 显示全部楼层
这个看着不错,微信现在很流行。
回复 支持 反对

使用道具 举报

发表于 2015-12-21 21:35:18 | 显示全部楼层
有个公网IP不错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-21 21:53:54 | 显示全部楼层
mikeliujia 发表于 2015-12-21 21:35
有个公网IP不错

现在管得严,不容易搞到。
回复 支持 反对

使用道具 举报

发表于 2015-12-21 22:31:35 | 显示全部楼层
公众号的回调和传感器数据的存储都可以在arduino 上实现
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-22 06:59:47 | 显示全部楼层
davidce 发表于 2015-12-21 22:31
公众号的回调和传感器数据的存储都可以在arduino 上实现


Uno内存小,有点悬,也没法扩展,外部访问困难
回复 支持 反对

使用道具 举报

发表于 2015-12-26 17:11:29 | 显示全部楼层
求问楼主用的传感器都哪写啊。
温度用ds18B20?

一个湿度传感器
一个co2传感器
一个激光pm2.5传感器(攀藤G3?)
还有啥?
另外底板是在哪里可以买到呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-27 18:17:16 | 显示全部楼层
yzhkpli 发表于 2015-12-26 17:11
求问楼主用的传感器都哪写啊。
温度用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买的,其他店里兼容板子都可以完成同样的功能。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 08:27 , Processed in 0.046738 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表