运行策略测试修改
This commit is contained in:
@ -194,6 +194,7 @@ public class EmsSiteConfigController extends BaseController{
|
|||||||
/**
|
/**
|
||||||
* PCS设备开关机
|
* PCS设备开关机
|
||||||
*/
|
*/
|
||||||
|
// @PreAuthorize("@ss.hasPermi('system:device:onAndOff')")
|
||||||
@Log(title = "开关机", businessType = BusinessType.UPDATE)
|
@Log(title = "开关机", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/updateDeviceStatus")
|
@PostMapping("/updateDeviceStatus")
|
||||||
public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request)
|
public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request)
|
||||||
|
|||||||
@ -6,10 +6,21 @@ import com.xzzn.common.enums.TopicHandleType;
|
|||||||
import com.xzzn.common.utils.StringUtils;
|
import com.xzzn.common.utils.StringUtils;
|
||||||
import com.xzzn.ems.domain.EmsMqttTopicConfig;
|
import com.xzzn.ems.domain.EmsMqttTopicConfig;
|
||||||
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
|
import com.xzzn.ems.mapper.EmsMqttTopicConfigMapper;
|
||||||
import com.xzzn.ems.service.*;
|
import com.xzzn.ems.service.IDDSDataProcessService;
|
||||||
|
import com.xzzn.ems.service.IDeviceDataProcessService;
|
||||||
|
import com.xzzn.ems.service.IEmsMqttMessageService;
|
||||||
|
import com.xzzn.ems.service.IEmsStrategyService;
|
||||||
|
import com.xzzn.ems.service.IFXXAlarmDataProcessService;
|
||||||
|
import com.xzzn.ems.service.IFXXDataProcessService;
|
||||||
|
import com.xzzn.ems.service.IMqttSyncLogService;
|
||||||
import com.xzzn.framework.manager.MqttLifecycleManager;
|
import com.xzzn.framework.manager.MqttLifecycleManager;
|
||||||
import com.xzzn.framework.web.service.MqttPublisher;
|
import com.xzzn.framework.web.service.MqttPublisher;
|
||||||
import com.xzzn.framework.web.service.MqttSubscriber;
|
import com.xzzn.framework.web.service.MqttSubscriber;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
|
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
@ -19,9 +30,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
||||||
|
|
||||||
@ -170,6 +178,7 @@ public class MqttMessageController implements MqttPublisher, MqttSubscriber {
|
|||||||
|
|
||||||
emsMqttMessageService.insertMqttOriginalMessage(topic, payload);
|
emsMqttMessageService.insertMqttOriginalMessage(topic, payload);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
log.error("Failed to process device alarm data message: " + e.getMessage(), e);
|
log.error("Failed to process device alarm data message: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.xzzn.common.core.modbus;
|
package com.xzzn.common.core.modbus;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.serotonin.modbus4j.BatchRead;
|
import com.serotonin.modbus4j.BatchRead;
|
||||||
import com.serotonin.modbus4j.BatchResults;
|
import com.serotonin.modbus4j.BatchResults;
|
||||||
import com.serotonin.modbus4j.ModbusMaster;
|
import com.serotonin.modbus4j.ModbusMaster;
|
||||||
@ -22,6 +23,7 @@ import com.xzzn.common.core.redis.RedisCache;
|
|||||||
import com.xzzn.common.enums.ModBusType;
|
import com.xzzn.common.enums.ModBusType;
|
||||||
import com.xzzn.common.enums.RegisterType;
|
import com.xzzn.common.enums.RegisterType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -47,6 +49,7 @@ public class ModbusProcessor {
|
|||||||
private Modbus4jConnectionManager connectionManager;
|
private Modbus4jConnectionManager connectionManager;
|
||||||
|
|
||||||
public boolean writeDataToDevice(DeviceConfig config) {
|
public boolean writeDataToDevice(DeviceConfig config) {
|
||||||
|
logger.info("writeDataToDevice: {}", JSON.toJSONString(config));
|
||||||
ModbusMaster master = null;
|
ModbusMaster master = null;
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
try {
|
try {
|
||||||
@ -80,7 +83,12 @@ public class ModbusProcessor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HOLDING_REGISTER: {
|
case HOLDING_REGISTER: {
|
||||||
double doubleValue = Double.parseDouble(String.valueOf(tag.getValue()));
|
Number value = Double.parseDouble(String.valueOf(tag.getValue()));
|
||||||
|
double doubleValue = value.doubleValue();
|
||||||
|
// 检查是否在16位有符号整数范围内
|
||||||
|
if (doubleValue < -32768 || doubleValue > 32767) {
|
||||||
|
logger.warn("Value {} out of range for 16-bit signed register at address {}", doubleValue, address);
|
||||||
|
}
|
||||||
writeRegisterRequest(master, config.getSlaveId(), address, (int) doubleValue);
|
writeRegisterRequest(master, config.getSlaveId(), address, (int) doubleValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -161,7 +169,7 @@ public class ModbusProcessor {
|
|||||||
|
|
||||||
public static void setRegisterValue(ModbusMaster master, int slaveId, int address, int value) {
|
public static void setRegisterValue(ModbusMaster master, int slaveId, int address, int value) {
|
||||||
// 写入单个保持寄存器(从站, 地址, 16位整数)
|
// 写入单个保持寄存器(从站, 地址, 16位整数)
|
||||||
BaseLocator<Number> holdingLocator = BaseLocator.holdingRegister(slaveId, address, DataType.TWO_BYTE_INT_UNSIGNED);
|
BaseLocator<Number> holdingLocator = BaseLocator.holdingRegister(slaveId, address, DataType.TWO_BYTE_INT_SIGNED);
|
||||||
try {
|
try {
|
||||||
// 写入整数值到保持寄存器
|
// 写入整数值到保持寄存器
|
||||||
master.setValue(holdingLocator, value);
|
master.setValue(holdingLocator, value);
|
||||||
@ -174,7 +182,7 @@ public class ModbusProcessor {
|
|||||||
public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
|
public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
|
||||||
ModbusMaster master = connectionManager.borrowMaster(config);
|
ModbusMaster master = connectionManager.borrowMaster(config);
|
||||||
// 设置了Modbus通信的超时时间为3000毫秒(3秒)。当主设备与从设备通信时,若在3秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
|
// 设置了Modbus通信的超时时间为3000毫秒(3秒)。当主设备与从设备通信时,若在3秒内未收到响应,则认为通信超时并抛出异常。这有助于避免长时间等待无响应的设备。
|
||||||
master.setTimeout(5000);
|
master.setTimeout(10000);
|
||||||
return master;
|
return master;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,14 +347,22 @@ public class ModbusProcessor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
BatchResults<String> results = master.send(batch);
|
BatchResults<String> results = master.send(batch);
|
||||||
for (TagConfig tag : tags){
|
|
||||||
if (tag.getBit()!=null){
|
|
||||||
logger.info("批处理读取寄存器成功: {}",tag.getAddress() +"(" + tag.getBit() + "):" + results.getValue(tag.getKey()));
|
|
||||||
|
|
||||||
|
List<String> logInfoList = new ArrayList<>();
|
||||||
|
for (TagConfig tag : tags){
|
||||||
|
StringBuilder logInfo = new StringBuilder();
|
||||||
|
logInfo.append(tag.getAddress());
|
||||||
|
if (tag.getBit()!=null){
|
||||||
|
// logger.info("批处理读取寄存器成功: {}",tag.getAddress() +"(" + tag.getBit() + "):" + results.getValue(tag.getKey()));
|
||||||
|
logInfo.append("(" + tag.getBit() + "):");
|
||||||
}else {
|
}else {
|
||||||
logger.info("批处理读取寄存器成功: {}",tag.getAddress() + ":" + results.getValue(tag.getKey()));
|
// logger.info("批处理读取寄存器成功: {}",tag.getAddress() + ":" + results.getValue(tag.getKey()));
|
||||||
|
logInfo.append(":");
|
||||||
}
|
}
|
||||||
|
logInfo.append(results.getValue(tag.getKey()));
|
||||||
|
logInfoList.add(logInfo.toString());
|
||||||
}
|
}
|
||||||
|
logger.info("批处理读取寄存器成功: {}", JSON.toJSONString(logInfoList));
|
||||||
return results;
|
return results;
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
logger.error("Failed to read master '{}'", slaveId, e);
|
logger.error("Failed to read master '{}'", slaveId, e);
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 轮询设备-通过modbus协议读取数据
|
* 轮询设备-通过modbus协议读取数据
|
||||||
@ -145,8 +146,9 @@ public class ModbusPoller {
|
|||||||
addDeviceOfflineRecord(siteId, config.getDeviceNumber());
|
addDeviceOfflineRecord(siteId, config.getDeviceNumber());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
List<String> rawValuEmptyList = new ArrayList<>();
|
||||||
Map<String, Object> data = modbusProcessor.readDataFromDevice(config, master);
|
Map<String, Object> data = modbusProcessor.readDataFromDevice(config, master);
|
||||||
// 在这里处理采集到的数据
|
// 在这里处理采集到的数据空
|
||||||
config.getTags().forEach(tag -> {
|
config.getTags().forEach(tag -> {
|
||||||
Object rawValue = data.get(tag.getKey());
|
Object rawValue = data.get(tag.getKey());
|
||||||
if (rawValue != null) {
|
if (rawValue != null) {
|
||||||
@ -167,10 +169,14 @@ public class ModbusPoller {
|
|||||||
data.put(tag.getKey(), value);
|
data.put(tag.getKey(), value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data.put(tag.getKey(), rawValue);
|
// data.put(tag.getKey(), rawValue);
|
||||||
log.warn("tag:{},数据为空: {}", tag.getKey(), rawValue);
|
// log.warn("tag:{},数据为空: {}", tag.getKey(), rawValue);
|
||||||
|
rawValuEmptyList.add("tag: " + tag.getKey() + ",数据为空: " + rawValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (!rawValuEmptyList.isEmpty()) {
|
||||||
|
log.warn("设备 {} 数据为空: {}", config.getDeviceName(), JSON.toJSONString(rawValuEmptyList));
|
||||||
|
}
|
||||||
log.info("Data from {}: {}", config.getDeviceName(), data);
|
log.info("Data from {}: {}", config.getDeviceName(), data);
|
||||||
String deviceNumber = config.getDeviceNumber();
|
String deviceNumber = config.getDeviceNumber();
|
||||||
//处理数据并发送MQTT消息、保存Redis数据和数据入库
|
//处理数据并发送MQTT消息、保存Redis数据和数据入库
|
||||||
@ -179,7 +185,7 @@ public class ModbusPoller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processingData(Map<String, Object> data, String deviceNumber) {
|
private void processingData(Map<String, Object> data, String deviceNumber) {
|
||||||
if (data == null || data.size() == 0) {
|
if (CollectionUtils.isEmpty(data)) {
|
||||||
// 增加失败计数
|
// 增加失败计数
|
||||||
int failureCount = deviceFailureCounts.getOrDefault(deviceNumber, 0) + 1;
|
int failureCount = deviceFailureCounts.getOrDefault(deviceNumber, 0) + 1;
|
||||||
deviceFailureCounts.put(deviceNumber, failureCount);
|
deviceFailureCounts.put(deviceNumber, failureCount);
|
||||||
@ -213,7 +219,7 @@ public class ModbusPoller {
|
|||||||
try {
|
try {
|
||||||
mqttPublisher.publish(topic, Collections.singletonList(json).toString(), 0);
|
mqttPublisher.publish(topic, Collections.singletonList(json).toString(), 0);
|
||||||
} catch (MqttException e) {
|
} catch (MqttException e) {
|
||||||
log.error("MQTT消息发布失败: {}", json.toJSONString(), e);
|
log.error("MQTT消息发布失败: {}, reason code: {}", json.toJSONString(), e.getReasonCode() ,e);
|
||||||
}
|
}
|
||||||
log.info("已发送数据: {}", json.toJSONString());
|
log.info("已发送数据: {}", json.toJSONString());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -51,6 +52,8 @@ import org.springframework.stereotype.Component;
|
|||||||
public class StrategyPoller {
|
public class StrategyPoller {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(StrategyPoller.class);
|
private static final Logger logger = LoggerFactory.getLogger(StrategyPoller.class);
|
||||||
|
|
||||||
|
private static final ConcurrentHashMap<Long, Boolean> strategyLocks = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// SOC 上下限值,默认为0%-100%
|
// SOC 上下限值,默认为0%-100%
|
||||||
private static final BigDecimal SOC_DOWN = new BigDecimal(0);
|
private static final BigDecimal SOC_DOWN = new BigDecimal(0);
|
||||||
private static final BigDecimal SOC_UP = new BigDecimal(100);
|
private static final BigDecimal SOC_UP = new BigDecimal(100);
|
||||||
@ -86,6 +89,8 @@ public class StrategyPoller {
|
|||||||
logger.info("开始执行运行策略数据轮询...");
|
logger.info("开始执行运行策略数据轮询...");
|
||||||
List<StrategyRunningVo> strategyRunningVoList = emsStrategyRunningMapper.getPendingPollerStrategy(null);
|
List<StrategyRunningVo> strategyRunningVoList = emsStrategyRunningMapper.getPendingPollerStrategy(null);
|
||||||
strategyRunningVoList.forEach(strategyVo -> {
|
strategyRunningVoList.forEach(strategyVo -> {
|
||||||
|
Long strategyId = strategyVo.getId();
|
||||||
|
if (strategyLocks.putIfAbsent(strategyId, true) == null) {
|
||||||
try {
|
try {
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
processData(strategyVo);
|
processData(strategyVo);
|
||||||
@ -93,9 +98,14 @@ public class StrategyPoller {
|
|||||||
.exceptionally(e -> {
|
.exceptionally(e -> {
|
||||||
logger.error("运行策略{}轮询异常", strategyVo.getId(), e);
|
logger.error("运行策略{}轮询异常", strategyVo.getId(), e);
|
||||||
return null;
|
return null;
|
||||||
});
|
})
|
||||||
|
.thenRun(() -> strategyLocks.remove(strategyId));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("运行策略{}任务失败", strategyVo.getId(), e);
|
logger.error("运行策略{}任务失败", strategyVo.getId(), e);
|
||||||
|
strategyLocks.remove(strategyId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.info("策略{}已在处理中,跳过重复执行", strategyId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -159,7 +169,7 @@ public class StrategyPoller {
|
|||||||
logger.info("当前站点: {} 未配置PCS设备", siteId);
|
logger.info("当前站点: {} 未配置PCS设备", siteId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 判断SOC上限和下限是否在范围内
|
// 判断SOC上下限
|
||||||
if (isSocInRange(emsStrategyTemp)) {
|
if (isSocInRange(emsStrategyTemp)) {
|
||||||
BigDecimal avgChargeDischargePower = emsStrategyTemp.getChargeDischargePower().divide(new BigDecimal(pcsDeviceList.size()));
|
BigDecimal avgChargeDischargePower = emsStrategyTemp.getChargeDischargePower().divide(new BigDecimal(pcsDeviceList.size()));
|
||||||
for (EmsDevicesSetting pcsDevice : pcsDeviceList) {
|
for (EmsDevicesSetting pcsDevice : pcsDeviceList) {
|
||||||
@ -168,8 +178,8 @@ public class StrategyPoller {
|
|||||||
logger.info("当前站点: {}, PCS设备: {} 未获取电池簇数量", siteId, pcsDevice.getDeviceId());
|
logger.info("当前站点: {}, PCS设备: {} 未获取电池簇数量", siteId, pcsDevice.getDeviceId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 平均功率值,根据电池簇数量进行平均分配
|
// 功率默认放大10倍,平均功率值,根据电池簇数量进行平均分配
|
||||||
avgChargeDischargePower = avgChargeDischargePower.divide(new BigDecimal(pcsSetting.getClusterNum()));
|
avgChargeDischargePower = avgChargeDischargePower.multiply(new BigDecimal(10)).divide(new BigDecimal(pcsSetting.getClusterNum()));
|
||||||
// 根据充电状态,处理数据
|
// 根据充电状态,处理数据
|
||||||
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus())) {
|
||||||
// 发送Modbus命令控制设备-充电
|
// 发送Modbus命令控制设备-充电
|
||||||
@ -189,7 +199,7 @@ public class StrategyPoller {
|
|||||||
powerDownType = lastStrategyLog.getPowerDownType();
|
powerDownType = lastStrategyLog.getPowerDownType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询电网电表的正向有功功率
|
// 查询电网电表的正向有功功率,36kW-50kW范围内,稳定运行,低于36kW,降功率,高于50kW,增加功率
|
||||||
EmsAmmeterData emsAmmeterData = emsAmmeterDataMapper.getLastData(emsStrategyTemp.getSiteId(), SiteDevice.LOAD.name());
|
EmsAmmeterData emsAmmeterData = emsAmmeterDataMapper.getLastData(emsStrategyTemp.getSiteId(), SiteDevice.LOAD.name());
|
||||||
if (emsAmmeterData == null || emsAmmeterData.getTotalActivePower() == null) {
|
if (emsAmmeterData == null || emsAmmeterData.getTotalActivePower() == null) {
|
||||||
logger.info("当前站点: {}, 未获取到最新电表数据", emsStrategyTemp.getSiteId());
|
logger.info("当前站点: {}, 未获取到最新电表数据", emsStrategyTemp.getSiteId());
|
||||||
@ -202,8 +212,8 @@ public class StrategyPoller {
|
|||||||
chargeDischargePower = chargeDischargePower.subtract(power);
|
chargeDischargePower = chargeDischargePower.subtract(power);
|
||||||
powerDownType = 0;
|
powerDownType = 0;
|
||||||
} else {
|
} else {
|
||||||
// 判断是否需要增加功率
|
// 判断是否需要增加功率,
|
||||||
if (powerDownType != null && emsAmmeterData.getTotalActivePower().compareTo(ANTI_REVERSE_UP) < 0) {
|
if (powerDownType != null && emsAmmeterData.getTotalActivePower().compareTo(ANTI_REVERSE_UP) > 0) {
|
||||||
if (chargeDischargePower.compareTo(avgChargeDischargePower) == 0) {
|
if (chargeDischargePower.compareTo(avgChargeDischargePower) == 0) {
|
||||||
// 功率增加到平均值则停止
|
// 功率增加到平均值则停止
|
||||||
continue;
|
continue;
|
||||||
@ -364,13 +374,19 @@ public class StrategyPoller {
|
|||||||
String siteId = pcsDevice.getSiteId();
|
String siteId = pcsDevice.getSiteId();
|
||||||
String deviceId = pcsDevice.getDeviceId();
|
String deviceId = pcsDevice.getDeviceId();
|
||||||
List<EmsStrategyLog> strategyLogList = getStrategyLog(deviceId, chargeStatus.getCode(), emsStrategyTemp, needAntiReverseFlow);
|
List<EmsStrategyLog> strategyLogList = getStrategyLog(deviceId, chargeStatus.getCode(), emsStrategyTemp, needAntiReverseFlow);
|
||||||
if (CollectionUtils.isNotEmpty(strategyLogList) && (!ChargeStatus.DISCHARGING.equals(chargeStatus) || !needAntiReverseFlow)) {
|
if (CollectionUtils.isNotEmpty(strategyLogList)) {
|
||||||
|
boolean isExist = true;
|
||||||
|
if (ChargeStatus.DISCHARGING.equals(chargeStatus) && needAntiReverseFlow) {
|
||||||
|
isExist = false;
|
||||||
|
}
|
||||||
|
if (isExist) {
|
||||||
logger.info("当前站点: {}, PCS设备: {} 当前时间段已存在策略执行记录,不再重复执行", siteId, deviceId);
|
logger.info("当前站点: {}, PCS设备: {} 当前时间段已存在策略执行记录,不再重复执行", siteId, deviceId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 每次操作先判断设备工作状态
|
// 每次操作先判断设备工作状态
|
||||||
if (WorkStatus.ABNORMAL.getCode().equals(pcsDevice.getWorkStatus())) {
|
if (StringUtils.isEmpty(pcsDevice.getWorkStatus()) || WorkStatus.ABNORMAL.getCode().equals(pcsDevice.getWorkStatus())) {
|
||||||
// 设备故障,不发送指令
|
// 设备故障,不发送指令
|
||||||
continue;
|
continue;
|
||||||
} else if (WorkStatus.STOP.getCode().equals(pcsDevice.getWorkStatus())) {
|
} else if (WorkStatus.STOP.getCode().equals(pcsDevice.getWorkStatus())) {
|
||||||
@ -381,6 +397,7 @@ public class StrategyPoller {
|
|||||||
} else {
|
} else {
|
||||||
// 充、放电,则先开机设备
|
// 充、放电,则先开机设备
|
||||||
switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL);
|
switchDevice(pcsDevice, pcsSetting, WorkStatus.NORMAL);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,11 +408,12 @@ public class StrategyPoller {
|
|||||||
boolean result = modbusProcessor.writeDataToDevice(deviceConfig);
|
boolean result = modbusProcessor.writeDataToDevice(deviceConfig);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
|
logger.info("当前站点: {}, PCS设备: {} modbus控制设备{}指令发送失败", siteId, deviceId, chargeStatus.getInfo());
|
||||||
}
|
} else {
|
||||||
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
|
if (ChargeStatus.STANDBY.equals(chargeStatus)) {
|
||||||
// 待机,先写功率值,再关机
|
// 待机,先写功率值,再关机
|
||||||
switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP);
|
switchDevice(pcsDevice, pcsSetting, WorkStatus.STOP);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 记录策略执行日志
|
// 记录策略执行日志
|
||||||
saveStrategyLog(deviceId, chargeDischargePower, chargeStatus.getCode(), emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
saveStrategyLog(deviceId, chargeDischargePower, chargeStatus.getCode(), emsStrategyTemp, needAntiReverseFlow, powerDownType);
|
||||||
}
|
}
|
||||||
@ -406,7 +424,7 @@ public class StrategyPoller {
|
|||||||
String siteId = pcsDevice.getSiteId();
|
String siteId = pcsDevice.getSiteId();
|
||||||
String deviceId = pcsDevice.getDeviceId();
|
String deviceId = pcsDevice.getDeviceId();
|
||||||
pcsDevice.setWorkStatus(workStatus.getCode());
|
pcsDevice.setWorkStatus(workStatus.getCode());
|
||||||
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 0);
|
DeviceConfig deviceConfig = getDeviceConfig(siteId, deviceId, pcsDevice, pcsSetting , null, 1);
|
||||||
if (deviceConfig == null) {
|
if (deviceConfig == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -428,7 +446,7 @@ public class StrategyPoller {
|
|||||||
return now.equals(startLocalTime) || (now.isAfter(startLocalTime) && now.isBefore(endLocalTime));
|
return now.equals(startLocalTime) || (now.isAfter(startLocalTime) && now.isBefore(endLocalTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断SOC上限和下限是否在范围内
|
// 判断SOC上限和下限
|
||||||
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp) {
|
private boolean isSocInRange(EmsStrategyTemp emsStrategyTemp) {
|
||||||
BigDecimal socDown = SOC_DOWN;
|
BigDecimal socDown = SOC_DOWN;
|
||||||
BigDecimal socUp = SOC_UP;
|
BigDecimal socUp = SOC_UP;
|
||||||
@ -438,9 +456,20 @@ public class StrategyPoller {
|
|||||||
}
|
}
|
||||||
// 查询电池堆(BMSD) SOC
|
// 查询电池堆(BMSD) SOC
|
||||||
EmsBatteryStack emsBatteryStack = emsBatteryStackMapper.getSiteSumStackInfo(emsStrategyTemp.getSiteId());
|
EmsBatteryStack emsBatteryStack = emsBatteryStackMapper.getSiteSumStackInfo(emsStrategyTemp.getSiteId());
|
||||||
if (emsBatteryStack != null && emsBatteryStack.getStackSoc() != null) {
|
if (emsBatteryStack == null || emsBatteryStack.getStackSoc() == null) {
|
||||||
return emsBatteryStack.getStackSoc().compareTo(socDown) > 0 && emsBatteryStack.getStackSoc().compareTo(socUp) < 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 充电阶段判断SOC上限值
|
||||||
|
if (ChargeStatus.CHARGING.getCode().equals(emsStrategyTemp.getChargeStatus()) && emsBatteryStack.getStackSoc().compareTo(socUp) >= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 放电阶段判断SOC下限值
|
||||||
|
if (ChargeStatus.DISCHARGING.getCode().equals(emsStrategyTemp.getChargeStatus()) && emsBatteryStack.getStackSoc().compareTo(socDown) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,9 @@ public class ProtectionSettingVo {
|
|||||||
/** 设备 */
|
/** 设备 */
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
|
|
||||||
|
/** 设备名称 */
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
/** 点位 */
|
/** 点位 */
|
||||||
private String point;
|
private String point;
|
||||||
|
|
||||||
@ -44,6 +47,14 @@ public class ProtectionSettingVo {
|
|||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDeviceName() {
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceName(String deviceName) {
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getPoint() {
|
public String getPoint() {
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -622,8 +622,8 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i
|
|||||||
|
|
||||||
// 2. 处理枚举值转换
|
// 2. 处理枚举值转换
|
||||||
List<EmsPointEnumMatch> pointEnumMatchList = pointEnumMatchMap.get(fieldName);
|
List<EmsPointEnumMatch> pointEnumMatchList = pointEnumMatchMap.get(fieldName);
|
||||||
if (CollectionUtils.isNotEmpty(pointEnumMatchList)) {
|
if (CollectionUtils.isNotEmpty(pointEnumMatchList) && matchValue != null) {
|
||||||
Object finalMatchValue = matchValue;
|
String finalMatchValue = String.valueOf(matchValue).replace(".0", "");
|
||||||
Optional<EmsPointEnumMatch> enumMatch = pointEnumMatchList.stream()
|
Optional<EmsPointEnumMatch> enumMatch = pointEnumMatchList.stream()
|
||||||
.filter(data -> data.getDataEnumCode().equals(finalMatchValue)).findFirst();
|
.filter(data -> data.getDataEnumCode().equals(finalMatchValue)).findFirst();
|
||||||
if (enumMatch.isPresent()) {
|
if (enumMatch.isPresent()) {
|
||||||
@ -928,7 +928,7 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i
|
|||||||
// 点位匹配数据
|
// 点位匹配数据
|
||||||
List<EmsPointMatch> pointMatchList = devicePointMatchDataProcessor.getDevicePointMatch(siteId, deviceId, DeviceMatchTable.CLUSTER.getCode());
|
List<EmsPointMatch> pointMatchList = devicePointMatchDataProcessor.getDevicePointMatch(siteId, deviceId, DeviceMatchTable.CLUSTER.getCode());
|
||||||
if (CollectionUtils.isEmpty(pointMatchList)) {
|
if (CollectionUtils.isEmpty(pointMatchList)) {
|
||||||
log.info("未找到匹配的点位数据,无法处理LOAD总表数据,siteId: " + siteId + ",deviceId: " + deviceId);
|
log.info("未找到匹配的点位数据,无法处理电池簇数据,siteId: " + siteId + ",deviceId: " + deviceId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<String, List<EmsPointEnumMatch>> pointEnumMatchMap = devicePointMatchDataProcessor.getPointEnumMatchMap(siteId, DeviceMatchTable.CLUSTER.getCode());
|
Map<String, List<EmsPointEnumMatch>> pointEnumMatchMap = devicePointMatchDataProcessor.getPointEnumMatchMap(siteId, DeviceMatchTable.CLUSTER.getCode());
|
||||||
@ -969,11 +969,11 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveDeviceWorkStatus(String deviceId, String siteId, String workStatus) {
|
private void saveDeviceWorkStatus(String deviceId, String siteId, String workStatus) {
|
||||||
if (StringUtils.isBlank(workStatus)) {
|
if (StringUtils.isEmpty(workStatus)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EmsDevicesSetting emsDevicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
|
EmsDevicesSetting emsDevicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
|
||||||
emsDevicesSetting.setWorkStatus(String.valueOf(new BigDecimal(workStatus).longValue()));
|
emsDevicesSetting.setWorkStatus(workStatus);
|
||||||
emsDevicesSetting.setUpdatedAt(DateUtils.getNowDate());
|
emsDevicesSetting.setUpdatedAt(DateUtils.getNowDate());
|
||||||
emsDevicesSettingMapper.updateEmsDevicesSetting(emsDevicesSetting);
|
emsDevicesSettingMapper.updateEmsDevicesSetting(emsDevicesSetting);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -250,7 +250,7 @@ public class EmsPointMatchServiceImpl implements IEmsPointMatchService {
|
|||||||
String pointEnumMatchKey = DevicePointMatchDataProcessor.getPointEnumMacthCacheKey(siteId, deviceCategory);
|
String pointEnumMatchKey = DevicePointMatchDataProcessor.getPointEnumMacthCacheKey(siteId, deviceCategory);
|
||||||
List<EmsPointEnumMatch> pointEnumMatchList = emsPointEnumMatchMapper.selectList(siteId, deviceCategory, null);
|
List<EmsPointEnumMatch> pointEnumMatchList = emsPointEnumMatchMapper.selectList(siteId, deviceCategory, null);
|
||||||
if (!CollectionUtils.isEmpty(pointEnumMatchList)) {
|
if (!CollectionUtils.isEmpty(pointEnumMatchList)) {
|
||||||
if (redisCache.hasKey(pointEnumMatchKey)) {
|
if (Boolean.TRUE.equals(redisCache.hasKey(pointEnumMatchKey))) {
|
||||||
redisCache.deleteObject(pointEnumMatchKey);
|
redisCache.deleteObject(pointEnumMatchKey);
|
||||||
}
|
}
|
||||||
redisCache.setCacheList(pointEnumMatchKey, pointEnumMatchList);
|
redisCache.setCacheList(pointEnumMatchKey, pointEnumMatchList);
|
||||||
@ -263,8 +263,14 @@ public class EmsPointMatchServiceImpl implements IEmsPointMatchService {
|
|||||||
if (StringUtils.isAllBlank(matchFieldEnum, dataEnum)) {
|
if (StringUtils.isAllBlank(matchFieldEnum, dataEnum)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<EmsPointEnumMatch> pointEnumMatchList = emsPointEnumMatchMapper.selectList(savePoint.getSiteId(), savePoint.getDeviceCategory(), savePoint.getMatchField());
|
String siteId = savePoint.getSiteId();
|
||||||
|
List<EmsPointEnumMatch> pointEnumMatchList = emsPointEnumMatchMapper.selectList(siteId, savePoint.getDeviceCategory(), savePoint.getMatchField());
|
||||||
if (CollectionUtils.isEmpty(pointEnumMatchList)) {
|
if (CollectionUtils.isEmpty(pointEnumMatchList)) {
|
||||||
|
siteId = SITE_ID;
|
||||||
|
pointEnumMatchList = emsPointEnumMatchMapper.selectList(siteId, savePoint.getDeviceCategory(), savePoint.getMatchField());
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(pointEnumMatchList)) {
|
||||||
|
log.info("未查询到点位点位枚举匹配数据");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String[] matchFieldEnums = matchFieldEnum.split(SEPARATOR);
|
String[] matchFieldEnums = matchFieldEnum.split(SEPARATOR);
|
||||||
@ -272,14 +278,22 @@ public class EmsPointMatchServiceImpl implements IEmsPointMatchService {
|
|||||||
if (matchFieldEnums.length != dataEnums.length) {
|
if (matchFieldEnums.length != dataEnums.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String finalSiteId = siteId;
|
||||||
for (int i = 0; i < matchFieldEnums.length; i++) {
|
for (int i = 0; i < matchFieldEnums.length; i++) {
|
||||||
String enumName = matchFieldEnums[i];
|
String enumName = matchFieldEnums[i];
|
||||||
String dataEnumCode = dataEnums[i];
|
String dataEnumCode = dataEnums[i];
|
||||||
pointEnumMatchList.forEach(pointEnumMatch -> {
|
pointEnumMatchList.forEach(pointEnumMatch -> {
|
||||||
if (pointEnumMatch.getEnumName().equals(enumName)) {
|
if (pointEnumMatch.getEnumName().equals(enumName)) {
|
||||||
pointEnumMatch.setDataEnumCode(dataEnumCode);
|
pointEnumMatch.setDataEnumCode(dataEnumCode);
|
||||||
|
if (SITE_ID.equals(finalSiteId)) {
|
||||||
|
EmsPointEnumMatch insertPointEnumMatch = new EmsPointEnumMatch();
|
||||||
|
BeanUtils.copyProperties(pointEnumMatch, insertPointEnumMatch);
|
||||||
|
insertPointEnumMatch.setSiteId(savePoint.getSiteId());
|
||||||
|
emsPointEnumMatchMapper.insertEmsPointEnumMatch(insertPointEnumMatch);
|
||||||
|
} else {
|
||||||
emsPointEnumMatchMapper.updateDataEnumCodeById(pointEnumMatch);
|
emsPointEnumMatchMapper.updateDataEnumCodeById(pointEnumMatch);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,11 +35,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="templateId != null and templateId != ''"> and template_id = #{templateId}</if>
|
<if test="templateId != null and templateId != ''"> and template_id = #{templateId}</if>
|
||||||
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
|
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
|
||||||
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
||||||
<if test="startTime != null "> and start_time = #{startTime}</if>
|
<if test="startTime != null "> and date_format(start_time, '%H:%i:%s') = date_format(#{startTime}, '%H:%i:%s')</if>
|
||||||
<if test="endTime != null "> and end_time = #{endTime}</if>
|
<if test="endTime != null "> and date_format(end_time, '%H:%i:%s') = date_format(#{endTime}, '%H:%i:%s')</if>
|
||||||
<if test="chargeDischargePower != null "> and charge_discharge_power = #{chargeDischargePower}</if>
|
<if test="chargeDischargePower != null "> and charge_discharge_power = #{chargeDischargePower}</if>
|
||||||
<if test="chargeStatus != null and chargeStatus != ''"> and charge_status = #{chargeStatus}</if>
|
<if test="chargeStatus != null and chargeStatus != ''"> and charge_status = #{chargeStatus}</if>
|
||||||
<if test="executionDate != null "> and execution_date = #{executionDate}</if>
|
<if test="executionDate != null "> and execution_date = date_format(#{executionDate}, '%Y-%m-%d')</if>
|
||||||
<if test="antiReverse != null "> and anti_reverse = #{antiReverse}</if>
|
<if test="antiReverse != null "> and anti_reverse = #{antiReverse}</if>
|
||||||
<if test="powerDownType != null "> and power_down_type = #{powerDownType}</if>
|
<if test="powerDownType != null "> and power_down_type = #{powerDownType}</if>
|
||||||
</where>
|
</where>
|
||||||
@ -132,8 +132,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="templateId != null and templateId != ''"> and template_id = #{templateId}</if>
|
<if test="templateId != null and templateId != ''"> and template_id = #{templateId}</if>
|
||||||
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
|
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
|
||||||
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
||||||
<if test="startTime != null "> and start_time = #{startTime}</if>
|
<if test="startTime != null "> and start_time = date_format(#{startTime}, '%H:%i:%s')</if>
|
||||||
<if test="endTime != null "> and end_time = #{endTime}</if>
|
<if test="endTime != null "> and end_time = date_format(#{endTime}, '%H:%i:%s')</if>
|
||||||
<if test="chargeDischargePower != null "> and charge_discharge_power = #{chargeDischargePower}</if>
|
<if test="chargeDischargePower != null "> and charge_discharge_power = #{chargeDischargePower}</if>
|
||||||
<if test="chargeStatus != null and chargeStatus != ''"> and charge_status = #{chargeStatus}</if>
|
<if test="chargeStatus != null and chargeStatus != ''"> and charge_status = #{chargeStatus}</if>
|
||||||
<if test="executionDate != null "> and execution_date = #{executionDate}</if>
|
<if test="executionDate != null "> and execution_date = #{executionDate}</if>
|
||||||
|
|||||||
Reference in New Issue
Block a user