From 8d662de2fd262b3a485f16e197cb4d0ca2a61cdf Mon Sep 17 00:00:00 2001
From: zsh_root <979909237@qq.com>
Date: 星期三, 10 十二月 2025 17:03:47 +0800
Subject: [PATCH] 发布版V1.0

---
 src/home/NetworkCommunicationPanel.java | 1075 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 996 insertions(+), 79 deletions(-)

diff --git a/src/home/NetworkCommunicationPanel.java b/src/home/NetworkCommunicationPanel.java
index e8ad19e..d8e1c70 100644
--- a/src/home/NetworkCommunicationPanel.java
+++ b/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;
+        }
+
+        // 鍦ㄦ暟鎹棩蹇楃獥鍙f樉绀哄彂閫佺殑鎸囦护
+        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")) {
+                // 浣跨敤瑙f瀽鍣ㄨВ鏋愮户鐢靛櫒鍝嶅簲鏁版嵁
+                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;
+            }
+
+            // 鍦ㄦ暟鎹棩蹇楃獥鍙f樉绀哄彂閫佺殑閰嶇疆鏁版嵁
+            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;
+        }
+
+        // 鏍规嵁褰撳墠閫変腑鐨勯潰鏉垮喅瀹氫娇鐢ㄥ摢涓寚浠ゅ拰瑙f瀽鏂规硶
+        String readCommand;
+        final boolean useParse2; // 澹版槑涓篺inal
+
+        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鎴朤CP Server妯″紡锛氬彂閫佸埌閫変腑鐨勫鎴风
+                String selectedClient = (String) clientCombo.getSelectedItem();
+                if (selectedClient != null && !selectedClient.isEmpty()) {
+                    if (currentNetwork instanceof UdpListener) {
+                        // UDP妯″紡锛氳В鏋怚P鍜岀鍙�
+                        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"));
+
+    /**
+     * 鑾峰彇鏈湴缃戝崱鐨処P鍦板潃骞跺~鍏呭埌涓嬫媺妗�
+     */
+    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();
+
+                    // 鍙坊鍔營Pv4鍦板潃
+                    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);
+        }
+
+        // 璁剧疆榛樿閫夋嫨绗竴涓狪P鍦板潃
+        if (hostAddressCombo.getItemCount() > 0) {
+            hostAddressCombo.setSelectedIndex(0);
+        }
     }
-    
+
+    /**
+     * 娓呯┖涓嬫媺妗嗗苟璁剧疆涓哄彲缂栬緫鐘舵�侊紙鐢ㄤ簬TCP Client妯″紡锛�
+     */
+    private void clearAndMakeEditable() {
+        hostAddressCombo.removeAllItems();
+        hostAddressCombo.setEditable(true);
+        hostAddressCombo.setSelectedItem(""); // 娓呯┖褰撳墠閫夋嫨
+    }
+
+    /**
+     * 濉厖鏈湴IP鍦板潃骞惰缃负涓嶅彲缂栬緫鐘舵�侊紙鐢ㄤ簬UDP鍜孴CP 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鍗忚锛屽皢鍙戦�佺鍦板潃娣诲姞鍒癱lientCombo涓�
+                    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);
+                }
+
+                // 鏂板锛歎DP妯″紡涓嬭缃鎴风涓嬫媺妗嗙殑鎻愮ず鏂囨湰
+                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;
+    }
+
+    // 鍗佸叚杩涘埗瀛楃涓茶浆瀛楄妭鏁扮粍 (浠嶴erialCommunicationPanel澶嶅埗)
+    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"));
+        }
+
+        // 鏇存柊涓绘満鏍囩鍜岀鍙f爣绛�
+        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;
             }
         }
     }
-    
+
+    /**
+     * 鏍规嵁鍗忚绫诲瀷鏇存柊涓绘満鍜岀鍙f爣绛�
+     */
+    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;
+        }
+    }
+
+    /**
+     * 灏哢DP鍙戦�佺鍦板潃娣诲姞鍒板鎴风涓嬫媺妗�
+     * @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();
+    }
+
+    /**
+     * 鍙戦�乁DP鏁版嵁鍒版寚瀹氬湴鍧�
+     */
+    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;
+    }
+
+    /**
+     * 鍙戦�乀CP鏁版嵁鍒版寚瀹氬鎴风
+     */
+    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;
+    }
+
+
 }
\ No newline at end of file

--
Gitblit v1.10.0