15 KiB
15 KiB
OTA固件API
**本文引用的文件** - [backend/src/routes/ota.js](file://backend/src/routes/ota.js) - [backend/src/models/Ota.js](file://backend/src/models/Ota.js) - [backend/src/services/otaStorage.js](file://backend/src/services/otaStorage.js) - [backend/src/validators/ota.js](file://backend/src/validators/ota.js) - [backend/src/utils/response.js](file://backend/src/utils/response.js) - [backend/src/middleware/auth.js](file://backend/src/middleware/auth.js) - [backend/src/config/env.js](file://backend/src/config/env.js) - [frontend/src/api/ota.js](file://frontend/src/api/ota.js) - [frontend/src/views/ota/index.vue](file://frontend/src/views/ota/index.vue) - [backend/package.json](file://backend/package.json) - [frontend/package.json](file://frontend/package.json)目录
简介
本文件为OTA固件管理API的完整RESTful接口文档,涵盖固件版本管理的HTTP方法、URL模式、请求/响应格式以及文件上传处理流程。内容包括:
- 固件版本列表查询、详情获取、创建、更新、删除接口
- 设备端“最新版本检查”接口
- 文件上传(Luxsin-X8上传至S3,Luxsin-X9保存到本地目录)
- 存储服务配置与使用示例
- 固件版本比较、强制更新策略与兼容性检查机制
- 下载链接生成、版本升级通知与错误处理实现指南
项目结构
后端采用Express + Sequelize + MySQL架构,前端基于Vue3 + Element Plus。OTA相关逻辑集中在路由、模型、服务层与验证器中,并通过统一响应封装返回。
graph TB
subgraph "前端"
FE_API["前端API模块<br/>frontend/src/api/ota.js"]
FE_VIEW["OTA页面视图<br/>frontend/src/views/ota/index.vue"]
end
subgraph "后端"
ROUTER["OTA路由<br/>backend/src/routes/ota.js"]
AUTH["认证中间件<br/>backend/src/middleware/auth.js"]
RESP["统一响应封装<br/>backend/src/utils/response.js"]
VALID["参数校验<br/>backend/src/validators/ota.js"]
MODEL["数据库模型<br/>backend/src/models/Ota.js"]
STORE["存储服务<br/>backend/src/services/otaStorage.js"]
ENV["环境配置<br/>backend/src/config/env.js"]
end
FE_API --> ROUTER
FE_VIEW --> FE_API
ROUTER --> AUTH
ROUTER --> VALID
ROUTER --> MODEL
ROUTER --> STORE
ROUTER --> RESP
STORE --> ENV
图表来源
章节来源
核心组件
- 路由层:定义所有OTA相关HTTP接口,包含设备端“最新版本检查”和后台管理接口。
- 认证中间件:保护后台接口,要求Bearer Token。
- 参数校验:使用Zod对创建/更新请求体进行严格校验。
- 数据模型:Sequelize定义的OTA表结构,包含版本号、MD5、强制更新、定向灰度、时间窗口等字段。
- 存储服务:根据设备型号选择不同存储路径(S3或本地),并生成公开下载链接。
- 响应封装:统一封装成功/错误/无数据三类响应格式。
章节来源
- backend/src/middleware/auth.js:1-36
- backend/src/validators/ota.js:1-36
- backend/src/models/Ota.js:1-97
- backend/src/services/otaStorage.js:1-113
- backend/src/utils/response.js:1-25
架构总览
OTA接口分为两类:
- 设备端调用:无需登录,用于查询最新可升级版本。
- 后台管理:需登录,用于维护OTA版本列表、上传升级包、查看/编辑/删除。
sequenceDiagram
participant Device as "设备端"
participant Router as "OTA路由"
participant Model as "数据库模型"
participant Logger as "日志"
Device->>Router : GET /api/ota/latest/check?currentVerCode&model&hw
Router->>Model : 查询 verCode > 当前版本且状态可用
alt 找到更高版本
Model-->>Router : 返回最高版本记录
Router-->>Device : 成功响应含下载URL、MD5、是否强制等
else 无更高版本
Router-->>Device : 无数据响应
end
Router->>Logger : 记录查询结果
图表来源
详细组件分析
设备端“最新版本检查”
- 方法与路径:GET /api/ota/latest/check
- 请求参数:
- currentVerCode: 当前设备版本号(整数)
- model: 设备型号(如 Luxsin-X8/X9)
- hw: 可选硬件版本号(整数)
- 响应:
- 成功:返回最高可用版本记录(含URL、MD5、是否强制更新、定向/灰度等)
- 无数据:表示无更高可用版本
- 兼容性与策略:
- 仅查询状态为可用且版本号大于当前版本的记录
- 支持按硬件版本过滤
- 强制更新字段用于客户端决定是否强制升级
章节来源
后台管理接口(需登录)
获取OTA版本列表
- 方法与路径:GET /api/ota/
- 查询参数:
- skip: 跳过条数(默认0)
- limit: 每页数量(默认100,最大1000)
- verCode: 精确匹配版本号
- verName: 模糊匹配版本名称
- model: 模糊匹配设备型号
- status: 状态(0/1)
- 响应:分页数据(items、total、skip、limit)
章节来源
获取指定OTA详情
- 方法与路径:GET /api/ota/:ota_id
- 路径参数:ota_id(整数)
- 响应:单条记录或无数据
章节来源
创建OTA版本
- 方法与路径:POST /api/ota/
- 请求体字段(必填/可选见校验规则):
- verCode: 整数(唯一性约束:同model下不可重复)
- verName: 字符串(1~20)
- url: 字符串(下载地址或上传后生成的URL)
- md5: 32位十六进制字符串
- force: 0/1(默认0)
- desc: 描述(可空)
- model: 设备型号(可空)
- hw: 硬件版本号(默认0)
- target: 是否定向(0/1,默认0)
- beta: 是否灰度(0/1,默认0)
- startTime/endTime: 时间字符串(可空)
- status: 状态(0/1,默认1)
- 响应:创建成功的记录
章节来源
更新OTA版本
- 方法与路径:PUT /api/ota/:ota_id
- 请求体字段:同创建接口(部分字段可为空表示不更新)
- 响应:更新后的记录
- 注意:
- 若更新版本号或设备型号,需保证新的组合在同model下唯一
- 日期字段会自动转换为Date类型
章节来源
删除OTA版本
- 方法与路径:DELETE /api/ota/:ota_id
- 响应:删除成功消息
章节来源
文件上传与存储
接口:上传升级包
- 方法与路径:POST /api/ota/upload-package
- 请求头:Content-Type: multipart/form-data
- 表单字段:
- package_file: 二进制文件
- model: 设备型号(仅支持 Luxsin-X8 或 Luxsin-X9)
- 响应:
- 成功:返回md5、filename、url;X8同时返回s3_key
- 错误:返回错误信息(如未配置S3、上传失败、不支持的设备型号等)
sequenceDiagram
participant Client as "客户端"
participant Router as "OTA路由"
participant Store as "存储服务"
participant S3 as "S3客户端"
participant FS as "本地文件系统"
Client->>Router : POST /api/ota/upload-package
Router->>Store : readUploadContentAndMd5(buffer)
alt model == Luxsin-X9
Store->>FS : 写入本地文件并生成URL
FS-->>Store : 返回保存名与URL
else model == Luxsin-X8
Store->>S3 : 上传对象并生成URL
S3-->>Store : 返回保存名、URL与S3 Key
end
Store-->>Router : {md5, filename, url[, s3_key]}
Router-->>Client : 成功响应
图表来源
存储策略与配置
- 设备型号支持:Luxsin-X8、Luxsin-X9
- 存储方式:
- X8:上传至S3,生成公开访问URL
- X9:写入本地目录,生成公开访问URL
- 关键环境变量(来自存储服务):
- OTA_UPLOAD_DIR:本地上传根目录(开发默认临时目录,生产默认/data/projects/source)
- AWS_REGION/AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY:S3区域与凭证(无凭证时走IAM角色)
- AWS_S3_OTA_BUCKET:S3存储桶名称
- OTA_X8_PUBLIC_BASE:X8公开URL基础路径
- OTA_X9_URL_BASE:X9公开URL基础路径
章节来源
前端集成与使用示例
- 前端API模块提供:
- 列表、详情、创建、更新、删除、上传包等方法
- OTA页面视图:
- 支持搜索(版本名、设备型号、状态、版本号)
- 分页与表格展示
- 上传升级包(X8/X9)并回填URL与MD5
- 表单校验与提交
章节来源
依赖关系分析
classDiagram
class OtaRoute {
+GET "/api/ota/"
+GET "/api/ota/ : ota_id"
+POST "/api/ota/"
+PUT "/api/ota/ : ota_id"
+DELETE "/api/ota/ : ota_id"
+POST "/api/ota/upload-package"
+GET "/api/ota/latest/check"
}
class AuthMiddleware {
+authMiddleware()
}
class ApiResponse {
+success(data,msg)
+error(msg,code)
+noData(msg)
}
class OtaValidator {
+OtaCreateSchema
+OtaUpdateSchema
}
class OtaModel {
+verCode : int
+verName : string
+url : string
+md5 : string
+force : smallint
+desc : string
+model : string
+hw : int
+target : smallint
+beta : smallint
+startTime : date
+endTime : date
+status : smallint
}
class OtaStorage {
+readUploadContentAndMd5()
+saveX9PackageLocal()
+uploadX8PackageToS3()
}
OtaRoute --> AuthMiddleware : "保护后台接口"
OtaRoute --> OtaValidator : "参数校验"
OtaRoute --> OtaModel : "读写数据库"
OtaRoute --> OtaStorage : "文件上传"
OtaRoute --> ApiResponse : "统一响应"
图表来源
- backend/src/routes/ota.js:1-292
- backend/src/middleware/auth.js:1-36
- backend/src/utils/response.js:1-25
- backend/src/validators/ota.js:1-36
- backend/src/models/Ota.js:1-97
- backend/src/services/otaStorage.js:1-113
性能考量
- 列表查询限制每页最大1000条,避免一次性返回过多数据。
- “最新版本检查”接口按verCode降序查询第一条,索引建议:
- 在verCode、model、status上建立复合索引以提升查询效率。
- 文件上传使用内存存储(multer.memoryStorage),大文件可能影响内存占用,建议:
- 控制上传文件大小与超时时间(前端已设置较长超时)。
- 对于X8大文件,优先考虑流式上传或分片上传策略(当前实现为一次性上传)。
[本节为通用性能建议,不直接分析具体文件]
故障排查指南
- 认证失败(401):
- 检查请求头Authorization是否为Bearer Token
- 确认Token未过期
- 参数校验失败:
- 按照Zod校验规则修正请求体字段(长度、类型、取值范围)
- 版本冲突:
- 创建/更新时若verCode与model组合重复,会返回“该版本已存在”
- S3上传失败:
- 检查AWS_REGION、AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY与AWS_S3_OTA_BUCKET配置
- 确认S3权限与存储桶存在
- 无可用版本:
- 设备端查询不到更高版本时返回“无数据”,确认目标设备型号、硬件版本与状态
章节来源
- backend/src/middleware/auth.js:1-36
- backend/src/validators/ota.js:1-36
- backend/src/routes/ota.js:174-181
- backend/src/services/otaStorage.js:72-103
结论
本OTA固件API提供了完善的版本管理能力,支持设备端“最新版本检查”与后台管理功能,结合S3与本地存储策略满足不同设备型号的升级包分发需求。通过严格的参数校验与统一响应封装,提升了接口的稳定性与易用性。建议在生产环境中完善索引、优化大文件上传策略,并加强S3权限与监控告警。
[本节为总结性内容,不直接分析具体文件]
附录
统一响应格式
- 成功:code=1,msg为成功信息,data为返回数据
- 错误:code=0,msg为错误信息,data=null
- 无数据:code=2,msg为提示信息,data=null
章节来源
设备端版本比较与强制更新策略
- 版本比较:仅返回verCode大于当前版本且状态为可用的最高版本
- 强制更新:由force字段控制,客户端据此决定是否强制升级
- 定向/灰度:target/beta字段可用于控制发布范围
章节来源
前端调用示例(参考)
- 列表查询:传入skip、limit、verName、model、status、verCode
- 上传包:构造FormData,包含package_file与model,设置Content-Type为multipart/form-data
- 提交表单:根据设备型号决定是否需要先上传包再填写URL/MD5
章节来源