From 9740b251d6b339fe54c6e7472bc2b0f3d9dc50e9 Mon Sep 17 00:00:00 2001 From: 25604 Date: Wed, 3 Sep 2025 17:33:31 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=B7=BB=E5=8A=A0=E5=9B=9E=E6=B0=B4?= =?UTF-8?q?=E6=B8=A9=E5=BA=A6=E6=8E=A7=E5=88=B6=E3=80=82=202=E3=80=81?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=98=BF=E4=B8=BD=E5=A1=94=E6=97=B6=E6=8E=A7?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E6=8E=A7=E5=88=B6=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mh/user/constants/DeviceEnum.java | 1 + .../mh/user/entity/DeviceCodeParamEntity.java | 3 + .../com/mh/user/factory/BackTempControl.java | 43 +++++ .../service/impl/ControlSetServiceImpl.java | 6 +- .../impl/DeviceControlServiceImpl.java | 182 +++++++++++++++--- .../strategy/BackTempControlStrategy.java | 103 ++++++++++ .../mh/user/strategy/EleMeterStrategy.java | 80 +++++--- .../mh/user/strategy/TimeControlStrategy.java | 162 ++++++++++++---- .../com/mh/user/utils/ExchangeStringUtil.java | 19 +- 9 files changed, 503 insertions(+), 96 deletions(-) create mode 100644 user-service/src/main/java/com/mh/user/factory/BackTempControl.java create mode 100644 user-service/src/main/java/com/mh/user/strategy/BackTempControlStrategy.java diff --git a/user-service/src/main/java/com/mh/user/constants/DeviceEnum.java b/user-service/src/main/java/com/mh/user/constants/DeviceEnum.java index a37241b..3f1542d 100644 --- a/user-service/src/main/java/com/mh/user/constants/DeviceEnum.java +++ b/user-service/src/main/java/com/mh/user/constants/DeviceEnum.java @@ -16,6 +16,7 @@ public enum DeviceEnum { PressureTransEnum("压变", PressureTrans.getInstance()), HeatPumpEnum("热泵", HeatPump.getInstance()), TempControlEnum("温控", TempControl.getInstance()), + BackTempControlEnum("回水温控", BackTempControl.getInstance()), TimeControlEnum("时控", TimeControl.getInstance()), WaterLevelSwitchEnum("水位开关", WaterLevelSwitch.getInstance()), StatusCheckEnum("状态检测", StatusCheck.getInstance()), diff --git a/user-service/src/main/java/com/mh/user/entity/DeviceCodeParamEntity.java b/user-service/src/main/java/com/mh/user/entity/DeviceCodeParamEntity.java index 0ed4ed7..28d1c85 100644 --- a/user-service/src/main/java/com/mh/user/entity/DeviceCodeParamEntity.java +++ b/user-service/src/main/java/com/mh/user/entity/DeviceCodeParamEntity.java @@ -25,4 +25,7 @@ public class DeviceCodeParamEntity { private String param; + // 寄存器大小 + private int registerSize; + } diff --git a/user-service/src/main/java/com/mh/user/factory/BackTempControl.java b/user-service/src/main/java/com/mh/user/factory/BackTempControl.java new file mode 100644 index 0000000..1cf9228 --- /dev/null +++ b/user-service/src/main/java/com/mh/user/factory/BackTempControl.java @@ -0,0 +1,43 @@ +package com.mh.user.factory; + +import com.mh.user.entity.DeviceCodeParamEntity; +import com.mh.user.strategy.DeviceStrategy; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 回水温度控制器 + * @date 2024-03-18 16:53:35 + */ +public class BackTempControl implements Device { + + private DeviceStrategy strategy; + + private static class SingletonHolder { + private static final BackTempControl INSTANCE = new BackTempControl(); + } + + private BackTempControl() { + // 防止外部直接实例化 + } + + public static BackTempControl getInstance() { + return BackTempControl.SingletonHolder.INSTANCE; + } + + @Override + public void setStrategy(DeviceStrategy strategy) { + this.strategy = strategy; + } + + @Override + public String createOrders(DeviceCodeParamEntity deviceCodeParamEntity) { + return strategy.createOrders(deviceCodeParamEntity); + } + + @Override + public String analysisReceiveData(String dateStr, String deviceType, String registerAddr, String brand, String buildingId, String buildingName, String dataStr) { + return strategy.analysisReceiveData(dateStr, deviceType, registerAddr, brand, buildingId, buildingName, dataStr); + } +} diff --git a/user-service/src/main/java/com/mh/user/service/impl/ControlSetServiceImpl.java b/user-service/src/main/java/com/mh/user/service/impl/ControlSetServiceImpl.java index a7b78d1..305f627 100644 --- a/user-service/src/main/java/com/mh/user/service/impl/ControlSetServiceImpl.java +++ b/user-service/src/main/java/com/mh/user/service/impl/ControlSetServiceImpl.java @@ -31,6 +31,10 @@ public class ControlSetServiceImpl implements ControlSetService { if (StringUtils.isBlank(timeName)) { return null; } - return controlSetMapper.queryControlSet(buildingId,timeName); + ControlSetEntity controlSetEntity = controlSetMapper.queryControlSet(buildingId, timeName + "时控"); + if (null == controlSetEntity) { + controlSetEntity = controlSetMapper.queryControlSet(buildingId, timeName + "温控"); + } + return controlSetEntity; } } diff --git a/user-service/src/main/java/com/mh/user/service/impl/DeviceControlServiceImpl.java b/user-service/src/main/java/com/mh/user/service/impl/DeviceControlServiceImpl.java index 46afeb6..b34af7a 100644 --- a/user-service/src/main/java/com/mh/user/service/impl/DeviceControlServiceImpl.java +++ b/user-service/src/main/java/com/mh/user/service/impl/DeviceControlServiceImpl.java @@ -98,6 +98,7 @@ public class DeviceControlServiceImpl implements DeviceControlService { // 根据设备类型和参数执行相应的操作 switch (deviceType) { case "时控": + case "阿丽塔时控": rtData = handleTimeControl(serialPortModel, deviceCodeParam, controlData, rtData, type, serialPortSingle); log.info("设备类型为时控==>{}", rtData); break; @@ -105,6 +106,10 @@ public class DeviceControlServiceImpl implements DeviceControlService { rtData = handleTempControl(serialPortModel, deviceCodeParam, controlData, rtData, type, serialPortSingle); log.info("设备类型为温控==>{}", rtData); break; + case "回水温控": + rtData = handleBackTempControl(serialPortModel, deviceCodeParam, controlData, rtData, type, serialPortSingle); + log.info("设备类型为回水温控==>{}", rtData); + break; case "水位开关": rtData = handleWaterLevelSwitch(serialPortModel, deviceCodeParam, controlData, rtData, type, serialPortSingle); log.info("设备类型为水位开关==>{}", rtData); @@ -138,10 +143,16 @@ public class DeviceControlServiceImpl implements DeviceControlService { // 开启热泵定时 if ("0028".equals(deviceCodeParam.getRegisterAddr())) { deviceCodeParam.setRegisterAddr("00230001"); - } if ("002A".equals(deviceCodeParam.getRegisterAddr())) { + } + if ("002A".equals(deviceCodeParam.getRegisterAddr())) { deviceCodeParam.setRegisterAddr("00240001"); } rtData = serialPortSingle.serialPortSend(deviceCodeParam); + } else if (!StringUtils.isBlank(brand) && brand.equals("阿丽塔")) { + // 需要继续发送指令 + deviceCodeParam.setFunCode("10"); + deviceCodeParam.setRegisterAddr("010C"); + rtData = serialPortSingle.serialPortSend(deviceCodeParam); } } } @@ -152,6 +163,33 @@ public class DeviceControlServiceImpl implements DeviceControlService { } } + private String handleBackTempControl(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { + switch (deviceCodeParam.getParam()) { + case "controlTemp": + // 目标温度控制值 + deviceCodeParam.setRegisterAddr("0001"); + break; + case "correctionTemp": + // 误差修正值 + deviceCodeParam.setRegisterAddr("000E"); + break; + case "curTemp": + // 当前温度 + deviceCodeParam.setRegisterAddr("0000"); + break; + } + if (Constant.READ.equals(type)) { + deviceCodeParam.setFunCode("03"); //功能码读数据 + rtData = serialPortSingle.serialPortSend(deviceCodeParam);//生成并发送指令 + } else { + // 只能输入整数 + int setValue = new BigDecimal(serialPortModel.getDataValue()).intValue(); + deviceCodeParam.setDataValue(String.valueOf(setValue)); + deviceCodeParam.setFunCode("06"); //功能码写数据 + } + return rtData; + } + private String handleTempControl(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { switch (deviceCodeParam.getParam()) { case "upperLimit": @@ -193,13 +231,13 @@ public class DeviceControlServiceImpl implements DeviceControlService { } if (Constant.READ.equals(type)) { deviceCodeParam.setFunCode("03"); //功能码读数据 - rtData = serialPortSingle.serialPortSend(deviceCodeParam);//生成并发送指令 } else { // 传入值,小数点保留一位,需要乘以10倍 int setValue = new BigDecimal(serialPortModel.getDataValue()).multiply(new BigDecimal(10)).intValue(); deviceCodeParam.setDataValue(String.valueOf(setValue)); deviceCodeParam.setFunCode("10"); //功能码写数据 } + rtData = serialPortSingle.serialPortSend(deviceCodeParam);//生成并发送指令 return rtData; } @@ -211,7 +249,7 @@ public class DeviceControlServiceImpl implements DeviceControlService { private String handleWaterMeter(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { rtData = serialPortSingle.serialPortSend(deviceCodeParam); // 要添加校准值 - Double deviationValue = deviceInstallService.selectDeviceDeviation(deviceCodeParam.getDeviceAddr(),deviceCodeParam.getDeviceType(), deviceCodeParam.getBuildingId()); + Double deviationValue = deviceInstallService.selectDeviceDeviation(deviceCodeParam.getDeviceAddr(), deviceCodeParam.getDeviceType(), deviceCodeParam.getBuildingId()); if (null != deviationValue && !StringUtils.isBlank(rtData) && !"fail".equals(rtData)) { rtData = new BigDecimal(rtData).add(BigDecimal.valueOf(deviationValue)).toString(); } @@ -280,25 +318,76 @@ public class DeviceControlServiceImpl implements DeviceControlService { return rtData; } - private String handleTimeControl(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { + private String handleTimeControl(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, + ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { + if ("阿丽塔".equals(deviceCodeParam.getBrand())) { + rtData = handleAlitaTimeControl(serialPortModel, deviceCodeParam, type, serialPortSingle); + } else { + rtData = handleDefaultTimeControl(serialPortModel, deviceCodeParam, controlData, rtData, type, serialPortSingle); + } + + return rtData; + } + + private String handleAlitaTimeControl(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, String type, SerialPortSingle2 serialPortSingle) { + // 设置值前面两位是场景选择,_隔开,后面是传入实际操作值 + String[] split = serialPortModel.getDataValue().split("_"); + if (split.length < 2) { + return Constant.FAIL; + } + + // 场景 + int scene = Integer.parseInt(split[0]); + // 实际操作值 + deviceCodeParam.setDataValue(split[1]); + serialPortModel.setDataValue(split[1]); + + // 根据读写类型设置功能码 + deviceCodeParam.setFunCode(Constant.READ.equals(type) ? "03" : "06"); + + // 根据参数类型设置寄存器地址 + String registerStr = ""; + switch (deviceCodeParam.getParam()) { + case "switching": + // 开关动作 + registerStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(String.valueOf(64 + (scene - 1) * 6)), 4); + deviceCodeParam.setRegisterSize(1); + break; + case "timeSet": + // 开关时间设置 + registerStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(String.valueOf(65 + (scene - 1) * 6)), 4); + deviceCodeParam.setRegisterSize(2); + break; + case "channelSet": + // 多路设置 + registerStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(String.valueOf(68 + (scene - 1) * 6)), 4); + deviceCodeParam.setRegisterSize(2); + break; + case "weekSet": + // 星期设置 + registerStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(String.valueOf(67 + (scene - 1) * 6)), 4); + deviceCodeParam.setRegisterSize(1); + break; + case "dateCalibrationSet": + // 时间设置 + int registerValue = Constant.READ.equals(type) ? 16 : 264; + deviceCodeParam.setRegisterSize(7); + registerStr = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(String.valueOf(registerValue)), 4); + break; + default: + return Constant.FAIL; + } + deviceCodeParam.setRegisterAddr(registerStr); + return serialPortSingle.serialPortSend(deviceCodeParam);//生成并发送指令 + } + + private String handleDefaultTimeControl(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, + ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { String time = serialPortModel.getDataValue(); + if (Constant.READ.equals(type)) { deviceCodeParam.setFunCode("03"); //功能码读数据 - switch (deviceCodeParam.getParam()) { - case "L1": - deviceCodeParam.setRegisterAddr("0009"); //寄存器地址,L3路,L1(0009),L2(000D) - break; - case "L2": - deviceCodeParam.setRegisterAddr("000D"); - break; - case "L3": - deviceCodeParam.setRegisterAddr("0011"); - break; - case "checkTime": - // 时控校准时间读取 - deviceCodeParam.setRegisterAddr("0000"); - break; - } + setRegisterAddressForRead(deviceCodeParam); rtData = serialPortSingle.serialPortSend(deviceCodeParam);//生成并发送指令 time = rtData; } else { @@ -307,37 +396,72 @@ public class DeviceControlServiceImpl implements DeviceControlService { } deviceCodeParam.setFunCode("10"); //功能码写数据 } - if (time.length() == 16) { + + processTimeData(time, deviceCodeParam, controlData); + controlSetService.saveControlSet(controlData); //保存设置内容 + + return rtData; + } + + private void setRegisterAddressForRead(DeviceCodeParamEntity deviceCodeParam) { + switch (deviceCodeParam.getParam()) { + case "L1": + deviceCodeParam.setRegisterAddr("0009"); //寄存器地址,L3路,L1(0009),L2(000D) + break; + case "L2": + deviceCodeParam.setRegisterAddr("000D"); + break; + case "L3": + deviceCodeParam.setRegisterAddr("0011"); + break; + case "checkTime": + // 时控校准时间读取 + deviceCodeParam.setRegisterAddr("0000"); + break; + } + } + + private void processTimeData(String time, DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData) { + if (time != null && time.length() == 16) { //时段1 HHmmHHmm String statTime1 = time.substring(0, 2) + ":" + time.substring(2, 4); //HH:mm String closeTime1 = time.substring(4, 6) + ":" + time.substring(6, 8); //HH:mm //时段2 String statTime2 = time.substring(8, 10) + ":" + time.substring(10, 12); String closeTime2 = time.substring(12, 14) + ":" + time.substring(14, 16); - if ("L1".equals(deviceCodeParam.getParam())) { + + setTimeDataForControl(deviceCodeParam, controlData, statTime1, closeTime1, statTime2, closeTime2); + } + } + + private void setTimeDataForControl(DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData, + String statTime1, String closeTime1, String statTime2, String closeTime2) { + switch (deviceCodeParam.getParam()) { + case "L1": deviceCodeParam.setRegisterAddr("0009"); //寄存器地址,L3路,L1(0009),L2(000D) controlData.setUseStartTime1(statTime1); controlData.setUseCloseTime1(closeTime1); controlData.setUseStartTime2(statTime2); controlData.setUseCloseTime2(closeTime2); - } else if ("L2".equals(deviceCodeParam.getParam())) { + break; + case "L2": deviceCodeParam.setRegisterAddr("000D"); controlData.setUseStartTime3(statTime1); controlData.setUseCloseTime3(closeTime1); controlData.setUseStartTime4(statTime2); controlData.setUseCloseTime4(closeTime2); - } else { + break; + case "L3": deviceCodeParam.setRegisterAddr("0011"); controlData.setUseStartTime5(statTime1); controlData.setUseCloseTime5(closeTime1); controlData.setUseStartTime6(statTime2); controlData.setUseCloseTime6(closeTime2); - } + break; } - controlSetService.saveControlSet(controlData); //保存设置内容 - return rtData; } + private String handleHotPump(SerialPortModel serialPortModel, DeviceCodeParamEntity deviceCodeParam, ControlSetEntity controlData, String rtData, String type, SerialPortSingle2 serialPortSingle) { //设置热泵实体对象 PumpSetEntity pumpData = new PumpSetEntity(); @@ -353,7 +477,7 @@ public class DeviceControlServiceImpl implements DeviceControlService { deviceCodeParam.setRegisterAddr("000A"); //寄存器地址 } else if ("海尔".equals(deviceCodeParam.getBrand())) { deviceCodeParam.setRegisterAddr(ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex("20003"), 4)); - } else { + } else { deviceCodeParam.setRegisterAddr("0003"); //寄存器地址 } rtData = serialPortSingle.serialPortSend(deviceCodeParam);//生成并发送指令 @@ -471,9 +595,9 @@ public class DeviceControlServiceImpl implements DeviceControlService { } else if ("startOrStop".equals(deviceCodeParam.getParam())) { deviceCodeParam.setFunCode("06"); //功能码读数据 if ("瑞星".equals(deviceCodeParam.getBrand())) { - deviceCodeParam.setRegisterAddr("0001"+ ExchangeStringUtil.addZeroForNum(deviceCodeParam.getDataValue(), 4)); + deviceCodeParam.setRegisterAddr("0001" + ExchangeStringUtil.addZeroForNum(deviceCodeParam.getDataValue(), 4)); } else if ("海尔".equals(deviceCodeParam.getBrand())) { - deviceCodeParam.setRegisterAddr(ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex("20001"), 4)+ ExchangeStringUtil.addZeroForNum(deviceCodeParam.getDataValue(), 4)); + deviceCodeParam.setRegisterAddr(ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex("20001"), 4) + ExchangeStringUtil.addZeroForNum(deviceCodeParam.getDataValue(), 4)); } } return rtData; diff --git a/user-service/src/main/java/com/mh/user/strategy/BackTempControlStrategy.java b/user-service/src/main/java/com/mh/user/strategy/BackTempControlStrategy.java new file mode 100644 index 0000000..01832bb --- /dev/null +++ b/user-service/src/main/java/com/mh/user/strategy/BackTempControlStrategy.java @@ -0,0 +1,103 @@ +package com.mh.user.strategy; + +import com.mh.user.constants.Constant; +import com.mh.user.entity.DeviceCodeParamEntity; +import com.mh.user.entity.NowPublicDataEntity; +import com.mh.user.service.BuildingService; +import com.mh.user.service.NowDataService; +import com.mh.user.service.NowPublicDataService; +import com.mh.user.utils.ExchangeStringUtil; +import com.mh.user.utils.SpringBeanUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; + +/** + * @author LJF + * @version 1.0 + * @project CHWS + * @description 回水温度控制器策略 + * @date 2024-03-18 09:51:17 + */ +@Slf4j +public class BackTempControlStrategy implements DeviceStrategy { + + + // 调用service + ApplicationContext context = SpringBeanUtil.getApplicationContext(); + NowDataService nowDataService = context.getBean(NowDataService.class); + + NowPublicDataService nowPublicDataService = context.getBean(NowPublicDataService.class); + + BuildingService buildingService = context.getBean(BuildingService.class); + + + + private static class SingletonHolder { + private static final BackTempControlStrategy INSTANCE = new BackTempControlStrategy(); + } + + private BackTempControlStrategy() { + // 防止外部直接实例化 + } + + public static BackTempControlStrategy getInstance() { + return BackTempControlStrategy.SingletonHolder.INSTANCE; + } + + @Override + public String createOrders(DeviceCodeParamEntity deviceCodeParamEntity) { + String deviceAddr = deviceCodeParamEntity.getDeviceAddr(); + String registerAddr = deviceCodeParamEntity.getRegisterAddr(); + String str = ""; + if (deviceAddr != null && deviceAddr.length() > 0) { + try { + str = ExchangeStringUtil.decToHex(deviceAddr); + str = ExchangeStringUtil.addZeroForNum(str, 2); //以0补位 + String funCode = ExchangeStringUtil.addZeroForNum(deviceCodeParamEntity.getFunCode(), 2); + if ("03".equals(funCode)) { + registerAddr = ExchangeStringUtil.addZeroForNum(registerAddr, 4); //寄存器地址 + str = str + funCode + registerAddr + "0001"; + } else if ("06".equals(funCode)) { + str = str + funCode + registerAddr + + ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(deviceCodeParamEntity.getDataValue()), 4); + } + String checkWord = ExchangeStringUtil.getStrCRC16(str); //CRC16校验 + str = str + checkWord; + } catch (Exception e) { + log.error("生成回水温控指令出错!" + str, e); + } + } + return str.toUpperCase(); + } + + @Override + public String analysisReceiveData(String dateStr, String deviceType, String registerAddr, String brand, String buildingId, String buildingName, String dataStr) { + String result = Constant.FAIL; + String checkStr = dataStr.substring(0, dataStr.length() - 4); + String checkWord = ExchangeStringUtil.getStrCRC16(checkStr);//生成校验码 + if (!checkWord.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4))) { + log.info("回水温控报文检验失败: " + dataStr); + return result; + } + String addr = ExchangeStringUtil.hexToDec(checkStr.substring(0, 2));//地址 + String data = ""; + if (checkStr.substring(2, 4).equalsIgnoreCase("03")) {// 读 + data = ExchangeStringUtil.hexToDec(checkStr.substring(6, 10)); + Double fdata = Double.parseDouble(data); + nowDataService.saveNowHistoryData2(addr, "回水温控", String.valueOf(fdata), "waterTemp", buildingId); + nowDataService.proWaterTemp(dateStr, buildingId, "");//保存时间点温度 + String avgTemp = nowDataService.selectAve(buildingId); + NowPublicDataEntity publicData = new NowPublicDataEntity(); + publicData.setBuildingId(buildingId); + publicData.setUseWaterTemp(avgTemp); + publicData.setBackWaterTemp(avgTemp); + publicData.setSingleTemp(String.valueOf(fdata));//单箱温度 + nowPublicDataService.saveNowHistoryPublicData(publicData); + log.info("回水温控号:" + addr + ",温度值:" + fdata + ",保存数据库成功!楼栋名称:" + buildingName); + return String.valueOf(fdata); + } else if (checkStr.substring(2, 4).equalsIgnoreCase("06")) {// 写 + result = Constant.SUCCESS; + } + return result; + } +} diff --git a/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java b/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java index 27ff6c3..da86edb 100644 --- a/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java +++ b/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java @@ -44,18 +44,35 @@ public class EleMeterStrategy implements DeviceStrategy { String deviceAddr = deviceCodeParamEntity.getDeviceAddr(); if (deviceAddr != null && deviceAddr.length() > 0) { try { - //0代表前面补充0,12代表长度为12,d代表参数为正数型,基表通讯号 - str = String.format("%012d", Long.parseLong(deviceAddr)); - //转换位置 - str = ExchangeStringUtil.changePosition(str); - //拼接功能码 - str = "68" + str + "680102"; - String strData = "1090"; - //加33操作 - str = str + ExchangeStringUtil.addThree(strData); - //检验和 - String checkSum = ExchangeStringUtil.makeChecksum(str); - str = "FEFEFE" + str + checkSum + "16"; + // 增加一个判断,判断是否是广仪电表modbus协议 + if ("广仪MODBUS协议".equals(deviceCodeParamEntity.getBrand())) { + str = ExchangeStringUtil.decToHex(deviceAddr); + str = ExchangeStringUtil.addZeroForNum(str, 2); //以0补位 +// if(registerAddr.equals("")){ +// str=str+"0300000002"; +// }else if(registerAddr.equals("")){ +// str=str+"0300000002"; +// } + String funCode = ExchangeStringUtil.addZeroForNum(deviceCodeParamEntity.getFunCode(), 2); + if ("04".equals(funCode)) { + str = str + funCode + "00010002"; + } + String checkWord = ExchangeStringUtil.getStrCRC16(str); //CRC16校验 + str = str + checkWord; + } else { + //0代表前面补充0,12代表长度为12,d代表参数为正数型,基表通讯号 + str = String.format("%012d", Long.parseLong(deviceAddr)); + //转换位置 + str = ExchangeStringUtil.changePosition(str); + //拼接功能码 + str = "68" + str + "680102"; + String strData = "1090"; + //加33操作 + str = str + ExchangeStringUtil.addThree(strData); + //检验和 + String checkSum = ExchangeStringUtil.makeChecksum(str); + str = "FEFEFE" + str + checkSum + "16"; + } } catch (Exception e) { log.error("生成采集电表指令错误==>", e); } @@ -67,13 +84,14 @@ public class EleMeterStrategy implements DeviceStrategy { @Override public String analysisReceiveData(String dateStr, String deviceType, String registerAddr, String brand, String buildingId, String buildingName, String dataStr) { String data = ""; + String meterId = ""; if (dataStr.length() == 36 || dataStr.length() == 40 || dataStr.length() == 44 || dataStr.length() == 50) { String checkStr = dataStr.substring(0, dataStr.length() - 4); //减去校验码 String checkNum = ExchangeStringUtil.makeChecksum(checkStr); //生成校验码 //返回的校验码与重新生成的校验码进行校验 if (checkNum.equalsIgnoreCase(dataStr.substring(dataStr.length() - 4, dataStr.length() - 2))) { //表号,12位 - String meterId = checkStr.substring(12, 14) + checkStr.substring(10, 12) + checkStr.substring(8, 10) + meterId = checkStr.substring(12, 14) + checkStr.substring(10, 12) + checkStr.substring(8, 10) + checkStr.substring(6, 8) + checkStr.substring(4, 6) + checkStr.substring(2, 4); meterId = String.format("%012d", Long.parseLong(meterId)); StringBuilder stringBuilder = new StringBuilder(); @@ -93,23 +111,31 @@ public class EleMeterStrategy implements DeviceStrategy { // 0 代表前面补充0,4 代表长度为4,d 代表参数为正数型 data = String.format("%08d", Long.parseLong(data)); data = data.substring(0, 6) + "." + data.substring(6, 8); - log.info("电表表号:" + meterId + ",电表读数:" + data); - try { - DataResultEntity dataResultEntity = new DataResultEntity(); - dataResultEntity.setDeviceAddr(meterId);//通讯编号 - dataResultEntity.setDeviceType("电表"); - dataResultEntity.setBuildingId(buildingId); - dataResultEntity.setCurValue(Double.parseDouble(data)); //当前读数 - Date date = new Date(); - dataResultEntity.setCurDate(date); //当前日期 - dataResultService.saveDataResult(dataResultEntity); - log.info("电表数据保存数据库成功! 楼栋名称:" + buildingName); - } catch (Exception e) { - log.error("电表数据保存数据库失败!楼栋名称:" + buildingName, e); - } + } else { log.info("电表报文检验失败: " + dataStr); } + } else if (dataStr.length() == 18) { + // 080404000000001212 + // modbus协议 + meterId = ExchangeStringUtil.hexToDec(dataStr.substring(0,2)); + // 电表读数 + data = ExchangeStringUtil.hexToDec(dataStr.substring(6,12)); + data = String.format("%.2f", Double.parseDouble(data) / 100); + } + log.info("电表表号:" + meterId + ",电表读数:" + data); + try { + DataResultEntity dataResultEntity = new DataResultEntity(); + dataResultEntity.setDeviceAddr(meterId);//通讯编号 + dataResultEntity.setDeviceType("电表"); + dataResultEntity.setBuildingId(buildingId); + dataResultEntity.setCurValue(Double.parseDouble(data)); //当前读数 + Date date = new Date(); + dataResultEntity.setCurDate(date); //当前日期 + dataResultService.saveDataResult(dataResultEntity); + log.info("电表数据保存数据库成功! 楼栋名称:" + buildingName); + } catch (Exception e) { + log.error("电表数据保存数据库失败!楼栋名称:" + buildingName, e); } if (!StringUtils.isBlank(data)) { data = String.valueOf(Double.valueOf(data)); //00010.76,去除读数前面带0的情况 diff --git a/user-service/src/main/java/com/mh/user/strategy/TimeControlStrategy.java b/user-service/src/main/java/com/mh/user/strategy/TimeControlStrategy.java index eebe28c..292aad1 100644 --- a/user-service/src/main/java/com/mh/user/strategy/TimeControlStrategy.java +++ b/user-service/src/main/java/com/mh/user/strategy/TimeControlStrategy.java @@ -45,38 +45,74 @@ public class TimeControlStrategy implements DeviceStrategy { String brand = deviceCodeParamEntity.getBrand(); String funCode = deviceCodeParamEntity.getFunCode(); String registerAddr = deviceCodeParamEntity.getRegisterAddr(); + String registerSize = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(String.valueOf(deviceCodeParamEntity.getRegisterSize())), 4); String dataValue = deviceCodeParamEntity.getDataValue(); String param = deviceCodeParamEntity.getParam(); String str = ""; - if (deviceAddr != null && deviceAddr.length() > 0) { + // 根据品牌进行判断 + if (deviceAddr != null && !deviceAddr.isEmpty()) { str = ExchangeStringUtil.decToHex(deviceAddr); str = ExchangeStringUtil.addZeroForNum(str, 2); //以0补位 - try { - if (!StringUtils.isBlank(funCode)) { - registerAddr = ExchangeStringUtil.addZeroForNum(registerAddr, 4); //寄存器地址 - funCode = ExchangeStringUtil.addZeroForNum(funCode, 2); // 功能码 - - if (funCode.equals("03")) { //功能码,读 - if (param.equals("checkTime")) { - // 读取时间:0A 03 00 00 00 03 04 B0 - str = str + "03" + registerAddr + "0003"; - } else { - str = str + "03" + registerAddr + "0004"; + if (!StringUtils.isBlank(brand) && "阿丽塔".equals(brand)) { + try { + if (!StringUtils.isBlank(funCode)) { + registerAddr = ExchangeStringUtil.addZeroForNum(registerAddr, 4); //寄存器地址 + funCode = ExchangeStringUtil.addZeroForNum(funCode, 2); // 功能码 + + if (funCode.equals("03")) { //功能码,读 + str = str + "03" + registerAddr + registerSize; + } else if (funCode.equals("10")) {//写 + // 判断寄存器地址 + if ("0108".equals(registerAddr)) { + // 1F1001080003060014001200225B97 + str = str + funCode + registerAddr + "000306" + + "00" + dataValue.substring(2, 4) // 年 + + "00" + dataValue.substring(4,6) // 月 + + "00" + dataValue.substring(6,8); // 日 + } else if ("010c".equals(registerAddr)) { + // 1F10010C0004080015004300300002BA23 + str = str + funCode + registerAddr + "000408" + + "00" + dataValue.substring(8, 10) // 时 + + "00" + dataValue.substring(10,12) // 分 + + "00" + dataValue.substring(12,14) // 秒 + + "0000"; // 毫秒 + } + } - } else if (funCode.equals("10")) {//写 - if (!dataValue.equals("") && !param.equals("checkTime")) { - str = str + "10" + registerAddr + "000408" + dataValue; - } else { - // 校验时间:0A 10 00 00 00 03 06 00 24 01 10 08 59 48 CF - // 0A 10 00 00 00 03 06 00 24 01 10 09 40 8B 95 - str = str + "10" + registerAddr + "00030600" + dataValue.substring(2); + } + String checkWord = ExchangeStringUtil.getStrCRC16(str); //CRC16校验 + str = str + checkWord; + } catch (Exception e) { + log.error("生成阿丽塔时控指令出错!" + str, e); + } + } else { + try { + if (!StringUtils.isBlank(funCode)) { + registerAddr = ExchangeStringUtil.addZeroForNum(registerAddr, 4); //寄存器地址 + funCode = ExchangeStringUtil.addZeroForNum(funCode, 2); // 功能码 + + if (funCode.equals("03")) { //功能码,读 + if (param.equals("checkTime")) { + // 读取时间:0A 03 00 00 00 03 04 B0 + str = str + "03" + registerAddr + "0003"; + } else { + str = str + "03" + registerAddr + "0004"; + } + } else if (funCode.equals("10")) {//写 + if (!dataValue.equals("") && !param.equals("checkTime")) { + str = str + "10" + registerAddr + "000408" + dataValue; + } else { + // 校验时间:0A 10 00 00 00 03 06 00 24 01 10 08 59 48 CF + // 0A 10 00 00 00 03 06 00 24 01 10 09 40 8B 95 + str = str + "10" + registerAddr + "00030600" + dataValue.substring(2); + } } } + String checkWord = ExchangeStringUtil.getStrCRC16(str); //CRC16校验 + str = str + checkWord; + } catch (Exception e) { + log.error("生成时控指令出错!" + str, e); } - String checkWord = ExchangeStringUtil.getStrCRC16(str); //CRC16校验 - str = str + checkWord; - } catch (Exception e) { - log.error("生成时控指令出错!" + str, e); } } return str.toUpperCase(); @@ -97,24 +133,78 @@ public class TimeControlStrategy implements DeviceStrategy { String data = ""; if (checkStr.substring(2, 4).equalsIgnoreCase("03")) {// 读 int rec = dataStr.length(); - - if (rec == 26) { //读时间设置值 - data = checkStr.substring(6, rec - 4); - String curTimeBegin1 = data.substring(0, 2) + ":" + data.substring(2, 4); - String curTimeEnd1 = data.substring(4, 6) + ":" + data.substring(6, 8); - String curTimeBegin2 = data.substring(8, 10) + ":" + data.substring(10, 12); - String curTimeEnd2 = data.substring(12, 14) + ":" + data.substring(14, 16); - - } else if (rec == 22) { //读校对时间 - data = checkStr.substring(8, rec - 4); - String strDate = "20" + data.substring(0, 2) + "-" + data.substring(2, 4) + "-" + data.substring(4, 6); //拼接日期 - String strTime = data.substring(6, 8) + ":" + data.substring(8, 10); //拼接时间 + if (!StringUtils.isBlank(brand) && "阿丽塔".equals(brand)) { + if (rec == 14 && isExactlyDivisible("0040", registerAddr)) { + // 开关设置 + // 16进制转2进制 10011 + data = ExchangeStringUtil.hexString2binaryString(checkStr.substring(8, rec - 4)); + data = ExchangeStringUtil.addZeroForNum(data, 8); + // 再截取前四位转换成10进制 + data = ExchangeStringUtil.hexToDec(data.substring(0, 4)); + } else if (rec == 18 && isExactlyDivisible("0041", registerAddr)) { + // 时间设置 + // 直接截取时,分 + data = checkStr.substring(8,10)+checkStr.substring(12, 14); + } else if (rec == 14 && isExactlyDivisible("0043", registerAddr)) { + // 星期掩码 + // 截取时间 + data = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.hexString2binaryString(checkStr.substring(8, 10)), 8); + data = new StringBuilder(data).reverse().toString(); + } else if (rec == 18 && isExactlyDivisible("0044", registerAddr)) { + // 定时控制继电器路数 + // 截取1-8路,低8位 从高到低表示1-8路 1是执行动作。 0是保持 + String multiple1 = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.hexString2binaryString(checkStr.substring(8, 10)), 8); + // 截取9-16路,低8位 从高到低表示9-16路 1是执行动作。 0是保持 + String multiple2 = ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.hexString2binaryString(checkStr.substring(12, 14)), 8); + data = multiple1 + multiple2; + } else if (rec == 38 && isExactlyDivisible("0010", registerAddr)) { + // 设备当前时间 + // 直接截取年、月、日、小时、分、秒 + data = checkStr.substring(8, 10) + + checkStr.substring(12, 14) + + checkStr.substring(16, 18) + + checkStr.substring(22, 24) + + checkStr.substring(26, 28) + + checkStr.substring(30, 32); + } + } else { + if (rec == 26) { //读时间设置值 + data = checkStr.substring(6, rec - 4); + String curTimeBegin1 = data.substring(0, 2) + ":" + data.substring(2, 4); + String curTimeEnd1 = data.substring(4, 6) + ":" + data.substring(6, 8); + String curTimeBegin2 = data.substring(8, 10) + ":" + data.substring(10, 12); + String curTimeEnd2 = data.substring(12, 14) + ":" + data.substring(14, 16); + } else if (rec == 22) { //读校对时间 +// {"code":200,"msg":"2509031508","data":"2509031508","count":0} + data = checkStr.substring(8, rec - 4); + String strDate = "20" + data.substring(0, 2) + "-" + data.substring(2, 4) + "-" + data.substring(4, 6); //拼接日期 + String strTime = data.substring(6, 8) + ":" + data.substring(8, 10); //拼接时间 + } } result = data; - } else if (checkStr.substring(2, 4).equalsIgnoreCase("05") || checkStr.substring(2, 4).equalsIgnoreCase("10")) { + } else if (checkStr.substring(2, 4).equalsIgnoreCase("05") + || checkStr.substring(2, 4).equalsIgnoreCase("10") + || checkStr.substring(2,4).equalsIgnoreCase("06") + ) { log.info("时间: " + dateStr + ",时控ID: " + addr + ",操作成功! "); return Constant.SUCCESS; } return result; } + + // 判断是否可以整除 + private static boolean isExactlyDivisible(String baseAddr, String registerAddr) { + // 16进制转十进制 + int baseAddrInt = ExchangeStringUtil.hexToDecimal(baseAddr); + int registerAddrInt = ExchangeStringUtil.hexToDecimal(registerAddr); + + // 判断地址差值是否能被6整除 + if (registerAddrInt >= baseAddrInt) { + int difference = registerAddrInt - baseAddrInt; + return difference % 6 == 0; + } + + return false; + } + } diff --git a/user-service/src/main/java/com/mh/user/utils/ExchangeStringUtil.java b/user-service/src/main/java/com/mh/user/utils/ExchangeStringUtil.java index d249c32..40d9479 100644 --- a/user-service/src/main/java/com/mh/user/utils/ExchangeStringUtil.java +++ b/user-service/src/main/java/com/mh/user/utils/ExchangeStringUtil.java @@ -28,6 +28,10 @@ public class ExchangeStringUtil { System.out.println(s); System.out.println(hexToLong("0000006C")); System.out.println(longToHex(317751L)); + String s1 = hexString2binaryString("0013"); + String s2 = ExchangeStringUtil.addZeroForNum(s1, 8); + System.out.println("16进制转2进制"+s2); + System.out.println("数据反转16进制转2进制"+new StringBuilder(s2).reverse().toString()); } /** @@ -305,16 +309,25 @@ public class ExchangeStringUtil { * @return */ public static String decToHex(String dec) { - BigInteger data = new BigInteger(dec,10); - String result = data.toString(16); + BigInteger data = new BigInteger(dec, 10); + String result; + if (data.signum() < 0) { + // 处理负数,使用补码表示 + // 假设使用32位表示 + BigInteger mask = BigInteger.ONE.shiftLeft(16).subtract(BigInteger.ONE); + result = data.and(mask).toString(16); + } else { + result = data.toString(16); + } if (result.length() < 2) { result = "0" + result; } - if ((result.length() % 2)!=0) { + if ((result.length() % 2) != 0) { result = "0" + result; } return result.toUpperCase(); } + /** * 十六进制数据转换为十进制字符串数 *