EdgeMesh 网络协议规范

EdgeMemory-MVP 分册 03 | 网络层 | v1.0(定稿) | 2026-10-26
EdgeMesh 是 EdgeHippo 设备之间的网络层:发现、互联、知识库碎片接力、账本同步。
它不共享算力。设备之间交换的是知识库碎片(.emf)与查询结果,不是计算任务(ADR-001)。

1. 定位与边界(先读这章)

EdgeMesh 接力的是「知识」,不是「算力」。
一块 ESP32-S3 没有值得交易的计算能力(实测 2890 万参数模型 9.88 tok/s;跨三块板拆 56M 模型的开源实验困惑度从 192 崩到 358,只产出约 30 个连贯词)。
它有交换价值的是:本地知识库、长期记忆与上下文、感知数据提炼出的模式、以及断网环境下的服务连续性。

1.1 EdgeMesh 负责什么 / 不负责什么

✅ 负责❌ 不负责
  • 设备发现与能力通告(我有哪些碎片、多少条、什么场景)
  • 碎片查询:谁有我需要的知识
  • 碎片传输:把 .emf 或其子集搬到请求方
  • 接力:源设备不在线时由 Hub 代持转发
  • 账本记账:谁给了谁多少配额(内部记账)
  • 版本与冲突消解:同名碎片取高版本
  • 任务分发 / 算力竞标 / 分布式推理
  • 模型权重切分与跨设备推理
  • 任何形式的代币发行、兑换、提现
  • 广域网路由(MVP 只做单局域网 / 单 Hub)

1.2 与 EdgeMemory / EdgeHippo 的分界

EdgeHippo   = 硬件:跑协议的物理设备
EdgeMesh  = 网络:设备之间怎么找到彼此、怎么搬碎片、怎么记账
EdgeMemory= 软件:碎片在板内怎么存、怎么查、怎么保持一致

EdgeMesh 不得直接访问 flash 或写库 —— 它只调用 EdgeMemory 的
  em_frag_import / em_frag_export / em_sync_* 接口。

2. 拓扑与节点类型

板级只有「形态」,没有「角色」。两块板都是 EdgeHippo 外设本体、彼此对等:Dev-A = γ 磁吸卡形态(form=gamma-card)、Dev-B = β USB Dongle 形态(form=usb-dongle)。下表中的 Hub 是 EdgeMesh 协议层的中继角色(负责代持转发与账本仲裁的协议能力),不是板级定位,也不构成上下级——它与设备形态正交(见 00 号总纲 ADR-018)。
节点类型MVP 载体职责约束
γ 磁吸卡形态
(form=gamma-card)
EdgeHippo Dev-A持有碎片、发起查询、请求接力容量小(3,700 条),通常只装专科包
β USB Dongle 形态
(form=usb-dongle)
EdgeHippo Dev-B持有大库(12,900 条)、承担 Hub 中转(代持转发)、账本仲裁MVP 只有 1 个 β 节点承担中转;多节点集群为 P2
Studio
(控制台)
浏览器生成碎片、触发烧录、查看账本不参与运行时接力,只在配置期介入
        ┌──────────────┐
        │   Hub        │  EdgeHippo Dev-B (form=usb-dongle, N16R8, 12,900 条)
        │  (relay)     │  代持转发 · 账本仲裁
        └───┬──────┬───┘
     BLE/ Wi-Fi    Wi-Fi/HTTP
        ┌──┘        └──┐
  ┌─────▼─────┐   ┌────▼──────┐
  │  Peer #1  │   │  Peer #2  │   EdgeHippo Dev-A (form=gamma-card, N8R8, 3,700 条)
  │  Dev-A    │   │ (second)  │   各装「专家记忆包」
  └───────────┘   └───────────┘
        └────── UART1 备用互联 ──────┘

现有 link_mgr 已实现 1 usb-dongle + 2 gamma-card 的 BLE 互联拓扑(原记作「1 gateway + 2 edge」,属板级角色表述),EdgeMesh 直接复用其链路管理,只替换上层语义。

3. 传输承载矩阵

承载速率(实测量级)适用G5 判据限制
Wi-Fi HTTP最快(局域网)灌库、大碎片传输、Studio 连接≤ 60 s
(12,000 条)
需同一局域网;须 CORS
USB CDC
(WebUSB / Serial)
12 Mbps Full-Speed,实际 bulk 有效约 0.5–1 MB/s在线灌库、调试、eme≤ 90 s需驱动(CDC 免驱);浏览器访问不了 MSC
USB MSCOS 层文件拷贝离线灌库、离线投递接力≤ 60 s非浏览器可达;需 PHY 决策(01 号分册第 6 章)
串口 UART0
(921600)
7.9 MB 理论 86 s,含板端写入约 2–4 min首刷、救砖、无 USB 场景≤ 240 s不要为凑 60 s 砍掉它——最可靠。要求:进度清晰 + 断点续传
BLE最慢(NimBLE 实测远低于 Wi-Fi)发现、小消息、控制面不用于灌满库只传控制消息与单条记忆;host 任务栈 ≥ 8192
UART1
(GPIO17/18)
中BLE 不可用时的降级互联—需交叉接线
承载选择策略:控制面一律 BLE 或 HTTP;数据面按「谁快用谁」自动降级 —— Wi-Fi > USB CDC > MSC > 串口 > BLE。降级必须对上层透明,em_frag_import 不感知承载。

4. 设备发现与标识

4.1 设备 ID

格式:EME-<MAC 后 3 字节大写 HEX>
例:  EME-21E980(Dev-B,MAC 14:C1:9F:21:E9:80)
     EME-71FAC8(Dev-A,MAC 44:BD:8D:71:FA:C8)

旧前缀 EMGW- 在 MVP 期间仅做兼容识别,不再新发。em_dev_is_placeholder_id() 已有占位 ID 检测逻辑,须同步更新前缀判断。

4.2 能力通告(advertise)

每个设备周期性广播自己的碎片目录摘要,不是全量内容:

{
  "msg": "mesh.advert",
  "body": {
    "dev": "EME-21E980",
    "form": "usb-dongle",        /* 板级形态标识(gamma-card / usb-dongle),非角色 */
    "cap_kb": 12900,          /* 容量上限 */
    "used_kb": 8412,          /* 已用条数 */
    "frags": [                /* 只列摘要,不列内容 */
      {"id":7,"name":"docs-core-v1","scene":3,"ver":3,"count":6000},
      {"id":9,"name":"expert-pack-v3","scene":2,"ver":3,"count":1800}
    ],
    "bearers": ["wifi","ble","usb"],
    "uptime_s": 12345
  }
}

4.3 发现流程

  1. 设备上电 → 广播 mesh.advert(BLE 广播包 / HTTP mDNS / UDP 组播)
  2. 中转方(Hub)收到 → 记录到邻居表(带 TTL,默认 120 s)
  3. link.scan / hub.discover 命令返回邻居表
  4. 未配对的设备 LED 白双闪;互联断开时黄慢闪(01 号分册第 8 章)

5. 消息 envelope

所有 EdgeMesh 消息(无论承载)共用同一 envelope。BLE 上用精简二进制变体,HTTP / 串口 / USB 用 JSON。

{
  "v":    1,                        /* 协议版本 */
  "src":  "EME-71FAC8",            /* 源设备 ID */
  "dst":  "EME-21E980" | "*",      /* 目的,* = 广播 */
  "msg":  "mesh.query",             /* 原语名 */
  "seq":  1234,                     /* 单调序号,用于去重与应答配对 */
  "ttl":  4,                        /* 跳数上限,防环路 */
  "ts":   1770000000000,            /* 毫秒时间戳 */
  "tok":  "…",                      /* 配对 token(配对后必填) */
  "body": { … }                     /* 原语专属 */
}
字段规则失败处理
seq每设备单调 +1;收到重复 seq 直接丢弃(防重放与环路)静默丢弃
ttl每转发一次减 1;为 0 时丢弃静默丢弃
tok未配对设备只能发 mesh.advert 与 mesh.pair返回 ERR_UNAUTHORIZED
ts与本地时钟差 > 5 min 时拒收(防重放)返回 ERR_CLOCK_SKEW

5.1 应答 envelope

{ "v":1, "src":"EME-21E980", "dst":"EME-71FAC8",
  "msg":"mesh.result", "seq":1234, "ack_seq":1234,
  "body":{ "code":0, "msg":"ok", "data":{ … } } }

/* 错误码 */
0   OK
1   ERR_BAD_REQUEST      参数错
2   ERR_UNAUTHORIZED     未配对 / token 无效
3   ERR_NOT_FOUND        碎片不存在
4   ERR_QUOTA_EXCEEDED   配额不足
5   ERR_BUSY             正在导入/导出
6   ERR_CLOCK_SKEW       时钟偏差过大
7   ERR_STORAGE_FULL     容量不足
8   ERR_CRC              数据校验失败

6. 协议原语(六种)

复用现有 /api/mesh/* 端点与 mesh.* 命令,消息名保留,字段从「算力竞标」重定义为「碎片接力」(ADR-011)。

原语旧语义 → 新语义body返回
mesh.query 算力询价 → 查谁有我需要的知识 {scene, tags[], vec_b64?, k, need_count} {candidates:[{dev, frag_id, ver, count, quota}]}
mesh.bid 算力报价 → 响应「我有,代价是 N 配额」 {frag_id, ver, count, bytes, quota, bearer[]} —
mesh.request 任务派发 → 请求具体碎片(可分块) {frag_id, ver, chunk_off, chunk_len} 接受或拒绝(含原因)
mesh.result 任务结果 → 返回碎片数据块 {frag_id, chunk_off, total, crc32, data_b64} 接收方逐块校验
mesh.award 结算给 winner → 记账:配额从请求方转给提供方 {frag_id, bytes, quota, from, to, ts} {ledger_seq}
mesh.ledger (已有)→ 查询本地账本 {since_seq?, peer?} {entries:[{seq, from, to, frag_id, bytes, quota, ts}]}

6.1 一次完整接力的时序

Peer(Dev-A, γ 磁吸卡形态)           Hub(Dev-B, β USB Dongle 形态)
    |--- mesh.query {scene:2} ------->|      我要野外巡检的碎片
    |<-- mesh.bid {frag:9, quota:12} -|      我有 expert-pack-v3,12 配额
    |--- mesh.request {frag:9} ------>|      请给我
    |<-- mesh.result chunk 0/87 ------|
    |<-- mesh.result chunk 1/87 ------|      4 KB 分块 + CRC32
    |       … 断点续传 …              |
    |--- mesh.award {quota:12} ------>|      记账:我给你 12 配额
    |<-- mesh.result {code:0} --------|
    |                                 |
    |  em_frag_import → 事务提交 → LED 蓝快闪结束 → 绿常亮
铁律:失败路径不得破坏已有库。整次接力在一个 em_frag_import 事务内完成。任一分块 CRC 失败 → 重传 → 三次失败则 abort → 已灌入的记忆必须完好如初。

7. 三种碎片接力模式

模式名称流程适用约束
M1直连取块
Direct
请求方与提供方同时在线,走上述六原语时序 同局域网 / BLE 可达;小到中等碎片 默认模式
M2Hub 中转
Relay
提供方离线,但其碎片已托管在 Hub。请求方向 Hub 取,Hub 代记双份账(给原提供方 + 给 Hub) 移动设备、间歇在线 Hub 须持有该碎片的完整副本与 owner 字段
M3离线投递
Sneakernet
用 USB MSC 把 .emf 拷到设备;账本靠 .emf 内嵌的 quota 字段与回执文件在下一次联网时对账 完全无网环境(野外巡检 S2 的核心) 账本最终一致;对账时以双方 ledger 并集为准,重复条目按 frag_id+seq 去重
M3 是本产品与云端记忆引擎(红熊笔记熊、mem0、Zep、Letta)的决定性差异。它们的记忆全在云端,没有离线投递这条路。S2 野外巡检场景正是靠 M3 成立的。

7.1 M3 离线投递的回执格式

/* 投递方生成 .emf 时同时生成 .emr(回执) */
{
  "v":1,
  "from":"EME-21E980",
  "to":"*",                       /* 未知目的,联网后补 */
  "frag_id":9, "name":"expert-pack-v3", "ver":3,
  "bytes":1188000, "quota":36,
  "delivered_ms":1770000000000,
  "crc32":"0x8A3F2C11"
}
/* 接收方联网后把 .emr 回传给 Hub,Hub 合并进账本 */

8. 账本与配额(合规红线)

这是本项目最容易出事的地方,请所有 UI / 文档 / 文案负责人逐字读完。
银发〔2026〕42 号《关于进一步防范和处置虚拟货币等相关风险的通知》明确:RWA 代币化境内严禁、境外严管,且「提供有关中介、信息技术服务等」被一并点名。

8.1 配额的定义

属性规定
名称配额(quota),单位「点」。设备间内部记账单位
可兑换性不可兑换法币、不可兑换任何虚拟资产、不可转让给第三方
提现不存在。没有任何提现通道,也不得在 UI 中出现该词
交易场所不存在。不得提供任何撮合、挂牌、报价界面
用途仅用于设备间协作的计量与反滥用(防止某台设备无限索取碎片)
初始分配每台设备出厂固定额度,不得增发

8.2 记账规则

  1. 每条账目:{seq, from, to, frag_id, bytes, quota, ts},seq 设备内单调
  2. 双向一致:请求方记「−quota」,提供方记「+quota」。对账误差必须为 0(G9)
  3. 配额不足 → 返回 ERR_QUOTA_EXCEEDED,不得降级为「先给数据后补账」
  4. 账本只保留最近 N 条(默认 4,096),超出滚动覆盖,但必须保证已对账区段不被覆盖
  5. 账本参与 store.map 的同源输出(02 号分册 6.2 节)

8.3 UI / 文案禁用词(发布前逐屏检查)

禁止出现:钱包、币价、代币、代币化、提现、收益、挖矿、算力市场、交易、撮合、上币、持仓、K 线、DePIN、RWA。

可用表述:配额、协作计量、记账、点对点同步、知识接力。

9. 一致性模型与冲突消解

9.1 两级一致性

对象一致性机制
板内库强一致(ACID)WAL + CoW + 原子提交(02 号分册 3.3 节)。不允许最终一致
跨设备碎片最终一致版本向量 (frag_id, name, ver);高 ver 胜,同 ver 比 created_ms
账本对账后一致双向条目并集去重;误差必须为 0

9.2 冲突消解规则

冲突规则例外
同名碎片不同版本高 ver 胜;同 ver 取 created_ms 大者OVERWRITE_SAME_NAME 未置位时直接拒绝
同 ID 不同内容取 ts_ms 大者;旧条目标记 CONFLICTED 并降 prioPINNED 条目不参与覆盖
记忆条目语义重复余弦 > 0.95 → 合并(hit_count 累加)不同 scene 不合并
账目重复(M3 回执)按 frag_id + seq 去重—

10. 安全

项MVP 方案说明
配对首次连接需 mesh.pair,token 存入 NVS未配对时 LED 白双闪
消息鉴权配对后所有消息带 tok未配对只放行 mesh.advert / mesh.pair
OTA 鉴权token emgw-ota-demoMVP 后必须改为每设备独立 token
重放防护seq 单调 + ts 偏差 ≤ 5 min返回 ERR_CLOCK_SKEW
滥用防护配额 + 每设备速率上限返回 ERR_QUOTA_EXCEEDED
数据加密MVP 不加密(局域网内明文)P2 评估 BLE 链路加密与 TLS
MVP 安全定位:防误操作与防滥用,不防恶意攻击。对外不得宣称「端到端加密」或「安全可信」。

11. 现有固件改造清单

现有动作说明
/api/mesh/query改字段入参从算力规格改为 {scene, tags, vec_b64, k}
/api/mesh/bid改字段报价改为 {frag_id, ver, count, bytes, quota}
/api/mesh/request改字段支持分块 chunk_off / chunk_len
/api/mesh/result改字段返回碎片数据块 + CRC32
/api/mesh/award改语义从「结算给 winner」改为「配额记账」
mesh.query / mesh.ledger保留 + 扩字段命令名不变
link_mgr(BLE 1 usb-dongle + 2 gamma-card)直接复用链路管理不改
Kconfig 板级选项
EMGW_ROLE_EDGE / EMGW_ROLE_GATEWAY
改名改为 EMGW_FORM_GAMMA_CARD / EMGW_FORM_USB_DONGLE(二选一不变;ADR-018)
运行时角色字符串
edge / gateway
改值改为 gamma-card / usb-dongle;mesh.advert 字段名 role → form(ADR-018)
link.sync / hub.*保留M2 中转基于此
em_dev_unique_id()改前缀EMGW- → EME-,保留旧前缀兼容识别
新增—mesh.advert / mesh.pair / /api/mesh/sync

12. 测试用例索引

完整用例见 05 号分册 TC-M-*(12 条)。本节列出覆盖矩阵,便于查漏补缺。

能力用例判据
发现TC-M-01/02两板 30 s 内互相可见;离线设备 120 s 后从邻居表消失
M1 直连接力TC-M-03/04/05完整六原语时序跑通;分块 CRC 全过;中断后续传成功
M2 Hub 中转TC-M-06/07源离线时仍可取到;账本记双份
M3 离线投递TC-M-08/09MSC 拷入后可用;联网对账误差 0
账本TC-M-10双向对账误差 = 0(G9)
失败路径TC-M-11接力失败后已有库完好如初
配额TC-M-12配额耗尽返回 ERR_QUOTA_EXCEEDED,不得降级放行