13 changed files with 489 additions and 2 deletions
@ -0,0 +1,52 @@ |
|||||||
|
package com.mh.quartz.domain; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @version 1.0 |
||||||
|
* @project EEMCS |
||||||
|
* @description PID参数 |
||||||
|
* @date 2025-05-30 13:51:22 |
||||||
|
*/ |
||||||
|
public class PIDParams { |
||||||
|
|
||||||
|
private volatile double kp; // 比例系数
|
||||||
|
private volatile double ki; // 积分系数
|
||||||
|
private volatile double kd; // 微分系数
|
||||||
|
|
||||||
|
public PIDParams(double kp, double ki, double kd) { |
||||||
|
this.kp = kp; |
||||||
|
this.ki = ki; |
||||||
|
this.kd = kd; |
||||||
|
} |
||||||
|
|
||||||
|
// 动态更新PID参数
|
||||||
|
public void updateParams(double kp, double ki, double kd) { |
||||||
|
this.kp = kp; |
||||||
|
this.ki = ki; |
||||||
|
this.kd = kd; |
||||||
|
} |
||||||
|
|
||||||
|
public double getKp() { |
||||||
|
return kp; |
||||||
|
} |
||||||
|
|
||||||
|
public void setKp(double kp) { |
||||||
|
this.kp = kp; |
||||||
|
} |
||||||
|
|
||||||
|
public double getKi() { |
||||||
|
return ki; |
||||||
|
} |
||||||
|
|
||||||
|
public void setKi(double ki) { |
||||||
|
this.ki = ki; |
||||||
|
} |
||||||
|
|
||||||
|
public double getKd() { |
||||||
|
return kd; |
||||||
|
} |
||||||
|
|
||||||
|
public void setKd(double kd) { |
||||||
|
this.kd = kd; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,258 @@ |
|||||||
|
package com.mh.quartz.task; |
||||||
|
|
||||||
|
import com.mh.common.config.MHConfig; |
||||||
|
import com.mh.common.core.domain.AjaxResult; |
||||||
|
import com.mh.common.core.domain.dto.DeviceMonitorDTO; |
||||||
|
import com.mh.common.core.domain.entity.CollectionParamsManage; |
||||||
|
import com.mh.common.core.domain.entity.CpmSpaceRelation; |
||||||
|
import com.mh.common.core.domain.entity.OrderEntity; |
||||||
|
import com.mh.common.core.domain.entity.PolicyManage; |
||||||
|
import com.mh.common.utils.DateUtils; |
||||||
|
import com.mh.framework.mqtt.service.IMqttGatewayService; |
||||||
|
import com.mh.quartz.domain.PIDParams; |
||||||
|
import com.mh.quartz.util.AHUPIDControlUtil; |
||||||
|
import com.mh.system.service.device.ICollectionParamsManageService; |
||||||
|
import com.mh.system.service.operation.IOperationDeviceService; |
||||||
|
import com.mh.system.service.policy.IPolicyManageService; |
||||||
|
import com.mh.system.service.space.ICpmSpaceRelationService; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
import java.time.LocalTime; |
||||||
|
import java.util.*; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @version 1.0 |
||||||
|
* @project EEMCS |
||||||
|
* @description 风柜系统任务 |
||||||
|
* @date 2025-05-30 08:36:43 |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
@Component("ahuTask") |
||||||
|
public class AHUTask { |
||||||
|
|
||||||
|
@Value("${control.topic}") |
||||||
|
String controlTopic; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private MHConfig mhConfig; |
||||||
|
|
||||||
|
private final ICollectionParamsManageService collectionParamsManageService; |
||||||
|
|
||||||
|
private final IPolicyManageService policyManageService; |
||||||
|
|
||||||
|
private final ICpmSpaceRelationService cpmSpaceRelationService; |
||||||
|
|
||||||
|
private final IOperationDeviceService iOperationService; |
||||||
|
|
||||||
|
private final IMqttGatewayService iMqttGatewayService; |
||||||
|
|
||||||
|
|
||||||
|
@Autowired |
||||||
|
public AHUTask(ICollectionParamsManageService collectionParamsManageService, IPolicyManageService policyManageService, ICpmSpaceRelationService cpmSpaceRelationService, IOperationDeviceService iOperationService, IMqttGatewayService iMqttGatewayService) { |
||||||
|
this.collectionParamsManageService = collectionParamsManageService; |
||||||
|
this.policyManageService = policyManageService; |
||||||
|
this.cpmSpaceRelationService = cpmSpaceRelationService; |
||||||
|
this.iOperationService = iOperationService; |
||||||
|
this.iMqttGatewayService = iMqttGatewayService; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void sendOrderToMqtt(List<OrderEntity> changeValues) { |
||||||
|
try { |
||||||
|
String sendOrder = iOperationService.operationDevice(changeValues); |
||||||
|
String name = mhConfig.getName(); |
||||||
|
// 获取mqtt操作队列(后期通过mqtt队列配置发送主题)
|
||||||
|
log.info("发送主题:{},消息:{}", name + "/" + controlTopic, sendOrder); |
||||||
|
iMqttGatewayService.publish(name + "/" + controlTopic, sendOrder, 1); |
||||||
|
} catch (Exception e) { |
||||||
|
log.error("设备操作失败", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void adjustWaterValve(String kp, String ki, String kd) { |
||||||
|
// 西餐走廊2、宴会走廊需要调整PID参数,其他的ddc自己已经处理好
|
||||||
|
String[] deviceLedgerIds = new String[]{"ddc0083b3a898d85f3a1205a2d82071e100", "ddc0133b3a898d85f3a1205a2d82071e100"}; |
||||||
|
for (String deviceLedgerId : deviceLedgerIds) { |
||||||
|
// 获取西餐走廊2的启停控制
|
||||||
|
HashMap<String, Object> queryMap = new HashMap<>(); |
||||||
|
queryMap.put("systemType", "2"); |
||||||
|
queryMap.put("deviceLedgerId", deviceLedgerId); |
||||||
|
queryMap.put("isUse", 0); |
||||||
|
// 得出 systemType =2 的数据
|
||||||
|
List<CollectionParamsManage> collectionParamsManages = collectionParamsManageService.selectListByParams(queryMap); |
||||||
|
|
||||||
|
// 过滤得出启停状态
|
||||||
|
Optional<CollectionParamsManage> first = collectionParamsManages.stream().filter(item -> item.getCurValue().intValue() == 1 && item.getParamType().equals("2")).findFirst(); |
||||||
|
if (first.isEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// 初始化PID参数(可动态调整)
|
||||||
|
// PIDParams params = new PIDParams(2.5, 0.1, 0.5);
|
||||||
|
PIDParams params = new PIDParams(new BigDecimal(kp).doubleValue(), new BigDecimal(ki).doubleValue(), new BigDecimal(kd).doubleValue()); // Kp, Ki, Kd
|
||||||
|
|
||||||
|
// 过滤获取回风温度设置值
|
||||||
|
Optional<CollectionParamsManage> second = collectionParamsManages |
||||||
|
.stream() |
||||||
|
.filter(item -> item.getOtherName().contains("回风温度") |
||||||
|
&& item.getParamType().equals("14")).findFirst(); |
||||||
|
if (second.isEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
// 得出回风温度设置值
|
||||||
|
double backTemp = second.get().getCurValue().doubleValue(); |
||||||
|
|
||||||
|
// 设定目标温度(夏季制冷24℃)
|
||||||
|
AHUPIDControlUtil pid = new AHUPIDControlUtil(params, backTemp); |
||||||
|
|
||||||
|
// 过滤获取当前回风温度
|
||||||
|
Optional<CollectionParamsManage> third = collectionParamsManages |
||||||
|
.stream() |
||||||
|
.filter(item -> item.getOtherName().contains("回风温度") |
||||||
|
&& item.getParamType().equals("12")).findFirst(); |
||||||
|
if (third.isEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
// 得出当前回风温度
|
||||||
|
double temp = third.get().getCurValue().doubleValue(); |
||||||
|
|
||||||
|
// 2. 计算水阀开度(时间间隔1秒)
|
||||||
|
double valveOpening1 = pid.calculate(temp, 1.0); |
||||||
|
int valveOpening = new BigDecimal(valveOpening1).intValue(); |
||||||
|
|
||||||
|
// 过滤获取水阀调节参数
|
||||||
|
Optional<CollectionParamsManage> fourth = collectionParamsManages |
||||||
|
.stream() |
||||||
|
.filter(item -> item.getOtherName().contains("水阀调节") |
||||||
|
&& item.getParamType().equals("3")).findFirst(); |
||||||
|
if (fourth.isEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
// 得出水阀调节参数
|
||||||
|
CollectionParamsManage collectionParamsManage = fourth.get(); |
||||||
|
// 发送控制指令
|
||||||
|
if (valveOpening > 0 && valveOpening <= 100) { |
||||||
|
// 开启
|
||||||
|
List<OrderEntity> changeValues = new ArrayList<>(); |
||||||
|
changeValues.add(new OrderEntity(collectionParamsManage.getId(), String.valueOf(valveOpening), Integer.parseInt(collectionParamsManage.getParamType()), collectionParamsManage.getOtherName())); |
||||||
|
sendOrderToMqtt(changeValues); |
||||||
|
// 3. 应用水阀开度(实际应用发送给执行机构)
|
||||||
|
log.info("回风温度: {} ℃ | 水阀开度: {} % | P:{}, I:{} D:{} ", |
||||||
|
temp, valveOpening, params.getKp(), params.getKi(), params.getKd()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void startOrStopAHU() { |
||||||
|
// 扫描启动了定时开关机的风机,根据当前时间判断是否需要启动或停止
|
||||||
|
// systemType 2: 风柜系统
|
||||||
|
HashMap<String, Object> queryMap = new HashMap<>(); |
||||||
|
queryMap.put("systemType", "2"); |
||||||
|
// 得出 systemType =2 的数据
|
||||||
|
List<CollectionParamsManage> collectionParamsManages = collectionParamsManageService.selectListByParams(queryMap); |
||||||
|
// 判断当前时间是星期几
|
||||||
|
String dayOfWeekValue = DateUtils.dayOfWeekValue(); |
||||||
|
// 过滤otherName包含dayOfWeekValue,paramType=29, curValue=1的数据,代表已经启用定时开关机的功能
|
||||||
|
List<CollectionParamsManage> needStartOrStopDataList = collectionParamsManages |
||||||
|
.stream() |
||||||
|
.filter(item -> item.getOtherName().contains(dayOfWeekValue) |
||||||
|
&& item.getParamType().equals("29") |
||||||
|
&& item.getCurValue().intValue() == 1) |
||||||
|
.toList(); |
||||||
|
// 查询得出对应的houseId
|
||||||
|
List<PolicyManage> policyManageList = policyManageService.selectListByCpmIds(needStartOrStopDataList); |
||||||
|
|
||||||
|
// 开始:根据houseId查询出对应的风机启停id
|
||||||
|
List<CpmSpaceRelation> cpmSpaceRelationList = cpmSpaceRelationService.selectListByHouseId(policyManageList); |
||||||
|
// collectionParamsManages过滤出能够开启风机的点位,paramType=2,isUse=0
|
||||||
|
List<CollectionParamsManage> startDeviceList = collectionParamsManages |
||||||
|
.stream() |
||||||
|
.filter(item -> item.getParamType().equals("2") |
||||||
|
&& item.getIsUse() == 0) |
||||||
|
.toList(); |
||||||
|
// 结束:根据houseId查询出对应的风机启停id
|
||||||
|
|
||||||
|
// 在拼接出启用定时开关机的启动时间、关闭时间
|
||||||
|
Map<String, List<PolicyManage>> groupedByHouseId = policyManageList.stream() |
||||||
|
.collect(Collectors.groupingBy( |
||||||
|
PolicyManage::getHouseId, |
||||||
|
Collectors.toList() |
||||||
|
)); |
||||||
|
// groupedByHouseId for 循环遍历
|
||||||
|
for (Map.Entry<String, List<PolicyManage>> entry : groupedByHouseId.entrySet()) { |
||||||
|
// 得出houseId
|
||||||
|
String houseId = entry.getKey(); |
||||||
|
// 得出policyManageList
|
||||||
|
List<PolicyManage> timeList = entry.getValue(); |
||||||
|
int startHour = 0; |
||||||
|
int startMinute = 0; |
||||||
|
int endHour = 0; |
||||||
|
int endMinute = 0; |
||||||
|
for (PolicyManage policyManage : timeList) { |
||||||
|
if (policyManage.getPointName().equals("开_时")) { |
||||||
|
startHour = collectionParamsManageService.selectCollectionParamsManageById(policyManage.getCpmId()).getCurValue().intValue(); |
||||||
|
} |
||||||
|
if (policyManage.getPointName().equals("开_分")) { |
||||||
|
startMinute = collectionParamsManageService.selectCollectionParamsManageById(policyManage.getCpmId()).getCurValue().intValue(); |
||||||
|
} |
||||||
|
if (policyManage.getPointName().equals("关_时")) { |
||||||
|
endHour = collectionParamsManageService.selectCollectionParamsManageById(policyManage.getCpmId()).getCurValue().intValue(); |
||||||
|
} |
||||||
|
if (policyManage.getPointName().equals("关_分")) { |
||||||
|
endMinute = collectionParamsManageService.selectCollectionParamsManageById(policyManage.getCpmId()).getCurValue().intValue(); |
||||||
|
} |
||||||
|
} |
||||||
|
LocalTime nowTime = LocalTime.now(); |
||||||
|
LocalTime startTime = LocalTime.of(startHour, startMinute); |
||||||
|
LocalTime endTime = LocalTime.of(endHour, endMinute); |
||||||
|
// collectionParamsManages过滤出能够开启风机的点位,paramType=2,isUse=0
|
||||||
|
Set<String> validCpmIds = cpmSpaceRelationList.stream() |
||||||
|
.filter(item -> item.getHouseId().equals(houseId)) |
||||||
|
.map(CpmSpaceRelation::getCpmId) |
||||||
|
.collect(Collectors.toSet()); |
||||||
|
List<CollectionParamsManage> startDataList = startDeviceList |
||||||
|
.stream() |
||||||
|
.filter(item -> validCpmIds.contains(item.getId())) |
||||||
|
.toList(); |
||||||
|
// 判断当前风机是否在开启状态了
|
||||||
|
if (null == startDataList || startDataList.size() == 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
CollectionParamsManage first = startDataList.getFirst(); |
||||||
|
// 判断当前时间是否在开启时间范围内
|
||||||
|
if (DateUtils.isBetween(nowTime, startTime, endTime)) { |
||||||
|
// 判断当前风机是否在开启状态了
|
||||||
|
if (first.getCurValue().intValue() == 1) { |
||||||
|
// 当前风机在开启状态,不需要启动
|
||||||
|
log.info("当前风机在开启状态,不需要启动"); |
||||||
|
} else { |
||||||
|
// 当前风机不在开启状态,需要启动
|
||||||
|
log.info("当前风机不在开启状态,需要启动"); |
||||||
|
List<OrderEntity> changeValues = new ArrayList<>(); |
||||||
|
changeValues.add(new OrderEntity(first.getId(), "1", Integer.parseInt(first.getParamType()), first.getOtherName())); |
||||||
|
sendOrderToMqtt(changeValues); |
||||||
|
} |
||||||
|
; |
||||||
|
} else { |
||||||
|
// 判断当前风机是否在关闭状态了
|
||||||
|
if (first.getCurValue().intValue() == 0) { |
||||||
|
// 当前风机在关闭状态,不需要停止
|
||||||
|
log.info("当前风机在关闭状态,不需要停止"); |
||||||
|
} else { |
||||||
|
// 当前风机不在关闭状态,需要停止
|
||||||
|
log.info("当前风机不在关闭状态,需要停止"); |
||||||
|
List<OrderEntity> changeValues = new ArrayList<>(); |
||||||
|
changeValues.add(new OrderEntity(first.getId(), "0", Integer.parseInt(first.getParamType()), first.getOtherName())); |
||||||
|
sendOrderToMqtt(changeValues); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
package com.mh.quartz.util; |
||||||
|
|
||||||
|
import com.mh.quartz.domain.PIDParams; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @version 1.0 |
||||||
|
* @project EEMCS |
||||||
|
* @description 风柜系统PID调节工具类 |
||||||
|
* @date 2025-05-30 13:47:40 |
||||||
|
*/ |
||||||
|
public class AHUPIDControlUtil { |
||||||
|
|
||||||
|
// PID控制器核心实现
|
||||||
|
private PIDParams params; |
||||||
|
private double setPoint; // 目标温度
|
||||||
|
private double prevError; // 上次误差
|
||||||
|
private double integral; // 积分累积值
|
||||||
|
private double minOutput = 0; // 输出下限(0%)
|
||||||
|
private double maxOutput = 100; // 输出上限(100%)
|
||||||
|
|
||||||
|
public AHUPIDControlUtil(PIDParams params, double setPoint) { |
||||||
|
this.params = params; |
||||||
|
this.setPoint = setPoint; |
||||||
|
} |
||||||
|
|
||||||
|
// 计算水阀开度百分比 (0-100%)
|
||||||
|
public double calculate(double currentTemp, double deltaTime) { |
||||||
|
// 1. 计算当前误差
|
||||||
|
double error = setPoint - currentTemp; |
||||||
|
|
||||||
|
// 2. 比例项计算
|
||||||
|
double proportional = params.getKp() * error; |
||||||
|
|
||||||
|
// 3. 积分项计算(带抗饱和)
|
||||||
|
integral += params.getKi() * error * deltaTime; |
||||||
|
// 积分限幅防止超调
|
||||||
|
integral = Math.max(minOutput, Math.min(maxOutput, integral)); |
||||||
|
|
||||||
|
// 4. 微分项计算(带低通滤波)
|
||||||
|
double derivative = params.getKd() * (error - prevError) / deltaTime; |
||||||
|
prevError = error; // 更新误差记录
|
||||||
|
|
||||||
|
// 5. 综合输出(0-100%)
|
||||||
|
double output = proportional + integral + derivative; |
||||||
|
|
||||||
|
// 6. 输出限幅
|
||||||
|
return Math.max(minOutput, Math.min(maxOutput, output)); |
||||||
|
} |
||||||
|
|
||||||
|
// 更新设定温度
|
||||||
|
public void setSetPoint(double setPoint) { |
||||||
|
this.setPoint = setPoint; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue