diff --git a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/dal/dataobject/integration/clean/CleanOrderIntegrationConfig.java b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/dal/dataobject/integration/clean/CleanOrderIntegrationConfig.java index c6e3f23..da78be8 100644 --- a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/dal/dataobject/integration/clean/CleanOrderIntegrationConfig.java +++ b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/dal/dataobject/integration/clean/CleanOrderIntegrationConfig.java @@ -7,6 +7,9 @@ import lombok.Data; *
* 这是 IoT 设备与保洁工单集成的总配置类,包含所有子配置 * 存储在 Ops 模块的 {@code ops_area_device_relation.config_data} 字段中 + *
+ * 注意:此配置仅包含区域级配置(如客流阈值、信标检测), + * 设备级配置(如按键映射)应存储在 {@code iot_device.config} 字段中 * * @author AI */ @@ -26,11 +29,4 @@ public class CleanOrderIntegrationConfig { * 用于基于工牌蓝牙信标检测自动确认到岗/离岗 */ private BeaconPresenceConfig beaconPresence; - - /** - * 按键事件配置 - *
- * 用于工牌按键事件的处理 - */ - private ButtonEventConfig buttonEvent; } diff --git a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigService.java b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigService.java index 51007de..c5b8d86 100644 --- a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigService.java +++ b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigService.java @@ -13,15 +13,30 @@ import com.viewsh.module.iot.dal.dataobject.integration.clean.CleanOrderIntegrat public interface CleanOrderIntegrationConfigService { /** - * 根据设备ID查询配置包装器(包含完整信息) + * 根据设备ID查询配置包装器 *
- * 返回包含设备ID、区域ID、关联类型等完整信息的配置包装器 + * 适用于一对一关系的设备(如 TRAFFIC_COUNTER),设备只关联一个区域 + *
+ * 内部实现:先通过 deviceId 获取 areaId,再查询配置 * * @param deviceId 设备ID * @return 配置包装器,如果不存在或未启用返回 null */ AreaDeviceConfigWrapper getConfigWrapperByDeviceId(Long deviceId); + /** + * 根据设备ID和区域ID查询配置包装器(包含完整信息) + *
+ * 返回包含设备ID、区域ID、关联类型等完整信息的配置包装器 + *
+ * 缓存Key: ops:area:{areaId}:type:{relationType} + * + * @param deviceId 设备ID + * @param areaId 区域ID + * @return 配置包装器,如果不存在或未启用返回 null + */ + AreaDeviceConfigWrapper getConfigWrapperByDeviceIdAndAreaId(Long deviceId, Long areaId); + /** * 根据区域ID查询所有启用的配置(带缓存) *
@@ -72,6 +87,16 @@ public interface CleanOrderIntegrationConfigService { */ void evictAreaCache(Long areaId); + /** + * 转换配置数据 Map -> CleanOrderIntegrationConfig + *
+ * 公开方法,供其他模块(如 TrafficThresholdRuleProcessor)调用
+ *
+ * @param configData 配置数据 Map
+ * @return 集成配置对象,如果输入为空返回 null
+ */
+ CleanOrderIntegrationConfig convertConfig(java.util.Map
diff --git a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigServiceImpl.java b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigServiceImpl.java
index 3b190b5..81db962 100644
--- a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigServiceImpl.java
+++ b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/integration/clean/CleanOrderIntegrationConfigServiceImpl.java
@@ -1,209 +1,320 @@
-package com.viewsh.module.iot.service.integration.clean;
-
-import com.viewsh.framework.common.pojo.CommonResult;
-import com.viewsh.framework.common.util.json.JsonUtils;
-import com.viewsh.module.iot.dal.dataobject.integration.clean.CleanOrderIntegrationConfig;
-import com.viewsh.module.ops.api.area.AreaDeviceApi;
-import com.viewsh.module.ops.api.area.AreaDeviceDTO;
-import com.viewsh.module.ops.api.area.DeviceRelationDTO;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 保洁工单集成配置 Service 实现类
- *
- * @author AI
- */
-@Service
-@Slf4j
-public class CleanOrderIntegrationConfigServiceImpl implements CleanOrderIntegrationConfigService {
-
- /**
- * Redis Key 前缀(与 Ops 模块保持一致)
- */
- private static final String DEVICE_CACHE_KEY_PREFIX = "ops:area:device:";
- private static final String AREA_TYPE_CACHE_KEY_PREFIX = "ops:area:%s:type:%s";
- private static final String NULL_CACHE = "NULL";
-
- /**
- * Ops 模块区域设备 API Client
- */
- @Resource
- private AreaDeviceApi areaDeviceApi;
-
- @Resource
- private StringRedisTemplate stringRedisTemplate;
-
- @Override
- public List
+ * 用于遍历查找设备配置
+ */
+ private static final String[] DEVICE_RELATION_TYPES = {"BADGE", "BEACON", "TRAFFIC_COUNTER"};
+
+ /**
+ * 缓存过期时间
+ */
+ private static final long DEVICE_INDEX_CACHE_TTL_SECONDS = 3600L; // 1小时
+
+ /**
+ * Ops 模块区域设备 API Client
+ */
+ @Resource
+ private AreaDeviceApi areaDeviceApi;
+
+ @Resource
+ private StringRedisTemplate stringRedisTemplate;
+
+ @Override
+ public List> result = areaDeviceApi.getDevicesByAreaAndType(areaId, null);
-
- if (result == null || !result.isSuccess() || result.getData() == null) {
- log.warn("[CleanOrderConfig] 调用 Ops 模块获取区域配置失败:areaId={}", areaId);
- return List.of();
- }
-
- return result.getData().stream()
- .map(this::wrapDto)
- .collect(Collectors.toList());
- }
-
- @Override
- public List
> result = areaDeviceApi.getDevicesByAreaAndType(areaId, relationType);
-
- if (result == null || !result.isSuccess() || result.getData() == null) {
- log.warn("[CleanOrderConfig] 调用 Ops 模块获取区域配置失败:areaId={}, relationType={}", areaId, relationType);
- return List.of();
- }
-
- return result.getData().stream()
- .map(this::wrapDto)
- .collect(Collectors.toList());
- }
-
- @Override
- public AreaDeviceConfigWrapper getConfigByAreaIdAndRelationType(Long areaId, String relationType) {
- log.debug("[CleanOrderConfig] 查询单个区域配置:areaId={}, relationType={}", areaId, relationType);
-
- // 1. 先读 Redis 缓存
- String cacheKey = String.format(AREA_TYPE_CACHE_KEY_PREFIX, areaId, relationType);
- try {
- String cached = stringRedisTemplate.opsForValue().get(cacheKey);
- if (cached != null) {
- if (NULL_CACHE.equals(cached)) {
- log.debug("[CleanOrderConfig] 命中空值缓存:areaId={}, relationType={}", areaId, relationType);
- return null;
- }
- log.debug("[CleanOrderConfig] 命中 Redis 缓存:areaId={}, relationType={}", areaId, relationType);
- AreaDeviceDTO dto = JsonUtils.parseObject(cached, AreaDeviceDTO.class);
- return wrapDto(dto);
- }
- } catch (Exception e) {
- log.warn("[CleanOrderConfig] 读取 Redis 缓存失败:areaId={}, relationType={}", areaId, relationType, e);
- }
-
- // 2. 缓存未命中,调用 Ops 模块
- CommonResult
> result = areaDeviceApi.getDevicesByAreaAndType(areaId, relationType);
-
- if (result == null || !result.isSuccess() || result.getData() == null) {
- log.warn("[CleanOrderConfig] 调用 Ops 模块获取区域配置失败:areaId={}, relationType={}", areaId, relationType);
- return null;
- }
-
- // 返回第一个启用的配置
- return result.getData().stream()
- .filter(dto -> dto.getEnabled() != null && dto.getEnabled())
- .findFirst()
- .map(this::wrapDto)
- .orElse(null);
- }
-
- @Override
- public AreaDeviceConfigWrapper getConfigWrapperByDeviceId(Long deviceId) {
- log.debug("[CleanOrderConfig] 查询设备完整配置:deviceId={}", deviceId);
-
- // 1. 先读 Redis 缓存
- String cacheKey = DEVICE_CACHE_KEY_PREFIX + deviceId;
- try {
- String cached = stringRedisTemplate.opsForValue().get(cacheKey);
- if (cached != null) {
- if (NULL_CACHE.equals(cached)) {
- log.debug("[CleanOrderConfig] 命中空值缓存:deviceId={}", deviceId);
- return null;
- }
- log.debug("[CleanOrderConfig] 命中 Redis 缓存:deviceId={}", deviceId);
- AreaDeviceDTO dto = JsonUtils.parseObject(cached, AreaDeviceDTO.class);
- return wrapDto(dto);
- }
- } catch (Exception e) {
- log.warn("[CleanOrderConfig] 读取 Redis 缓存失败:deviceId={}", deviceId, e);
- }
-
- // 2. 缓存未命中,调用 Ops 模块
- CommonResult
> result = areaDeviceApi.getDevicesByAreaAndType(areaId, null);
+
+ if (result == null || !result.isSuccess() || result.getData() == null) {
+ log.warn("[CleanOrderConfig] 调用 Ops 模块获取区域配置失败:areaId={}", areaId);
+ return List.of();
+ }
+
+ return result.getData().stream()
+ .map(this::wrapDto)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List
> result = areaDeviceApi.getDevicesByAreaAndType(areaId, relationType);
+
+ if (result == null || !result.isSuccess() || result.getData() == null) {
+ log.warn("[CleanOrderConfig] 调用 Ops 模块获取区域配置失败:areaId={}, relationType={}", areaId, relationType);
+ return List.of();
+ }
+
+ return result.getData().stream()
+ .map(this::wrapDto)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public AreaDeviceConfigWrapper getConfigByAreaIdAndRelationType(Long areaId, String relationType) {
+ log.debug("[CleanOrderConfig] 查询单个区域配置:areaId={}, relationType={}", areaId, relationType);
+
+ // 1. 先读 Redis 缓存
+ String cacheKey = String.format(AREA_TYPE_CACHE_KEY_PREFIX, areaId, relationType);
+ try {
+ String cached = stringRedisTemplate.opsForValue().get(cacheKey);
+ if (cached != null) {
+ if (NULL_CACHE.equals(cached)) {
+ log.debug("[CleanOrderConfig] 命中空值缓存:areaId={}, relationType={}", areaId, relationType);
+ return null;
+ }
+ log.debug("[CleanOrderConfig] 命中 Redis 缓存:areaId={}, relationType={}", areaId, relationType);
+ AreaDeviceDTO dto = JsonUtils.parseObject(cached, AreaDeviceDTO.class);
+ return wrapDto(dto);
+ }
+ } catch (Exception e) {
+ log.warn("[CleanOrderConfig] 读取 Redis 缓存失败:areaId={}, relationType={}", areaId, relationType, e);
+ }
+
+ // 2. 缓存未命中,调用 Ops 模块
+ CommonResult
> result = areaDeviceApi.getDevicesByAreaAndType(areaId, relationType);
+
+ if (result == null || !result.isSuccess() || result.getData() == null) {
+ log.warn("[CleanOrderConfig] 调用 Ops 模块获取区域配置失败:areaId={}, relationType={}", areaId, relationType);
+ return null;
+ }
+
+ // 返回第一个启用的配置
+ return result.getData().stream()
+ .filter(dto -> dto.getEnabled() != null && dto.getEnabled())
+ .findFirst()
+ .map(this::wrapDto)
+ .orElse(null);
+ }
+
+ @Override
+ public AreaDeviceConfigWrapper getConfigWrapperByDeviceId(Long deviceId) {
+ if (deviceId == null) {
+ return null;
+ }
+
+ log.debug("[CleanOrderConfig] 查询设备配置:deviceId={}", deviceId);
+
+ // 1. 查询设备反向索引缓存
+ String indexKey = String.format(DEVICE_INDEX_KEY_PREFIX, deviceId);
+ try {
+ Map