cmvr-es/protos
xtkuang 428ee328de feat: complete QUIC edge integration
Vendor MsQuic with build and install support, add DeviceManager status to configurable heartbeats, and report only enabled devices.

Add the local QUIC gateway, protocol coverage, real MsQuic E2E tests, process smoke tests, and updated integration documentation.
2026-07-24 12:35:04 +08:00
..
cmvr feat: complete QUIC edge integration 2026-07-24 12:35:04 +08:00
rbk/protocol update src1100 module 2026-07-07 15:54:09 +08:00
README.md fix: bound gRPC camera stream latency 2026-07-23 14:22:09 +08:00

Protobuf 与协议开发指南

protos/ 是 CMVR-ES 配置、gRPC API、共享消息和 QUIC 控制面的契约源。生成代码由 CMake 创建,不应手工编辑或提交。

返回项目总览

目录职责

目录 职责
cmvr/api/ gRPC service 和 command DTO
cmvr/msgs/ 设备、状态和错误等共享消息
cmvr/config/ Proto Text 运行配置 Schema
cmvr/common/ 通用几何等跨领域消息
cmvr/quic_edge/v1/ QUIC reliable control message 和 v1 wire 文档
rbk/ 第三方/兼容协议 Schema

C++ 生成流程

CMakeLists.txt

  1. 递归收集 protos/**/*.proto
  2. 使用 protoc 生成 .pb.h/.pb.cc
  3. 使用 grpc_cpp_plugin 生成 .grpc.pb.h/.grpc.pb.cc
  4. 输出到 build/_protobuf/
  5. 打包为 cmvr_es::proto

build/_protobuf/ 是构建产物,不手改、不提交。

当前使用 file(GLOB_RECURSE ...) 且没有 CONFIGURE_DEPENDS。新增 Proto 文件后必须重新执行 CMake configure

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMVR_ARCH=x86

cmake --build build -j"$(nproc)"

protocgrpc_cpp_plugin 当前固定从 output/bin/ 使用。干净环境首次构建先执行根 README 的工具引导步骤。

通用兼容规则

已发布协议中禁止:

  • 修改或复用字段号;
  • 修改 enum 数值含义;
  • 修改 oneof tag
  • 修改字段 wire type
  • 修改 gRPC package、service 或 method 全名;
  • 将原本可选的字段改成必填语义;
  • 把同一字段单位从 m 改成 mm 等隐式破坏。

删除字段时同时 reserved 字段号和名称:

message Example {
  reserved 2;
  reserved "old_field";

  string id = 1;
  string new_field = 3;
}

新增字段使用新 tag。需要区分“缺失”和“零值”时使用 proto3 optional,并验证目标语言工具链支持。

破坏性 gRPC 变化应创建版本化 package/service而不是原地改变旧方法。

配置 Proto

配置也必须考虑已部署 .pb.txt

  • 新 scalar 的零值不能自动成为危险默认值;
  • C++ 必须做范围和跨字段校验;
  • enum unknown、oneof 未设置应明确失败;
  • root message 命名保持 XxxRootConfig
  • 字段注释写明单位、范围和安全语义;
  • Schema 变更同步 ../cmvr-es/config/README.md 与样例配置。

TextFormat 使用字段名,因此随意重命名字段同样会破坏旧配置。

gRPC API

推荐一个领域拆分为:

cmvr/api/example_command.proto
cmvr/api/example_service.proto

service 文件 import command 文件。公共 header、错误和时间戳复用 common.proto,不要复制出多个略有差异的定义。

新增 API 后还需要:

  1. 实现 C++ service
  2. 加入 service CMake target
  3. 在 GrpcServerTask 中构造和注册;
  4. 生成 Java client
  5. 增加 handler、reflection 和 grpcurl 测试。

完整流程见 ../cmvr-es/service/README.md

cmvr/api/test_service.proto 当前没有实现或注册,且包含历史拼写 TestReqeust,不要把它作为新 API 模板。

QUIC Edge v1

当前固定契约:

  • packagecmvr.quic_edge.v1
  • protocol_version = 1
  • ALPNcmvr-quic-edge/1
  • reliable streamuint32_be length + EdgeControlEnvelope
  • media DATAGRAM固定 64 字节非 Protobuf header + payload

完整字段和偏移见 cmvr/quic_edge/v1/README.md

破坏 framing、固定头、状态机或时序时必须建立新协议版本、package 和 ALPN不能只修改 Proto。

新增 control envelope payload 时:

  • 使用未占用的新 oneof tag
  • 同步 edge 发送/dispatch 和状态机;
  • 同步 message/session/heartbeat sequence 校验;
  • 同步 Java Gateway
  • 更新 wire 文档;
  • 增加 golden vector 和 fake transport 测试。

Edge 当前入站只实现 RegisterResponse、HeartbeatAck 和 ProtocolError。Proto 中存在的消息不等于两个方向都已实现。

每次 QUIC 连接建立后Edge 的出站 control message_sequence0 重新开始,因此首个 NodeRegisterRequest.message_sequence 当前为 0。Gateway 必须接受该起始值,不能假设从 1 开始;后续只要求同一发送方向严格递增,允许出现间隔。

QUIC stream 与 DATAGRAM 没有跨通道到达顺序保证。Gateway 不能假设 session/descriptor 一定先于媒体到达。

Java 生成

仓库只自动生成 C++。Java 平台应在自己的 Gradle/Maven 工程中锁定:

  • protoc
  • protobuf-java
  • protoc-gen-grpc-java
  • grpc-java

并以 protos/ 作为 import root。

QUIC Gateway 只需普通 Protobuf Java message

output/bin/protoc \
  -I protos \
  --java_out=platform-gateway/src/main/java \
  protos/cmvr/quic_edge/v1/quic_edge.proto

gRPC Java client 还需要 grpc-java plugin。当前 Proto 没有统一 java_packagejava_multiple_files,增加这些 option 时应同步两端生成结果和平台 import。

cmvr.api.FrameData 的字段 713 是可选的实时流诊断信息,包括边缘端采集 UTC 时间、源序列、PTS/DTS、SDK 帧率、SDK 原始时间戳和帧号。旧客户端会安全忽略 这些字段Java 平台需要重新生成 message 和 stub 才能读取它们。SDK 原始时间戳 的单位和时钟域由设备定义,不能按 Unix 时间直接解释。

浏览器不能直接消费自定义 QUIC ALPN不应从这些 Proto 推导“浏览器可直连 Edge”。

Review 与验证

# 重新生成并编译 C++
cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMVR_ARCH=x86
cmake --build build -j"$(nproc)"

# 验证当前自动测试
ctest --test-dir build --output-on-failure

# 验证运行时 reflection
/tmp/grpcurl -plaintext 127.0.0.1:50052 list

评审清单:

  • 新字段只使用新 tag
  • 删除字段同时 reserved number 和 name
  • enum 数值和语义兼容
  • 旧 pb.txt 仍可解析
  • C++ 重新 configure 并生成
  • Java/其他语言生成成功
  • service 已真正注册
  • grpcurl reflection 与预期一致
  • QUIC wire 文档和测试同步更新
  • 破坏性变化采用新版本