4 Commits

Author SHA1 Message Date
2995840376
4c2d92571e feat(K): 规则保存时校验动作参数必须用物模型 code, 禁止 dpId
背景: 规则动作 params 的 key 会被原样当作涂鸦 code 下发(dp_id 从不参与下发), 历史测试数据里出现过 switch_1 与 1 混用, 导致下发失败或指令相互矛盾, 且保存时无任何校验。

后端: 新增 RuleActionValidator, createRule/updateRule 前校验动作参数 key 必须命中 product_property.code; 命中 dp_id 时直接提示应改用的 code; 同步校验值域(bool 取值、数值 min/max 区间、enum 候选值); 目标设备不存在、无产品物模型等场景给出明确业务错误。

前端: 后台规则表单补齐执行动作编辑(JSON), 提交前本地解析校验, 原本表单不提交 actions 导致新建规则必然失败。

Android: 物模型不可用时的回退路径改为优先使用涂鸦 code(反射读取), 避免提交 dpId 被后端拒绝。

V24: scene_run 表不存在时容错跳过, 便于在未执行 V16 的旧结构库上整段执行。
2026-10-28 00:52:04 +08:00
2995840376
b2d758be33 fix(F): 日志轮转治理 - 统一 logback 配置 + journald 限额
问题根因:
- iot-device.out 涨到 613MB:systemd StandardOutput=append: 无任何轮转
- DEBUG 刷屏(单日 11521 条):logging.level.com.iot=DEBUG 使 MyBatis 每条 SQL 打印两遍
- 涂鸦 open-mq-sdk jar 自带 logback.xml 抢占日志配置(iot-data/rule/alarm 未声明 logging.config),
  把日志写到 ./logs 相对目录且无总量上限

改动:
- 新增 backend/iot-common/src/main/resources/logback-spring.xml(4 服务共用唯一真相源):
  RollingFileAppender 按日 + 50MB 双触发切分,保留 7 天,主日志总量上限 2GB,
  错误日志单独一份(保留 30 天 / 512MB),并对涂鸦/MQTT/AMQP 等第三方 SDK 降噪
- 父 pom 增加 maven-resources-plugin,把该配置复制进各服务 BOOT-INF/classes
- 4 个服务 application.yml 统一声明 logging.config,并把 com.iot 级别收敛为 INFO
- 新增 backend/deploy/systemd/:4 个 unit 改为 StandardOutput=journal + 注入 LOG_DIR,
  附 journald 限额(SystemMaxUse=1G / SystemMaxFileSize=50M / MaxRetentionSec=7day)
- deploy-all.bat 增加日志治理步骤(同步 unit + journald + 清理历史 .out)

生产验证:日志落到 /opt/iotsaas/logs/app/*.log,DEBUG 计数 0,历史 .out 已清理,
journal 776M 降到 552M,4 服务 active,9081/9083 文档返回 200
2026-10-27 18:28:19 +08:00
2995840376
297206368e feat(B11): AI 指令码从产品物模型派生, 消除第三套指令码档案
重构前: ai_device_profile 的指令码全靠品类猜(默认 switch_1/switch_led/control),
与 product_property 物模型、涂鸦 SDK schema 是三套独立来源, 必然漂移 ——
多开关位/带背光设备会拿到错误指令码。

重构后决策优先级:
1. 人工覆盖(source=manual) —— 用户显式指定, 最高优先
2. 产品物模型派生          —— semantic 标注的权威来源(后端 SpecSemanticResolver 落库)
3. 已存在的档案(探测写入/类型默认) —— 兼容历史数据
4. 品类推断兜底            —— 物模型缺失时

新增 ProductSpecMapper(只读投影): 查询产品物模型功能点(code/name/type/semantic/grp/access/dp_id)

fromProductSpec 映射:
- power    -> powerCode        (多开关位取 is_primary 通道)
- switch   -> powerCode 兜底   (物模型未标 power 时取首个可写开关通道)
- brightness -> brightnessCode
- color_temp -> colorTempCode
- mode     -> modeCode
- temperature -> temperatureCode

派生结果同时写回 product_id(产品级共享), 不再逐设备重复存储

验证: mvn -pl iot-common,iot-device,iot-rule -am compile BUILD SUCCESS
2026-10-27 13:25:32 +08:00
2995840376
0ce191c448 chore: 初始化 iotsaas 版本库基线
纳入范围:
- 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
2026-10-27 12:00:41 +08:00