新版ONENET的物联网环境调节系统(esp32+onenet+微信小程序)
好久没用onenet突然发现它大更新了,现在都是使用新版的物联网开放平台,只有老用户还有老版的多协议接入,新用户是没有的,所以我顺便更新一下新的开发组件吧.温湿度、Oled、风扇这些基本不变,这里就不再赘叙。
1、ONENET平台
1.1创建产品
这里你任意设置就行
我这里选择的是设备接入
这里我选择用MQTT协议接入,数据协议选择的数据流,这里最好还是跟我一样。
这样就创建完成了
1.2创建设备
1.3创建数据流
这里就可以看到我创建设备完成了,然后进入详情页面,创建数据流
2、下位机代码编写
2.1接入地址
查看文档可以发现新版的接口是1883
const int port = 1883; //端口号
2.2token秘钥生成
查看文档发现现在只能使用安全鉴权才可以访问了,以前的是可以直接使用api-key
这里使用token生成秘钥,token工具自行去onenet官方下载
只需要产品id和access_key就可以生成token秘钥
#define mqtt_password "********" //鉴权信息换成你自己的
2.3 主题订阅
因为我前面选择的是数据流,而不是物模型,所以查看onenet的文档时要注意,主题命名的方式是有所不同的,这前面的物模型的主题,
这下面的才是我们所要注意到的格式
然后我们去参考Onenet提供的实践可以看到是这样的
所以我在这里可以简化一下设置主题
#define mqtt_devid "******" //设备ID
#define mqtt_pubid "*******" //产品ID
//接收设备属性获取命令主题
#define ONENET_TOPIC_GET "$sys/" mqtt_pubid "/" mqtt_devid "/cmd/request/+"
//设备上发数据主题
#define ONENET_TOPIC_POST "$sys/" mqtt_pubid "/" mqtt_devid "/dp/post/json"
2.4订阅主题
在setup函数里面对mqtt进行相关配置,client.subscribe是订阅应用程序下发命令的主题,而sendtempAndHumi函数是我发布主题的函数
client.setServer(mqtt_server, port); //设置客户端连接的服务器,连接Onenet服务器, 使用1883端口
client.connect(mqtt_devid, mqtt_pubid, mqtt_password); //客户端连接到指定的产品的指定设备.同时输入鉴权信息
//client.setCallback(callback); //设置好客户端收到信息是的回调
client.subscribe(ONENET_TOPIC_GET);
client.setCallback(callback); //订阅命令下发主题
tim1.attach(5, sendTempAndHumi); //定时每5秒调用一次发送数据函数sendTempAndHumi
2.5发布主题
//信息模板
//这是post上传数据使用的模板
#define ONENET_POST_BODY_FORMAT "{\"id\":%d,\"dp\":%s}"
void sendTempAndHumi()
{
if (client.connected())
{
//先拼接出json字符串
char param[82];
char jsonBuf[178];
sprintf(param, "{\"feng\":[{\"v\":%d}], \"temp\":[{\"v\":%.2f}],\"humi\":[{\"v\":%.2f}] , \"threshold\":[{\"v\":%d}]}",shan, dht.readTemperature(),dht.readHumidity(),threshold); //我们把要上传的数据写在param里
postMsgId += 1;
sprintf(jsonBuf, ONENET_POST_BODY_FORMAT, postMsgId, param);
Serial.print("public the data:");
//client.publish("$dp", (uint8_t *)msg_buf, 3+strlen(msgJson));
client.publish(ONENET_TOPIC_POST, jsonBuf);
//发送数据到主题
delay(500);
}
}
2.6callback函数
使用了JSON数据,利用键值对来实现操作
//收到主题下发的回调, 注意这个回调要实现三个形参 1:topic 主题, 2: payload: 传递过来的信息 3: length: 长度
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
// Handle incoming message here
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println("Received message: " + message);
// Parse message as JSON
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, payload, length);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
// Check which command was received
if (doc.containsKey("修改温度阈值")) {
threshold = doc["修改温度阈值"];
Serial.println("Executing temperature threshold update operation.");
Serial.print(threshold);
} else if (doc.containsKey("风扇")) {
newshan =doc["风扇"];
Serial.print(F("\n"));
Serial.print(newshan);
} else {
// Unknown command
Serial.println("Unknown command received.");
}
// Get the new threshold value
}
3、小程序
3.1如何获取数据
查看onenet的api可以知道,我们可以查看它相关的设备数据
3.2获取设备在线状态
可以看到我们需要地址,安全鉴权、以及相关参数,这里我们用apipost先调试。
header填写我们这前获取的token秘钥,query填写产品id,设备id这些参数
在获取到的数据里面可以看到,以及onenet相关文档提及到data.status、data.enable_status都可以获取到设备是否在线
3.3获取数据
还是继续查看文档可以知道我们可以获取当前的数据或者某一个时间段的数据,这里我就直接获取最新的数据。
header填写我们这前获取的token秘钥,query填写产品id,设备id这些参数。基本不变,变的是http地址的访问
3.4下发数据
这里也是http地址不一样,以及query要添加timeout数据就可以了,然后这里会出现超时返回,是因为我单片机没有订阅返回成功的主题,这里我觉得不影响操作就没搞了