温湿度监测与控制系统设计:基于ESP32与阿里云物联网的实现
文章目录
前言
这篇文章主要介绍了如何在Arduino环境下,使用ESP32接入阿里云物联网平台(http://www.aliyun.com),实现温湿度数据的实时更新和手机APP的远程控制。以下是我在开发过程中总结的具体步骤。主要参考这篇文章:链接:基于Arduino环境下ESP32接入阿里云
注:这里默认你们对MQTT协议和阿里云物联网平台有一定的了解,不了解的可以观看这个视频合集里面的前五个视频。https://www.bilibili.com/video/BV1oJ411176Q?spm_id_from=333.788.videopod.episodes&vd_source=44f96ba7e07ae350233601fdcdd9bcce
一、物联网平台配置
本章节主要讲述阿里云物联网平台的相关操作,具体流程及关系图如下图所示:
1.1功能定义
首先登录阿里云平台,没有账号的注册一个账号并实名认证;在产品目录下找到物联网,再找到生活物联网平台(飞燕平台)。
然后点击管理控制台→项目→创建新项目→前往开发→创建新产品,产品名称自定义,所属品类可以选择环境电器(温湿度传感器),节点类型选择网关,通讯方式选择蜂窝,芯片模组选择其他,其余设置默认。
创建完之后点击前往开发,在功能定义那一块可以选择用系统自带的,也可以选择自定义(个人建议使用自定义),使用自定义之前记得把系统自带的删除(避免标识符冲突,这个标识符在数据传输的过程中很重要,在后文会提及);在自定义栏目的那里点击“添加自定义功能”,根据自己实际需求填写,可参考下图,功能名称可以自定义,不用选择系统提示的,标识符也是自己定义,但要确保在同一产品下不能重复。
如果要创建诸如空调、加湿器等只有开、关两种状态的功能,建议数据类型选择bool。
1.2人机互动设置
功能定义完成之后,进入人机互动设置,选择云智能APP,点击保存。
产品展示界面的品牌随便选一个就行,产品型号自己起名字。
这里设备面板是指手机app的显示面板,可以选择模板,也可以点击创建模板,空白模板自己编辑。
在编辑过程中,诸如空调等可以控制的模块要选择“功能”栏下面的,只需要显示信息的模块在“信息”栏下面选择。例如下面的界面,如果在“功能”栏下面的温度拖到面板上,到时候在手机APP就会出现你可以自己手动调节显示温度的情况,所以一定要注意,编辑完之后保存,退出之后再次点击选择模板,选择自己编辑的模板 。
最后一步产品说明,随便上传一个PDF文档就可以。
1.3创建测试设备
人机交互设置完之后,点击设备调试,创建测试设备,自定义测试设备名之后便能得到平台颁布的设备参数信息。
二、环境配置
首先在platformIO创建一个新项目,并安装一下库Adafruit Unified Sensor库、DHT sensor library库、PubSubClient库和ArduinoJson库,ArduinoJson建议使用6.21.4版本。除此之外还需修改PubSubClient.h文件参数,将参数修改至如图所示,可以通过在mian.cpp文件下引入PubSubClient.h,右击“转到定义”找到文件。
一定要修改!
一定要修改!
一定要修改!
不然会连接失败。
三、代码实现
3.1参数查询
代码部分包含物联网连接与温湿度读取两块,在开始之前,需要知道设备三元组信息、MQTT连接参数和发布与订阅消息的topic;相关概念这里就不在赘述,接下来讲一下如何获取这些参数;首先打开阿里云的官网,在产品目录下找到物联网平台。
点击管理控制台,公共实例,设备管理,在设备目录下找到刚刚新增的设备。
上面的箭头指向的就是三元组信息,下面的箭头指向的就是MQTT连接参数。
订阅和发布消息的topic可以在产品→点击产品→Topic类列表→物模型通信Topic里查看,这里我直接给出代码。
发布消息的topic,Produckey和deviceName改成自己设备的Produckey和deviceName。
sys/ProductKey/${deviceName}/thing/event/property/post
订阅消息的topic,同上。
/sys/ProductKey/${deviceName}/thing/service/property/set
3.2物联网连接、温湿度数据读取、发送与消息接收
根据实际修改以下所有“*”部分的代码,代码中空调等设备可以根据自己的情况进行修改。
//引入头文件
#include <Arduino.h>
#include <WiFi.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
//设备三元组信息
#define Product_Key "****************"
#define Device_Name "****************"
#define DeviceS_ecret "****************"
//MQTT连接参数
#define MQTT_SERVER Product_Key ".iot-as-mqtt." Region_ID ".aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_USERNAME "************************"
#define CLIENT_ID "************************"
#define MQTT_PASSWORD "************************"
//发布和订阅消息用的topic
#define PubTopic "/sys/***********/*****/thing/event/property/post"
#define SubTopic "/sys/***********/*****/thing/service/property/set"
//温度监测
#define DHTPIN ** // DHT11 数据引脚连接的 GPIO
#define DHTTYPE DHT11 // 定义传感器型号,我这的是DHT11,需改为自己的传感器型号
//wifi信息
const char *ssid = "*****"; //wifi名称
const char *password = "*****"; //wifi密码
//设备控制引脚
#define air_pin * //空调GPIO引脚
#define humier_pin * //加湿器GPIO引脚
#define dehumi_pin * //除湿器GPIO引脚
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
以下的是发布消息的函数,这段代码中params[]里面的temp、humi就是前文提到的标识符,这里根据自己设置的标识符进行修改。
//发布消息
void pubMsg() {
// 创建一个足够大的StaticJsonDocument对象来存储预期的JSON数据
StaticJsonDocument<512> doc;
// 设置JSON数据
JsonObject params = doc.createNestedObject("params");
params["temp"] = dht.readTemperature();; // 温度
params["humi"] = dht.readHumidity(); // 湿度
params["air"] = digitalRead(air_pin); //空调状态
params["dehumi"] = digitalRead(dehumi_pin); //除湿器状态
params["humier"] = digitalRead(humier_pin); //加湿器状态
doc["method"] = "thing.event.property.post";
// 序列化JSON数据为字符串
char jsonOutput[512];
serializeJson(doc, jsonOutput);
// 使用修改后的pubMsg函数发送JSON字符串
if (client.publish(PubTopic, jsonOutput)) {
Serial.println("Publish success");
// 连接成功后订阅主题
client.subscribe(SubTopic);
} else {
Serial.println("Publish fail");
}
}
以下是接收消息的函数, 跟上文提及的一样,修改自己的标识符。
//接收消息
void processJsonMessage(char* message) {
StaticJsonDocument<512> doc; // 调整大小以适应您的需要
DeserializationError error = deserializeJson(doc, message);
bool airState = digitalRead(air_pin); // 空调的当前状态
bool humierState = digitalRead(humier_pin); // 加湿器的当前状态
bool dehumiState = digitalRead(dehumi_pin); // 除湿器的当前状态
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
// 从JSON中提取信息
const char* method = doc["method"]; // "thing.service.property.set"
JsonObject params = doc["params"];
float temp = params["temp"]; // 温度
float humi = params["humi"]; // 湿度
bool air = params.containsKey("air") ? params["air"] : airState; // 空调状态
bool humier = params.containsKey("humier") ? params["humier"] : humierState;// 加湿器状态
bool dehumi = params.containsKey("dehumi") ? params["dehumi"] : dehumiState;// 除湿器状态
Serial.print("Method:");
Serial.println(method);
Serial.print("temp:");
Serial.println(temp);
Serial.print("humi:");
Serial.println(humi);
Serial.print("air:");
Serial.println(air);
Serial.print("humier:");
Serial.println(humier);
Serial.print("dehumi:");
Serial.println(dehumi);
// 根据接收到的设备控制信息更新设备状态
if (air != airState) {
airState = air;
digitalWrite(air_pin, air);
}
if (humier != humierState) {
humierState = humier;
digitalWrite(humier_pin, humier);
}
if (dehumi != dehumiState) {
dehumiState = dehumi;
digitalWrite(dehumi_pin, dehumi);
}
}
这是个回调函数,Esp32接收到信息就会调用这个函数来处理消息。
//回调函数
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
// 将payload转换为字符串
char message[length + 1];
memcpy(message, payload, length);
message[length] = '\0';
// 打印原始消息
Serial.println(message);
// 调用processJsonMessage函数处理消息
processJsonMessage(message);
}
下面的是wifi初始化和MQTT服务器连接函数。
//wifi初始化
void wifiInit()
{
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.println("WiFi not Connect");
}
Serial.println("Connected to AP");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("espClient [");
client.setServer(MQTT_SERVER, MQTT_PORT); /* 连接WiFi之后,连接MQTT服务器 */
client.setCallback(callback);
}
//连接服务器
void mqttCheckConnect()
{
while (!client.connected())
{
Serial.println("Connecting to MQTT Server ...");
if (client.connect(CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD))
{
Serial.println("MQTT Connected!");
}
else
{
Serial.print("MQTT Connect err:");
Serial.println(client.state());
delay(5000);
}
}
}
实现每两秒发送一次数据,可以通过修改UPDATE_INTERVAL的数值来修改发送数据的间隔。
void setup() {
Serial.begin(115200); //开启串口
Serial.println("Demo Start");
dht.begin(); //初始化传感器
pinMode(air_pin,OUTPUT); //配置空调引脚
pinMode(humier_pin,OUTPUT); //配置加湿器引脚
pinMode(dehumi_pin,OUTPUT); //配置除湿器引脚
wifiInit(); //连接wifi
mqttCheckConnect(); //连接MQTT服务器
pubMsg(); //发布初始化消息
}
void loop() {
client.loop(); //保持客户端的连接
// 定时发布消息(每2秒)
unsigned long UPDATE_INTERVAL = 2000
unsigned long lastUpdateTime = 0;
unsigned long currentMillis = millis();
if (currentMillis - lastUpdateTime >= UPDATE_INTERVAL)
{
lastUpdateTime = currentMillis;
pubMsg();
}
}
在物联网平台点击日志服务可以看到,数据已经发送成功,再点击设备的物模型就可以看到数据了,至此代码部分讲解完成。
四、APP连接
首先在手机下载名为“云智能”的APP,打生活物联网平台,找到自己的项目,打开人机互动界面,点击下载配网二维码,输入自己的设备名称就可以生成二维码了。
在手机端打开APP,点击主界面右上角的加号,再点击右上角的扫描,扫刚刚生成的二维码就能添加了,如果添加失败,就检查一下在创建产品时是否选择网关+蜂窝。
点击“完成”之后就能进入控制面板界面了,这里的控制面板就是在设置人机交互时自己设计的面板。
作者:Σ踏支浪の书➹