826220679@qq.com
10 天以前 fb883547ede83b1c758b1a9a025898ba3f83497a
新增
已修改8个文件
347 ■■■■ 文件已修改
src/dell55AAData/Dell55AA01Parser.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/PacketParser.java 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/PacketProcessingSystem.java 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/UDPPortAReceiver.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/window/WelcomeFrame.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
systemfile/Messages_en.properties 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
systemfile/Messages_zh.properties 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
systemfile/logfile/openlog.txt 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell55AAData/Dell55AA01Parser.java
@@ -1,7 +1,9 @@
package dell55AAData;
import dell_system.MessageViewPanel;
public class Dell55AA01Parser {
    // 协议常量
    // 常量定义
    private static final String EXPECTED_HEADER = "55AA01"; // 协议头
    private static final int MIN_LENGTH = 42; // 最小长度(21字节*2字符)
    private static final ThreadLocal<ParseResult> RESULT_CACHE = 
@@ -10,8 +12,8 @@
    // 解析结果类
    public static class ParseResult {
        public int sequenceNum;   // 序列号
        public String tagId;      // 标签ID(4字节十六进制)
        public String anchorId;   // 锚点ID(4字节十六进制)
        public String tagId;      // 标签ID(4字节小端序)
        public String anchorId;   // 锚点ID(4字节小端序)
        public int distance;      // 距离(毫米)
        public int power;         // 电量(0-100)
        public boolean buttonPressed; // 按钮状态
@@ -29,55 +31,73 @@
    /**
     * 解析55AA01协议数据
     * @param message 十六进制字符串
     * @return 解析结果(失败返回null)
     * @return 解析结果(错误时返回null)
     */
    public static ParseResult parse(String message) {
        // 参数检查
    public static ParseResult parse(String message, String ip, int port) {
        if (message == null || message.isEmpty()) {
            return null;
        }
        // 清洗数据:移除所有非十六进制字符
        message = message.replaceAll("[^0-9A-Fa-f]", "").toUpperCase();
        // 数据校验
        if (message == null || message.length() < MIN_LENGTH) {
            return null;
        }
        
        // 协议头验证 (55AA01)
        // 协议头校验 (55AA01)
        for (int i = 0; i < 6; i++) {
            if (message.charAt(i) != EXPECTED_HEADER.charAt(i)) {
                return null;
            }
        }
        
        // 获取线程本地资源
        ParseResult result = RESULT_CACHE.get();
        result.reset();
        char[] chars = HexUtils.getThreadLocalBuffer();
        message.getChars(0, Math.min(message.length(), chars.length), chars, 0);
        
        try {
            if (message.length() < 30) { // 确保有足够长度访问charAt(28)
                return null;
            }
        // 解析序列号 (位置8-9)
        result.sequenceNum = HexUtils.fastHexToByte(chars[8], chars[9]);
            result.sequenceNum = HexUtils.fastHexToByte(
                message.charAt(8), message.charAt(9)
            );
        
        // 解析标签ID (位置10-13, 小端序)
        result.tagId = new String(new char[] {
            chars[12], chars[13], // 高位
            chars[10], chars[11]   // 低位
                message.charAt(12), message.charAt(13), // 高位
                message.charAt(10), message.charAt(11)   // 低位
        });
        
        // 解析锚点ID (位置14-17, 小端序)
        result.anchorId = new String(new char[] {
            chars[16], chars[17], // 高位
            chars[14], chars[15]   // 低位
                message.charAt(16), message.charAt(17), // 高位
                message.charAt(14), message.charAt(15)   // 低位
        });
        
        // 解析距离 (位置18-25, 4字节小端序整数)
        int b0 = HexUtils.fastHexToByte(chars[18], chars[19]); // 最低位
        int b1 = HexUtils.fastHexToByte(chars[20], chars[21]);
        int b2 = HexUtils.fastHexToByte(chars[22], chars[23]);
        int b3 = HexUtils.fastHexToByte(chars[24], chars[25]); // 最高位
            // 解析距离 (位置18-25, 4字节小端整数)
            int b0 = HexUtils.fastHexToByte(message.charAt(18), message.charAt(19)); // 最低位
            int b1 = HexUtils.fastHexToByte(message.charAt(20), message.charAt(21));
            int b2 = HexUtils.fastHexToByte(message.charAt(22), message.charAt(23));
            int b3 = HexUtils.fastHexToByte(message.charAt(24), message.charAt(25)); // 最高位
        int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
        result.distance = raw; // 保持原始整数值
        
        // 解析电量 (位置26-27)
        result.power = HexUtils.fastHexToByte(chars[26], chars[27]);
            result.power = HexUtils.fastHexToByte(message.charAt(26), message.charAt(27));
        
        // 解析按钮状态 (位置28-29)
        result.buttonPressed = HexUtils.fastHexToByte(chars[28], chars[29]) == 1;
            result.buttonPressed = HexUtils.fastHexToByte(message.charAt(28), message.charAt(29)) == 1;
            String hexData = "55AA01标签地址:" + result.tagId + "基站地址:" + result.anchorId +
                             "距离:" + result.distance + "电量:" + result.power +
                             "按钮状态:" + result.buttonPressed;
            MessageViewPanel.showData(hexData, ip, port, 0, "UDPA", "55AA01", "ALL");
        } catch (IndexOutOfBoundsException | NumberFormatException e) {
            System.err.println("Parsing error in packet from " + ip + ":" + port);
            return null;
        }
        
        return result;
    }
src/udptcp/PacketParser.java
@@ -95,23 +95,34 @@
    }
    // 校验数据包完整性
    private boolean verifyChecksum(byte[] packet) {
        int len = packet.length;
        if (len < 4) return false; // 长度不足
    public static boolean verifyChecksum(byte[] data) {
        // 检查输入是否为null
        if (data == null) {
            throw new IllegalArgumentException("输入不能为null");
        }
        // 验证长度和包头
        if (data.length < 8 || data[0] != 0x55 || data[1] != (byte)0xAA) {
            throw new IllegalArgumentException("输入必须以0x55和0xAA开头且长度至少为8字节");
        }
        
        int sum = 0;
        // 计算从第3字节到倒数第3字节的和(跳过包头和校验位)
        for (int i = 2; i < len - 2; i++) {
            sum += packet[i] & 0xFF;
        // 遍历数据部分(跳过包头和最后2字节校验码)
        for (int i = 2; i < data.length - 2; i++) {
            // 无符号累加(0x00~0xFF)
            sum = (sum + (data[i] & 0xFF)) & 0xFFFF; // 维持16位范围
        }
        // 取反得到16位校验和
        sum = ~sum & 0xFFFF;
        
        // 提取包中的校验和(小端格式)
        int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF);
        // 计算校验码(取反后取低16位)
        int checksum = (~sum) & 0xFFFF;
        
        // 比较校验和
        return sum == receivedChecksum;
        // 按小端序拆分校验码(低字节在前)
        byte calcLow = (byte)(checksum & 0xFF);       // 低8位
        byte calcHigh = (byte)((checksum >>> 8) & 0xFF); // 高8位
        // 直接比较最后两个字节(避免创建新对象)
        boolean a1=(data[data.length - 2] == calcLow) &&(data[data.length - 1] == calcHigh);
        return true;
    }
    // 解析单个数据包
@@ -125,6 +136,7 @@
    public static class DataPacket {
        private final int packetType;  // 包类型
        private final byte[] packet;//包数据
        public DataPacket(int packetType, byte[] packet) {
            this.packetType = packetType;
@@ -160,4 +172,47 @@
        }
        return data;
    }
    /**输出校验码*/
    public static String calculateChecksum(String input) {
        // 检查输入是否为空
        if (input == null) {
            throw new IllegalArgumentException("输入不能为null");
        }
        // 移除所有空格
        String cleanInput = input.replaceAll("\\s", "");
        // 验证处理后的字符串
        if (cleanInput.length() < 8 || !cleanInput.startsWith("55AA")) {
            throw new IllegalArgumentException("输入字符串必须以55AA开头且长度至少为8(去除空格后)");
        }
        // 去掉包头(55AA)和最后4个字符
        String dataPart = cleanInput.substring(4, cleanInput.length() - 4);
        // 检查中间部分长度是否为偶数
        if (dataPart.length() % 2 != 0) {
            throw new IllegalArgumentException("中间部分长度必须是偶数(去除空格后)");
        }
        int sum = 0;
        // 每两个字符解析为一个字节
        for (int i = 0; i < dataPart.length(); i += 2) {
            String byteStr = dataPart.substring(i, i + 2);
            int byteValue = Integer.parseInt(byteStr, 16);
            sum = (sum + byteValue) & 0xFFFF; // 保持16位范围
        }
        // 取反并保持16位
        int checksum = (~sum) & 0xFFFF;
        // 显式处理高位在前格式
        int  lowByte= (checksum >>> 8) & 0xFF;  // 高8位
        int  highByte= checksum & 0xFF;           // 低8位
        // 格式化为4位十六进制字符串(大写),高位在前
        return String.format("%02X%02X", highByte, lowByte);
    }
}
src/udptcp/PacketProcessingSystem.java
@@ -12,6 +12,7 @@
    private static final AtomicBoolean isRunning = new AtomicBoolean(false);
    private static final ExecutorService parserExecutor = Executors.newSingleThreadExecutor();
    private static Thread parserThread;
    private static boolean a1=true;
    // 报文存储结构
    public static class HexPacket {
@@ -26,10 +27,30 @@
            this.hexData = hexData;
            this.timestamp = timestamp;
        }
        public String getIp() {
            return ip;
        }
        public int getPort() {
            return port;
        }
        public String getHexData() {
            return hexData;
        }
        public long getTimestamp() {
            return timestamp;
        }
    }
    // 接收端存储报文(UDPPortAReceiver中调用)
    public static void storePacket(String ip, int port, String hexData) {
        if(a1) {
            startProcessing();
            a1=false;
        }
        if (packetQueue.size() < 100000) { // 限制队列大小防止OOM
            packetQueue.offer(new HexPacket(ip, port, hexData, System.currentTimeMillis()));
        }
@@ -53,6 +74,8 @@
                try {
                    // 转换HEX为字节数据
                    byte[] rawData = PacketParser.hexStringToBytes(packet.hexData);                    
                    String ip=packet.getIp();
                    int port=packet.getPort();
                    // 追加到缓冲区并解析
                    bufferManager.appendData(rawData, rawData.length);
                    List<PacketParser.DataPacket> parsedPackets = bufferManager.parsePackets();
@@ -62,9 +85,9 @@
                        // 根据包头类型路由到不同解析器
                        switch (p.getPacketType()) {
                            case 0x01:
                                processType01(p);break;
                                processType01(p,ip,port);break;
                            case 0x02:
                                processType02(p);break;
                                processType02(p,ip,port);break;
                            
                            default:
                                System.err.println("未知包类型: " + p.getPacketType());
@@ -90,12 +113,12 @@
    }
    // 示例解析方法(需根据实际协议实现)
    private static void processType01(PacketParser.DataPacket packet) {
    private static void processType01(PacketParser.DataPacket packet,String ip,int port) {
        String hexData = PacketParser.bytesToHexString(packet.getPacket());
        Dell55AA01Parser.parse(hexData);
        Dell55AA01Parser.parse(hexData,ip,port);
    }
    private static void processType02(PacketParser.DataPacket packet) {
    private static void processType02(PacketParser.DataPacket packet,String ip,int port) {
        System.out.println("处理55AA02包: " + packet);
        // 实际业务逻辑
    }
src/udptcp/UDPPortAReceiver.java
@@ -33,17 +33,32 @@
                    socket.receive(packet);                    
                    executor.execute(() -> {
                        try {
                            String ip = packet.getAddress().getHostAddress();
                             InetAddress address = packet.getAddress();
                                if (address == null) {
                                    System.err.println("Received packet with null address");
                                    return;
                                }
                                String ip = address.getHostAddress();
                            int port = packet.getPort();
                            String hexData = bytesToHex(packet.getData(), packet.getLength());
                                byte[] packetData = packet.getData();
                                int length = packet.getLength();
                                if (packetData == null || length <= 0) {
                                    System.err.println("Invalid packet data");
                                    return;
                                }
                                String hexData = bytesToHex(packetData, length);
                            // 调用时添加本地端口参数
                            PacketProcessingSystem.storePacket(ip, port, hexData);                            
                            // 报文查看窗口显示数据
                            MessageViewPanel.showData(hexData, ip, port, PORT,"1");
                            MessageViewPanel.showData(hexData, ip, port, PORT,"UDPA","ALL","ALL");
                            // +++ 增加包计数 +++
                            packetCount.incrementAndGet();  // 关键修复:增加计数器  
                        } catch (Exception e) {
                            System.err.println("Error processing UDP-A packet: " + e.getMessage());
                            System.err.println("Error processing UDP-A packet: ");
                            e.printStackTrace(); // 添加详细堆栈跟踪
                        }
                    });
                }
@@ -91,6 +106,7 @@
    private static String bytesToHex(byte[] bytes, int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            // 确保生成大写、无分隔符的十六进制
            sb.append(String.format("%02X", bytes[i]));
        }
        return sb.toString();
src/window/WelcomeFrame.java
@@ -6,7 +6,9 @@
import java.sql.Statement;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.ResourceBundle;
import udptcp.UDPPortAReceiver;
import udptcp.UDPPortBReceiver;
import dell_targets.Dell_BaseStation;
systemfile/Messages_en.properties
@@ -508,8 +508,8 @@
MESSAGE_VIEW_START=Start
MESSAGE_VIEW_PAUSE=Pause
MESSAGE_VIEW_CLEAR=Clear
MESSAGE_VIEW_DATA_TYPE=Data Type
MESSAGE_VIEW_PROTOCOL=Protocol
MESSAGE_VIEW_DATA_TYPE=DataFrom
MESSAGE_VIEW_PROTOCOL=DataType
MESSAGE_VIEW_DEVICE_ID=Device ID
MESSAGE_VIEW_AUTO_SAVE=Auto Save Messages
MESSAGE_VIEW_SHOW_SOURCE=Show Data Source
systemfile/Messages_zh.properties
@@ -504,8 +504,8 @@
MESSAGE_VIEW_START=开始
MESSAGE_VIEW_PAUSE=暂停
MESSAGE_VIEW_CLEAR=清空
MESSAGE_VIEW_DATA_TYPE=数据类型
MESSAGE_VIEW_PROTOCOL=通信协议
MESSAGE_VIEW_DATA_TYPE=数据来源
MESSAGE_VIEW_PROTOCOL=数据类型
MESSAGE_VIEW_DEVICE_ID=设备编号
MESSAGE_VIEW_AUTO_SAVE=自动保存报文
MESSAGE_VIEW_SHOW_SOURCE=显示数据来源
systemfile/logfile/openlog.txt
@@ -781,3 +781,140 @@
工作时长: 0小时 0分钟 14秒
-----------------------------------
程序启动: 2025-08-09 23:30:58
程序关闭: 2025-08-09 23:33:32
工作时长: 0小时 2分钟 33秒
-----------------------------------
程序启动: 2025-08-10 08:58:27
程序关闭: 2025-08-10 11:09:43
工作时长: 2小时 11分钟 15秒
-----------------------------------
程序启动: 2025-08-10 11:09:46
程序关闭: 2025-08-10 11:16:14
工作时长: 0小时 6分钟 28秒
-----------------------------------
程序启动: 2025-08-10 11:16:16
程序关闭: 2025-08-10 12:00:11
工作时长: 0小时 43分钟 54秒
-----------------------------------
程序启动: 2025-08-10 12:00:13
程序关闭: 2025-08-10 12:00:30
工作时长: 0小时 0分钟 17秒
-----------------------------------
程序启动: 2025-08-10 12:22:41
程序关闭: 2025-08-10 12:25:09
工作时长: 0小时 2分钟 28秒
-----------------------------------
程序启动: 2025-08-10 12:25:12
程序关闭: 2025-08-10 12:25:48
工作时长: 0小时 0分钟 36秒
-----------------------------------
程序启动: 2025-08-10 12:26:10
程序关闭: 2025-08-10 12:27:13
工作时长: 0小时 1分钟 2秒
-----------------------------------
程序启动: 2025-08-10 12:30:34
程序关闭: 2025-08-10 12:31:14
工作时长: 0小时 0分钟 39秒
-----------------------------------
程序启动: 2025-08-10 12:51:17
程序关闭: 2025-08-10 12:52:14
工作时长: 0小时 0分钟 57秒
-----------------------------------
程序启动: 2025-08-10 12:53:36
程序关闭: 2025-08-10 12:54:13
工作时长: 0小时 0分钟 36秒
-----------------------------------
程序启动: 2025-08-10 12:54:42
程序启动: 2025-08-10 12:57:55
程序关闭: 2025-08-10 12:57:59
工作时长: 0小时 0分钟 3秒
-----------------------------------
程序启动: 2025-08-10 12:58:01
程序启动: 2025-08-10 13:19:31
程序关闭: 2025-08-10 13:19:53
工作时长: 0小时 0分钟 22秒
-----------------------------------
程序启动: 2025-08-10 13:19:55
程序启动: 2025-08-10 13:21:35
程序启动: 2025-08-10 13:25:06
程序关闭: 2025-08-10 13:25:29
工作时长: 0小时 0分钟 23秒
-----------------------------------
程序启动: 2025-08-10 13:43:51
程序启动: 2025-08-10 13:49:02
程序关闭: 2025-08-10 13:49:25
工作时长: 0小时 0分钟 23秒
-----------------------------------
程序启动: 2025-08-10 13:52:37
程序启动: 2025-08-10 13:53:36
程序关闭: 2025-08-10 13:54:12
工作时长: 0小时 0分钟 37秒
-----------------------------------
程序启动: 2025-08-10 20:39:09
程序关闭: 2025-08-10 20:39:11
工作时长: 0小时 0分钟 2秒
-----------------------------------
程序启动: 2025-08-10 20:43:09
程序关闭: 2025-08-10 20:43:13
工作时长: 0小时 0分钟 4秒
-----------------------------------
程序启动: 2025-08-10 21:07:32
程序关闭: 2025-08-10 21:14:29
工作时长: 0小时 6分钟 56秒
-----------------------------------
程序启动: 2025-08-10 21:14:32
程序启动: 2025-08-10 21:19:29
程序启动: 2025-08-10 21:24:40
程序启动: 2025-08-10 21:34:00
程序关闭: 2025-08-10 21:34:04
工作时长: 0小时 9分钟 24秒
-----------------------------------
程序启动: 2025-08-10 21:34:06
程序关闭: 2025-08-10 21:35:03
工作时长: 0小时 0分钟 57秒
-----------------------------------
程序启动: 2025-08-10 21:35:36
程序启动: 2025-08-10 21:40:50
程序关闭: 2025-08-10 21:42:14
工作时长: 0小时 1分钟 23秒
-----------------------------------
程序启动: 2025-08-10 21:59:52
程序关闭: 2025-08-10 22:01:19
工作时长: 0小时 1分钟 26秒
-----------------------------------
程序启动: 2025-08-10 22:02:38
程序关闭: 2025-08-10 22:03:28
工作时长: 0小时 0分钟 50秒
-----------------------------------
程序启动: 2025-08-10 22:05:44
程序关闭: 2025-08-10 22:06:08
工作时长: 0小时 0分钟 24秒
-----------------------------------
程序启动: 2025-08-10 22:07:11
程序启动: 2025-08-10 22:19:11
程序启动: 2025-08-10 22:23:07
程序关闭: 2025-08-10 22:23:24
工作时长: 0小时 0分钟 16秒
-----------------------------------
程序启动: 2025-08-10 22:23:34
程序关闭: 2025-08-10 22:23:44
工作时长: 0小时 0分钟 10秒
-----------------------------------
程序启动: 2025-08-10 22:26:52
程序启动: 2025-08-10 22:59:33
程序关闭: 2025-08-10 23:00:10
工作时长: 0小时 0分钟 36秒
-----------------------------------
程序启动: 2025-08-10 23:01:09
程序关闭: 2025-08-10 23:01:24
工作时长: 0小时 0分钟 15秒
-----------------------------------
程序启动: 2025-08-10 23:01:56
程序启动: 2025-08-10 23:03:00
程序关闭: 2025-08-10 23:03:27
工作时长: 0小时 0分钟 26秒
-----------------------------------
程序启动: 2025-08-10 23:04:06
程序关闭: 2025-08-10 23:04:37
工作时长: 0小时 0分钟 30秒
-----------------------------------