|
|
7dc00b542d
|
feat(iot): 一期 Controller 补齐 (B2/B4-6/B10/B11/B12/B13)
对照前端 feat/iot-2.0 已固化 API 契约补齐 5 组缺失端点(发现于一期 19/19
宣称完成后前端联调阶段),归属原任务卡 Controller 层返工,不占用二期
B20+ 编号。
- B2 规则链: 补 PUT /disable /deploy /debug + POST /copy?id= +
新增 GET /rule-chain/get?id= 返 GraphVO(保留 /get/{id})
deployRuleChain=enable+主动 Pub/Sub evict(对齐 B8)
- B10 子系统: 新增 GET /device-count 聚合(HGETALL 返空 map 遵循 A6)
+ GET /get?id= query 别名(保留 /get/{id})
- B11 设备: 新增驼峰 PUT /bindSubsystem /batchBindSubsystem
+ 2 ReqVO,保留 kebab 兼容
- B12/B13 告警: 新增 IotAlarmRecordController(整缺)11 端点:
page/get/ack/unack/clear/archive/batch-{ack,clear,archive}/
history/remark;Service 补 6 方法(getPage/batchAck/
batchClear/batchArchive/updateRemark/listHistory)
+ Mapper 2 方法 + 8 VO
- B4/5/6 节点元数据: 新增 GET /iot/rule/provider/metadata 聚合端点;
3 SPI 加 default getMetadata(),4 Manager 加
listAllMetadata(),13 具体 Provider 覆写(中文 label
+ mdi: icon),schema MVP 空骨架 {rule:[]}
测试:
- iot-rule 191/191 全绿(+5 B2 补齐 +9 B4/5/6 补齐)
- iot-server 106 active/161 Skipped v1 遗产 全绿
(+6 B12/B13 补齐 +3 B10 补齐)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-24 15:47:41 +08:00 |
|
|
|
bac4f216fc
|
feat(iot): B15 告警传播(iot_alarm_propagation 关联表)
沿资产层级(SUBSYSTEM→PROJECT→TENANT)向上传播,替代原 JSON_CONTAINS 全表扫描。
关键实现:
- IotAlarmPropagationMapper:INSERT IGNORE 幂等批量插入;selectAlarmIdsByAsset
命中 idx_asset(asset_type, asset_id, tenant_id),毫秒级响应
- IotAlarmPropagationServiceImpl:三层传播逻辑(无 project_id 时仅 2 层)
- IotAlarmRecordServiceImpl:首次触发(existing==null)时调用传播,
@Lazy 注入避免循环依赖
- IotProjectMapper:最小化 Mapper(B10 有 DO 无 Mapper)
- 7 个单元测试(3层/2层/无subsystem/重复幂等/分页查询)
测试:iot-server 258/258 全绿(含 B14/B15 新增 23 用例)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-24 11:08:36 +08:00 |
|
|
|
171f201384
|
feat(iot): Wave 5 Round 2 — B9/B14/B16 统一消费入口 + 告警分布式锁 + 通知集成
B9 IotRuleEngineMessageHandler(统一消费入口)
- 新消费者 v2 统一入口,@PostConstruct 注册到 IotMessageBus
- versionResolver.shouldUseV2 三态路由(V1/V2/HYBRID),绝不双跑
- device null 时 WARN + skip;RuleEngine 异常 try-catch 吞掉防重试风暴
- v1 三消费者(DataRule/SceneRule/CleanRule)增加前置 v2 bypass 判断
- 6 个单元测试(global-v1/v2/hybrid 白名单命中/未命中/device-null/引擎异常)
B14 告警缓存 + SET NX PX 分布式锁 + 有效性判断
- IotAlarmLockService:SET NX PX + Lua 原子解锁,锁冲突抛 ALARM_LOCK_CONFLICT
- IotAlarmCacheService:Redis Hash iot:alarm:state:{id},TTL 7天,cache miss 从DB重建
- AlarmStateValidator:isEffectiveTrigger/isEffectiveClear 时序校验,防旧消息重置已清除告警
- IotAlarmRecordServiceImpl:trigger/clear/ack/archive 全部在锁内,DB写后立即同步缓存
- 新增 ALARM_LOCK_CONFLICT 错误码;AlarmTriggerRequest 增加 timestamp 字段
- 17 个单元测试(锁 4 + 缓存 5 + 校验 9 + 集成 3)
B16 NotifyAction 4 通道集成 + 模板解析
- NotifyChannel SPI 接口 + Sms/Email/InApp/Webhook 四实现(@Component 注册)
- WebhookNotifyChannel:JDK 17 HttpClient 10s 超时 + SSRF 强制 HTTPS 校验
- NotifyDispatcher:独立 ForkJoinPool(8) 并行分发,30s 整体超时,部分失败不阻塞
- 模板变量统一走 TemplateResolver(评审 C5),缺失变量降级为空串
- NotifyAction 移除 stub,委托 NotifyDispatcher
- viewsh-module-system-api 依赖引入;13 个测试(Dispatcher 7 + Webhook SSRF 6)
测试:iot-rule 177/177 全绿;iot-server 251/251 全绿(含 Skipped 161 旧 v1 测试)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-24 11:00:38 +08:00 |
|
|
|
8e7631987f
|
feat(iot): Wave 5 Round 1 — B8/B13 规则链缓存 + AlarmHistory 时序 DAO
B8 规则链全量缓存 + Redis Pub/Sub + 版本拉模式兜底:
- CompiledRuleChainFactory:IotRuleChainGraphVO→CompiledRuleChain
- RuleChainCache(@PostConstruct loadAll + evict + reload + B48 钩子)
· TenantUtils.executeIgnore 跨租户全量加载;TenantUtils.execute 逐租户切换
· ConcurrentHashMap.compute 保证 reload 串行(避免并发 DB 查询)
· 超 500 条规则链打 WARN 日志
- RuleChainCacheListener:Redis Pub/Sub 订阅 iot:rule:cache:evict,收到后 evict+reload
- RuleChainVersionChecker:5 分钟拉模式兜底,version drift 时 reload + metric
- RuleChainCacheConfiguration:@EnableScheduling + RedisMessageListenerContainer
- IotRuleChainMapper 新增 selectAllEnabledTenantIds()(跨租户查询)
- IotRuleChainServiceImpl.updateRuleChain 末尾发布 Pub/Sub 驱逐事件
- 5 单元测试全绿(含 version drift 检测 + 容量告警)
B13 AlarmHistory 时序表 DAO 双实现:
- AlarmHistoryDO(时序对象:ts/device/severity/ack/clear/archived/eventType 等)
- IotTsDbAlarmHistoryDao 接口(insert/queryByAlarmRecord/queryLatestByDevice)
- CtsdbAlarmHistoryDaoImpl(CTSDB/InfluxDB 协议,@ConditionalOnProperty)
- TdengineAlarmHistoryDaoImpl(TDengine JDBC,@ConditionalOnProperty)
- IotAlarmHistoryService(协调 TSDB 写;异步 @Async;写失败不影响主流程)
- TsDbAutoConfiguration 注册 IotAlarmHistoryService
- 5 单元测试全绿(含 TSDB 失败降级 + 异步写验证)
测试总计:rule 模块 164/164 ✓,server 模块 B13 5/5 ✓
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-24 10:37:07 +08:00 |
|
|
|
ec3981195d
|
feat(iot): B17 SceneRule → DAG 自动转换工具 + dry-run/execute
- SceneRuleToChainMapper:v1→v2 纯转换逻辑
· trigger type 映射(1→device_state 等 4 种 + timer)
· action type 映射(1→device_property_set / 2→device_service_invoke / 100→alarm_trigger / 101→alarm_clear)
· SpEL→Aviator:#root.x → ${data.x};含 T(/instanceof/new 标记 WARNING 不中断
· 线性 DAG:Trigger → [Condition] → Action×N,临时 key -1/-2/-3...
- SceneRuleMigrator:干运行 + 分批执行(50条/批)+ 幂等(force 覆盖重迁)
- SceneRuleMigrationController:3 端点 dry-run/execute/mapping
- MigrationDryRunResultVO / MigrationExecuteReqVO
- 8 单元测试全绿(含 spel→aviator / unsupported_spel / idempotent / force)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-24 10:21:52 +08:00 |
|
|
|
24c486900a
|
feat(iot): Wave 4 Round 2 — B6/B7/B18 ActionProvider + 分支执行 + DataRule迁移
B6 ActionProvider SPI + 5 核心动作(alarm/notify/device-ctrl):
- ActionProvider 接口(extends NodeProvider,默认 bridge execute)
- ActionResult record(SUCCESS/FAILURE/SKIP + output + message)
- ActionProviderManager(Spring 自动收集 + fail-fast 重复 type)
- AlarmTriggerAction(调用 IotAlarmRecordApi.triggerAlarm,模板变量解析)
- AlarmClearAction(alarmId 从 config 或 ctx.metadata 解析,幂等)
- NotifyAction(4 通道并发 + 部分失败不阻塞,第一期 stub)
- DeviceServiceInvokeAction(调用 IotDeviceControlApi.invokeService)
- DevicePropertySetAction(第一期 stub,B27 补全 Redis/MySQL)
- IotAlarmRecordApi + DTO(rule 模块→server 跨模块接口)
- IotAlarmRecordApiImpl(server 端 FeignClient 实现,委托 Service)
- 14 单元测试全绿
B7 分支执行逻辑(executeAnyway if/else-if/else):
- BranchConfiguration POJO(branches[] + executeAnyway + BranchCondition)
- BranchExecutor(核心语义:else/executeAnyway/条件异常短路/action 异常隔离)
- BranchNode NodeProvider(ACTION/"branch",内联执行命中 branch actions)
- DagExecutor 最小扩展(ctx.metadata 传递 CompiledRuleChain 供 BranchNode 使用)
- 9 单元测试全绿(含 validate else 位置校验)
B18 DataRule → DAG 自动转换工具:
- DataRuleToChainMapper(v1→v2 映射,6 种 Sink,合并/拆分多 source)
- DataRuleMigrator(dry-run + execute + 幂等映射表)
- DataRuleMigrationController(3 端点:dry-run/execute/mapping)
- 8 单元测试全绿
测试总计:rule 模块 159/159 ✓,server 模块 8/8(B18)✓
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-24 10:10:04 +08:00 |
|
|
|
42466363c7
|
feat(iot): Wave 4 Round 1 — B12/B4/B5 告警状态机 + 规则引擎 SPI
主会话 Opus:
- B12 iot_alarm_record 正交状态机(ack_state + clear_state + archived)
* V2.0.4__iot_alarm_record.sql:主表 + iot_alarm_propagation 关联表
* 评审 C1 正交三字段(替代线性 4 枚举,表达"已清除未确认")
* 评审 C2 联合 UK (device_id, alarm_config_id, tenant_id, deleted)
* 评审 C3 传播关联表(替代 propagated_to JSON 查询)
* Service 5 方法:triggerAlarm / ackAlarm / unackAlarm / clearAlarm / archiveAlarm
* 幂等 upsert(trigger_count++)+ 归档后禁止修改
* 13 单元测试全绿
* TODO B14 分布式锁 / B15 传播 / B16 通知
Sonnet subagent B4:TriggerProvider SPI + 5 内置触发器
* spi/TriggerProvider + TriggerProviderManager(@Component + getType 索引,fail-fast 重复 type)
* trigger/DeviceState / DeviceProperty / DeviceEvent / DeviceService / Timer(Spring TaskScheduler)
* 评审 A3 落地:禁 ServiceLoader / @SPI
* 44 单元测试全绿
Sonnet subagent B5:ConditionEvaluator SPI + 3 条件 + 统一模板变量
* spi/ConditionEvaluator + condition/Manager
* condition/Expression(Aviator + LRU(256) 编译缓存)
* condition/TimeRange(跨午夜支持)
* condition/DeviceState(Redis 查询,空值按 offline)
* template/TemplateResolver:\${namespace.key},拒绝 \$[...] 旧语法(评审 B5)
* TODO B44 完整 8 层 Aviator 沙箱
* 50 单元测试全绿(TemplateResolver 16 + 条件 3x ≈ 34)
测试汇总:rule 136 全绿 / server 13 新增全绿
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet (subagent) <noreply@anthropic.com>
|
2026-04-24 00:35:14 +08:00 |
|
|
|
1f87d599c0
|
feat(iot): B11 iot_device.subsystem_id + 设备归属绑定 API(一期允许 NULL)
- 新增 sql/iot/V2.0.3__iot_device_add_subsystem.sql(ALTER + idx_subsystem)
- 新增 sql/iot/V2.1.0__iot_device_subsystem_not_null.sql(二期预留,带 "勿执行" 注释)
- IotDeviceDO 加 subsystemId(一期可 NULL,二期改 NOT NULL)
- IotDeviceService 加 bindDeviceToSubsystem / batchBind / unbind / selectCountBySubsystemId
- IotDeviceServiceImpl.createDevice 强校验 subsystemId + 同租户 + Redis HINCRBY +1
- 绑定变更按 TransactionSynchronizationManager afterCommit 同步 Redis(-1 / +1,避免脏状态)
- IotDeviceMapper 加 selectCountBySubsystemId / updateSubsystemId 等
- IotSubsystemServiceImpl 加 incrementDeviceCount/decrementDeviceCount;deleteSubsystem 改用 DB 计数兜底(更可靠)
- IotDeviceController 加 PUT /bindSubsystem + /batchBindSubsystem(@PreAuthorize iot:device:update)
- IotDevicePageReqVO 加 subsystemId 过滤参数(null 可走 IS NULL 查未归属)
- api ErrorCodeConstants 加 DEVICE_SUBSYSTEM_REQUIRED / DEVICE_SUBSYSTEM_CROSS_TENANT(1_050_003_009/010)
- 测试:IotDeviceServiceImplTest 8/8 + B10 IotSubsystemServiceImplTest 补 mock deviceMapper 后 8/8 全绿
- Known Pitfalls 落地:
⚠️ 评审 A2:一期允许 NULL,V2.1.0 预留二期 NOT NULL
⚠️ Redis 计数:事务提交后同步(TransactionSynchronizationManager.afterCommit)
⚠️ 跨租户:校验 subsystem 属于当前租户,不然抛 DEVICE_SUBSYSTEM_CROSS_TENANT
⚠️ 索引 idx_subsystem (tenant_id, subsystem_id, deleted) 最左匹配;IS NULL 查询走全表扫,文档已提示
Co-Authored-By: Claude Sonnet (B11 subagent) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context, orchestrator) <noreply@anthropic.com>
|
2026-04-24 00:03:57 +08:00 |
|
|
|
6649e1abb6
|
feat(iot): B10 iot_subsystem 表 + CRUD + Redis 设备计数聚合
- 新增 sql/iot/V2.0.2__iot_subsystem.sql(iot_project + iot_subsystem)
- 新增 server 模块 subsystem/ 下 DO + Mapper + Service + Controller + VO(7 端点)
- 新增 IotSubsystemDeviceCountRedisDAO(HINCRBY + rebuild + ApplicationReadyEvent 触发)
- api 模块 ErrorCodeConstants 新增子系统段(1-050-020-xxx)
- server 模块 RedisKeyConstants 新增 SUBSYSTEM_DEVCOUNT
- 测试:8 个单元用例全绿(mvn test IotSubsystemServiceImplTest)
- Known Pitfalls 落地:
⚠️ 评审 A4:UK(name, tenant_id, project_id, deleted) + 应用层 existsByNameAndProject 兜底 NULL
⚠️ 评审 A6:device-stats 走 Redis Hash,避免 GROUP BY
⚠️ 评审 A7:simple-list 权限码 iot:device:query,返回字段仅 id/name/code
⚠️ 删除校验:Redis 计数 > 0 抛 SUBSYSTEM_HAS_DEVICES
⚠️ Redis 重建:ApplicationReadyEvent + try/catch + log.warn 不阻塞启动
说明:iot_device 当前无 subsystem_id 列(rebuild 逻辑标 TODO B11),
待 B11 加列后启用 DB 重建查询。
Co-Authored-By: Claude Sonnet (B10 subagent) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context, orchestrator) <noreply@anthropic.com>
|
2026-04-23 21:08:00 +08:00 |
|
|
|
fef3e13ff4
|
fix(iot): IoT 事件发布补充 tenantId 并修复租户上下文缺陷
7 个事件构建点补充 .tenantId(TenantContextHolder.getTenantId()):
- TrafficThresholdRuleProcessor: CleanOrderCreateEvent
- BeaconDetectionRuleProcessor: CleanOrderArriveEvent, CleanOrderAuditEvent
- SignalLossRuleProcessor: CleanOrderCompleteEvent, CleanOrderAuditEvent
- ButtonEventRuleProcessor: confirm/query 事件 Map
其他修复:
- IotSceneRuleMessageHandler: 添加 TenantUtils.execute() 包裹
- SignalLossRuleProcessor: 硬编码 execute(1L) 改为从设备动态获取
- 更新 SignalLossRuleProcessorTest 和 RssiSlidingWindowDetectorTest
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-03-30 11:41:41 +08:00 |
|
|
|
d2f2e06c58
|
test: 更新测试数据以适配配置模型变更
Java CI with Maven / build (11) (push) Has been cancelled
Java CI with Maven / build (17) (push) Has been cancelled
Java CI with Maven / build (8) (push) Has been cancelled
- SignalLossRuleProcessorTest: 更新测试用例
- area_device_relation_full_config.sql: 移除buttonEvent配置
- badge_device_dispatch_test_data.sql: 更新测试数据
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
2026-02-01 00:57:52 +08:00 |
|
|
|
a3909a0482
|
test: Adapt tests to master branch refactoring (handlers and dispatch logic)
|
2026-01-25 18:41:00 +08:00 |
|
|
|
130048d958
|
Merge remote-tracking branch 'origin/master' into test/cleaning-coverage
|
2026-01-25 18:29:47 +08:00 |
|
|
|
373f379b01
|
refactor(iot): 移除Redis DAO,使用统一服务接口
- 删除 DeviceCurrentOrderRedisDAO
- 各 RuleProcessor 直接调用 BadgeDeviceStatusService
- 简化调用链,移除中间层
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
2026-01-25 18:23:15 +08:00 |
|
|
|
382e4d6ae2
|
test: Fix master branch test configs and add comprehensive tests for Badge Device Dispatch and Signal Loss logic
|
2026-01-23 14:29:46 +08:00 |
|
|
|
5bb3ff6979
|
test: Add comprehensive tests for dispatch strategies and IoT signal processing, fix SignalLossRuleProcessor bug
|
2026-01-23 11:44:49 +08:00 |
|
|
|
8ccfafe2bb
|
first commit
Java CI with Maven / build (11) (push) Has been cancelled
Java CI with Maven / build (17) (push) Has been cancelled
Java CI with Maven / build (8) (push) Has been cancelled
|
2025-12-31 11:48:19 +08:00 |
|