diff --git a/design/ota-upgrade-and-log-monitoring/index.md b/design/ota-upgrade-and-log-monitoring/index.md index ac239b5..9bcb218 100644 --- a/design/ota-upgrade-and-log-monitoring/index.md +++ b/design/ota-upgrade-and-log-monitoring/index.md @@ -8,13 +8,13 @@ http://git.huangwc.com/pig/pig-farm-controller/issues/71 # 开发计划 +## Lora 监听逻辑重构 + +- [x] [Lora逻辑重构](design/ota-upgrade-and-log-monitoring/lora_refactoring_plan.md) + ## OTA 升级 - [x] 增加一个proto对象, 用于封装ota升级包 - [x] 区域主控增加版本号 - [x] 增加ping指令并获取带版本号的响应 - [ ] [实现ota升级逻辑](design/ota-upgrade-and-log-monitoring/ota_upgrade_solution.md) - -## Lora 监听逻辑重构 - -- [x] [Lora逻辑重构](design/ota-upgrade-and-log-monitoring/lora_refactoring_plan.md) diff --git a/design/ota-upgrade-and-log-monitoring/ota_upgrade_solution.md b/design/ota-upgrade-and-log-monitoring/ota_upgrade_solution.md index b573715..c4a8e33 100644 --- a/design/ota-upgrade-and-log-monitoring/ota_upgrade_solution.md +++ b/design/ota-upgrade-and-log-monitoring/ota_upgrade_solution.md @@ -93,7 +93,6 @@ message PrepareUpdateReq { message RequestFile { string task_id = 1; // 升级任务ID string filepath = 2; // 请求的文件路径 (例如 "/manifest.json" 或 "/main.py") - uint32 retry_count = 3; // 设备请求该文件的重试次数 } // FileResponse: 平台响应设备请求,发送单个文件的完整内容 @@ -106,9 +105,8 @@ message FileResponse { // UpdateStatusReport: 设备向平台报告升级状态 message UpdateStatusReport { - string device_id = 1; // 设备ID - string task_id = 2; // 升级任务ID - string current_version = 3; // 操作完成后的当前版本 + string task_id = 1; // 升级任务ID + string current_version = 2; // 操作完成后的当前版本 enum Status { STATUS_UNKNOWN = 0; @@ -121,9 +119,9 @@ message UpdateStatusReport { // --- 平台推断的状态 (数据库记录用) --- FAILED_TIMEOUT = 5; // 平台在超时后仍未收到SUCCESS报告,将任务标记为此状态 } - Status status = 4; // 升级的最终状态 - string error_message = 6; // 人类可读的详细错误信息 - string failed_file = 7; // 失败时关联的文件路径 (可选) + Status status = 3; // 升级的最终状态 + string error_message = 4; // 人类可读的详细错误信息 + string failed_file = 5; // 失败时关联的文件路径 (可选) } ``` diff --git a/internal/infra/transport/proto/device.pb.go b/internal/infra/transport/proto/device.pb.go index e39bf9f..7d8b303 100644 --- a/internal/infra/transport/proto/device.pb.go +++ b/internal/infra/transport/proto/device.pb.go @@ -21,121 +21,68 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// LogLevel 定义了日志的严重级别。 -type LogLevel int32 +type UpdateStatusReport_Status int32 const ( - LogLevel_LOG_LEVEL_UNSPECIFIED LogLevel = 0 // 未指定 - LogLevel_DEBUG LogLevel = 1 // 调试信息 - LogLevel_INFO LogLevel = 2 // 普通信息 - LogLevel_WARN LogLevel = 3 // 警告 - LogLevel_ERROR LogLevel = 4 // 错误 + UpdateStatusReport_STATUS_UNSPECIFIED UpdateStatusReport_Status = 0 // 未指定,protobuf3 要求枚举从0开始 + UpdateStatusReport_SUCCESS UpdateStatusReport_Status = 1 // 升级成功,新固件已运行 + UpdateStatusReport_SUCCESS_ALREADY_UP_TO_DATE UpdateStatusReport_Status = 2 // 版本已是最新,未执行升级 + UpdateStatusReport_FAILED_PRE_CHECK UpdateStatusReport_Status = 3 // 升级前检查失败 (例如拒绝降级、准备分区失败) + UpdateStatusReport_FAILED_MANIFEST_VERIFY UpdateStatusReport_Status = 4 // 清单文件下载或校验失败 + UpdateStatusReport_FAILED_DOWNLOAD UpdateStatusReport_Status = 5 // 固件文件下载或校验失败 + UpdateStatusReport_FAILED_ROLLED_BACK UpdateStatusReport_Status = 6 // 新固件启动失败,已自动回滚 + UpdateStatusReport_FAILED_TIMEOUT UpdateStatusReport_Status = 7 // 平台在超时后仍未收到SUCCESS报告,将任务标记为此状态 (平台推断) ) -// Enum value maps for LogLevel. +// Enum value maps for UpdateStatusReport_Status. var ( - LogLevel_name = map[int32]string{ - 0: "LOG_LEVEL_UNSPECIFIED", - 1: "DEBUG", - 2: "INFO", - 3: "WARN", - 4: "ERROR", + UpdateStatusReport_Status_name = map[int32]string{ + 0: "STATUS_UNSPECIFIED", + 1: "SUCCESS", + 2: "SUCCESS_ALREADY_UP_TO_DATE", + 3: "FAILED_PRE_CHECK", + 4: "FAILED_MANIFEST_VERIFY", + 5: "FAILED_DOWNLOAD", + 6: "FAILED_ROLLED_BACK", + 7: "FAILED_TIMEOUT", } - LogLevel_value = map[string]int32{ - "LOG_LEVEL_UNSPECIFIED": 0, - "DEBUG": 1, - "INFO": 2, - "WARN": 3, - "ERROR": 4, + UpdateStatusReport_Status_value = map[string]int32{ + "STATUS_UNSPECIFIED": 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, } ) -func (x LogLevel) Enum() *LogLevel { - p := new(LogLevel) +func (x UpdateStatusReport_Status) Enum() *UpdateStatusReport_Status { + p := new(UpdateStatusReport_Status) *p = x return p } -func (x LogLevel) String() string { +func (x UpdateStatusReport_Status) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (LogLevel) Descriptor() protoreflect.EnumDescriptor { +func (UpdateStatusReport_Status) Descriptor() protoreflect.EnumDescriptor { return file_device_proto_enumTypes[0].Descriptor() } -func (LogLevel) Type() protoreflect.EnumType { +func (UpdateStatusReport_Status) Type() protoreflect.EnumType { return &file_device_proto_enumTypes[0] } -func (x LogLevel) Number() protoreflect.EnumNumber { +func (x UpdateStatusReport_Status) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// Deprecated: Use LogLevel.Descriptor instead. -func (LogLevel) EnumDescriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{0} -} - -// LogEntry 代表一条由设备生成的日志记录。 -type LogEntry struct { - state protoimpl.MessageState `protogen:"open.v1"` - TimestampUnix int64 `protobuf:"varint,1,opt,name=timestamp_unix,json=timestampUnix,proto3" json:"timestamp_unix,omitempty"` // 日志生成的Unix时间戳 (秒) - Level LogLevel `protobuf:"varint,2,opt,name=level,proto3,enum=device.LogLevel" json:"level,omitempty"` // 日志级别 - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` // 日志内容 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *LogEntry) Reset() { - *x = LogEntry{} - mi := &file_device_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *LogEntry) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LogEntry) ProtoMessage() {} - -func (x *LogEntry) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LogEntry.ProtoReflect.Descriptor instead. -func (*LogEntry) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{0} -} - -func (x *LogEntry) GetTimestampUnix() int64 { - if x != nil { - return x.TimestampUnix - } - return 0 -} - -func (x *LogEntry) GetLevel() LogLevel { - if x != nil { - return x.Level - } - return LogLevel_LOG_LEVEL_UNSPECIFIED -} - -func (x *LogEntry) GetMessage() string { - if x != nil { - return x.Message - } - return "" +// Deprecated: Use UpdateStatusReport_Status.Descriptor instead. +func (UpdateStatusReport_Status) EnumDescriptor() ([]byte, []int) { + return file_device_proto_rawDescGZIP(), []int{9, 0} } // 平台生成的原始485指令,单片机直接发送到总线 @@ -149,7 +96,7 @@ type Raw485Command struct { func (x *Raw485Command) Reset() { *x = Raw485Command{} - mi := &file_device_proto_msgTypes[1] + mi := &file_device_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -161,7 +108,7 @@ func (x *Raw485Command) String() string { func (*Raw485Command) ProtoMessage() {} func (x *Raw485Command) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[1] + mi := &file_device_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -174,7 +121,7 @@ func (x *Raw485Command) ProtoReflect() protoreflect.Message { // Deprecated: Use Raw485Command.ProtoReflect.Descriptor instead. func (*Raw485Command) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{1} + return file_device_proto_rawDescGZIP(), []int{0} } func (x *Raw485Command) GetBusNumber() int32 { @@ -202,7 +149,7 @@ type BatchCollectCommand struct { func (x *BatchCollectCommand) Reset() { *x = BatchCollectCommand{} - mi := &file_device_proto_msgTypes[2] + mi := &file_device_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -214,7 +161,7 @@ func (x *BatchCollectCommand) String() string { func (*BatchCollectCommand) ProtoMessage() {} func (x *BatchCollectCommand) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[2] + mi := &file_device_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -227,7 +174,7 @@ func (x *BatchCollectCommand) ProtoReflect() protoreflect.Message { // Deprecated: Use BatchCollectCommand.ProtoReflect.Descriptor instead. func (*BatchCollectCommand) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{2} + return file_device_proto_rawDescGZIP(), []int{1} } func (x *BatchCollectCommand) GetCorrelationId() string { @@ -254,7 +201,7 @@ type CollectTask struct { func (x *CollectTask) Reset() { *x = CollectTask{} - mi := &file_device_proto_msgTypes[3] + mi := &file_device_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -266,7 +213,7 @@ func (x *CollectTask) String() string { func (*CollectTask) ProtoMessage() {} func (x *CollectTask) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[3] + mi := &file_device_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -279,7 +226,7 @@ func (x *CollectTask) ProtoReflect() protoreflect.Message { // Deprecated: Use CollectTask.ProtoReflect.Descriptor instead. func (*CollectTask) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{3} + return file_device_proto_rawDescGZIP(), []int{2} } func (x *CollectTask) GetCommand() *Raw485Command { @@ -300,7 +247,7 @@ type CollectResult struct { func (x *CollectResult) Reset() { *x = CollectResult{} - mi := &file_device_proto_msgTypes[4] + mi := &file_device_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -312,7 +259,7 @@ func (x *CollectResult) String() string { func (*CollectResult) ProtoMessage() {} func (x *CollectResult) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[4] + mi := &file_device_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -325,7 +272,7 @@ func (x *CollectResult) ProtoReflect() protoreflect.Message { // Deprecated: Use CollectResult.ProtoReflect.Descriptor instead. func (*CollectResult) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{4} + return file_device_proto_rawDescGZIP(), []int{3} } func (x *CollectResult) GetCorrelationId() string { @@ -342,220 +289,6 @@ func (x *CollectResult) GetValues() []float32 { return nil } -// OTA(空中下载)升级指令,包含完整的固件包。 -type OtaUpgradeCommand struct { - state protoimpl.MessageState `protogen:"open.v1"` - FirmwareVersion string `protobuf:"bytes,1,opt,name=firmware_version,json=firmwareVersion,proto3" json:"firmware_version,omitempty"` // 目标固件版本, e.g., "v1.2.3" - FirmwareHash string `protobuf:"bytes,2,opt,name=firmware_hash,json=firmwareHash,proto3" json:"firmware_hash,omitempty"` // 固件包的SHA-256哈希值,用于完整性校验 - FirmwarePackage []byte `protobuf:"bytes,3,opt,name=firmware_package,json=firmwarePackage,proto3" json:"firmware_package,omitempty"` // 完整的固件二进制文件 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OtaUpgradeCommand) Reset() { - *x = OtaUpgradeCommand{} - mi := &file_device_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OtaUpgradeCommand) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OtaUpgradeCommand) ProtoMessage() {} - -func (x *OtaUpgradeCommand) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OtaUpgradeCommand.ProtoReflect.Descriptor instead. -func (*OtaUpgradeCommand) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{5} -} - -func (x *OtaUpgradeCommand) GetFirmwareVersion() string { - if x != nil { - return x.FirmwareVersion - } - return "" -} - -func (x *OtaUpgradeCommand) GetFirmwareHash() string { - if x != nil { - return x.FirmwareHash - } - return "" -} - -func (x *OtaUpgradeCommand) GetFirmwarePackage() []byte { - if x != nil { - return x.FirmwarePackage - } - return nil -} - -// 设备端执行OTA升级后的状态报告 (上行)。 -type OtaUpgradeStatus struct { - state protoimpl.MessageState `protogen:"open.v1"` - // 状态码: 0=成功, 1=哈希校验失败, 2=烧录失败, 3=空间不足, 99=其他未知错误 - StatusCode int32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"` - // 设备当前运行的固件版本 (升级后或升级失败时) - CurrentFirmwareVersion string `protobuf:"bytes,2,opt,name=current_firmware_version,json=currentFirmwareVersion,proto3" json:"current_firmware_version,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OtaUpgradeStatus) Reset() { - *x = OtaUpgradeStatus{} - mi := &file_device_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OtaUpgradeStatus) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OtaUpgradeStatus) ProtoMessage() {} - -func (x *OtaUpgradeStatus) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OtaUpgradeStatus.ProtoReflect.Descriptor instead. -func (*OtaUpgradeStatus) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{6} -} - -func (x *OtaUpgradeStatus) GetStatusCode() int32 { - if x != nil { - return x.StatusCode - } - return 0 -} - -func (x *OtaUpgradeStatus) GetCurrentFirmwareVersion() string { - if x != nil { - return x.CurrentFirmwareVersion - } - return "" -} - -// 控制设备日志上传的指令 (下行)。 -type ControlLogUploadCommand struct { - state protoimpl.MessageState `protogen:"open.v1"` - Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"` // true = 开始上传, false = 停止上传 - DurationSeconds uint32 `protobuf:"varint,2,opt,name=duration_seconds,json=durationSeconds,proto3" json:"duration_seconds,omitempty"` // 指定上传持续时间(秒)。 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ControlLogUploadCommand) Reset() { - *x = ControlLogUploadCommand{} - mi := &file_device_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ControlLogUploadCommand) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ControlLogUploadCommand) ProtoMessage() {} - -func (x *ControlLogUploadCommand) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ControlLogUploadCommand.ProtoReflect.Descriptor instead. -func (*ControlLogUploadCommand) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{7} -} - -func (x *ControlLogUploadCommand) GetEnable() bool { - if x != nil { - return x.Enable - } - return false -} - -func (x *ControlLogUploadCommand) GetDurationSeconds() uint32 { - if x != nil { - return x.DurationSeconds - } - return 0 -} - -// 设备用于向平台批量上传日志的请求 (上行)。 -type LogUploadRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Entries []*LogEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` // 一批日志条目 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *LogUploadRequest) Reset() { - *x = LogUploadRequest{} - mi := &file_device_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *LogUploadRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LogUploadRequest) ProtoMessage() {} - -func (x *LogUploadRequest) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LogUploadRequest.ProtoReflect.Descriptor instead. -func (*LogUploadRequest) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{8} -} - -func (x *LogUploadRequest) GetEntries() []*LogEntry { - if x != nil { - return x.Entries - } - return nil -} - // 平台向设备发送的Ping指令,用于检查存活性。 type Ping struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -565,7 +298,7 @@ type Ping struct { func (x *Ping) Reset() { *x = Ping{} - mi := &file_device_proto_msgTypes[9] + mi := &file_device_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -577,7 +310,7 @@ func (x *Ping) String() string { func (*Ping) ProtoMessage() {} func (x *Ping) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[9] + mi := &file_device_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -590,7 +323,7 @@ func (x *Ping) ProtoReflect() protoreflect.Message { // Deprecated: Use Ping.ProtoReflect.Descriptor instead. func (*Ping) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{9} + return file_device_proto_rawDescGZIP(), []int{4} } // 设备对Ping的响应,或设备主动上报的心跳。 @@ -604,7 +337,7 @@ type Pong struct { func (x *Pong) Reset() { *x = Pong{} - mi := &file_device_proto_msgTypes[10] + mi := &file_device_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -616,7 +349,7 @@ func (x *Pong) String() string { func (*Pong) ProtoMessage() {} func (x *Pong) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[10] + mi := &file_device_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -629,7 +362,7 @@ func (x *Pong) ProtoReflect() protoreflect.Message { // Deprecated: Use Pong.ProtoReflect.Descriptor instead. func (*Pong) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{10} + return file_device_proto_rawDescGZIP(), []int{5} } func (x *Pong) GetFirmwareVersion() string { @@ -639,6 +372,259 @@ func (x *Pong) GetFirmwareVersion() string { return "" } +// PrepareUpdateReq: 平台发送给设备,通知设备准备开始 OTA 升级 (下行) +type PrepareUpdateReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` // 新固件版本号 + TaskId string `protobuf:"bytes,2,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 升级任务唯一ID + ManifestMd5 string `protobuf:"bytes,3,opt,name=manifest_md5,json=manifestMd5,proto3" json:"manifest_md5,omitempty"` // 清单文件的 MD5 校验和,用于设备初步校验清单文件完整性 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrepareUpdateReq) Reset() { + *x = PrepareUpdateReq{} + mi := &file_device_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrepareUpdateReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrepareUpdateReq) ProtoMessage() {} + +func (x *PrepareUpdateReq) ProtoReflect() protoreflect.Message { + mi := &file_device_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrepareUpdateReq.ProtoReflect.Descriptor instead. +func (*PrepareUpdateReq) Descriptor() ([]byte, []int) { + return file_device_proto_rawDescGZIP(), []int{6} +} + +func (x *PrepareUpdateReq) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *PrepareUpdateReq) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *PrepareUpdateReq) GetManifestMd5() string { + if x != nil { + return x.ManifestMd5 + } + return "" +} + +// RequestFile: 设备向平台请求特定文件 (包括清单文件和固件文件) (上行) +type RequestFile struct { + state protoimpl.MessageState `protogen:"open.v1"` + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 升级任务ID + Filepath string `protobuf:"bytes,2,opt,name=filepath,proto3" json:"filepath,omitempty"` // 请求的文件路径 (例如 "/manifest.json" 或 "/main.py") + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RequestFile) Reset() { + *x = RequestFile{} + mi := &file_device_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RequestFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestFile) ProtoMessage() {} + +func (x *RequestFile) ProtoReflect() protoreflect.Message { + mi := &file_device_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestFile.ProtoReflect.Descriptor instead. +func (*RequestFile) Descriptor() ([]byte, []int) { + return file_device_proto_rawDescGZIP(), []int{7} +} + +func (x *RequestFile) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *RequestFile) GetFilepath() string { + if x != nil { + return x.Filepath + } + return "" +} + +// FileResponse: 平台响应设备请求,发送单个文件的完整内容 (下行) +// LoRa 传输层会自动处理分片和重组,因此应用层可以直接发送完整的单个文件内容 +type FileResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 升级任务ID + Filepath string `protobuf:"bytes,2,opt,name=filepath,proto3" json:"filepath,omitempty"` // 设备上的目标路径 (例如 "/manifest.json" 或 "/main.py") + Content []byte `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` // 文件的完整内容 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FileResponse) Reset() { + *x = FileResponse{} + mi := &file_device_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileResponse) ProtoMessage() {} + +func (x *FileResponse) ProtoReflect() protoreflect.Message { + mi := &file_device_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileResponse.ProtoReflect.Descriptor instead. +func (*FileResponse) Descriptor() ([]byte, []int) { + return file_device_proto_rawDescGZIP(), []int{8} +} + +func (x *FileResponse) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *FileResponse) GetFilepath() string { + if x != nil { + return x.Filepath + } + return "" +} + +func (x *FileResponse) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + +// UpdateStatusReport: 设备向平台报告升级状态 (上行) +type UpdateStatusReport struct { + state protoimpl.MessageState `protogen:"open.v1"` + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 升级任务ID + CurrentVersion string `protobuf:"bytes,2,opt,name=current_version,json=currentVersion,proto3" json:"current_version,omitempty"` // 操作完成后的当前版本 + Status UpdateStatusReport_Status `protobuf:"varint,3,opt,name=status,proto3,enum=device.UpdateStatusReport_Status" json:"status,omitempty"` // 升级的最终状态 + ErrorMessage string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` // 人类可读的详细错误信息 + FailedFile string `protobuf:"bytes,5,opt,name=failed_file,json=failedFile,proto3" json:"failed_file,omitempty"` // 失败时关联的文件路径 (可选) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateStatusReport) Reset() { + *x = UpdateStatusReport{} + mi := &file_device_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateStatusReport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStatusReport) ProtoMessage() {} + +func (x *UpdateStatusReport) ProtoReflect() protoreflect.Message { + mi := &file_device_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStatusReport.ProtoReflect.Descriptor instead. +func (*UpdateStatusReport) Descriptor() ([]byte, []int) { + return file_device_proto_rawDescGZIP(), []int{9} +} + +func (x *UpdateStatusReport) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *UpdateStatusReport) GetCurrentVersion() string { + if x != nil { + return x.CurrentVersion + } + return "" +} + +func (x *UpdateStatusReport) GetStatus() UpdateStatusReport_Status { + if x != nil { + return x.Status + } + return UpdateStatusReport_STATUS_UNSPECIFIED +} + +func (x *UpdateStatusReport) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +func (x *UpdateStatusReport) GetFailedFile() string { + if x != nil { + return x.FailedFile + } + return "" +} + // Instruction 封装了所有与设备间的通信。 // 使用 oneof 来确保每个消息只有一个负载类型,这在嵌入式系统中是高效且类型安全的。 type Instruction struct { @@ -647,13 +633,13 @@ type Instruction struct { // // *Instruction_Raw_485Command // *Instruction_BatchCollectCommand - // *Instruction_OtaUpgradeCommand - // *Instruction_ControlLogUploadCommand // *Instruction_Ping + // *Instruction_PrepareUpdateReq + // *Instruction_FileResponse // *Instruction_CollectResult - // *Instruction_OtaUpgradeStatus - // *Instruction_LogUploadRequest // *Instruction_Pong + // *Instruction_RequestFile + // *Instruction_UpdateStatusReport Payload isInstruction_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -661,7 +647,7 @@ type Instruction struct { func (x *Instruction) Reset() { *x = Instruction{} - mi := &file_device_proto_msgTypes[11] + mi := &file_device_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -673,7 +659,7 @@ func (x *Instruction) String() string { func (*Instruction) ProtoMessage() {} func (x *Instruction) ProtoReflect() protoreflect.Message { - mi := &file_device_proto_msgTypes[11] + mi := &file_device_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -686,7 +672,7 @@ func (x *Instruction) ProtoReflect() protoreflect.Message { // Deprecated: Use Instruction.ProtoReflect.Descriptor instead. func (*Instruction) Descriptor() ([]byte, []int) { - return file_device_proto_rawDescGZIP(), []int{11} + return file_device_proto_rawDescGZIP(), []int{10} } func (x *Instruction) GetPayload() isInstruction_Payload { @@ -714,24 +700,6 @@ func (x *Instruction) GetBatchCollectCommand() *BatchCollectCommand { return nil } -func (x *Instruction) GetOtaUpgradeCommand() *OtaUpgradeCommand { - if x != nil { - if x, ok := x.Payload.(*Instruction_OtaUpgradeCommand); ok { - return x.OtaUpgradeCommand - } - } - return nil -} - -func (x *Instruction) GetControlLogUploadCommand() *ControlLogUploadCommand { - if x != nil { - if x, ok := x.Payload.(*Instruction_ControlLogUploadCommand); ok { - return x.ControlLogUploadCommand - } - } - return nil -} - func (x *Instruction) GetPing() *Ping { if x != nil { if x, ok := x.Payload.(*Instruction_Ping); ok { @@ -741,6 +709,24 @@ func (x *Instruction) GetPing() *Ping { return nil } +func (x *Instruction) GetPrepareUpdateReq() *PrepareUpdateReq { + if x != nil { + if x, ok := x.Payload.(*Instruction_PrepareUpdateReq); ok { + return x.PrepareUpdateReq + } + } + return nil +} + +func (x *Instruction) GetFileResponse() *FileResponse { + if x != nil { + if x, ok := x.Payload.(*Instruction_FileResponse); ok { + return x.FileResponse + } + } + return nil +} + func (x *Instruction) GetCollectResult() *CollectResult { if x != nil { if x, ok := x.Payload.(*Instruction_CollectResult); ok { @@ -750,24 +736,6 @@ func (x *Instruction) GetCollectResult() *CollectResult { return nil } -func (x *Instruction) GetOtaUpgradeStatus() *OtaUpgradeStatus { - if x != nil { - if x, ok := x.Payload.(*Instruction_OtaUpgradeStatus); ok { - return x.OtaUpgradeStatus - } - } - return nil -} - -func (x *Instruction) GetLogUploadRequest() *LogUploadRequest { - if x != nil { - if x, ok := x.Payload.(*Instruction_LogUploadRequest); ok { - return x.LogUploadRequest - } - } - return nil -} - func (x *Instruction) GetPong() *Pong { if x != nil { if x, ok := x.Payload.(*Instruction_Pong); ok { @@ -777,6 +745,24 @@ func (x *Instruction) GetPong() *Pong { return nil } +func (x *Instruction) GetRequestFile() *RequestFile { + if x != nil { + if x, ok := x.Payload.(*Instruction_RequestFile); ok { + return x.RequestFile + } + } + return nil +} + +func (x *Instruction) GetUpdateStatusReport() *UpdateStatusReport { + if x != nil { + if x, ok := x.Payload.(*Instruction_UpdateStatusReport); ok { + return x.UpdateStatusReport + } + } + return nil +} + type isInstruction_Payload interface { isInstruction_Payload() } @@ -790,16 +776,16 @@ type Instruction_BatchCollectCommand struct { BatchCollectCommand *BatchCollectCommand `protobuf:"bytes,2,opt,name=batch_collect_command,json=batchCollectCommand,proto3,oneof"` } -type Instruction_OtaUpgradeCommand struct { - OtaUpgradeCommand *OtaUpgradeCommand `protobuf:"bytes,3,opt,name=ota_upgrade_command,json=otaUpgradeCommand,proto3,oneof"` -} - -type Instruction_ControlLogUploadCommand struct { - ControlLogUploadCommand *ControlLogUploadCommand `protobuf:"bytes,4,opt,name=control_log_upload_command,json=controlLogUploadCommand,proto3,oneof"` -} - type Instruction_Ping struct { - Ping *Ping `protobuf:"bytes,6,opt,name=ping,proto3,oneof"` + Ping *Ping `protobuf:"bytes,3,opt,name=ping,proto3,oneof"` +} + +type Instruction_PrepareUpdateReq struct { + PrepareUpdateReq *PrepareUpdateReq `protobuf:"bytes,4,opt,name=prepare_update_req,json=prepareUpdateReq,proto3,oneof"` +} + +type Instruction_FileResponse struct { + FileResponse *FileResponse `protobuf:"bytes,5,opt,name=file_response,json=fileResponse,proto3,oneof"` } type Instruction_CollectResult struct { @@ -807,45 +793,41 @@ type Instruction_CollectResult struct { CollectResult *CollectResult `protobuf:"bytes,101,opt,name=collect_result,json=collectResult,proto3,oneof"` } -type Instruction_OtaUpgradeStatus struct { - OtaUpgradeStatus *OtaUpgradeStatus `protobuf:"bytes,102,opt,name=ota_upgrade_status,json=otaUpgradeStatus,proto3,oneof"` -} - -type Instruction_LogUploadRequest struct { - LogUploadRequest *LogUploadRequest `protobuf:"bytes,103,opt,name=log_upload_request,json=logUploadRequest,proto3,oneof"` -} - type Instruction_Pong struct { - Pong *Pong `protobuf:"bytes,104,opt,name=pong,proto3,oneof"` + Pong *Pong `protobuf:"bytes,102,opt,name=pong,proto3,oneof"` +} + +type Instruction_RequestFile struct { + RequestFile *RequestFile `protobuf:"bytes,103,opt,name=request_file,json=requestFile,proto3,oneof"` +} + +type Instruction_UpdateStatusReport struct { + UpdateStatusReport *UpdateStatusReport `protobuf:"bytes,104,opt,name=update_status_report,json=updateStatusReport,proto3,oneof"` } func (*Instruction_Raw_485Command) isInstruction_Payload() {} func (*Instruction_BatchCollectCommand) isInstruction_Payload() {} -func (*Instruction_OtaUpgradeCommand) isInstruction_Payload() {} - -func (*Instruction_ControlLogUploadCommand) isInstruction_Payload() {} - func (*Instruction_Ping) isInstruction_Payload() {} +func (*Instruction_PrepareUpdateReq) isInstruction_Payload() {} + +func (*Instruction_FileResponse) isInstruction_Payload() {} + func (*Instruction_CollectResult) isInstruction_Payload() {} -func (*Instruction_OtaUpgradeStatus) isInstruction_Payload() {} - -func (*Instruction_LogUploadRequest) isInstruction_Payload() {} - func (*Instruction_Pong) isInstruction_Payload() {} +func (*Instruction_RequestFile) isInstruction_Payload() {} + +func (*Instruction_UpdateStatusReport) isInstruction_Payload() {} + var File_device_proto protoreflect.FileDescriptor const file_device_proto_rawDesc = "" + "\n" + - "\fdevice.proto\x12\x06device\"s\n" + - "\bLogEntry\x12%\n" + - "\x0etimestamp_unix\x18\x01 \x01(\x03R\rtimestampUnix\x12&\n" + - "\x05level\x18\x02 \x01(\x0e2\x10.device.LogLevelR\x05level\x12\x18\n" + - "\amessage\x18\x03 \x01(\tR\amessage\"S\n" + + "\fdevice.proto\x12\x06device\"S\n" + "\rRaw485Command\x12\x1d\n" + "\n" + "bus_number\x18\x01 \x01(\x05R\tbusNumber\x12#\n" + @@ -857,40 +839,48 @@ const file_device_proto_rawDesc = "" + "\acommand\x18\x01 \x01(\v2\x15.device.Raw485CommandR\acommand\"N\n" + "\rCollectResult\x12%\n" + "\x0ecorrelation_id\x18\x01 \x01(\tR\rcorrelationId\x12\x16\n" + - "\x06values\x18\x02 \x03(\x02R\x06values\"\x8e\x01\n" + - "\x11OtaUpgradeCommand\x12)\n" + - "\x10firmware_version\x18\x01 \x01(\tR\x0ffirmwareVersion\x12#\n" + - "\rfirmware_hash\x18\x02 \x01(\tR\ffirmwareHash\x12)\n" + - "\x10firmware_package\x18\x03 \x01(\fR\x0ffirmwarePackage\"m\n" + - "\x10OtaUpgradeStatus\x12\x1f\n" + - "\vstatus_code\x18\x01 \x01(\x05R\n" + - "statusCode\x128\n" + - "\x18current_firmware_version\x18\x02 \x01(\tR\x16currentFirmwareVersion\"\\\n" + - "\x17ControlLogUploadCommand\x12\x16\n" + - "\x06enable\x18\x01 \x01(\bR\x06enable\x12)\n" + - "\x10duration_seconds\x18\x02 \x01(\rR\x0fdurationSeconds\">\n" + - "\x10LogUploadRequest\x12*\n" + - "\aentries\x18\x01 \x03(\v2\x10.device.LogEntryR\aentries\"\x06\n" + + "\x06values\x18\x02 \x03(\x02R\x06values\"\x06\n" + "\x04Ping\"1\n" + "\x04Pong\x12)\n" + - "\x10firmware_version\x18\x01 \x01(\tR\x0ffirmwareVersion\"\xf5\x04\n" + + "\x10firmware_version\x18\x01 \x01(\tR\x0ffirmwareVersion\"h\n" + + "\x10PrepareUpdateReq\x12\x18\n" + + "\aversion\x18\x01 \x01(\tR\aversion\x12\x17\n" + + "\atask_id\x18\x02 \x01(\tR\x06taskId\x12!\n" + + "\fmanifest_md5\x18\x03 \x01(\tR\vmanifestMd5\"B\n" + + "\vRequestFile\x12\x17\n" + + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12\x1a\n" + + "\bfilepath\x18\x02 \x01(\tR\bfilepath\"]\n" + + "\fFileResponse\x12\x17\n" + + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12\x1a\n" + + "\bfilepath\x18\x02 \x01(\tR\bfilepath\x12\x18\n" + + "\acontent\x18\x03 \x01(\fR\acontent\"\x9a\x03\n" + + "\x12UpdateStatusReport\x12\x17\n" + + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12'\n" + + "\x0fcurrent_version\x18\x02 \x01(\tR\x0ecurrentVersion\x129\n" + + "\x06status\x18\x03 \x01(\x0e2!.device.UpdateStatusReport.StatusR\x06status\x12#\n" + + "\rerror_message\x18\x04 \x01(\tR\ferrorMessage\x12\x1f\n" + + "\vfailed_file\x18\x05 \x01(\tR\n" + + "failedFile\"\xc0\x01\n" + + "\x06Status\x12\x16\n" + + "\x12STATUS_UNSPECIFIED\x10\x00\x12\v\n" + + "\aSUCCESS\x10\x01\x12\x1e\n" + + "\x1aSUCCESS_ALREADY_UP_TO_DATE\x10\x02\x12\x14\n" + + "\x10FAILED_PRE_CHECK\x10\x03\x12\x1a\n" + + "\x16FAILED_MANIFEST_VERIFY\x10\x04\x12\x13\n" + + "\x0fFAILED_DOWNLOAD\x10\x05\x12\x16\n" + + "\x12FAILED_ROLLED_BACK\x10\x06\x12\x12\n" + + "\x0eFAILED_TIMEOUT\x10\a\"\xc5\x04\n" + "\vInstruction\x12?\n" + "\x0fraw_485_command\x18\x01 \x01(\v2\x15.device.Raw485CommandH\x00R\rraw485Command\x12Q\n" + - "\x15batch_collect_command\x18\x02 \x01(\v2\x1b.device.BatchCollectCommandH\x00R\x13batchCollectCommand\x12K\n" + - "\x13ota_upgrade_command\x18\x03 \x01(\v2\x19.device.OtaUpgradeCommandH\x00R\x11otaUpgradeCommand\x12^\n" + - "\x1acontrol_log_upload_command\x18\x04 \x01(\v2\x1f.device.ControlLogUploadCommandH\x00R\x17controlLogUploadCommand\x12\"\n" + - "\x04ping\x18\x06 \x01(\v2\f.device.PingH\x00R\x04ping\x12>\n" + - "\x0ecollect_result\x18e \x01(\v2\x15.device.CollectResultH\x00R\rcollectResult\x12H\n" + - "\x12ota_upgrade_status\x18f \x01(\v2\x18.device.OtaUpgradeStatusH\x00R\x10otaUpgradeStatus\x12H\n" + - "\x12log_upload_request\x18g \x01(\v2\x18.device.LogUploadRequestH\x00R\x10logUploadRequest\x12\"\n" + - "\x04pong\x18h \x01(\v2\f.device.PongH\x00R\x04pongB\t\n" + - "\apayload*O\n" + - "\bLogLevel\x12\x19\n" + - "\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\t\n" + - "\x05DEBUG\x10\x01\x12\b\n" + - "\x04INFO\x10\x02\x12\b\n" + - "\x04WARN\x10\x03\x12\t\n" + - "\x05ERROR\x10\x04B\x1eZ\x1cinternal/domain/device/protob\x06proto3" + "\x15batch_collect_command\x18\x02 \x01(\v2\x1b.device.BatchCollectCommandH\x00R\x13batchCollectCommand\x12\"\n" + + "\x04ping\x18\x03 \x01(\v2\f.device.PingH\x00R\x04ping\x12H\n" + + "\x12prepare_update_req\x18\x04 \x01(\v2\x18.device.PrepareUpdateReqH\x00R\x10prepareUpdateReq\x12;\n" + + "\rfile_response\x18\x05 \x01(\v2\x14.device.FileResponseH\x00R\ffileResponse\x12>\n" + + "\x0ecollect_result\x18e \x01(\v2\x15.device.CollectResultH\x00R\rcollectResult\x12\"\n" + + "\x04pong\x18f \x01(\v2\f.device.PongH\x00R\x04pong\x128\n" + + "\frequest_file\x18g \x01(\v2\x13.device.RequestFileH\x00R\vrequestFile\x12N\n" + + "\x14update_status_report\x18h \x01(\v2\x1a.device.UpdateStatusReportH\x00R\x12updateStatusReportB\t\n" + + "\apayloadB\x1eZ\x1cinternal/domain/device/protob\x06proto3" var ( file_device_proto_rawDescOnce sync.Once @@ -905,41 +895,39 @@ func file_device_proto_rawDescGZIP() []byte { } var file_device_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_device_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_device_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_device_proto_goTypes = []any{ - (LogLevel)(0), // 0: device.LogLevel - (*LogEntry)(nil), // 1: device.LogEntry - (*Raw485Command)(nil), // 2: device.Raw485Command - (*BatchCollectCommand)(nil), // 3: device.BatchCollectCommand - (*CollectTask)(nil), // 4: device.CollectTask - (*CollectResult)(nil), // 5: device.CollectResult - (*OtaUpgradeCommand)(nil), // 6: device.OtaUpgradeCommand - (*OtaUpgradeStatus)(nil), // 7: device.OtaUpgradeStatus - (*ControlLogUploadCommand)(nil), // 8: device.ControlLogUploadCommand - (*LogUploadRequest)(nil), // 9: device.LogUploadRequest - (*Ping)(nil), // 10: device.Ping - (*Pong)(nil), // 11: device.Pong - (*Instruction)(nil), // 12: device.Instruction + (UpdateStatusReport_Status)(0), // 0: device.UpdateStatusReport.Status + (*Raw485Command)(nil), // 1: device.Raw485Command + (*BatchCollectCommand)(nil), // 2: device.BatchCollectCommand + (*CollectTask)(nil), // 3: device.CollectTask + (*CollectResult)(nil), // 4: device.CollectResult + (*Ping)(nil), // 5: device.Ping + (*Pong)(nil), // 6: device.Pong + (*PrepareUpdateReq)(nil), // 7: device.PrepareUpdateReq + (*RequestFile)(nil), // 8: device.RequestFile + (*FileResponse)(nil), // 9: device.FileResponse + (*UpdateStatusReport)(nil), // 10: device.UpdateStatusReport + (*Instruction)(nil), // 11: device.Instruction } var file_device_proto_depIdxs = []int32{ - 0, // 0: device.LogEntry.level:type_name -> device.LogLevel - 4, // 1: device.BatchCollectCommand.tasks:type_name -> device.CollectTask - 2, // 2: device.CollectTask.command:type_name -> device.Raw485Command - 1, // 3: device.LogUploadRequest.entries:type_name -> device.LogEntry - 2, // 4: device.Instruction.raw_485_command:type_name -> device.Raw485Command - 3, // 5: device.Instruction.batch_collect_command:type_name -> device.BatchCollectCommand - 6, // 6: device.Instruction.ota_upgrade_command:type_name -> device.OtaUpgradeCommand - 8, // 7: device.Instruction.control_log_upload_command:type_name -> device.ControlLogUploadCommand - 10, // 8: device.Instruction.ping:type_name -> device.Ping - 5, // 9: device.Instruction.collect_result:type_name -> device.CollectResult - 7, // 10: device.Instruction.ota_upgrade_status:type_name -> device.OtaUpgradeStatus - 9, // 11: device.Instruction.log_upload_request:type_name -> device.LogUploadRequest - 11, // 12: device.Instruction.pong:type_name -> device.Pong - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 3, // 0: device.BatchCollectCommand.tasks:type_name -> device.CollectTask + 1, // 1: device.CollectTask.command:type_name -> device.Raw485Command + 0, // 2: device.UpdateStatusReport.status:type_name -> device.UpdateStatusReport.Status + 1, // 3: device.Instruction.raw_485_command:type_name -> device.Raw485Command + 2, // 4: device.Instruction.batch_collect_command:type_name -> device.BatchCollectCommand + 5, // 5: device.Instruction.ping:type_name -> device.Ping + 7, // 6: device.Instruction.prepare_update_req:type_name -> device.PrepareUpdateReq + 9, // 7: device.Instruction.file_response:type_name -> device.FileResponse + 4, // 8: device.Instruction.collect_result:type_name -> device.CollectResult + 6, // 9: device.Instruction.pong:type_name -> device.Pong + 8, // 10: device.Instruction.request_file:type_name -> device.RequestFile + 10, // 11: device.Instruction.update_status_report:type_name -> device.UpdateStatusReport + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_device_proto_init() } @@ -947,16 +935,16 @@ func file_device_proto_init() { if File_device_proto != nil { return } - file_device_proto_msgTypes[11].OneofWrappers = []any{ + file_device_proto_msgTypes[10].OneofWrappers = []any{ (*Instruction_Raw_485Command)(nil), (*Instruction_BatchCollectCommand)(nil), - (*Instruction_OtaUpgradeCommand)(nil), - (*Instruction_ControlLogUploadCommand)(nil), (*Instruction_Ping)(nil), + (*Instruction_PrepareUpdateReq)(nil), + (*Instruction_FileResponse)(nil), (*Instruction_CollectResult)(nil), - (*Instruction_OtaUpgradeStatus)(nil), - (*Instruction_LogUploadRequest)(nil), (*Instruction_Pong)(nil), + (*Instruction_RequestFile)(nil), + (*Instruction_UpdateStatusReport)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -964,7 +952,7 @@ func file_device_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_device_proto_rawDesc), len(file_device_proto_rawDesc)), NumEnums: 1, - NumMessages: 12, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/infra/transport/proto/device.proto b/internal/infra/transport/proto/device.proto index 9e83e1d..bcee6c0 100644 --- a/internal/infra/transport/proto/device.proto +++ b/internal/infra/transport/proto/device.proto @@ -4,24 +4,6 @@ package device; option go_package = "internal/domain/device/proto"; -// --- 日志相关 --- - -// LogLevel 定义了日志的严重级别。 -enum LogLevel { - LOG_LEVEL_UNSPECIFIED = 0; // 未指定 - DEBUG = 1; // 调试信息 - INFO = 2; // 普通信息 - WARN = 3; // 警告 - ERROR = 4; // 错误 -} - -// LogEntry 代表一条由设备生成的日志记录。 -message LogEntry { - int64 timestamp_unix = 1; // 日志生成的Unix时间戳 (秒) - LogLevel level = 2; // 日志级别 - string message = 3; // 日志内容 -} - // --- 核心指令与数据结构 --- // 平台生成的原始485指令,单片机直接发送到总线 @@ -47,32 +29,6 @@ message CollectResult { repeated float values = 2; // 按预定顺序排列的采集值 } -// OTA(空中下载)升级指令,包含完整的固件包。 -message OtaUpgradeCommand { - string firmware_version = 1; // 目标固件版本, e.g., "v1.2.3" - string firmware_hash = 2; // 固件包的SHA-256哈希值,用于完整性校验 - bytes firmware_package = 3; // 完整的固件二进制文件 -} - -// 设备端执行OTA升级后的状态报告 (上行)。 -message OtaUpgradeStatus { - // 状态码: 0=成功, 1=哈希校验失败, 2=烧录失败, 3=空间不足, 99=其他未知错误 - int32 status_code = 1; - // 设备当前运行的固件版本 (升级后或升级失败时) - string current_firmware_version = 2; -} - -// 控制设备日志上传的指令 (下行)。 -message ControlLogUploadCommand { - bool enable = 1; // true = 开始上传, false = 停止上传 - uint32 duration_seconds = 2; // 指定上传持续时间(秒)。 -} - -// 设备用于向平台批量上传日志的请求 (上行)。 -message LogUploadRequest { - repeated LogEntry entries = 1; // 一批日志条目 -} - // 平台向设备发送的Ping指令,用于检查存活性。 message Ping { // 可以留空,指令本身即代表意图 @@ -85,6 +41,48 @@ message Pong { // 可以扩展更多状态, e.g., int32 uptime_seconds = 2; } +// --- OTA 升级相关 --- + +// PrepareUpdateReq: 平台发送给设备,通知设备准备开始 OTA 升级 (下行) +message PrepareUpdateReq { + string version = 1; // 新固件版本号 + string task_id = 2; // 升级任务唯一ID + string manifest_md5 = 3; // 清单文件的 MD5 校验和,用于设备初步校验清单文件完整性 +} + +// RequestFile: 设备向平台请求特定文件 (包括清单文件和固件文件) (上行) +message RequestFile { + string task_id = 1; // 升级任务ID + string filepath = 2; // 请求的文件路径 (例如 "/manifest.json" 或 "/main.py") +} + +// FileResponse: 平台响应设备请求,发送单个文件的完整内容 (下行) +// LoRa 传输层会自动处理分片和重组,因此应用层可以直接发送完整的单个文件内容 +message FileResponse { + string task_id = 1; // 升级任务ID + string filepath = 2; // 设备上的目标路径 (例如 "/manifest.json" 或 "/main.py") + bytes content = 3; // 文件的完整内容 +} + +// UpdateStatusReport: 设备向平台报告升级状态 (上行) +message UpdateStatusReport { + string 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; // 失败时关联的文件路径 (可选) +} + // --- 顶层指令包装器 --- @@ -95,14 +93,14 @@ message Instruction { // --- 下行指令 (平台 -> 设备) --- Raw485Command raw_485_command = 1; BatchCollectCommand batch_collect_command = 2; - OtaUpgradeCommand ota_upgrade_command = 3; - ControlLogUploadCommand control_log_upload_command = 4; - Ping ping = 6; + Ping ping = 3; + PrepareUpdateReq prepare_update_req = 4; + FileResponse file_response = 5; // --- 上行数据 (设备 -> 平台) --- CollectResult collect_result = 101; - OtaUpgradeStatus ota_upgrade_status = 102; - LogUploadRequest log_upload_request = 103; - Pong pong = 104; + Pong pong = 102; + RequestFile request_file = 103; + UpdateStatusReport update_status_report = 104; } }