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>
This commit is contained in:
lzh
2026-03-30 11:41:41 +08:00
parent 7d19e7bafa
commit fef3e13ff4
8 changed files with 55 additions and 30 deletions

View File

@@ -104,6 +104,7 @@ class RssiSlidingWindowDetectorTest {
BeaconPresenceConfig.ExitConfig exitConfig = new BeaconPresenceConfig.ExitConfig();
exitConfig.setWeakRssiThreshold(-85);
exitConfig.setHitCount(2);
exitConfig.setWindowSize(5);
// 场景:在区域内,信号变弱但未达退出阈值 [-80, -82, -84] -> 都在 -70 和 -85 之间 -> 无变化
List<Integer> window = Arrays.asList(-80, -82, -84);

View File

@@ -1,12 +1,14 @@
package com.viewsh.module.iot.service.rule.clean.processor;
import com.viewsh.module.iot.core.integration.constants.CleanOrderTopics;
import com.viewsh.module.iot.dal.dataobject.device.IotDeviceDO;
import com.viewsh.module.iot.dal.dataobject.integration.clean.BeaconPresenceConfig;
import com.viewsh.module.iot.dal.dataobject.integration.clean.CleanOrderIntegrationConfig;
import com.viewsh.module.iot.dal.redis.clean.BadgeDeviceStatusRedisDAO;
import com.viewsh.module.iot.dal.redis.clean.BeaconArrivedTimeRedisDAO;
import com.viewsh.module.iot.dal.redis.clean.BeaconRssiWindowRedisDAO;
import com.viewsh.module.iot.dal.redis.clean.SignalLossRedisDAO;
import com.viewsh.module.iot.service.device.IotDeviceService;
import com.viewsh.module.iot.service.integration.clean.CleanOrderIntegrationConfigService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.junit.jupiter.api.BeforeEach;
@@ -41,6 +43,8 @@ class SignalLossRuleProcessorTest {
@Mock
private CleanOrderIntegrationConfigService configService;
@Mock
private IotDeviceService deviceService;
@Mock
private RocketMQTemplate rocketMQTemplate;
@Mock
private StringRedisTemplate stringRedisTemplate;
@@ -55,6 +59,12 @@ class SignalLossRuleProcessorTest {
when(stringRedisTemplate.keys(anyString())).thenReturn(
Set.of("iot:clean:signal:loss:" + DEVICE_ID + ":" + AREA_ID)
);
// Mock device lookup (for tenant context)
IotDeviceDO device = new IotDeviceDO();
device.setId(DEVICE_ID);
device.setTenantId(1L);
when(deviceService.getDevice(DEVICE_ID)).thenReturn(device);
}
@Test
@@ -108,18 +118,19 @@ class SignalLossRuleProcessorTest {
}
@Test
void testCheckLossTimeout_Suppressed_InvalidDuration() {
// Setup times
void testCheckLossTimeout_ShortDuration_StillCompletes() {
// 注意当前生产代码已暂时取消作业时长不足的抑制逻辑TODO 注释),
// 所有超时情况均触发完成。此测试验证该行为。
long now = System.currentTimeMillis();
long firstLossTime = now - 6 * 60 * 1000; // 6 minutes ago (timeout)
long lastLossTime = now;
long arrivedTime = now - 5 * 60 * 1000; // Only 5 minutes work (min is 10)
long arrivedTime = now - 5 * 60 * 1000; // Only 5 minutes work
// Mock DAOs
when(signalLossRedisDAO.getFirstLossTime(DEVICE_ID, AREA_ID)).thenReturn(firstLossTime);
when(signalLossRedisDAO.getLastLossTime(DEVICE_ID, AREA_ID)).thenReturn(lastLossTime);
when(arrivedTimeRedisDAO.getArrivedTime(DEVICE_ID, AREA_ID)).thenReturn(arrivedTime);
// Mock Current Order (Valid area)
BadgeDeviceStatusRedisDAO.OrderInfo orderInfo = new BadgeDeviceStatusRedisDAO.OrderInfo();
orderInfo.setOrderId(500L);
@@ -130,13 +141,13 @@ class SignalLossRuleProcessorTest {
BeaconPresenceConfig.ExitConfig exitConfig = new BeaconPresenceConfig.ExitConfig();
exitConfig.setLossTimeoutMinutes(5);
exitConfig.setMinValidWorkMinutes(10);
BeaconPresenceConfig bpConfig = new BeaconPresenceConfig();
bpConfig.setExit(exitConfig);
CleanOrderIntegrationConfig mainConfig = new CleanOrderIntegrationConfig();
mainConfig.setBeaconPresence(bpConfig);
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper wrapper =
new CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper();
wrapper.setConfig(mainConfig);
@@ -147,11 +158,7 @@ class SignalLossRuleProcessorTest {
// Execute
processor.checkLossTimeout();
// Verify
// 1. Should NOT send complete message
verify(rocketMQTemplate, never()).syncSend(eq(CleanOrderTopics.ORDER_COMPLETE), any(Message.class));
// 2. Should send Audit Event (TTS)
verify(rocketMQTemplate, atLeastOnce()).syncSend(eq(CleanOrderTopics.ORDER_AUDIT), any(Message.class));
// Verify: 即使作业时长不足,当前仍会触发完成(抑制逻辑已暂时关闭)
verify(rocketMQTemplate).syncSend(eq(CleanOrderTopics.ORDER_COMPLETE), any(Message.class));
}
}