基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

  1. 项目背景

目前,科学技术飞速发展,其渗透到各个行业和生活的方方面面,室内设计与高科技相结合的智能家居应运而生。所谓智能家居,就是以生活场所为平台,利用物联网、传感器和智能控制技术,将各种家用电器连接起来,实现居住环境的智能化、自动化和人性化。通过语音操控、远程操控、预约操控、个性化设计、一键操控等功能,进一步提升生活的舒适性、便捷性和安全性。

[En]

At present, the rapid development of science and technology, its penetration into a variety of industries and all aspects of life, interior design and high-tech combination of the emergence of “smart home”. The so-called smart home is to take the living place as the platform, using the Internet of things, sensors and intelligent control technology to connect all kinds of household appliances to realize the intelligence, automation and humanization of the living environment. Through voice control, remote control, reservation control, personalized design, one-button control and other functions to further improve the comfort, convenience and security of life.

2.设计目标

本系统主要分为三大模块,分别为传感器监测模块,自动报警模块和远程控制模块。传感器监测模块包括对环境的温湿度和空气质量监测,用户可以在微信小程序上查看到实时传感数据;自动报警模块是当传感数据超过设置的阈值时会进行报警,提醒用户注意火灾的发生;远程控制模块可以通过微信小程序远程控制LED灯,风扇和加湿器的开关,实现了不在家也能远程控制家里的电器的开关。

3.设备端 硬件设计

3.1硬件总体设计

整体硬件框架如下图所示。

[En]

The overall hardware framework is shown in the following figure.

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

3.2单片机选型及传感器选型

3.2.1 ESP32模块

SP32-WROOM-32 是一款通用型Wi-Fi+BT+BLE+MCU的模组,功能强大,用途广泛,可以用于低功耗传感器网络和要求极高的任务,例如语音编码、音频流和MP3解码等。ESP32还集成了丰富的外设,包括电容式触摸传感器、霍尔传感器、低噪声传感放大器,SD卡接口、以太网接口、高速SDIO/SPI、UART、I2S 和I2C等。

3.2.2 温湿度模块

本系统采集环境的温湿度选择 DHT11 温湿度传感器。DHT11 数字温湿度传感器采 用的是已校准数字信号输出,它能够同时检测温度和湿度,它使用专用的数字模块采集 技术和温湿度传感技术,能够确保产品的高可靠性与稳定性。 该传感器包括一个电阻式感湿元件和一个 NTC 测温元件,利用元件的电气特性随 温湿度的变化测量出环境的温湿度,元件与一个高性能 8 位单片机相连接。该产品具有 高品质、响应快、抗干扰强、性价比高等优点。低功耗与非常小的体积使得它能够被应 用于各种复杂的场景。DHT11 为 4 针单排引脚封装,连接方便。DHT11 温湿度模块实物图如下图所示。

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

4.直接上代码

4.1.1、设备怎么连上网

#include

const char* ssid     = "baby"; //wifi名称
const char* password = "13456789";//wifi密码

void setupWifi(){
 delay(10);
  Serial.println("连接WIFI");
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("OK");
  Serial.println("Wifi连接成功");
}

4.1.2、MQTT接入地址

1、mqtt协议的接口端号是6002,而mqtts协议的接口端号是1883

const char *mqtt_server = "183.230.40.96"; //onenet 的 IP地址
const int port = 6002;                     //端口号

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

2、数据如何发送给onenet

这里我们需要查阅onenet的相关文档

OneNET – 中国移动物联网开放平台

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令
#define mqtt_devid "945965335" //设备ID
#define mqtt_pubid "577632"        //产品ID
//鉴权信息
#define mqtt_password "123456" //鉴权信息
char msg_buf[200];               //发送信息缓冲区
char msgJson[75]; //要发送的json格式的数据
unsigned short json_len = 0;                      //json长度
//信息模板
char dataTemplate[] = "{\"temp\":%.2f,\"humi\":%.2f,\"led\":%d}";  //  temp humi led要与onenet相对应
void sendTempAndHumi()
{
  if (client.connected())
  {
    //dht.readHumidity()
    snprintf(msgJson,75,dataTemplate,dht.readTemperature(),dht.readHumidity(),god);
    json_len = strlen(msgJson);                   //msgJson的长度
    msg_buf[0] = char(0x03);                       //要发送的数据必须按照ONENET的要求发送, 根据要求,数据第一位是3
    msg_buf[1] = char(json_len >> 8);              //数据第二位是要发送的数据长度的高八位
    msg_buf[2] = char(json_len & 0xff);            //数据第三位是要发送数据的长度的低八位
    memcpy(msg_buf + 3, msgJson, strlen(msgJson)); //从msg_buf的第四位开始,放入要传的数据msgJson
    msg_buf[3 + strlen(msgJson)] = 0;              //添加一个0作为最后一位, 这样要发送的msg_buf准备好了

    Serial.print("public the data:");
    Serial.print(msgJson);
    client.publish("$dp", (uint8_t *)msg_buf, 3+strlen(msgJson));
    //发送数据到主题
    delay(500);

  }
}

在setup()函数中定义了每5秒发一次信息到OneNET平台

 tim1.attach(5, sendTempAndHumi);                            //定时每5秒调用一次发送数据函数sendTempAndHumi

3、在 setup()函数订阅命令下发主题

  client.setCallback(callback); //订阅命令下发主题
//收到主题下发的回调, 注意这个回调要实现三个形参 1:topic 主题, 2: payload: 传递过来的信息 3: length: 长度
void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '0') {
    digitalWrite(led, LOW);   //
    god=0;
  } if ((char)payload[0] == '1') {
    digitalWrite(led, HIGH);  //
    god=1;
  }
  else{}

}

4.1.3、测温湿度

使用DHT11模块,调用库

#include "DHT.h"

定义DHT11,数据引脚我接在IO13口

#define DHTPIN 13     // io13
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);

5、总代码(当然了这个是新手必备,只需要一个DHT11和一个LED灯就可以实现的)

#include
#include "DHT.h"
#include "PubSubClient.h"
#include "Ticker.h"
#define DHTPIN 13
#define DHTTYPE DHT11   // DHT 11
#define led 18 //灯的接口
DHT dht(DHTPIN, DHTTYPE);
int god=0;

const char *ssid     = "baby"; //wifi名称
const char *password = "12345671";//wifi密码
const char *mqtt_server = "183.230.40.96"; //onenet 的 IP地址
const int port = 6002;                     //端口号
#define mqtt_devid "999999735" //设备ID
#define mqtt_pubid "599995"        //产品ID
//鉴权信息
#define mqtt_password "123456" //鉴权信息
WiFiClient espClient;           //创建一个WIFI连接客户端
PubSubClient client(espClient); // 创建一个PubSub客户端, 传入创建的WIFI客户端
char msg_buf[200];               //发送信息缓冲区
char msgJson[75]; //要发送的json格式的数据
unsigned short json_len = 0;                      //json长度
//信息模板
char dataTemplate[] = "{\"temp\":%.2f,\"humi\":%.2f,\"led\":%d}";  //  temp humi要与onenet相对应
Ticker tim1; //定时器,用来循环上传数据

//连接WIFI
void setupWifi(){
 delay(10);
  Serial.println("连接WIFI");
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("OK");
  Serial.println("Wifi连接成功");
}

void setup() {

  Serial.begin(115200);
  pinMode(led,OUTPUT);//输出
  setupWifi();   //调用函数连接WIFI
  Serial.print(F("DHT11 test!"));
  dht.begin();
  client.setServer(mqtt_server, port);                   //设置客户端连接的服务器,连接Onenet服务器, 使用6002端口
  client.connect(mqtt_devid, mqtt_pubid, mqtt_password); //客户端连接到指定的产品的指定设备.同时输入鉴权信息
  if (client.connected())
  {
    Serial.print("OneNet is connected!");//判断以下是不是连好了.

  }
  //client.setCallback(callback);                                //设置好客户端收到信息是的回调
  client.setCallback(callback); //订阅命令下发主题
  tim1.attach(5, sendTempAndHumi);                            //定时每5秒调用一次发送数据函数sendTempAndHumi

}

void loop() {
delay(5000);
float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!\n"));
    return;
  }
  //可以让我们通过串口查看数据
  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("℃  \n "));

  if (!WiFi.isConnected()) //先看WIFI是否还在连接
  {
    setupWifi();
  }
  if (!client.connected()) //如果客户端没连接ONENET, 重新连接
  {
    clientReconnect();
    delay(100);
  }
  client.loop(); //客户端循环检测

}

void sendTempAndHumi()
{
  if (client.connected())
  {
    //dht.readHumidity()
    snprintf(msgJson,75,dataTemplate,dht.readTemperature(),dht.readHumidity(),god);
    json_len = strlen(msgJson);                   //msgJson的长度
    msg_buf[0] = char(0x03);                       //要发送的数据必须按照ONENET的要求发送, 根据要求,数据第一位是3
    msg_buf[1] = char(json_len >> 8);              //数据第二位是要发送的数据长度的高八位
    msg_buf[2] = char(json_len & 0xff);            //数据第三位是要发送数据的长度的低八位
    memcpy(msg_buf + 3, msgJson, strlen(msgJson)); //从msg_buf的第四位开始,放入要传的数据msgJson
    msg_buf[3 + strlen(msgJson)] = 0;              //添加一个0作为最后一位, 这样要发送的msg_buf准备好了

    Serial.print("public the data:");
    Serial.print(msgJson);
    client.publish("$dp", (uint8_t *)msg_buf, 3+strlen(msgJson));
    //发送数据到主题
    delay(500);

  }
}

//收到主题下发的回调, 注意这个回调要实现三个形参 1:topic 主题, 2: payload: 传递过来的信息 3: length: 长度
void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '0') {
    digitalWrite(led, LOW);   //
    god=0;
  } if ((char)payload[0] == '1') {
    digitalWrite(led, HIGH);  //
    god=1;
  }
  else{}

}

void clientReconnect()
{
  while (!client.connected()) //再重连客户端
  {
    Serial.print("reconnect MQTT...");
   if (client.connect(mqtt_devid, mqtt_pubid, mqtt_password))
    {
      Serial.print("connected");
    }
    else
    {
      Serial.print("failed");
      Serial.print(client.state());
      Serial.print("try again in 5 sec");
     delay(5000);
    }
  }
}

6、微信开发者工具

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

自己创建一个项目,直接替换index.js,index.wxml,index.wxss

index.js

// index.js
// &#x83B7;&#x53D6;&#x5E94;&#x7528;&#x5B9E;&#x4F8B;
const app = getApp()
const mqtt=require('../../utils/mqtt')
Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo'),
    canIUseGetUserProfile: false,
    canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // &#x5982;&#x9700;&#x5C1D;&#x8BD5;&#x83B7;&#x53D6;&#x7528;&#x6237;&#x4FE1;&#x606F;&#x53EF;&#x6539;&#x4E3A;false
  },
  // &#x4E8B;&#x4EF6;&#x5904;&#x7406;&#x51FD;&#x6570;
  bindViewTap() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad() {
    if (wx.getUserProfile) {
      this.setData({
        canIUseGetUserProfile: true
      })
    }
  },
  getUserProfile(e) {
    // &#x63A8;&#x8350;&#x4F7F;&#x7528;wx.getUserProfile&#x83B7;&#x53D6;&#x7528;&#x6237;&#x4FE1;&#x606F;&#xFF0C;&#x5F00;&#x53D1;&#x8005;&#x6BCF;&#x6B21;&#x901A;&#x8FC7;&#x8BE5;&#x63A5;&#x53E3;&#x83B7;&#x53D6;&#x7528;&#x6237;&#x4E2A;&#x4EBA;&#x4FE1;&#x606F;&#x5747;&#x9700;&#x7528;&#x6237;&#x786E;&#x8BA4;&#xFF0C;&#x5F00;&#x53D1;&#x8005;&#x59A5;&#x5584;&#x4FDD;&#x7BA1;&#x7528;&#x6237;&#x5FEB;&#x901F;&#x586B;&#x5199;&#x7684;&#x5934;&#x50CF;&#x6635;&#x79F0;&#xFF0C;&#x907F;&#x514D;&#x91CD;&#x590D;&#x5F39;&#x7A97;
    wx.getUserProfile({
      desc: '&#x5C55;&#x793A;&#x7528;&#x6237;&#x4FE1;&#x606F;', // &#x58F0;&#x660E;&#x83B7;&#x53D6;&#x7528;&#x6237;&#x4E2A;&#x4EBA;&#x4FE1;&#x606F;&#x540E;&#x7684;&#x7528;&#x9014;&#xFF0C;&#x540E;&#x7EED;&#x4F1A;&#x5C55;&#x793A;&#x5728;&#x5F39;&#x7A97;&#x4E2D;&#xFF0C;&#x8BF7;&#x8C28;&#x614E;&#x586B;&#x5199;
      success: (res) => {
        console.log(res)
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    })
  },
  getUserInfo(e) {
    // &#x4E0D;&#x63A8;&#x8350;&#x4F7F;&#x7528;getUserInfo&#x83B7;&#x53D6;&#x7528;&#x6237;&#x4FE1;&#x606F;&#xFF0C;&#x9884;&#x8BA1;&#x81EA;2021&#x5E74;4&#x6708;13&#x65E5;&#x8D77;&#xFF0C;getUserInfo&#x5C06;&#x4E0D;&#x518D;&#x5F39;&#x51FA;&#x5F39;&#x7A97;&#xFF0C;&#x5E76;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x533F;&#x540D;&#x7684;&#x7528;&#x6237;&#x4E2A;&#x4EBA;&#x4FE1;&#x606F;
    console.log(e)
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  },
  points:function(e) {
    var that = this
    wx.request({
       //&#x8BBE;&#x5907;ID
      //api-key
      url: 'http://api.heclouds.com/devices/xxxxxxxxxx/datapoints?', //xxxxxxxxxx&#x8FD9;&#x91CC;&#x586B;&#x5199;&#x4F60;&#x7684;&#x8BBE;&#x5907;id
      header:{
        "api-key":"5oXSCXaNrBBlsQm6YNWU3wtHu1U="  //&#x8FD9;&#x91CC;&#x5199;&#x4F60;&#x7684;api-key
      },
      data:{
        limit:1
      },
      method :"GET",
       //&#x83B7;&#x53D6;&#x6210;&#x529F;
      success:function(res){
       that.setData({
         light:res.data.data.datastreams[0].datapoints[0].value,
         wendu:res.data.data.datastreams[1].datapoints[0].value,
         shidu:res.data.data.datastreams[3].datapoints[0].value, //&#x8FD9;&#x91CC;&#x7684;shidu&#x8981;&#x8DDF;wxml{{shidu}} &#x540D;&#x5B57;&#x76F8;&#x540C;

       })
      }
    })
  },

  openled:function(e){
    let pafload
    if(e.detail.value==true)
    pafload = 1
    else
    pafload =0
    console.log(pafload)
    wx.request({
      url: 'http://api.heclouds.com/cmds?device_id=xxxxxxxxxx',
      //*&#x53F7;&#x8FD9;&#x91CC;&#x5199;&#x4F60;&#x8BBE;&#x5907;id//&#x8BBE;&#x5907;ID//api-key
      header:{
        'content-type':'application/json',
        "api-key":"5oXSCXaNrQm6YNWU3wtHu1U="  //&#x8FD9;&#x91CC;&#x5199;&#x4F60;&#x7684;api-key
      },
      method :"POST",
       data:pafload,//&#x6570;&#x636E;1&#x662F;&#x4E3A;&#x706F;&#x5F00;
       success(res){
         console.log("&#x63A7;&#x5236;&#x6210;&#x529F;,&#x5DF2;&#x5F00;&#x706F;")
        console.log(res)
        console.log(res.data);
      }
    })
  },
    /**
* &#x751F;&#x547D;&#x5468;&#x671F;&#x51FD;&#x6570;--&#x76D1;&#x542C;&#x9875;&#x9762;&#x52A0;&#x8F7D; */
  onLoad: function (options) {
    this.points()  //&#x8FD9;&#x4E2A;&#x662F;&#x6211;&#x83B7;&#x53D6;onenet&#x6570;&#x636E;&#x7684;&#x51FD;&#x6570;
    var that=this
    setInterval(function(){
      that.points();
    },3000   //&#x8FD9;&#x91CC;&#x6211;&#x8BBE;&#x7F6E;3&#x79D2;&#x5237;&#x65B0;&#x4E00;&#x6B21;
    )
  },
})

index.wxml

<!--pages/index/index.wxml-->
<view class="content">
    <view class="zm">
    <text class="zm1">&#x7167;&#x660E;&#x5F00;&#x5173;</text>
    <switch class="kai" id="1" bindchange="openled">
    </switch></view>
     <view style="flex:1;width:100%">
       <label class="xia">
       <text class="zm1">&#x5F53;&#x524D;&#x6E29;&#x5EA6;&#xFF1A;{{wendu}}&#xB0;C</text>
       </label>
     </view>
     <view style="flex:1;width:100%">
     <label class="xia">
      <text class="zm1">&#x5F53;&#x524D;&#x6E7F;&#x5EA6;&#xFF1A;{{shidu}} %</text>
     </label>
     </view>
  </view>

index.wxss

/* pages/index/index.wxss */
page {
  background: #f6f6f6;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
.headTitle{
   width: 100%;
   height: 80rpx;
   background-color: #ffffff;
   overflow:hidden  ;/** &#x8BBE;&#x7F6E;&#x8D85;&#x51FA;&#x5185;&#x5BB9;&#x9690;&#x85CF; */
   white-space:nowrap;   /*&#x8BBE;&#x7F6E;&#x8D85;&#x51FA;&#x4E0D;&#x6362;&#x884C; */
   border-bottom :1px solid #F3F3F3;
}
.headTitle .titleItem{
  display: inline-block;
  line-height:80rpx;
  color: #889999;
  font-size:34rpx;
  margin: 0 20rpx;
}
.headTitle .selctItem{
  color: #000000;
  font-weight: bold;
}
.itemView{
  width: 100%;
  height:180rpx;
  position: relative;
  border-bottom: 1px solid #F3F3F3;
}
.zm{
  margin-top: 20rpx;
  border:1px solid#ebe4e286;
  width:750rpx;
  height: 100rpx;
  border-radius: 5px;
  font-size: 36;
  font-weight: bold;
  line-height: 80rpx;
  color: #32d5e0;
  text-align: center;
  display: flex;
  position: relative;/*&#x7236;&#x5143;&#x7D20;&#x4F4D;&#x7F6E;&#x8981;&#x8BBE;&#x7F6E;&#x4E3A;&#x76F8;&#x5BF9;*/

}
.login-btn{
  width: 40%!important;
  background-color: #33ff33;
  color: white;
  font-weight: normal;
}
.content{
  margin-top: 20rpx;
  border:1px solid#ebe4e286;
  width:750rpx;
  height: 600rpx;
  border-radius: 5px;
  font-size: 36;
  font-weight: bold;
  line-height: 80rpx;
  color: #32d5e0;
  text-align: center;
  flex-direction: column;
  display: flex;

}
.xia{
  justify-content: space-between;
}
.zm1{
  position: absolute; /* &#x8981;&#x7EA6;&#x675F;&#x6240;&#x5728;&#x4F4D;&#x7F6E;&#x7684;&#x5B50;&#x5143;&#x7D20;&#x7684;&#x4F4D;&#x7F6E;&#x8981;&#x8BBE;&#x7F6E;&#x6210;&#x7EDD;&#x5BF9; */
  left: 30rpx; /* &#x9760;&#x53F3;&#x8C03;&#x8282; */
}
.radio{
  display:inline-block; /*  &#x6A2A;&#x5411;&#x5E03;&#x5C40;*/

}
.kai{

  position: absolute; /* &#x8981;&#x7EA6;&#x675F;&#x6240;&#x5728;&#x4F4D;&#x7F6E;&#x7684;&#x5B50;&#x5143;&#x7D20;&#x7684;&#x4F4D;&#x7F6E;&#x8981;&#x8BBE;&#x7F6E;&#x6210;&#x7EDD;&#x5BF9; */
  right: 100rpx; /* &#x9760;&#x53F3;&#x8C03;&#x8282; */

}
.mos{

  left: 120rpx; /* &#x9760;&#x53F3;&#x8C03;&#x8282; */
  height: 200rpx;
}

微信小程序链接

百度网盘

Original: https://blog.csdn.net/qq_56395983/article/details/125364455
Author: 梦露晨曦695
Title: 基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/524930/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球