diff --git a/docs/docs.go b/docs/docs.go index 4f61ff5..89875f3 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1027,6 +1027,86 @@ const docTemplate = `{ } } }, + "/api/v1/area-controllers/ota/progress/{taskId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "根据任务ID查询指定OTA升级任务的当前进度", + "produces": [ + "application/json" + ], + "tags": [ + "区域主控管理" + ], + "summary": "查询OTA升级进度", + "parameters": [ + { + "type": "string", + "description": "OTA任务ID", + "name": "taskId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/controller.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/dto.OtaUpgradeProgressResponse" + } + } + } + ] + } + } + } + } + }, + "/api/v1/area-controllers/ota/tasks/{taskId}/stop": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "根据任务ID请求停止一个正在进行的OTA升级任务", + "produces": [ + "application/json" + ], + "tags": [ + "区域主控管理" + ], + "summary": "停止OTA升级任务", + "parameters": [ + { + "type": "string", + "description": "OTA任务ID", + "name": "taskId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, "/api/v1/area-controllers/{id}": { "get": { "security": [ @@ -1161,6 +1241,62 @@ const docTemplate = `{ } } }, + "/api/v1/area-controllers/{id}/ota/start": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "为指定的区域主控上传固件并启动一个OTA升级任务", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "区域主控管理" + ], + "summary": "启动区域主控OTA升级", + "parameters": [ + { + "type": "string", + "description": "区域主控ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "file", + "description": "固件压缩包文件", + "name": "firmware_file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/controller.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/dto.OtaUpgradeResponse" + } + } + } + ] + } + } + } + } + }, "/api/v1/device-templates": { "get": { "security": [ @@ -3828,6 +3964,7 @@ const docTemplate = `{ }, { "enum": [ + 7, -1, 0, 1, @@ -3837,12 +3974,12 @@ const docTemplate = `{ 5, -1, 5, - 6, - 7 + 6 ], "type": "integer", "format": "int32", "x-enum-varnames": [ + "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -3852,8 +3989,7 @@ const docTemplate = `{ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel", - "_numLevels" + "InvalidLevel" ], "name": "level", "in": "query" @@ -8252,6 +8388,44 @@ const docTemplate = `{ } } }, + "dto.OtaUpgradeProgressResponse": { + "type": "object", + "properties": { + "current_stage": { + "description": "当前阶段", + "allOf": [ + { + "$ref": "#/definitions/models.OTATaskStatus" + } + ] + }, + "executed_num": { + "description": "已执行步骤数", + "type": "integer" + }, + "message": { + "description": "状态消息", + "type": "string" + }, + "task_id": { + "description": "OTA 升级任务ID", + "type": "integer" + }, + "total_num": { + "description": "总步骤数", + "type": "integer" + } + } + }, + "dto.OtaUpgradeResponse": { + "type": "object", + "properties": { + "task_id": { + "description": "OTA 升级任务ID", + "type": "integer" + } + } + }, "dto.PaginationDTO": { "type": "object", "properties": { @@ -10168,9 +10342,11 @@ const docTemplate = `{ "models.AIModel": { "type": "string", "enum": [ + "None", "Gemini" ], "x-enum-varnames": [ + "AI_MODEL_NONE", "AI_MODEL_GEMINI" ] }, @@ -10333,6 +10509,53 @@ const docTemplate = `{ "NotifierTypeLog" ] }, + "models.OTATaskStatus": { + "type": "string", + "enum": [ + "待开始", + "进行中", + "成功", + "版本已是最新", + "预检失败", + "下载或校验失败", + "固件回滚", + "超时", + "平台内部错误" + ], + "x-enum-comments": { + "OTATaskStatusAlreadyUpToDate": "设备报告版本已是最新,未执行升级", + "OTATaskStatusFailedDownload": "设备报告文件下载或校验失败 (包括清单文件和固件文件)", + "OTATaskStatusFailedPreCheck": "设备报告升级前检查失败 (如拒绝降级、准备分区失败)", + "OTATaskStatusFailedRollback": "新固件启动失败,设备自动回滚", + "OTATaskStatusInProgress": "任务已下发,设备正在处理", + "OTATaskStatusPending": "任务已创建,等待下发", + "OTATaskStatusPlatformError": "平台处理过程中发生的非设备报告错误", + "OTATaskStatusSuccess": "设备报告升级成功,新固件已运行", + "OTATaskStatusTimedOut": "平台在超时后仍未收到最终报告" + }, + "x-enum-descriptions": [ + "任务已创建,等待下发", + "任务已下发,设备正在处理", + "设备报告升级成功,新固件已运行", + "设备报告版本已是最新,未执行升级", + "设备报告升级前检查失败 (如拒绝降级、准备分区失败)", + "设备报告文件下载或校验失败 (包括清单文件和固件文件)", + "新固件启动失败,设备自动回滚", + "平台在超时后仍未收到最终报告", + "平台处理过程中发生的非设备报告错误" + ], + "x-enum-varnames": [ + "OTATaskStatusPending", + "OTATaskStatusInProgress", + "OTATaskStatusSuccess", + "OTATaskStatusAlreadyUpToDate", + "OTATaskStatusFailedPreCheck", + "OTATaskStatusFailedDownload", + "OTATaskStatusFailedRollback", + "OTATaskStatusTimedOut", + "OTATaskStatusPlatformError" + ] + }, "models.Operator": { "type": "string", "enum": [ @@ -10700,7 +10923,8 @@ const docTemplate = `{ "告警通知", "通知刷新", "设备阈值检查", - "区域阈值检查" + "区域阈值检查", + "OTA升级检查任务" ], "x-enum-comments": { "TaskPlanAnalysis": "解析Plan的Task列表并添加到待执行队列的特殊任务", @@ -10710,6 +10934,7 @@ const docTemplate = `{ "TaskTypeFullCollection": "新增的全量采集任务", "TaskTypeHeartbeat": "区域主控心跳检测任务", "TaskTypeNotificationRefresh": "通知刷新任务", + "TaskTypeOTACheck": "OTA升级超时检查任务", "TaskTypeReleaseFeedWeight": "下料口释放指定重量任务", "TaskTypeWaiting": "等待任务" }, @@ -10722,7 +10947,8 @@ const docTemplate = `{ "告警通知任务", "通知刷新任务", "设备阈值检查任务", - "区域阈值检查任务" + "区域阈值检查任务", + "OTA升级超时检查任务" ], "x-enum-varnames": [ "TaskPlanAnalysis", @@ -10733,7 +10959,8 @@ const docTemplate = `{ "TaskTypeAlarmNotification", "TaskTypeNotificationRefresh", "TaskTypeDeviceThresholdCheck", - "TaskTypeAreaCollectorThresholdCheck" + "TaskTypeAreaCollectorThresholdCheck", + "TaskTypeOTACheck" ] }, "models.ValueDescriptor": { @@ -10769,6 +10996,7 @@ const docTemplate = `{ "type": "integer", "format": "int32", "enum": [ + 7, -1, 0, 1, @@ -10778,10 +11006,10 @@ const docTemplate = `{ 5, -1, 5, - 6, - 7 + 6 ], "x-enum-varnames": [ + "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -10791,8 +11019,7 @@ const docTemplate = `{ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel", - "_numLevels" + "InvalidLevel" ] } }, diff --git a/docs/swagger.json b/docs/swagger.json index db22f17..4fc3aa7 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1019,6 +1019,86 @@ } } }, + "/api/v1/area-controllers/ota/progress/{taskId}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "根据任务ID查询指定OTA升级任务的当前进度", + "produces": [ + "application/json" + ], + "tags": [ + "区域主控管理" + ], + "summary": "查询OTA升级进度", + "parameters": [ + { + "type": "string", + "description": "OTA任务ID", + "name": "taskId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/controller.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/dto.OtaUpgradeProgressResponse" + } + } + } + ] + } + } + } + } + }, + "/api/v1/area-controllers/ota/tasks/{taskId}/stop": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "根据任务ID请求停止一个正在进行的OTA升级任务", + "produces": [ + "application/json" + ], + "tags": [ + "区域主控管理" + ], + "summary": "停止OTA升级任务", + "parameters": [ + { + "type": "string", + "description": "OTA任务ID", + "name": "taskId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/controller.Response" + } + } + } + } + }, "/api/v1/area-controllers/{id}": { "get": { "security": [ @@ -1153,6 +1233,62 @@ } } }, + "/api/v1/area-controllers/{id}/ota/start": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "为指定的区域主控上传固件并启动一个OTA升级任务", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "区域主控管理" + ], + "summary": "启动区域主控OTA升级", + "parameters": [ + { + "type": "string", + "description": "区域主控ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "file", + "description": "固件压缩包文件", + "name": "firmware_file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/controller.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/dto.OtaUpgradeResponse" + } + } + } + ] + } + } + } + } + }, "/api/v1/device-templates": { "get": { "security": [ @@ -3820,6 +3956,7 @@ }, { "enum": [ + 7, -1, 0, 1, @@ -3829,12 +3966,12 @@ 5, -1, 5, - 6, - 7 + 6 ], "type": "integer", "format": "int32", "x-enum-varnames": [ + "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -3844,8 +3981,7 @@ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel", - "_numLevels" + "InvalidLevel" ], "name": "level", "in": "query" @@ -8244,6 +8380,44 @@ } } }, + "dto.OtaUpgradeProgressResponse": { + "type": "object", + "properties": { + "current_stage": { + "description": "当前阶段", + "allOf": [ + { + "$ref": "#/definitions/models.OTATaskStatus" + } + ] + }, + "executed_num": { + "description": "已执行步骤数", + "type": "integer" + }, + "message": { + "description": "状态消息", + "type": "string" + }, + "task_id": { + "description": "OTA 升级任务ID", + "type": "integer" + }, + "total_num": { + "description": "总步骤数", + "type": "integer" + } + } + }, + "dto.OtaUpgradeResponse": { + "type": "object", + "properties": { + "task_id": { + "description": "OTA 升级任务ID", + "type": "integer" + } + } + }, "dto.PaginationDTO": { "type": "object", "properties": { @@ -10160,9 +10334,11 @@ "models.AIModel": { "type": "string", "enum": [ + "None", "Gemini" ], "x-enum-varnames": [ + "AI_MODEL_NONE", "AI_MODEL_GEMINI" ] }, @@ -10325,6 +10501,53 @@ "NotifierTypeLog" ] }, + "models.OTATaskStatus": { + "type": "string", + "enum": [ + "待开始", + "进行中", + "成功", + "版本已是最新", + "预检失败", + "下载或校验失败", + "固件回滚", + "超时", + "平台内部错误" + ], + "x-enum-comments": { + "OTATaskStatusAlreadyUpToDate": "设备报告版本已是最新,未执行升级", + "OTATaskStatusFailedDownload": "设备报告文件下载或校验失败 (包括清单文件和固件文件)", + "OTATaskStatusFailedPreCheck": "设备报告升级前检查失败 (如拒绝降级、准备分区失败)", + "OTATaskStatusFailedRollback": "新固件启动失败,设备自动回滚", + "OTATaskStatusInProgress": "任务已下发,设备正在处理", + "OTATaskStatusPending": "任务已创建,等待下发", + "OTATaskStatusPlatformError": "平台处理过程中发生的非设备报告错误", + "OTATaskStatusSuccess": "设备报告升级成功,新固件已运行", + "OTATaskStatusTimedOut": "平台在超时后仍未收到最终报告" + }, + "x-enum-descriptions": [ + "任务已创建,等待下发", + "任务已下发,设备正在处理", + "设备报告升级成功,新固件已运行", + "设备报告版本已是最新,未执行升级", + "设备报告升级前检查失败 (如拒绝降级、准备分区失败)", + "设备报告文件下载或校验失败 (包括清单文件和固件文件)", + "新固件启动失败,设备自动回滚", + "平台在超时后仍未收到最终报告", + "平台处理过程中发生的非设备报告错误" + ], + "x-enum-varnames": [ + "OTATaskStatusPending", + "OTATaskStatusInProgress", + "OTATaskStatusSuccess", + "OTATaskStatusAlreadyUpToDate", + "OTATaskStatusFailedPreCheck", + "OTATaskStatusFailedDownload", + "OTATaskStatusFailedRollback", + "OTATaskStatusTimedOut", + "OTATaskStatusPlatformError" + ] + }, "models.Operator": { "type": "string", "enum": [ @@ -10692,7 +10915,8 @@ "告警通知", "通知刷新", "设备阈值检查", - "区域阈值检查" + "区域阈值检查", + "OTA升级检查任务" ], "x-enum-comments": { "TaskPlanAnalysis": "解析Plan的Task列表并添加到待执行队列的特殊任务", @@ -10702,6 +10926,7 @@ "TaskTypeFullCollection": "新增的全量采集任务", "TaskTypeHeartbeat": "区域主控心跳检测任务", "TaskTypeNotificationRefresh": "通知刷新任务", + "TaskTypeOTACheck": "OTA升级超时检查任务", "TaskTypeReleaseFeedWeight": "下料口释放指定重量任务", "TaskTypeWaiting": "等待任务" }, @@ -10714,7 +10939,8 @@ "告警通知任务", "通知刷新任务", "设备阈值检查任务", - "区域阈值检查任务" + "区域阈值检查任务", + "OTA升级超时检查任务" ], "x-enum-varnames": [ "TaskPlanAnalysis", @@ -10725,7 +10951,8 @@ "TaskTypeAlarmNotification", "TaskTypeNotificationRefresh", "TaskTypeDeviceThresholdCheck", - "TaskTypeAreaCollectorThresholdCheck" + "TaskTypeAreaCollectorThresholdCheck", + "TaskTypeOTACheck" ] }, "models.ValueDescriptor": { @@ -10761,6 +10988,7 @@ "type": "integer", "format": "int32", "enum": [ + 7, -1, 0, 1, @@ -10770,10 +10998,10 @@ 5, -1, 5, - 6, - 7 + 6 ], "x-enum-varnames": [ + "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -10783,8 +11011,7 @@ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel", - "_numLevels" + "InvalidLevel" ] } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index dfc6ebb..ad562e8 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -994,6 +994,31 @@ definitions: $ref: '#/definitions/dto.NutrientRawMaterialDTO' type: array type: object + dto.OtaUpgradeProgressResponse: + properties: + current_stage: + allOf: + - $ref: '#/definitions/models.OTATaskStatus' + description: 当前阶段 + executed_num: + description: 已执行步骤数 + type: integer + message: + description: 状态消息 + type: string + task_id: + description: OTA 升级任务ID + type: integer + total_num: + description: 总步骤数 + type: integer + type: object + dto.OtaUpgradeResponse: + properties: + task_id: + description: OTA 升级任务ID + type: integer + type: object dto.PaginationDTO: properties: page: @@ -2288,9 +2313,11 @@ definitions: type: object models.AIModel: enum: + - None - Gemini type: string x-enum-varnames: + - AI_MODEL_NONE - AI_MODEL_GEMINI models.AlarmCode: enum: @@ -2420,6 +2447,48 @@ definitions: - NotifierTypeWeChat - NotifierTypeLark - NotifierTypeLog + models.OTATaskStatus: + enum: + - 待开始 + - 进行中 + - 成功 + - 版本已是最新 + - 预检失败 + - 下载或校验失败 + - 固件回滚 + - 超时 + - 平台内部错误 + type: string + x-enum-comments: + OTATaskStatusAlreadyUpToDate: 设备报告版本已是最新,未执行升级 + OTATaskStatusFailedDownload: 设备报告文件下载或校验失败 (包括清单文件和固件文件) + OTATaskStatusFailedPreCheck: 设备报告升级前检查失败 (如拒绝降级、准备分区失败) + OTATaskStatusFailedRollback: 新固件启动失败,设备自动回滚 + OTATaskStatusInProgress: 任务已下发,设备正在处理 + OTATaskStatusPending: 任务已创建,等待下发 + OTATaskStatusPlatformError: 平台处理过程中发生的非设备报告错误 + OTATaskStatusSuccess: 设备报告升级成功,新固件已运行 + OTATaskStatusTimedOut: 平台在超时后仍未收到最终报告 + x-enum-descriptions: + - 任务已创建,等待下发 + - 任务已下发,设备正在处理 + - 设备报告升级成功,新固件已运行 + - 设备报告版本已是最新,未执行升级 + - 设备报告升级前检查失败 (如拒绝降级、准备分区失败) + - 设备报告文件下载或校验失败 (包括清单文件和固件文件) + - 新固件启动失败,设备自动回滚 + - 平台在超时后仍未收到最终报告 + - 平台处理过程中发生的非设备报告错误 + x-enum-varnames: + - OTATaskStatusPending + - OTATaskStatusInProgress + - OTATaskStatusSuccess + - OTATaskStatusAlreadyUpToDate + - OTATaskStatusFailedPreCheck + - OTATaskStatusFailedDownload + - OTATaskStatusFailedRollback + - OTATaskStatusTimedOut + - OTATaskStatusPlatformError models.Operator: enum: - < @@ -2724,6 +2793,7 @@ definitions: - 通知刷新 - 设备阈值检查 - 区域阈值检查 + - OTA升级检查任务 type: string x-enum-comments: TaskPlanAnalysis: 解析Plan的Task列表并添加到待执行队列的特殊任务 @@ -2733,6 +2803,7 @@ definitions: TaskTypeFullCollection: 新增的全量采集任务 TaskTypeHeartbeat: 区域主控心跳检测任务 TaskTypeNotificationRefresh: 通知刷新任务 + TaskTypeOTACheck: OTA升级超时检查任务 TaskTypeReleaseFeedWeight: 下料口释放指定重量任务 TaskTypeWaiting: 等待任务 x-enum-descriptions: @@ -2745,6 +2816,7 @@ definitions: - 通知刷新任务 - 设备阈值检查任务 - 区域阈值检查任务 + - OTA升级超时检查任务 x-enum-varnames: - TaskPlanAnalysis - TaskTypeWaiting @@ -2755,6 +2827,7 @@ definitions: - TaskTypeNotificationRefresh - TaskTypeDeviceThresholdCheck - TaskTypeAreaCollectorThresholdCheck + - TaskTypeOTACheck models.ValueDescriptor: properties: multiplier: @@ -2778,6 +2851,7 @@ definitions: - PlanTypeFilterSystem zapcore.Level: enum: + - 7 - -1 - 0 - 1 @@ -2788,10 +2862,10 @@ definitions: - -1 - 5 - 6 - - 7 format: int32 type: integer x-enum-varnames: + - _numLevels - DebugLevel - InfoLevel - WarnLevel @@ -2802,7 +2876,6 @@ definitions: - _minLevel - _maxLevel - InvalidLevel - - _numLevels info: contact: email: divano@example.com @@ -3542,6 +3615,86 @@ paths: summary: 更新区域主控信息 tags: - 区域主控管理 + /api/v1/area-controllers/{id}/ota/start: + post: + consumes: + - multipart/form-data + description: 为指定的区域主控上传固件并启动一个OTA升级任务 + parameters: + - description: 区域主控ID + in: path + name: id + required: true + type: string + - description: 固件压缩包文件 + in: formData + name: firmware_file + required: true + type: file + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/controller.Response' + - properties: + data: + $ref: '#/definitions/dto.OtaUpgradeResponse' + type: object + security: + - BearerAuth: [] + summary: 启动区域主控OTA升级 + tags: + - 区域主控管理 + /api/v1/area-controllers/ota/progress/{taskId}: + get: + description: 根据任务ID查询指定OTA升级任务的当前进度 + parameters: + - description: OTA任务ID + in: path + name: taskId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/controller.Response' + - properties: + data: + $ref: '#/definitions/dto.OtaUpgradeProgressResponse' + type: object + security: + - BearerAuth: [] + summary: 查询OTA升级进度 + tags: + - 区域主控管理 + /api/v1/area-controllers/ota/tasks/{taskId}/stop: + post: + description: 根据任务ID请求停止一个正在进行的OTA升级任务 + parameters: + - description: OTA任务ID + in: path + name: taskId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/controller.Response' + security: + - BearerAuth: [] + summary: 停止OTA升级任务 + tags: + - 区域主控管理 /api/v1/device-templates: get: description: 获取系统中所有设备模板的列表 @@ -5101,6 +5254,7 @@ paths: name: end_time type: string - enum: + - 7 - -1 - 0 - 1 @@ -5111,12 +5265,12 @@ paths: - -1 - 5 - 6 - - 7 format: int32 in: query name: level type: integer x-enum-varnames: + - _numLevels - DebugLevel - InfoLevel - WarnLevel @@ -5127,7 +5281,6 @@ paths: - _minLevel - _maxLevel - InvalidLevel - - _numLevels - enum: - 邮件 - 企业微信 diff --git a/internal/app/api/router.go b/internal/app/api/router.go index 3575a62..c2daa37 100644 --- a/internal/app/api/router.go +++ b/internal/app/api/router.go @@ -84,11 +84,14 @@ func (a *API) setupRoutes() { // 区域主控相关路由组 areaControllerGroup := authGroup.Group("/area-controllers") { - areaControllerGroup.POST("", a.areaControllerController.CreateAreaController) // 创建区域主控 - areaControllerGroup.GET("", a.areaControllerController.ListAreaControllers) // 获取区域主控列表 - areaControllerGroup.GET("/:id", a.areaControllerController.GetAreaController) // 获取单个区域主控 - areaControllerGroup.PUT("/:id", a.areaControllerController.UpdateAreaController) // 更新区域主控 - areaControllerGroup.DELETE("/:id", a.areaControllerController.DeleteAreaController) // 删除区域主控 + areaControllerGroup.POST("", a.areaControllerController.CreateAreaController) // 创建区域主控 + areaControllerGroup.GET("", a.areaControllerController.ListAreaControllers) // 获取区域主控列表 + areaControllerGroup.GET("/:id", a.areaControllerController.GetAreaController) // 获取单个区域主控 + areaControllerGroup.PUT("/:id", a.areaControllerController.UpdateAreaController) // 更新区域主控 + areaControllerGroup.DELETE("/:id", a.areaControllerController.DeleteAreaController) // 删除区域主控 + areaControllerGroup.POST("/:id/ota/start", a.areaControllerController.StartUpgrade) // 开始升级 + areaControllerGroup.GET("/ota/progress/:taskId", a.areaControllerController.GetUpgradeProgress) // 获取升级进度 + areaControllerGroup.POST("/ota/tasks/:taskId/stop", a.areaControllerController.StopUpgrade) // 停止升级 } logger.Debug("区域主控相关接口注册成功 (需要认证和审计)") diff --git a/internal/app/controller/device/area_controller_controller.go b/internal/app/controller/device/area_controller_controller.go index f0edf06..3b84cf7 100644 --- a/internal/app/controller/device/area_controller_controller.go +++ b/internal/app/controller/device/area_controller_controller.go @@ -198,3 +198,113 @@ func (c *AreaControllerController) DeleteAreaController(ctx echo.Context) error logger.Infof("%s: 区域主控删除成功, ID: %s", actionType, acID) return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "区域主控删除成功", nil, actionType, "区域主控删除成功", acID) } + +// StartUpgrade godoc +// @Summary 启动区域主控OTA升级 +// @Description 为指定的区域主控上传固件并启动一个OTA升级任务 +// @Tags 区域主控管理 +// @Security BearerAuth +// @Accept mpfd +// @Produce json +// @Param id path string true "区域主控ID" +// @Param firmware_file formData file true "固件压缩包文件" +// @Success 200 {object} controller.Response{data=dto.OtaUpgradeResponse} +// @Router /api/v1/area-controllers/{id}/ota/start [post] +func (c *AreaControllerController) StartUpgrade(ctx echo.Context) error { + reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "StartUpgrade") + const actionType = "启动区域主控OTA升级" + + acID := ctx.Param("id") + id, err := strconv.ParseUint(acID, 10, 64) + if err != nil { + logger.Errorf("%s: 无效的区域主控ID: %s", actionType, acID) + return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的区域主控ID: "+acID, actionType, "无效的ID", acID) + } + + var req dto.OtaUpgradeRequest + if err := ctx.Bind(&req); err != nil { + logger.Errorf("%s: 参数绑定失败: %v", actionType, err) + return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求: "+err.Error(), actionType, "请求绑定失败", req) + } + + resp, err := c.areaControllerService.StartUpgrade(reqCtx, uint32(id), &req) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + logger.Warnf("%s: 区域主控不存在, ID: %s", actionType, acID) + return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "区域主控未找到", actionType, "区域主控不存在", acID) + } + logger.Errorf("%s: 服务层启动升级失败: %v, ID: %s", actionType, err, acID) + return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "启动升级失败: "+err.Error(), actionType, "服务层启动升级失败", acID) + } + + logger.Infof("%s: 升级任务启动成功, 任务ID: %d", actionType, resp.TaskID) + return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "升级任务启动成功", resp, actionType, "升级任务启动成功", resp) +} + +// GetUpgradeProgress godoc +// @Summary 查询OTA升级进度 +// @Description 根据任务ID查询指定OTA升级任务的当前进度 +// @Tags 区域主控管理 +// @Security BearerAuth +// @Produce json +// @Param taskId path string true "OTA任务ID" +// @Success 200 {object} controller.Response{data=dto.OtaUpgradeProgressResponse} +// @Router /api/v1/area-controllers/ota/progress/{taskId} [get] +func (c *AreaControllerController) GetUpgradeProgress(ctx echo.Context) error { + reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetUpgradeProgress") + const actionType = "查询OTA升级进度" + + taskIDStr := ctx.Param("taskId") + taskID, err := strconv.ParseUint(taskIDStr, 10, 64) + if err != nil { + logger.Errorf("%s: 无效的任务ID: %s", actionType, taskIDStr) + return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的任务ID: "+taskIDStr, actionType, "无效的ID", taskIDStr) + } + + resp, err := c.areaControllerService.GetUpgradeProgress(reqCtx, uint32(taskID)) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + logger.Warnf("%s: 升级任务不存在, ID: %s", actionType, taskIDStr) + return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "升级任务未找到", actionType, "升级任务不存在", taskIDStr) + } + logger.Errorf("%s: 服务层查询进度失败: %v, ID: %s", actionType, err, taskIDStr) + return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "查询进度失败: "+err.Error(), actionType, "服务层查询进度失败", taskIDStr) + } + + logger.Infof("%s: 查询进度成功, 任务ID: %d", actionType, resp.TaskID) + return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "查询进度成功", resp, actionType, "查询进度成功", resp) +} + +// StopUpgrade godoc +// @Summary 停止OTA升级任务 +// @Description 根据任务ID请求停止一个正在进行的OTA升级任务 +// @Tags 区域主控管理 +// @Security BearerAuth +// @Produce json +// @Param taskId path string true "OTA任务ID" +// @Success 200 {object} controller.Response +// @Router /api/v1/area-controllers/ota/tasks/{taskId}/stop [post] +func (c *AreaControllerController) StopUpgrade(ctx echo.Context) error { + reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "StopUpgrade") + const actionType = "停止OTA升级任务" + + taskIDStr := ctx.Param("taskId") + taskID, err := strconv.ParseUint(taskIDStr, 10, 64) + if err != nil { + logger.Errorf("%s: 无效的任务ID: %s", actionType, taskIDStr) + return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的任务ID: "+taskIDStr, actionType, "无效的ID", taskIDStr) + } + + err = c.areaControllerService.StopUpgrade(reqCtx, uint32(taskID)) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + logger.Warnf("%s: 升级任务不存在, ID: %s", actionType, taskIDStr) + return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "升级任务未找到", actionType, "升级任务不存在", taskIDStr) + } + logger.Errorf("%s: 服务层停止任务失败: %v, ID: %s", actionType, err, taskIDStr) + return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "停止任务失败: "+err.Error(), actionType, "服务层停止任务失败", taskIDStr) + } + + logger.Infof("%s: 停止任务请求成功, 任务ID: %s", actionType, taskIDStr) + return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "停止任务请求成功", nil, actionType, "停止任务请求成功", taskIDStr) +} diff --git a/internal/app/dto/device_dto.go b/internal/app/dto/device_dto.go index d5bd843..a5e654e 100644 --- a/internal/app/dto/device_dto.go +++ b/internal/app/dto/device_dto.go @@ -1,6 +1,10 @@ package dto -import "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" +import ( + "mime/multipart" + + "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" +) // CreateDeviceRequest 定义了创建设备时需要传入的参数 type CreateDeviceRequest struct { @@ -101,3 +105,22 @@ type DeviceTemplateResponse struct { CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` } + +// OtaUpgradeRequest 定义了 OTA 升级请求时需要传入的参数 +type OtaUpgradeRequest struct { + FirmwareFile *multipart.FileHeader `form:"firmware_file" validate:"required"` // 固件压缩包文件 +} + +// OtaUpgradeResponse 定义了 OTA 升级响应的结构 +type OtaUpgradeResponse struct { + TaskID uint32 `json:"task_id"` // OTA 升级任务ID +} + +// OtaUpgradeProgressResponse 定义了 OTA 升级进度响应的结构 +type OtaUpgradeProgressResponse struct { + TaskID uint32 `json:"task_id"` // OTA 升级任务ID + CurrentStage models.OTATaskStatus `json:"current_stage"` // 当前阶段 + ExecutedNum uint32 `json:"executed_num"` // 已执行步骤数 + TotalNum uint32 `json:"total_num"` // 总步骤数 + Message string `json:"message"` // 状态消息 +} diff --git a/internal/app/service/area_controller_service.go b/internal/app/service/area_controller_service.go index b18fdb5..63ea715 100644 --- a/internal/app/service/area_controller_service.go +++ b/internal/app/service/area_controller_service.go @@ -18,6 +18,13 @@ type AreaControllerService interface { ListAreaControllers(ctx context.Context) ([]*dto.AreaControllerResponse, error) UpdateAreaController(ctx context.Context, id uint32, req *dto.UpdateAreaControllerRequest) (*dto.AreaControllerResponse, error) DeleteAreaController(ctx context.Context, id uint32) error + + // StartUpgrade 用于启动一个 OTA 升级任务。 + StartUpgrade(ctx context.Context, areaControllerID uint32, firmware *dto.OtaUpgradeRequest) (*dto.OtaUpgradeResponse, error) + // GetUpgradeProgress 用于查询指定 OTA 任务的进度。 + GetUpgradeProgress(ctx context.Context, taskID uint32) (*dto.OtaUpgradeProgressResponse, error) + // StopUpgrade 用于请求停止一个正在进行的 OTA 升级任务。 + StopUpgrade(ctx context.Context, taskID uint32) error } // areaControllerService 是 AreaControllerService 接口的具体实现。 @@ -138,3 +145,21 @@ func (s *areaControllerService) DeleteAreaController(ctx context.Context, id uin // 3. 执行删除 return s.areaControllerRepo.Delete(serviceCtx, id) } + +// StartUpgrade 用于启动一个 OTA 升级任务。 +func (s *areaControllerService) StartUpgrade(ctx context.Context, areaControllerID uint32, firmware *dto.OtaUpgradeRequest) (*dto.OtaUpgradeResponse, error) { + //TODO implement me + panic("implement me") +} + +// GetUpgradeProgress 用于查询指定 OTA 任务的进度。 +func (s *areaControllerService) GetUpgradeProgress(ctx context.Context, taskID uint32) (*dto.OtaUpgradeProgressResponse, error) { + //TODO implement me + panic("implement me") +} + +// StopUpgrade 用于请求停止一个正在进行的 OTA 升级任务。 +func (s *areaControllerService) StopUpgrade(ctx context.Context, taskID uint32) error { + //TODO implement me + panic("implement me") +} diff --git a/internal/domain/device/device_service.go b/internal/domain/device/device_service.go index f4ba368..e460f02 100644 --- a/internal/domain/device/device_service.go +++ b/internal/domain/device/device_service.go @@ -79,14 +79,13 @@ type OtaService interface { // StartUpgrade 用于启动一个 OTA 升级任务。 // areaControllerID: 目标区域主控的设备 ID。 // firmwarePath: 新固件文件所在的临时目录的绝对路径。 - // targetVersion: 目标固件的版本号。 // 返回创建的 OTA 任务 ID 和可能发生的错误。 - StartUpgrade(ctx context.Context, areaControllerID uint32, firmwarePath, targetVersion string) (uint32, error) + StartUpgrade(ctx context.Context, areaControllerID uint32, firmwarePath string) (uint32, error) // GetUpgradeProgress 用于查询指定 OTA 任务的进度。 // taskID: 要查询的 OTA 任务 ID。 - // 返回 OTA 任务的当前状态和可能发生的错误。 - GetUpgradeProgress(ctx context.Context, taskID uint32) (status models.OTATaskStatus, err error) + // 返回 OTA 任务的已执行步骤数和总步骤数和当前阶段和可能发生的错误。 + GetUpgradeProgress(ctx context.Context, taskID uint32) (executed, total uint32, CurrentStage models.OTATaskStatus, err error) // StopUpgrade 用于请求停止一个正在进行的 OTA 升级任务。 // taskID: 要停止的 OTA 任务 ID。 diff --git a/internal/domain/device/ota_service.go b/internal/domain/device/ota_service.go index 076d18e..8553c62 100644 --- a/internal/domain/device/ota_service.go +++ b/internal/domain/device/ota_service.go @@ -21,12 +21,12 @@ func NewOtaService(otaRepo repository.OtaRepository, deviceRepo repository.Devic } } -func (o *otaServiceImpl) StartUpgrade(ctx context.Context, areaControllerID uint32, firmwarePath, targetVersion string) (uint32, error) { +func (o *otaServiceImpl) StartUpgrade(ctx context.Context, areaControllerID uint32, firmwarePath string) (uint32, error) { //TODO implement me panic("implement me") } -func (o *otaServiceImpl) GetUpgradeProgress(ctx context.Context, taskID uint32) (status models.OTATaskStatus, err error) { +func (o *otaServiceImpl) GetUpgradeProgress(ctx context.Context, taskID uint32) (executed, total uint32, CurrentStage models.OTATaskStatus, err error) { //TODO implement me panic("implement me") }