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 JComboBox protocolCombo; private JComboBox hostAddressCombo; // 改为下拉框 private JTextField portField; private JLabel protocolTypeLabel, hostLabel, portLabel; private JButton openBtn; private JTabbedPane rightTabbedPane; private BaseParameterPanel baseParamPanel; private BaseStationPanel baseStationPanel; private TagPanel tagPanel; private AntiCollisionPanel antiCollisionPanel; private UpgradePanel upgradePanel; private JButton readParamsBtn, saveParamsBtn, restartDeviceBtn, resetFactoryBtn; private boolean isOpen = false; // 在类变量声明部分添加新按钮 private JButton readRelayParamsBtn, saveRelayParamsBtn; // 新增:数据日志面板引用 private DataLogPanel dataLogPanel; private JComboBox clientCombo; // 客户端/发送端下拉框 private NetworkBase currentNetwork; private java.util.List 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); // 移除面板边框 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 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 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)); 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); // 创建主机地址下拉框并填充本地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创建蓝色样式按钮 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; } /** * 获取本地网卡的IP地址并填充到下拉框 */ private void populateLocalIPAddresses() { List ipAddresses = new ArrayList<>(); try { Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); while (networkInterfaces.hasMoreElements()) { NetworkInterface networkInterface = networkInterfaces.nextElement(); Enumeration 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 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); // 移除面板边框 // 右侧选项卡 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创建蓝色样式按钮 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")); // 更新新按钮文本 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": clientCombo.setToolTipText(getString("data.sender.list")); break; case "TCP Server": 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; } }