Browse Source

1、netty控制热泵设置;

2、大屏数据整合;
3、风柜系统策略管理优化;
dev_mz
25604 2 days ago
parent
commit
6973b889c8
  1. 20
      mh-common/src/main/java/com/mh/common/utils/ModbusUtils.java
  2. 2
      mh-common/src/main/java/com/mh/common/utils/NettyTools.java
  3. 13
      mh-common/src/main/java/com/mh/common/utils/SendOrderUtils.java
  4. 2
      mh-framework/src/main/java/com/mh/framework/dealdata/DataProcessService.java
  5. 4
      mh-framework/src/main/java/com/mh/framework/dealdata/impl/DataProcessServiceImpl.java
  6. 77
      mh-framework/src/main/java/com/mh/framework/netty/EchoServerHandler.java
  7. 12
      mh-framework/src/main/java/com/mh/framework/netty/NettyServiceImpl.java
  8. 7
      mh-quartz/src/main/java/com/mh/quartz/task/DealDataTask.java
  9. 17
      mh-system/src/main/java/com/mh/system/mapper/device/DataProcessMapper.java
  10. 2
      mh-system/src/main/java/com/mh/system/mapper/policy/PolicyManageMapper.java
  11. 50
      mh-system/src/main/java/com/mh/system/service/overview/impl/BigScreenServiceImpl.java
  12. 2
      mh-system/src/main/java/com/mh/system/service/policy/impl/PolicyManageServiceImpl.java

20
mh-common/src/main/java/com/mh/common/utils/ModbusUtils.java

@ -3,6 +3,7 @@ package com.mh.common.utils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
/**
* @author LJF
@ -11,7 +12,24 @@ import io.netty.channel.ChannelHandlerContext;
* @description Modbus协议工具类
* @date 2025-06-06 14:40:24
*/
@Slf4j
public class ModbusUtils {
public static String createReadOrder(String mtCode, String funCode, String registerAddr, String registerNum) {
// 开始创建指令
// 拼接指令
String sendOrderStr = ExchangeStringUtil.addZeroForNum(mtCode, 2)
+ ExchangeStringUtil.addZeroForNum(funCode, 2)
+ ExchangeStringUtil.addZeroForNum(registerAddr, 4)
+ ExchangeStringUtil.addZeroForNum(registerNum, 4);
byte[] strOrder = ExchangeStringUtil.hexStrToBinaryStr(sendOrderStr);
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
sendOrderStr = sendOrderStr + checkWord;
return sendOrderStr;
}
public static String createControlCode(String mtCode, Integer type, String registerAddr, String param) {
String orderStr;
mtCode = ExchangeStringUtil.addZeroForNum(mtCode, 2);
@ -22,6 +40,8 @@ public class ModbusUtils {
int checkNum = CRC16.CRC16_MODBUS(strOrder);
String checkWord = ExchangeStringUtil.decToHex(String.valueOf(checkNum));
checkWord = checkWord.substring(2, 4) + checkWord.substring(0, 2);
// 发送的指令
log.info("发送指令:{}", orderStr+checkWord);
return orderStr + checkWord;
}

2
mh-common/src/main/java/com/mh/common/utils/NettyTools.java

@ -67,7 +67,7 @@ public class NettyTools {
public static void setReceiveMsg(String key, String msg) {
if(responseMsgCache.getIfPresent(key) != null){
responseMsgCache.getIfPresent(key).add(msg);
Objects.requireNonNull(responseMsgCache.getIfPresent(key)).add(msg);
return;
}

13
mh-common/src/main/java/com/mh/common/utils/SendOrderUtils.java

@ -37,7 +37,7 @@ public class SendOrderUtils {
ctx.channel().writeAndFlush(buffer);
log.info("sends :" + sendOrderStr + ",num:" + num + ",records:" + size);
try {
Thread.sleep(1000);
Thread.sleep(500);
} catch (InterruptedException e) {
log.error("线程休眠异常", e);
}
@ -50,4 +50,15 @@ public class SendOrderUtils {
buffer.writeBytes(ExchangeStringUtil.hexStrToBinaryStr(sendStr));//对接需要16进制
return buffer;
}
public static void sendOrderToDTU(ChannelHandlerContext ctx, String sendStr) {
ByteBuf buffer = getByteBuf(ctx, sendStr);
// 发送数据
ctx.channel().writeAndFlush(buffer);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.error("线程休眠异常", e);
}
}
}

2
mh-framework/src/main/java/com/mh/framework/dealdata/DataProcessService.java

@ -37,7 +37,7 @@ public interface DataProcessService {
* @param deviceNum
* @return
*/
String queryInitValue(String deviceNum, String mtCode);
String queryInitValue(String deviceNum, String mtCode, String registerAddr);
/**
* 查询上一次采集数据时间等参数

4
mh-framework/src/main/java/com/mh/framework/dealdata/impl/DataProcessServiceImpl.java

@ -234,11 +234,11 @@ public class DataProcessServiceImpl implements DataProcessService {
}
@Override
public String queryInitValue(String deviceNum, String mtCode) {
public String queryInitValue(String deviceNum, String mtCode, String registerAddr) {
if (StringUtils.isEmpty(mtCode)) {
return dataProcessMapper.queryInitValue1(deviceNum);
} else {
return dataProcessMapper.queryInitValue(deviceNum, mtCode);
return dataProcessMapper.queryInitValue(deviceNum, mtCode, registerAddr);
}
}

77
mh-framework/src/main/java/com/mh/framework/netty/EchoServerHandler.java

@ -30,6 +30,7 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@ -143,7 +144,7 @@ public class EchoServerHandler extends ChannelInboundHandlerAdapter {
deviceCodeParamList = arrayCache.toList(CollectionParamsManage.class);
}
size = deviceCodeParamList.size();
log.info("deviceCodeParam size ===> {}", size);
// log.info("deviceCodeParam size ===> {}", size);
// 清空receiveStr
receiveStr = "";
num = 0;
@ -160,30 +161,79 @@ public class EchoServerHandler extends ChannelInboundHandlerAdapter {
log.info("gateway not find deviceCodeParam!");
}
} else if (receiveStr.length() == 18) {
// 水电表、热泵设置返回数据解析
// 水电表返回数据解析
idleCount = 1;
log.info("水电表、热泵设置接收==>{},长度:{}", receiveStr, receiveStr.length());
nextSendOrder(ctx);
} else if (receiveStr.length() == 12 || receiveStr.length() == 14) {
// 热泵返回数据解析
idleCount = 1;
log.info("热泵读取接收===>{},长度:{}", receiveStr, receiveStr.length());
nextSendOrder(ctx);
} else if (receiveStr.length() == 16) {
// 热泵设置指令返回
// 判断是否有指令发送
if (redisCache.hasKey("order_send") && redisCache.getCacheObject("order_send").equals(receiveStr)) {
NettyTools.setReceiveMsg("order_wait", receiveStr);
log.info("热泵读取接收===>{},长度:{},是否存在order_send_read: {}", receiveStr, receiveStr.length(), redisCache.hasKey("order_send_read"));
if (redisCache.hasKey("order_send_read")) {
log.error("order_send_read存在,接收到指令是{}", receiveStr);
CollectionParamsManage collectionParamsManage = new CollectionParamsManage();
collectionParamsManage.setDataType(2);
collectionParamsManage.setParamType("14");
Object orderSend = redisCache.getCacheObject("order_send_read");
String orderSendStr = String.valueOf(orderSend);
String substring = orderSendStr.substring(0, 2);
collectionParamsManage.setOtherName(ExchangeStringUtil.hexToDec(substring) + "号热泵温度设置");
analysisReceiveData(receiveStr, collectionParamsManage);
redisCache.deleteObject("order_send_read");
} else {
nextSendOrder(ctx);
}
} else if (receiveStr.length() == 16) {
idleCount = 1;
nextSendOrder(ctx);
} else if (receiveStr.length() > 50 && receiveStr.length() < 100) {
// 热泵设置指令返回
controlOrder(ctx);
} else if (receiveStr.length() > 20 && receiveStr.length() < 100) {
idleCount = 1;
// 清空receiveStr
nextSendOrder(ctx);
controlOrder(ctx);
}
ctx.flush();
}
private void controlOrder(ChannelHandlerContext ctx) {
// 热泵设置指令返回
if (redisCache.hasKey("order_send")) {
// 判断是否有指令发送
Object orderSend = redisCache.getCacheObject("order_send");
String orderSendStr = String.valueOf(orderSend);
// // 发送读取热泵设置温度
// String controlCode = ModbusUtils.createReadOrder(orderSendStr.substring(0, 2),
// "03",
// "0003",
// "1");
// SendOrderUtils.sendOrderToDTU(ctx, controlCode);
if (receiveStr.contains(orderSendStr)) {
String readOrder = ModbusUtils.createReadOrder(orderSendStr.substring(0, 2),
"03",
"0003",
"1");
// 初始化发送指令
// NettyTools.initReceiveMsg("order_wait_read");
// 发送读取指令
redisCache.setCacheObject("order_send_read", readOrder, 10, TimeUnit.SECONDS);
ctx.writeAndFlush(ModbusUtils.createByteBuf(readOrder));
// 发送读取指令
log.error("热泵设置读取指令发送:{},order_send_read键值:{}", readOrder, redisCache.hasKey("order_send_read"));
log.error("热泵设置指令返回:{}", receiveStr);
NettyTools.setReceiveMsg("order_wait", receiveStr);
redisCache.deleteObject("order_send");
receiveStr = "";
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
private void dealSession(ChannelHandlerContext ctx) {
// 获取表号
String deviceCode =receiveStr;
@ -227,10 +277,15 @@ public class EchoServerHandler extends ChannelInboundHandlerAdapter {
private void nextSendOrder(ChannelHandlerContext ctx) throws InterruptedException {
// 发送指令响应不用解析
if (receiveStr.length() != 16) {
if (receiveStr.length() != 16 && receiveStr.length() < 20) {
// 解析采集的报文,并保存到数据库
analysisReceiveData(receiveStr, deviceCodeParamList.get(num));
}
// 判断是否有远程指令发送,如果有先不采集
if (redisCache.hasKey("order_send")) {
log.error("有远程设置指令发送,不进行采集");
return;
}
// 清空receiveStr
receiveStr = "";
// 判断发送的下标,如果不等于指令数组大小

12
mh-framework/src/main/java/com/mh/framework/netty/NettyServiceImpl.java

@ -95,12 +95,20 @@ public class NettyServiceImpl implements INettyService {
NettyTools.initReceiveMsg("order_wait");
// 设置缓存,方便在netty中判断发送的指令
redisCache.setCacheObject("order_send", controlCode, 10, TimeUnit.SECONDS);
// 发送指令
Thread.sleep(500);
// 发送控制指令
serverSession.getChannel().writeAndFlush(ModbusUtils.createByteBuf(controlCode));
// 等待指令
if (NettyTools.waitReceiveMsg("order_wait")) {
log.error("发送指令成功,心跳包:{}", gatewayManage.getHeartBeat());
// 初始化发送指令
Thread.sleep(3000);
return true;
// if (NettyTools.waitReceiveMsg("order_wait_read")) {
// return true;
// } else {
// log.error("读取指令异常,心跳包:{}", gatewayManage.getHeartBeat());
// return false;
// }
} else {
log.error("发送指令异常,心跳包:{}", gatewayManage.getHeartBeat());
return false;

7
mh-quartz/src/main/java/com/mh/quartz/task/DealDataTask.java

@ -115,7 +115,7 @@ public class DealDataTask {
int ratio = entity.getMtRatio();
if (ObjectUtils.isEmpty(lastData) || ObjectUtils.isEmpty(lastData.getLastValue())) {
//从device_manage取出初始值
String initValue = dataProcessService.queryInitValue(entity.getMtNum(), entity.getMtCode());
String initValue = dataProcessService.queryInitValue(entity.getMtNum(), entity.getMtCode(), entity.getRegisterAddr());
if (StringUtils.isEmpty(initValue)) {
initValue = "0";
}
@ -207,6 +207,7 @@ public class DealDataTask {
}
temp.setDeviceType(deviceType);
temp.setRatio(ratio);
temp.setRegisterAddr(dataI.getRegisterAddr());
dataMinList.add(temp);
i++;
j++;
@ -324,7 +325,7 @@ public class DealDataTask {
DeviceReport hourEntity = dataProcessService.queryLastValue(key, tableType);
if (ObjectUtils.isEmpty(hourEntity)) {
//查询设备信息初始值
lastValue = dataProcessService.queryInitValue(key, null);
lastValue = dataProcessService.queryInitValue(key, null, null);
if (StringUtils.isEmpty(lastValue)) {
lastValue = "0";
}
@ -505,7 +506,7 @@ public class DealDataTask {
DeviceReport entity = deviceList.get(i);
DeviceReport lastEntity = dataProcessService.queryLastValue(deviceNum, "month");
if (ObjectUtils.isEmpty(lastEntity)) {
lastValue = dataProcessService.queryInitValue(deviceNum, null);
lastValue = dataProcessService.queryInitValue(deviceNum, null, null);
lastTime = entity.getCurTime();
} else {
lastValue = lastEntity.getLastValue();

17
mh-system/src/main/java/com/mh/system/mapper/device/DataProcessMapper.java

@ -75,7 +75,7 @@ public interface DataProcessMapper {
*/
@Select("<script>" +
"<foreach collection='batchList' item='item' index='index' separator=';'>" +
"INSERT INTO ${tableName} (device_num, device_code, device_type, last_value, last_time, cur_value, cur_time, used_value, calc_value, grade, ratio) " +
"INSERT INTO ${tableName} (device_num, device_code, device_type, last_value, last_time, cur_value, cur_time, used_value, calc_value, grade, ratio, register_addr) " +
"SELECT " +
" #{item.deviceNum}, " +
" #{item.deviceCode}, " +
@ -87,7 +87,8 @@ public interface DataProcessMapper {
" cast(#{item.usedValue} as decimal(24,2)), " +
" cast(#{item.calcValue} as numeric(24,2)), " +
" #{item.grade}, " +
" #{item.ratio} " +
" #{item.ratio}," +
" #{item.registerAddr} " +
"WHERE NOT EXISTS (" +
" SELECT 1 FROM ${tableName} WHERE device_num = #{item.deviceNum} AND cur_time = #{item.curTime} " +
")" +
@ -170,9 +171,15 @@ public interface DataProcessMapper {
* @param deviceNum
* @return
*/
@Select("select mt_init_value from collection_params_manage where mt_num = #{deviceNum} " +
" and mt_code = #{mtCode} and is_use = '0' limit 1")
String queryInitValue(@Param("deviceNum") String deviceNum, @Param("mtCode") String mtCode);
@Select("<script>" +
"select mt_init_value from collection_params_manage where mt_num = #{deviceNum} " +
" and mt_code = #{mtCode} and is_use = '0' " +
"<if test='registerAddr != null and registerAddr != \"\"'>" +
" and register_addr = #{registerAddr} " +
"</if>" +
" limit 1" +
"</script>")
String queryInitValue(@Param("deviceNum") String deviceNum, @Param("mtCode") String mtCode, @Param("registerAddr") String registerAddr);
/**
* 查询初始数据

2
mh-system/src/main/java/com/mh/system/mapper/policy/PolicyManageMapper.java

@ -32,7 +32,7 @@ public interface PolicyManageMapper extends BaseMapper<PolicyManage> {
" where pm.system_type = #{systemType} " +
" and pm.fun_policy_type = #{funPolicyType} " +
" and house_id = #{houseId} " +
" order by pm.policy_type, pm.order_num ")
" order by pm.policy_type::int, pm.order_num ")
List<PolicyManage> selectPolicyListByParams(@Param("systemType") String systemType,
@Param("funPolicyType") String funPolicyType,
@Param("houseId") String houseId);

50
mh-system/src/main/java/com/mh/system/service/overview/impl/BigScreenServiceImpl.java

@ -50,7 +50,7 @@ public class BigScreenServiceImpl implements IBigScreenService {
BigScreenOverviewAndBasicDTO bigScreenOverviewAndBasicDTO = new BigScreenOverviewAndBasicDTO();
for (String paramType : paramTypes) {
int mtIsSum = queryCollectionParams(paramType, 40);
BigDecimal useValue = bigScreenMapper.selectOverviewData(tableName, paramType, vo.getStartTime(), vo.getEndTime(), mtIsSum, 40, null);
BigDecimal useValue = bigScreenMapper.selectOverviewData(tableName, paramType, vo.getStartTime(), vo.getEndTime(), mtIsSum, 40, vo.getSystemType());
switch (paramType) {
case "16":
bigScreenOverviewAndBasicDTO.setTotalEle(useValue);
@ -70,13 +70,40 @@ public class BigScreenServiceImpl implements IBigScreenService {
}
// 换算标准煤
// 用电转换,公式:标准煤量(kgce)= 用电量(kWh)×0.1229
bigScreenOverviewAndBasicDTO.setEleStandardCoal(bigScreenOverviewAndBasicDTO.getTotalEle().multiply(new BigDecimal("0.1229")));
// 用冷转换,公式:标准煤量(kgce)= 3.6*用冷量(kW)➗29.3076
bigScreenOverviewAndBasicDTO.setColdStandardCoal(bigScreenOverviewAndBasicDTO.getTotalCold().multiply(new BigDecimal("3.6")).divide(new BigDecimal("29.3076")));
// 用水转换,公式:标准煤量(kgce)=用水量(吨)×0.0857
bigScreenOverviewAndBasicDTO.setWaterStandardCoal(bigScreenOverviewAndBasicDTO.getTotalWater().multiply(new BigDecimal("0.0857")));
// 用气转换,公式:标准煤量(kgce)=用蒸汽量(吨)×0.0948
bigScreenOverviewAndBasicDTO.setGasStandardCoal(bigScreenOverviewAndBasicDTO.getTotalGas().multiply(new BigDecimal("0.0948")));
if (bigScreenOverviewAndBasicDTO.getTotalEle() != null) {
bigScreenOverviewAndBasicDTO.setEleStandardCoal(
bigScreenOverviewAndBasicDTO.getTotalEle()
.multiply(new BigDecimal("0.1229"))
.setScale(2, BigDecimal.ROUND_HALF_UP)
);
}
// 用冷转换,公式:标准煤量(kgce)= 3.6 × 用冷量(kW) ÷ 29.3076
if (bigScreenOverviewAndBasicDTO.getTotalCold() != null) {
bigScreenOverviewAndBasicDTO.setColdStandardCoal(
bigScreenOverviewAndBasicDTO.getTotalCold()
.multiply(new BigDecimal("3.6"))
.divide(new BigDecimal("29.3076"), 2, BigDecimal.ROUND_HALF_UP)
);
}
// 用水转换,公式:标准煤量(kgce)= 用水量(吨) × 0.0857
if (bigScreenOverviewAndBasicDTO.getTotalWater() != null) {
bigScreenOverviewAndBasicDTO.setWaterStandardCoal(
bigScreenOverviewAndBasicDTO.getTotalWater()
.multiply(new BigDecimal("0.0857"))
.setScale(2, BigDecimal.ROUND_HALF_UP)
);
}
// 用气转换,公式:标准煤量(kgce)= 用蒸汽量(吨) × 0.0948
if (bigScreenOverviewAndBasicDTO.getTotalGas() != null) {
bigScreenOverviewAndBasicDTO.setGasStandardCoal(
bigScreenOverviewAndBasicDTO.getTotalGas()
.multiply(new BigDecimal("0.0948"))
.setScale(2, BigDecimal.ROUND_HALF_UP)
);
}
// 获取建筑面积
List<SysParams> sysParams = sysParamsMapper.selectSysParamsList();
if (!sysParams.isEmpty()) {
@ -182,7 +209,8 @@ public class BigScreenServiceImpl implements IBigScreenService {
dateFormat = "yyyy-MM";
break;
case "month":
tableName = "data_day";
tableName = "data_day" + vo.getStartTime().substring(0, 4);
;
dateFormat = "yyyy-MM-dd";
break;
case "day":
@ -206,9 +234,9 @@ public class BigScreenServiceImpl implements IBigScreenService {
// 根据时间分组,求和取总和,再根据时间升序排序
// 使用LinkedHashMap保持时间顺序
LinkedHashMap<String, Double> eleMap = dataList.stream()
.sorted(Comparator.comparing(val->DateUtils.dateToString(val.getCurTime(), finalDateFormat))) // 按时间字段排序
.sorted(Comparator.comparing(val -> DateUtils.dateToString(val.getCurTime(), finalDateFormat))) // 按时间字段排序
.collect(Collectors.groupingBy(
val->DateUtils.dateToString(val.getCurTime(), finalDateFormat),
val -> DateUtils.dateToString(val.getCurTime(), finalDateFormat),
LinkedHashMap::new,
Collectors.summingDouble(value ->
value.getCalcValue().doubleValue())

2
mh-system/src/main/java/com/mh/system/service/policy/impl/PolicyManageServiceImpl.java

@ -65,7 +65,7 @@ public class PolicyManageServiceImpl implements IPolicyManageService {
List<PolicyManage> policyManages = policyManageMapper.selectPolicyListByParams(systemType, funPolicyType, houseId);
Map<String, List<PolicyManage>> listMap = policyManages.stream()
// 先排序(例如按 policyType)
.sorted(Comparator.comparing(PolicyManage::getPolicyType))
// .sorted(Comparator.comparing(PolicyManage::getPolicyType))
// 处理每个PolicyManage对象的curValue字段
.peek(policy -> {
policy.setCurValue(BigDecimal.valueOf(policy.getCurValue().intValue())); // 除以1000并保留整数

Loading…
Cancel
Save