张世豪
4 小时以前 d22349714c8d199c02f336f90fba841ef8f5cd39
src/publicway/ProtocolParser01.java
@@ -1,13 +1,20 @@
package publicway;
import java.util.ArrayList;
import java.util.List;
import chuankou.SerialPortService;
import chushihua.SlotManager;
public class ProtocolParser01 {
    // 缓存常用字符串减少重复创建
    private static final String[] WORK_STATUS_DESC = {"无效", "待机", "充电", "充满", "故障", "授权到期", "通信超时", "未知状态"};
    private static final String[] DOOR_STATUS_DESC = {"未知状态", "开门状态", "关门状态"};
    private static final String[] CARD_STATUS_DESC = {"无卡", "有卡", "读卡错误(卡非法)", "未知状态"};
    // StringBuilder 对象池
    private static final ThreadLocal<StringBuilder> stringBuilderPool =
        ThreadLocal.withInitial(() -> new StringBuilder(512));
    /**
     * 新增:直接使用字节数组解析的方法(避免字符串转换)
     * 优化后的字节数组解析方法
     */
    public static ParseResult parseDDCC01Data(byte[] packetData) {
        if (packetData == null || packetData.length < 18) {
@@ -19,45 +26,49 @@
            throw new IllegalArgumentException("非DDCC协议数据");
        }
        ParseResult result = ParseResultPool.borrowObject();
        try {
            // 跳过包头DDCC (2字节),直接使用剩余数据
            byte[] dataBytes = new byte[packetData.length - 2];
            System.arraycopy(packetData, 2, dataBytes, 0, dataBytes.length);
            if (dataBytes.length < 16) {
            // 直接使用原数组,避免创建新数组
            if (packetData.length < 18) { // 2(包头) + 16(最小数据长度)
                throw new IllegalArgumentException("数据长度不足");
            }
            // 2. 解析各个字段
            int dataLength = parseDataLength(dataBytes);
            int hostAddress = parseHostAddress(dataBytes);
            int slotNumber = parseSlotNumber(dataBytes);
            int functionCode = parseFunctionCode(dataBytes);
            WorkStatus workStatus = parseWorkStatus(dataBytes);
            DoorStatus doorStatus = parseDoorStatus(dataBytes);
            CardStatus cardStatus = parseCardStatus(dataBytes);
            int cardStatusChange = parseCardStatusChange(dataBytes);
            String cardNumber = parseCardNumber(dataBytes);
            List<FaultType> faults = parseFaults(dataBytes);
            double voltage = parseVoltage(dataBytes);
            double current = parseCurrent(dataBytes);
            // 解析各个字段
            int dataLength = parseDataLength(packetData, 2);
            int hostAddress = parseHostAddress(packetData, 4);
            int slotNumber = parseSlotNumber(packetData, 5);
            int functionCode = parseFunctionCode(packetData, 6);
            // 3. 验证功能码
            // 验证功能码
            if (functionCode != 0x01) {
                throw new IllegalArgumentException("非01功能码数据");
            }
            return new ParseResult(hostAddress, slotNumber, workStatus, doorStatus,
                    cardStatus, cardStatusChange, cardNumber,
                    faults, voltage, current, dataLength);
            WorkStatus workStatus = parseWorkStatus(packetData, 7);
            DoorStatus doorStatus = parseDoorStatus(packetData, 8);
            CardStatus cardStatus = parseCardStatus(packetData, 9);
            int cardStatusChange = parseCardStatusChange(packetData, 10);
            String cardNumber = parseCardNumber(packetData, 13);
            List<FaultType> faults = parseFaults(packetData, 15);
            double voltage = parseVoltage(packetData, 16);
            double current = parseCurrent(packetData, 17);
            // 重用 ParseResult 对象
            result.reset(hostAddress, slotNumber, workStatus, doorStatus,
                        cardStatus, cardStatusChange, cardNumber,
                        faults, voltage, current, dataLength);
            return result;
        } catch (Exception e) {
            // 发生异常时归还对象
            ParseResultPool.returnObject(result);
            throw new RuntimeException("解析数据时发生错误: " + e.getMessage(), e);
        }
    }
    /**
     * 保留原有方法用于兼容性
     * 优化后的字符串解析方法
     */
    public static ParseResult parseDDCC01Data(String hexData) {
        if (hexData == null || hexData.isEmpty()) {
@@ -69,6 +80,7 @@
            throw new IllegalArgumentException("非DDCC协议数据");
        }
        ParseResult result = ParseResultPool.borrowObject();
        try {
            // 1. 移除包头DDCC进行解析
            String dataWithoutHeader = hexData.substring(4);
@@ -79,178 +91,162 @@
            }
            // 2. 解析各个字段
            int dataLength = parseDataLength(dataBytes);
            int hostAddress = parseHostAddress(dataBytes);
            int slotNumber = parseSlotNumber(dataBytes);
            int functionCode = parseFunctionCode(dataBytes);
            WorkStatus workStatus = parseWorkStatus(dataBytes);
            DoorStatus doorStatus = parseDoorStatus(dataBytes);
            CardStatus cardStatus = parseCardStatus(dataBytes);
            int cardStatusChange = parseCardStatusChange(dataBytes);
            String cardNumber = parseCardNumber(dataBytes);
            List<FaultType> faults = parseFaults(dataBytes);
            double voltage = parseVoltage(dataBytes);
            double current = parseCurrent(dataBytes);
            int dataLength = parseDataLength(dataBytes, 0);
            int hostAddress = parseHostAddress(dataBytes, 2);
            int slotNumber = parseSlotNumber(dataBytes, 3);
            int functionCode = parseFunctionCode(dataBytes, 4);
            // 3. 验证功能码
            if (functionCode != 0x01) {
                throw new IllegalArgumentException("非01功能码数据");
            }
            return new ParseResult(hostAddress, slotNumber, workStatus, doorStatus,
                    cardStatus, cardStatusChange, cardNumber,
                    faults, voltage, current, dataLength);
            WorkStatus workStatus = parseWorkStatus(dataBytes, 5);
            DoorStatus doorStatus = parseDoorStatus(dataBytes, 6);
            CardStatus cardStatus = parseCardStatus(dataBytes, 7);
            int cardStatusChange = parseCardStatusChange(dataBytes, 8);
            String cardNumber = parseCardNumber(dataBytes, 11);
            List<FaultType> faults = parseFaults(dataBytes, 13);
            double voltage = parseVoltage(dataBytes, 14);
            double current = parseCurrent(dataBytes, 15);
            result.reset(hostAddress, slotNumber, workStatus, doorStatus,
                        cardStatus, cardStatusChange, cardNumber,
                        faults, voltage, current, dataLength);
            return result;
        } catch (Exception e) {
            ParseResultPool.returnObject(result);
            throw new RuntimeException("解析数据时发生错误: " + e.getMessage(), e);
        }
    }
    /**
     * CRC校验
     * 根据协议:CRC16校验从功能码之后一直到CRC16之前的数据
     */
    private static boolean validateCRC(String hexData) {
        try {
            // CRC在最后4个字符
            String receivedCRC = hexData.substring(hexData.length() - 6);
            byte[] cmdBytes = HexUtil.hexStringToBytes(hexData.replace(receivedCRC,""));
            String crc = HexUtil.calculate(cmdBytes)+"00";
            System.out.println("收到的完整数据是:"+hexData);
            System.out.println("收到数据校验码是:"+receivedCRC);
            System.out.println("校验码是:"+crc);
            return receivedCRC.equalsIgnoreCase(crc);
        } catch (Exception e) {
            System.err.println("CRC校验异常: " + e.getMessage());
            return false;
        }
    }
    /**
     * 解析数据长度(2字节)
     * 数据长度是从该字节之后开始到CRC16之前数据字节数
     */
    private static int parseDataLength(byte[] data) {
        if (data.length < 2) {
    private static int parseDataLength(byte[] data, int offset) {
        if (data.length < offset + 2) {
            throw new IllegalArgumentException("数据长度不足,无法解析数据长度");
        }
        return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
        return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
    }
    /**
     * 解析主机地址(1字节)
     */
    private static int parseHostAddress(byte[] data) {
        if (data.length < 3) {
    private static int parseHostAddress(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析主机地址");
        }
        return data[2] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析卡槽编号(1字节)
     */
    private static int parseSlotNumber(byte[] data) {
        if (data.length < 4) {
    private static int parseSlotNumber(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡槽编号");
        }
        return data[3] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析功能码(1字节)
     */
    private static int parseFunctionCode(byte[] data) {
        if (data.length < 5) {
    private static int parseFunctionCode(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析功能码");
        }
        return data[4] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析工作状态(1字节)
     */
    private static WorkStatus parseWorkStatus(byte[] data) {
        if (data.length < 6) {
    private static WorkStatus parseWorkStatus(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析工作状态");
        }
        int statusValue = data[5] & 0xFF;
        int statusValue = data[offset] & 0xFF;
        return WorkStatus.fromValue(statusValue);
    }
    /**
     * 解析在位状态/门状态(1字节)
     */
    private static DoorStatus parseDoorStatus(byte[] data) {
        if (data.length < 7) {
    private static DoorStatus parseDoorStatus(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析在位状态");
        }
        int statusValue = data[6] & 0xFF;
        int statusValue = data[offset] & 0xFF;
        return DoorStatus.fromValue(statusValue);
    }
    /**
     * 解析卡状态(1字节)
     */
    private static CardStatus parseCardStatus(byte[] data) {
        if (data.length < 8) {
    private static CardStatus parseCardStatus(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡状态");
        }
        int statusValue = data[7] & 0xFF;
        int statusValue = data[offset] & 0xFF;
        return CardStatus.fromValue(statusValue);
    }
    /**
     * 解析卡状态变更(1字节)
     */
    private static int parseCardStatusChange(byte[] data) {
        if (data.length < 9) {
    private static int parseCardStatusChange(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡状态变更");
        }
        return data[8] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析卡号(卡号3 + 卡号4)
     */
    private static String parseCardNumber(byte[] data) {
        if (data.length < 13) {
    private static String parseCardNumber(byte[] data, int offset) {
        if (data.length < offset + 2) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡号");
        }
        // 索引11:卡号3,索引12:卡号4
        byte cardNumber3 = data[11];
        byte cardNumber4 = data[12];
        return String.format("%02X%02X", cardNumber3 & 0xFF, cardNumber4 & 0xFF);
        // 直接返回字符串,避免创建临时对象
        char[] hexChars = new char[4];
        hexChars[0] = Character.forDigit((data[offset] >> 4) & 0xF, 16);
        hexChars[1] = Character.forDigit(data[offset] & 0xF, 16);
        hexChars[2] = Character.forDigit((data[offset + 1] >> 4) & 0xF, 16);
        hexChars[3] = Character.forDigit(data[offset + 1] & 0xF, 16);
        return new String(hexChars).toUpperCase();
    }
    /**
     * 解析故障信息(1字节)
     */
    private static List<FaultType> parseFaults(byte[] data) {
        if (data.length < 14) {
    private static List<FaultType> parseFaults(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析故障信息");
        }
        int faultByte = data[13] & 0xFF;
        List<FaultType> faults = new ArrayList<>();
        int faultByte = data[offset] & 0xFF;
        List<FaultType> faults = new ArrayList<>(5); // 预分配容量
        for (FaultType fault : FaultType.values()) {
            if ((faultByte & fault.getBitMask()) != 0) {
                faults.add(fault);
            }
        }
        return faults;
    }
    /**
     * 解析电压值(1字节)
     */
    private static double parseVoltage(byte[] data) {
        if (data.length < 15) {
    private static double parseVoltage(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析电压");
        }
        int voltageValue = data[14] & 0xFF;
        int voltageValue = data[offset] & 0xFF;
        // 50mV/bit 转换为伏特
        return voltageValue * 0.05;
    }
@@ -258,18 +254,16 @@
    /**
     * 解析电流值(1字节)
     */
    private static double parseCurrent(byte[] data) {
        if (data.length < 16) {
    private static double parseCurrent(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析电流");
        }
        int currentValue = data[15] & 0xFF;
        int currentValue = data[offset] & 0xFF;
        // 10mA/bit 转换为安培
        return currentValue * 0.01;
    }
    /**
     * 工作状态枚举
     */
    // 枚举类保持不变...
    public enum WorkStatus {
        INVALID(0, "无效"),
        STANDBY(1, "待机"),
@@ -288,13 +282,8 @@
            this.description = description;
        }
        public int getValue() {
            return value;
        }
        public String getDescription() {
            return description;
        }
        public int getValue() { return value; }
        public String getDescription() { return description; }
        public static WorkStatus fromValue(int value) {
            for (WorkStatus status : values()) {
@@ -306,9 +295,6 @@
        }
    }
    /**
     * 门状态枚举
     */
    public enum DoorStatus {
        UNKNOWN(0, "δ֪״̬"),
        DOOR_OPEN(1, "开门状态"),
@@ -322,13 +308,8 @@
            this.description = description;
        }
        public int getValue() {
            return value;
        }
        public String getDescription() {
            return description;
        }
        public int getValue() { return value; }
        public String getDescription() { return description; }
        public static DoorStatus fromValue(int value) {
            for (DoorStatus status : values()) {
@@ -340,9 +321,6 @@
        }
    }
    /**
     * 卡状态枚举
     */
    public enum CardStatus {
        NO_CARD(0, "无卡"),
        HAS_CARD(1, "有卡"),
@@ -357,13 +335,8 @@
            this.description = description;
        }
        public int getValue() {
            return value;
        }
        public String getDescription() {
            return description;
        }
        public int getValue() { return value; }
        public String getDescription() { return description; }
        public static CardStatus fromValue(int value) {
            for (CardStatus status : values()) {
@@ -375,9 +348,6 @@
        }
    }
    /**
     * 故障类型枚举
     */
    public enum FaultType {
        INSERT_ERROR(0x01, "插卡错误"),
        OVER_CURRENT(0x02, "过流"),
@@ -393,17 +363,12 @@
            this.description = description;
        }
        public int getBitMask() {
            return bitMask;
        }
        public String getDescription() {
            return description;
        }
        public int getBitMask() { return bitMask; }
        public String getDescription() { return description; }
    }
    /**
     * 解析结果类 - 添加对象池支持
     * 优化后的解析结果类
     */
    public static class ParseResult {
        private int hostAddress;
@@ -418,29 +383,12 @@
        private double current;
        private int dataLength;
        // 默认构造器用于对象池
        // 重用列表对象
        private final List<FaultType> faultList = new ArrayList<>(5);
        private final List<String> faultDescList = new ArrayList<>(5);
        public ParseResult() {}
        public ParseResult(int hostAddress, int slotNumber, WorkStatus workStatus,
                DoorStatus doorStatus, CardStatus cardStatus, int cardStatusChange,
                String cardNumber, List<FaultType> faults, double voltage,
                double current, int dataLength) {
            this.hostAddress = hostAddress;
            this.slotNumber = slotNumber;
            this.workStatus = workStatus;
            this.doorStatus = doorStatus;
            this.cardStatus = cardStatus;
            this.cardStatusChange = cardStatusChange;
            this.cardNumber = cardNumber;
            this.faults = faults;
            this.voltage = voltage;
            this.current = current;
            this.dataLength = dataLength;
        }
        /**
         * 重置方法,用于对象重用
         */
        public void reset(int hostAddress, int slotNumber, WorkStatus workStatus, 
                         DoorStatus doorStatus, CardStatus cardStatus, int cardStatusChange,
                         String cardNumber, List<FaultType> faults, double voltage, 
@@ -452,10 +400,16 @@
            this.cardStatus = cardStatus;
            this.cardStatusChange = cardStatusChange;
            this.cardNumber = cardNumber;
            this.faults = faults;
            this.voltage = voltage;
            this.current = current;
            this.dataLength = dataLength;
            // 重用故障列表
            this.faultList.clear();
            if (faults != null) {
                this.faultList.addAll(faults);
            }
            this.faults = this.faultList;
        }
        // Getter方法
@@ -475,21 +429,24 @@
         * 获取故障的中文描述列表
         */
        public List<String> getFaultDescriptions() {
            List<String> descriptions = new ArrayList<>();
            faultDescList.clear();
            for (FaultType fault : faults) {
                descriptions.add(fault.getDescription());
                faultDescList.add(fault.getDescription());
            }
            return descriptions;
            return faultDescList;
        }
        /**
         * 获取故障的中文描述字符串
         */
        public String getFaultsString() {
            if (faults == null || faults.isEmpty()) {
            if (faults.isEmpty()) {
                return "无故障";
            }
            StringBuilder sb = new StringBuilder();
            StringBuilder sb = stringBuilderPool.get();
            sb.setLength(0);
            for (int i = 0; i < faults.size(); i++) {
                if (i > 0) sb.append(", ");
                sb.append(faults.get(i).getDescription());
@@ -499,49 +456,47 @@
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("=== DDCC协议数据解析结果 ===\n");
            sb.append("1. 主机地址: ").append(String.format("%02X", hostAddress));
            sb.append("2. 卡槽编号: ").append(slotNumber);
            sb.append("3. 工作状态: ").append(workStatus.getDescription())
              .append(" (").append(workStatus.getValue());
            sb.append("4. 门状态: ").append(doorStatus.getDescription())
              .append(" (").append(doorStatus.getValue());
            sb.append("5. 卡状态: ").append(cardStatus.getDescription())
              .append(" (").append(cardStatus.getValue());
            sb.append("6. 卡状态变更: ").append(cardStatusChange);
            sb.append("7. 卡号: ").append(cardNumber);
            sb.append("8. 故障: ").append(getFaultsString());
            sb.append("9. 电压: ").append(String.format("%.2f", voltage));
            sb.append("10. 电流: ").append(String.format("%.2f", current));
            sb.append("数据长度: ").append(dataLength).append(" 字节");
//            System.out.println(sb.toString());
            return sb.toString();
            StringBuilder sb = stringBuilderPool.get();
            sb.setLength(0);
            sb.append("1.主机地址:").append(String.format("%02X", hostAddress));
            sb.append("2.卡槽编号:").append(slotNumber);
            sb.append("3.工作状态:").append(workStatus.getDescription())
              .append("(").append(workStatus.getValue()).append(")");
            sb.append("4. 门状态:").append(doorStatus.getDescription())
              .append("(").append(doorStatus.getValue()).append(")");
            sb.append("5.卡状态:").append(cardStatus.getDescription())
              .append("(").append(cardStatus.getValue()).append(")");
            sb.append("6.卡状态变更:").append(cardStatusChange);
            sb.append("7.卡号:").append(cardNumber);
            sb.append("8.故障:").append(getFaultsString());
            sb.append("9.电压:").append(String.format("%.2f", voltage));
            sb.append("10.电流:").append(String.format("%.2f", current));
            sb.append("数据长度:").append(dataLength).append(" 字节");
            return sb.toString();
        }
        
        public void fuzhi() {
           SlotManager.gengxinshuxingzhi(
            SlotManager.gengxinshuxingzhi(
                    slotNumber,    // 卡槽编号
                    cardNumber,    // 卡编号
                    String.valueOf(cardStatus.getValue()),       // 是否有卡0无卡,1有卡,-1未知
                    String.valueOf(workStatus.getValue()),    // 工作状态0.无效1.待机;2.充电;3.充满;4.故障;5.授权到期;6.通信超时
                    String.valueOf(workStatus.getValue()),    // 工作状态
                    String.format("%.2f", voltage),      // 电压
                    String.format("%.2f", current),       // 电流
                    getFaultsString()        // 故障1插卡错误;2过流;3,门控故障;4过压;5欠压;
                    );
                    getFaultsString()        // 故障
            );
        }
    }
    /**
     * 简单的对象池实现
     * 改进的对象池实现
     */
    public static class ParseResultPool {
        private static final int POOL_SIZE = 10;
        private static final int POOL_SIZE = 20;
        private static final java.util.concurrent.BlockingQueue<ParseResult> pool = 
            new java.util.concurrent.ArrayBlockingQueue<>(POOL_SIZE);
            new java.util.concurrent.LinkedBlockingQueue<>(POOL_SIZE);
        
        static {
            // 预创建对象
@@ -556,9 +511,17 @@
        }
        
        public static void returnObject(ParseResult result) {
            if (result != null && !pool.offer(result)) {
                // 池已满,不回收
            if (result != null) {
                // 清理状态
                result.reset(0, 0, WorkStatus.UNKNOWN, DoorStatus.UNKNOWN,
                           CardStatus.UNKNOWN, 0, "", null, 0.0, 0.0, 0);
                // 非阻塞式归还
                pool.offer(result);
            }
        }
        public static int getPoolSize() {
            return pool.size();
        }
    }
}