Merge branch 'master' of http://124.221.55.225:3000/XW-AIOT/aiot-platform-cloud into test/cleaning-coverage

This commit is contained in:
lzh
2026-01-23 13:57:49 +08:00
15 changed files with 1492 additions and 25 deletions

View File

@@ -54,6 +54,19 @@ public interface CleanOrderIntegrationConfigService {
*/
java.util.List<AreaDeviceConfigWrapper> getConfigsByAreaIdAndRelationType(Long areaId, String relationType);
/**
* 根据区域ID和关联类型查询单个配置
* <p>
* 用于跨设备获取配置的场景,例如:工牌设备需要获取该区域的信标配置
* <p>
* 注意:如果同一区域同一类型有多个设备配置,返回第一个
*
* @param areaId 区域ID
* @param relationType 关联类型TRAFFIC_COUNTER/BEACON/BADGE
* @return 集成配置包装器,如果不存在返回 null
*/
AreaDeviceConfigWrapper getConfigByAreaIdAndRelationType(Long areaId, String relationType);
/**
* 清除设备配置缓存
* <p>

View File

@@ -107,6 +107,24 @@ public class CleanOrderIntegrationConfigServiceImpl implements CleanOrderIntegra
.collect(Collectors.toList());
}
@Override
public AreaDeviceConfigWrapper getConfigByAreaIdAndRelationType(Long areaId, String relationType) {
log.debug("[CleanOrderConfig] 查询单个区域配置areaId={}, relationType={}", areaId, relationType);
List<OpsAreaDeviceRelationDO> relations = relationMapper.selectListByAreaIdAndRelationType(areaId, relationType);
if (relations.isEmpty()) {
return null;
}
// 返回第一个启用的配置
return relations.stream()
.filter(r -> r.getEnabled())
.findFirst()
.map(this::wrapConfig)
.orElse(null);
}
@Override
public AreaDeviceConfigWrapper getConfigWrapperByDeviceId(Long deviceId) {
log.debug("[CleanOrderConfig] 查询设备完整配置deviceId={}", deviceId);

View File

@@ -70,23 +70,32 @@ public class BeaconDetectionRuleProcessor {
log.debug("[BeaconDetection] 收到蓝牙属性deviceId={}", deviceId);
// 2. 获取配置
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper =
// 2. 获取工牌设备的配置包含区域ID
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper badgeConfigWrapper =
configService.getConfigWrapperByDeviceId(deviceId);
if (configWrapper == null || configWrapper.getConfig() == null) {
log.debug("[BeaconDetection] 设备无配置deviceId={}", deviceId);
if (badgeConfigWrapper == null || badgeConfigWrapper.getAreaId() == null) {
log.debug("[BeaconDetection] 工牌设备无区域配置deviceId={}", deviceId);
return;
}
BeaconPresenceConfig beaconConfig = configWrapper.getConfig().getBeaconPresence();
Long areaId = badgeConfigWrapper.getAreaId();
// 3. 获取该区域的信标配置(从 BEACON 类型的设备获取)
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper beaconConfigWrapper =
configService.getConfigByAreaIdAndRelationType(areaId, "BEACON");
if (beaconConfigWrapper == null || beaconConfigWrapper.getConfig() == null) {
log.debug("[BeaconDetection] 区域无信标配置areaId={}", areaId);
return;
}
BeaconPresenceConfig beaconConfig = beaconConfigWrapper.getConfig().getBeaconPresence();
if (beaconConfig == null || !beaconConfig.getEnabled()) {
log.debug("[BeaconDetection] 未启用信标检测:deviceId={}", deviceId);
log.debug("[BeaconDetection] 未启用信标检测:areaId={}", areaId);
return;
}
Long areaId = configWrapper.getAreaId();
// 3. 解析蓝牙数据,提取目标信标的 RSSI
Integer targetRssi = detector.extractTargetRssi(propertyValue, beaconConfig.getBeaconMac());
@@ -118,7 +127,7 @@ public class BeaconDetectionRuleProcessor {
// 9. 处理检测结果
switch (result) {
case ARRIVE_CONFIRMED:
handleArriveConfirmed(deviceId, areaId, window, beaconConfig, configWrapper);
handleArriveConfirmed(deviceId, areaId, window, beaconConfig, badgeConfigWrapper);
break;
case LEAVE_CONFIRMED:
handleLeaveConfirmed(deviceId, areaId, window, beaconConfig);
@@ -134,7 +143,7 @@ public class BeaconDetectionRuleProcessor {
*/
private void handleArriveConfirmed(Long deviceId, Long areaId, List<Integer> window,
BeaconPresenceConfig beaconConfig,
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper) {
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper badgeConfigWrapper) {
log.info("[BeaconDetection] 到达确认deviceId={}, areaId={}, window={}",
deviceId, areaId, window);
@@ -156,11 +165,11 @@ public class BeaconDetectionRuleProcessor {
// 5. 发布到岗事件
if (beaconConfig.getEnter().getAutoArrival()) {
publishArriveEvent(deviceId, configWrapper.getDeviceKey(), areaId, triggerData);
publishArriveEvent(deviceId, badgeConfigWrapper.getDeviceKey(), areaId, triggerData);
}
// 6. 发布审计日志
publishAuditEvent("BEACON_ARRIVE_CONFIRMED", deviceId, configWrapper.getDeviceKey(), areaId,
publishAuditEvent("BEACON_ARRIVE_CONFIRMED", deviceId, badgeConfigWrapper.getDeviceKey(), areaId,
"蓝牙信标自动到岗确认", triggerData);
}

View File

@@ -121,17 +121,23 @@ public class SignalLossRuleProcessor {
return;
}
// 1. 获取配置
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper =
configService.getConfigWrapperByDeviceId(deviceId);
// 1. 获取该区域的信标配置(从 BEACON 类型的设备获取)
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper beaconConfigWrapper =
configService.getConfigByAreaIdAndRelationType(areaId, "BEACON");
if (configWrapper == null || configWrapper.getConfig() == null ||
configWrapper.getConfig().getBeaconPresence() == null) {
log.debug("[SignalLoss] 设备无信标配置:deviceId={}", deviceId);
if (beaconConfigWrapper == null || beaconConfigWrapper.getConfig() == null ||
beaconConfigWrapper.getConfig().getBeaconPresence() == null) {
log.debug("[SignalLoss] 区域无信标配置:areaId={}", areaId);
return;
}
BeaconPresenceConfig.ExitConfig exitConfig = configWrapper.getConfig().getBeaconPresence().getExit();
BeaconPresenceConfig.ExitConfig exitConfig = beaconConfigWrapper.getConfig().getBeaconPresence().getExit();
// 2. 获取工牌设备信息(用于获取 deviceKey
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper badgeConfigWrapper =
configService.getConfigWrapperByDeviceId(deviceId);
String badgeDeviceKey = (badgeConfigWrapper != null) ? badgeConfigWrapper.getDeviceKey() : null;
// 2. 获取首次丢失时间
Long firstLossTime = signalLossRedisDAO.getFirstLossTime(deviceId, areaId);
@@ -175,11 +181,11 @@ public class SignalLossRuleProcessor {
// 6. 分支处理:有效 vs 无效作业
if (durationMs < minValidWorkMillis) {
// 作业时长不足,抑制完成
handleInvalidWork(deviceId, configWrapper.getDeviceKey(), areaId,
handleInvalidWork(deviceId, badgeDeviceKey, areaId,
durationMs, minValidWorkMillis, exitConfig);
} else {
// 作业时长有效,触发完成
handleTimeoutComplete(deviceId, configWrapper.getDeviceKey(), areaId,
handleTimeoutComplete(deviceId, badgeDeviceKey, areaId,
durationMs, lastLossTime);
}
}