package com.mh.user.strategy; import com.mh.common.utils.StringUtils; import com.mh.user.constants.Constant; import com.mh.user.entity.DeviceCodeParamEntity; 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 TimeControlStrategy implements DeviceStrategy { // 调用service ApplicationContext context = SpringBeanUtil.getApplicationContext(); NowDataService nowDataService = context.getBean(NowDataService.class); NowPublicDataService nowPublicDataService = context.getBean(NowPublicDataService.class); private static class SingletonHolder { private static final TimeControlStrategy INSTANCE = new TimeControlStrategy(); } private TimeControlStrategy() { // 防止外部直接实例化 } public static TimeControlStrategy getInstance() { return TimeControlStrategy.SingletonHolder.INSTANCE; } @Override public String createOrders(DeviceCodeParamEntity deviceCodeParamEntity) { String deviceAddr = deviceCodeParamEntity.getDeviceAddr(); 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.isEmpty()) { str = ExchangeStringUtil.decToHex(deviceAddr); str = ExchangeStringUtil.addZeroForNum(str, 2); //以0补位 if (!StringUtils.isBlank(brand) && Constant.BRAND_ALITA.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")) {//写 // 判断寄存器地址 registerAddr = registerAddr.toUpperCase(); 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) // 分 + "0000" // 秒 + "0002"; // 只写 写2设置日期,写1读取日期 } else if ("0041".equals(registerAddr)) { str = str + funCode + registerAddr + "000204" + "00" + dataValue.substring(0, 2) // 分 + "00" + dataValue.substring(2, 4); // 秒 } else if ("0044".equals(registerAddr)) { str = str + funCode + registerAddr + "000204" + ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.parseByte2HexStr(dataValue.substring(0, 8)), 4) // 1-8路 + ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.parseByte2HexStr(dataValue.substring(8, 16)), 4); // 9-16路 } } else if (funCode.equals("06")) { str = str + funCode + registerAddr + ExchangeStringUtil.addZeroForNum(ExchangeStringUtil.decToHex(dataValue), 4); } } 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); } } } 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))) { return result; } log.info("时控报文检验成功: " + dataStr); //地址 String addr = ExchangeStringUtil.hexToDec(checkStr.substring(0, 2)); log.info("时控号: " + addr); String data = ""; if (checkStr.substring(2, 4).equalsIgnoreCase("03")) {// 读 int rec = dataStr.length(); if (!StringUtils.isBlank(brand) && Constant.BRAND_ALITA.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") || 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; } }