syntax = "proto3"; package device; option go_package = "internal/domain/device/proto"; // --- 核心指令与数据结构 --- // 平台生成的原始485指令,单片机直接发送到总线 message Raw485Command { int32 bus_number = 1; // 总线号,用于指示单片机将指令发送到哪个总线 bytes command_bytes = 2; // 原始485指令的字节数组 } // 一个完整的、包含所有元数据的批量采集任务。 message BatchCollectCommand { string correlation_id = 1; // 用于关联请求和响应的唯一ID repeated CollectTask tasks = 2; // 采集任务列表 } // 定义了单个采集任务的“意图”。 message CollectTask { Raw485Command command = 1; // 平台生成的原始485指令 } // 这是设备响应的、极致精简的数据包。 message CollectResult { string correlation_id = 1; // 从下行指令中原样返回的关联ID repeated float values = 2; // 按预定顺序排列的采集值 } // 平台向设备发送的Ping指令,用于检查存活性。 message Ping { // 可以留空,指令本身即代表意图 } // 设备对Ping的响应,或设备主动上报的心跳。 // 它包含了设备的关键状态信息。 message Pong { string firmware_version = 1; // 当前固件版本 // 可以扩展更多状态, e.g., int32 uptime_seconds = 2; } // --- OTA 升级相关 --- // PrepareUpdateReq: 平台发送给设备,通知设备准备开始 OTA 升级 (下行) message PrepareUpdateReq { string version = 1; // 新固件版本号 uint32 task_id = 2; // 升级任务唯一ID string manifest_md5 = 3; // 清单文件的 MD5 校验和,用于设备初步校验清单文件完整性 } // RequestFile: 设备向平台请求特定文件 (包括清单文件和固件文件) (上行) message RequestFile { uint32 task_id = 1; // 升级任务ID string filepath = 2; // 请求的文件路径 (例如 "/manifest.json" 或 "/main.py") } // FileResponse: 平台响应设备请求,发送单个文件的完整内容 (下行) // LoRa 传输层会自动处理分片和重组,因此应用层可以直接发送完整的单个文件内容 message FileResponse { uint32 task_id = 1; // 升级任务ID string filepath = 2; // 设备上的目标路径 (例如 "/manifest.json" 或 "/main.py") bytes content = 3; // 文件的完整内容 } // UpdateStatusReport: 设备向平台报告升级状态 (上行) message UpdateStatusReport { uint32 task_id = 1; // 升级任务ID string current_version = 2; // 操作完成后的当前版本 enum Status { STATUS_UNSPECIFIED = 0; // 未指定,protobuf3 要求枚举从0开始 SUCCESS = 1; // 升级成功,新固件已运行 SUCCESS_ALREADY_UP_TO_DATE = 2; // 版本已是最新,未执行升级 FAILED_PRE_CHECK = 3; // 升级前检查失败 (例如拒绝降级、准备分区失败) FAILED_MANIFEST_VERIFY = 4; // 清单文件下载或校验失败 FAILED_DOWNLOAD = 5; // 固件文件下载或校验失败 FAILED_ROLLED_BACK = 6; // 新固件启动失败,已自动回滚 FAILED_TIMEOUT = 7; // 平台在超时后仍未收到SUCCESS报告,将任务标记为此状态 (平台推断) } Status status = 3; // 升级的最终状态 string error_message = 4; // 人类可读的详细错误信息 string failed_file = 5; // 失败时关联的文件路径 (可选) } // --- 顶层指令包装器 --- // Instruction 封装了所有与设备间的通信。 // 使用 oneof 来确保每个消息只有一个负载类型,这在嵌入式系统中是高效且类型安全的。 message Instruction { oneof payload { // --- 下行指令 (平台 -> 设备) --- Raw485Command raw_485_command = 1; BatchCollectCommand batch_collect_command = 2; Ping ping = 3; PrepareUpdateReq prepare_update_req = 4; FileResponse file_response = 5; // --- 上行数据 (设备 -> 平台) --- CollectResult collect_result = 101; Pong pong = 102; RequestFile request_file = 103; UpdateStatusReport update_status_report = 104; } }