当前位置:   article > 正文

微信小程序获取Onenet温湿度数据并控制灯亮灭_onenet可视化按键控制灯亮

onenet可视化按键控制灯亮

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

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

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

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

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

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

在这里插入图片描述
在这里插入图片描述

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

2、创建设备

点击设备列表->点击右边的添加设备,设备名称和鉴权信息需要填写,鉴权信息设备连接onenet用的上,还有设备的id号
在这里插入图片描述

3、创建数据流

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

这里设置的数据流名称后面要用到,这里我创建了温度、湿度、灯的数据流。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、Arduino ide编译环境

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

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

链接:https://pan.baidu.com/s/1kLPvsDpwQf1lz_e3goxpJg
提取码:1234
在这里插入图片描述
在这里插入图片描述
配置好开发板相应环境
在这里插入图片描述

三、嵌入代码撰写

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

1、设备怎么连上网

这里可以调用wifi库

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

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

#include "DHT.h"
  • 1

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

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

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

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

在这里插入图片描述

4、数据如何发送给onenet

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

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

在这里插入图片描述

#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相对应
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在 setup()函数定义了每5秒发送一次数据到onenet

 tim1.attach(5, sendTempAndHumi);                            //定时每5秒调用一次发送数据函数sendTempAndHumi

  • 1
  • 2
5、下发命令

在 setup()函数订阅命令下发主题

  client.setCallback(callback); //订阅命令下发主题
  • 1
//收到主题下发的回调, 注意这个回调要实现三个形参 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{}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
6、led灯

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

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

  • 1
  • 2

在setup()定义灯是输出的

pinMode(led,OUTPUT);//输出
  • 1

我这里设置一个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);
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
四、微信开发者工具

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

1、微信界面

在这里插入图片描述
在这里插入图片描述

2、获取Onenet的API接口

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

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

 points:function(e) {
 
 
 }
  • 1
  • 2
  • 3
  • 4

​ 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}} 名字相同
        
       })    
      }
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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

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

在这里插入图片描述

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);

      }

    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
7、数据刷新

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

页面刷新

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

定时刷新

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

  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
8、效果展示

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

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

onenet-iot

结语

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/567958
推荐阅读
相关标签
  

闽ICP备14008679号