4. CoAP协议基础与LwM2M消息映射

LwM2M 的轻量特性并非凭空而来,它建立在 CoAP(Constrained Application Protocol,受限应用协议)之上。理解 LwM2M 的设备注册、对象读写、属性上报,本质上就是理解“LwM2M 操作如何被翻译成一条条 CoAP 报文”。本节先拆解 CoAP 的四个核心要素——方法、消息类型、选项、响应码,再给出 LwM2M 操作到 CoAP 请求的映射规则,最后说明如何用抓包工具验证这套映射。

一、CoAP 的报文结构与四个核心要素

CoAP 运行在 UDP 之上,默认端口 5683,使用 DTLS 时端口为 5684。它的固定头部只有 4 字节,结构紧凑:版本号(Ver,固定为 1)、消息类型(T,2 bit)、Token 长度(TKL,4 bit)、请求/响应码(Code,8 bit)、消息 ID(Message ID,16 bit),其后跟随 Token、选项(Options)和负载(Payload)。负载前有一个 0xFF 字节作为分隔符,用于区分“选项结束”和“负载开始”。

方法(Method)决定对资源做什么操作,取值位于 Code 字段的高 3 bit:GET(0.01)、POST(0.02)、PUT(0.03)、DELETE(0.04)。GET 用于读取资源,PUT 用于整体替换或创建资源,POST 用于触发动作或部分更新,DELETE 用于删除资源实例。

消息类型(Type)体现 CoAP 的可靠性机制,共四种:CON(Confirmable,需确认)、NON(Non-confirmable,不需确认)、ACK(Acknowledgement,确认应答)、RST(Reset,复位)。CON 报文要求对端回 ACK;若对端无法处理,则回 RST。NON 用于可容忍丢失的周期上报,以降低功耗。

选项(Options)是 CoAP 的扩展机制,采用“增量编号 + 长度”编码。与 LwM2M 关系最密切的选项包括:Uri-Path(编号 11,可重复,用于拼接资源路径)、Content-Format(编号 12,标识负载格式,如 11542 表示 SenML+CBOR、0 表示 text/plain)、Accept(编号 17,声明期望的响应格式)、Observe(编号 6,值为 0 表示注册观察、1 表示取消观察)、Block1/Block2(编号 27/23,用于分块传输大负载)、ETag(编号 4,用于缓存校验)。

响应码(Response Code)位于 Code 字段,格式为“类别.明细”,如 2.05。2.xx 表示成功,4.xx 表示客户端错误,5.xx 表示服务端错误。常见取值:2.01 Created、2.02 Deleted、2.04 Changed、2.05 Content、4.00 Bad Request、4.01 Unauthorized、4.04 Not Found、4.05 Method Not Allowed、5.00 Internal Server Error。

CoAP 报文结构与 LwM2M 映射关系 ① CoAP 报文结构(UDP 载荷) Ver/T/TKL 1字节 Code 1字节 Message ID 2字节 Token 0~8字节 Options(增量编码) Uri-Path / Content-Format / Observe… 0xFF + Payload SenML / CBOR / TLV ② 方法(Code 高3位) GET 0.01 读取资源 POST 0.02 触发动作/部分更新 PUT 0.03 整体替换/创建 DELETE 0.04 删除实例 ③ 消息类型(T) CON 需确认 注册/写操作 NON 不需确认 周期Notify ACK 确认应答 携带响应码 RST 复位 无法处理 ④ LwM2M 操作 → CoAP 请求映射 Register → POST /rd?ep=…&lt=…&b=U  |  Update → POST /rd/{loc}  |  Deregister → DELETE /rd/{loc} Read → GET /{obj}/{inst}/{res}  |  Write → PUT /{obj}/{inst}/{res}  |  Execute → POST /{obj}/{inst}/{res} Discover → GET /{obj}? |  Observe → GET + Observe:0  |  Notify → 2.05 + Observe 序号递增

二、LwM2M 操作到 CoAP 请求的映射规则

LwM2M 在 CoAP 之上定义了一套 REST 风格的资源模型,路径形如 /{Object ID}/{Object Instance ID}/{Resource ID},例如 /3/0/0 表示设备对象(Object 3)第 0 个实例的制造商资源。映射规则可以归纳为“操作决定方法,路径决定 Uri-Path,语义决定选项”。

注册(Register):客户端向服务器发送 POST /rd?ep={Endpoint Client Name}&lt={Lifetime}&b=U。其中 ep 是端点名,lt 是注册有效期(秒),b=U 表示使用 UDP 传输。服务器成功后在 2.01 Created 响应的 Location-Path 选项中返回注册位置,如 /rd/5a3f,后续 Update 和 Deregister 都基于该位置。

更新(Update):POST /rd/{location},可携带新的 lt 参数续期。若注册过期前未更新,服务器会将该端点标记为离线。

注销(Deregister):DELETE /rd/{location},正常返回 2.02 Deleted。

读取(Read):GET /{obj}/{inst}/{res},成功返回 2.05 Content,负载格式由 Accept 选项协商,通常为 SenML+CBOR(Content-Format 11542)或 TLV(11542 之外的 11542 需按实现确认,常见 TLV 为 11542 的替代编码)。

写入(Write):PUT /{obj}/{inst}/{res},负载为待写入值,成功返回 2.04 Changed。若资源为只读,服务器返回 4.05 Method Not Allowed。

执行(Execute):POST /{obj}/{inst}/{res},用于触发固件升级、重启等动作,成功返回 2.04 Changed。

发现(Discover):GET /{obj},服务器返回该对象下可访问的资源列表及属性,响应 Content-Format 为 application/link-format(40)。

观察(Observe)与通知(Notify):客户端发送 GET /{obj}/{inst}/{res} 并携带 Observe: 0 选项注册观察。此后资源变化时,服务器主动发送 2.05 Content 响应,且 Observe 选项值按 24 位序号递增,客户端据此判断通知的新旧顺序。取消观察时发送 GET 并携带 Observe: 1,或直接发送 RST。

三、抓包分析:从一条 Read 看完整交互

下面以一次“读取设备制造商”为例,说明抓包中应观察的字段。假设客户端端点名为 urn:dev:001,服务器地址为 coap://lwm2m.example.com:5683。

# 客户端 → 服务器(CON 请求)
Code: 0.01 (GET)
Type: 0 (CON)
Message ID: 0x1a2b
Token: 0x7f3c
Options:
  Uri-Path: "3"
  Uri-Path: "0"
  Uri-Path: "0"
  Accept: 11542 (application/senml+cbor)

# 服务器 → 客户端(ACK 响应)
Code: 2.05 (Content)
Type: 2 (ACK)
Message ID: 0x1a2b   ← 与请求一致,完成匹配
Token: 0x7f3c       ← 与请求一致,完成匹配
Options:
  Content-Format: 11542
Payload: SenML CBOR 编码的制造商字符串

抓包时重点核对三处:Message ID 用于 CON/ACK 配对,Token 用于请求与响应的业务匹配(尤其在 NON 或分块场景下),Uri-Path 选项的拼接顺序必须与 LwM2M 路径一致。若响应为 4.04 Not Found,通常说明对象或实例未在注册时声明;若为 4.01 Unauthorized,则需检查 DTLS 握手或服务器侧鉴权配置。

观察通知的抓包中,同一 Token 会持续复用,而 Observe 选项值不断递增。若发现序号回绕或跳变,应检查服务器是否重启或观察关系是否被重建。

四、映射速查表

LwM2M 操作CoAP 方法典型路径关键选项成功响应码
RegisterPOST/rd?ep=…&lt=…&b=UUri-Query2.01 Created
UpdatePOST/rd/{loc}Uri-Query(lt)2.04 Changed
DeregisterDELETE/rd/{loc}—2.02 Deleted
ReadGET/{obj}/{inst}/{res}Accept2.05 Content
WritePUT/{obj}/{inst}/{res}Content-Format2.04 Changed
ExecutePOST/{obj}/{inst}/{res}Content-Format2.04 Changed
DiscoverGET/{obj}Accept(40)2.05 Content
ObserveGET/{obj}/{inst}/{res}Observe:02.05 Content
Notify—(服务器主动)/{obj}/{inst}/{res}Observe:序号2.05 Content

掌握这张映射表后,开发 LwM2M 设备端时就可以把“业务动作”直接翻译为“CoAP 报文构造”:先确定方法与路径,再选择消息类型(注册、写操作优先 CON,周期上报可用 NON),最后按需附加 Content-Format、Accept、Observe 等选项。抓包验证时,只要 Message ID、Token、Uri-Path、响应码四者自洽,就说明映射链路正确。