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);
}
}