ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OneNET数据下发到WxBit(MQTTM通信)

OneNET数据下发到WxBit(MQTTM通信)

目录

一、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 属性填什么从哪获取
服务器 URItcp://studio-mqtt.heclouds.com:1883固定
客户端标识设备名称 如MQTT_testOneNET 控制台 → 设备详情
用户名称产品 ID 如8Du5E4QO5kOneNET 控制台 → 产品详情
密码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

  1. 毕设演示网络环境一般,QoS 0 最轻量、延迟最低;
  2. OneNET 平台下发的属性设置本身就常用 0~1 级别,你填 0 完全够用;
  3. 填 1 会引入重复消息——WxBit 图形化客户端没有现成的"去重"积木,收到两条一模一样的开关指令反而要自己判断。

两个补充知识点

  1. 实际投递级别取"发布端"和"订阅端"的较小值:比如平台用 QoS 2 发布,你订阅填 0,实际就按 QoS 0 投递。所以你填 0 不会把更可靠的消息"降级"到丢消息——它只是告诉平台"我这边最高只接受到这个程度"。
  2. 什么时候改成 1:如果你的开关指令很关键(比如控制老人家里的电器通断,要求不能丢),把这个数字槽直接改成1即可,积木其他地方不用动。OneNET 控制台属性下发一般能配合到 1 级。
  3. 另外补一句:QoS 2 看着最完美,但四段握手代价大,绝大多数物联网平台(OneNET 也一样)对系统主题只支持 0 和 1,**实际项目里 QoS 1 是性价比最高的选择**。真正关键的命令,与其依赖 QoS 2,不如在应用层自己加一层"收到请回复"的业务确认,可控得多。

简单记:0 像发短信(不管对方看没看),1 像打电话(不接通就重打,可能打两遍),2 像挂号信(签字回执,最稳但最慢)。控制类用 1。

三、变量

是什么:变量是程序里存数据的容器,有名字、有内容,内容可以随时改。

比如:变量就是一个贴了标签的盒子

  • 盒子上的标签 = 变量名(如DHT11、kaiguan)
  • 盒子里的东西 = 变量值(如26、true)

三个要点:

  1. 变量名:自己起,要见名知意,比如用 DHT11 表示温湿度;
  2. 变量值:可以反复修改,新值覆盖旧值;
  3. 变量类型:盒子里放的是什么——数字、文字、真假、还是字典。

全局变量 vs 局部变量:

全局变量局部变量
比喻客厅的公共柜子,谁都能开你书包里的笔袋,只自己用
谁能访问整个 APP 所有按钮、所有事件都能读写只在某个事件/函数内部有效
生命周期APP 不关,它一直在事件执行完就销毁

在我的积木里:

  • 我拖的创建全局变量 Attribute 为 ""、创建全局变量 DHT11 为 ""就是在建三个盒子并先放空;
  • "设置全局变量 DHT11 为 26" = 往盒子里放 26;
  • 积木里直接用DHT11这个小方块 = 取出盒子里的东西。

四、键(Key)

是什么:键是字典里每一条数据的名字,用来从字典里找到对应内容。

比如:像查新华字典

  • 你要找"苹果"这个词,"苹果"就是键;
  • 翻到的那一页解释,就是值。

四个特点:

  1. 同一个字典里,键不能重复(否则分不清取哪个);
  2. 键一般是文字(字符串);
  3. 键和值成对出现,不能单独存在;
  4. 报出键名就能查到值,这个动作叫"查找"。

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

四个特点:

  1. 数据成对出现;
  2. 键唯一,值可以重复;
  3. 不用按顺序翻,直接按键查,很快;
  4. 值可以是另一个字典(嵌套)。

在我积木里:

  • JSON转为字典:把收到的文字变成能操作的档案袋;
  • 字典转JSON:把档案袋变回文字(上报时用);
  • 你的Attribute变量里装的就是一个字典。

{"id":"15","version":"1.0","params":{"DHT11":26,"kaiguan":true}}

嵌套(重点理解):你数据里params这条,它的内容又是一个{}档案袋,所以要先取出 params 这个档案袋,再从里面找 DHT11——这就是"档案袋里装着小档案袋"。

这串数据里,params这个键 的 值本身又是一个字典,里面那个就是 "子字典"


六、JSON

是什么:JSON 是一种用文字表示数据的标准格式,专门用来在网络上传输数据。

比如:

  • 字典是程序内部的档案袋(只能在 APP 里用);
  • JSON 是把档案袋内容抄成标准格式的纸条,这样才能通过网络寄出去;
  • 就像寄快递:东西要打包成标准包裹才能运输。

书写规则:

  1. 大括号{}表示一个字典;
  2. 键必须用双引号包起来:"DHT11";
  3. 键和值之间用冒号:"DHT11": 26;
  4. 不同条目之间用逗号;
  5. 值的写法:
    • 文字加引号:"id": "15"
    • 数字不加引号:"DHT11": 26
    • 真假不加引号:"kaiguan": true

逐段读你收到的 JSON:

{"id":"15","version":"1.0","params":{"DHT11":26,"kaiguan":true}}
部分键值类型
外层id"15"文字
外层version"1.0"文字
外层params一个{}字典
params里DHT1126数字
params里kaiguantrue真假

为什么必须转字典:JSON在网络上只是一串文字,程序没法直接"按键查值",必须先JSON转字典解析后才能查;上报时反过来,把字典转成 JSON 再发布。

常见错误:用了中文的引号、漏逗号、漏大括号、数字加了引号(就变成文字不能计算)。


四者关系(一句话串起来)

数据在 APP 里 → 用【变量】装 变量里可以装【字典】(成对的名字和内容) 字典里每条数据 = 【键】(名字) + 值(内容) 数据要上网传输 → 把字典写成【JSON】文字 收到 JSON → 转回字典 → 报键名取出值

最通俗的记法:变量是盒子,字典是里面装"名字→内容"的档案袋,键是每条的名字,值是对应名字的内容,JSON 是档案袋寄出去时的标准纸条写法。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进