Esp32+阿里云物联网平台+DHT11+控制LED
关于本文:利用ESP32连接DHT11温湿度传感器获取温湿度,上报到阿里云物联网平台,通过阿里云物联网平台实时远程查看温湿度,并且接收平台下发的LED灯控制指令。要注意的是,阿里云有两个版本的物联网平台,我这里使用的是新版的。
关于开发中用到的【MQTT库】,找到适用的有PubSubClient和AsyncMqttClient
- PubSubClient:使用上简单直接,不需要用户自行加密生成MQTT_PASSWD(在阿里云直接查到),但属于阻塞型库,小项目使用影响不大。
- AsyncMqttClient:属于非阻塞型库,效率性能更强。笔者在测试连接MQTT时直接使用阿里云中的CLIENT_ID、MQTT_USRNAME、MQTT_PASSWD并没有成功,而是采用该库中的源码方式,用SHA256加密后作为密码连接MQTT才能成功。
本文采用第一种PubSubClient库方式,另一种AsyncMqttClient库方式在另一篇文章中。
1.准备工作
1.1.本地开发环境
尝试了三种开发环境:
- VSCode(espressif):在VSCode上安装乐鑫官方开发库;
- VSCode(platformIO):在VSCode上安装兼容esp32和Arduino的库platformIO;
- Arduino IDE
最后整个体验下来,Arduino IDE是最省心的,当然另两个也很强大,特别是platformIO。
安装必要的库
在Arduino IDE库管理中搜索并安装三个库
- PubSubClient
- DHT sensor
- ArduinoJson
对应代码中的库包含
#include <PubSubClient.h> A client library for MQTT messaging.
#include <DHT.h>
#include <ArduinoJson.h>
还有一个是“WiFi.h”,选择esp32板卡默认存在的库,不需要额外安装
1.2.新版阿里云物联网平台
注册并登录物联网平台
-
看到左下角 公共实例 中显示具体ID才是新版,否则为旧版。
-
点击 公共实例 》进入实例设备数(查看),在查看实例界面可以看到左侧产品和设备,这里的产品是指一大类设备归属的产品,也就是新建一个产品并给产品一个归属哪一类之后就可以在这个产品上添加多个设备。
-
新建产品
不同的产品默认的功能会有所不同,但都可以自定义添加额外的功能
-
添加功能定义(这一步很重要)
因为之前已经选择添加了“卧室温度”,这里选择“室内温度”为例。
注意,添加功能分三种:属性、服务、事件。不同功能对应的数据定义不同,操作也不同。对比我添加的两个主灯开关,功能类型是服务和属性的区别,一个是异步调用,另一个是布尔值,标识符也不一样。这里的标识符在后面编程时会用到,例如温度标识符RoomTemp。
- 添加设备,这里添加了两个设备,能看到都归属中控屏产品
查看温湿度设备,有两个地方需要记录后面编程用到:
1.MQTT连接参数
2.设备证书三元组数据
3.在物模型数据查看刚刚新建的产品功能
1.3.硬件准备
ESP32的主控板
DHT11温湿度传感器
LED
杜邦线若干
2.编程
#include <WiFi.h>
#include <PubSubClient.h> //A client library for MQTT messaging.
#include <DHT.h>
#include <ArduinoJson.h>#define LED 22 // LED接esp32引脚22
#define DHTPIN 4 // 温湿度引脚接esp32引脚4
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE); // Creats a DHT object/* 修改要连接的WIFI SSID和密码 */
#define WIFI_SSID "xxx"
#define WIFI_PASSWD "xxxxxx"/* 修改设备的三元组信息*/
#define PRODUCT_KEY "xxxxx"
#define DEVICE_NAME "TempHumi"
#define DEVICE_SECRET "3012e866383a1931cb2bc963fdfd15e"//不需要,自动生成
#define REGION_ID "cn-shanghai"/* 修改MQTT的参数,线上环境域名和端口号*/
#define MQTT_SERVER "iot-06z00bpscn7cdj.mqtt.iothub.aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_USRNAME DEVICE_NAME "&" PRODUCT_KEY
#define CLIENT_ID "k15j9kWxg8H.TempHumi|securemode=2,signmethod=hmacsha256,timestamp=1715070823046|"
#define MQTT_PASSWD "dbb0a917f61b85032abc363b7c825911d3fffaef8fbca179ff8ffcf9a587a7e"//宏定义订阅主题,可以修改ID为自己的设备名称TempHumi
#define ALINK_BODY_FORMAT "{\"id\":\"TempHumi\",\"version\":\"1.0\",\"method\":\"thing.event.property.post\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"const char* topic = "/sys/k15j9kWxg8H/TempHumi/thing/service/property/set";
unsigned long lastMs = 0;
extern String WiFiAddr = "";
float HumiValue;
float TempValue;WiFiClient espClient;
PubSubClient client(espClient);//连接wifi,获取MAC地址
void wifiInit() {WiFi.begin(WIFI_SSID, WIFI_PASSWD);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.println("Connecting to WiFi...");}Serial.println("");Serial.println("WiFi connected");Serial.print("Camera Ready! Use 'http://");Serial.print(WiFi.localIP());WiFiAddr = WiFi.localIP().toString();Serial.println("' to connect");// 获取MAC地址uint8_t mac[6];esp_read_mac(mac, ESP_MAC_WIFI_STA);// 打印MAC地址Serial.printf("MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}//mqtt连接
void mqttCheckConnect() {while (!client.connected()) {Serial.println("Connecting to MQTT Server ...");if (client.connect(CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD)) {Serial.println("MQTT Connected!");} else {Serial.print("MQTT Connect err:");Serial.println(client.state());delay(5000);}}
}//上传温湿度
void mqttIntervalPost() {char param[32];char jsonBuf[128];//upload humidityHumiValue = dht.readHumidity();sprintf(param, "{\"RoomHumidity\":%0.1f}", HumiValue);//这里的RoomHumidity修改为自己的产品功能标识符sprintf(jsonBuf, ALINK_BODY_FORMAT, param);Serial.println(jsonBuf);bool b = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);// if(b){// Serial.println("publish Humidity success");// }else{// Serial.println("publish Humidity fail");// }// Upload temperatureTempValue = dht.readTemperature();sprintf(param, "{\"RoomTemp\":%0.2f}", TempValue);//这里的RoomTemp修改为自己的产品功能标识符sprintf(jsonBuf, ALINK_BODY_FORMAT, param);Serial.println(jsonBuf);bool c = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);// if(c){// Serial.println("publish Temperature success");// }else{// Serial.println("publish Temperature fail");// }
}//回调函数
void callback(char* topic, byte* payload, unsigned int length) {Serial.print("Message arrived [");Serial.print(topic); // 打印主题信息Message arrived [/sys/k15j9kWxg8H/TempHumi/thing/service/property/set]Serial.print("] ");for (int i = 0; i < length; i++) {Serial.print((char)payload[i]); // 打印主题内容{"method":"thing.service.property.set","id":"704369436","params":{"LightSwitch":1},"version":"1.0.0"}}Serial.println();DynamicJsonDocument doc(1024); //创建了一个名为 doc 的动态 JSON 文档deserializeJson(doc, String((char*)payload)); //从一个名为 payload 的数据中解析 JSON 数据并将其填充到 doc 中if (doc["params"].containsKey("LightSwitch")) {//这里的LightSwitch也是一个开关标识符,同样对应主灯开关属性,注意这里是属性,不是服务或者事件。Serial.println("GOT LightSwitch CMD");digitalWrite(LED, doc["params"]["LightSwitch"]);//改变这里的属性布尔值即可控制LED开关。}
}void setup() {pinMode(LED, OUTPUT);Serial.begin(115200);dht.begin();wifiInit();client.setServer(MQTT_SERVER, MQTT_PORT); /* 连接MQTT服务器 */client.setCallback(callback); //设定回调方式,当ESP32收到订阅消息时会调用此方法digitalWrite(LED, LOW);
}void loop() {if (millis() - lastMs >= 5000) {lastMs = millis();mqttCheckConnect();mqttIntervalPost();}client.loop();// delay(2000);
}
3.连接线路
4.实现效果
- 在本地Arduino IDE
烧录代码后串口监视器能看到WiFi连接、MQTT连接、温湿度值
- 阿里云网联网端
打开实时刷新,能看到刷新时间和温湿度值
- 在线调试
在主灯开关调试选择 关闭 / 打开,控制LED亮或者灭,右侧查看参数
在Arduino IDE端同样能看到物联网平台发出的指令,标识符LightSwitch为1点亮LED,为0就熄灭LED。