1562f05c0c85fb45cc8ffba8ac6984e9b6f96bd4..a8a90fd2d5040e66cc66b3da122a7f82561ff6f6
2025-08-09 826220679@qq.com
优化了欢迎页面
a8a90f 对比 | 目录
2025-08-09 826220679@qq.com
修改
ccb681 对比 | 目录
已删除4个文件
已添加5个文件
已修改16个文件
2334 ■■■■■ 文件已修改
src/chushihua/Chushihua.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell55AAData/Dell55AA02Parser.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_anchor/BaseStationAdjacentConfigPanel.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_anchor/BaseStationManagementPanel.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_anchor/BaseStationSyncConfigPanel.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_anchor/Dell_BaseStation.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_system/MessageViewPanel.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_targets/Dell_BaseStation.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_targets/Dell_SystemConfiguration.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/dell_targets/Dell_tag.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/publicsWay/Languages.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/publicsWay/UwbDataParser.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/targets/LocationBaseStation.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/DellHexBaowen.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/HexBaowen.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/PacketParser.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/PacketProcessingSystem.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/TCPDiffDataReceiver.java 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/UDPPortAReceiver.java 210 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udptcp/UDPPortBReceiver.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/window/WelcomeFrame.java 368 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/window/Windows.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
systemfile/Messages_en.properties 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
systemfile/Messages_zh.properties 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
systemfile/logfile/openlog.txt 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chushihua/Chushihua.java
@@ -1,11 +1,11 @@
package chushihua;
import java.sql.SQLException;
import dell_Fence.Dell_Fence;
import dell_anchor.Dell_BaseStation;
import dell_map.Dell_Map;
import dell_suanfa.Dell_GroupManagement;
import dell_suanfa.Dell_LayerManagement;
import dell_system.Dell_company;
import dell_targets.Dell_BaseStation;
import dell_targets.Dell_SystemConfiguration;
import dell_targets.Dell_tag;
import udptcp.UDPPortAReceiver;
@@ -13,6 +13,7 @@
public class Chushihua {
    public static void getchushihua()  {
        try {
            Dell_SystemConfiguration.getSystemConfigurations();
            Dell_tag.getlocationTags();
            Dell_BaseStation.getBaseStations();
            UDPPortAReceiver.startReceiver();
@@ -20,8 +21,7 @@
            Dell_Fence.getAllFences();
            Dell_company.getAllCompanies();
            Dell_LayerManagement.getAllLayers();
            Dell_GroupManagement.getAllGroups();
            Dell_SystemConfiguration.getSystemConfigurations();
            Dell_GroupManagement.getAllGroups();
            if(Dell_SystemConfiguration.gnsstoxyOpen) {Dell_Map.get_foor_xycs();}            
        } catch (SQLException e) {
            // TODO è‡ªåŠ¨ç”Ÿæˆçš„ catch å—
src/dell55AAData/Dell55AA02Parser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
package dell55AAData;
import dell_targets.Dell_BaseStation;
public class Dell55AA02Parser {
    private static final String EXPECTED_HEADER = "55AA02";
    private static final int MIN_LENGTH = 36; // 18字节 * 2字符/字节
    private static final int BASE_ID_START = 8;   // åŸºç«™ID起始位置(第4字节)
    private static final int SYNC_STATUS_START = 12; // åŒæ­¥çŠ¶æ€èµ·å§‹ä½ç½®(第5字节)
    private static final int PRESSURE_START = 14; // æ°”压值起始位置(第6字节)
    /**
     * è§£æž55AA02格式的基站数据
     * @param message æŽ¥æ”¶åˆ°çš„æ•°æ®ï¼ˆåå…­è¿›åˆ¶å­—符串)
     */
    public static void parseAndUpdate(String message) {
        // 1. åŸºç¡€æ ¡éªŒ
        if (message == null || message.length() < MIN_LENGTH) {
            return;
        }
        // 2. å¤´éƒ¨æ ¡éªŒï¼ˆå›ºå®šå¼€å¤´å­—符串)
        for (int i = 0; i < EXPECTED_HEADER.length(); i++) {
            if (message.charAt(i) != EXPECTED_HEADER.charAt(i)) {
                return;
            }
        }
        // 3. è§£æžåŸºç«™ID(原始数据字符串)
        String baseId = new String(new char[]{
                message.charAt(BASE_ID_START),
                message.charAt(BASE_ID_START + 1),
                message.charAt(BASE_ID_START + 2),
                message.charAt(BASE_ID_START + 3)
        });
        // 4. è§£æžåŒæ­¥çŠ¶æ€ï¼ˆ1字节)
        char syncChar = message.charAt(SYNC_STATUS_START + 1); // å–状态字符
        String syncStatus = (syncChar == '0') ? "0" : "1";
        // 5. è§£æžæ°”压值(4字节小端序)
        int pressure = 0;
        for (int i = 0; i < 8; i += 2) {
            int idx = PRESSURE_START + i;
            // ä½¿ç”¨HexUtils的快速转换方法
            int byteValue = HexUtils.fastHexToByte(message.charAt(idx), message.charAt(idx + 1));
            pressure |= (byteValue << (i * 4)); // å°ç«¯åˆå¹¶
        }
        String pressureStr = String.valueOf(pressure);
        // 6. æ›´æ–°åŸºç«™æ•°æ®
        updateBaseStationData(baseId, syncStatus ,pressureStr);
    }
    /**
     * æ›´æ–°åŸºç«™æ•°æ®
     * @param baseId åŸºç«™ID
     * @param syncStatus åŒæ­¥çŠ¶æ€
     * @param pressure æ°”压值字符串
     */
    private static void updateBaseStationData(String baseId, String syncStatus, String pressure) {
        Dell_BaseStation.updateBaseStationProperty(baseId, "syncStatus", syncStatus);
        Dell_BaseStation.updateBaseStationProperty(baseId, "barometerReading", pressure);
    }
}
src/dell_anchor/BaseStationAdjacentConfigPanel.java
@@ -1,6 +1,7 @@
package dell_anchor;
import databases.DBConnector;
import dell_targets.Dell_BaseStation;
import targets.LocationBaseStation;
import javax.swing.*;
src/dell_anchor/BaseStationManagementPanel.java
@@ -1,6 +1,8 @@
package dell_anchor;
import databases.DBConnector;
import dell_targets.Dell_BaseStation;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.*;
src/dell_anchor/BaseStationSyncConfigPanel.java
@@ -1,5 +1,7 @@
package dell_anchor;
import databases.DBConnector;
import dell_targets.Dell_BaseStation;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.*;
src/dell_anchor/Dell_BaseStation.java
ÎļþÒÑɾ³ý
src/dell_system/MessageViewPanel.java
@@ -7,13 +7,11 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import dell_targets.Dell_MessageType;
import dell_targets.Dell_tag;
import publicsWay.Languages;
import udptcp.UDPPortAReceiver;
import udptcp.UDPPortBReceiver;
@@ -28,7 +26,7 @@
    // UI组件声明
    private JButton btnStart, btnPause, btnClear, btnSend; // æŽ§åˆ¶æŒ‰é’®ï¼šå¼€å§‹ã€æš‚停、清除、发送
    private static JComboBox<String> cbDataType; // ä¸‹æ‹‰æ¡†ï¼šæ•°æ®ç±»åž‹ã€åè®®ã€è®¾å¤‡ID
    private JComboBox<String> cbProtocol;
    private static JComboBox<String> cbProtocol;
    private static JComboBox<String> cbDeviceId;
    private static JComboBox<String> cbRemoteDevice; // è¿œç¨‹è®¾å¤‡ä¸‹æ‹‰æ¡†
    private static JCheckBox chkAutoSave; // å¤é€‰æ¡†ï¼šè‡ªåŠ¨ä¿å­˜ã€æ˜¾ç¤ºæ¥æºã€åå…­è¿›åˆ¶æ˜¾ç¤ºã€ASCII显示
@@ -46,15 +44,16 @@
    // çŠ¶æ€å˜é‡
    private static boolean isCapturing = false; // æ˜¯å¦æ­£åœ¨æ•获数据的标志
    // å­˜å‚¨æ‰€æœ‰è¿œç¨‹è®¾å¤‡(IP:端口)
    private static Set<String> remoteDevices = new HashSet<>();
       // ä¿®æ”¹ä¸ºMap存储设备及其本地端口
    // ä¿®æ”¹ä¸ºMap存储设备及其本地端口
    private static Map<String, Integer> remoteDeviceLocalPortMap = new HashMap<>();
    // æž„造函数
    public MessageViewPanel(ResourceBundle messages) {       
        this.messages = messages; // åˆå§‹åŒ–消息资源包        
        initializeUI(); // åˆå§‹åŒ–用户界面
    }
    public void addNotify() {
        super.addNotify();
@@ -66,7 +65,7 @@
                public void windowClosing(WindowEvent e) {
                    isWindowVisible = false;
                }
                @Override
                public void windowClosed(WindowEvent e) {
                    isWindowVisible = false;
@@ -199,22 +198,22 @@
        // åˆ›å»ºå‘送选项面板
        JPanel sendOptionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
        sendOptionsPanel.setBackground(new Color(240, 245, 249));
        // åˆ›å»ºå•选按钮组
        ButtonGroup sendFormatGroup = new ButtonGroup();
        // åˆ›å»ºHEX发送单选按钮
        rdoSendHex = createStyledRadioButton(messages.getString("MESSAGE_VIEW_SEND_HEX"));
        // åˆ›å»ºASCII发送单选按钮
        rdoSendAscii = createStyledRadioButton(messages.getString("MESSAGE_VIEW_SEND_ASCII"));
        // å°†å•选按钮添加到按钮组
        sendFormatGroup.add(rdoSendHex);
        sendFormatGroup.add(rdoSendAscii);
        // é»˜è®¤é€‰ä¸­ASCII发送
        rdoSendAscii.setSelected(true);
        // å›žè½¦æ¢è¡Œå¤é€‰æ¡†
        chkAppendNewline = createStyledCheckbox(messages.getString("MESSAGE_VIEW_APPEND_NEWLINE"));
@@ -266,18 +265,18 @@
        checkBox.setForeground(new Color(70, 70, 70)); // è®¾ç½®å‰æ™¯è‰²
        return checkBox;
    }
    // åˆ›å»ºå¸¦æ ·å¼çš„单选按钮
    private JRadioButton createStyledRadioButton(String text) {
        JRadioButton radioButton = new JRadioButton(text); // åˆ›å»ºå•选按钮
        radioButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // è®¾ç½®å­—体
        radioButton.setBackground(new Color(240, 245, 249)); // è®¾ç½®èƒŒæ™¯è‰²
        radioButton.setForeground(new Color(70, 70, 70)); // è®¾ç½®å‰æ™¯è‰²
        // ç¾ŽåŒ–选中效果
        radioButton.setIcon(new RadioButtonIcon(false));
        radioButton.setSelectedIcon(new RadioButtonIcon(true));
        // æ·»åŠ é¼ æ ‡æ‚¬åœæ•ˆæžœ
        radioButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
@@ -287,7 +286,7 @@
                radioButton.setForeground(new Color(70, 70, 70));
            }
        });
        return radioButton;
    }
@@ -295,21 +294,21 @@
    private static class RadioButtonIcon implements Icon {
        private static final int SIZE = 14;
        private final boolean selected;
        public RadioButtonIcon(boolean selected) {
            this.selected = selected;
        }
        @Override
        public void paintIcon(Component c, Graphics g, int x, int y) {
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            if (selected) {
                // é€‰ä¸­çŠ¶æ€ - è“è‰²å¡«å……
                g2d.setColor(new Color(70, 130, 180));
                g2d.fillOval(x, y, SIZE, SIZE);
                // å†…圆 - ç™½è‰²
                g2d.setColor(Color.WHITE);
                g2d.fillOval(x + SIZE/4, y + SIZE/4, SIZE/2, SIZE/2);
@@ -318,39 +317,31 @@
                g2d.setColor(new Color(150, 150, 150));
                g2d.drawOval(x, y, SIZE-1, SIZE-1);
            }
            g2d.dispose();
        }
        @Override
        public int getIconWidth() {
            return SIZE;
        }
        @Override
        public int getIconHeight() {
            return SIZE;
        }
    }
    // åŠ è½½è®¾å¤‡ID列表
    private void loadDeviceIds() {
        // ä»ŽDell_tag类获取所有设备ID
        List<String>  tags = Dell_tag.getAlldeviceIds();
        // éåŽ†è®¾å¤‡ID列表并添加到下拉框
        for (String tag : tags) {
            cbDeviceId.addItem(tag);
        }
    }
    // åŠ è½½æ•°æ®ç±»åž‹
    private void loadtyps() {
        // ä»ŽDell_tag类获取所有设备ID
        List<String>  typs = Dell_MessageType.getAllMessageTypes();
        // éåŽ†è®¾å¤‡ID列表并添加到下拉框
        for (String typ : typs) {
            cbDataType.addItem(typ);
        }
        cbDataType.removeAllItems();
        // æ·»åŠ å›½é™…åŒ–é€‰é¡¹
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_ALL_TYPES"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_UDP_PORT_A"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_UDP_PORT_B"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_TCP_PORT"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_MQTT_PORT"));
    }
    // è®¾ç½®æŒ‰é’®åŠ¨ä½œ
@@ -385,21 +376,23 @@
    // å‘送数据到远程设备
    private void sendData() {
        // ä½¿ç”¨æ–°æ–¹æ³•获取当前资源包
        ResourceBundle currentMessages = Languages.getCurrentMessages();
        String selectedDevice = (String) cbRemoteDevice.getSelectedItem();
        if (selectedDevice == null || selectedDevice.equals(messages.getString("MESSAGE_VIEW_ALL_DEVICES"))) {
        if (selectedDevice == null || selectedDevice.equals(currentMessages.getString("MESSAGE_VIEW_ALL_DEVICES"))) {
            JOptionPane.showMessageDialog(this, 
                    messages.getString("MESSAGE_VIEW_SELECT_DEVICE"),
                    messages.getString("WARNING"),
                    currentMessages.getString("MESSAGE_VIEW_SELECT_DEVICE"),
                    currentMessages.getString("WARNING"),
                    JOptionPane.WARNING_MESSAGE);
            return;
        }
        // èŽ·å–æœ¬åœ°ç«¯å£
        Integer localPort = remoteDeviceLocalPortMap.get(selectedDevice);
        if (localPort == null) {
            JOptionPane.showMessageDialog(this, 
                    "无法确定设备的接收端口",
                    messages.getString("ERROR"),
                    currentMessages.getString("ERROR"),
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
@@ -408,8 +401,8 @@
        String[] parts = selectedDevice.split(":");
        if (parts.length != 2) {
            JOptionPane.showMessageDialog(this, 
                    messages.getString("MESSAGE_VIEW_INVALID_DEVICE"),
                    messages.getString("ERROR"),
                    currentMessages.getString("MESSAGE_VIEW_INVALID_DEVICE"),
                    currentMessages.getString("ERROR"),
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
@@ -420,8 +413,8 @@
            port = Integer.parseInt(parts[1]);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this, 
                    messages.getString("MESSAGE_VIEW_INVALID_PORT"),
                    messages.getString("ERROR"),
                    currentMessages.getString("MESSAGE_VIEW_INVALID_PORT"),
                    currentMessages.getString("ERROR"),
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
@@ -429,8 +422,8 @@
        String dataToSend = txtSendData.getText();
        if (dataToSend.isEmpty()) {
            JOptionPane.showMessageDialog(this, 
                    messages.getString("MESSAGE_VIEW_EMPTY_DATA"),
                    messages.getString("WARNING"),
                    currentMessages.getString("MESSAGE_VIEW_EMPTY_DATA"),
                    currentMessages.getString("WARNING"),
                    JOptionPane.WARNING_MESSAGE);
            return;
        }
@@ -458,7 +451,7 @@
                // ä¼ å…¥æ˜¯å¦HEX发送的标志
                UDPPortBReceiver.sendData(ip, port, dataToSend, true);
            }
        } else {
            // ASCII格式发送
            displayData.append(dataToSend);
@@ -477,7 +470,7 @@
            txtDataView.setCaretPosition(txtDataView.getDocument().getLength());
        });
    }
    // ä¿®æ”¹æ·»åŠ è¿œç¨‹è®¾å¤‡æ–¹æ³•
    // åœ¨MessageViewPanel类中修改addRemoteDevice方法
    public static void addRemoteDevice(String ip, int port, int localPort) {
@@ -494,65 +487,133 @@
                        break;
                    }
                }
                if (!exists) {
                    cbRemoteDevice.addItem(device);
                }
            });
        }
    }
    // æ•获数据的核心方法
    public  static void captureData(String rawData, String ip, int port, int localPort, String timestamp) {
         // æ£€æŸ¥çª—口是否可见
    // ä¿®æ”¹é€šç”¨æ•°æ®æ˜¾ç¤ºæ–¹æ³•
    public static void showData(String rawData, String ip, int port, int localPort, String deviceId) {
        if (!isWindowVisible) {
            return;
        }
        String formattedData = formatData(rawData,ip,port,timestamp); // æ ¼å¼åŒ–数据
        if(isCapturing) {
        // èŽ·å–å½“å‰é€‰æ‹©
        String selectedDataType = (String) cbDataType.getSelectedItem();
        String selectedProtocol = (String) cbProtocol.getSelectedItem();
        String selectedDeviceId = (String) cbDeviceId.getSelectedItem();
        // ä½¿ç”¨æ–°æ–¹æ³•获取当前资源包
        ResourceBundle messages = Languages.getCurrentMessages();
        String allTypes = messages.getString("MESSAGE_VIEW_ALL_TYPES");
        String allProtocols = messages.getString("MESSAGE_VIEW_ALL_PROTOCOLS");
        String allDevices = messages.getString("MESSAGE_VIEW_ALL_DEVICES");
        String udpPortA = messages.getString("MESSAGE_VIEW_UDP_PORT_A");
        String udpPortB = messages.getString("MESSAGE_VIEW_UDP_PORT_B");
        String udpProtocol = "UDP"; // ç›´æŽ¥ä½¿ç”¨åè®®åç§°
        // æ£€æŸ¥æ•°æ®ç±»åž‹è¿‡æ»¤
        boolean dataTypeMatch = selectedDataType.equals(allTypes) ||
                (localPort == UDPPortAReceiver.PORT && selectedDataType.equals(udpPortA)) ||
                (localPort == UDPPortBReceiver.PORT && selectedDataType.equals(udpPortB));
        // æ£€æŸ¥åè®®è¿‡æ»¤
        boolean protocolMatch = selectedProtocol.equals(allProtocols) ||
                (localPort == UDPPortAReceiver.PORT && selectedProtocol.equals(udpProtocol)) ||
                (localPort == UDPPortBReceiver.PORT && selectedProtocol.equals(udpProtocol));
        // æ£€æŸ¥è®¾å¤‡ID过滤
        boolean deviceIdMatch=false;
        if("1".equals(deviceId)) {
            deviceIdMatch=true;
        }else {
            deviceIdMatch = selectedDeviceId.equals(allDevices) ||
                    (deviceId != null && deviceId.equals(selectedDeviceId));
        }
        // åªæœ‰å½“所有条件都匹配时才显示
        if (!(dataTypeMatch && protocolMatch && deviceIdMatch)) {
            return;
        }
        // ç”Ÿæˆæ¯«ç§’级时间戳
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        String timestamp = sdf.format(new Date());
        String formattedData = formatData(rawData, ip, port, timestamp);
        if (isCapturing) {
            // æ·»åŠ è¿œç¨‹è®¾å¤‡åˆ°ä¸‹æ‹‰æ¡†
            addRemoteDevice(ip, port, localPort); // ç¡®ä¿è°ƒç”¨å¸¦ç«¯å£å‚数的方法
            // èŽ·å–å½“å‰é€‰æ‹©çš„è®¾å¤‡ID和数据类型
            String deviceId = cbDeviceId.getSelectedItem().toString();
            String dataType = cbDataType.getSelectedItem().toString();
            addRemoteDevice(ip, port, localPort);
            // åœ¨EDT线程中更新UI
            SwingUtilities.invokeLater(() -> {
                txtDataView.append(formattedData + "\n"); // æ·»åŠ æ•°æ®åˆ°æ–‡æœ¬åŒºåŸŸ
                // è‡ªåŠ¨æ»šåŠ¨åˆ°åº•éƒ¨
                txtDataView.append(formattedData + "\n");
                txtDataView.setCaretPosition(txtDataView.getDocument().getLength());
            });
        }
        // å¦‚果启用了自动保存,则保存到文件
        if (chkAutoSave.isSelected()) {
            saveToFile(formattedData);
        }
        }
    }
    // æ ¼å¼åŒ–数据显示
    private static String formatData(String rawData, String ip,  int port,String timestamp) {
        StringBuilder formatted = new StringBuilder(); // ä½¿ç”¨StringBuilder构建格式化字符串
        // å¦‚果启用了显示来源,添加时间戳和源地址
    // ä¿®æ”¹æ ¼å¼æ˜¾ç¤ºæ–¹æ³•,支持混合格式
    private static String formatData(String rawData, String ip, int port, String timestamp) {
        StringBuilder formatted = new StringBuilder();
        // ä½¿ç”¨æ–°æ–¹æ³•获取当前资源包
        ResourceBundle messages = Languages.getCurrentMessages();
        // æ˜¾ç¤ºæ¥æºä¿¡æ¯
        if (chkShowSource.isSelected()) {
            formatted.append("["+timestamp+";"+ip+":"+port+"]"); // æ·»åŠ æ¨¡æ‹Ÿæºåœ°å€
            formatted.append("[")
            .append(timestamp)
            .append("][")
            .append(ip)
            .append(":")
            .append(port)
            .append("] ");
        }
        // æ ¹æ®æ˜¾ç¤ºé€‰é¡¹æ ¼å¼åŒ–数据
        if (chkHexDisplay.isSelected() && chkAsciiDisplay.isSelected()) {
            // åŒæ—¶æ˜¾ç¤ºåå…­è¿›åˆ¶å’ŒASCII
            formatted.append(toHexString(rawData)) // æ·»åŠ åå…­è¿›åˆ¶è¡¨ç¤º
            .append(" | ") // æ·»åŠ åˆ†éš”ç¬¦
            .append(rawData); // æ·»åŠ åŽŸå§‹ASCII数据
            formatted.append(formatHexString(rawData))
            .append(" | ")
            .append(hexToAscii(rawData))
            .append(" [")
            .append(messages.getString("MESSAGE_VIEW_MIXED_FORMAT"))
            .append("]");
        } else if (chkHexDisplay.isSelected()) {
            // ä»…显示十六进制
            formatted.append(toHexString(rawData));
            formatted.append(formatHexString(rawData))
            .append(" [")
            .append(messages.getString("MESSAGE_VIEW_HEX_FORMAT"))
            .append("]");
        } else if (chkAsciiDisplay.isSelected()) {
            formatted.append(hexToAscii(rawData))
            .append(" [")
            .append(messages.getString("MESSAGE_VIEW_ASCII_FORMAT"))
            .append("]");
        } else {
            // é»˜è®¤æ˜¾ç¤ºåŽŸå§‹ASCII数据
            formatted.append(rawData);
            formatted.append(hexToAscii(rawData));
        }
        return formatted.toString(); // è¿”回格式化后的字符串
        return formatted.toString();
    }
    // ä¿®æ”¹è®¾å¤‡ID加载方法
    private void loadDeviceIds() {
        cbDeviceId.removeAllItems();
        cbDeviceId.addItem(messages.getString("MESSAGE_VIEW_ALL_DEVICES"));
        List<String> tags = Dell_tag.getAlldeviceIds();
        for (String tag : tags) {
            cbDeviceId.addItem(tag);
        }
    }
    // å°†å­—符串转换为十六进制表示
@@ -563,7 +624,25 @@
        }
        return hex.toString().trim(); // è¿”回并去除末尾空格
    }
    // æ ¼å¼åŒ–十六进制字符串(每两个字符加空格)
    private static String formatHexString(String hex) {
        StringBuilder formatted = new StringBuilder();
        for (int i = 0; i < hex.length(); i += 2) {
            if (i > 0) formatted.append(" ");
            formatted.append(hex.substring(i, Math.min(i + 2, hex.length())));
        }
        return formatted.toString();
    }
    // å°†åå…­è¿›åˆ¶å­—符串转换为ASCII
    private static String hexToAscii(String hexStr) {
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < hexStr.length(); i += 2) {
            String str = hexStr.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }
    // ä¿å­˜æ•°æ®åˆ°æ–‡ä»¶
    private static void saveToFile(String data) {
        SimpleDateFormat fileFormat = new SimpleDateFormat("yyyyMMdd"); // æ–‡ä»¶æ—¥æœŸæ ¼å¼
src/dell_targets/Dell_BaseStation.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,180 @@
package dell_targets;
import databases.DBConnector;
import targets.LocationBaseStation;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class Dell_BaseStation {
    public static List<LocationBaseStation> baseStations;
    private static ConcurrentHashMap<String, LocationBaseStation> baseStationMap; // ä»¥åŸºç«™ID为键的映射
    public static List<LocationBaseStation> getBaseStations() throws SQLException {
        baseStations = new ArrayList<>();
        baseStationMap = new ConcurrentHashMap<>(); // ä¿®å¤ï¼šåˆå§‹åŒ–映射
        ResultSet rs = DBConnector.queryTableData("location_base_station");
         if (rs == null) {
                // è¯´æ˜Žåº•层拿不到数据,直接抛异常或打印日志
                throw new SQLException("DBConnector.queryTableData returned null, "
                                     + "please check database connection & SQL.");
            }
        while (rs.next()) {
            LocationBaseStation baseStation = new LocationBaseStation();
            baseStation.setId((int) rs.getLong("id"));
            baseStation.setCode(rs.getString("base_station_id"));
            baseStation.setStatus(rs.getString("statuss"));
            baseStation.setXCoordinate(rs.getString("x_coordinate"));
            baseStation.setYCoordinate(rs.getString("y_coordinate"));
            baseStation.setZCoordinate(rs.getString("z_coordinate"));
            baseStation.setLongitude(rs.getString("longitude"));
            baseStation.setLatitude(rs.getString("latitude"));
            baseStation.setElevation(rs.getString("elevation"));
            baseStation.setHorizontalAngle(rs.getString("horizontal_angle"));
            baseStation.setPitchAngle(rs.getString("pitch_angle"));
            baseStation.setFloor(rs.getString("located_layer"));
            baseStation.setGroup(rs.getString("located_group"));
            baseStation.setRange(rs.getString("range"));
            baseStation.setSyncStatus(rs.getString("sync_status"));
            baseStation.setSyncType(rs.getString("sync_type"));
            baseStation.setSyncBaseStation(rs.getString("sync_base_station"));
            baseStation.setIpAddress(rs.getString("ip_address"));
            baseStation.setPort(rs.getString("ports"));
            baseStation.setFirmwareVersion(rs.getString("firmware_version"));
            baseStation.setJudgmentDistance(rs.getString("judgment_distance"));
            baseStation.setBattery(rs.getString("battery"));
            baseStation.setCalibrationDistance(rs.getString("calibration_distance"));
            baseStation.setSignalSendTime(rs.getString("signal_transmission_time"));
            baseStation.setCommunicationGroup(rs.getString("communication_group"));
            baseStation.setIconAddress(rs.getString("icon_url"));
            baseStation.setOnlineTime(rs.getString("online_time"));
            baseStation.setOfflineTime(rs.getString("offline_time"));
            baseStation.setOfflineDuration(rs.getString("offline_duration"));
            baseStation.setAlgorithmDimension(rs.getString("algorithm_dimension"));
            baseStation.setBottomHeight(rs.getString("located_bottom_height"));
            baseStation.setTopHeight(rs.getString("located_top_height"));
            baseStation.setIsBarometricStation(rs.getString("barometric_base_station"));
            baseStation.setSwitchDistance(rs.getString("handover_distance"));
            baseStation.setMaxDistance(rs.getString("maximum_distance"));
            baseStation.setOutputAllRanging(rs.getString("output_all_base_station_ranging"));
            baseStation.setCompany(rs.getString("company"));
            baseStation.setCrossLayerHeight(rs.getString("cross_layer_height"));
            baseStation.setCrossLayerGroup(rs.getString("cross_layer_group"));
            baseStation.setRequiredDistance(rs.getString("must_pass_distance"));
            baseStation.setAdjacent1(rs.getString("adjacent1"));
            baseStation.setAdjacent2(rs.getString("adjacent2"));
            baseStation.setAdjacent3(rs.getString("adjacent3"));
            baseStation.setAdjacent4(rs.getString("adjacent4"));
            baseStation.setAdjacent5(rs.getString("adjacent5"));
            baseStation.setAdjacent6(rs.getString("adjacent6"));
            baseStation.setAdjacent7(rs.getString("adjacent7"));
            baseStation.setAdjacent8(rs.getString("adjacent8"));
            baseStation.setAdjacent9(rs.getString("adjacent9"));
            baseStation.setAdjacent10(rs.getString("adjacent10"));
            baseStation.setReserved1(rs.getString("reserved1"));
            baseStation.setReserved2(rs.getString("reserved2"));
            baseStation.setReserved3(rs.getString("reserved3"));
            baseStation.setReserved4(rs.getString("reserved4"));
            baseStation.setReserved5(rs.getString("reserved5"));
            baseStation.setReserved6(rs.getString("reserved6"));
            baseStation.setReserved7(rs.getString("reserved7"));
            baseStation.setReserved8(rs.getString("reserved8"));
            baseStation.setReserved9(rs.getString("reserved9"));
            baseStation.setReserved10(rs.getString("reserved10"));
            baseStation.setReserved11(rs.getString("reserved11"));
            baseStation.setReserved12(rs.getString("reserved12"));
            baseStation.setReserved13(rs.getString("reserved13"));
            baseStation.setReserved14(rs.getString("reserved14"));
            baseStation.setReserved15(rs.getString("reserved15"));
            baseStation.setReserved16(rs.getString("reserved16"));
            baseStations.add(baseStation);
            baseStationMap.put(baseStation.getCode(), baseStation); // ä»¥åŸºç«™ID为键存入映射
        }
        return baseStations;
    }
    /**
     * æ ¹æ®åŸºç«™ID高效修改属性值
     * @param baseStationId åŸºç«™ID(base_station_id)
     * @param propertyName å±žæ€§åï¼ˆéœ€ä¸Žsetter方法匹配)
     * @param value æ–°å±žæ€§å€¼
     */
    public static void updateBaseStationProperty(String baseStationId, String propertyName, String value) {
        LocationBaseStation station = baseStationMap.get(baseStationId);
        if (station == null) return; // åŸºç«™ä¸å­˜åœ¨åˆ™å¿½ç•¥
        // æ ¹æ®å±žæ€§åè°ƒç”¨å¯¹åº”setter(高效匹配高频属性)
        switch (propertyName) {
        case "status":
            station.setStatus(value); break; // æ›´æ–°çŠ¶æ€
        case "battery":
            station.setBattery(value); break; // æ›´æ–°ç”µé‡
        case "ipAddress":
            station.setIpAddress(value); break; // æ›´æ–°IP地址
        case "onlineTime":
            station.setOnlineTime(value); break; // æ›´æ–°ä¸Šçº¿æ—¶é—´
        case "offlineTime":
            station.setOfflineTime(value); break; // æ›´æ–°ç¦»çº¿æ—¶é—´
        case "offlineDuration":
            station.setOfflineDuration(value); break; // æ›´æ–°ç¦»çº¿æ—¶é•¿
        case "syncStatus":
            station.setSyncStatus(value); break; //同步状态
        case "barometerReading":
            station.setBarometerReading(value); break; //同步状态
            // æ·»åŠ å…¶ä»–é«˜é¢‘å±žæ€§...
        default:
            throw new IllegalArgumentException("不支持属性: " + propertyName);
        }
    }
    /**
     * æ ¹æ®åŸºç«™ID获取基站对象(高效访问)
     * @param baseStationId åŸºç«™ID
     * @return åŸºç«™å¯¹è±¡ï¼ˆä¸å­˜åœ¨åˆ™è¿”回null)
     */
    public static LocationBaseStation getBaseStationById(String baseStationId) {
        return baseStationMap.get(baseStationId); // O(1)复杂度直接获取
    }
    /**
     * èŽ·å–æ‰€æœ‰åœ¨çº¿çŠ¶æ€(onlineStatus=1)的设备(高效内存操作)
     * @return ä¸å¯ä¿®æ”¹çš„baseStationMap集合(避免外部修改缓存)
     */
    public static List<LocationBaseStation> getOnlineBaseStations() {
        if (baseStationMap == null || baseStationMap.isEmpty()) {
            return Collections.emptyList(); // ç¼“存为空时返回空集合
        }
        List<LocationBaseStation> BaseStation = new ArrayList<>();
        for (LocationBaseStation base : baseStationMap.values()) {
            if ("1".equals(base.getStatus())) { // å­—符串比较避免NPE
                BaseStation.add(base);
            }
        }
        return Collections.unmodifiableList(BaseStation); // è¿”回不可变集合
    }
    /**
     * å¿«é€ŸèŽ·å–LocationTag对象的总数(使用内存缓存提高性能)
     * @return LocationTag对象的总数
     */
    public static int getLocationBaseCount() {
        if (baseStationMap == null) {
            synchronized (LocationBaseStation.class) {
                if (baseStationMap == null) {
                    try {
                        getBaseStations(); // åˆå§‹åŒ–缓存
                    } catch (SQLException e) {
                        e.printStackTrace();
                        return 0; // åˆå§‹åŒ–失败返回0
                    }
                }
            }
        }
        return baseStationMap.size();
    }
}
src/dell_targets/Dell_SystemConfiguration.java
@@ -14,6 +14,9 @@
    static List<SystemConfiguration> configs;
    public static boolean xytognssOpen=false;
    public static boolean gnsstoxyOpen=false;
    public static String language="0";
    public static int hexport=8234;
    public static int ascallport=7000;
    // èŽ·å–ç³»ç»Ÿé…ç½®åˆ—è¡¨
    public static List<SystemConfiguration> getSystemConfigurations()  {
        // åˆ›å»ºé…ç½®å¯¹è±¡åˆ—表
@@ -39,9 +42,14 @@
                // æ•°æ®åº“密码
                config.setDatabasePassword(rs.getString("database_password"));
                // HEX数据UDP接收端口
                config.setHexDataUdpReceivePort(rs.getString("hex_data_udp_receive_port"));
                String hexp=rs.getString("hex_data_udp_receive_port");
                hexport=Integer.parseInt(hexp);
                config.setHexDataUdpReceivePort(hexp);
                String ascll=rs.getString("ascii_data_udp_receive_port");
                ascallport=Integer.parseInt(ascll);;
                // ASCII数据UDP接收端口
                config.setAsciiDataUdpReceivePort(rs.getString("ascii_data_udp_receive_port"));
                config.setAsciiDataUdpReceivePort(ascll);
                // TCP数据接收端口1
                config.setTcpDataReceivePort1(rs.getString("tcp_data_receive_port1"));
                // TCP数据接收端口2
@@ -158,8 +166,10 @@
                config.setRealTimeTrajectoryDuration(rs.getString("real_time_trajectory_duration"));
                // å®žæ—¶è½¨è¿¹é¢œè‰²
                config.setRealTimeTrajectoryColor(rs.getString("real_time_trajectory_color"));
                String langua=rs.getString("system_language");
                language=langua;
                // ç³»ç»Ÿè¯­è¨€
                config.setSystemLanguage(rs.getString("system_language"));
                config.setSystemLanguage(langua);
                // JNA日志开关
                config.setJnaLogSwitch(rs.getString("jna_log_switch"));
                // æ—¶é—´ç‰‡åˆ†é…æ–¹å¼
src/dell_targets/Dell_tag.java
@@ -4,12 +4,21 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class Dell_tag {
    static List<LocationTag> locationTags;
    public static List<LocationTag> locationTags;
    private static ConcurrentHashMap<String, LocationTag> tagMap; // è®¾å¤‡ID->标签对象的映射
    public static List<LocationTag> getlocationTags() throws SQLException{
        List<LocationTag> locationTags = new ArrayList<>();
        List<LocationTag> locationTags = new ArrayList<>();
        tagMap = new ConcurrentHashMap<>(); // åˆå§‹åŒ–映射
        ResultSet rs =DBConnector.queryTableData("location_tag");
         if (rs == null) {
                // è¯´æ˜Žåº•层拿不到数据,直接抛异常或打印日志
                throw new SQLException("DBConnector.queryTableData returned null, "
                                     + "please check database connection & SQL.");
            }
        while (rs.next()) {
            LocationTag locationTag = new LocationTag();
            locationTag.setId((int) rs.getLong("id"));            
@@ -98,6 +107,7 @@
            locationTag.setIpAddress(rs.getString("ipAddress"));
            locationTag.setIpPort(rs.getString("Interaction_Type"));
            locationTags.add(locationTag);
            tagMap.put(locationTag.getDeviceNumber(), locationTag); // æ·»åŠ åˆ°æ˜ å°„
        }
        return locationTags;
    }
@@ -119,6 +129,117 @@
        DBConnector.executeUpdate(sql, deviceId);
    }
    
    /**
     * æ ¹æ®è®¾å¤‡ID高效修改属性值
     * @param deviceId è®¾å¤‡ID(device_id)
     * @param propertyName å±žæ€§åï¼ˆéœ€ä¸Žsetter方法匹配)
     * @param value æ–°å±žæ€§å€¼
     */
    public static void updateLocationTagProperty(String deviceId, String propertyName, String value) {
        LocationTag tag = tagMap.get(deviceId);
        if (tag == null) return; // æ ‡ç­¾ä¸å­˜åœ¨åˆ™å¿½ç•¥
        // æ ¹æ®å±žæ€§åè°ƒç”¨å¯¹åº”setter
        switch (propertyName) {
            case "id": tag.setId(Integer.parseInt(value)); break;
            case "deviceNumber": tag.setDeviceNumber(value); break;
            case "deviceName": tag.setDeviceName(value); break;
            case "deviceVersion": tag.setDeviceVersion(value); break;
            case "deviceCardNumber": tag.setDeviceCardNumber(value); break;
            case "deviceType": tag.setDeviceType(value); break;
            case "team": tag.setTeam(value); break;
            case "group": tag.setGroup(value); break;
            case "department": tag.setDepartment(value); break;
            case "iconAddress": tag.setIconAddress(value); break;
            case "gender": tag.setGender(value); break;
            case "ethnicity": tag.setEthnicity(value); break;
            case "communicationAddress": tag.setCommunicationAddress(value); break;
            case "boundPhone": tag.setBoundPhone(value); break;
            case "idNumber": tag.setIdNumber(value); break;
            case "position": tag.setPosition(value); break;
            case "boundPlateNumber": tag.setBoundPlateNumber(value); break;
            case "faceAddress": tag.setFaceAddress(value); break;
            case "heartRate": tag.setHeartRate(value); break;
            case "bloodPressure": tag.setBloodPressure(value); break;
            case "bloodOxygen": tag.setBloodOxygen(value); break;
            case "temperature": tag.setTemperature(value); break;
            case "sosStatus": tag.setSosStatus(value); break;
            case "motionStatus": tag.setMotionStatus(value); break;
            case "onlineStatus": tag.setOnlineStatus(value); break;
            case "searchStatus": tag.setSearchStatus(value); break;
            case "batteryStatus": tag.setBatteryStatus(value); break;
            case "deviceBattery": tag.setDeviceBattery(value); break;
            case "removalStatus": tag.setRemovalStatus(value); break;
            case "collisionStatus": tag.setCollisionStatus(value); break;
            case "elevationStatus": tag.setElevationStatus(value); break;
            case "gatheringCount": tag.setGatheringCount(value); break;
            case "proximityAlarm": tag.setProximityAlarm(value); break;
            case "area": tag.setArea(value); break;
            case "xCoordinate": tag.setXCoordinate(value); break;
            case "yCoordinate": tag.setYCoordinate(value); break;
            case "zCoordinate": tag.setZCoordinate(value); break;
            case "floor": tag.setFloor(value); break;
            case "speed": tag.setSpeed(value); break;
            case "locationSource": tag.setLocationSource(value); break;
            case "lastUwbSignalTime": tag.setLastUwbSignalTime(value); break;
            case "lastSatelliteSignalTime": tag.setLastSatelliteSignalTime(value); break;
            case "uwbTimeSlot": tag.setUwbTimeSlot(value); break;
            case "latestRangingSeq": tag.setLatestRangingSeq(value); break;
            case "latestRangingBaseId": tag.setLatestRangingBaseId(value); break;
            case "latestRangingDistance": tag.setLatestRangingDistance(value); break;
            case "latestRangingBaseCount": tag.setLatestRangingBaseCount(value); break;
            case "latestRangingSignalStrength": tag.setLatestRangingSignalStrength(value); break;
            case "utcTime": tag.setUtcTime(value); break;
            case "latitude": tag.setLatitude(value); break;
            case "longitude": tag.setLongitude(value); break;
            case "satelliteQuality": tag.setSatelliteQuality(value); break;
            case "hdop": tag.setHdop(value); break;
            case "satelliteCount": tag.setSatelliteCount(value); break;
            case "altitude": tag.setAltitude(value); break;
            case "differentialTime": tag.setDifferentialTime(value); break;
            case "geoidHeight": tag.setGeoidHeight(value); break;
            case "satelliteSpeed": tag.setSatelliteSpeed(value); break;
            case "lastBarometricValue": tag.setLastBarometricValue(value); break;
            case "recentCoordinates": tag.setRecentCoordinates(value); break;
            case "recentBarometricValues": tag.setRecentBarometricValues(value); break;
            case "offlineTime": tag.setOfflineTime(value); break;
            case "onlineTime": tag.setOnlineTime(value); break;
            case "offlineDuration": tag.setOfflineDuration(value); break;
            case "onlineDuration": tag.setOnlineDuration(value); break;
            case "motionlessStartTime": tag.setMotionlessStartTime(value); break;
            case "motionlessEndTime": tag.setMotionlessEndTime(value); break;
            case "motionlessDuration": tag.setMotionlessDuration(value); break;
            case "validSatelliteSignal": tag.setValidSatelliteSignal(value); break;
            case "company": tag.setCompany(value); break;
            case "sleepTime": tag.setSleepTime(value); break;
            case "vibrationTime": tag.setVibrationTime(value); break;
            case "frequency": tag.setFrequency(value); break;
            case "motionlessTime": tag.setMotionlessTime(value); break;
            case "accelerationValue": tag.setAccelerationValue(value); break;
            case "imuTime": tag.setImuTime(value); break;
            case "reserved1": tag.setReserved1(value); break;
            case "reserved2": tag.setReserved2(value); break;
            case "reserved3": tag.setReserved3(value); break;
            case "reserved4": tag.setReserved4(value); break;
            case "reserved5": tag.setReserved5(value); break;
            case "ipAndPort": tag.setIpAndPort(value); break;
            case "interactionType": tag.setInteractionType(value); break;
            case "ipAddress": tag.setIpAddress(value); break;
            case "ipPort": tag.setIpPort(value); break;
            default:
                throw new IllegalArgumentException("无效属性: " + propertyName);
        }
    }
    /**
     * æ ¹æ®è®¾å¤‡ID获取标签对象(高效访问)
     * @param deviceId è®¾å¤‡ID
     * @return æ ‡ç­¾å¯¹è±¡ï¼ˆä¸å­˜åœ¨è¿”回null)
     */
    public static LocationTag getTagByDeviceId(String deviceId) {
        return tagMap.get(deviceId);
    }
    //获取所有的tagid
    public static List<String> getAlldeviceIds() {
        List<String> types = new ArrayList<>();
@@ -134,4 +255,42 @@
        }
        return types;
    }
    /**
     * èŽ·å–æ‰€æœ‰åœ¨çº¿çŠ¶æ€(onlineStatus=1)的设备(高效内存操作)
     * @return ä¸å¯ä¿®æ”¹çš„LocationTag集合(避免外部修改缓存)
     */
    public static List<LocationTag> getOnlineLocationTags() {
        if (tagMap == null || tagMap.isEmpty()) {
            return Collections.emptyList(); // ç¼“存为空时返回空集合
        }
        List<LocationTag> onlineTags = new ArrayList<>();
        for (LocationTag tag : tagMap.values()) {
            if ("1".equals(tag.getOnlineStatus())) { // å­—符串比较避免NPE
                onlineTags.add(tag);
            }
        }
        return Collections.unmodifiableList(onlineTags); // è¿”回不可变集合
    }
    /**
     * å¿«é€ŸèŽ·å–LocationTag对象的总数(使用内存缓存提高性能)
     * @return LocationTag对象的总数
     */
    public static int getLocationTagCount() {
        if (tagMap == null) {
            synchronized (Dell_tag.class) {
                if (tagMap == null) {
                    try {
                        getlocationTags(); // åˆå§‹åŒ–缓存
                    } catch (SQLException e) {
                        e.printStackTrace();
                        return 0; // åˆå§‹åŒ–失败返回0
                    }
                }
            }
        }
        return tagMap.size();
    }
src/publicsWay/Languages.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
package publicsWay;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import dell_targets.Dell_SystemConfiguration;
public class Languages {
    // ä¿®æ”¹åŽçš„资源加载方法
    public static ResourceBundle getCurrentMessages() {
        // æ ¹æ®ç³»ç»Ÿé…ç½®å†³å®šè¯­è¨€
        Locale locale = "1".equals(Dell_SystemConfiguration.language) ?
                Locale.ENGLISH : Locale.SIMPLIFIED_CHINESE;
        // ä½¿ç”¨ä¸ŽWindows.java相同的加载逻辑
        String fileName = locale.equals(Locale.ENGLISH) ?
                "Messages_en.properties" : "Messages_zh.properties";
        File langFile = new File("systemfile/" + fileName);
        if (!langFile.exists()) {
            System.err.println("默认资源文件未找到: " + langFile.getAbsolutePath());
            try {
                return ResourceBundle.getBundle("systemfile.Messages", locale);
            } catch (Exception e) {
                System.err.println("后备资源加载失败: " + e.getMessage());
                // è¿”回空包避免崩溃
                return new ResourceBundle() {
                    @Override
                    protected Object handleGetObject(String key) {
                        return "!" + key + "!";
                    }
                    @Override
                    public Enumeration<String> getKeys() {
                        return java.util.Collections.emptyEnumeration();
                    }
                };
            }
        }
        try (InputStream inputStream = new FileInputStream(langFile)) {
            return new PropertyResourceBundle(inputStream);
        } catch (IOException e) {
            System.err.println("无法加载资源文件: " + e.getMessage());
            return ResourceBundle.getBundle("systemfile.Messages", locale);
        }
    }
}
src/publicsWay/UwbDataParser.java
@@ -130,11 +130,6 @@
            this.battery = battery;
            this.buttonStatus = buttonStatus;
        }
        @Override
        public String toString() {
            return String.format("包序: %d, æ ‡ç­¾: %s, åŸºç«™: %s, è·ç¦»: %d mm, ç”µé‡: %d%%, æŒ‰é”®: %d",
                                sequence, tagId, baseId, distance, battery, buttonStatus);
        }
    }
}
src/targets/LocationBaseStation.java
@@ -66,6 +66,7 @@
    private String reserved14; // å¤‡ç”¨ 14
    private String reserved15; // å¤‡ç”¨ 15
    private String reserved16; // å¤‡ç”¨ 16
    private String barometerReading;//气压计值
    // Getter and Setter methods
    public int getId() {
@@ -595,4 +596,36 @@
    public void setReserved16(String reserved16) {
        this.reserved16 = reserved16;
    }
    public String getxCoordinate() {
        return xCoordinate;
    }
    public String getyCoordinate() {
        return yCoordinate;
    }
    public String getzCoordinate() {
        return zCoordinate;
    }
    public String getBarometerReading() {
        return barometerReading;
    }
    public void setxCoordinate(String xCoordinate) {
        this.xCoordinate = xCoordinate;
    }
    public void setyCoordinate(String yCoordinate) {
        this.yCoordinate = yCoordinate;
    }
    public void setzCoordinate(String zCoordinate) {
        this.zCoordinate = zCoordinate;
    }
    public void setBarometerReading(String barometerReading) {
        this.barometerReading = barometerReading;
    }
}
src/udptcp/DellHexBaowen.java
ÎļþÒÑɾ³ý
src/udptcp/HexBaowen.java
ÎļþÒÑɾ³ý
src/udptcp/PacketParser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,163 @@
package udptcp;
import java.util.ArrayList;
import java.util.List;
// é‡å‘½åä¸ºPacketParser,表示数据包解析器
public class PacketParser {
    // æ·»åŠ åå…­è¿›åˆ¶å­—ç¬¦æ•°ç»„å¸¸é‡
    private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
    // ç¼“冲区字节数组
    private byte[] buffer = new byte[4096];
    // å½“前缓冲区有效数据长度
    private int bufferLength = 0;
    // è¿½åŠ æ–°æ•°æ®åˆ°ç¼“å†²åŒº
    public void appendData(byte[] newData, int length) {
        // æ£€æŸ¥ç¼“冲区是否足够
        if (bufferLength + length > buffer.length) {
            // åˆ›å»ºæ–°çš„æ›´å¤§ç¼“冲区
            byte[] newBuffer = new byte[bufferLength + length];
            // å¤åˆ¶åŽŸæœ‰æ•°æ®
            System.arraycopy(buffer, 0, newBuffer, 0, bufferLength);
            buffer = newBuffer;
        }
        // è¿½åŠ æ–°æ•°æ®
        System.arraycopy(newData, 0, buffer, bufferLength, length);
        // æ›´æ–°ç¼“冲区长度
        bufferLength += length;
    }
 // æ–°å¢žæ–¹æ³•:字节数组转十六进制字符串
    public static String bytesToHexString(byte[] bytes) {
        if (bytes == null) return "";
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }
    // è§£æžç¼“冲区中的所有完整数据包
    public List<DataPacket> parsePackets() {
        List<DataPacket> packets = new ArrayList<>();
        int index = 0;  // å½“前解析位置索引
        // éåŽ†ç¼“å†²åŒºæŸ¥æ‰¾å®Œæ•´æ•°æ®åŒ…
        while (index <= bufferLength - 4) { // ç¡®ä¿æœ‰è¶³å¤Ÿæ•°æ®æ£€æŸ¥åŒ…头
            // æ£€æŸ¥åŒ…头标识 0x55 0xAA
            if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) {
                // èŽ·å–åŒ…ç±»åž‹ï¼ˆç¬¬3字节)
                int packetType = buffer[index + 2] & 0xFF;
                // èŽ·å–æ•°æ®é•¿åº¦ï¼ˆç¬¬4字节)
                int dataLenField = buffer[index + 3] & 0xFF;
                // è®¡ç®—完整包长度(包头+数据+校验)
                int totalPacketLen = 4 + dataLenField + 2;  // å¢žåŠ 2字节校验位
                // æ£€æŸ¥æ˜¯å¦æœ‰è¶³å¤Ÿæ•°æ®æž„成完整包
                if (index + totalPacketLen > bufferLength) {
                    break; // æ•°æ®ä¸è¶³ï¼Œç­‰å¾…更多数据
                }
                // æå–完整数据包
                byte[] packetData = new byte[totalPacketLen];
                System.arraycopy(buffer, index, packetData, 0, totalPacketLen);
                // éªŒè¯æ ¡éªŒå’Œ
                if (verifyChecksum(packetData)) {
                    // è§£æžå•个数据包
                    DataPacket packet = parseSinglePacket(packetType, packetData);
                    if (packet != null) {
                        packets.add(packet); // æ·»åŠ åˆ°ç»“æžœåˆ—è¡¨
                    }
                    index += totalPacketLen; // ç§»åŠ¨åˆ°ä¸‹ä¸€ä¸ªåŒ…
                } else {
                    index++; // æ ¡éªŒå¤±è´¥ï¼Œè·³è¿‡å½“前字节
                }
            } else {
                index++; // éžåŒ…头标识,继续查找
            }
        }
        // æ¸…理已处理数据
        if (index > 0) {
            int remaining = bufferLength - index;
            if (remaining > 0) {
                // ç§»åŠ¨å‰©ä½™æ•°æ®åˆ°ç¼“å†²åŒºå¼€å¤´
                System.arraycopy(buffer, index, buffer, 0, remaining);
            }
            bufferLength = remaining; // æ›´æ–°ç¼“冲区长度
        }
        return packets;
    }
    // æ ¡éªŒæ•°æ®åŒ…完整性
    private boolean verifyChecksum(byte[] packet) {
        int len = packet.length;
        if (len < 4) return false; // é•¿åº¦ä¸è¶³
        int sum = 0;
        // è®¡ç®—从第3字节到倒数第3字节的和(跳过包头和校验位)
        for (int i = 2; i < len - 2; i++) {
            sum += packet[i] & 0xFF;
        }
        // å–反得到16位校验和
        sum = ~sum & 0xFFFF;
        // æå–包中的校验和(小端格式)
        int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF);
        // æ¯”较校验和
        return sum == receivedChecksum;
    }
    // è§£æžå•个数据包
    private DataPacket parseSinglePacket(int packetType, byte[] packet) {
        // åˆ›å»ºæ•°æ®åŒ…对象(包含包类型)
        return new DataPacket(packetType, packet);
    }
    // æ•°æ®åŒ…内部类
    public static class DataPacket {
        private final int packetType;  // åŒ…类型
        private final byte[] packet;//包数据
        public DataPacket(int packetType, byte[] packet) {
            this.packetType = packetType;
            this.packet = packet;
        }
        // èŽ·å–åŒ…ç±»åž‹
        public int getPacketType() {
            return packetType;
        }
        // åŒ…数据
        public byte[] getPacket() {
            return packet;
        }
    }
    // HEX字符串转字节数组
    public static byte[] hexStringToBytes(String hex) {
        // ç§»é™¤ç©ºæ ¼
        hex = hex.replaceAll("\\s", "");
        int len = hex.length();
        // åˆ›å»ºç»“果数组
        byte[] data = new byte[len / 2];
        // æ¯ä¸¤ä¸ªå­—符转换一个字节
        for (int i = 0; i < len; i += 2) {
            // é«˜ä½è½¬æ¢
            int high = Character.digit(hex.charAt(i), 16) << 4;
            // ä½Žä½è½¬æ¢
            int low = Character.digit(hex.charAt(i + 1), 16);
            data[i / 2] = (byte) (high | low);
        }
        return data;
    }
}
src/udptcp/PacketProcessingSystem.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@
package udptcp;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import dell55AAData.Dell55AA01Parser;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PacketProcessingSystem {
    // çº¿ç¨‹å®‰å…¨çš„æŠ¥æ–‡å­˜å‚¨é˜Ÿåˆ—(集合A)
    private static final ConcurrentLinkedQueue<HexPacket> packetQueue = new ConcurrentLinkedQueue<>();
    private static final AtomicBoolean isRunning = new AtomicBoolean(false);
    private static final ExecutorService parserExecutor = Executors.newSingleThreadExecutor();
    private static Thread parserThread;
    // æŠ¥æ–‡å­˜å‚¨ç»“æž„
    public static class HexPacket {
        public final String ip;
        public final int port;
        public final String hexData;
        public final long timestamp;
        public HexPacket(String ip, int port, String hexData, long timestamp) {
            this.ip = ip;
            this.port = port;
            this.hexData = hexData;
            this.timestamp = timestamp;
        }
    }
    // æŽ¥æ”¶ç«¯å­˜å‚¨æŠ¥æ–‡ï¼ˆUDPPortAReceiver中调用)
    public static void storePacket(String ip, int port, String hexData) {
        if (packetQueue.size() < 100000) { // é™åˆ¶é˜Ÿåˆ—大小防止OOM
            packetQueue.offer(new HexPacket(ip, port, hexData, System.currentTimeMillis()));
        }
    }
    // å¯åŠ¨è§£æžç³»ç»Ÿ
    public static void startProcessing() {
        if (isRunning.get()) return;
        isRunning.set(true);
        parserThread = new Thread(() -> {
            PacketParser bufferManager = new PacketParser();
            while (isRunning.get()) {
                HexPacket packet = packetQueue.poll();
                if (packet == null) {
                    Thread.yield(); // é˜Ÿåˆ—为空时让出CPU
                    continue;
                }
                try {
                    // è½¬æ¢HEX为字节数据
                    byte[] rawData = PacketParser.hexStringToBytes(packet.hexData);
                    // è¿½åŠ åˆ°ç¼“å†²åŒºå¹¶è§£æž
                    bufferManager.appendData(rawData, rawData.length);
                    List<PacketParser.DataPacket> parsedPackets = bufferManager.parsePackets();
                    // å¤„理解析后的数据包
                    for (PacketParser.DataPacket p : parsedPackets) {
                        // æ ¹æ®åŒ…头类型路由到不同解析器
                        switch (p.getPacketType()) {
                            case 0x01:
                                processType01(p);break;
                            case 0x02:
                                processType02(p);break;
                            default:
                                System.err.println("未知包类型: " + p.getPacketType());
                        }
                    }
                } catch (Exception e) {
                    System.err.println("解析错误: " + e.getMessage());
                }
            }
        });
        parserThread.setDaemon(true);
        parserThread.start();
    }
    // åœæ­¢è§£æžç³»ç»Ÿ
    public static void stopProcessing() {
        isRunning.set(false);
        parserExecutor.shutdownNow();
        if (parserThread != null) {
            parserThread.interrupt();
        }
    }
    // ç¤ºä¾‹è§£æžæ–¹æ³•(需根据实际协议实现)
    private static void processType01(PacketParser.DataPacket packet) {
        String hexData = PacketParser.bytesToHexString(packet.getPacket());
        Dell55AA01Parser.parse(hexData);
    }
    private static void processType02(PacketParser.DataPacket packet) {
        System.out.println("处理55AA02包: " + packet);
        // å®žé™…业务逻辑
    }
    // å…¶ä»–类型处理方法...
}
src/udptcp/TCPDiffDataReceiver.java
ÎļþÒÑɾ³ý
src/udptcp/UDPPortAReceiver.java
@@ -2,119 +2,115 @@
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import dell_system.MessageViewPanel;
import dell_targets.Dell_SystemConfiguration;
public class UDPPortAReceiver {
    public static final int PORT = 8234;
    private static final int MAX_DEVICES = 50000;
    private static final AtomicLong packetCount = new AtomicLong(0);
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    private static DatagramSocket socket;
    private static volatile boolean isRunning = false;
    private static Thread receiverThread;
    private static final int LOCAL_PORT = PORT; // å®šä¹‰æœ¬åœ°ç«¯å£
    // å¯åŠ¨æŽ¥æ”¶å™¨çš„é™æ€æ–¹æ³•
    public static void startReceiver() {
        if (isRunning) return;
        isRunning = true;
        receiverThread = new Thread(() -> {
            try {
                socket = new DatagramSocket(PORT);
                byte[] buffer = new byte[2048];
                while (isRunning) {
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    socket.receive(packet);
                    executor.execute(() -> {
                        try {
                            String ip = packet.getAddress().getHostAddress();
                            int port = packet.getPort();
                            String hexData = bytesToHex(packet.getData(), packet.getLength());
                            packetCount.incrementAndGet();
                            // èŽ·å–å½“å‰æ—¶é—´å’Œæ—¶é—´æˆ³
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            String time = sdf.format(new Date());
                            int timestamp = (int)(System.currentTimeMillis() / 1000);
                            // ä¿å­˜åˆ°HexBaowen集合
                         // è°ƒç”¨æ—¶æ·»åŠ æœ¬åœ°ç«¯å£å‚æ•°
                            HexBaowen.intsert(ip, hexData, time, port, LOCAL_PORT, timestamp);
                        } catch (Exception e) {
                            System.err.println("Error processing UDP-A packet: " + e.getMessage());
                        }
                    });
                }
            } catch (Exception e) {
                System.err.println("UDP-A Server crashed: " + e.getMessage());
            } finally {
                if (socket != null && !socket.isClosed()) {
                    socket.close();
                }
            }
        });
        receiverThread.setDaemon(true);
        receiverThread.start();
    }
    // åœæ­¢æŽ¥æ”¶å™¨
    public static void stopReceiver() {
        isRunning = false;
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
        executor.shutdown();
    }
    // å‘送数据到指定设备
    public static void sendData(String ip, int port, String data, boolean isHex) {
        try {
            byte[] sendBytes;
            if (isHex) {
                // HEX格式发送:将十六进制字符串转换为字节数组
                sendBytes = hexStringToByteArray(data);
            } else {
                // ASCII格式发送:直接获取字节数组
                sendBytes = data.getBytes();
            }
            InetAddress address = InetAddress.getByName(ip);
            DatagramPacket packet = new DatagramPacket(sendBytes, sendBytes.length, address, port);
            socket.send(packet);
        } catch (Exception e) {
            System.err.println("Error sending UDP data: " + e.getMessage());
        }
    }
    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();
    }
    private static byte[] hexStringToByteArray(String hex) {
        hex = hex.replaceAll("\\s", ""); // ç§»é™¤æ‰€æœ‰ç©ºæ ¼
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // å¤„理每两个字符作为一个字节
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                                 + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }
    public static final int PORT =Dell_SystemConfiguration.hexport;
    @SuppressWarnings("unused")
    private static final int MAX_DEVICES = 50000;
    private static final AtomicLong packetCount = new AtomicLong(0);
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    private static DatagramSocket socket;
    private static volatile boolean isRunning = false;
    private static Thread receiverThread;
    @SuppressWarnings("unused")
    private static final int LOCAL_PORT = PORT; // å®šä¹‰æœ¬åœ°ç«¯å£
    // å¯åŠ¨æŽ¥æ”¶å™¨çš„é™æ€æ–¹æ³•
    public static void startReceiver() {
        if (isRunning) return;
        isRunning = true;
        receiverThread = new Thread(() -> {
            try {
                socket = new DatagramSocket(PORT);
                byte[] buffer = new byte[2048];
                while (isRunning) {
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    socket.receive(packet);
                    executor.execute(() -> {
                        try {
                            String ip = packet.getAddress().getHostAddress();
                            int port = packet.getPort();
                            String hexData = bytesToHex(packet.getData(), packet.getLength());
                            // è°ƒç”¨æ—¶æ·»åŠ æœ¬åœ°ç«¯å£å‚æ•°
                            PacketProcessingSystem.storePacket(ip, port, hexData);
                            // æŠ¥æ–‡æŸ¥çœ‹çª—口显示数据
                            MessageViewPanel.showData(hexData, ip, port, PORT,"1");
                            // +++ å¢žåŠ åŒ…è®¡æ•° +++
                            packetCount.incrementAndGet();  // å…³é”®ä¿®å¤ï¼šå¢žåŠ è®¡æ•°å™¨
                        } catch (Exception e) {
                            System.err.println("Error processing UDP-A packet: " + e.getMessage());
                        }
                    });
                }
            } catch (Exception e) {
                System.err.println("UDP-A Server crashed: " + e.getMessage());
            } finally {
                if (socket != null && !socket.isClosed()) {
                    socket.close();
                }
            }
        });
        receiverThread.setDaemon(true);
        receiverThread.start();
    }
    public static long getPacketCount() {
        return packetCount.get();
    }
    // åœæ­¢æŽ¥æ”¶å™¨
    public static void stopReceiver() {
        isRunning = false;
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
        executor.shutdown();
    }
    // å‘送数据到指定设备
    public static void sendData(String ip, int port, String data, boolean isHex) {
        try {
            byte[] sendBytes;
            if (isHex) {
                // HEX格式发送:将十六进制字符串转换为字节数组
                sendBytes = hexStringToByteArray(data);
            } else {
                // ASCII格式发送:直接获取字节数组
                sendBytes = data.getBytes();
            }
            InetAddress address = InetAddress.getByName(ip);
            DatagramPacket packet = new DatagramPacket(sendBytes, sendBytes.length, address, port);
            socket.send(packet);
        } catch (Exception e) {
            System.err.println("Error sending UDP data: " + e.getMessage());
        }
    }
    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();
    }
    private static byte[] hexStringToByteArray(String hex) {
        hex = hex.replaceAll("\\s", ""); // ç§»é™¤æ‰€æœ‰ç©ºæ ¼
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // å¤„理每两个字符作为一个字节
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }
    // èŽ·å–æŽ¥æ”¶åˆ°çš„æ•°æ®åŒ…æ€»æ•°
    public static long getPacketCount() {
        return packetCount.get();
    }
}
src/udptcp/UDPPortBReceiver.java
@@ -2,22 +2,21 @@
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import dell_system.MessageViewPanel;
public class UDPPortBReceiver {
    public static final int PORT = 7000;
    private static final int MAX_DEVICES = 50000;
    @SuppressWarnings("unused")
    private static final int MAX_DEVICES = 50000;
    private static final AtomicLong packetCount = new AtomicLong(0);
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    private static DatagramSocket socket;
    private static volatile boolean isRunning = false;
    private static Thread receiverThread;
    private static final int LOCAL_PORT = PORT; // å®šä¹‰æœ¬åœ°ç«¯å£
    @SuppressWarnings("unused")
    private static final int LOCAL_PORT = PORT; // å®šä¹‰æœ¬åœ°ç«¯å£
    // å¯åŠ¨æŽ¥æ”¶å™¨çš„é™æ€æ–¹æ³•
    public static void startReceiver() {
        if (isRunning) return;
@@ -37,15 +36,8 @@
                            String ip = packet.getAddress().getHostAddress();
                            int port = packet.getPort();
                            String hexData = bytesToHex(packet.getData(), packet.getLength());
                            packetCount.incrementAndGet();
                            // èŽ·å–å½“å‰æ—¶é—´å’Œæ—¶é—´æˆ³
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            String time = sdf.format(new Date());
                            int timestamp = (int)(System.currentTimeMillis() / 1000);
                            // ä¿å­˜åˆ°HexBaowen集合
                         // è°ƒç”¨æ—¶æ·»åŠ æœ¬åœ°ç«¯å£å‚æ•°
                            HexBaowen.intsert(ip, hexData, time, port, LOCAL_PORT, timestamp);
                            // è°ƒç”¨æ—¶æ·»åŠ æœ¬åœ°ç«¯å£å‚æ•°
                            PacketProcessingSystem.storePacket(ip, port, hexData);
                            
                        } catch (Exception e) {
                            System.err.println("Error processing UDP-A packet: " + e.getMessage());
@@ -74,7 +66,6 @@
    }
    
    // å‘送数据到指定设备
 // å‘送数据到指定设备
    public static void sendData(String ip, int port, String data, boolean isHex) {
        try {
            byte[] sendBytes;
src/window/WelcomeFrame.java
@@ -1,213 +1,237 @@
package window; // åŒ…声明
import java.awt.*; // å¯¼å…¥AWT包
import java.sql.Connection; // å¯¼å…¥æ•°æ®åº“连接类
import java.sql.ResultSet; // å¯¼å…¥ç»“果集类
import java.sql.Statement; // å¯¼å…¥SQL语句类
import javax.swing.*; // å¯¼å…¥Swing包
import javax.swing.border.EmptyBorder; // å¯¼å…¥ç©ºè¾¹æ¡†ç±»
import java.util.ResourceBundle; // å¯¼å…¥èµ„源束类
import udptcp.UDPPortAReceiver; // å¯¼å…¥UDP端口A接收器
import udptcp.UDPPortBReceiver; // å¯¼å…¥UDP端口B接收器
import javax.swing.plaf.basic.BasicInternalFrameUI; // å¯¼å…¥åŸºç¡€å†…部框架UI
package window;
public class WelcomeFrame extends JInternalFrame { // æ¬¢è¿Žæ¡†æž¶ç±»
    private static final long serialVersionUID = 1L; // åºåˆ—化版本ID
    private ResourceBundle messages; // æ¶ˆæ¯èµ„源束
    private Connection conn; // æ•°æ®åº“连接
    private Timer statsTimer; // ç»Ÿè®¡å®šæ—¶å™¨
    private JLabel udpAPacketCountLabel; // UDP端口A包计数标签
    private JLabel udpBPacketCountLabel; // UDP端口B包计数标签
    private JLabel memoryUsageLabel; // å†…存使用标签
    private JLabel threadCountLabel; // çº¿ç¨‹è®¡æ•°æ ‡ç­¾
import java.awt.*;
import java.sql.Connection;
import java.sql.ResultSet;
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;
import dell_targets.Dell_tag;
import dell_targets.Dell_SystemConfiguration;
    public WelcomeFrame(ResourceBundle messages, Connection conn) { // æž„造函数
        super("", true, true, true, true); // è°ƒç”¨çˆ¶ç±»æž„造函数,设置标题为空
        this.messages = messages; // åˆå§‹åŒ–消息资源束
        this.conn = conn; // åˆå§‹åŒ–数据库连接
public class WelcomeFrame extends JInternalFrame {
    private static final long serialVersionUID = 1L;
    private final ResourceBundle messages;
    private final Connection conn;
    private Timer statsTimer;
    private JLabel memoryUsageLabel;
    private JLabel threadCountLabel;
    private JLabel tagStatsLabel;
    private JLabel baseStationStatsLabel;
    private JLabel dbVersionLabel;
    private JLabel udpAInfoLabel;
    private JLabel udpBInfoLabel;
    public WelcomeFrame(ResourceBundle messages, Connection conn) {
        super("", true, true, true, true);
        this.messages = messages;
        this.conn = conn;
        
        initializeFrame(); // åˆå§‹åŒ–框架
        setContentPane(createWelcomePanel()); // è®¾ç½®å†…容面板
        startStatsTimer(); // å¯åŠ¨ç»Ÿè®¡å®šæ—¶å™¨
        initializeFrame();
        setContentPane(createWelcomePanel());
        startStatsTimer();
    }
    private void initializeFrame() { // åˆå§‹åŒ–框架方法
        setSize(900, 700); // è®¾ç½®æ¡†æž¶å¤§å°
        setLocation(100, 100); // è®¾ç½®æ¡†æž¶ä½ç½®
        setMaximizable(true); // è®¾ç½®å¯æœ€å¤§åŒ–
        setIconifiable(true); // è®¾ç½®å¯å›¾æ ‡åŒ–
        setClosable(true); // è®¾ç½®å¯å…³é—­
        setBorder(null); // ç§»é™¤è¾¹æ¡†
        setVisible(true); // è®¾ç½®å¯è§
    private void initializeFrame() {
        setSize(900, 700);
        setLocation(100, 100);
        setMaximizable(true);
        setIconifiable(true);
        setClosable(true);
        setBorder(null);
        
        // ç§»é™¤æ ‡é¢˜æ 
        BasicInternalFrameUI ui = (BasicInternalFrameUI) this.getUI(); // èŽ·å–UI组件
        ui.setNorthPane(null); // ç§»é™¤æ ‡é¢˜æ 
        ((javax.swing.plaf.basic.BasicInternalFrameUI)this.getUI()).setNorthPane(null);
        
        try {
            setMaximum(true); // å°è¯•最大化窗口
            setMaximum(true);
        } catch (java.beans.PropertyVetoException e) {
            e.printStackTrace(); // æ‰“印异常堆栈
            e.printStackTrace();
        }
        setVisible(true); // ç¡®ä¿æ¡†æž¶å¯è§
    }
    private JPanel createWelcomePanel() { // åˆ›å»ºæ¬¢è¿Žé¢æ¿æ–¹æ³•
        JPanel panel = new BackgroundPanel(); // åˆ›å»ºèƒŒæ™¯é¢æ¿
        panel.setLayout(new BorderLayout()); // è®¾ç½®è¾¹ç•Œå¸ƒå±€
        panel.setBorder(new EmptyBorder(30, 30, 30, 30)); // è®¾ç½®ç©ºè¾¹æ¡†
    private JPanel createWelcomePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(new EmptyBorder(30, 30, 30, 30));
        panel.setBackground(new Color(245, 248, 255));
        
        // åˆ›å»ºæ ‡é¢˜é¢æ¿
        JPanel titlePanel = new JPanel(new BorderLayout()); // åˆ›å»ºè¾¹ç•Œå¸ƒå±€é¢æ¿
        titlePanel.setOpaque(false); // è®¾ç½®é€æ˜Ž
        // æ ‡é¢˜é¢æ¿
        JPanel titlePanel = new JPanel(new BorderLayout());
        titlePanel.setOpaque(false);
        titlePanel.setBorder(new EmptyBorder(0, 0, 30, 0));
        
        JLabel titleLabel = new JLabel(messages.getString("APP_NAME"), SwingConstants.CENTER); // åˆ›å»ºåº”用名称标签
        titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 42)); // è®¾ç½®å­—体
        titleLabel.setForeground(new Color(25, 25, 112)); // è®¾ç½®å‰æ™¯è‰²
        titleLabel.setBorder(new EmptyBorder(20, 0, 20, 0)); // è®¾ç½®ç©ºè¾¹æ¡†
        titleLabel.setOpaque(false); // è®¾ç½®é€æ˜Ž
        JLabel titleLabel = new JLabel(messages.getString("APP_NAME"), SwingConstants.CENTER);
        titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 42));
        titleLabel.setForeground(new Color(25, 25, 112));
        
        JLabel subtitleLabel = new JLabel(messages.getString("WELCOME_MSG"), SwingConstants.CENTER); // åˆ›å»ºæ¬¢è¿Žæ¶ˆæ¯æ ‡ç­¾
        subtitleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.ITALIC, 22)); // è®¾ç½®å­—体
        subtitleLabel.setForeground(new Color(70, 130, 180)); // è®¾ç½®å‰æ™¯è‰²
        subtitleLabel.setOpaque(false); // è®¾ç½®é€æ˜Ž
        JLabel subtitleLabel = new JLabel(messages.getString("WELCOME_MSG"), SwingConstants.CENTER);
        subtitleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.ITALIC, 22));
        subtitleLabel.setForeground(new Color(70, 130, 180));
        subtitleLabel.setBorder(new EmptyBorder(10, 0, 20, 0));
        
        titlePanel.add(titleLabel, BorderLayout.NORTH); // æ·»åŠ æ ‡é¢˜åˆ°åŒ—éƒ¨
        titlePanel.add(subtitleLabel, BorderLayout.CENTER); // æ·»åŠ å‰¯æ ‡é¢˜åˆ°ä¸­éƒ¨
        titlePanel.add(titleLabel, BorderLayout.NORTH);
        titlePanel.add(subtitleLabel, BorderLayout.CENTER);
        
        // åˆ›å»ºä¿¡æ¯é¢æ¿
        JPanel infoPanel = new JPanel(new GridLayout(0, 2, 20, 20)); // åˆ›å»ºç½‘格布局面板
        infoPanel.setBorder(new EmptyBorder(30, 50, 30, 50)); // è®¾ç½®ç©ºè¾¹æ¡†
        infoPanel.setBackground(new Color(255, 255, 255, 180)); // è®¾ç½®åŠé€æ˜Žç™½è‰²èƒŒæ™¯
        infoPanel.setOpaque(true); // è®¾ç½®ä¸é€æ˜Ž
        // ä¸»ä¿¡æ¯é¢æ¿
        JPanel infoPanel = new JPanel(new GridBagLayout());
        infoPanel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(200, 220, 240), 2),
            new EmptyBorder(30, 40, 30, 40)
        ));
        infoPanel.setBackground(new Color(255, 255, 255, 255));
        infoPanel.setOpaque(true);
        
        // æ·»åŠ ç³»ç»ŸçŠ¶æ€ä¿¡æ¯
        infoPanel.add(createInfoLabel(messages.getString("SYSTEM_STATUS"),
                     messages.getString("RUNNING_NORMAL"),
                     new Color(0, 100, 0))); // æ·±ç»¿è‰²
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(15, 15, 15, 15);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        
        // æ·»åŠ æ•°æ®åº“è¿žæŽ¥ä¿¡æ¯
        infoPanel.add(createInfoLabel(messages.getString("DB_CONNECTION"),
                     conn != null ? messages.getString("CONNECTED") : messages.getString("DISCONNECTED"),
                     conn != null ? new Color(0, 100, 0) : Color.RED)); // è¿žæŽ¥æˆåŠŸç»¿è‰²/失败红色
        // ç¬¬ä¸€åˆ—
        gbc.gridx = 0;
        gbc.gridy = 0;
        
        try {
            if (conn != null) { // æ£€æŸ¥æ•°æ®åº“连接
                try (Statement stmt = conn.createStatement(); // åˆ›å»ºè¯­å¥
                     ResultSet rs = stmt.executeQuery("SELECT VERSION()")) { // æ‰§è¡Œç‰ˆæœ¬æŸ¥è¯¢
                    if (rs.next()) { // å¦‚果有结果
                        infoPanel.add(createInfoLabel(messages.getString("DB_VERSION"),
                                     rs.getString(1),
                                     new Color(25, 25, 112))); // æ·»åŠ æ•°æ®åº“ç‰ˆæœ¬
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace(); // æ‰“印异常
        // ä¿®å¤1: åˆå§‹åŒ–标签并设置初始文本
        tagStatsLabel = new JLabel("0 / 0");
        tagStatsLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("TAG_STATS"), tagStatsLabel, new Color(0, 100, 0)), gbc);
        gbc.gridy++;
        baseStationStatsLabel = new JLabel("0 / 0");
        baseStationStatsLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("BASE_STATION_STATS"), baseStationStatsLabel, new Color(0, 100, 0)), gbc);
        gbc.gridy++;
        udpAInfoLabel = new JLabel(Dell_SystemConfiguration.hexport + " - " + messages.getString("RECEIVED_PACKETS") + ": 0");
        udpAInfoLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("UDP_PORT_A"), udpAInfoLabel, new Color(178, 34, 34)), gbc);
        gbc.gridy++;
        udpBInfoLabel = new JLabel(Dell_SystemConfiguration.ascallport + " - " + messages.getString("RECEIVED_PACKETS") + ": 0");
        udpBInfoLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("UDP_PORT_B"), udpBInfoLabel, new Color(178, 34, 34)), gbc);
        gbc.gridy++;
        memoryUsageLabel = new JLabel("0 MB / 0 MB");
        memoryUsageLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("MEMORY_USAGE"), memoryUsageLabel, new Color(148, 0, 211)), gbc);
        // ç¬¬äºŒåˆ—
        gbc.gridx = 1;
        gbc.gridy = 0;
        threadCountLabel = new JLabel("0");
        threadCountLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("THREAD_COUNT"), threadCountLabel, new Color(148, 0, 211)), gbc);
        gbc.gridy++;
        dbVersionLabel = new JLabel(""); // åˆå§‹ä¸ºç©ºï¼Œç¨åŽè®¾ç½®
        dbVersionLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("DB_VERSION"), dbVersionLabel, new Color(25, 25, 112)), gbc);
        gbc.gridy++;
        JLabel dbStatusLabel = new JLabel(conn != null ? messages.getString("CONNECTED") : messages.getString("DISCONNECTED"));
        dbStatusLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        dbStatusLabel.setForeground(conn != null ? new Color(0, 100, 0) : Color.RED);
        infoPanel.add(createInfoRow(messages.getString("DB_STATUS"), dbStatusLabel, new Color(25, 25, 112)), gbc);
        gbc.gridy++;
        JLabel softwareVersionLabel = new JLabel(messages.getString("APP_VERSION"));
        softwareVersionLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        infoPanel.add(createInfoRow(messages.getString("SOFTWARE_VERSION"), softwareVersionLabel, new Color(25, 25, 112)), gbc);
        // åˆå§‹åŒ–数据库版本
        if (conn != null && dbVersionLabel.getText().isEmpty()) {
            updateDbVersion();
        }
        // æ·»åŠ å½“å‰ç”¨æˆ·ä¿¡æ¯
        infoPanel.add(createInfoLabel(messages.getString("CURRENT_USER"),
                     messages.getString("ADMIN"),
                     new Color(25, 25, 112))); // æ·±è“è‰²
        // æ·»åŠ ç³»ç»Ÿæ—¶é—´ä¿¡æ¯
        infoPanel.add(createInfoLabel(messages.getString("SYSTEM_TIME"),
                     new java.util.Date().toString(),
                     new Color(25, 25, 112))); // æ·±è“è‰²
        // æ·»åŠ UDP端口A统计
        infoPanel.add(createInfoLabel(messages.getString("UDP_PORT_A"), "0", new Color(178, 34, 34))); // ç –红色
        udpAPacketCountLabel = createInfoLabel("", "", new Color(178, 34, 34)); // åˆ›å»ºè®¡æ•°æ ‡ç­¾
        infoPanel.add(udpAPacketCountLabel); // æ·»åŠ è®¡æ•°æ ‡ç­¾
        // æ·»åŠ UDP端口B统计
        infoPanel.add(createInfoLabel(messages.getString("UDP_PORT_B"), "0", new Color(178, 34, 34))); // ç –红色
        udpBPacketCountLabel = createInfoLabel("", "", new Color(178, 34, 34)); // åˆ›å»ºè®¡æ•°æ ‡ç­¾
        infoPanel.add(udpBPacketCountLabel); // æ·»åŠ è®¡æ•°æ ‡ç­¾
        // æ·»åŠ å†…å­˜ä½¿ç”¨ç»Ÿè®¡
        infoPanel.add(createInfoLabel(messages.getString("MEMORY_USAGE"), "", new Color(148, 0, 211))); // ç´«ç½—兰色
        memoryUsageLabel = createInfoLabel("", "", new Color(148, 0, 211)); // åˆ›å»ºå†…存标签
        infoPanel.add(memoryUsageLabel); // æ·»åŠ å†…å­˜æ ‡ç­¾
        // æ·»åŠ çº¿ç¨‹è®¡æ•°ç»Ÿè®¡
        infoPanel.add(createInfoLabel(messages.getString("THREAD_COUNT"), "", new Color(148, 0, 211))); // ç´«ç½—兰色
        threadCountLabel = createInfoLabel("", "", new Color(148, 0, 211)); // åˆ›å»ºçº¿ç¨‹æ ‡ç­¾
        infoPanel.add(threadCountLabel); // æ·»åŠ çº¿ç¨‹æ ‡ç­¾
        // åˆ›å»ºçŠ¶æ€é¢æ¿
        JPanel statsPanel = new JPanel(new GridLayout(1, 4, 15, 15)); // åˆ›å»ºç½‘格布局面板
        statsPanel.setBorder(new EmptyBorder(20, 50, 10, 50)); // è®¾ç½®ç©ºè¾¹æ¡†
        statsPanel.setOpaque(false); // è®¾ç½®é€æ˜Ž
        // æ·»åŠ ç»Ÿè®¡ç›’å­
        statsPanel.add(createStatBox(messages.getString("UDP_PORT_A_STAT"), udpAPacketCountLabel)); // UDP端口A统计
        statsPanel.add(createStatBox(messages.getString("UDP_PORT_B_STAT"), udpBPacketCountLabel)); // UDP端口B统计
        statsPanel.add(createStatBox(messages.getString("MEMORY_USAGE_STAT"), memoryUsageLabel)); // å†…存使用统计
        statsPanel.add(createStatBox(messages.getString("THREAD_COUNT_STAT"), threadCountLabel)); // çº¿ç¨‹è®¡æ•°ç»Ÿè®¡
        
        // ç»„装主面板
        panel.add(titlePanel, BorderLayout.NORTH); // æ·»åŠ æ ‡é¢˜é¢æ¿åˆ°åŒ—éƒ¨
        panel.add(infoPanel, BorderLayout.CENTER); // æ·»åŠ ä¿¡æ¯é¢æ¿åˆ°ä¸­éƒ¨
        panel.add(statsPanel, BorderLayout.SOUTH); // æ·»åŠ çŠ¶æ€é¢æ¿åˆ°å—éƒ¨
        panel.add(titlePanel, BorderLayout.NORTH);
        panel.add(infoPanel, BorderLayout.CENTER);
        
        return panel; // è¿”回面板
        return panel;
    }
    private JLabel createInfoLabel(String title, String value, Color color) { // åˆ›å»ºä¿¡æ¯æ ‡ç­¾æ–¹æ³•
        JLabel label = new JLabel("<html><div style='text-align:center;'><b>" + title + "</b><br>" + value + "</div></html>"); // åˆ›å»ºå¸¦HTML格式的标签
        label.setFont(new Font(messages.getString("FONT_NAME"), Font.PLAIN, 16)); // è®¾ç½®å­—体
        label.setForeground(color); // è®¾ç½®å‰æ™¯è‰²
        label.setHorizontalAlignment(SwingConstants.CENTER); // è®¾ç½®æ°´å¹³å±…中
        label.setVerticalAlignment(SwingConstants.CENTER); // è®¾ç½®åž‚直居中
        label.setOpaque(false); // è®¾ç½®é€æ˜Ž
        return label; // è¿”回标签
    private JPanel createInfoRow(String title, JLabel valueLabel, Color color) {
        JPanel rowPanel = new JPanel(new BorderLayout(10, 0));
        rowPanel.setOpaque(false);
        JLabel titleLabel = new JLabel(title + ":");
        titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18));
        titleLabel.setForeground(color.darker());
        valueLabel.setForeground(color);
        rowPanel.add(titleLabel, BorderLayout.WEST);
        rowPanel.add(valueLabel, BorderLayout.CENTER);
        // æ·»åŠ è£…é¥°å™¨
        JPanel decorator = new JPanel();
        decorator.setPreferredSize(new Dimension(5, 5));
        decorator.setBackground(color);
        decorator.setOpaque(true);
        rowPanel.add(decorator, BorderLayout.EAST);
        return rowPanel;
    }
    
    private JPanel createStatBox(String title, JLabel valueLabel) { // åˆ›å»ºç»Ÿè®¡ç›’子方法
        JPanel boxPanel = new JPanel(new BorderLayout()); // åˆ›å»ºè¾¹ç•Œå¸ƒå±€é¢æ¿
        boxPanel.setBorder(BorderFactory.createCompoundBorder( // è®¾ç½®å¤åˆè¾¹æ¡†
            BorderFactory.createLineBorder(new Color(70, 130, 180), 2), // è“è‰²è¾¹æ¡†
            new EmptyBorder(15, 10, 15, 10) // å†…边距
        ));
        boxPanel.setBackground(new Color(240, 248, 255, 220)); // è®¾ç½®åŠé€æ˜ŽèƒŒæ™¯
        boxPanel.setOpaque(true); // è®¾ç½®ä¸é€æ˜Ž
        JLabel titleLabel = new JLabel(title, SwingConstants.CENTER); // åˆ›å»ºæ ‡é¢˜æ ‡ç­¾
        titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); // è®¾ç½®ç²—体
        titleLabel.setForeground(new Color(25, 25, 112)); // è®¾ç½®æ·±è“è‰²
        valueLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 24)); // è®¾ç½®ç²—体大字号
        valueLabel.setHorizontalAlignment(SwingConstants.CENTER); // è®¾ç½®å±…中
        boxPanel.add(titleLabel, BorderLayout.NORTH); // æ·»åŠ æ ‡é¢˜åˆ°åŒ—éƒ¨
        boxPanel.add(valueLabel, BorderLayout.CENTER); // æ·»åŠ å€¼æ ‡ç­¾åˆ°ä¸­éƒ¨
        return boxPanel; // è¿”回面板
    private void updateDbVersion() {
        if (conn != null) {
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT VERSION()")) {
                if (rs.next()) {
                    dbVersionLabel.setText(rs.getString(1));
                }
            } catch (Exception ex) {
                dbVersionLabel.setText("N/A");
            }
        }
    }
    
    private void startStatsTimer() { // å¯åŠ¨ç»Ÿè®¡å®šæ—¶å™¨æ–¹æ³•
        statsTimer = new Timer(1000, e -> { // åˆ›å»º1秒间隔的定时器
            // æ›´æ–°UDP数据包计数
            udpAPacketCountLabel.setText(String.valueOf(UDPPortAReceiver.getPacketCount())); // æ›´æ–°ç«¯å£A计数
            udpBPacketCountLabel.setText(String.valueOf(UDPPortBReceiver.getPacketCount())); // æ›´æ–°ç«¯å£B计数
    private void startStatsTimer() {
        statsTimer = new Timer(1000, e -> {
            // æ›´æ–°UDP端口A信息
            int packetCountA = (int) UDPPortAReceiver.getPacketCount();
            udpAInfoLabel.setText(Dell_SystemConfiguration.hexport + " - " +
                                 messages.getString("RECEIVED_PACKETS") + ": " + packetCountA);
            // æ›´æ–°UDP端口B信息
            int packetCountB = (int) UDPPortBReceiver.getPacketCount();
            udpBInfoLabel.setText(Dell_SystemConfiguration.ascallport + " - " +
                                  messages.getString("RECEIVED_PACKETS") + ": " + packetCountB);
            
            // æ›´æ–°å†…存使用情况
            Runtime runtime = Runtime.getRuntime(); // èŽ·å–è¿è¡Œæ—¶å®žä¾‹
            long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024); // è®¡ç®—已用内存(MB)
            long maxMemory = runtime.maxMemory() / (1024 * 1024); // è®¡ç®—最大内存(MB)
            memoryUsageLabel.setText(usedMemory + " " + messages.getString("MB") + " / " + maxMemory + " " + messages.getString("MB")); // è®¾ç½®å†…存文本
            Runtime runtime = Runtime.getRuntime();
            long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024);
            long maxMemory = runtime.maxMemory() / (1024 * 1024);
            memoryUsageLabel.setText(usedMemory + " " + messages.getString("MB") + " / " +
                                    maxMemory + " " + messages.getString("MB"));
            
            // æ›´æ–°çº¿ç¨‹æ•°é‡
            threadCountLabel.setText(String.valueOf(Thread.activeCount())); // è®¾ç½®æ´»åŠ¨çº¿ç¨‹æ•°
            // æ›´æ–°çº¿ç¨‹æ•°
            threadCountLabel.setText(String.valueOf(Thread.activeCount()));
            // æ›´æ–°æ ‡ç­¾çŠ¶æ€
            int onlineTags = Dell_tag.getOnlineLocationTags().size();
            int totalTags = Dell_tag.getLocationTagCount();
            tagStatsLabel.setText(onlineTags + " / " + totalTags);
            // æ›´æ–°åŸºç«™çŠ¶æ€
            int onlineStations = Dell_BaseStation.getOnlineBaseStations().size();
            int totalStations = Dell_BaseStation.getLocationBaseCount();
            baseStationStatsLabel.setText(onlineStations + " / " + totalStations);
        });
        statsTimer.start(); // å¯åŠ¨å®šæ—¶å™¨
        statsTimer.start();
    }
    
    @Override
    public void dispose() { // é”€æ¯æ–¹æ³•
        super.dispose(); // è°ƒç”¨çˆ¶ç±»é”€æ¯
        if (statsTimer != null) { // æ£€æŸ¥å®šæ—¶å™¨
            statsTimer.stop(); // åœæ­¢å®šæ—¶å™¨
    public void dispose() {
        super.dispose();
        if (statsTimer != null) {
            statsTimer.stop();
        }
    }
}
src/window/Windows.java
@@ -17,6 +17,7 @@
import dell_map.Dell_Map;
import dell_map.MapViewer;
import dell_targets.Dell_SystemConfiguration;
import targets.Mapdata;
public class Windows extends JFrame {
@@ -82,6 +83,16 @@
        createLanguageMenu();
    }
    // æ–°å¢žæ–¹æ³•:根据系统配置获取当前语言环境
    public Locale getSystemLocale() {
        return "1".equals(Dell_SystemConfiguration.language) ?
               Locale.ENGLISH : Locale.SIMPLIFIED_CHINESE;
    }
    // æ–°å¢žæ–¹æ³•:供其他类获取当前语言环境
    public Locale getCurrentLocale() {
        return this.currentLocale;
    }
    private ResourceBundle loadResourceBundle(Locale locale) {
        String fileName = locale.equals(Locale.ENGLISH) ? 
systemfile/Messages_en.properties
@@ -1,3 +1,26 @@
TAG_STATS = Tag Statistics
BASE_STATION_STATS = Base Station Statistics
SOFTWARE_VERSION = Software Version
APP_VERSION = 1.0.0
UDP_PORT_A = UDP Receive Port A
UDP_PORT_B = UDP Receive Port B
DB_VERSION = Database Version
DB_STATUS = Database Status
RECEIVED_PACKETS=Received
# New message viewing related resources
MESSAGE_VIEW_ALL_TYPES=All Types
MESSAGE_VIEW_UDP_PORT_A=UDP Port A
MESSAGE_VIEW_UDP_PORT_B=UDP Port B
MESSAGE_VIEW_TCP_PORT=TCP Port
MESSAGE_VIEW_MQTT_PORT=MQTT Port
MESSAGE_VIEW_ALL_DEVICES=All Devices
MESSAGE_VIEW_ALL_PROTOCOLS=All Protocols
MESSAGE_VIEW_SHOW_DATA=Show Data
MESSAGE_VIEW_DATA_SOURCE=Data Source
MESSAGE_VIEW_FILTERED_DATA=Filtered Data
MESSAGE_VIEW_HEX_FORMAT=HEX Format
MESSAGE_VIEW_ASCII_FORMAT=ASCII Format
MESSAGE_VIEW_MIXED_FORMAT=Mixed Format
# New Resource Key-Value Pairs
packet.count.format=Packets Received: %d
label.id=Label ID
systemfile/Messages_zh.properties
@@ -1,3 +1,26 @@
TAG_STATS=标签统计
BASE_STATION_STATS=基站统计
SOFTWARE_VERSION=软件版本
APP_VERSION=1.0.0
UDP_PORT_A=数据接收端口
UDP_PORT_B=数据接收端口
DB_VERSION=数据库版本
DB_STATUS=数据库状态
RECEIVED_PACKETS=接收
# æ–°å¢žçš„æŠ¥æ–‡æŸ¥çœ‹ç›¸å…³èµ„源
MESSAGE_VIEW_ALL_TYPES=所有类型
MESSAGE_VIEW_UDP_PORT_A=UDP端口A
MESSAGE_VIEW_UDP_PORT_B=UDP端口B
MESSAGE_VIEW_TCP_PORT=TCP端口
MESSAGE_VIEW_MQTT_PORT=MQTT端口
MESSAGE_VIEW_ALL_DEVICES=所有设备
MESSAGE_VIEW_ALL_PROTOCOLS=所有协议
MESSAGE_VIEW_SHOW_DATA=显示数据
MESSAGE_VIEW_DATA_SOURCE=数据来源
MESSAGE_VIEW_FILTERED_DATA=已过滤数据
MESSAGE_VIEW_HEX_FORMAT=HEX格式
MESSAGE_VIEW_ASCII_FORMAT=ASCII格式
MESSAGE_VIEW_MIXED_FORMAT=混合格式
# æ–°å¢žèµ„源键值对
packet.count.format=收到数据:%d条
label.id=标签编号
@@ -469,8 +492,6 @@
MESSAGE_VIEW_EMPTY_DATA=发送内容不能为空
ERROR=错误
# æ¬¢è¿Žç•Œé¢ç›‘控
UDP_PORT_A=UDP端口A (8234)
UDP_PORT_B=UDP端口B (7000)
MEMORY_USAGE=内存使用
THREAD_COUNT=线程数量
MB=MB
systemfile/logfile/openlog.txt
@@ -634,3 +634,150 @@
程序关闭: 2025-08-08 23:06:23
工作时长: 0小时 0分钟 41秒
-----------------------------------
程序启动: 2025-08-09 10:43:53
程序关闭: 2025-08-09 15:09:35
工作时长: 4小时 25分钟 41秒
-----------------------------------
程序启动: 2025-08-09 15:09:38
程序关闭: 2025-08-09 15:09:41
工作时长: 0小时 0分钟 2秒
-----------------------------------
程序启动: 2025-08-09 15:21:34
程序启动: 2025-08-09 15:26:45
程序关闭: 2025-08-09 15:26:49
工作时长: 0小时 5分钟 15秒
-----------------------------------
程序启动: 2025-08-09 15:26:51
程序启动: 2025-08-09 15:28:12
程序关闭: 2025-08-09 15:29:23
工作时长: 0小时 1分钟 10秒
-----------------------------------
程序启动: 2025-08-09 15:29:25
程序关闭: 2025-08-09 15:30:53
工作时长: 0小时 1分钟 27秒
-----------------------------------
程序启动: 2025-08-09 15:30:55
程序关闭: 2025-08-09 15:31:19
工作时长: 0小时 0分钟 23秒
-----------------------------------
程序启动: 2025-08-09 15:31:22
程序关闭: 2025-08-09 15:36:19
工作时长: 0小时 4分钟 57秒
-----------------------------------
程序启动: 2025-08-09 15:36:21
程序关闭: 2025-08-09 15:38:36
工作时长: 0小时 2分钟 15秒
-----------------------------------
程序启动: 2025-08-09 15:38:39
程序关闭: 2025-08-09 16:03:25
工作时长: 0小时 24分钟 46秒
-----------------------------------
程序启动: 2025-08-09 16:03:28
程序关闭: 2025-08-09 16:03:42
工作时长: 0小时 0分钟 14秒
-----------------------------------
程序启动: 2025-08-09 16:13:27
程序关闭: 2025-08-09 16:16:14
工作时长: 0小时 2分钟 46秒
-----------------------------------
程序启动: 2025-08-09 16:16:17
程序关闭: 2025-08-09 16:16:37
工作时长: 0小时 0分钟 19秒
-----------------------------------
程序启动: 2025-08-09 16:19:34
程序关闭: 2025-08-09 16:21:03
工作时长: 0小时 1分钟 29秒
-----------------------------------
程序启动: 2025-08-09 16:21:05
程序关闭: 2025-08-09 16:22:09
工作时长: 0小时 1分钟 3秒
-----------------------------------
程序启动: 2025-08-09 16:22:10
程序关闭: 2025-08-09 16:28:22
工作时长: 0小时 6分钟 11秒
-----------------------------------
程序启动: 2025-08-09 16:28:24
程序关闭: 2025-08-09 16:32:37
工作时长: 0小时 4分钟 12秒
-----------------------------------
程序启动: 2025-08-09 16:32:39
程序关闭: 2025-08-09 20:05:40
工作时长: 3小时 33分钟 1秒
-----------------------------------
程序启动: 2025-08-09 20:07:08
程序关闭: 2025-08-09 20:11:43
工作时长: 0小时 4分钟 35秒
-----------------------------------
程序启动: 2025-08-09 20:11:46
程序关闭: 2025-08-09 21:57:03
工作时长: 1小时 45分钟 17秒
-----------------------------------
程序启动: 2025-08-09 21:57:05
程序关闭: 2025-08-09 22:02:50
工作时长: 0小时 5分钟 44秒
-----------------------------------
程序启动: 2025-08-09 22:12:39
程序关闭: 2025-08-09 22:21:24
工作时长: 0小时 8分钟 45秒
-----------------------------------
程序启动: 2025-08-09 22:21:26
程序关闭: 2025-08-09 22:31:29
工作时长: 0小时 10分钟 2秒
-----------------------------------
程序启动: 2025-08-09 22:31:30
程序关闭: 2025-08-09 22:31:44
工作时长: 0小时 0分钟 13秒
-----------------------------------
程序启动: 2025-08-09 22:31:59
程序关闭: 2025-08-09 22:44:51
工作时长: 0小时 12分钟 52秒
-----------------------------------
程序启动: 2025-08-09 22:44:53
程序关闭: 2025-08-09 22:44:55
工作时长: 0小时 0分钟 1秒
-----------------------------------
程序启动: 2025-08-09 22:45:33
程序关闭: 2025-08-09 22:45:35
工作时长: 0小时 0分钟 1秒
-----------------------------------
程序启动: 2025-08-09 22:46:58
程序关闭: 2025-08-09 22:49:10
工作时长: 0小时 2分钟 12秒
-----------------------------------
程序启动: 2025-08-09 22:49:12
程序关闭: 2025-08-09 22:58:17
工作时长: 0小时 9分钟 4秒
-----------------------------------
程序启动: 2025-08-09 22:58:19
程序关闭: 2025-08-09 23:09:45
工作时长: 0小时 11分钟 25秒
-----------------------------------
程序启动: 2025-08-09 23:09:47
程序关闭: 2025-08-09 23:19:34
工作时长: 0小时 9分钟 46秒
-----------------------------------
程序启动: 2025-08-09 23:19:36
程序关闭: 2025-08-09 23:19:51
工作时长: 0小时 0分钟 14秒
-----------------------------------
程序启动: 2025-08-09 23:20:10
程序关闭: 2025-08-09 23:20:15
工作时长: 0小时 0分钟 5秒
-----------------------------------
程序启动: 2025-08-09 23:21:01
程序关闭: 2025-08-09 23:21:05
工作时长: 0小时 0分钟 4秒
-----------------------------------
程序启动: 2025-08-09 23:24:49
程序关闭: 2025-08-09 23:29:56
工作时长: 0小时 5分钟 6秒
-----------------------------------
程序启动: 2025-08-09 23:29:58
程序关闭: 2025-08-09 23:30:36
工作时长: 0小时 0分钟 38秒
-----------------------------------
程序启动: 2025-08-09 23:30:38
程序关闭: 2025-08-09 23:30:52
工作时长: 0小时 0分钟 14秒
-----------------------------------
程序启动: 2025-08-09 23:30:58