当前位置: 首页 > news >正文

【蓝牙精品系列文档】【04_blemesh model】01_访问层

Access Layer 访问层

章节定位

Week3 已覆盖Bearer 承载层 → Network 网络层 → Lower Transport 底层传输层 → Upper Transport 上层传输层(应用安全层)

本章从Access Layer开始,向上衔接 Foundation Model 与业务 Model。Access 层是传输层与模型层之间的中间层:不负责加解密(Upper Transport 已解密),也不执行业务逻辑(Model 层负责),核心工作是解析 Access PDU、按地址与 Opcode 路由到正确的 Model 实例

┌─────────────────────────────────────────────────────────┐ │ Model Layer 业务模型层(OnOff、Lightness…) │ ├─────────────────────────────────────────────────────────┤ │ Foundation Model 基础模型层(Config、Health…) │ ├─────────────────────────────────────────────────────────┤ │ Access Layer ◀──── 本章:Opcode 解析、Element/Model 路由│ ├─────────────────────────────────────────────────────────┤ │ Upper Transport AppKey/DevKey 加密、TransMIC │ ├─────────────────────────────────────────────────────────┤ │ Lower Transport 分段重组、Segment ACK │ ├─────────────────────────────────────────────────────────┤ │ Network Layer NetKey、Relay、IV Index │ ├─────────────────────────────────────────────────────────┤ │ Bearer Layer ADV / GATT │ └─────────────────────────────────────────────────────────┘

Access 层一句话

Upper Transport 解密后得到明文 Access PDU;Access 层按DST 地址 + OpcodeElement → Model表,把消息交给对应 Model 的 handler 处理。


一、Access PDU 格式

Access PDU 是 Upper Transport 解密后的应用层可见明文,结构固定:

Access PDU ┌─────────────┬──────────────────────────────────┐ │ Opcode │ Parameters(可选) │ │ 1 ~ 3 字节 │ 0 ~ 多字节,由消息定义决定 │ └─────────────┴──────────────────────────────────┘
字段作用
Opcode消息类型 ID;Access 层据此匹配 Model 的 handler
Parameters载荷;Set 写入 State,Get 通常为空,Status 从 State 读出

Opcode 编码规则

长度取值范围归属进 Access 层?
1 字节0x00~0x7F由 Network PDU 的 CTL 位决定归属:CTL=1 → Transport Control;CTL=0 → Foundation 层 Access 消息CTL=1不进;CTL=0
2 字节0x8000~0xBFFFAccess 层 SIG 消息(业务 Model 全部 + Foundation 大部分),CTL=0
3 字节0xC0xxxxAccess 层厂商自定义:0xC0+ Vendor Opcode + Company ID,CTL=0进(查vnd_models[]

关键区分区分 Control vs Access 的不是 Opcode 长度,是 Network PDU 的 CTL 位。1 字节 Opcode 既可能是 Transport Control(CTL=1,Transport 层自处理),也可能是 Foundation 层 Access 消息(CTL=0,进 Access 层查 Model handler)。Access 层会收到 1/2/3 字节 Opcode 都可能——只有 CTL=1 的 Control 消息才不进 Access。

1 字节 Opcode 的两种归属

1 字节 Opcode 空间(0x00~0x7F)被 SIG分给两类完全不同的消息,靠 CTL 位区分:

第一类:Transport Control(CTL=1)—— 不进 Access 层

源码transport.h:23

#define TRANS_CTL_OP_ACK 0x00 #define TRANS_CTL_OP_FRIEND_POLL 0x01 #define TRANS_CTL_OP_FRIEND_UPDATE 0x02 #define TRANS_CTL_OP_FRIEND_REQ 0x03 #define TRANS_CTL_OP_FRIEND_OFFER 0x04 #define TRANS_CTL_OP_FRIEND_CLEAR 0x05 #define TRANS_CTL_OP_FRIEND_CLEAR_CFM 0x06 #define TRANS_CTL_OP_FRIEND_SUB_ADD 0x07 #define TRANS_CTL_OP_FRIEND_SUB_REM 0x08 #define TRANS_CTL_OP_FRIEND_SUB_CFM 0x09 #define TRANS_CTL_OP_HEARTBEAT 0x0a
Opcode名称方向用途
0x00Segment ACK接收方 → 发送方分段消息确认,携带 BlockAck 位图
0x01Friend PollLPN → Friend低功耗节点轮询 Friend 是否有缓存消息
0x02Friend UpdateFriend → LPN回复 Poll,告知是否有消息 + 当前 IV Index/Flags
0x03Friend RequestLPN → 周边广播找 Friend,携带 ReceiveWindow/QueueSize 等参数
0x04Friend Offer候选 Friend → LPN应答 Request,告知自身缓存能力
0x05Friend Clear新 Friend → 旧 FriendLPN 换 Friend 时,新 Friend 通知旧 Friend 释放
0x06Friend Clear Confirm旧 Friend → 新 Friend确认释放,握手完成
0x07Friend Subscription AddLPN → FriendLPN 让 Friend 帮它监听新增的 Group/Virtual 地址
0x08Friend Subscription RemoveLPN → FriendLPN 让 Friend 取消监听某些地址
0x09Friend Subscription ConfirmFriend → LPN确认订阅列表已更新
0x0AHeartbeat节点 → 周边周期心跳,携带 Active Relay/Proxy/Feature 等位图 + TTL

第二类:Foundation 层 Access 消息(CTL=0)—— 进 Access 层

源码foundation.h:12

#define OP_APP_KEY_ADD BT_MESH_MODEL_OP_1(0x00) #define OP_APP_KEY_UPDATE BT_MESH_MODEL_OP_1(0x01) #define OP_DEV_COMP_DATA_STATUS BT_MESH_MODEL_OP_1(0x02) #define OP_MOD_PUB_SET BT_MESH_MODEL_OP_1(0x03) #define OP_HEALTH_CURRENT_STATUS BT_MESH_MODEL_OP_1(0x04) #define OP_HEALTH_FAULT_STATUS BT_MESH_MODEL_OP_1(0x05) #define OP_HEARTBEAT_PUB_STATUS BT_MESH_MODEL_OP_1(0x06)
Opcode名称方向类型用途
0x00Config AppKey AddClient → Server命令添加 AppKey(最高频 Config 命令,故给短 Opcode)
0x01Config AppKey UpdateClient → Server命令更新 AppKey(Key Refresh 用)
0x02Config Composition Data StatusServer → ClientStatus回复 Composition Data Get,携带完整 Composition
0x03Config Model Publication SetClient → Server命令设置 Model Publish 参数
0x04Health Current StatusServer → ClientStatus上报当前 Health Fault 列表
0x05Health Fault StatusServer → ClientStatus回复 Health Fault Get/Test,携带 Fault 列表
0x06Config Heartbeat Publication StatusServer → ClientStatus回复 Heartbeat Pub Get/Set,携带发布配置

重要观察

  • 这 7 个 1 字节 Access Opcode全部属于 Foundation 层(Config + Health + Heartbeat),业务 Model(Generic/Lighting/Sensor 等)没有任何 1 字节 Opcode——业务消息全部用 2 字节(0x82xx 系列)
  • Foundation 层也不是全部用 1 字节:只有这 7 个高频消息用短 Opcode,其余(Composition Data Get 0x8008、AppKey Delete 0x8000、Beacon Get 0x8009 等)仍用 2 字节
  • 1 字节空间混合了命令和 Status:0x00/0x01/0x03 是命令,0x02/0x04/0x05/0x06 是 Status
三类 Opcode 归属对比(修正版)
维度1 字节(CTL=1)Control1 字节(CTL=0)Foundation2 字节(CTL=0)SIG 业务3 字节(CTL=0)Vendor
归属层Transport 层 ControlAccess 层 Foundation ModelAccess 层 SIG 业务 ModelAccess 层厂商 Model
加密NetKey 加密即可,不加密 AppKeyAppKey/DevKey 加密 + TransMICAppKey/DevKey 加密 + TransMICAppKey/DevKey 加密 + TransMIC
是否进 Access 层不进,Transport 层自己处理,查 Config/Health Server 的op[]进,查业务 Model 的op[]进,查vnd_models[]
谁定义Mesh Profile Spec §3.4.xMesh Profile Spec §5.4(Foundation)Mesh Model Spec(各 Model 章节)厂商自定义(Company ID 区分)
消息类型ACK/Friendship/HeartbeatConfig/Health/Heartbeat Pub 的高频消息OnOff Set、Lightness Get 等业务厂商私有业务
路由方式Transport 层按ctl_opswitch,不经 Model handlerAccess 层find_op()→ Config/Health Server handlerAccess 层find_op()→ 业务 Model handler同左,但查vnd_models[]
例子0x00 ACK、0x01 Friend Poll0x00 AppKey Add、0x02 Comp Data Status0x8202 OnOff Set、0x8008 Comp Data Get0xC0xxxx 厂商私有

源码证据:CTL=1 的 Control 消息在 Transport 层直接按ctl_opswitch 分发,根本不调用bt_mesh_model_recv()

case TRANS_CTL_OP_ACK: /* ... 处理 Segment ACK ... */ break; /* ... */ switch (ctl_op) { case TRANS_CTL_OP_FRIEND_POLL: /* ... */ case TRANS_CTL_OP_FRIEND_REQ: /* ... */ case TRANS_CTL_OP_FRIEND_CLEAR: /* ... */ case TRANS_CTL_OP_FRIEND_CLEAR_CFM: /* ... */ case TRANS_CTL_OP_FRIEND_SUB_ADD: /* ... */ case TRANS_CTL_OP_
http://www.jsqmd.com/news/1191569/

相关文章:

  • Clang/LLVM 四种生产级安装方式与工程化管理指南
  • Unity多人游戏开发入门:30分钟构建首个网络同步Demo
  • 2026年大同企业老板力荐合同纠纷律师 5位实战精选推荐 - 本地品牌推荐
  • 真力时官方更换原装表带价格查询|全新服务热线及门店地址权威信息公告(2026年7月最新) - 亨得利钟表维修中心
  • Python游戏自动化:Interception底层输入模拟实战指南
  • CTF逆向实战:从魔改UPX脱壳到RC4、SM4密码算法分析
  • 【紧急预警】LangChain 0.1.20+版本Chain.run()存在静默降级风险!3行代码检测+2种兼容性兜底方案(附CVE-2024-LC001技术通告)
  • IP核之RAM:从配置到实战,解锁FPGA高效数据缓存方案
  • MoviePy 是一个基于 Python 的开源视频编辑库,用于剪辑、合成、处理和生成视频
  • 2025年C++跨端架构演进:逻辑统一、数据驱动与AI辅助的工程实践
  • Windows下配置glslangValidator实现本地GLSL语法检查与VS Code集成
  • DHCP协议深度解析:从DORA流程到安全实践
  • Codex 必须开 ChatGPT Plus 吗?GPT-5.6 下 Free、Plus、Pro 与 API Key 一次讲清
  • AM572x硬件设计实战:从引脚复用、GPMC接口到PCB布局避坑指南
  • (2026最新)枣庄漏水检测维修师傅上门-正规防水补漏公司本地居民实测推荐五家-卫生间/屋顶/厨房/阳台/外墙/地下室专业仪器精准检测漏水点 - 安佳防水
  • OpenStack Neutron部署三大核心支点:Keystone认证、消息队列与Linux内核调优
  • C++构建智慧城市道路巡检平台:微服务架构与高性能实战
  • C++算法实践:哈希表与摩尔投票法高效求解众数问题
  • Flutter与Unity集成Vuforia AR:跨平台混合开发实战与避坑指南
  • 解决OpenBabel在Python 3.11+的兼容性问题:从ABI冲突到Conda一站式部署
  • 清华AI教程实战指南:从零掌握深度学习与OpenCV核心技能
  • LLaMA Factory大模型微调实战:从零部署到高效定制AI应用
  • 15天学会AI应用开发(十三)上下文与RAG的阶段性总结
  • Cursor为何成硬科技首选AI原生IDE?键盘即编译器的工程革命
  • VC++中Tab键导航的完整实现:从原理到高级技巧
  • 安卓手机一键生成腾讯云IoT设备密钥工具(含源码与安装包)
  • 鸿蒙中declare关键字
  • 2026年五大数据挖掘平台:算法与性能解析 - 科技焦点
  • PY32F003F18之ADC外部干扰排查与硬件设计优化
  • 遥控器上的X:用运算符重载实现图形交互控制