ESP32连接OneNET-MQTT平台传送数据
一、首先在OneNET上创建一个产品和一个设备
1、创建MQTT产品
第一步:
第二步:
第三步:
点击确定之后:
2、为产品添加设备
第一步:
第二步:
第三步:创建完成后可以查看设备的ID和Key。
3、为设备创建数据流
第一步:
第二步:
第三步:
二、使用OneNET提供的MQTT软件测试MQTT
软件下载地址,OneNet官网:https://open.iot.10086.cn/doc/mqtt/book/get-start/connect.html
打开MQTT软件后:
第一步:
第二步:配置MQTT。
以下网址必看:
MQTT地址和端口号的配置:(我这里选择的是非加密接口)
https://open.iot.10086.cn/doc/mqtt/book/device-develop/manual.html
token算法详解:https://open.iot.10086.cn/doc/mqtt/book/manual/auth/token.html
token算法工具以及使用:
https://open.iot.10086.cn/doc/mqtt/book/manual/auth/tool.html
unix时间戳转换工具:
https://tool.lu/timestamp/
注意:使用的时间戳必须大于当前的时间,否则会提示密码错误,导致无法连接。
token密钥生成举例:
products/426214/devices/radar
以上步骤完成后:
点击Connect够就连接成功啦!
在OneNet上查看设备,已在线:
三、使用MQTT发送数据到OneNET
参考官网,MQTT 协议规范:https://open.iot.10086.cn/doc/mqtt/book/device-develop/protocol.html
参考官网,数据点 topic 簇:
https://open.iot.10086.cn/doc/mqtt/book/device-develop/topics/dp-topics.html
第一步:首先订阅 “订阅设备数据点上报结果 ”;
注意修改产品ID和设备名称,其他的目前OneNet不允许修改。
$sys/426214/radar/dp/post/json/+
第二步:发布消息;
$sys/426214/radar/dp/post/json
发布消息的规则如下:
id
: 后面的id
号可随便改。
dp
:不可更改。目前OneNet还不允许自定义修改。
dis
:自己在OneNet产品定义的数据流的名称。
v
: 不可更改,后边的数据可更改。
{
"id": 123,
"dp": {
"dis":
[{
"v": 100.00
}]
}
}
查看订阅消息:
在云平台查看发送的数据:
四、使用ESP32连接OneNet-MQTT
以上测试都成功后,其实就是用代码在实现一遍这个过程。
注意,这个ESP32是未烧写任何固件的,如果之前少写过其他的固件,请先擦出后再使用。
1、ESP32-Arduino IDE 开发环境的搭建
Arduino IDE 下载:
https://www.arduino.cc/en/software
在Arduino IDE的开发版管理网址中添加:https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
之后就可以在开发版管理器中下载了,没梯子的源码安装吧。
这里就不赘述了。
2、代码实现
直接上代码吧:
参考:https://blog.csdn.net/finedayforu/article/details/111517908
#include <Arduino.h>
#include "WiFi.h"
#include "PubSubClient.h"
#include "Ticker.h"
//#include "uFire_SHT20.h"
#include "ArduinoJson.h"
//uFire_SHT20 sht20;
const char* ssid = "NET502"; //wifi名
const char* password = "502502502"; //wifi密码
const char* mqtt_server = "mqtts.heclouds.com"; //onenet 的 IP地址 mqtts.heclouds.com 183.230.40.96
const int port = 1883; //端口号
#define mqtt_pubid "426214" //产品ID
#define mqtt_devid "radar" //设备名称
//鉴权信息
#define mqtt_password "version=2018-10-31&res=products%2F426214%2Fdevices%2Fradar&et=1552234385&method=md5&sign=GZpCklfYK8LviOhGxXP3Iw%3D%3D" //鉴权信息
WiFiClient espClient; //创建一个WIFI连接客户端
PubSubClient client(espClient); // 创建一个PubSub客户端, 传入创建的WIFI客户端
Ticker tim1; //定时器,用来循环上传数据
Ticker tim2; //定时器,用来循环上传数据
float temp;
float humi;
float dis;
//设备上传数据的post主题
#define ONENET_TOPIC_PROP_POST "$sys/" mqtt_pubid "/" mqtt_devid "/dp/post/json" //"$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/post"
//接收下发属性设置主题
#define ONENET_TOPIC_PROP_SET "$sys/" mqtt_pubid "/" mqtt_devid "/dp/post/json/+" //"$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/set"
//接收下发属性设置成功的回复主题
#define ONENET_TOPIC_PROP_SET_REPLY "$sys/" mqtt_pubid "/" mqtt_devid "/dp/post/accepted" //"$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/set_reply"
//接收设备属性获取命令主题
#define ONENET_TOPIC_PROP_GET "$sys/" mqtt_pubid "/" mqtt_devid "/cmd/request/+" //"$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/get"
//接收设备属性获取命令成功的回复主题
#define ONENET_TOPIC_PROP_GET_REPLY "$sys/" mqtt_pubid "/" mqtt_devid "/cmd/response/+/+" //"$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/get_reply"
//这是post上传数据使用的模板
#define ONENET_POST_BODY_FORMAT "{\"id\":%d,\"dp\":%s}"
//#define ONENET_POST_BODY_FORMAT
int postMsgId = 0; //记录已经post了多少条
//连接WIFI相关函数
void setupWifi()
{
delay(10);
Serial.println("connect WIFI");
WiFi.begin(ssid, password);
while (!WiFi.isConnected())
{
Serial.print(".");
delay(500);
}
Serial.println("OK");
Serial.println("Wifi connected!");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
//向主题发送模拟的温湿度数据
void sendTempAndHumi()
{
if (client.connected())
{
//先拼接出json字符串
char param[82];
char jsonBuf[178];
//sprintf(param, "{ \"temp\":[{\"v\":%.2f}],\"humi\":[{\"v\":%.2f}] }", temp, humi); //我们把要上传的数据写在param里
sprintf(param, "{ \"dis\":[{\"v\":%.2f}] }", dis); //我们把要上传的数据写在param里
postMsgId += 1;
sprintf(jsonBuf, ONENET_POST_BODY_FORMAT, postMsgId, param);
//再从mqtt客户端中发布post消息
if (client.publish(ONENET_TOPIC_PROP_POST, jsonBuf))
{
Serial.print("Post message to cloud: ");
Serial.println(jsonBuf);
}
else
{
Serial.println("Publish message to cloud failed!");
}
}
}
//重连函数, 如果客户端断线,可以通过此函数重连
void clientReconnect()
{
while (!client.connected()) //再重连客户端
{
Serial.println("reconnect MQTT...");
if ( client.connect(mqtt_devid, mqtt_pubid, mqtt_password) )
{
Serial.println("connected");
}
else
{
Serial.println("failed");
Serial.println(client.state());
Serial.println("try again in 5 sec");
delay(5000);
}
}
}
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.println("message rev:");
Serial.println(topic);
for (size_t i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println();
if (strstr(topic, ONENET_TOPIC_PROP_SET))
{
DynamicJsonDocument doc(100);
DeserializationError error = deserializeJson(doc, payload);
if (error)
{
Serial.println("parse json failed");
return;
}
JsonObject setAlinkMsgObj = doc.as<JsonObject>();
serializeJsonPretty(setAlinkMsgObj, Serial);
String str = setAlinkMsgObj["id"];
Serial.println(str);
char sendbuf[100];
sprintf(sendbuf, "{\"id\": \"%s\",\"code\":200,\"msg\":\"success\"}", str.c_str());
Serial.println(sendbuf);
client.publish(ONENET_TOPIC_PROP_SET_REPLY, sendbuf);
}
if (strstr(topic, ONENET_TOPIC_PROP_GET))
{
DynamicJsonDocument doc(100);
DeserializationError error = deserializeJson(doc, payload);
if (error)
{
Serial.println("parse json failed");
return;
}
JsonObject setAlinkMsgObj = doc.as<JsonObject>();
serializeJsonPretty(setAlinkMsgObj, Serial);
String str = setAlinkMsgObj["id"];
Serial.println(str);
char sendbuf[100];
//sprintf(sendbuf, "{\"id\": \"%s\",\"code\":200,\"msg\":\"success\",\"data\":{\"temp\":%.2f,\"humi\":%.2f}}", str.c_str(), temp, humi);
sprintf(sendbuf, "{\"id\": \"%s\",\"code\":200,\"msg\":\"success\",\"data\":{\"dis\":%.2f }}", str.c_str(), temp);
Serial.println(sendbuf);
client.publish(ONENET_TOPIC_PROP_GET_REPLY, sendbuf);
}
}
void update_date(void)
{
temp++;
humi++;
dis++;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); //初始化串口
//Wire.begin();
//sht20.begin();
delay(3000);
setupWifi(); //调用函数连接WIFI
client.setServer(mqtt_server, port); //设置客户端连接的服务器,连接Onenet服务器, 使用1883端口
delay(2000);
Serial.println("setServer Init!");
//client.setCallback(callback);
client.connect(mqtt_devid, mqtt_pubid, mqtt_password); //客户端连接到指定的产品的指定设备.同时输入鉴权信息
delay(2000);
Serial.println("connect Init!");
if (client.connected())
{
Serial.println("OneNet is connected!"); //判断以下是不是连好了.
}
client.subscribe(ONENET_TOPIC_PROP_SET);
client.subscribe(ONENET_TOPIC_PROP_GET);
client.setCallback(callback);
tim1.attach(8, sendTempAndHumi); //定时每20秒调用一次发送数据函数sendTempAndHumi
tim2.attach(4, update_date);
temp =10;
humi =20;
dis = 100;
}
int count = 0;
void loop() {
// put your main code here, to run repeatedly:
if (!WiFi.isConnected()) //先看WIFI是否还在连接
{
setupWifi();
}
if (!client.connected()) //如果客户端没连接ONENET, 重新连接
{
clientReconnect();
delay(100);
}
client.loop(); //客户端循环检测
}
3、实现效果
Arduino IDE串口读取数据:
云平台接收的数据: