第1章:LoRaWAN协议栈架构

各位同学,今天我们来聊聊LoRaWAN协议栈。说实话,这个协议栈我研究了快十年,从最早的1.0版本一直跟到现在的1.1。每次看都觉得设计得挺巧妙——它把复杂的东西藏起来了,留给开发者的接口其实很干净。

1.1 协议分层模型

LoRaWAN的协议栈分三层,我习惯这么记:

  • 物理层(PHY)——负责无线信号的收发。LoRa调制技术就在这层,扩频因子、带宽、编码率这些参数都在这里调。
  • MAC层——这是核心层。帧结构、入网流程、确认重传、信道访问策略,全在这层搞定。
  • 应用层——你只管发数据,底层怎么传你不用操心。FPort和payload都在这层定义。

我刚开始做LoRa项目时,总觉得MAC层可有可无,直接用物理层裸传多省事。后来在工厂里部署了200多个节点,发现没有MAC层的调度,信道冲突能把整个网络搞瘫痪。嗯,从那以后我再也不敢跳过MAC层了。

关键点:LoRaWAN的MAC层是网络稳定性的基石。物理层只管传,MAC层管怎么传、什么时候传、传完怎么确认。

1.2 MAC层帧结构

MAC层的帧结构,说白了就是数据包的包装方式。我拆开给你看:

字段 长度(字节) 说明
MHDR 1 消息类型(上行/下行/入网等)
MACPayload 可变 真正的数据内容,包含FHDR、FPort、FRMPayload
MIC 4 消息完整性校验码,防篡改用的

MACPayload里面又分三块:

  • FHDR(帧头)——包含设备地址、帧计数器、控制位。帧计数器特别重要,我见过有人忘记处理帧计数器回绕,结果设备死活连不上服务器。
  • FPort(端口号)——1字节,用来区分不同的应用数据流。比如FPort=1是温度数据,FPort=2是湿度数据。
  • FRMPayload(负载)——真正的业务数据,最大51字节(DR0速率下)。

我的经验:帧计数器千万别乱改。我曾经为了测试,手动重置了帧计数器,结果网关直接丢弃了所有数据包,因为服务器认为这是重放攻击。折腾了两天才找到原因。

1.3 Class A/B/C设备类型

LoRaWAN定义了三种设备类型,你想想看,为什么需要三种?因为不同的应用场景对功耗和延迟的要求完全不同。

  • Class A——最省电的模式。设备发完数据后,打开两个短暂的接收窗口(RX1和RX2),然后继续睡觉。适合电池供电的传感器,比如温湿度计、水表。
  • Class B——在Class A基础上增加了定期接收窗口。设备会同步网关的beacon信号,按固定时间醒来收数据。适合需要定期下发指令的场景,比如智能路灯。
  • Class C——几乎一直开着接收窗口,功耗最大。适合有持续供电的设备,比如网关本身、工业控制器。

我做过一个项目,客户非要让电池供电的烟感用Class C模式。我说这不行,电池撑不过一周。后来改成Class A,配合紧急报警时的额外接收窗口,电池寿命直接拉到三年。选对设备类型,比优化代码重要得多。

注意:Class B需要网关支持beacon同步,不是所有网关都支持。部署前一定要确认网关的固件版本。我吃过这个亏,买了100个Class B设备,结果网关不支持,全白买了。

1.4 入网流程:OTAA vs ABP

设备要加入LoRaWAN网络,有两种方式。我分别说说:

OTAA(Over-The-Air Activation)

这是最推荐的方式。设备出厂时只烧录三个东西:DevEUI(设备唯一ID)、AppEUI(应用唯一ID)、AppKey(应用密钥)。入网流程分三步:

  1. 设备发送Join Request,包含DevEUI和AppEUI。
  2. 服务器验证后,回复Join Accept,包含设备地址(DevAddr)和会话密钥(NwkSKey、AppSKey)。
  3. 设备用会话密钥加密后续通信。

这样做的好处是密钥动态生成,安全性高。而且设备可以随时重新入网,换服务器也方便。

ABP(Activation By Personalization)

这种方式是把DevAddr、NwkSKey、AppSKey直接烧录到设备里。设备上电就能通信,不需要入网流程。看起来省事,但有个大坑:

  • 密钥是固定的,一旦泄露,所有设备都得重新烧录。
  • 帧计数器必须手动管理,设备掉电后计数器重置,服务器会认为数据包是重放的。

我的建议:能用OTAA就别用ABP。除非你的设备在极端环境下(比如矿井、水下),网络连接不稳定,需要设备上电即用。我做过一个矿井项目,用的就是ABP,因为井下信号差,OTAA的入网流程经常超时。但我们在生产线上额外加了密钥烧录校验,防止密钥写错。

好了,这一章的内容就这些。下一章我们聊聊LoRaWAN的速率自适应(ADR)机制,这东西调好了能省一半的功耗。到时候我会分享一个实际案例,看看我是怎么把某个项目的电池寿命从8个月优化到2年的。