纳入范围: - backend/ Spring Boot 多模块后端(iot-common/device/rule/data/alarm/auth) - frontend/admin/ Vue3 + Element Plus 管理后台 - Android/ 涂鸦原生 APP (com.xhai.iot) - backend/sql/ Flyway 风格迁移脚本(V2~V21) - docs/ 对接文档与设计文档 排除范围: - 构建产物: node_modules/ target/ build/ dist/ .gradle/ - 签名密钥: *.jks *.keystore (严禁入库) - 本机配置: Android/local.properties - 运行日志: logs/ *.log - AI 协作本地数据 .codebuddy/ 与第三方 demo tuya-demo/ .gitattributes 统一以 LF 存储, Windows 批处理保留 CRLF
14 KiB
14 KiB
产品管理模块(Product & TSL & OTA)分析设计
状态:分析设计(待评审,先不开发) 日期:2026-09-19 目标:论证并设计中控屏/IoT 平台所需的"产品管理"能力(产品参数、物模型 TSL、固件 OTA)
1. 结论先行(建议)
非常需要,且应尽快立项。 当前系统是"设备直管"模式,缺少产品(Product)这一层抽象,导致物模型零散、固件无管理、新增设备类型成本高。引入 产品 → 设备 两级模型(对标涂鸦/阿里云 IoT 的 Product 概念)是平台标准化的必经之路,并能直接支撑中控屏标准控制 UI、场景、AI 控制、固件升级。
2. 现状与痛点
2.1 现状(代码事实)
Device实体(device表)字段:deviceId, deviceName, platform, deviceType, manufacturer, model, firmwareVersion, status, capabilities(JSON), ..., homeId, roomId—— 无productId。Device.capabilities:设备级 JSON,存"设备能力描述",每个设备重复存静态能力,无产品级统一定义。AiDeviceProfile(ai_device_profile表,iot-device 与 iot-rule 两侧都有):设备级"指令码档案"(powerCode/brightnessCode/colorTempCode/temperatureCode/modeCode…),本质是物模型 DP 雏形,但按deviceId维度重复存储。Device.firmwareVersion:仅版本字符串,无固件库、无升级包、无 OTA 任务、无灰度/回滚。- 涂鸦侧
TuyaDeviceDTO有productId/productName/category,但平台未把它沉淀为自有 Product 实体,仅在对接时透传。
2.2 痛点
- 重复定义、难维护:同类设备(同型号)每个都重复存
capabilities/AiDeviceProfile指令码,产品能力变更需逐设备改。 - 无标准物模型:控制逻辑(DP 点、属性/事件/服务)散落在设备 JSON 与
AiDeviceProfile,AI 控制、场景、中控屏各自解析,易错且无法复用。 - 固件无管理:只有版本号,无法上传/发布/下发/灰度/回滚固件,中控屏等设备的固件升级无法支撑。
- 产品参数无沉淀:厂商/型号/品类/联网方式/配网/图标等散落,无法以"产品"维度统一管理和展示标准控制 UI。
- 接入新设备类型成本高:每接一类设备都要改代码/前端,无法配置化。
3. 产品管理模块范围
| 能力 | 说明 |
|---|---|
| 产品基础信息 | 名称、品类(category)、厂商(manufacturer)、型号(model)、联网方式(wifi/ble/zigbee/matter)、配网方式、图标、说明、发布状态 |
| 物模型(TSL) | 属性(Property)、事件(Event)、服务(Action) 三类功能点,含 DP 点定义与涂鸦/平台映射 |
| 固件管理(OTA) | 固件版本库、升级包存储(md5)、发布、升级任务、灰度、回滚、设备当前版本追踪 |
| 平台映射 | 本平台 Product ↔ 涂鸦 productId 等(platform + platformProductId) |
| 设备归属 | Device 增加 productId,继承产品物模型与固件基线 |
| 接入/配网模板(二期) | 标准化配网流程、设备自动归属产品 |
4. 与现有概念的关系(迁移策略)
| 现有 | 去向 |
|---|---|
Device.manufacturer / model |
提升到 Product;Device 改为引用 productId(建议移除冗余,或保留只读快照防不一致) |
Device.capabilities(JSON) |
由 Product 物模型(TSL)生成,设备运行时状态另存(device_data/status),不再每设备存静态能力 |
AiDeviceProfile(设备级指令码) |
下沉为 Product 物模型的 DP 定义(powerCode 等即产品的"开关属性");AI 控制/场景直接读产品物模型,设备不再单独存 |
涂鸦 productId |
Product.platform + platformProductId 字段建立映射(一个平台产品 → 本平台一个 Product) |
Device.firmwareVersion |
保留为设备"当前版本"(运行时上报);新增 firmware 表管理"可用版本库",ota_task 记录目标版本 |
5. 数据模型设计
5.1 product(产品表)
| 字段 | 说明 |
|---|---|
| id | PK |
| product_key | 业务编码(如 P_LIGHT_001) |
| name | 产品名称 |
| category | 品类(light/switch/ac/security…) |
| manufacturer | 厂商 |
| model | 型号 |
| platform | 接入平台(tuya/local/matter…) |
| platform_product_id | 涂鸦 productId 等映射 |
| connect_type | wifi/ble/zigbee/matter |
| net_config_type | 配网方式 |
| icon | 图标 |
| description | 说明 |
| status | 草稿/已发布 |
| spec_version | 当前物模型版本号 |
| create_time / update_time | — |
5.2 物模型(TSL)
推荐拆表(便于校验、UI 渲染、DP 映射),顶层用 spec_version 关联快照:
product_property(属性):id, product_id, code(如 switch_1), name, access(读/写/上报), type(bool/int/enum/float/string/json), min, max, step, unit, enum_list, dp_id(涂鸦DP映射), default_value, sortproduct_event(事件):id, product_id, code, name, type(info/alert/fault), params(JSON)product_action(服务):id, product_id, code, name, input(JSON), output(JSON)
可选:同时存一份
product.spec_json(完整 TSL 快照)便于缓存下发。
5.3 firmware(固件表)
| 字段 | 说明 |
|---|---|
| id | PK |
| product_id | 所属产品 |
| version | 固件版本 |
| file_url | 升级包地址 |
| file_md5 | 校验 |
| size | 大小 |
| release_note | 更新说明 |
| is_latest | 是否最新 |
| status | 草稿/已发布 |
| create_time | — |
5.4 ota_task(升级任务)
| 字段 | 说明 |
|---|---|
| id | PK |
| product_id | 产品 |
| firmware_id | 目标固件 |
| target_version | 目标版本 |
| scope | 全部 / 指定设备 / 灰度% |
| device_ids | 指定设备 |
| status | 进行中/完成/暂停/失败 |
| success_count / fail_count | 统计 |
| create_time | — |
5.5 Device 改造
- 新增
product_id(FK,关联 product.id)。 - 视情况移除
model/manufacturer冗余(或保留只读快照)。 firmwareVersion保留为设备当前运行版本(上报)。
6. 接口设计(建议)
6.1 管理端(后台/管理员)
POST/GET/PUT/DELETE /api/v1/products—— 产品 CRUDGET /api/v1/products/{id}/spec—— 物模型查询POST /api/v1/products/{id}/spec/properties等 —— DP/事件/服务增删改POST /api/v1/products/{id}/firmware—— 上传固件GET /api/v1/products/{id}/firmwares—— 固件列表POST /api/v1/products/{id}/ota—— 创建升级任务GET /api/v1/ota-tasks/{id}—— 任务进度
6.2 设备/中控屏侧(复用)
- 设备详情返回
productId+ 物模型(用于渲染标准控制 UI,不再依赖零散 capabilities)。 - 控制接口基于物模型 DP(统一语义)。
- 固件查询:设备上报/拉取最新固件版本,触发 OTA。
7. 固件 OTA 流程
- 管理员上传固件到 Product → 生成
firmware记录(version, url, md5)。 - 创建
ota_task(目标版本 + 设备范围 / 灰度比例)。 - 设备定期上报/查询最新固件(或平台主动推送升级指令)→ 下载升级 → 上报新
firmwareVersion→ 任务统计。 - 支持回滚(将上一版本
is_latest=false,重新下发任务)。
- 中控屏本身也是一类 Product,可纳入同一套 OTA 管理。
8. 分阶段实施
- P0 产品基础:
product表 +Device.productId改造 + 产品 CRUD;按model+manufacturer自动归并或手动建产品,给存量设备回填productId。 - P1 物模型:TSL(property/event/action)建模 + 管理接口;将
AiDeviceProfile/capabilities迁移沉淀为产品物模型,AI 控制/场景改读产品物模型。 - P2 固件 OTA:✅ 已实现(2026-09-19)。后端
FirmwareService/Controller:固件注册(草稿)/发布(置最新)/最新版查询、升级任务创建(all/designated/gray 物化目标设备)/任务分页/详情/设备上报回调(回写 device.firmware_version、统计完成)/暂停。管理后台「设备管理→产品管理」含固件OTA面板(注册/发布/建任务/进度/暂停)。V13/V14 迁移已在开发库(iot-mysql 3386)执行,8 台涂鸦设备已 reconcile 归类为 8 个产品。 - P3 标准化控制:✅ 已实现(2026-09-20)。核心是「标准控制模型」
ControlSchemaService:GET /api/v1/products/{id}/control-schema(产品级)与GET /api/v1/devices/{deviceId}/control-schema(设备级,含 DP 当前值填充)。物模型→控件映射:bool→switch、int/float 有范围→slider、enum→segmented、其余→number/text;主开关自动识别(开关/电源/switch/power 优先,否则唯一可写 bool)。设备无产品时available=false,客户端回退原有渲染。消费端:管理后台「物模型→控制预览」按模型渲染只读控件;AndroidDeviceControlActivity优先拉后端模型渲染(ApiService.getDeviceControlSchema),失败/无模型回退涂鸦 schema(需 Android Studio 编译确认)。 - P4 高级:✅ 大部分已实现(2026-09-20)。版本回滚
POST /products/{id}/ota/rollback(不指定版本则回退上一个已发布版本);灰度改为设备ID稳定哈希分组(同一设备恒在同一组,可配合不同版本做 A/B 对比);统计看板GET /ota-tasks/stats?productId=(任务数/进行中/完成/暂停、成功失败数、成功率、设备固件版本分布),管理后台 OTA 面板顶部为统计卡片 + 版本分布。未做:配网模板。
9. 风险与注意
- 存量迁移:设备需回填
productId(按 model+manufacturer 归并或人工关联)。 - 兼容性:保留
capabilities读兼容,逐步切到产品物模型,避免一次性大改。 - 物模型版本:用
spec_version管理,产品变更不影响已部署设备(设备绑定创建时的 spec 快照)。 - 涂鸦映射一致性:
platformProductId与涂鸦 productId 对齐,DP 映射字段dp_id准确。
10. 价值总结
引入产品层可一次性解决当前三大痛点:① 物模型统一(消除 capabilities/AiDeviceProfile 设备级重复)② 固件可管理(OTA)③ 设备类型配置化接入。同时为已规划的中控屏标准控制 UI、场景、AI 语音控制提供统一数据底座,是平台从"能连设备"走向"可运营 IoT 平台"的关键一步。
11. 已确认决策(2026-09-19 评审)
| 项 | 决策 |
|---|---|
| 存量设备回填 | 两者结合:系统按 model+platform 自动预归类生成建议产品与归属,管理员在后台确认/调整 |
| Device 冗余字段 | 移除 Device.model / manufacturer,统一从 product 取(需同步改所有读写该字段的逻辑:DeviceController.createDevice、DeviceInfo DTO、AiDeviceProfile、前端设备卡片等) |
| 物模型存储 | 拆表:product_property / product_event / product_action,每行一个 DP 点,含 dp_id 涂鸦映射与 spec_version |
| 首期范围 | P0 + P1 全做:产品基础 + Device.product_id + 存量回填 + 物模型(属性/事件/服务)建模与接口,并将 AiDeviceProfile / capabilities 下沉为产品物模型 |
11.1 开发前影响面排查(移除冗余字段必做)
Device.model/manufacturer读写点:DeviceController(create/update/query)、DeviceInfo/DeviceData等 DTO、SQL 映射、前端设备详情/卡片展示。AiDeviceProfile下沉:iot-device 写入、iot-rule 读取(AI 控制翻译)需改为读产品物模型;迁移脚本把存量 deviceId 级指令码归并到所属产品的 property。capabilities兼容:保留读兼容,新设备改由产品物模型生成;提供回填/转换脚本。
12. 实现进度(2026-09-19,P0+P1 基础)
12.1 已完成(可编译,已通过 LSP)
- SQL
backend/sql/V13__add_product_module.sql:新建product/product_property/product_event/product_action/firmware/ota_task六表;device表新增product_id列(保留原model/manufacturer兼容快照,未物理删除)。 - 实体 + Mapper:6 个实体与 6 个
BaseMapper(纯新增)。 - ProductService / Impl:产品 CRUD、物模型查询与增删改、
resolveProductId(按平台信息解析/自动建产品)、reconcileDevices(存量设备按model+platform自动归类回填product_id)。 - ProductController
POST/GET/PUT/DELETE /api/v1/products、/products/{id}/spec、/properties|events|actions、/reconcile、/resolve。 - Device / DeviceInfo 增加
productId;TuyaDeviceAdapter.getDeviceInfo回填productId(设备详情可返回所属产品)。
12.2 未做(高风险,单列计划,未破坏现有功能)
- ✅ 移除
Device.model/manufacturer冗余(D):V14给device加platform_product_id(承接塞进model列的涂鸦 productId)、迁移存量、再DROP COLUMN model/manufacturer。Device实体删两字段加platformProductId;TuyaController改设platformProductId;reconcileDevices改按platform+platformProductId归类;DeviceInfo的model/manufacturer改为从product取(TuyaDeviceAdapter注入ProductMapper)→ 前端零改动。 - ✅
AiDeviceProfile下沉产品级(C,向后兼容):ai_device_profile加product_id。iot-device探测与iot-rule解析/保存全部改为优先读产品级、推断落产品级;旧设备级作 fallback。AiDeviceView加productId。 - ✅ 设备同步自动关联(B):
TuyaController创建/更新涂鸦设备时自动resolveProductId设device.product_id。 - ✅
capabilities由物模型生成:DeviceServiceImpl.getDeviceInfo改为依据设备所属product+product_property动态推导能力描述(product元数据 + 每个功能点code/name/type/access/writable/min/max/step/unit/enum/default),取代各 adapter 硬编码能力(如LocalDeviceAdapter的switch/brightness/color);device.capabilities列仅保留dps运行时态;无产品时回退 adapter 自带能力。前端无引用,零改动。
验证:后端
mvn -pl iot-device,iot-rule -am compile通过(exitCode 0)。存量设备 productId 回填与产品创建由部署后执行POST /api/v1/products/reconcile完成(已基于platformProductId)。