zsh_root
2025-12-10 8d662de2fd262b3a485f16e197cb4d0ca2a61cdf
src/home/NetworkCommunicationPanel.java
@@ -1,26 +1,34 @@
package home;
import javax.swing.*;
import PublicPannel.AntiCollisionPanel;
import PublicPannel.BaseParameterPanel;
import PublicPannel.BaseStationPanel;
import PublicPannel.TagPanel;
import PublicPannel.UpgradePanel;
import jiexi.DellTag55AA03;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
public class NetworkCommunicationPanel extends JPanel {
    /**
    *
    */
   private static final long serialVersionUID = 1L;
   private MainFrame mainFrame;
     *
     */
    private static final long serialVersionUID = 1L;
    private MainFrame mainFrame;
    private JComboBox<String> protocolCombo;
    private JTextField hostAddressField, portField;
    private JLabel hostLabel, portLabel;
    private JComboBox<String> hostAddressCombo; // 改为下拉框
    private JTextField portField;
    private JLabel protocolTypeLabel, hostLabel, portLabel;
    private JButton openBtn;
    private JTabbedPane rightTabbedPane;
    private BaseParameterPanel baseParamPanel;
@@ -30,182 +38,1091 @@
    private UpgradePanel upgradePanel;
    private JButton readParamsBtn, saveParamsBtn, restartDeviceBtn, resetFactoryBtn;
    private boolean isOpen = false;
    // 在类变量声明部分添加新按钮
    private JButton readRelayParamsBtn, saveRelayParamsBtn;
    // 新增:数据日志面板引用
    private DataLogPanel dataLogPanel;
    private JComboBox<String> clientCombo; // 客户端/发送端下拉框
    private NetworkBase currentNetwork;
    private java.util.List<String> connectedClients = new java.util.ArrayList<>();
    // 配置命令常量 - 新增
    private static final String READ_CONFIG_CMD = "55AA03060102800073FF"; // 读取配置命令
    private static final String READ_CONFIG_CMD2 = "55AA03060102F800FBFE"; // 读取配置命令
    private static final String RESTART_DEVICE_CMD = "55AA03016001FF"; // 重启设备命令
    private static final String RESET_FACTORY_CMD = "55AA03016002FF"; // 恢复出厂设置命令
    public NetworkCommunicationPanel(MainFrame mainFrame) {
        this.mainFrame = mainFrame;
        initializeUI();
        setupButtonListeners(); // 新增:设置按钮监听器
    }
    private void initializeUI() {
        setLayout(new BorderLayout());
        // 控制面板
        // 控制面板
        add(createControlPanel(), BorderLayout.NORTH);
        // 主分割面板 - 使用水平分割
        // 主分割面板 - 使用水平分割
        JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        mainSplitPane.setDividerLocation(320);
        // 基础参数面板
        // 基础参数面板
        JPanel leftPanel = createBaseParameterPanel();
        // 右侧功能面板
        // 右侧功能面板
        JPanel rightPanel = createRightPanel();
        rightPanel.setBorder(null); // 移除面板边框
        rightPanel.setBorder(null); // 移除面板边框
        mainSplitPane.setLeftComponent(leftPanel);
        mainSplitPane.setRightComponent(rightPanel);
        add(mainSplitPane, BorderLayout.CENTER);
        // 底部按钮面板
        // 底部按钮面板
        add(createBottomButtonPanel(), BorderLayout.SOUTH);
    }
    /**
     * 设置按钮监听器 - 新增方法
     */
    private void setupButtonListeners() {
        readParamsBtn.addActionListener(e -> readParameters());
        saveParamsBtn.addActionListener(e -> saveParameters());
        restartDeviceBtn.addActionListener(e -> restartDevice());
        resetFactoryBtn.addActionListener(e -> resetFactory());
        // 新增继电器参数按钮监听器
        readRelayParamsBtn.addActionListener(e -> readRelayParameters());
        saveRelayParamsBtn.addActionListener(e -> saveRelayParameters());
    }
    // 修改后的读取继电器参数方法
    private void readRelayParameters() {
        if (!isOpen || currentNetwork == null) {
            JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 继电器参数读取命令 - 需要根据实际协议定义
        String readRelayCommand = "55AA03060102800073FF"; // 示例命令,需要替换为实际的继电器读取命令
        byte[] data = hexStringToByteArray(readRelayCommand);
        if (data == null) {
            JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 在数据日志窗口显示发送的指令
        if (dataLogPanel != null) {
            dataLogPanel.addLogData(data, getString("send.read.relay.command"));
        }
        AtomicBoolean responseReceived = new AtomicBoolean(false);
        AtomicBoolean operationCompleted = new AtomicBoolean(false);
        // 按钮视觉反馈
        readRelayParamsBtn.setBackground(Color.CYAN);
        readRelayParamsBtn.setEnabled(false);
        // 设置响应消费者
        Consumer<byte[]> responseConsumer = responseData -> {
            if (operationCompleted.get()) return;
            currentNetwork.setResponseConsumer(null);
            operationCompleted.set(true);
            String hexResponse = bytesToHex(responseData);
            if (hexResponse.startsWith("55AA03")) {
                // 使用解析器解析继电器响应数据
                DellTag55AA03.ParseResult result = DellTag55AA03.parse3(hexResponse, "127.0.0.1", 0);
                if (result != null) {
                    SwingUtilities.invokeLater(() -> {
                        // 这里可以添加更新继电器参数字段的逻辑
                        // 如果继电器参数需要更新到特定面板,可以在这里调用相应的方法
                        updateParameterFields2(result);
                        responseReceived.set(true);
                        JOptionPane.showMessageDialog(this, getString("relay_read_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
                        // 恢复按钮状态
                        readRelayParamsBtn.setBackground(new Color(70, 130, 180));
                        readRelayParamsBtn.setEnabled(true);
                    });
                    return;
                }
            }
            // 响应数据不合法
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(this, getString("invalid_response_data"), getString("error"), JOptionPane.ERROR_MESSAGE);
                readRelayParamsBtn.setBackground(new Color(70, 130, 180));
                readRelayParamsBtn.setEnabled(true);
            });
        };
        // 在独立线程中执行网络操作
        new Thread(() -> {
            currentNetwork.setResponseConsumer(responseConsumer);
            boolean success = sendNetworkDataInternal(data, getString("read.relay.parameters"));
            if (!success) {
                SwingUtilities.invokeLater(() -> {
                    JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
                    currentNetwork.setResponseConsumer(null);
                    readRelayParamsBtn.setBackground(new Color(70, 130, 180));
                    readRelayParamsBtn.setEnabled(true);
                });
                return;
            }
            // 等待响应,最长5秒
            long startTime = System.currentTimeMillis();
            while (!operationCompleted.get() && (System.currentTimeMillis() - startTime) < 5000) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            // 检查是否超时
            if (!operationCompleted.get()) {
                operationCompleted.set(true);
                SwingUtilities.invokeLater(() -> {
                    JOptionPane.showMessageDialog(this, getString("relay_read_timeout"), getString("error"), JOptionPane.ERROR_MESSAGE);
                    currentNetwork.setResponseConsumer(null);
                    readRelayParamsBtn.setBackground(new Color(70, 130, 180));
                    readRelayParamsBtn.setEnabled(true);
                });
            }
        }).start();
    }
    // 修改后的保存继电器参数方法
    private void saveRelayParameters() {
        if (!isOpen || currentNetwork == null) {
            JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        try {
            // 从防撞面板获取继电器参数并构建配置数据
            byte[] relayConfigData = PanelFieldUpdater.collectParametersToConfig2(antiCollisionPanel);
            if (relayConfigData == null) {
                JOptionPane.showMessageDialog(this, getString("invalid_relay_config"), getString("error"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            // 在数据日志窗口显示发送的配置数据
            if (dataLogPanel != null) {
                dataLogPanel.addLogData(relayConfigData, getString("send.save.relay.command"));
            }
            // 按钮视觉反馈
            saveRelayParamsBtn.setBackground(Color.CYAN);
            saveRelayParamsBtn.setEnabled(false);
            boolean success = sendNetworkDataInternal(relayConfigData, getString("save.relay.parameters"));
            SwingUtilities.invokeLater(() -> {
                if (success) {
                    JOptionPane.showMessageDialog(this, getString("relay_save_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
                }
                // 恢复按钮状态
                saveRelayParamsBtn.setBackground(new Color(70, 130, 180));
                saveRelayParamsBtn.setEnabled(true);
            });
        } catch (Exception e) {
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(this, getString("relay_save_failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
                saveRelayParamsBtn.setBackground(new Color(70, 130, 180));
                saveRelayParamsBtn.setEnabled(true);
            });
        }
    }
    /**
     * 更新参数字段到界面 - 新增方法用于继电器参数
     */
    private void updateParameterFields2(DellTag55AA03.ParseResult result) {
        PanelFieldUpdater.updateAllPanels2(result, antiCollisionPanel);
    }
    /**
     * 读取参数 - 新增方法
     */
    private void readParameters() {
        if (!isOpen || currentNetwork == null) {
            JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 根据当前选中的面板决定使用哪个指令和解析方法
        String readCommand;
        final boolean useParse2; // 声明为final
        int selectedPanelIndex = getCurrentSelectedPanelIndex();
        if (selectedPanelIndex == 2) { // 防撞面板的索引为2
            readCommand = READ_CONFIG_CMD2;
            useParse2 = true;
        } else {
            readCommand = READ_CONFIG_CMD;
            useParse2 = false;
        }
        byte[] data = hexStringToByteArray(readCommand);
        if (data == null) {
            JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 新增:在数据日志窗口显示发送的指令
        if (dataLogPanel != null) {
            dataLogPanel.addLogData(data, getString("send.read.config.command"));
        }
        AtomicBoolean responseReceived = new AtomicBoolean(false);
        AtomicBoolean operationCompleted = new AtomicBoolean(false);
        // 按钮视觉反馈
        readParamsBtn.setBackground(Color.GREEN);
        // 设置响应消费者
        Consumer<byte[]> responseConsumer = responseData -> {
            if (operationCompleted.get()) return;
            // 清空响应消费者以避免重复处理
            currentNetwork.setResponseConsumer(null);
            operationCompleted.set(true);
            String hexResponse = bytesToHex(responseData);
            if (hexResponse.startsWith("55AA03")) {
                // 根据面板选择使用parse还是parse2方法
                DellTag55AA03.ParseResult result;
                if (useParse2) {
                    result = DellTag55AA03.parse2(hexResponse, "127.0.0.1", 0);
                } else {
                    result = DellTag55AA03.parse(hexResponse, "127.0.0.1", 0);
                }
                if (result != null) {
                    SwingUtilities.invokeLater(() -> {
                        updateParameterFields(result);
                        JOptionPane.showMessageDialog(this, getString("config_read_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
                        // 恢复按钮状态
                        readParamsBtn.setBackground(new Color(70, 130, 180));
                    });
                    return;
                }
            }
            // 响应数据不合法
            SwingUtilities.invokeLater(() -> {
                //JOptionPane.showMessageDialog(this, getString("invalid_response_data"), getString("error"), JOptionPane.ERROR_MESSAGE);
                readParamsBtn.setBackground(new Color(70, 130, 180));
            });
        };
        // 在独立线程中执行网络操作
        new Thread(() -> {
            currentNetwork.setResponseConsumer(responseConsumer);
            boolean success = sendNetworkDataInternal(data, getString("read.parameters"));
            if (!success) {
                SwingUtilities.invokeLater(() -> {
                    //JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
                    currentNetwork.setResponseConsumer(null);
                    readParamsBtn.setBackground(new Color(70, 130, 180));
                });
                return;
            }
            // 等待响应,最长5秒
            long startTime = System.currentTimeMillis();
            while (!operationCompleted.get() && (System.currentTimeMillis() - startTime) < 5000) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            // 检查是否超时
            if (!operationCompleted.get()) {
                operationCompleted.set(true);
                SwingUtilities.invokeLater(() -> {
                    //JOptionPane.showMessageDialog(this, getString("config_read_timeout"), getString("error"), JOptionPane.ERROR_MESSAGE);
                    currentNetwork.setResponseConsumer(null);
                    readParamsBtn.setBackground(new Color(70, 130, 180));
                });
            }
        }).start();
    }
    /**
     * 更新参数字段到界面 - 新增方法
     */
    private void updateParameterFields(DellTag55AA03.ParseResult result) {
        PanelFieldUpdater.updateAllPanels(result, baseParamPanel, baseStationPanel,
                tagPanel, antiCollisionPanel, upgradePanel);
    }
    /**
     * 保存参数 - 新增方法
     */
    private void saveParameters() {
        if (!isOpen || currentNetwork == null) {
            JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        try {
            // 使用工具类从各个面板收集参数并构建配置数据
            byte[] configData = PanelFieldUpdater.collectParametersToConfig(
                    baseParamPanel, baseStationPanel, tagPanel, antiCollisionPanel, upgradePanel);
            if (configData == null) {
                JOptionPane.showMessageDialog(this, getString("invalid_config_data"), getString("error"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            // 新增:在数据日志窗口显示发送的配置数据
            if (dataLogPanel != null) {
                dataLogPanel.addLogData(configData, getString("send.save.config.command"));
            }
            boolean success = sendNetworkDataInternal(configData, getString("save.parameters"));
            if (success) {
                JOptionPane.showMessageDialog(this, getString("config_save_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
            } else {
                JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, getString("config_save_failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 按钮视觉反馈
        saveParamsBtn.setBackground(Color.GREEN);
        Timer timer = new Timer(500, e -> {
            saveParamsBtn.setBackground(new Color(70, 130, 180));
        });
        timer.setRepeats(false);
        timer.start();
    }
    /**
     * 重启设备 - 新增方法
     */
    private void restartDevice() {
        if (!isOpen || currentNetwork == null) {
            JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        byte[] data = hexStringToByteArray(RESTART_DEVICE_CMD);
        if (data == null) {
            JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 新增:在数据日志窗口显示发送的指令
        if (dataLogPanel != null) {
            dataLogPanel.addLogData(data, getString("send.restart.command"));
        }
        boolean success = sendNetworkDataInternal(data, getString("restart.device"));
        if (success) {
            JOptionPane.showMessageDialog(this, getString("restart_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
        } else {
            JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
        }
        // 按钮视觉反馈
        restartDeviceBtn.setBackground(Color.ORANGE);
        Timer timer = new Timer(500, e -> {
            restartDeviceBtn.setBackground(new Color(70, 130, 180));
        });
        timer.setRepeats(false);
        timer.start();
    }
    /**
     * 恢复出厂设置 - 新增方法
     */
    private void resetFactory() {
        if (!isOpen || currentNetwork == null) {
            JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 恢复出厂设置命令
        byte[] data = hexStringToByteArray(RESET_FACTORY_CMD);
        if (data == null) {
            JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 新增:在数据日志窗口显示发送的指令
        if (dataLogPanel != null) {
            dataLogPanel.addLogData(data, getString("send.reset.factory.command"));
        }
        boolean success = sendNetworkDataInternal(data, getString("reset.factory"));
        if (success) {
            JOptionPane.showMessageDialog(this, getString("reset_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
        } else {
            JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
        }
        // 按钮视觉反馈
        resetFactoryBtn.setBackground(Color.RED);
        Timer timer = new Timer(500, e -> {
            resetFactoryBtn.setBackground(new Color(70, 130, 180));
        });
        timer.setRepeats(false);
        timer.start();
    }
    /**
     * 内部发送网络数据方法 - 根据协议类型选择发送目标
     */
    public boolean sendNetworkDataInternal(byte[] data, String description) {
        if (currentNetwork == null || !isOpen) {
            return false;
        }
        try {
            String protocol = (String) protocolCombo.getSelectedItem();
            boolean success = false;
            if ("TCP Client".equals(protocol)) {
                // TCP Client模式:直接发送到服务端
                success = currentNetwork.sendData(new String(data, java.nio.charset.StandardCharsets.UTF_8));
            } else {
                // UDP或TCP Server模式:发送到选中的客户端
                String selectedClient = (String) clientCombo.getSelectedItem();
                if (selectedClient != null && !selectedClient.isEmpty()) {
                    if (currentNetwork instanceof UdpListener) {
                        // UDP模式:解析IP和端口
                        String[] parts = selectedClient.split(":");
                        if (parts.length == 2) {
                            String ip = parts[0];
                            int port = Integer.parseInt(parts[1]);
                            success = ((UdpListener) currentNetwork).sendDataTo(data, ip, port);
                        }
                    } else if (currentNetwork instanceof TcpServer) {
                        // TCP Server模式:发送到指定客户端
                        success = ((TcpServer) currentNetwork).sendDataToClient(selectedClient, data);
                    }
                } else {
                    JOptionPane.showMessageDialog(this, getString("please.select.client"), getString("error"), JOptionPane.ERROR_MESSAGE);
                    return false;
                }
            }
            if (success && dataLogPanel != null) {
                dataLogPanel.addLogData(data, description);
            }
            return success;
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, getString("send.data.failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
            return false;
        }
    }
    private JPanel createControlPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel.add(new JLabel(getString("protocol.type")));
        protocolTypeLabel = new JLabel(getString("protocol.type"));
        panel.add(protocolTypeLabel);
        protocolCombo = new JComboBox<>(new String[]{"UDP", "TCP Client", "TCP Server"});
        protocolCombo.addActionListener(new ProtocolChangeListener());
        panel.add(protocolCombo);
        hostLabel = new JLabel(getString("local.host.address"));
        panel.add(hostLabel);
        hostAddressField = new JTextField(15);
        panel.add(hostAddressField);
        // 创建主机地址下拉框并填充本地IP地址
        hostAddressCombo = new JComboBox<>();
        populateLocalIPAddresses();
        hostAddressCombo.setEditable(false); // 默认不可编辑
        panel.add(hostAddressCombo);
        portLabel = new JLabel(getString("local.host.port"));
        panel.add(portLabel);
        portField = new JTextField(8);
        panel.add(portField);
        // 使用ButtonUtils创建蓝色样式按钮
        // 使用ButtonUtils创建蓝色样式按钮
        openBtn = ButtonUtils.createBlueButton(getString("open"));
        openBtn.addActionListener(e -> toggleConnection());
        panel.add(openBtn);
        // 添加客户端/发送端下拉框
        clientCombo = new JComboBox<>();
        clientCombo.setEnabled(false);
        clientCombo.setPreferredSize(new Dimension(150, 25));
        panel.add(clientCombo);
        return panel;
    }
    private void toggleConnection() {
        isOpen = !isOpen;
        openBtn.setText(isOpen ? getString("close") : getString("open"));
    /**
     * 获取本地网卡的IP地址并填充到下拉框
     */
    private void populateLocalIPAddresses() {
        List<String> ipAddresses = new ArrayList<>();
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
                while (inetAddresses.hasMoreElements()) {
                    InetAddress inetAddress = inetAddresses.nextElement();
                    // 只添加IPv4地址
                    if (inetAddress.getAddress().length == 4) {
                        ipAddresses.add(inetAddress.getHostAddress());
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
            // 如果获取失败,添加本地回环地址作为备选
            ipAddresses.add("127.0.0.1");
        }
        // 如果没有找到任何IP地址,添加本地回环地址
        if (ipAddresses.isEmpty()) {
            ipAddresses.add("127.0.0.1");
        }
        // 清空下拉框并添加获取到的IP地址
        hostAddressCombo.removeAllItems();
        for (String ip : ipAddresses) {
            hostAddressCombo.addItem(ip);
        }
        // 设置默认选择第一个IP地址
        if (hostAddressCombo.getItemCount() > 0) {
            hostAddressCombo.setSelectedIndex(0);
        }
    }
    /**
     * 清空下拉框并设置为可编辑状态(用于TCP Client模式)
     */
    private void clearAndMakeEditable() {
        hostAddressCombo.removeAllItems();
        hostAddressCombo.setEditable(true);
        hostAddressCombo.setSelectedItem(""); // 清空当前选择
    }
    /**
     * 填充本地IP地址并设置为不可编辑状态(用于UDP和TCP Server模式)
     */
    private void populateAndMakeNonEditable() {
        populateLocalIPAddresses();
        hostAddressCombo.setEditable(false);
    }
    private void toggleConnection() {
        if (!isOpen) {
            openConnection();
        } else {
            closeConnection();
            refreshLocalIPAddresses();
        }
    }
    private void openConnection() {
        String protocol = (String) protocolCombo.getSelectedItem();
        String host = getSelectedHostAddress();
        String portText = portField.getText().trim();
        if (host.isEmpty() || portText.isEmpty()) {
            JOptionPane.showMessageDialog(this, getString("please.fill.host.port"), getString("error"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        try {
            int port = Integer.parseInt(portText);
            switch (protocol) {
                case "UDP":
                    currentNetwork = new UdpListener(host, port);
                    break;
                case "TCP Client":
                    currentNetwork = new TcpClient(host, port);
                    break;
                case "TCP Server":
                    currentNetwork = new TcpServer(host, port);
                    ((TcpServer) currentNetwork).setClientListListener(this::updateClientList);
                    break;
            }
            currentNetwork.setDataListener(new NetworkBase.NetworkDataListener() {
                @Override
                public void onDataReceived(byte[] data, String fromAddress) {
                    // 新增:将接收到的数据输出到数据日志面板
                    if (dataLogPanel != null && data != null ) {
                        String logDescription = "From: " + fromAddress ;
                        dataLogPanel.addLogData(data, logDescription);
                    }
                    // 新增:如果是UDP协议,将发送端地址添加到clientCombo中
                    if ("UDP".equals(protocol)) {
                        addUdpSenderToCombo(fromAddress);
                    }
                }
                @Override
                public void onStatusChanged(String status, boolean isConnected) {
                    SwingUtilities.invokeLater(() -> {
                        System.out.println(status);
                        // 可选:将状态信息也记录到数据日志
                        if (dataLogPanel != null) {
                            dataLogPanel.addLog(status);
                        }
                    });
                }
                @Override
                public void onError(String errorMessage) {
                    SwingUtilities.invokeLater(() -> {
                        JOptionPane.showMessageDialog(NetworkCommunicationPanel.this,
                                errorMessage, getString("error"), JOptionPane.ERROR_MESSAGE);
                        // 记录错误信息到数据日志
                        if (dataLogPanel != null) {
                            dataLogPanel.addLog(getString("error") + ": " + errorMessage);
                        }
                        if (!isOpen) {
                            // 如果连接失败,不更新打开按钮状态
                            return;
                        }
                    });
                }
            });
            boolean success = currentNetwork.start();
            if (success) {
                isOpen = true;
                openBtn.setText(getString("close"));
                clientCombo.setEnabled(true);
                // 记录连接成功信息到数据日志
                if (dataLogPanel != null) {
                    String connectionInfo = protocol + " " + getString("connection.established") + " - " + host + ":" + port;
                    dataLogPanel.addLog(connectionInfo);
                }
                // 新增:UDP模式下设置客户端下拉框的提示文本
                if ("UDP".equals(protocol)) {
                    clientCombo.setToolTipText(getString("data.sender.list"));
                }
            } else {
                // 连接失败,不更新按钮状态
                currentNetwork = null;
            }
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, getString("port.must.be.number"), getString("error"), JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, getString("connection.failed.msg") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
            currentNetwork = null;
        }
    }
    private void closeConnection() {
        if (currentNetwork != null) {
            // 记录关闭连接信息到数据日志
            if (dataLogPanel != null) {
                dataLogPanel.addLog(getString("network.connection.closed"));
            }
            currentNetwork.stop();
            currentNetwork = null;
        }
        isOpen = false;
        openBtn.setText(getString("open"));
        clientCombo.setEnabled(false);
        clientCombo.removeAllItems();
        connectedClients.clear();
    }
    /**
     * 设置数据日志面板引用
     */
    public void setDataLogPanel(DataLogPanel dataLogPanel) {
        this.dataLogPanel = dataLogPanel;
    }
    // 十六进制字符串转字节数组 (从SerialCommunicationPanel复制)
    private byte[] hexStringToByteArray(String s) {
        try {
            int len = s.length();
            byte[] data = new byte[len / 2];
            for (int i = 0; i < len; i += 2) {
                data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                        + Character.digit(s.charAt(i+1), 16));
            }
            return data;
        } catch (Exception e) {
            return null;
        }
    }
    // 字节数组转十六进制字符串 - 新增方法
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
    // 更新客户端列表
    private void updateClientList(java.util.List<String> clients) {
        SwingUtilities.invokeLater(() -> {
            connectedClients = clients;
            clientCombo.removeAllItems();
            for (String client : connectedClients) {
                clientCombo.addItem(client);
            }
        });
    }
    private JPanel createBaseParameterPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        baseParamPanel = new BaseParameterPanel(mainFrame);
        panel.add(baseParamPanel, BorderLayout.CENTER);
        return panel;
    }
    private JPanel createRightPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(null); // 移除面板边框
        // 右侧选项卡
        panel.setBorder(null); // 移除面板边框
        // 右侧选项卡
        rightTabbedPane = new JTabbedPane();
        // 创建各个功能面板
        // 创建各个功能面板
        baseStationPanel = new BaseStationPanel(mainFrame);
        tagPanel = new TagPanel(mainFrame);
        antiCollisionPanel = new AntiCollisionPanel(mainFrame);
        upgradePanel = new UpgradePanel(mainFrame);
        rightTabbedPane.addTab(getString("base.station"), baseStationPanel);
        rightTabbedPane.addTab(getString("tag"), tagPanel);
        rightTabbedPane.addTab(getString("anti.collision"), antiCollisionPanel);
        rightTabbedPane.addTab(getString("upgrade"), upgradePanel);
        panel.add(rightTabbedPane, BorderLayout.CENTER);
        return panel;
    }
    private JPanel createBottomButtonPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        // 使用ButtonUtils创建蓝色样式按钮
        // 使用ButtonUtils创建蓝色样式按钮
        readParamsBtn = ButtonUtils.createBlueButton(getString("read.parameters"));
        saveParamsBtn = ButtonUtils.createBlueButton(getString("save.parameters"));
        restartDeviceBtn = ButtonUtils.createBlueButton(getString("restart.device"));
        resetFactoryBtn = ButtonUtils.createBlueButton(getString("reset.factory"));
        // 新增继电器参数按钮
        readRelayParamsBtn = ButtonUtils.createBlueButton(getString("read.relay.parameters"));
        saveRelayParamsBtn = ButtonUtils.createBlueButton(getString("save.relay.parameters"));
        panel.add(readParamsBtn);
        panel.add(saveParamsBtn);
        panel.add(restartDeviceBtn);
        panel.add(resetFactoryBtn);
        // 添加新按钮
        panel.add(readRelayParamsBtn);
        panel.add(saveRelayParamsBtn);
        return panel;
    }
    public void updateLanguage() {
        // 更新控制面板文本
        // 更新控制面板文本
        openBtn.setText(isOpen ? getString("close") : getString("open"));
        readParamsBtn.setText(getString("read.parameters"));
        saveParamsBtn.setText(getString("save.parameters"));
        restartDeviceBtn.setText(getString("restart.device"));
        resetFactoryBtn.setText(getString("reset.factory"));
        // 更新主机标签和端口标签
        hostLabel.setText(getString("local.host.address"));
        portLabel.setText(getString("local.host.port"));
        // 更新协议选择
        // 更新新按钮文本
        readRelayParamsBtn.setText(getString("read.relay.parameters"));
        saveRelayParamsBtn.setText(getString("save.relay.parameters"));
        // 更新协议类型标签
        if (protocolTypeLabel != null) {
            protocolTypeLabel.setText(getString("protocol.type"));
        }
        // 更新主机标签和端口标签
        String protocol = (String) protocolCombo.getSelectedItem();
        if (protocol != null) {
            updateHostAndPortLabels(protocol);
        }
        // 更新协议选择
        protocolCombo.removeAllItems();
        protocolCombo.addItem("UDP");
        protocolCombo.addItem("TCP Client");
        protocolCombo.addItem("TCP Server");
        // 更新选项卡标题
        // 根据当前协议更新主机地址输入框状态
        if (protocol != null) {
            updateHostAddressFieldState(protocol);
        }
        // 更新选项卡标题
        // 更新选项卡标题
        if (rightTabbedPane != null) {
            rightTabbedPane.setTitleAt(0, getString("base.station"));
            rightTabbedPane.setTitleAt(1, getString("tag"));
            rightTabbedPane.setTitleAt(2, getString("anti.collision"));
            rightTabbedPane.setTitleAt(3, getString("upgrade"));
        }
        // 更新各个功能面板的语言
        // 更新各个功能面板的语言
        baseParamPanel.updateLanguage();
        baseStationPanel.updateLanguage();
        tagPanel.updateLanguage();
        antiCollisionPanel.updateLanguage();
        upgradePanel.updateLanguage();
        revalidate();
        repaint();
    }
    public boolean isOpen() {
        return isOpen;
    }
    private class ProtocolChangeListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String protocol = (String) protocolCombo.getSelectedItem();
            // 添加空值检查
            if (protocol == null) {
                return;
            }
            updateHostAndPortLabels(protocol);
            updateHostAddressFieldState(protocol);
            // 根据协议类型更新客户端下拉框的提示文本
            switch (protocol) {
                case "UDP":
                    hostLabel.setText(getString("local.host.address"));
                    portLabel.setText(getString("local.host.port"));
                    break;
                case "TCP Client":
                    hostLabel.setText(getString("remote.host.address"));
                    portLabel.setText(getString("remote.host.port"));
                    clientCombo.setToolTipText(getString("data.sender.list"));
                    break;
                case "TCP Server":
                    hostLabel.setText(getString("local.host.address"));
                    portLabel.setText(getString("local.host.port"));
                    clientCombo.setToolTipText(getString("client.connection.list"));
                    break;
                case "TCP Client":
                    clientCombo.setToolTipText(getString("not.connected"));
                    clientCombo.setEnabled(false);
                    break;
            }
        }
    }
    /**
     * 根据协议类型更新主机和端口标签
     */
    private void updateHostAndPortLabels(String protocol) {
        switch (protocol) {
            case "UDP":
                hostLabel.setText(getString("local.host.address"));
                portLabel.setText(getString("local.host.port"));
                break;
            case "TCP Client":
                hostLabel.setText(getString("remote.host.address"));
                portLabel.setText(getString("remote.host.port"));
                break;
            case "TCP Server":
                hostLabel.setText(getString("local.host.address"));
                portLabel.setText(getString("local.host.port"));
                break;
        }
    }
    /**
     * 根据协议类型更新主机地址输入框状态
     */
    private void updateHostAddressFieldState(String protocol) {
        switch (protocol) {
            case "UDP":
            case "TCP Server":
                populateAndMakeNonEditable();
                break;
            case "TCP Client":
                clearAndMakeEditable();
                break;
        }
    }
    private String getString(String key) {
        return mainFrame.getString(key);
    }
    /**
     * 获取当前选择的主机地址
     * @return 选择的主机地址
     */
    public String getSelectedHostAddress() {
        return (String) hostAddressCombo.getSelectedItem();
    }
    /**
     * 设置选中的主机地址
     * @param address 要设置的IP地址
     */
    public void setSelectedHostAddress(String address) {
        hostAddressCombo.setSelectedItem(address);
    }
    /**
     * 手动刷新本地IP地址列表
     */
    public void refreshLocalIPAddresses() {
        populateLocalIPAddresses();
    }
    // 添加清理资源的方法
    public void cleanup() {
        if (currentNetwork != null) {
            currentNetwork.stop();
            currentNetwork = null;
        }
    }
    /**
     * 将UDP发送端地址添加到客户端下拉框
     * @param senderAddress 发送端地址 (格式: IP:端口)
     */
    private void addUdpSenderToCombo(String senderAddress) {
        SwingUtilities.invokeLater(() -> {
            // 检查是否已存在相同的地址
            boolean exists = false;
            for (int i = 0; i < clientCombo.getItemCount(); i++) {
                if (senderAddress.equals(clientCombo.getItemAt(i))) {
                    exists = true;
                    break;
                }
            }
            // 如果不存在,则添加到下拉框
            if (!exists) {
                clientCombo.addItem(senderAddress);
                System.out.println("添加UDP发送端: " + senderAddress);
            }
        });
    }
    /**
     * 清空UDP发送端列表
     */
    public void clearUdpSenders() {
        SwingUtilities.invokeLater(() -> {
            clientCombo.removeAllItems();
        });
    }
    /**
     * 获取当前选中的面板索引 - 新增方法
     * @return 当前选中的面板索引 (0-基站, 1-标签, 2-防撞, 3-升级)
     */
    public int getCurrentSelectedPanelIndex() {
        if (rightTabbedPane == null) {
            return 0; // 默认基站面板
        }
        return rightTabbedPane.getSelectedIndex();
    }
    /**
     * 获取当前选中的客户端
     */
    public String getSelectedClient() {
        return (String) clientCombo.getSelectedItem();
    }
    /**
     * 发送UDP数据到指定地址
     */
    public boolean sendUdpData(byte[] data, String ip, int port, String description) {
        if (currentNetwork instanceof UdpListener) {
            UdpListener udp = (UdpListener) currentNetwork;
            boolean success = udp.sendDataTo(data, ip, port);
            if (success && dataLogPanel != null) {
                dataLogPanel.addLogData(data, description + " -> " + ip + ":" + port);
            }
            return success;
        }
        return false;
    }
    /**
     * 发送TCP数据到指定客户端
     */
    public boolean sendTcpDataToClient(String clientKey, byte[] data, String description) {
        if (currentNetwork instanceof TcpServer) {
            TcpServer tcpServer = (TcpServer) currentNetwork;
            try {
                boolean success = tcpServer.sendDataToClient(clientKey, data);
                if (success && dataLogPanel != null) {
                    dataLogPanel.addLogData(data, description + " -> " + clientKey);
                }
                return success;
            } catch (Exception e) {
                JOptionPane.showMessageDialog(this, getString("send.data.failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
                return false;
            }
        }
        return false;
    }
    /**
     * 获取当前网络实例
     */
    public NetworkBase getCurrentNetwork() {
        return currentNetwork;
    }
}