目录
一、OneNET和WxBit联合开发
最终效果展示:
WxBit页面设置
WxBit积木搭建
主题订阅
二、消息可靠性级别 = MQTT 的 QoS(服务质量)
三个级别对比(0、1、2)
三、变量
四、键(Key)
五、字典(Dict)
六、JSON
一、OneNET和WxBit联合开发
最终效果展示:
WxBit能够成功连上OneNET云平台,同时OneNET云平台能够下发数据到app上
先在WxBit上进行MQTT连接,连接成功和订阅后在OneNET云平台上设置数据下发来模拟传感器上传的数据,结果:数据下发正常,app上显示下发的数据
OneNET云平台下发数据
app接收到的数据
(调试信息最能直观看到云平台返回了什么,返回的具体数据格式,好后续调整代码和模块)
WxBit页面设置
详解:
1、先分清你用的是哪个版本的 OneNET
| 版本 | 服务器 URI |
|---|---|
| 新版(物联网平台 / 物模型,现在新注册的都是这个) | tcp://studio-mqtt.heclouds.com:1883 |
| 旧版(多协议接入 → MQTT 套件) | tcp://mqtt.heclouds.com:1883 |
2、新版 OneNET 属性填写(推荐)
| WxBit 属性 | 填什么 | 从哪获取 |
|---|---|---|
| 服务器 URI | tcp://studio-mqtt.heclouds.com:1883 | 固定 |
| 客户端标识 | 设备名称 如MQTT_test | OneNET 控制台 → 设备详情 |
| 用户名称 | 产品 ID 如8Du5E4QO5k | OneNET 控制台 → 产品详情 |
| 密码 | Token(用密钥计算,不是填 key 本身) | 需用脚本生成,见下文 |
| 是否自动重连 | 勾选 | — |
| 其余超时项 | 默认 | — |
注意:密码不是设备密钥 Key,而是用 Key 算出来的一串 Token,且有过期时间。时间戳弄大点最好
布局:
WxBit积木搭建
组件MQTT客户端1设置好后能够连接上OneNET云平台
订阅主题,OneNET设备属性下发
目前app上报数据还有点问题,上传修改不了对应传感器数据,这个post还是有点难搞,头疼
主题订阅
详细主题情况请看下面文档说明,读一下就大概明白了
通信主题_开发者文档_OneNET
Topic概念
物联网平台中,服务端和设备端通过通信主题Topic实现消息通信,设备可以通过发布消息到系统 topic 调用服务接口,也可以订阅系统 topic 用于接收服务消息通知,服务提供的系统 topic 见Topic列表。
Topic列表
物联网平台预定义物模型通信Topic,各物模型功能Topic消息的数据格式,见OneJSON数据格式。 Topic类以正斜线(/)进行分层,区分每个类目。其中,有两个类目为既定类目:${pid}表示产品的产品id;${device-name}表示设备名称;${identifier}表示服务标识符
$sys/8Du5E4QO5k/MQTT_test/thing/property/set
OneNET 不为每个属性建独立主题,所有属性共用固定的主题,靠消息内容里的标识符区分
$sys/8Du5E4QO5k/MQTT_test/thing/property/set是 OneNET 平台按 "产品 + 设备 + 功能 + 动作" 四级拼出来的固定收件地址,含义是:"平台 → 产品 8Du5E4QO5k 里的设备 MQTT_test,下发属性设置指令"。你的手机订阅它,就相当于告诉平台 "开关控制指令请发到这个地址,我来接收"。
为什么不能只订阅kaiguan?因为kaiguan是你在物模型里定义的属性标识符,它走的是消息内容(JSON 的params字段),不是主题名
set主题可以承载该设备的所有属性设置(开关、阈值、使能位都从这一个主题下发,靠 JSON 里的标识符区分)。
二、消息可靠性级别 = MQTT 的 QoS(服务质量)
消息可靠性级别”就是 MQTT 里的 QoS(Quality of Service,服务质量等级)
这是 MQTT 协议规定的消息送达保证等级,订阅块里填的数字代表"你希望平台以什么级别把消息推给你"。只有 0、1、2 三个值,不是越大越好,而是可靠性越高、速度越慢、流量开销越大。
三个级别对比(0、1、2)
| 值 | 名称 | 通俗解释 | 传输机制 | 适用场景 |
|---|---|---|---|---|
| 0 | 最多一次 | 发出去就不管了 | 设备/平台发完即忘,不等待对方确认,不重发 | 高频温湿度上报,丢一条无所谓 |
| 1 | 至少一次 | 保证你能收到,但可能收到重复的 | 对方没回"收到"就一直重发,直到确认 | 开关控制、报警等重要指令 |
| 2 | 恰好一次 | 保证收到且只收到一次 | 四次握手来回确认,最复杂最慢、流量最大 | 计费、扣费类绝不能重复的业务 |
图示:
QoS 0 的优点
- **最快**:没有等确认的往返时间,延迟最低
- **最省**:报文少、内存占用小,ESP32 这种小设备友好
- **不阻塞**:不会因为某条消息没确认而堵住后面的消息丢一条也不心疼的场景,它就最合适:**每秒一次的温湿度上报、心跳包、实时位置轨迹**——反正下一秒还有新数据,旧数据丢了无所谓。
QoS 0 的坑(这才要注意的)
1. **消息可能凭空消失**。网络抖一下、Wi-Fi 断一下、broker 重启,消息就没了,而且没有任何报错提示给你。
2. **离线期间的消息直接丢弃**。如果订阅方当时不在线,QoS 0 的消息不会排队等你上线(QoS 1/2 配合持久会话才会)。
3. **控制指令千万别用 0**。开灯、开锁、继电器这类命令丢了就是事故——你手机上按了"开",设备没反应,而 App 显示已发送。
4. **发布端和订阅端会"取小"**。这是最容易忽略的一条:你发布时设 QoS 1,但订阅时设了 QoS 0,实际交付按 **0** 走。想可靠,两边都得设成 1。
为什么建议你填 0
- 毕设演示网络环境一般,QoS 0 最轻量、延迟最低;
- OneNET 平台下发的属性设置本身就常用 0~1 级别,你填 0 完全够用;
- 填 1 会引入重复消息——WxBit 图形化客户端没有现成的"去重"积木,收到两条一模一样的开关指令反而要自己判断。
两个补充知识点
- 实际投递级别取"发布端"和"订阅端"的较小值:比如平台用 QoS 2 发布,你订阅填 0,实际就按 QoS 0 投递。所以你填 0 不会把更可靠的消息"降级"到丢消息——它只是告诉平台"我这边最高只接受到这个程度"。
- 什么时候改成 1:如果你的开关指令很关键(比如控制老人家里的电器通断,要求不能丢),把这个数字槽直接改成1即可,积木其他地方不用动。OneNET 控制台属性下发一般能配合到 1 级。
- 另外补一句:QoS 2 看着最完美,但四段握手代价大,绝大多数物联网平台(OneNET 也一样)对系统主题只支持 0 和 1,**实际项目里 QoS 1 是性价比最高的选择**。真正关键的命令,与其依赖 QoS 2,不如在应用层自己加一层"收到请回复"的业务确认,可控得多。
简单记:0 像发短信(不管对方看没看),1 像打电话(不接通就重打,可能打两遍),2 像挂号信(签字回执,最稳但最慢)。控制类用 1。
三、变量
是什么:变量是程序里存数据的容器,有名字、有内容,内容可以随时改。
比如:变量就是一个贴了标签的盒子
- 盒子上的标签 = 变量名(如
DHT11、kaiguan) - 盒子里的东西 = 变量值(如
26、true)
三个要点:
- 变量名:自己起,要见名知意,比如用 DHT11 表示温湿度;
- 变量值:可以反复修改,新值覆盖旧值;
- 变量类型:盒子里放的是什么——数字、文字、真假、还是字典。
全局变量 vs 局部变量:
| 全局变量 | 局部变量 | |
|---|---|---|
| 比喻 | 客厅的公共柜子,谁都能开 | 你书包里的笔袋,只自己用 |
| 谁能访问 | 整个 APP 所有按钮、所有事件都能读写 | 只在某个事件/函数内部有效 |
| 生命周期 | APP 不关,它一直在 | 事件执行完就销毁 |
在我的积木里:
- 我拖的
创建全局变量 Attribute 为 ""、创建全局变量 DHT11 为 ""就是在建三个盒子并先放空;- "设置全局变量 DHT11 为 26" = 往盒子里放 26;
- 积木里直接用
DHT11这个小方块 = 取出盒子里的东西。
四、键(Key)
是什么:键是字典里每一条数据的名字,用来从字典里找到对应内容。
比如:像查新华字典
- 你要找"苹果"这个词,"苹果"就是键;
- 翻到的那一页解释,就是值。
四个特点:
- 同一个字典里,键不能重复(否则分不清取哪个);
- 键一般是文字(字符串);
- 键和值成对出现,不能单独存在;
- 报出键名就能查到值,这个动作叫"查找"。
{"id":"15","version":"1.0","params":{"DHT11":26,"kaiguan":true}}
在上面数据里:id、version、params、DHT11、kaiguan都是键。
在我积木里:
在字典中查找键 "params"= 报出 params 这个名字,并取出它的内容;查找键 "DHT11"= 取出 26。
注意:键名必须和平台一字不差,大小写也要一致(DHT11不能写成dht11),找不到时你积木里设置的就是返回"未找到"。
五、字典(Dict)
是什么:字典是一种用"键值对"存数据的结构,一组成对的"名字→内容"。 名字+内容
比如:字典是一个档案袋
- 里面不是装一个东西,而是装好多条"名字→内容"的记录;
- 就像通讯录:名字(键)→ 电话号码(值)。
长相:
{ "DHT11": 26, "kaiguan": true }四个特点:
- 数据成对出现;
- 键唯一,值可以重复;
- 不用按顺序翻,直接按键查,很快;
- 值可以是另一个字典(嵌套)。
在我积木里:
JSON转为字典:把收到的文字变成能操作的档案袋;字典转JSON:把档案袋变回文字(上报时用);- 你的
Attribute变量里装的就是一个字典。
{"id":"15","version":"1.0","params":{"DHT11":26,"kaiguan":true}}
嵌套(重点理解):你数据里
params这条,它的内容又是一个{}档案袋,所以要先取出 params 这个档案袋,再从里面找 DHT11——这就是"档案袋里装着小档案袋"。
这串数据里,params这个键 的 值本身又是一个字典,里面那个就是 "子字典"
六、JSON
是什么:JSON 是一种用文字表示数据的标准格式,专门用来在网络上传输数据。
比如:
- 字典是程序内部的档案袋(只能在 APP 里用);
- JSON 是把档案袋内容抄成标准格式的纸条,这样才能通过网络寄出去;
- 就像寄快递:东西要打包成标准包裹才能运输。
书写规则:
- 大括号
{}表示一个字典;- 键必须用双引号包起来:
"DHT11";- 键和值之间用冒号:
"DHT11": 26;- 不同条目之间用逗号;
- 值的写法:
- 文字加引号:
"id": "15"- 数字不加引号:
"DHT11": 26- 真假不加引号:
"kaiguan": true
逐段读你收到的 JSON:
{"id":"15","version":"1.0","params":{"DHT11":26,"kaiguan":true}}| 部分 | 键 | 值 | 类型 |
|---|---|---|---|
| 外层 | id | "15" | 文字 |
| 外层 | version | "1.0" | 文字 |
| 外层 | params | 一个{} | 字典 |
| params里 | DHT11 | 26 | 数字 |
| params里 | kaiguan | true | 真假 |
为什么必须转字典:JSON在网络上只是一串文字,程序没法直接"按键查值",必须先
JSON转字典解析后才能查;上报时反过来,把字典转成 JSON 再发布。
常见错误:用了中文的引号、漏逗号、漏大括号、数字加了引号(就变成文字不能计算)。
四者关系(一句话串起来)
数据在 APP 里 → 用【变量】装 变量里可以装【字典】(成对的名字和内容) 字典里每条数据 = 【键】(名字) + 值(内容) 数据要上网传输 → 把字典写成【JSON】文字 收到 JSON → 转回字典 → 报键名取出值最通俗的记法:变量是盒子,字典是里面装"名字→内容"的档案袋,键是每条的名字,值是对应名字的内容,JSON 是档案袋寄出去时的标准纸条写法。