

系统框架分为:感知层,传输层,应用层

硬件:MCU(STC89C52/STM32)及USB线、esp8266-01s(wifi模块),温湿度传感器(DHT11),CH340模块(板载)
软件:emqx、keil、cubemax,串口调试助手,ISP下载工具,微信小程序开发者,
链接地址:https://mqttx.app/zh



DHT11引脚
接线:
1VCC --- 外接3.3V-5V
2GND--- 外接GND
3DATA --- 接单片机O口(51单片机IO口,STM32开发板接PG11)

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。该传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连。

DHT11工作时序

Esp8266(NodeMCU)是一款集成了Wifi功能的MCU开发板,可以直接连接wifi,开发环境多元化,也是表较受欢迎的物联网芯片。
ESP8266是一款高性能的WIFI串口模块,内部集成MCU能实现单片机之间串口通信,是目前使用最广泛的一种WIFI模块之一。可以简单理解为一个WIFI转串口的设备,不用知道太多WIFI相关知识,只需要知道串口怎么使用就可以。
1、AT指令开发,开发简单,只需知道AT指令集,以及它的通信方式即可,但是需要MCU与其通信,不能独立完成某项功能,烧录过程相对与其它开发方式来说比较麻烦。 2、使用lua脚本进行开发,NodeMCU本质也是ESP8266,只是它的固件是与lua脚本语言交互,可以节省资源,开发简单,代码量少,但是lua解释器执行效率较低。 3、Arduino IDE开发,使用C语言进行编程,集编程和烧录一体,并且还有许多的库函数可以使用。Arduino IDE相对lua需要写的带代码较长。如果要查看底层的代码,表较麻烦,不容易查看。 4、VS Code 配置Arduino开发环境,可以在VS Code 进行编程和烧录,使用快捷键一键烧录,使用方便,并且还自带代码补全功能,还可以很方便的查看底层原代码,推荐使用这种方式。
ESP8266系列一般具有两种开发方式:AT指令开发和SDK开发。
AT指令:厂家出厂时预先在ESP8266芯片烧入好固件,封装好WiFi的协议栈,内部已经实现透传,而用户只需要使用一个USB转TTL的模块或者单片机的串口就能实现与WiFi模块的通信,发送AT指令来对WiFi模块进行控制。(和蓝牙透传模块类似)
SDK开发:由于ESP8266本身即是可编程的芯片,可以把它视为一个带有无线通信的单片机,而用户需要在专门的IDE中编写对应的程序,然后通过烧写固件的方式将程序写入到芯片中,因此,想要实现WiFi通信,需要自定义WiFi协议栈,对用户掌握的相关知识要求更高。
AT指令类型:
AT测试指令:AT
AT配置指令:AT+cmd=<值>
AT查询指令:AT+cmd?

注:需要模块升级
TXD-U --- RXD
RXD-U --- TXD
GND --- IO0 --升级的时候需要连接
5V --- 3V3
GND --- GND
x1恢复出厂设置 AT+RESTORE 2测试模块 AT 3关闭回显 ATE04查看版本信息AT+GMR5复位模块状态 AT+RST6设置客户端模式7AT+CWMODE=1 客服端 Station8AT+CWMODE=2 服务端 AP9AT+CWMODE=3 双端模式10查看附近无线网络 AT+CWLAP11
12连接WIFI AP13AT+CWJAP="wifi名","密码"14获取ip地址 AT+CIFSR15
16查询网络连接状态 AT+CIPSTATUS17开启传透模式 AT+CIPMODE=118关闭穿透模式 AT+CIPMODE=019
20AT+UART=9600,8,1,0,0 设置波特率21 22UDP连接23AT+CIPSTART="UDP","目标IP",目标端口号,本机端口号,024如:AT+CIPSTART="UDP","192.168.1.1",8080,9000,025 26TCP连接27AT+CIPSTART="TCP","目标IP",目标端口号28如:AT+CIPSTART="TCP","192.168.1.1",808029 30开启发送 AT+CIPSEND31指定发送长度 AT+CIPSEND=num32退出发送 +++xxxxxxxxxx141连接MQTT服务器服务器21. AT 测试指令32. AT+RST 复位43. AT+CWMODE=1 客户端模式54. AT+CWJAP="wifi名","密码"6 eg.AT+CWJAP="iPhone13_yxq","15270910076"75. AT+MQTTUSERCFG=0,1,"STC89C52","espressif","1234567890",0,0,"" MQTT配置信息86. AT+MQTTCONN=0,"43.138.234.120",1883,0 连接MQTT服务器地址97. AT+MQTTSUB=0,"/mcu/sub",1 订阅主题topic108. AT+MQTTPUB=0,"/mcu/pub","\{\"beep\":0\}",1,0 推送主题topic11
12接收到订阅的topic13+MQTTSUBRECV:0,"/mcu/sub",26,{"target":"led","value":1}14接收到的标志,xxxxxxxxxx141连接服务器21. AT+CWMODE=1 客服端32. AT+CIPMODE=1 透传模式143. AT+CWJAP="wifi名","密码"54. AT+CIFSR 获取ip地址65. AT+CIPSTART="UDP","目标ip地址",目标端口,8266端口默认9000,07发送数据有两种方法8一 1. AT+CIPSEND (开启传输数据)92. > (这个符号代表等待输入,回车发送,在程序里用\r\n转义发送)103. +++ (发送+++代表退出发送,串口助手里需要关闭发送新行才能关闭发送,程序里用+++\r\n关闭)11二 1. AT+CIPSEND=num (指定发送数据长度,由于指定长度,达到长度后会自动发送,并退出发送)122. > (这个符号代表等待输入,回车发送,在程序里用\r\n转义发送)1314多次发送只需要循环发送数据方法
xxxxxxxxxx121连接服务器21. AT+CWMODE=1 客服端32. AT+CIPMODE=0 透传模式043. AT+CWJAP="wifi名","密码"54. AT+CIFSR 获取ip地址65. AT+CIPSTART="TCP","目标ip地址",目标端口7发送数据有两种方法8一 1. AT+CIPSEND (开启传输数据)9 2. > (这个符号代表等待输入,回车发送,在程序里用\r\n转义发送)10 3. +++ (发送+++代表退出发送,串口助手里需要关闭发送新行才能关闭发送,程序里用+++\r\n关闭)11二 1. AT+CIPSEND=num (指定发送数据长度,由于指定长度,达到长度后会自动发送,并退出发送)12 2. > (这个符号代表等待输入,回车发送,在程序里用\r\n转义发送)总结:上面讲的都是AT指令,真正应用都要在STC89C51中,STC89C51连接ESP8266也是使用串口发送AT指令,与串口助手用法是一样的。
具体实现看下面代码
STC89C516通过串口发送AT指令需要在最后加"\r\n"(0x0D 0x0A)作为回车
xxxxxxxxxx1611、升级固件,升级到MQTT库文件22、修改默认波特率115200,修改成9600,51单片只能配置成960033、按照MQTT连接方式进行连接4 AT 测试指令5 AT+RST 复位6 AT+CWMODE=1 客户端模式7 AT+CWJAP="wifi名","密码"8 eg.AT+CWJAP="iPhone13_yxq","15270910076"9 AT+MQTTUSERCFG=0,1,"STC89C52","espressif","1234567890",0,0,"" MQTT配置信息10 AT+MQTTCONN=0,"43.138.234.120",1883,0 连接MQTT服务器地址11 AT+MQTTSUB=0,"/mcu/sub",1 订阅主题topic12 AT+MQTTPUB=0,"/mcu/pub","\{\"beep\":0\}",1,0 推送主题topic134、emqx软件测试14链接地址:https://mqttx.app/zh15 上行数据和下行数据的测试16 Topic
概念:MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
特点: MQTT协议运行在TCP/IP或其他网络协议,提供有序、无损、双向连接。其特点包括:
使用的发布/订阅消息模式,它提供了一对多消息分发,以实现与应用程序的解耦。
对负载内容屏蔽的消息传输机制。
对传输消息有三种服务质量(QoS):
最多一次,这一级别会发生消息丢失或重复,消息发布依赖于底层TCP/IP网络。即:<=1。
最少一次,这一级别会确保消息到达,但消息可能会重复。即:>=1。
只有一次,确保消息只有一次到达。即:=1。在一些要求比较严格的计费系统中,可以使用此级别。
数据传输和协议交换的最小化(协议头部只有2字节),以减少网络流量。
通知机制,异常中断时通知传输双方。
(1)MQTT实现方式

实现MQTT协议需要:客户端和服务器端 MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。 MQTT传输的消息分为:主题(Topic)和负载(payload)两部分 Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload) payload,可以理解为消息的内容,是指订阅者具体要使用的内容
3.MQTT客户端一个使用MQTT协议的应用程序或者设备,它总是建立到服务器的网络连接。客户端可以:
发布其他客户端可能会订阅的信息
订阅其它客户端发布的消息
退订或删除应用程序的消息
断开与服务器连接
MQTT服务器MQTT服务器以称为“消息代理”(Broker),可以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间,它可以:
接受来自客户的网络连接
接受客户发布的应用信息
处理来自客户端的订阅和退订请求
向订阅的客户转发应用程序消息
(1)搭建框图
搭建之前需要在腾讯云服务器上购买一个自己的云服务器(华为云、阿里云、腾讯云、移动云)

(2)当前主流的MQTT服务器代理
Mosquitto:https://mosquitto.org/
VerneMQ:https://vernemq.com/
EMQX:https://www.emqx.io/(本次采用)
(3)云服务器安装EMQX
点击网址连接进入到首页

点击网页左下角切换成中文。

点击立即下载,选择Linux操作系统。

下载安装MQTT,在云服务器中安装后,启动EMQX。
xxxxxxxxxx1211、配置 EMQX Yum 源 2
3curl -s https://assets.emqx.com/scripts/install-emqx-rpm.sh | sudo bash4
52、安装 EMQX 6
7sudo yum install emqx -y8
93、启动 EMQX 10
11 sudo systemctl start emqx12
进入到安全中心,放开端口,增加防火墙放开端口。
(注:每个云服务商不一样,详细见云服务器控制台)
腾讯云服务器如下:

放开以下端口:
EMQX管理界面:18083
ssl:8883 --- 加密通道
Tcp:1883 -- 未加密通道
ws:8083 ---微信小程序
wss:8084 ---微信小程序加密通道
登录地址:云服务器IP地址:端口号
eg:127.0.0.1:18083
腾讯云服务器地址:http://43.138.234.120:18083/
默认账号密码:admin /public

修改成中文

MQTT服务器测试
连接服务器

订阅默认消息,同时发布消息,显示已接收和已发布则代表测试成功如下图。

MQTTX
下载方式
链接地址:https://mqttx.app/


MQTTX软件MQTT协议主题发布/订阅测试
发布主题:/my/sub
订阅主题:/my/Pub
(1)打开软件

(2)订阅主题

向该主题/my/sub发送消息

发送消息hello world情况

注册链接地址:https://mp.weixin.qq.com/
点击 “立即注册” 按钮进行注册(右上角)。注册的账号类型可以是订阅号、服务号、小程序以及企业微信,我们选择 “小程序” 即可。

填写注册信息
接着填写账号信息,需要注意的是,填写的邮箱必须是未被微信公众平台注册、未被个人微信号绑定的邮箱,而且每个邮箱仅能申请一个小程序。
激活邮箱之后,选择主体类型为 “个人类型”,并按要求登记主体信息,主体信息提交后不可修改。


1)新建项目


2)微信小程序页面介绍

3)项目的组成

4)页面信息

5)新建页面信息组成
xxxxxxxxxx51###页面文件具体作用2index.js 业务逻辑3index.json 页面配置4index.wxml 模板文件5index.wxss 样式

激活邮箱
1)小程序的模板语法约等于vue的模板语法
xxxxxxxxxx2411文本渲染2{{ msg }}可以执行简单的js表达式3{{2+3}}4{{msg.length}}562条件渲染7wx:if=""8wx:elif=""9wx:else10113列表渲染12wx:for="{{list}}"13wx:key="index"14{{item}}15{{index}}16174自定义列表渲染18定义item与index的名称19wx:for="{{list}}}"20wx:for-item="myitem"21wx:for-index="myidx"22{{myidx}}23{{myitem}}24
2)导入文件
xxxxxxxxxx21import { 对象 } from "module";2import { connect } from "../../static/mqtt";3)wxss
xxxxxxxxxx31微信小程序默认单位是rpx,html默认单位为px2750rpx 等于一个屏幕的宽3375就是50%的宽
4)事件
xxxxxxxxxx41bindInput 表单输入时2bindconfirm 表单输入确认3bindtap 点击时候4bindchange 改变时5)表单的绑定
xxxxxxxxxx101.wxml文件2<input value="{{s1}}" bindinput="inputHd">3 4.js文件 5inputHd(e){6 this.setData({s1:e.detail.value})7}8
9表单的值获取:e.detail.value10
6)内置的api
xxxxxxxxxx81#显示提示2showToast3
4#本地存储5wx.setStorageSync(key,value)6
7#本地取8wx.request 网络请求7)生命周期
xxxxxxxxxx41onLoad 页面加载完毕2onShow 页面显示调用3onPullDownRefresh 下拉刷新4onReachBottom 触底更新xxxxxxxxxx261内置标签:23(1)view:视图容器,类似div,整体布局使用view搭建框架,原生小程序采用flex布局45(2)image:图片标签 类似img src路径,可以相对../ 直接绝对 /项目根开始67(3)text:文本标签 类似span 包裹文字89页面增加数据10Page({11data: {12client: null,//连接的客户端13temp: 23,//温度14humi: 30,//湿度15led: 0,//大灯的状态16beep: 0//蜂鸣器的状态17},1819数据的赋值/绑定20this.setData({21//变量名:赋值内容22client:connect('wxs://broker.emqx.io:8084/mqtt')2324})25表单的值获取:26event.detail.value
iconfont图标下载
阿里巴巴图标:https://www.iconfont.cn/

小程序标题
xxxxxxxxxx81 "window": {2 "navigationBarBackgroundColor": "#ffffff",3 "navigationBarTextStyle": "black",4 "navigationBarTitleText": "单片机智能家居",5 "backgroundColor": "#eeeeee",6 "backgroundTextStyle": "light",7 "navigationStyle": "custom"8 }tabbar制作
xxxxxxxxxx131 "tabBar": {2 "list": [{3 "pagePath": "pages/index/index",4 "text": "",5 "iconPath": "/image/home.png",6 "selectedIconPath": "/image/home_active.png"7 },{8 "pagePath": "pages/logs/logs",9 "text": "",10 "iconPath": "/image/user.png",11 "selectedIconPath": "/image/user_active.png"12 }]13 }
wxml文件
xxxxxxxxxx131<view class="header-container">2 <view class="header-title">3 <view>空气质量-良</view>4 <view>江西赣州</view>5 </view>6 <view class="header-air">7 <view>60</view>8 <view>晴</view>9 </view>10 <view class="header-ad">11 <view>今天天气真好,适合远游!</view>12 </view>13 </view>wxss文件
xxxxxxxxxx441.page-container{2 /* 外边距 */3 margin: 32rpx;4
5}6
7.head-container{8 /* 背景颜色 */9 background-color: #44a9f0;10 /* 圆角 */11 border-radius: 32rpx;12
13}14
15.head-container .head-title{16 display: flex;17 /* 分布在两边 */18 justify-content: space-between;19 /* 字体颜色 */20 color: white;21 /* 内边距:上下,左右 */22 padding: 32rpx 32rpx;23}24
25.head-container .head-data{26 display: flex;27 /* 分布在两边 */28 justify-content: space-between;29 /* 字体颜色 */30 color: white;31 /* 内边距:上下,左右 */32 padding: 0rpx 32rpx;33 /* 字体大小 */34 font-size: 72rpx;35
36}37
38.head-container .head-advice{39 /* 字体颜色 */40 color: white;41 /* 内边距:上下,左右 */42 padding: 12rpx 32rpx;43
44}wxml文件
xxxxxxxxxx221 <view class="data-container">2 <!-- 温度 -->3 <view class="data-card">4 <view>5 <image class="data-card-icon" src="/image/temp.png" mode="" />6 </view>7 <view>8 <view class="data-card-title">温度</view>9 <view class="data-card-data"> {{temp}}°</view>10 </view>11 </view>12 <!-- 湿度 -->13 <view class="data-card">14 <view>15 <image class="data-card-icon" src="/image/humi.png" mode="" />16 </view>17 <view>18 <view class="data-card-title">湿度</view>19 <view class="data-card-data"> {{humi}}°</view>20 </view>21 </view>22 </view>wxss样式
xxxxxxxxxx341/* 数据样式 */2.data-container {3 background-color: burlywood;4 margin-top: 32rpx;5 /* 网格布局 */6 display: grid;7 justify-content: center;8 /* 卡片宽度大小设置 */9 grid-template-columns: repeat(auto-fill, 300rpx);10 /* 卡片之间间隙 */11 grid-gap: 18rpx;12}13
14.data-container .data-card{15 background-color: #fff;16 height: 150rpx;17 box-shadow:#d6d6d6 0 0 8rpx;18 border-radius: 32rpx;19 display: flex;20 justify-content: space-between;21 padding: 16rpx 16rpx;22}23.data-container .data-card .data-card-icon{24 height: 80rpx;25 width: 80rpx;26 margin-top: 32rpx;27}28
29.data-container .data-card .data-card-data{30 font-size: 48rpx;31 font-weight: bold;32 margin-top: 32rpx;33}34
xxxxxxxxxx301 <!-- 温度 -->2 <view class="data-card">3 <!-- 左 -->4 <view> 5 <!-- icon图片 -->6 <image class="data-card-icon" src="/image/temp.png" mode=""/>7 </view>8 <!-- 右 -->9 <view>10 <view class="data-card-title">温度</view>11 <view class="data-card-value">{{temp}}℃</view>12 </view>13 </view>14 15 /**16 * 页面的初始数据17 */18 data: {19 //定义一个MQTT客户端20 client:null,21
22 temp:30,//温度23 humi:60,//湿度24 led:1,//LED按钮25 beep:0//蜂鸣器按钮26
27 },28 29 数据绑定与前端进行交互30 定义变量:{{ }} -- 用两对花括号与数据进行绑定。微信小程序的网络使用

MQTT包下载
https://www.emqx.com/zh/mqtt-client-sdk

下载MQTT包文件
下载地址:unpkg.com/mqtt/dist/mqtt.min.js

导入mqtt.js的包
xxxxxxxxxx31//引入MQTT包文件2import { } from "module";3eg:import { connect } from "../../static/js/mqtt";前提:需要导入mqtt包文件至微信小程序。
使用 EMQ X Cloud 提供的 免费公共 MQTT 服务器 作为本次测试的 MQTT 服务器地址,服务器接入信息如下:
Broker: broker.emqx.io
TCP Port: 1883
WebSocket 端口: 8083
SSL/TLS Port: 8883
WebSocket Secure 端口: 8084
Broker: www.mqttssl.icu
公网IP:43.138.234.120
TCP Port: 1883
WebSocket 端口: 8083
SSL/TLS Port: 8883
WebSocket Secure 端口: 8084
微信小程序使用 WebSocket 的方式连接到 MQTT 服务器,但连接的 URL 地址中请使用 wxs 协议名称,连接及初始化数据的关键代码:
xxxxxxxxxx3711、给客户端赋值,给定MQTT服务器地址端口号2 that.setData({3 //43.138.234.1204 //client: connect('wxs://broker.emqx.io:8084/mqtt')5 client: connect('wxs://43.138.234.120:8084/mqtt')6 })7 82、连接回调函数9 //连接回调函数10 that.data.client.on('connect', function name(params) {11 console.log('成功连接到MQTT服务器')12 //弹出窗口13 wx.showToast({14 title: '连接成功',15 icon: 'success',16 mask: true17 })183、订阅主题19 //订阅上行数据20 that.data.client.subscribe(devicePubTopic, function name(err) {21 if (!err) {22 console.log("成功订阅上行数据:"+ devicePubTopic)23 }24 })254、接收订阅的消息26 that.data.client.on('message', function name(topic, message) {27 console.log(topic)28 console.log(message)29 })30 5、发布消息31 that.data.client.publish(mpPubTopic, "open_led", function name(err) {32 if (!err) {33 console.log("成功下发一条指令:开灯")34 }35 }36
37 )xxxxxxxxxx181/**2 * 生命周期函数--监听页面显示3 */4 onShow: function () {5 var that = this6 //设置连接MQTT服务器的地址和端口号7 that.setData({8 client:connect('wxs://43.138.234.120:8084/mqtt')9 })10 //连接MQTT服务器11 that.data.client.on('connect',function name(err) {12 console.log('成功连接服务器')13 //连接成功的弹窗14 wx.showToast({15 title: '成功连接服务器',16
17 })18 })xxxxxxxxxx81 //订阅主题2 that.data.client.subscribe('/mcu/pub',function name(err) {3 if(!err)4 {5 console.log('成功订阅主题:/mcu/pub')6
7 }8 })xxxxxxxxxx151 //接收订阅消息2 that.data.client.on('message',function name(topic,message) {3 console.log(topic)4 //message是一个16进制流5 console.log(message)6 //把message转换成json7 var recData = JSON.parse(message)8 console.log(recData)9 //设置接收的数据到前端10 that.setData({11 temp : recData.temp,12 humi : recData.humi13 })14
15 })xxxxxxxxxx271 //开关状态,传递值2 onledchange(event) {3 const that = this4 console.log(event.detail.value) //获取按键的值,true,false5 const sw = event.detail.value6 that.setData({7 led: sw8 })9 //根据开关发送消息至设备10 if (sw) {11 that.data.client.publish(mpPubTopic, "open_led", function name(err) {12 if (!err) {13 console.log("成功下发一条指令:开灯")14 }15 }16
17 )18 } else {19 that.data.client.publish(mpPubTopic, "close_led", function name(err) {20 if (!err) {21 console.log("成功下发一条指令:关灯")22 }23 }24
25 )26 }27 },xxxxxxxxxx671<!-- index.html -->2<view class="page-container">3 <!-- 头部 -->4 <view class="header-container">5 <view class="header-title">6 <view>空气质量-良</view>7 <view>江西赣州</view>8 </view>9 <view class="header-air">10 <view>60</view>11 <view>晴</view>12 </view>13 <view class="header-ad">14 <view>今天天气真好,适合远游!</view>15 </view>16 </view>17 <!-- 数据 -->18 <view class="data-container">19 <!-- 温度 -->20 <view class="data-card">21 <view>22 <image class="data-card-icon" src="/static/image/temp.png" mode="" />23 </view>24 <view>25 <view class="data-card-title">温度</view>26 <view class="data-card-data"> {{temp}}°</view>27 </view>28 </view>29 <!-- 湿度 -->30 <view class="data-card">31 <view>32 <image class="data-card-icon" src="/static/image/humi.png" mode="" />33 </view>34 <view >35 <view class="data-card-title">湿度</view>36 <view class="data-card-data"> {{humi}}%</view>37 </view>38 </view>39 <!-- 蜂鸣器 -->40 <view class="data-card">41 <view>42 <image class="data-card-icon" src="/static/image/beep.png" mode="" />43 </view>44 <view >45 <view class="data-card-title">蜂鸣器</view>46 <view class="data-card-data"> 47 <switch checked="{{beep}}" bindchange="onbeepchange" color="#2A69C7"/>48 </view>49 </view>50 </view>51 <!-- 灯 -->52 <view class="data-card">53 <view>54 <image class="data-card-icon" src="/static/image/light.png" mode="" />55 </view>56 <view >57 <view class="data-card-title">灯</view>58 <view class="data-card-data"> 59 <switch checked="{{led}}" bindchange="onledchange" color="#2A69C7"/>60 </view>61 </view>62 </view>63 </view>64 <!-- 数据展示 -->65 <view id = wx-echart class="echart-container">66 </view>67</view>xxxxxxxxxx601.page-container {2 margin: 36rpx;3}4/* 头样式 */5.header-container {6 background-color: #2a69c7;7 color: #fff;8 border-radius: 24rpx;9 padding: 40rpx 48rpx;10}11
12.header-container .header-air {13 display: flex;14 justify-content: space-between;15 font-size: 64rpx;16}17
18.header-container .header-title {19 display: flex;20 justify-content: space-between;21
22}23
24.header-container .header-ad {25 margin-top: 24rpx;26 font-size: small;27}28/* 数据样式 */29.data-container {30 /* background-color: burlywood; */31 margin-top: 32rpx;32 display: grid;33 justify-content: center;34 /* grid-template-columns: auto auto; */35 grid-template-columns: repeat(auto-fill, 300rpx);36 grid-gap: 18rpx;37
38}39
40.data-container .data-card{41 background-color: #fff;42 height: 150rpx;43 box-shadow:#d6d6d6 0 0 8rpx;44 border-radius: 32rpx;45 display: flex;46 justify-content: space-between;47 padding: 16rpx 16rpx;48}49.data-container .data-card .data-card-icon{50 height: 72rpx;51 width: 72rpx;52 margin-top: 32rpx;53}54
55.data-container .data-card .data-card-data{56 font-size: 48rpx;57 font-weight: bold;58 margin-top: 32rpx;59}60
xxxxxxxxxx1411// index.js2import {3 echarts4} from "../../static/js/echarts";5
6const app = getApp()7
8//引入MQTT包文件9import {10 connect11} from "../../static/js/mqtt";12
13const Host = 'broker.emqx.io' //mqtt服务器14const Port = '8084' //mqtt服务器端口15
16const deviceSubTopic = '/mcu/sub' //设备订阅Topic (小程序发布命令的Topic)17const devicePubTopic = '/mcu/pub' //设备发布Topic (小程序订阅数据的Topic)18
19const mpSubTopic = devicePubTopic20const mpPubTopic = deviceSubTopic21
22
23Page({24 data: {25 client: null,26 temp: 23,27 humi: 30,28 led: 0,29 beep: 030 },31 //开关状态,传递值32 onledchange(event) {33 const that = this34 console.log(event.detail.value) //获取按键的值,true,false35 const sw = event.detail.value36 that.setData({37 led: sw38 })39 //根据开关发送消息至设备40 if (sw) {41 that.data.client.publish("/mcu/sub", "open_led", function name(err) {42 if (!err) {43 console.log("成功下发一条指令:开灯")44 }45 }46
47 )48 } else {49 that.data.client.publish("/mcu/sub", "close_led", function name(err) {50 if (!err) {51 console.log("成功下发一条指令:关灯")52 }53 }54
55 )56 }57 },58
59 //蜂鸣器60 //开关状态,传递值61 onbeepchange(event) {62 const that = this63 console.log(event.detail.value) //获取按键的值,true,false64 const sw = event.detail.value65 that.setData({66 beep: sw67 })68 //根据开关发送消息至设备69 if (sw) {70 that.data.client.publish("/mcu/sub", "open_beep", function name(err) {71 if (!err) {72 console.log("成功下发一条指令:开蜂鸣器")73 }74 }75 76 )77 } else {78 that.data.client.publish("/mcu/sub","close_beep", function name(err) {79 if (!err) {80 console.log("成功下发一条指令:关蜂鸣器")81 }82 }83 84 )85 }86 },87
88 89 //事件函数90 onShow() {91 const that = this92 //wxs 实际上就是wss => wss 实际上就是拥有SSL加密的web socket93 that.setData({94 // client: connect(`wxs://${Host}:${Port}/mqtt`)95 client: connect('wxs://broker.emqx.io:8084/mqtt')96 })97 98 //连接回调函数99 that.data.client.on('connect', function name(params) {100 console.log('成功连接到MQTT服务器')101 //弹出窗口102 wx.showToast({103 title: '连接成功',104 icon: 'success',105 mask: true106 })107 //订阅上行数据108 that.data.client.subscribe('/mcu/pub', function name(err) {109 if (!err) {110 console.log("成功订阅上行数据:"+ devicePubTopic)111 }112 })113 })114
115 that.data.client.on('message', function name(topic, message) {116 console.log(topic)117 console.log(message)118 //message 是16进制的buffer字节流119 let dataFormdev = {}120 try {121 //解析16进制数据122 dataFormdev = JSON.parse(message)123 console.log(dataFormdev)124 //赋值语句125 that.setData({126 temp: dataFormdev.temp,127 humi: dataFormdev.humi,128 led: dataFormdev.led,129 beep: dataFormdev.beep130 })131
132 } catch (error) {133 console.log('json解析失败', error)134
135 }136 })137
138 },139
140})141