diff --git a/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java b/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java index 7fc2123..b01c6d9 100644 --- a/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java +++ b/intc-modules/intc-iot/src/main/java/com/intc/iot/handler/DeviceDataHandler.java @@ -2179,33 +2179,124 @@ public class DeviceDataHandler { *
  • 溶解氧 ≥ 上限且上限开关已开且未触发过:关闭联动开关,设置 isOxyUpperTrigger=1
  • *
  • 溶解氧 ≤ 上限-0.3且已触发过:重置 isOxyUpperTrigger=0
  • * + *

    + * 当塘口内有多台测氧仪时,以塘口内所有测氧仪的最低溶解氧值作为判断依据, + * 并对塘口内所有配置了联动控制的设备执行判断。 + *

    * * @param deviceName 设备名称(serialNum) - * @param dissolvedOxygen 当前溶解氧値 + * @param dissolvedOxygen 当前溶解氧值(本设备上报值,最终使用塘口最低值) */ private void handleLinkedCtrl(String deviceName, double dissolvedOxygen) { try { - // 查询设备(需要 id 和 iotId) - Device device = deviceMapper.selectOne( + // 查询当前设备(需要 id、iotId、pondId) + Device currentDevice = deviceMapper.selectOne( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() .eq(Device::getSerialNum, deviceName) - .select(Device::getId, Device::getIotId, Device::getSerialNum, Device::getDeviceName) + .select(Device::getId, Device::getIotId, Device::getSerialNum, Device::getDeviceName, + Device::getPondId, Device::getValueDissolvedOxygen) .last("LIMIT 1") ); - if (device == null || device.getId() == null) { + if (currentDevice == null || currentDevice.getId() == null) { return; } - // 查询该设备的所有联动控制配置 + // 先更新当前设备的实时溶解氧(确保后续取最低值时已包含本次上报值) + // 注意:updateDeviceRealTimeData 在 handleLinkedCtrl 调用前已执行,此处直接使用传入值 + + // 确定实际用于联动判断的溶解氧值: + // 若设备属于某个塘口,则取该塘口内所有测氧仪的最低溶解氧值;否则直接使用本设备值 + double effectiveDissolvedOxygen = dissolvedOxygen; + Long pondId = currentDevice.getPondId(); + if (pondId != null) { + // 查询同塘口所有设备(包含溶解氧实时值),用本次上报值覆盖当前设备的库存值 + List pondDevices = deviceMapper.selectList( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(Device::getPondId, pondId) + .select(Device::getId, Device::getSerialNum, Device::getValueDissolvedOxygen, + Device::getIsOxygenUsed, Device::getDeviceType) + ); + double minOxy = dissolvedOxygen; // 默认为本设备当前上报值 + for (Device pd : pondDevices) { + // 仅统计水质检测仪(type=1)或开启溶氧检测的测控一体机(type=2 & isOxygenUsed=1) + boolean isDetector = (pd.getDeviceType() != null && pd.getDeviceType() == 1) + || (pd.getDeviceType() != null && pd.getDeviceType() == 2 + && pd.getIsOxygenUsed() != null && pd.getIsOxygenUsed() == 1); + if (!isDetector) { + continue; + } + double oxy; + if (pd.getId().equals(currentDevice.getId())) { + // 当前设备使用本次最新上报值(库存值可能尚未刷新) + oxy = dissolvedOxygen; + } else { + if (pd.getValueDissolvedOxygen() == null) { + continue; + } + oxy = pd.getValueDissolvedOxygen(); + } + if (oxy < minOxy) { + minOxy = oxy; + } + } + effectiveDissolvedOxygen = minOxy; + log.debug("[联动控制] 塘口={} 设备={} 本机溶解氧={}, 塘口最低溶解氧={}", + pondId, deviceName, dissolvedOxygen, effectiveDissolvedOxygen); + } + + // 查询该塘口(或该设备)所有有联动控制配置的设备 ID + // 若在塘口内,需对塘口内所有设备的联动控制进行判断 + List deviceIdsToCheck = new java.util.ArrayList<>(); + if (pondId != null) { + // 查询同塘口内所有测氧仪设备 ID(含联动控制配置的) + List pondDetectors = deviceMapper.selectList( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(Device::getPondId, pondId) + .select(Device::getId, Device::getIsOxygenUsed, Device::getDeviceType) + ); + for (Device pd : pondDetectors) { + boolean isDetector = (pd.getDeviceType() != null && pd.getDeviceType() == 1) + || (pd.getDeviceType() != null && pd.getDeviceType() == 2 + && pd.getIsOxygenUsed() != null && pd.getIsOxygenUsed() == 1); + if (isDetector) { + deviceIdsToCheck.add(pd.getId()); + } + } + } else { + deviceIdsToCheck.add(currentDevice.getId()); + } + + if (deviceIdsToCheck.isEmpty()) { + return; + } + + // 查询上述设备的所有联动控制配置 List linkedCtrls = linkedCtrlMapper.selectList( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() - .eq(com.intc.fishery.domain.LinkedCtrl::getDeviceId, device.getId()) + .in(com.intc.fishery.domain.LinkedCtrl::getDeviceId, deviceIdsToCheck) ); if (linkedCtrls == null || linkedCtrls.isEmpty()) { return; } + // 预加载联动控制对应的控制器设备信息(用于下发指令),按设备ID缓存 + java.util.Map deviceCacheById = new java.util.HashMap<>(); + deviceCacheById.put(currentDevice.getId(), currentDevice); + for (com.intc.fishery.domain.LinkedCtrl linkedCtrl : linkedCtrls) { + // 获取该联动控制所属设备(用于下发指令时获取 iotId) + Long linkedDeviceId = linkedCtrl.getDeviceId(); + Device device = deviceCacheById.computeIfAbsent(linkedDeviceId, id -> + deviceMapper.selectOne( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(Device::getId, id) + .select(Device::getId, Device::getIotId, Device::getSerialNum, Device::getDeviceName) + .last("LIMIT 1") + ) + ); + if (device == null) { + continue; + } // 查询该联动控制关联的所有开关 List switches = deviceSwitchMapper.selectList( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() @@ -2215,12 +2306,12 @@ public class DeviceDataHandler { continue; } - // 溶解氧下限联动:溶解氧 ≤ 下限就开启开关 + // 溶解氧下限联动:塘口最低溶解氧 ≤ 下限就开启开关 if (linkedCtrl.getOxyLowerOpen() != null && linkedCtrl.getOxyLowerOpen() == 1 && linkedCtrl.getOxyLowerValue() != null - && dissolvedOxygen <= linkedCtrl.getOxyLowerValue()) { - log.info("[联动控制] 设备={} 溶解氧={} ≤ 下限={},开启开关", - deviceName, dissolvedOxygen, linkedCtrl.getOxyLowerValue()); + && effectiveDissolvedOxygen <= linkedCtrl.getOxyLowerValue()) { + log.info("[联动控制] 触发设备={} 塘口最低溶解氧={} ≤ 下限={},开启开关(本机上报={})", + deviceName, effectiveDissolvedOxygen, linkedCtrl.getOxyLowerValue(), dissolvedOxygen); setDeviceSwitchLinkedOpen(device, switches, true); } @@ -2228,28 +2319,28 @@ public class DeviceDataHandler { boolean isOxyUpperTrigger = linkedCtrl.getIsOxyUpperTrigger() != null && linkedCtrl.getIsOxyUpperTrigger() == 1; if (isOxyUpperTrigger) { - // 已触发过:溶解氧降回 上限-0.3 则重置触发标志 + // 已触发过:塘口最低溶解氧降回 上限-0.3 则重置触发标志 if (linkedCtrl.getOxyUpperValue() != null - && dissolvedOxygen <= linkedCtrl.getOxyUpperValue() - 0.3) { + && effectiveDissolvedOxygen <= linkedCtrl.getOxyUpperValue() - 0.3) { com.intc.fishery.domain.LinkedCtrl updateCtrl = new com.intc.fishery.domain.LinkedCtrl(); updateCtrl.setId(linkedCtrl.getId()); updateCtrl.setIsOxyUpperTrigger(0); linkedCtrlMapper.updateById(updateCtrl); - log.info("[联动控制] 设备={} 溶解氧={} 降回至 上限-0.3={},重置触发标志", - deviceName, dissolvedOxygen, linkedCtrl.getOxyUpperValue() - 0.3); + log.info("[联动控制] 触发设备={} 塘口最低溶解氧={} 降回至 上限-0.3={},重置触发标志", + deviceName, effectiveDissolvedOxygen, linkedCtrl.getOxyUpperValue() - 0.3); } } else { - // 未触发:溶解氧 ≥ 上限则关闭开关 + // 未触发:塘口最低溶解氧 ≥ 上限则关闭开关 if (linkedCtrl.getOxyUpperOpen() != null && linkedCtrl.getOxyUpperOpen() == 1 && linkedCtrl.getOxyUpperValue() != null - && dissolvedOxygen >= linkedCtrl.getOxyUpperValue()) { + && effectiveDissolvedOxygen >= linkedCtrl.getOxyUpperValue()) { // 设置触发标志并关闭开关 com.intc.fishery.domain.LinkedCtrl updateCtrl = new com.intc.fishery.domain.LinkedCtrl(); updateCtrl.setId(linkedCtrl.getId()); updateCtrl.setIsOxyUpperTrigger(1); linkedCtrlMapper.updateById(updateCtrl); - log.info("[联动控制] 设备={} 溶解氧={} ≥ 上限={},关闭开关", - deviceName, dissolvedOxygen, linkedCtrl.getOxyUpperValue()); + log.info("[联动控制] 触发设备={} 塘口最低溶解氧={} ≥ 上限={},关闭开关", + deviceName, effectiveDissolvedOxygen, linkedCtrl.getOxyUpperValue()); setDeviceSwitchLinkedOpen(device, switches, false); } }