4、消息类型详解:Join-Request、Join-Accept、Unconfirmed Data Up/Down、Confirmed Data Up/Down、Rejoin-Request

好,咱们今天来聊聊 LoRaWAN 里最核心的几种消息类型。说实话,很多刚入门的同学,甚至一些做了一两年开发的朋友,都容易把这几种消息搞混。我个人习惯是把它们分成两组来看:一组是入网相关的,一组是数据传输相关的。这样思路会清晰很多。

4.1 Join-Request:终端的第一声问候

当一个节点第一次通电,或者因为某些原因需要重新入网时,它会发送 Join-Request 消息。你可以把它理解成终端在敲门:「嘿,网关,我想加入网络,这是我的身份信息。」

这条消息里包含什么?其实很简单,就三个关键字段:AppEUI(应用标识)、DevEUI(设备标识)和 DevNonce(随机数)。

关键点:DevNonce 是一个随机数,用于防止重放攻击。同一个 DevNonce 不能被网络服务器接受两次。

我在项目中遇到过一个问题:某个客户批量生产的节点,有大概 5% 的设备死活入不了网。排查了半天,发现是他们的固件里 DevNonce 生成逻辑有 bug,每次上电都生成同一个随机数。嗯,这就是典型的「随机数不够随机」的坑。

4.2 Join-Accept:网络的回应

网络服务器收到 Join-Request 后,如果验证通过,就会回复 Join-Accept 消息。这条消息是加密的,终端需要用预置的 AppKey 来解密。

Join-Accept 里包含什么?最重要的就是 DevAddr(设备短地址)和 NwkSKeyAppSKey 的生成材料。说白了,这就是网络给终端发了一张「身份证」和两把「钥匙」。

个人经验:我建议你在调试阶段,把 Join-Accept 的原始数据打印出来。我曾经靠这个发现过网关配置错误——网关把 Join-Accept 的 MIC 算错了,导致终端一直收不到确认。

这里有个细节要注意:Join-Accept 消息里包含一个 DLSettings 字段,用来协商下行速率和 RX1 的延迟。你想想看,如果这个字段配错了,终端可能永远收不到下行的数据。

4.3 Unconfirmed Data Up/Down:最常用的消息

这是 LoRaWAN 里最基础、最常用的消息类型。说白了就是「发出去就不管了」——终端发送上行数据,网关收到后转发给网络服务器,但不需要任何确认。

Unconfirmed Data Up 适合什么场景?

  • 传感器周期性上报数据(比如温度、湿度)
  • 数据丢失一两次不影响整体业务
  • 对功耗要求极高的场景

Unconfirmed Data Down 则是服务器给终端下发数据,同样不需要终端回复确认。比如服务器下发一个配置参数,丢了就丢了,下次上报时再下发一次。

注意:虽然叫 Unconfirmed,但网络层还是会尽力传输的。LoRaWAN 的 ADR(自适应数据速率)机制会动态调整速率,保证一定的传输成功率。我见过有人以为 Unconfirmed 就是「随便发发」,结果把 SF 设成了 SF12,电池一个月就耗光了。

4.4 Confirmed Data Up/Down:可靠传输的保证

当数据必须可靠到达时,就要用 Confirmed 消息了。终端发送 Confirmed Data Up 后,网络服务器必须回复一个 ACK(确认帧)。如果终端在规定时间内没收到 ACK,就会重传。

为什么会这样设计?你想想看,LoRa 的无线环境很不稳定,有时候一次传输可能被干扰。Confirmed 消息就是给业务上了一道保险。

我个人的习惯是:控制类指令用 Confirmed,数据上报用 Unconfirmed。比如远程控制阀门开关,这种指令丢了会出大问题,必须用 Confirmed。而温度上报,丢了就丢了,下次再报就行。

避坑指南:我曾经在一个项目中,把所有上行都设成了 Confirmed。结果 200 个节点同时上报时,网关的 ACK 队列爆了,大量节点超时重传,整个网络直接瘫痪。后来改成了 Unconfirmed + 应用层确认的方案,问题才解决。

Confirmed Data Down 也是一样的逻辑。服务器下发重要指令时,会要求终端回复 ACK。如果终端没回复,服务器会重试。

4.5 Rejoin-Request:紧急情况下的重新入网

这个类型可能很多同学不太熟悉。它是 LoRaWAN 1.1 版本引入的,用于终端在特定情况下主动发起重新入网请求。

什么时候会触发 Rejoin-Request?

  • 帧计数器溢出:每个方向的帧计数器最大是 2^32,用完了就必须重新入网
  • 网络参数变更:比如终端检测到信道计划变了
  • 终端主动触发:某些应用场景下,终端可以主动发起重新入网

Rejoin-Request 和 Join-Request 有什么区别?最大的区别是:Rejoin-Request 可以携带 Rejoin Type 字段,告诉服务器「我为什么要重新入网」。服务器可以根据这个信息做不同的处理。

我的建议:如果你的设备部署在信号不稳定的环境中,可以考虑在固件里加入「信号质量低于阈值时主动发起 Rejoin」的逻辑。我在一个地下管廊项目中用过这个方案,效果不错。

4.6 消息类型对比总结

最后,我用一个表格把这几种消息类型做个对比,方便你查阅:

消息类型 方向 是否需要ACK 典型场景
Join-Request 上行 是(Join-Accept) 终端入网
Join-Accept 下行 网络回应入网请求
Unconfirmed Data Up 上行 传感器周期性上报
Unconfirmed Data Down 下行 非关键参数下发
Confirmed Data Up 上行 报警信息、关键数据
Confirmed Data Down 下行 控制指令、固件升级
Rejoin-Request 上行 是(Join-Accept) 帧计数器溢出、网络变更

嗯,这几种消息类型就讲到这里。记住一句话:选对消息类型,比优化射频参数更重要。我见过太多项目因为消息类型选错,导致功耗高、网络拥堵、数据丢失。希望你能从这些经验里少走一些弯路。