|
|
@@ -0,0 +1,199 @@
|
|
|
+package com.zksy.electricity.utils;
|
|
|
+
|
|
|
+import com.zksy.electricity.domain.MessageParseResult;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import java.text.DecimalFormat;
|
|
|
+import java.util.Date;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+public class DataParser {
|
|
|
+ private static Logger logger = LoggerFactory.getLogger(DataParser.class);
|
|
|
+ public static MessageParseResult parseMessage(String msgString) {
|
|
|
+ MessageParseResult result = new MessageParseResult();
|
|
|
+ try {
|
|
|
+ String processedResult = msgString.replaceAll("\\s", "");
|
|
|
+ result.setLeadingString(processedResult.substring(0, 8));
|
|
|
+ result.setFixed1(processedResult.substring(8, 10));
|
|
|
+ result.setTableNumber(bigEndianToLittleEndian(processedResult.substring(10, 22)));
|
|
|
+ result.setFixed2(processedResult.substring(22, 24));
|
|
|
+ result.setCommandCode(processedResult.substring(24, 26));
|
|
|
+ result.setDataFieldLength(Integer.parseUnsignedInt(processedResult.substring(26, 28), 16));
|
|
|
+
|
|
|
+ String dataIdentificationString = processedResult.substring(28, 36);
|
|
|
+ result.setDataIdentification(bigEndianToLittleEndian(subtractFromHex(dataIdentificationString)));
|
|
|
+
|
|
|
+ String remainingAmountString = processedResult.substring(36, 44);
|
|
|
+ result.setRemainingAmount(bigEndianToLittleEndian(subtractFromHex(remainingAmountString)));
|
|
|
+
|
|
|
+ String overdraftAmountString = processedResult.substring(44, 52);
|
|
|
+ result.setOverdraftAmount(bigEndianToLittleEndian(subtractFromHex(overdraftAmountString)));
|
|
|
+
|
|
|
+ String AVoltageString = processedResult.substring(52, 56);
|
|
|
+ result.setAVoltage(dataFormat(bigEndianToLittleEndian(subtractFromHex(AVoltageString)), 10, "0.0", "V"));
|
|
|
+
|
|
|
+ String BVoltageString = processedResult.substring(56, 60);
|
|
|
+ result.setBVoltage(dataFormat(bigEndianToLittleEndian(subtractFromHex(BVoltageString)), 10, "0.0", "V"));
|
|
|
+
|
|
|
+ String CVoltageString = processedResult.substring(60, 64);
|
|
|
+ result.setCVoltage(dataFormat(bigEndianToLittleEndian(subtractFromHex(CVoltageString)), 10, "0.0", "V"));
|
|
|
+
|
|
|
+ String ACurrentString = processedResult.substring(64, 70);
|
|
|
+ result.setACurrent(dataFormat(bigEndianToLittleEndian(subtractFromHex(ACurrentString)), 1000, "0.000", "A"));
|
|
|
+
|
|
|
+ String BCurrentString = processedResult.substring(70, 76);
|
|
|
+ result.setBCurrent(dataFormat(bigEndianToLittleEndian(subtractFromHex(BCurrentString)), 1000, "0.000", "A"));
|
|
|
+
|
|
|
+ String CCurrentString = processedResult.substring(76, 82);
|
|
|
+ result.setCCurrent(dataFormat(bigEndianToLittleEndian(subtractFromHex(CCurrentString)), 1000, "0.000", "A"));
|
|
|
+
|
|
|
+ String totalActivePowerString = processedResult.substring(82, 88);
|
|
|
+ result.setTotalActivePower(dataFormat(bigEndianToLittleEndian(subtractFromHex(totalActivePowerString)), 1000, "0.000", "KWH"));
|
|
|
+
|
|
|
+ String AActivePowerString = processedResult.substring(88, 94);
|
|
|
+ result.setAActivePower(dataFormat(bigEndianToLittleEndian(subtractFromHex(AActivePowerString)), 10000, "0.0000", "KWH"));
|
|
|
+
|
|
|
+ String BActivePowerString = processedResult.substring(94, 100);
|
|
|
+ result.setBActivePower(dataFormat(bigEndianToLittleEndian(subtractFromHex(BActivePowerString)), 10000, "0.0000", "KWH"));
|
|
|
+
|
|
|
+ String CActivePowerString = processedResult.substring(100, 106);
|
|
|
+ result.setCActivePower(dataFormat(bigEndianToLittleEndian(subtractFromHex(CActivePowerString)), 10000, "0.0000", "KWH"));
|
|
|
+
|
|
|
+ String totalPowerString = processedResult.substring(106, 110);
|
|
|
+ result.setTotalPower(dataFormat(bigEndianToLittleEndian(subtractFromHex(totalPowerString)), 1000, "0.000", ""));
|
|
|
+
|
|
|
+ String APowerString = processedResult.substring(110, 114);
|
|
|
+ result.setAPower(dataFormat(bigEndianToLittleEndian(subtractFromHex(APowerString)), 1000, "0.000", ""));
|
|
|
+
|
|
|
+ String BPowerString = processedResult.substring(114, 118);
|
|
|
+ result.setBPower(dataFormat(bigEndianToLittleEndian(subtractFromHex(BPowerString)), 1000, "0.000", ""));
|
|
|
+
|
|
|
+ String CPowerString = processedResult.substring(118, 122);
|
|
|
+ result.setCPower(dataFormat(bigEndianToLittleEndian(subtractFromHex(CPowerString)), 1000, "0.000", ""));
|
|
|
+
|
|
|
+ String totalElectricityString = processedResult.substring(122, 130);
|
|
|
+ result.setTotalElectricity(dataFormat(bigEndianToLittleEndian(subtractFromHex(totalElectricityString)), 100, "0.00", "KWH"));
|
|
|
+
|
|
|
+ String sharpActivePowerConsumptionString = processedResult.substring(130, 138);
|
|
|
+ result.setSharpActivePowerConsumption(dataFormat(bigEndianToLittleEndian(subtractFromHex(sharpActivePowerConsumptionString)), 100, "0.00", "KWH"));
|
|
|
+
|
|
|
+ String peakActivePowerConsumptionString = processedResult.substring(138, 146);
|
|
|
+ result.setPeakActivePowerConsumption(dataFormat(bigEndianToLittleEndian(subtractFromHex(peakActivePowerConsumptionString)), 100, "0.00", "KWH"));
|
|
|
+
|
|
|
+ String averageActivePowerConsumptionString = processedResult.substring(146, 154);
|
|
|
+ result.setAverageActivePowerConsumption(dataFormat(bigEndianToLittleEndian(subtractFromHex(averageActivePowerConsumptionString)), 100, "0.00", "KWH"));
|
|
|
+
|
|
|
+ String valleyActivePowerString = processedResult.substring(154, 162);
|
|
|
+ result.setValleyActivePower(dataFormat(bigEndianToLittleEndian(subtractFromHex(valleyActivePowerString)), 100, "0.00", "KWH"));
|
|
|
+
|
|
|
+ String stateString = processedResult.substring(162, 166);
|
|
|
+ result.setState(bigEndianToLittleEndian(subtractFromHex(stateString)));
|
|
|
+
|
|
|
+ result.setCreateTime(new Date());
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("解析消息时出错", e);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 将大端表示的十六进制字符串转换为小端表示的十六进制字符串。
|
|
|
+ *
|
|
|
+ * @param bigEndianHexString 大端表示的十六进制字符串(如 "032002250111")
|
|
|
+ * @return 小端表示的十六进制字符串(如 "110125022003")
|
|
|
+ */
|
|
|
+ public static String bigEndianToLittleEndian(String bigEndianHexString) {
|
|
|
+ // 将十六进制字符串转换为字节数组
|
|
|
+ byte[] bigEndianBytes = hexStringToByteArray(bigEndianHexString);
|
|
|
+
|
|
|
+ // 进行大小端转换
|
|
|
+ byte[] littleEndianBytes = reverseBytes(bigEndianBytes);
|
|
|
+
|
|
|
+ // 将字节数组转换回十六进制字符串
|
|
|
+ return bytesToHex(littleEndianBytes, 0, littleEndianBytes.length);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将十六进制字符串转换为字节数组。
|
|
|
+ *
|
|
|
+ * @param s 十六进制字符串
|
|
|
+ * @return 字节数组
|
|
|
+ */
|
|
|
+ private static byte[] hexStringToByteArray(String s) {
|
|
|
+ int len = s.length();
|
|
|
+ byte[] data = new byte[len / 2];
|
|
|
+ for (int i = 0; i < len; i += 2) {
|
|
|
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
|
|
+ + Character.digit(s.charAt(i + 1), 16));
|
|
|
+ }
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将字节数组转换为十六进制字符串。
|
|
|
+ *
|
|
|
+ * @param bytes 字节数组
|
|
|
+ * @param offset 偏移量
|
|
|
+ * @param length 长度
|
|
|
+ * @return 十六进制字符串
|
|
|
+ */
|
|
|
+ private static String bytesToHex(byte[] bytes, int offset, int length) {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
+ sb.append(String.format("%02X", bytes[offset + i]));
|
|
|
+ }
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 反转字节数组以进行大小端转换。
|
|
|
+ *
|
|
|
+ * @param bytes 字节数组
|
|
|
+ * @return 转换后的字节数组
|
|
|
+ */
|
|
|
+ private static byte[] reverseBytes(byte[] bytes) {
|
|
|
+ byte[] reversedBytes = new byte[bytes.length];
|
|
|
+ for (int i = 0; i < bytes.length; i++) {
|
|
|
+ reversedBytes[i] = bytes[bytes.length - 1 - i];
|
|
|
+ }
|
|
|
+ return reversedBytes;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 将十六进制字符串中的每个字节减去指定的十进制数值,并返回新的十六进制字符串。
|
|
|
+ *
|
|
|
+ * @param hexStr 十六进制字符串(例如 "3244B335")
|
|
|
+ * @return 新的十六进制字符串
|
|
|
+ */
|
|
|
+ public static String subtractFromHex(String hexStr) {
|
|
|
+ StringBuilder result = new StringBuilder();
|
|
|
+ // 将十六进制减数转换为十进制整数
|
|
|
+ int subValue = Integer.parseInt("33", 16);
|
|
|
+
|
|
|
+ // 按两位一组遍历十六进制字符串
|
|
|
+ for (int i = 0; i < hexStr.length(); i += 2) {
|
|
|
+ // 提取两位十六进制数
|
|
|
+ String pair = hexStr.substring(i, Math.min(i + 2, hexStr.length()));
|
|
|
+ // 将提取的两位十六进制数转换为十进制整数
|
|
|
+ int pairValue = Integer.parseInt(pair, 16);
|
|
|
+ // 进行减法运算
|
|
|
+ int newVal = pairValue - subValue;
|
|
|
+ // 处理负数情况,保留最后两位十六进制表示
|
|
|
+ newVal = newVal & 0xFF;
|
|
|
+ // 将结果转换为两位十六进制字符串
|
|
|
+ String newHex = String.format("%02X", newVal);
|
|
|
+ // 将结果添加到结果字符串中
|
|
|
+ result.append(newHex);
|
|
|
+ }
|
|
|
+ return result.toString();
|
|
|
+ }
|
|
|
+ public static String dataFormat(String input,int size,String decimalPlaces,String unit) {
|
|
|
+ // 将输入的字符串转换为浮点数
|
|
|
+ double voltage = Double.parseDouble(input) / + size;
|
|
|
+ // 使用DecimalFormat来格式化数字,保留小数
|
|
|
+ DecimalFormat df = new DecimalFormat(decimalPlaces);
|
|
|
+ String formattedVoltage = df.format(voltage);
|
|
|
+ // 添加单位V
|
|
|
+ return formattedVoltage + unit;
|
|
|
+ }
|
|
|
+}
|