| | |
| | | package PublicPannel; |
| | | |
| | | import javax.swing.*; |
| | | import home.ButtonUtils; |
| | | import home.MainFrame; |
| | | |
| | | import Ymodem.YModem; |
| | | import home.*; |
| | | import jiexi.DellTag55AA03; |
| | | |
| | | import java.awt.*; |
| | | import java.awt.event.ActionListener; |
| | | import java.io.*; |
| | | import java.net.Socket; |
| | | |
| | | public class UpgradePanel extends JPanel { |
| | | /** |
| | |
| | | private JTextField filePathField; |
| | | private JButton selectBinBtn; |
| | | private JProgressBar progressBar; |
| | | private JLabel selectFileLabel; // 新增:用于文件选择标签 |
| | | private JLabel progressLabel; // 新增:用于进度标签 |
| | | private JLabel selectFileLabel; |
| | | private JLabel progressLabel; |
| | | |
| | | // 新增:通信方式选择 |
| | | private JComboBox<String> communicationTypeCombo; |
| | | private JLabel communicationTypeLabel; |
| | | |
| | | // 串口服务实例 |
| | | private SerialPortService serialService; |
| | | // 网络通信面板引用 |
| | | private NetworkCommunicationPanel networkPanel; |
| | | |
| | | // 新增:升级相关状态 |
| | | private volatile boolean upgradeInProgress = false; |
| | | private volatile boolean cancelUpgrade = false; |
| | | |
| | | public UpgradePanel(MainFrame mainFrame) { |
| | | this.mainFrame = mainFrame; |
| | | this.serialService = SerialCommunicationPanel.getSerialService(); |
| | | initializeUI(); |
| | | } |
| | | |
| | | private void initializeUI() { |
| | | setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); |
| | | |
| | | // 内容面板 - 使用垂直布局,与BaseParameterPanel一致 |
| | | // 内容面板 |
| | | JPanel contentPanel = new JPanel(); |
| | | contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); |
| | | |
| | | // 文件选择面板 |
| | | JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | // 通信方式选择面板 |
| | | JPanel communicationPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | communicationTypeLabel = new JLabel(mainFrame.getString("communication.type")); |
| | | communicationTypeCombo = new JComboBox<>(new String[]{ |
| | | mainFrame.getString("serial"), |
| | | mainFrame.getString("tcp.client"), |
| | | mainFrame.getString("tcp.server"), |
| | | mainFrame.getString("udp") |
| | | }); |
| | | communicationPanel.add(communicationTypeLabel); |
| | | communicationPanel.add(communicationTypeCombo); |
| | | |
| | | // 文件选择面板 |
| | | JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | filePathField = new JTextField(); |
| | | filePathField.setEditable(false); |
| | | filePathField.setPreferredSize(new Dimension(200, 25)); // 设置文件路径宽度 |
| | | filePathField.setPreferredSize(new Dimension(200, 25)); |
| | | |
| | | selectBinBtn = ButtonUtils.createBlueButton(mainFrame.getString("select.bin.file")); |
| | | selectBinBtn.addActionListener(e -> selectBinFile()); |
| | | |
| | | // 使用变量引用标签,以便后续更新 |
| | | selectFileLabel = new JLabel(mainFrame.getString("select.bin.file")); |
| | | |
| | | filePanel.add(selectFileLabel); |
| | | filePanel.add(filePathField); |
| | | filePanel.add(selectBinBtn); |
| | | |
| | | // 进度条和升级按钮面板 - 放在同一行 |
| | | // 进度条和升级按钮面板 |
| | | JPanel progressButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
| | | |
| | | // 进度条 |
| | | progressBar = new JProgressBar(0, 100); |
| | | progressBar.setStringPainted(true); |
| | | progressBar.setVisible(false); |
| | | progressBar.setPreferredSize(new Dimension(200, 25)); // 设置进度条宽度 |
| | | progressBar.setPreferredSize(new Dimension(200, 25)); |
| | | |
| | | // 升级按钮 |
| | | upgradeBtn = ButtonUtils.createBlueButton(mainFrame.getString("start.upgrade")); |
| | | upgradeBtn.addActionListener(e -> startUpgrade()); |
| | | |
| | | // 使用变量引用进度标签,以便后续更新 |
| | | progressLabel = new JLabel(mainFrame.getString("upgrade.progress")); // 需要在语言资源文件中添加"upgrade.progress"键 |
| | | progressLabel = new JLabel(mainFrame.getString("upgrade.progress")); |
| | | |
| | | progressButtonPanel.add(progressLabel); |
| | | progressButtonPanel.add(progressBar); |
| | | progressButtonPanel.add(upgradeBtn); |
| | | |
| | | // 设置固定高度 |
| | | // 设置固定高度 |
| | | communicationPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | filePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | progressButtonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | |
| | | // 将所有组件添加到内容面板 |
| | | contentPanel.add(Box.createVerticalStrut(10)); // 顶部10像素间距 |
| | | // 将所有组件添加到内容面板 |
| | | contentPanel.add(Box.createVerticalStrut(10)); |
| | | contentPanel.add(communicationPanel); |
| | | contentPanel.add(filePanel); |
| | | contentPanel.add(progressButtonPanel); |
| | | |
| | | // 添加内容面板,不添加滚动面板 |
| | | add(contentPanel); |
| | | } |
| | | |
| | |
| | | |
| | | int result = fileChooser.showOpenDialog(this); |
| | | if (result == JFileChooser.APPROVE_OPTION) { |
| | | // 将选择的文件路径显示在文件路径框中 |
| | | String selectedFile = fileChooser.getSelectedFile().getAbsolutePath(); |
| | | filePathField.setText(selectedFile); |
| | | |
| | |
| | | } |
| | | |
| | | private void startUpgrade() { |
| | | // 检查升级条件 |
| | | // 检查升级条件 |
| | | if (filePathField.getText().isEmpty()) { |
| | | JOptionPane.showMessageDialog(this, |
| | | mainFrame.getString("please.select.file.first"), |
| | |
| | | return; |
| | | } |
| | | |
| | | progressBar.setVisible(true); |
| | | upgradeBtn.setEnabled(false); |
| | | |
| | | // 模拟升级进度 |
| | | Timer timer = new Timer(100, null); |
| | | ActionListener actionListener = new ActionListener() { |
| | | int progress = 0; |
| | | |
| | | @Override |
| | | public void actionPerformed(java.awt.event.ActionEvent e) { |
| | | progress += 5; |
| | | progressBar.setValue(progress); |
| | | |
| | | if (progress >= 100) { |
| | | ((Timer) e.getSource()).stop(); |
| | | upgradeBtn.setEnabled(true); |
| | | JOptionPane.showMessageDialog(UpgradePanel.this, |
| | | mainFrame.getString("upgrade.completed"), |
| | | mainFrame.getString("success"), |
| | | JOptionPane.INFORMATION_MESSAGE); |
| | | // 检查通信连接状态 |
| | | String communicationType = (String) communicationTypeCombo.getSelectedItem(); |
| | | if (!checkCommunicationStatus(communicationType)) { |
| | | return; |
| | | } |
| | | |
| | | // 对于网络升级,检查是否选择了客户端 |
| | | if (!communicationType.equals(mainFrame.getString("serial"))) { |
| | | if (!checkSelectedClient()) { |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // 确认升级 |
| | | int result = JOptionPane.showConfirmDialog(this, |
| | | mainFrame.getString("upgrade.confirm.message"), |
| | | mainFrame.getString("confirm.upgrade"), |
| | | JOptionPane.YES_NO_OPTION, |
| | | JOptionPane.QUESTION_MESSAGE); |
| | | |
| | | if (result != JOptionPane.YES_OPTION) { |
| | | return; |
| | | } |
| | | |
| | | upgradeBtn.setEnabled(false); |
| | | selectBinBtn.setEnabled(false); |
| | | progressBar.setVisible(true); |
| | | progressBar.setValue(0); |
| | | upgradeInProgress = true; |
| | | cancelUpgrade = false; |
| | | |
| | | String filePath = filePathField.getText(); |
| | | |
| | | new Thread(() -> { |
| | | int retryCount = 0; |
| | | final int maxRetries = 3; |
| | | |
| | | try { |
| | | // 发送升级命令 |
| | | boolean success = sendUpgradeCommand(communicationType); |
| | | if (!success) { |
| | | throw new IOException("Failed to send upgrade command"); |
| | | } |
| | | |
| | | // 等待设备准备升级 |
| | | Thread.sleep(1000); |
| | | |
| | | // 执行升级 |
| | | if (communicationType.equals(mainFrame.getString("serial"))) { |
| | | performSerialUpgrade(filePath); |
| | | } else { |
| | | performNetworkUpgrade(filePath, communicationType); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | if (retryCount < maxRetries && !cancelUpgrade) { |
| | | retryCount++; |
| | | try { |
| | | Thread.sleep(1000); |
| | | // 可以在这里添加重试逻辑 |
| | | } catch (InterruptedException ie) { |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } else { |
| | | SwingUtilities.invokeLater(() -> { |
| | | if (!cancelUpgrade) { |
| | | JOptionPane.showMessageDialog(this, |
| | | "升级失败" + ": " + e.getMessage(), |
| | | "错误", |
| | | JOptionPane.ERROR_MESSAGE); |
| | | } |
| | | restoreUIAfterUpgrade(); |
| | | }); |
| | | } |
| | | } finally { |
| | | restoreUIAfterUpgrade(); |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | /** |
| | | * 检查通信连接状态 |
| | | */ |
| | | private boolean checkCommunicationStatus(String communicationType) { |
| | | if (communicationType.equals(mainFrame.getString("serial"))) { |
| | | if (!serialService.isOpen()) { |
| | | JOptionPane.showMessageDialog(this, |
| | | "请先打开串口连接", |
| | | "错误", |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return false; |
| | | } |
| | | } else { |
| | | // 获取网络通信面板 |
| | | if (networkPanel == null) { |
| | | networkPanel = mainFrame.getNetworkCommunicationPanel(); |
| | | } |
| | | if (networkPanel == null || !networkPanel.isOpen()) { |
| | | JOptionPane.showMessageDialog(this, |
| | | "请先打开网络连接", |
| | | "错误", |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 检查是否选择了客户端(针对网络升级) |
| | | */ |
| | | private boolean checkSelectedClient() { |
| | | if (networkPanel == null) { |
| | | networkPanel = mainFrame.getNetworkCommunicationPanel(); |
| | | } |
| | | |
| | | // 获取当前选中的客户端 |
| | | String selectedClient = networkPanel.getSelectedClient(); |
| | | if (selectedClient == null || selectedClient.isEmpty()) { |
| | | JOptionPane.showMessageDialog(this, |
| | | "请先选择要升级的客户端", |
| | | "错误", |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 发送升级命令 |
| | | */ |
| | | private boolean sendUpgradeCommand(String communicationType) { |
| | | byte[] upgradeCommand = DellTag55AA03.shengjizhiling(); |
| | | |
| | | if (communicationType.equals(mainFrame.getString("serial"))) { |
| | | // 串口升级期间停止数据捕获 |
| | | serialService.stopCapture(); |
| | | return serialService.send(upgradeCommand); |
| | | } else { |
| | | // 网络升级 |
| | | return sendNetworkData(upgradeCommand, "发送升级指令"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 执行串口升级 |
| | | */ |
| | | private void performSerialUpgrade(String filePath) throws Exception { |
| | | InputStream inputStream = serialService.getInputStream(); |
| | | OutputStream outputStream = serialService.getOutputStream(); |
| | | |
| | | if (inputStream == null || outputStream == null) { |
| | | throw new IOException("串口不可用"); |
| | | } |
| | | |
| | | YModem ymodem = new YModem(inputStream, outputStream); |
| | | File file = new File(filePath); |
| | | |
| | | YModem.ProgressCallback progressCallback = new YModem.ProgressCallback() { |
| | | @Override |
| | | public void onProgress(int currentBlock, int totalBlocks) { |
| | | int progress = (int) ((currentBlock * 100.0) / totalBlocks); |
| | | SwingUtilities.invokeLater(() -> { |
| | | progressBar.setValue(progress); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | timer.addActionListener(actionListener); |
| | | timer.start(); |
| | | ymodem.send(file.toPath(), progressCallback); |
| | | |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(this, "升级成功", "成功", JOptionPane.INFORMATION_MESSAGE); |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 执行网络升级 |
| | | */ |
| | | private void performNetworkUpgrade(String filePath, String communicationType) throws Exception { |
| | | File file = new File(filePath); |
| | | |
| | | // 获取选中的客户端信息 |
| | | String selectedClient = networkPanel.getSelectedClient(); |
| | | if (selectedClient == null || selectedClient.isEmpty()) { |
| | | throw new IOException("未选择客户端"); |
| | | } |
| | | |
| | | // 解析客户端地址 |
| | | String[] clientParts = selectedClient.split(":"); |
| | | if (clientParts.length != 2) { |
| | | throw new IOException("客户端地址格式错误: " + selectedClient); |
| | | } |
| | | |
| | | String clientIp = clientParts[0]; |
| | | int clientPort; |
| | | try { |
| | | clientPort = Integer.parseInt(clientParts[1]); |
| | | } catch (NumberFormatException e) { |
| | | throw new IOException("客户端端口格式错误: " + clientParts[1]); |
| | | } |
| | | |
| | | // 创建网络输入输出流适配器 |
| | | NetworkStreamAdapter streamAdapter = new NetworkStreamAdapter(networkPanel, communicationType, clientIp, clientPort); |
| | | InputStream inputStream = streamAdapter.getInputStream(); |
| | | OutputStream outputStream = streamAdapter.getOutputStream(); |
| | | |
| | | if (inputStream == null || outputStream == null) { |
| | | throw new IOException("网络流不可用"); |
| | | } |
| | | |
| | | YModem ymodem = new YModem(inputStream, outputStream); |
| | | |
| | | YModem.ProgressCallback progressCallback = new YModem.ProgressCallback() { |
| | | @Override |
| | | public void onProgress(int currentBlock, int totalBlocks) { |
| | | int progress = (int) ((currentBlock * 100.0) / totalBlocks); |
| | | SwingUtilities.invokeLater(() -> { |
| | | progressBar.setValue(progress); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | try { |
| | | ymodem.send(file.toPath(), progressCallback); |
| | | |
| | | if (!cancelUpgrade) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(UpgradePanel.this, |
| | | "网络升级成功", "成功", JOptionPane.INFORMATION_MESSAGE); |
| | | }); |
| | | } |
| | | } catch (Exception e) { |
| | | if (!cancelUpgrade) { |
| | | throw e; |
| | | } |
| | | } finally { |
| | | streamAdapter.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 发送网络数据 |
| | | */ |
| | | private boolean sendNetworkData(byte[] data, String description) { |
| | | if (networkPanel == null) { |
| | | networkPanel = mainFrame.getNetworkCommunicationPanel(); |
| | | } |
| | | |
| | | if (networkPanel != null) { |
| | | // 使用NetworkCommunicationPanel的发送方法 |
| | | return networkPanel.sendNetworkDataInternal(data, description); |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 恢复UI状态 |
| | | */ |
| | | private void restoreUIAfterUpgrade() { |
| | | SwingUtilities.invokeLater(() -> { |
| | | upgradeInProgress = false; |
| | | upgradeBtn.setEnabled(true); |
| | | selectBinBtn.setEnabled(true); |
| | | progressBar.setVisible(false); |
| | | progressBar.setValue(0); |
| | | |
| | | // 重新启动串口数据捕获(如果是串口升级) |
| | | if (serialService != null) { |
| | | serialService.startCapture(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 取消升级 |
| | | */ |
| | | public void cancelUpgrade() { |
| | | if (upgradeInProgress) { |
| | | cancelUpgrade = true; |
| | | upgradeInProgress = false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置网络通信面板引用 |
| | | */ |
| | | public void setNetworkCommunicationPanel(NetworkCommunicationPanel networkPanel) { |
| | | this.networkPanel = networkPanel; |
| | | } |
| | | |
| | | public void updateLanguage() { |
| | | // 更新按钮文本 |
| | | // 更新通信方式选择 |
| | | communicationTypeLabel.setText(mainFrame.getString("communication.type")); |
| | | communicationTypeCombo.removeAllItems(); |
| | | communicationTypeCombo.addItem(mainFrame.getString("serial")); |
| | | communicationTypeCombo.addItem(mainFrame.getString("tcp.client")); |
| | | communicationTypeCombo.addItem(mainFrame.getString("tcp.server")); |
| | | communicationTypeCombo.addItem(mainFrame.getString("udp")); |
| | | |
| | | // 更新按钮文本 |
| | | selectBinBtn.setText(mainFrame.getString("select.bin.file")); |
| | | upgradeBtn.setText(mainFrame.getString("start.upgrade")); |
| | | |
| | | // 更新标签文本 |
| | | // 更新标签文本 |
| | | selectFileLabel.setText(mainFrame.getString("select.bin.file")); |
| | | progressLabel.setText(mainFrame.getString("upgrade.progress")); // 需要在语言资源文件中添加"upgrade.progress"键 |
| | | |
| | | // 更新文件选择器对话框标题 |
| | | // 注意:这里无法直接更新已创建的JFileChooser,但下次打开时会使用新的文本 |
| | | progressLabel.setText(mainFrame.getString("upgrade.progress")); |
| | | |
| | | revalidate(); |
| | | repaint(); |
| | | } |
| | | /** |
| | | * 网络流适配器 - 内部类 |
| | | * 用于将网络通信适配为YModem所需的InputStream和OutputStream |
| | | */ |
| | | private class NetworkStreamAdapter { |
| | | private NetworkCommunicationPanel networkPanel; |
| | | private String communicationType; |
| | | private String clientIp; |
| | | private int clientPort; |
| | | private PipedInputStream inputStream; |
| | | private PipedOutputStream outputStream; |
| | | private boolean isConnected = false; |
| | | |
| | | // 用于数据接收的管道 |
| | | private PipedInputStream receiverInputStream; |
| | | private PipedOutputStream receiverOutputStream; |
| | | |
| | | // 保存原始的数据监听器 |
| | | private NetworkBase.NetworkDataListener originalDataListener; |
| | | |
| | | public NetworkStreamAdapter(NetworkCommunicationPanel networkPanel, String communicationType, |
| | | String clientIp, int clientPort) { |
| | | this.networkPanel = networkPanel; |
| | | this.communicationType = communicationType; |
| | | this.clientIp = clientIp; |
| | | this.clientPort = clientPort; |
| | | initializeStreams(); |
| | | setupNetworkDataListener(); |
| | | } |
| | | |
| | | private void initializeStreams() { |
| | | try { |
| | | // 创建管道流用于数据发送 |
| | | inputStream = new PipedInputStream(8192); // 增加缓冲区大小 |
| | | outputStream = new PipedOutputStream(inputStream); |
| | | |
| | | // 创建管道流用于数据接收 |
| | | receiverInputStream = new PipedInputStream(8192); |
| | | receiverOutputStream = new PipedOutputStream(receiverInputStream); |
| | | |
| | | isConnected = true; |
| | | System.out.println("网络流适配器初始化成功"); |
| | | } catch (Exception e) { |
| | | System.err.println("初始化网络流失败: " + e.getMessage()); |
| | | isConnected = false; |
| | | throw new RuntimeException("网络流初始化失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置网络数据监听器 |
| | | */ |
| | | private void setupNetworkDataListener() { |
| | | try { |
| | | // 获取网络通信面板的当前网络实例 |
| | | NetworkBase currentNetwork = networkPanel.getCurrentNetwork(); |
| | | if (currentNetwork == null) { |
| | | System.err.println("网络连接未建立"); |
| | | return; |
| | | } |
| | | |
| | | // 保存原来的数据监听器 |
| | | originalDataListener = currentNetwork.getDataListener(); |
| | | |
| | | // 创建升级专用的数据监听器 |
| | | NetworkBase.NetworkDataListener upgradeDataListener = new NetworkBase.NetworkDataListener() { |
| | | @Override |
| | | public void onDataReceived(byte[] data, String fromAddress) { |
| | | // 检查数据是否来自目标客户端 |
| | | String expectedAddress = clientIp + ":" + clientPort; |
| | | if (expectedAddress.equals(fromAddress)) { |
| | | try { |
| | | // 将接收到的数据写入接收管道,供YModem读取 |
| | | if (receiverOutputStream != null && !cancelUpgrade) { |
| | | receiverOutputStream.write(data); |
| | | receiverOutputStream.flush(); |
| | | |
| | | // 调试信息 |
| | | System.out.println("接收到升级响应数据,长度: " + data.length + ",来自: " + fromAddress); |
| | | } |
| | | } catch (IOException e) { |
| | | System.err.println("写入接收管道失败: " + e.getMessage()); |
| | | if (!cancelUpgrade) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(UpgradePanel.this, |
| | | "升级数据接收失败: " + e.getMessage(), |
| | | "错误", JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } |
| | | } |
| | | } else { |
| | | // 非目标客户端的数据,可以记录日志但忽略 |
| | | System.out.println("忽略非目标客户端数据,来自: " + fromAddress + ",期望: " + expectedAddress); |
| | | } |
| | | |
| | | // 同时调用原来的监听器,保持其他功能正常 |
| | | if (originalDataListener != null) { |
| | | originalDataListener.onDataReceived(data, fromAddress); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onStatusChanged(String status, boolean isConnected) { |
| | | // 传递状态变化给原来的监听器 |
| | | if (originalDataListener != null) { |
| | | originalDataListener.onStatusChanged(status, isConnected); |
| | | } |
| | | |
| | | // 如果连接断开且正在升级,需要处理 |
| | | if (!isConnected && upgradeInProgress) { |
| | | System.err.println("网络连接断开,升级可能失败"); |
| | | if (!cancelUpgrade) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(UpgradePanel.this, |
| | | "网络连接已断开,升级失败", |
| | | "错误", JOptionPane.ERROR_MESSAGE); |
| | | cancelUpgrade = true; |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onError(String errorMessage) { |
| | | // 传递错误给原来的监听器 |
| | | if (originalDataListener != null) { |
| | | originalDataListener.onError(errorMessage); |
| | | } |
| | | |
| | | // 如果正在升级,需要处理错误 |
| | | if (upgradeInProgress && !cancelUpgrade) { |
| | | System.err.println("升级过程中发生网络错误: " + errorMessage); |
| | | SwingUtilities.invokeLater(() -> { |
| | | JOptionPane.showMessageDialog(UpgradePanel.this, |
| | | "网络错误: " + errorMessage, |
| | | "错误", JOptionPane.ERROR_MESSAGE); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 设置新的数据监听器 |
| | | currentNetwork.setDataListener(upgradeDataListener); |
| | | |
| | | System.out.println("升级数据监听器已设置,目标客户端: " + clientIp + ":" + clientPort); |
| | | |
| | | } catch (Exception e) { |
| | | System.err.println("设置网络数据监听器失败: " + e.getMessage()); |
| | | throw new RuntimeException("网络数据监听器初始化失败", e); |
| | | } |
| | | } |
| | | |
| | | public InputStream getInputStream() { |
| | | return receiverInputStream; |
| | | } |
| | | |
| | | public OutputStream getOutputStream() { |
| | | return new NetworkOutputStream(); |
| | | } |
| | | |
| | | public void close() { |
| | | try { |
| | | // 恢复原始的数据监听器 |
| | | if (networkPanel != null && networkPanel.getCurrentNetwork() != null && originalDataListener != null) { |
| | | networkPanel.getCurrentNetwork().setDataListener(originalDataListener); |
| | | System.out.println("已恢复原始数据监听器"); |
| | | } |
| | | |
| | | if (inputStream != null) inputStream.close(); |
| | | if (outputStream != null) outputStream.close(); |
| | | if (receiverInputStream != null) receiverInputStream.close(); |
| | | if (receiverOutputStream != null) receiverOutputStream.close(); |
| | | |
| | | System.out.println("网络流适配器已关闭"); |
| | | } catch (IOException e) { |
| | | System.err.println("关闭网络流失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 网络输出流实现 |
| | | * 将YModem写入的数据通过网络发送到指定客户端 |
| | | */ |
| | | private class NetworkOutputStream extends OutputStream { |
| | | @Override |
| | | public void write(int b) throws IOException { |
| | | write(new byte[]{(byte) b}, 0, 1); |
| | | } |
| | | |
| | | @Override |
| | | public void write(byte[] b, int off, int len) throws IOException { |
| | | if (cancelUpgrade) { |
| | | throw new IOException("升级已取消"); |
| | | } |
| | | |
| | | byte[] dataToSend = new byte[len]; |
| | | System.arraycopy(b, off, dataToSend, 0, len); |
| | | |
| | | boolean success = false; |
| | | |
| | | if (communicationType.equals(mainFrame.getString("udp"))) { |
| | | // UDP模式发送 |
| | | success = networkPanel.sendUdpData(dataToSend, clientIp, clientPort, "升级数据"); |
| | | } else if (communicationType.equals(mainFrame.getString("tcp.server"))) { |
| | | // TCP Server模式发送到指定客户端 |
| | | String clientKey = clientIp + ":" + clientPort; |
| | | success = networkPanel.sendTcpDataToClient(clientKey, dataToSend, "升级数据"); |
| | | } |
| | | |
| | | if (!success) { |
| | | throw new IOException("网络发送失败"); |
| | | } |
| | | |
| | | // 调试信息 |
| | | System.out.println("发送升级数据,长度: " + len); |
| | | } |
| | | |
| | | @Override |
| | | public void flush() throws IOException { |
| | | // 网络发送立即生效,无需特殊处理 |
| | | } |
| | | |
| | | @Override |
| | | public void close() throws IOException { |
| | | // 不关闭底层网络连接 |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |