本节摘要:MAC 命令是网络服务器与设备之间的"管理通道"——调速率、调功率、查状态都走它。本节列出常用 MAC 命令、命令引擎的实现要点,并讲透占空比这道免授权频段的硬约束怎么算、怎么守。位置:3.2 算了时间账,本节算管理开销与法规约束,MAC 层的账就此结清。
| 命令 | 方向 | 作用 | 触发方 |
|---|---|---|---|
| LinkCheckReq/Ans | 设备→NS | 查链路质量(余量与网关数) | 设备(常配合 ADR 关场景) |
| LinkADRReq/Ans | NS→设备 | 调数据速率、发射功率、信道 | 网络服务器 |
| DutyCycleReq/Ans | NS→设备 | 设置最大占空比 | 网络服务器 |
| RXParamSetupReq/Ans | NS→设备 | 设置 RX1 偏移与 RX2 参数 | 网络服务器 |
| DevStatusReq/Ans | NS→设备 | 查电量与信噪比 | 网络服务器 |
| NewChannelReq/Ans | NS→设备 | 增删改可用信道 | 网络服务器 |
| RXTimingSetupReq/Ans | NS→设备 | 设置接收窗口延迟 | 网络服务器 |
MAC 命令可以在上行或下行帧的 FOpts 字段捎带(不加密),也可以放在 FPort=0 的载荷里(加密)。实现上的三个要点:解析要幂等(同一命令可能重复收到,重放执行不能产生副作用);应答要配对(收到 Req 必须回 Ans,否则网络服务器会重发);命令与应用数据要分流(FOpts 命令不进应用回调,避免业务代码误处理管理帧)。
/* 伪代码:上行前的 MAC 命令收集 */ void mac_collect_commands(uint8_t *fopts, uint8_t *len) { *len = 0; if (link_check_pending) { fopts[(*len)++] = 0x02; /* LinkCheckReq */ } if (adr_ans_pending) { fopts[(*len)++] = 0x03; /* LinkADRAns */ } if (dev_status_pending) { fopts[(*len)++] = 0x06; /* DevStatusAns */ } /* FOpts 最多 15 字节,超出部分转 FPort=0 载荷 */ }
免授权频段普遍限制发射占空比:EU868 为 1%,即每小时内发射总时间不得超过 36 秒(DutyCycleReq 可进一步调低)。设备侧实现要做两件事:一是记账——记录最近一小时内的累计发射时间;二是限速——发射前检查预算,不足则推迟发送。
算例:SF12 报文空中时间 1.6s,占空比 1% 每小时最大条数 = 36s / 1.6s = 22 条(SF12) 同样的预算下 SF7(0.11s/条)≈ 327 条
网络服务器侧同样要守约束:下行也占占空比(虽然多数区域对下行计算口径不同,但设计上要留预算),且占空比在区域参数表(第 6 章)里各不相同——EU868 是 1%,US915 是 10% 总量、单信道 0.4% 的限制口径不同,实现时不能写死。
命令引擎的健壮性不在正常路径,而在边界用例。四个高频故障场景与恢复策略:
| 场景 | 现象 | 正确行为 |
|---|---|---|
| LinkADRReq 重复收到 | 设备重复执行同一档位设置 | 幂等:第二次设置与第一次相同则直接回 Ans,不重复切换射频参数 |
| DevStatusReq 密集下发 | 电量/信噪比上报频繁 | 按 NS 的节奏应答即可,但实现要防溢出(电量编码 0–254) |
| 命令过长放不进 FOpts | 15 字节上限超了 | 超出的命令转入 FPort=0 载荷,接收端要同时解析两处 |
| 占空比与 ADR 同时生效 | 速率调高但占空比限制更紧 | 两条约束取严者:速率高省时间,但占空比仍是硬上限 |
不同区域对占空比的口径不同,代码里不能写死一种:
| 区域 | 口径 | 数值 | 说明 |
|---|---|---|---|
| EU868 | 每小时(滚动窗口) | 1%(36s/h) | 设备与网关都适用 |
| US915 | 总量/单信道双口径 | 总量 10% 左右、单信道受限 | 跳频模式下实际更宽松 |
| CN470 | 无统一占空比限制 | — | 以当地监管为准,常按信道频率使用要求 |
实现建议:把占空比抽象成"策略对象"(每区域一个实例),上层只调用 duty_check(airtime),区域参数由第 6 章的参数表驱动。这样换区域只换数据、不换代码。
要点回顾:MAC 命令走 FOpts 或 FPort=0,实现要幂等、应答、分流;占空比是免授权频段的硬约束,设备要记账限速,NS 侧也要守;参数随区域而变。MAC 层的账结清了,下一章入网与安全——Join 流程到底花了多少时间与字节。
命令引擎的健壮性三条:幂等执行、Req/Ans 配对、长度越界防护;占空比三条:滚动窗口记账、跨重启持久化、区域参数驱动。两者合起来,MAC 层的管理通道才算闭环。延伸思考:占空比与信道跳频(hopping)的关系——部分区域允许跳频模式获得更宽松的发射限制,但跳频要求设备与网络服务器同步信道序列,实现复杂度显著上升。是否需要跳频,要在"法规合规"与"实现成本"之间先做一次明确的账,别为了多几条消息把协议栈复杂度翻倍。