| | |
| | | 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; |
| | |
| | | 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; |
| | | } |
| | | |
| | | |
| | | } |