- 项目背景
目前,科学技术飞速发展,其渗透到各个行业和生活的方方面面,室内设计与高科技相结合的智能家居应运而生。所谓智能家居,就是以生活场所为平台,利用物联网、传感器和智能控制技术,将各种家用电器连接起来,实现居住环境的智能化、自动化和人性化。通过语音操控、远程操控、预约操控、个性化设计、一键操控等功能,进一步提升生活的舒适性、便捷性和安全性。
[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.
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 温湿度模块实物图如下图所示。
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; //端口号
2、数据如何发送给onenet
这里我们需要查阅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、微信开发者工具
自己创建一个项目,直接替换index.js,index.wxml,index.wxss
index.js
// index.js
// 获取应用实例
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') // 如需尝试获取用户信息可改为false
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad() {
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
getUserInfo(e) {
// 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
console.log(e)
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
points:function(e) {
var that = this
wx.request({
//设备ID
//api-key
url: 'http://api.heclouds.com/devices/xxxxxxxxxx/datapoints?', //xxxxxxxxxx这里填写你的设备id
header:{
"api-key":"5oXSCXaNrBBlsQm6YNWU3wtHu1U=" //这里写你的api-key
},
data:{
limit:1
},
method :"GET",
//获取成功
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, //这里的shidu要跟wxml{{shidu}} 名字相同
})
}
})
},
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',
//*号这里写你设备id//设备ID//api-key
header:{
'content-type':'application/json',
"api-key":"5oXSCXaNrQm6YNWU3wtHu1U=" //这里写你的api-key
},
method :"POST",
data:pafload,//数据1是为灯开
success(res){
console.log("控制成功,已开灯")
console.log(res)
console.log(res.data);
}
})
},
/**
* 生命周期函数--监听页面加载 */
onLoad: function (options) {
this.points() //这个是我获取onenet数据的函数
var that=this
setInterval(function(){
that.points();
},3000 //这里我设置3秒刷新一次
)
},
})
index.wxml
<!--pages/index/index.wxml-->
<view class="content">
<view class="zm">
<text class="zm1">照明开关</text>
<switch class="kai" id="1" bindchange="openled">
</switch></view>
<view style="flex:1;width:100%">
<label class="xia">
<text class="zm1">当前温度:{{wendu}}°C</text>
</label>
</view>
<view style="flex:1;width:100%">
<label class="xia">
<text class="zm1">当前湿度:{{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 ;/** 设置超出内容隐藏 */
white-space:nowrap; /*设置超出不换行 */
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;/*父元素位置要设置为相对*/
}
.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; /* 要约束所在位置的子元素的位置要设置成绝对 */
left: 30rpx; /* 靠右调节 */
}
.radio{
display:inline-block; /* 横向布局*/
}
.kai{
position: absolute; /* 要约束所在位置的子元素的位置要设置成绝对 */
right: 100rpx; /* 靠右调节 */
}
.mos{
left: 120rpx; /* 靠右调节 */
height: 200rpx;
}
微信小程序链接
百度网盘
Original: https://blog.csdn.net/qq_56395983/article/details/125364455
Author: 梦露晨曦695
Title: 基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/524930/
转载文章受原作者版权保护。转载请注明原作者出处!