其实之前就写过类似的文章,但是看过我博客的朋友就知道,我是先写微信小程序获取onenet,然后再写esp32上云到onenet。一篇是ESP32-C3通过MQTT协议把温湿度上传到OneNet平台(实际是mqtts协议,之前没细看以为没区别),一篇是微信小程序获取onenet数据显示温湿度(硬件连接上云是朋友搞的),之所以写这一篇是因为协议不同,权限不同,之前设备协议用的是mqtts协议,由于之前是作业需要,只搞了获取数据,并没有搞下发命令。这两天重新去翻阅相关文档才发现,onenet现在暂不支持mqtts协议下发命令,支持mqtt协议。部分重要代码需要修改,顺便优化了小程序界面。

需要注意的是这里用的是onenet老版的mqtt协议,多协议接入。新版和旧版数据不互通

硬件设备:	 安信可的ESP32-C3
传感器:	  dht11
代码编译环境: Arduino ide
设备传输协议: mqtt
onenet云平台: 老版多协议接入
微信小程序:	 微信开发者工具


文章目录

  • 一、Onenet云平台
  • 1、创建产品
  • 2、创建设备
  • 3、创建数据流
  • 二、Arduino ide编译环境
  • 三、嵌入代码撰写
  • 1、设备怎么连上网
  • 2、温湿度
  • 3 、接入地址
  • 4、数据如何发送给onenet
  • 5、下发命令
  • 6、led灯
  • 7、嵌入源代码
  • 四、微信开发者工具
  • 1、微信界面
  • 2、获取Onenet的API接口
  • 3、查询OneNet平台多协议接入文档,这里直接查看MQTT的API使用
  • 4、我用ApiPost来进行测试是否能获取数据
  • 5、微信小程序获取OneNet数据
  • 6、微信小程序下发命令
  • 7、数据刷新
  • 8、效果展示
  • 结语


一、Onenet云平台
1、创建产品

控制台 —>多接入–>添加产品

关于产品名称、行业、类别那些自行选择即可,这里选用mqtt旧版协议

小程序NFC读写扇区 如何用微信小程序读写onenet_c语言


小程序NFC读写扇区 如何用微信小程序读写onenet_小程序NFC读写扇区_02

点击我们刚刚创建的dht11,然后点击产品概况,记住我们的产品id,后面用得上

2、创建设备

点击设备列表->点击右边的添加设备,设备名称和鉴权信息需要填写,鉴权信息设备连接onenet用的上,还有设备的id号

小程序NFC读写扇区 如何用微信小程序读写onenet_json_03

3、创建数据流

首先点击数据流,然后点击数据流模板管理,最后添加数据流模板

这里设置的数据流名称后面要用到,这里我创建了温度、湿度、灯的数据流。

小程序NFC读写扇区 如何用微信小程序读写onenet_c语言_04


小程序NFC读写扇区 如何用微信小程序读写onenet_小程序NFC读写扇区_05


小程序NFC读写扇区 如何用微信小程序读写onenet_小程序NFC读写扇区_06


小程序NFC读写扇区 如何用微信小程序读写onenet_物联网_07

二、Arduino ide编译环境

这里我使用的是Arduino IDE,它的库很多,大部分可以直接调用,只有少部分需要自己下载,网上资源有很多,可以自己查找下载,这里我直接跳过安装。

小程序NFC读写扇区 如何用微信小程序读写onenet_c语言_08

因为我之前使用过esp32开发板,一开始我以为环境是跟ESP32一样的,事实证明我还是太年轻了。后面我通过安信可官方给的包替换。下面的链接是官方的,里面也有Arduino IDE 的安装包

链接:https://pan.baidu.com/s/1kLPvsDpwQf1lz_e3goxpJg 提取码:1234

小程序NFC读写扇区 如何用微信小程序读写onenet_c语言_09


小程序NFC读写扇区 如何用微信小程序读写onenet_物联网_10


配置好开发板相应环境

小程序NFC读写扇区 如何用微信小程序读写onenet_微信小程序_11

三、嵌入代码撰写

之前用的是mqtts协议,这里是mqtt协议,只需要修改之前代码的一部分就能解决

1、设备怎么连上网

这里可以调用wifi库

#include <WiFi.h>
const char* ssid     = "3671"; //wifi名称
const char* password = "05210835";//wifi密码
2、温湿度

我传感器用的是DHT11,这里也可以调用库

#include "DHT.h"

定义DHT11,数据引脚我接在IO7口

#define DHTPIN 7     // io7
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);
3 、接入地址

mqtts协议的接口端号是1883,这里是6002

const char *mqtt_server = "183.230.40.96"; //onenet 的 IP地址
const int port = 6002;                     //端口号

小程序NFC读写扇区 如何用微信小程序读写onenet_微信小程序_12

4、数据如何发送给onenet

这里我们需要查阅onenet的相关文档

https://open.iot.10086.cn/doc/v5/develop/detail/463

小程序NFC读写扇区 如何用微信小程序读写onenet_微信小程序_13

#define mqtt_devid "884337606" //设备ID
#define mqtt_pubid "487632"        //产品ID
//鉴权信息
#define mqtt_password "20222222" //鉴权信息
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
5、下发命令

在 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{}

}
6、led灯

关于灯,本来想外接的,但是我在查看原理图后就想偷懒了,毕竟开发板有自带了两个灯和RGB灯。这里我选择的是18接口的灯,因为19的灯是常亮的,所以不选它。

小程序NFC读写扇区 如何用微信小程序读写onenet_微信小程序_14

const int led =18; //灯的接口

在setup()定义灯是输出的

pinMode(led,OUTPUT);//输出

我这里设置一个god变量,初始化是0,即灯没有开,等接收到指令再进行变化,1为灯开。

7、嵌入源代码
#include <WiFi.h>
#include "DHT.h"
#include "PubSubClient.h"
#include "Ticker.h"
#define DHTPIN 7     
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);
int god=0;
const int led =18; //灯的接口
const char *ssid     = "3671"; //wifi名称
const char *password = "05210835";//wifi密码
const char *mqtt_server = "183.230.40.96"; //onenet 的 IP地址
const int port = 6002;                     //端口号
#define mqtt_devid "884337606" //设备ID
#define mqtt_pubid "487632"        //产品ID
//鉴权信息
#define mqtt_password "20222222" //鉴权信息
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; //定时器,用来循环上传数据

void setupWifi(){
  WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print("正在连接中----\n");
        
    }

    Serial.print("WIFI已连接\n");
    Serial.print(WiFi.localIP());
}
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);
    }
  }
}
四、微信开发者工具

这个是微信提供的一个开发工具,有框架,也方便我们把项目部署到线上。这里我着重讲述怎么获取onene数据和发送指令

1、微信界面

小程序NFC读写扇区 如何用微信小程序读写onenet_微信小程序_15


小程序NFC读写扇区 如何用微信小程序读写onenet_c语言_16

2、获取Onenet的API接口

回到onenet的设备列表,然后在点击右边的详情就可以看到设备的详细信息,复制API地址和API-key,一个设备可以多个apikey,自行添加。

小程序NFC读写扇区 如何用微信小程序读写onenet_物联网_17

3、查询OneNet平台多协议接入文档,这里直接查看MQTT的API使用

小程序NFC读写扇区 如何用微信小程序读写onenet_小程序NFC读写扇区_18

4、我用ApiPost来进行测试是否能获取数据

小程序NFC读写扇区 如何用微信小程序读写onenet_物联网_19

5、微信小程序获取OneNet数据

这里我定义了points()函数,是用来获取Onenet平台数据的,主要放在index.js,为后面数据定时刷新做好铺垫。

points:function(e) {
 
 
 },

2、参考小程序文档,我这里采用wx.request 获取数据

points:function(e) {
    var that = this
    wx.request({
      url: 'http://api.heclouds.com/devices/xxxxxxxxxx/datapoints?', //xxz这里填写你的设备id
      //设备ID
      //api-key
      header:{
        "api-key":"xxxxxxx"  //这里写你的api-key
      },
      data:{
        limit:1    //数据流最新的一个数据 如果是5,即五个数据
      },
      method :"GET",
       //获取成功
      success:function(res){
       that.setData({
          wendu:res.data.data.datastreams[0].datapoints[0].value,
         time:res.data.data.datastreams[0].datapoints[0].at,
         shidu:res.data.data.datastreams[1].datapoints[0].value,
         led:res.data.data.datastreams[2].datapoints[0].value, //这里的shidu要跟wxml{{shidu}} 名字相同
        
       })    
      }
    })
  },

3、关于如何显示到具体数字,因人而异,下面我这两行代码是根据json数据来定位的

shidu:res.data.data.datastreams[0].datapoints[0].value, 
wendu:res.data.data.datastreams[1].datapoints[0].value,

小程序NFC读写扇区 如何用微信小程序读写onenet_小程序NFC读写扇区_20

6、微信小程序下发命令

这里我也封装了两个函数,一个是发1值,一个发0值,因为我们的嵌入代码写是1代表打开灯,0代表关灯。这里以打开灯函数介绍

openled:function(e){
    wx.request({
      url: 'http://api.heclouds.com/cmds?device_id=*****',//*号这里写你设备id
      //设备ID
      //api-key
      header:{
        'content-type':'application/json',
        "api-key":"xxxxxxx"  //这里写你的api-key
      },

      method :"POST",
      data:1,//数据1是为灯开
      success(res){
        console.log("控制成功,已开灯")
        console.log(res)
        console.log(res.data);

      }

    })
  },
7、数据刷新

其实这些网上都有的函数例子,我试过页面刷新、定时刷新,如果页面没有点击事件的话都可以用我下面这两个方法。但是有点击事件的话还是用定时刷新

页面刷新

//生命周期函数--监听页面加载
onLoad:function(options){
	this.points();  //这个是我获取onenet数据的函数
	if(getCurrentPages().length !=0){
	 getCurrentPages()[getCurrentPages().length-1].onLoad()
	}
}

定时刷新

/**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.points()  //这个是我获取onenet数据的函数
    var that=this
    setInterval(function(){
      that.points();
    },3000   //这里我设置3秒刷新一次
    )

  },
8、效果展示

因为我硬件是每5秒上传一次,微信小程序数据是3秒刷新一次,可能会造成一定是时延,还有可能是因为我这边网络的原因,我手机开热点给电脑连接,电脑开热点给设备连接,我手机开的热点,设备就是连不上。但是从视频里面可以看到我们的下发指令,设备一下子就接收到了。

这里我采用的是wx:if条件来进行图片切换的。按钮的点击并不能决定图片的切换,我这里设置if条件的判断 wx:if=“{{led==1}}”,是判断onenet的led数据流,如果为1,则灯亮,其他为灯灭。虽然会有一定的时延,但能保证其一定的真实性。


onenet-iot


结语

这样一整个物联网流程算是彻底完成了,也实现了获取设备数据并控制开关,算是做了一个小小小项目。如果有兄弟需要我这微信小程序源码(附这个项目界面设计的设计和数据交互文档),可以私信找我要。整个流程都是自己一个人完成的,查阅了很多相关文档,写代码也花费了很多时间,界面设计也是自己设计出来的。经过一次又一次的失败才成功的。个人创作实属不易,还请多多谅解!

小程序NFC读写扇区 如何用微信小程序读写onenet_json_21