| | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.ResourceBundle; |
| | | import java.util.Set; |
| | | import dell_targets.Dell_MessageType; |
| | | import dell_targets.Dell_tag; |
| | | import publicsWay.Languages; |
| | | import udptcp.UDPPortAReceiver; |
| | | import udptcp.UDPPortBReceiver; |
| | | |
| | |
| | | // UI组件声明 |
| | | private JButton btnStart, btnPause, btnClear, btnSend; // 控制按钮:开始、暂停、清除、发送 |
| | | private static JComboBox<String> cbDataType; // 下拉框:数据类型、协议、设备ID |
| | | private JComboBox<String> cbProtocol; |
| | | private static JComboBox<String> cbProtocol; |
| | | private static JComboBox<String> cbDeviceId; |
| | | private static JComboBox<String> cbRemoteDevice; // 远程设备下拉框 |
| | | private static JCheckBox chkAutoSave; // 复选框:自动保存、显示来源、十六进制显示、ASCII显示 |
| | |
| | | // 状态变量 |
| | | private static boolean isCapturing = false; // 是否正在捕获数据的标志 |
| | | |
| | | // 存储所有远程设备(IP:端口) |
| | | private static Set<String> remoteDevices = new HashSet<>(); |
| | | // 修改为Map存储设备及其本地端口 |
| | | private static Map<String, Integer> remoteDeviceLocalPortMap = new HashMap<>(); |
| | | // 构造函数 |
| | |
| | | this.messages = messages; // 初始化消息资源包 |
| | | initializeUI(); // 初始化用户界面 |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | public void addNotify() { |
| | | super.addNotify(); |
| | |
| | | } |
| | | } |
| | | |
| | | // 加载设备ID列表 |
| | | private void loadDeviceIds() { |
| | | // 从Dell_tag类获取所有设备ID |
| | | List<String> tags = Dell_tag.getAlldeviceIds(); |
| | | // 遍历设备ID列表并添加到下拉框 |
| | | for (String tag : tags) { |
| | | cbDeviceId.addItem(tag); |
| | | } |
| | | } |
| | | |
| | | // 加载数据类型 |
| | | private void loadtyps() { |
| | | // 从Dell_tag类获取所有设备ID |
| | | List<String> typs = Dell_MessageType.getAllMessageTypes(); |
| | | // 遍历设备ID列表并添加到下拉框 |
| | | for (String typ : typs) { |
| | | cbDataType.addItem(typ); |
| | | } |
| | | cbDataType.removeAllItems(); |
| | | // 添加国际化选项 |
| | | cbDataType.addItem(messages.getString("MESSAGE_VIEW_ALL_TYPES")); |
| | | cbDataType.addItem(messages.getString("MESSAGE_VIEW_UDP_PORT_A")); |
| | | cbDataType.addItem(messages.getString("MESSAGE_VIEW_UDP_PORT_B")); |
| | | cbDataType.addItem(messages.getString("MESSAGE_VIEW_TCP_PORT")); |
| | | cbDataType.addItem(messages.getString("MESSAGE_VIEW_MQTT_PORT")); |
| | | } |
| | | |
| | | // 设置按钮动作 |
| | |
| | | |
| | | // 发送数据到远程设备 |
| | | private void sendData() { |
| | | // 使用新方法获取当前资源包 |
| | | ResourceBundle currentMessages = Languages.getCurrentMessages(); |
| | | String selectedDevice = (String) cbRemoteDevice.getSelectedItem(); |
| | | if (selectedDevice == null || selectedDevice.equals(messages.getString("MESSAGE_VIEW_ALL_DEVICES"))) { |
| | | if (selectedDevice == null || selectedDevice.equals(currentMessages.getString("MESSAGE_VIEW_ALL_DEVICES"))) { |
| | | JOptionPane.showMessageDialog(this, |
| | | messages.getString("MESSAGE_VIEW_SELECT_DEVICE"), |
| | | messages.getString("WARNING"), |
| | | currentMessages.getString("MESSAGE_VIEW_SELECT_DEVICE"), |
| | | currentMessages.getString("WARNING"), |
| | | JOptionPane.WARNING_MESSAGE); |
| | | return; |
| | | } |
| | |
| | | if (localPort == null) { |
| | | JOptionPane.showMessageDialog(this, |
| | | "无法确定设备的接收端口", |
| | | messages.getString("ERROR"), |
| | | currentMessages.getString("ERROR"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return; |
| | | } |
| | |
| | | String[] parts = selectedDevice.split(":"); |
| | | if (parts.length != 2) { |
| | | JOptionPane.showMessageDialog(this, |
| | | messages.getString("MESSAGE_VIEW_INVALID_DEVICE"), |
| | | messages.getString("ERROR"), |
| | | currentMessages.getString("MESSAGE_VIEW_INVALID_DEVICE"), |
| | | currentMessages.getString("ERROR"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return; |
| | | } |
| | |
| | | port = Integer.parseInt(parts[1]); |
| | | } catch (NumberFormatException ex) { |
| | | JOptionPane.showMessageDialog(this, |
| | | messages.getString("MESSAGE_VIEW_INVALID_PORT"), |
| | | messages.getString("ERROR"), |
| | | currentMessages.getString("MESSAGE_VIEW_INVALID_PORT"), |
| | | currentMessages.getString("ERROR"), |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return; |
| | | } |
| | |
| | | String dataToSend = txtSendData.getText(); |
| | | if (dataToSend.isEmpty()) { |
| | | JOptionPane.showMessageDialog(this, |
| | | messages.getString("MESSAGE_VIEW_EMPTY_DATA"), |
| | | messages.getString("WARNING"), |
| | | currentMessages.getString("MESSAGE_VIEW_EMPTY_DATA"), |
| | | currentMessages.getString("WARNING"), |
| | | JOptionPane.WARNING_MESSAGE); |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | // 捕获数据的核心方法 |
| | | public static void captureData(String rawData, String ip, int port, int localPort, String timestamp) { |
| | | // 检查窗口是否可见 |
| | | // 修改通用数据显示方法 |
| | | public static void showData(String rawData, String ip, int port, int localPort, String deviceId) { |
| | | if (!isWindowVisible) { |
| | | return; |
| | | } |
| | | String formattedData = formatData(rawData,ip,port,timestamp); // 格式化数据 |
| | | |
| | | // 获取当前选择 |
| | | String selectedDataType = (String) cbDataType.getSelectedItem(); |
| | | String selectedProtocol = (String) cbProtocol.getSelectedItem(); |
| | | String selectedDeviceId = (String) cbDeviceId.getSelectedItem(); |
| | | |
| | | // 使用新方法获取当前资源包 |
| | | ResourceBundle messages = Languages.getCurrentMessages(); |
| | | |
| | | String allTypes = messages.getString("MESSAGE_VIEW_ALL_TYPES"); |
| | | String allProtocols = messages.getString("MESSAGE_VIEW_ALL_PROTOCOLS"); |
| | | String allDevices = messages.getString("MESSAGE_VIEW_ALL_DEVICES"); |
| | | String udpPortA = messages.getString("MESSAGE_VIEW_UDP_PORT_A"); |
| | | String udpPortB = messages.getString("MESSAGE_VIEW_UDP_PORT_B"); |
| | | String udpProtocol = "UDP"; // 直接使用协议名称 |
| | | |
| | | // 检查数据类型过滤 |
| | | boolean dataTypeMatch = selectedDataType.equals(allTypes) || |
| | | (localPort == UDPPortAReceiver.PORT && selectedDataType.equals(udpPortA)) || |
| | | (localPort == UDPPortBReceiver.PORT && selectedDataType.equals(udpPortB)); |
| | | |
| | | // 检查协议过滤 |
| | | boolean protocolMatch = selectedProtocol.equals(allProtocols) || |
| | | (localPort == UDPPortAReceiver.PORT && selectedProtocol.equals(udpProtocol)) || |
| | | (localPort == UDPPortBReceiver.PORT && selectedProtocol.equals(udpProtocol)); |
| | | |
| | | // 检查设备ID过滤 |
| | | boolean deviceIdMatch=false; |
| | | if("1".equals(deviceId)) { |
| | | deviceIdMatch=true; |
| | | }else { |
| | | deviceIdMatch = selectedDeviceId.equals(allDevices) || |
| | | (deviceId != null && deviceId.equals(selectedDeviceId)); |
| | | } |
| | | |
| | | // 只有当所有条件都匹配时才显示 |
| | | if (!(dataTypeMatch && protocolMatch && deviceIdMatch)) { |
| | | return; |
| | | } |
| | | |
| | | // 生成毫秒级时间戳 |
| | | SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); |
| | | String timestamp = sdf.format(new Date()); |
| | | String formattedData = formatData(rawData, ip, port, timestamp); |
| | | |
| | | if(isCapturing) { |
| | | // 添加远程设备到下拉框 |
| | | addRemoteDevice(ip, port, localPort); // 确保调用带端口参数的方法 |
| | | // 获取当前选择的设备ID和数据类型 |
| | | String deviceId = cbDeviceId.getSelectedItem().toString(); |
| | | String dataType = cbDataType.getSelectedItem().toString(); |
| | | addRemoteDevice(ip, port, localPort); |
| | | |
| | | // 在EDT线程中更新UI |
| | | SwingUtilities.invokeLater(() -> { |
| | | txtDataView.append(formattedData + "\n"); // 添加数据到文本区域 |
| | | // 自动滚动到底部 |
| | | txtDataView.append(formattedData + "\n"); |
| | | txtDataView.setCaretPosition(txtDataView.getDocument().getLength()); |
| | | }); |
| | | } |
| | | |
| | | // 如果启用了自动保存,则保存到文件 |
| | | if (chkAutoSave.isSelected()) { |
| | | saveToFile(formattedData); |
| | |
| | | } |
| | | |
| | | // 格式化数据显示 |
| | | // 修改格式显示方法,支持混合格式 |
| | | private static String formatData(String rawData, String ip, int port,String timestamp) { |
| | | StringBuilder formatted = new StringBuilder(); // 使用StringBuilder构建格式化字符串 |
| | | |
| | | // 如果启用了显示来源,添加时间戳和源地址 |
| | | StringBuilder formatted = new StringBuilder(); |
| | | // 使用新方法获取当前资源包 |
| | | ResourceBundle messages = Languages.getCurrentMessages(); |
| | | // 显示来源信息 |
| | | if (chkShowSource.isSelected()) { |
| | | formatted.append("["+timestamp+";"+ip+":"+port+"]"); // 添加模拟源地址 |
| | | formatted.append("[") |
| | | .append(timestamp) |
| | | .append("][") |
| | | .append(ip) |
| | | .append(":") |
| | | .append(port) |
| | | .append("] "); |
| | | } |
| | | |
| | | // 根据显示选项格式化数据 |
| | | if (chkHexDisplay.isSelected() && chkAsciiDisplay.isSelected()) { |
| | | // 同时显示十六进制和ASCII |
| | | formatted.append(toHexString(rawData)) // 添加十六进制表示 |
| | | .append(" | ") // 添加分隔符 |
| | | .append(rawData); // 添加原始ASCII数据 |
| | | formatted.append(formatHexString(rawData)) |
| | | .append(" | ") |
| | | .append(hexToAscii(rawData)) |
| | | .append(" [") |
| | | .append(messages.getString("MESSAGE_VIEW_MIXED_FORMAT")) |
| | | .append("]"); |
| | | } else if (chkHexDisplay.isSelected()) { |
| | | // 仅显示十六进制 |
| | | formatted.append(toHexString(rawData)); |
| | | formatted.append(formatHexString(rawData)) |
| | | .append(" [") |
| | | .append(messages.getString("MESSAGE_VIEW_HEX_FORMAT")) |
| | | .append("]"); |
| | | } else if (chkAsciiDisplay.isSelected()) { |
| | | formatted.append(hexToAscii(rawData)) |
| | | .append(" [") |
| | | .append(messages.getString("MESSAGE_VIEW_ASCII_FORMAT")) |
| | | .append("]"); |
| | | } else { |
| | | // 默认显示原始ASCII数据 |
| | | formatted.append(rawData); |
| | | formatted.append(hexToAscii(rawData)); |
| | | } |
| | | |
| | | return formatted.toString(); // 返回格式化后的字符串 |
| | | return formatted.toString(); |
| | | } |
| | | |
| | | // 修改设备ID加载方法 |
| | | private void loadDeviceIds() { |
| | | cbDeviceId.removeAllItems(); |
| | | cbDeviceId.addItem(messages.getString("MESSAGE_VIEW_ALL_DEVICES")); |
| | | |
| | | List<String> tags = Dell_tag.getAlldeviceIds(); |
| | | for (String tag : tags) { |
| | | cbDeviceId.addItem(tag); |
| | | } |
| | | } |
| | | |
| | | // 将字符串转换为十六进制表示 |
| | |
| | | } |
| | | return hex.toString().trim(); // 返回并去除末尾空格 |
| | | } |
| | | // 格式化十六进制字符串(每两个字符加空格) |
| | | private static String formatHexString(String hex) { |
| | | StringBuilder formatted = new StringBuilder(); |
| | | for (int i = 0; i < hex.length(); i += 2) { |
| | | if (i > 0) formatted.append(" "); |
| | | formatted.append(hex.substring(i, Math.min(i + 2, hex.length()))); |
| | | } |
| | | return formatted.toString(); |
| | | } |
| | | |
| | | // 将十六进制字符串转换为ASCII |
| | | private static String hexToAscii(String hexStr) { |
| | | StringBuilder output = new StringBuilder(); |
| | | for (int i = 0; i < hexStr.length(); i += 2) { |
| | | String str = hexStr.substring(i, i + 2); |
| | | output.append((char) Integer.parseInt(str, 16)); |
| | | } |
| | | return output.toString(); |
| | | } |
| | | // 保存数据到文件 |
| | | private static void saveToFile(String data) { |
| | | SimpleDateFormat fileFormat = new SimpleDateFormat("yyyyMMdd"); // 文件日期格式 |