From ccb681ec3a4ef38da878ac3a01c498853e9be4ca Mon Sep 17 00:00:00 2001 From: 826220679@qq.com <826220679@qq.com> Date: 星期六, 09 八月 2025 16:34:19 +0800 Subject: [PATCH] 修改 --- src/dell_anchor/BaseStationSyncConfigPanel.java | 2 src/dell_anchor/BaseStationAdjacentConfigPanel.java | 1 src/chushihua/Chushihua.java | 6 src/dell_system/MessageViewPanel.java | 239 ++++++++---- src/publicsWay/Languages.java | 53 ++ src/dell_targets/Dell_SystemConfiguration.java | 5 src/targets/LocationBaseStation.java | 33 + systemfile/logfile/openlog.txt | 67 +++ src/dell55AAData/Dell55AA02Parser.java | 66 +++ src/udptcp/PacketParser.java | 163 ++++++++ /dev/null | 151 ------- src/udptcp/PacketProcessingSystem.java | 104 +++++ src/dell_targets/Dell_BaseStation.java | 137 +++++++ src/window/Windows.java | 11 systemfile/Messages_en.properties | 14 src/udptcp/UDPPortAReceiver.java | 30 - systemfile/Messages_zh.properties | 14 src/publicsWay/UwbDataParser.java | 7 src/udptcp/UDPPortBReceiver.java | 21 src/dell_anchor/BaseStationManagementPanel.java | 2 20 files changed, 851 insertions(+), 275 deletions(-) diff --git a/src/chushihua/Chushihua.java b/src/chushihua/Chushihua.java index 84abf00..f99cc13 100644 --- a/src/chushihua/Chushihua.java +++ b/src/chushihua/Chushihua.java @@ -1,11 +1,11 @@ package chushihua; import java.sql.SQLException; import dell_Fence.Dell_Fence; -import dell_anchor.Dell_BaseStation; import dell_map.Dell_Map; import dell_suanfa.Dell_GroupManagement; import dell_suanfa.Dell_LayerManagement; import dell_system.Dell_company; +import dell_targets.Dell_BaseStation; import dell_targets.Dell_SystemConfiguration; import dell_targets.Dell_tag; import udptcp.UDPPortAReceiver; @@ -13,6 +13,7 @@ public class Chushihua { public static void getchushihua() { try { + Dell_SystemConfiguration.getSystemConfigurations(); Dell_tag.getlocationTags(); Dell_BaseStation.getBaseStations(); UDPPortAReceiver.startReceiver(); @@ -20,8 +21,7 @@ Dell_Fence.getAllFences(); Dell_company.getAllCompanies(); Dell_LayerManagement.getAllLayers(); - Dell_GroupManagement.getAllGroups(); - Dell_SystemConfiguration.getSystemConfigurations(); + Dell_GroupManagement.getAllGroups(); if(Dell_SystemConfiguration.gnsstoxyOpen) {Dell_Map.get_foor_xycs();} } catch (SQLException e) { // TODO 自动生成的 catch 块 diff --git a/src/dell55AAData/Dell55AA02Parser.java b/src/dell55AAData/Dell55AA02Parser.java new file mode 100644 index 0000000..741ae5e --- /dev/null +++ b/src/dell55AAData/Dell55AA02Parser.java @@ -0,0 +1,66 @@ +package dell55AAData; + +import dell_targets.Dell_BaseStation; + +public class Dell55AA02Parser { + private static final String EXPECTED_HEADER = "55AA02"; + private static final int MIN_LENGTH = 36; // 18字节 * 2字符/字节 + private static final int BASE_ID_START = 8; // 基站ID起始位置(第4字节) + private static final int SYNC_STATUS_START = 12; // 同步状态起始位置(第5字节) + private static final int PRESSURE_START = 14; // 气压值起始位置(第6字节) + + /** + * 解析55AA02格式的基站数据 + * @param message 接收到的数据(十六进制字符串) + */ + public static void parseAndUpdate(String message) { + // 1. 基础校验 + if (message == null || message.length() < MIN_LENGTH) { + return; + } + + // 2. 头部校验(固定开头字符串) + for (int i = 0; i < EXPECTED_HEADER.length(); i++) { + if (message.charAt(i) != EXPECTED_HEADER.charAt(i)) { + return; + } + } + + // 3. 解析基站ID(原始数据字符串) + String baseId = new String(new char[]{ + message.charAt(BASE_ID_START), + message.charAt(BASE_ID_START + 1), + message.charAt(BASE_ID_START + 2), + message.charAt(BASE_ID_START + 3) + }); + + // 4. 解析同步状态(1字节) + char syncChar = message.charAt(SYNC_STATUS_START + 1); // 取状态字符 + String syncStatus = (syncChar == '0') ? "0" : "1"; + + // 5. 解析气压值(4字节小端序) + int pressure = 0; + for (int i = 0; i < 8; i += 2) { + int idx = PRESSURE_START + i; + // 使用HexUtils的快速转换方法 + int byteValue = HexUtils.fastHexToByte(message.charAt(idx), message.charAt(idx + 1)); + pressure |= (byteValue << (i * 4)); // 小端合并 + } + String pressureStr = String.valueOf(pressure); + + // 6. 更新基站数据 + updateBaseStationData(baseId, syncStatus ,pressureStr); + } + + /** + * 更新基站数据 + * @param baseId 基站ID + * @param syncStatus 同步状态 + * @param pressure 气压值字符串 + */ + private static void updateBaseStationData(String baseId, String syncStatus, String pressure) { + Dell_BaseStation.updateBaseStationProperty(baseId, "syncStatus", syncStatus); + Dell_BaseStation.updateBaseStationProperty(baseId, "barometerReading", pressure); + } + +} \ No newline at end of file diff --git a/src/dell_anchor/BaseStationAdjacentConfigPanel.java b/src/dell_anchor/BaseStationAdjacentConfigPanel.java index 697b56a..e78a460 100644 --- a/src/dell_anchor/BaseStationAdjacentConfigPanel.java +++ b/src/dell_anchor/BaseStationAdjacentConfigPanel.java @@ -1,6 +1,7 @@ package dell_anchor; import databases.DBConnector; +import dell_targets.Dell_BaseStation; import targets.LocationBaseStation; import javax.swing.*; diff --git a/src/dell_anchor/BaseStationManagementPanel.java b/src/dell_anchor/BaseStationManagementPanel.java index c9625ad..b5c7650 100644 --- a/src/dell_anchor/BaseStationManagementPanel.java +++ b/src/dell_anchor/BaseStationManagementPanel.java @@ -1,6 +1,8 @@ package dell_anchor; import databases.DBConnector; +import dell_targets.Dell_BaseStation; + import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.table.*; diff --git a/src/dell_anchor/BaseStationSyncConfigPanel.java b/src/dell_anchor/BaseStationSyncConfigPanel.java index 768a8bc..12329ef 100644 --- a/src/dell_anchor/BaseStationSyncConfigPanel.java +++ b/src/dell_anchor/BaseStationSyncConfigPanel.java @@ -1,5 +1,7 @@ package dell_anchor; import databases.DBConnector; +import dell_targets.Dell_BaseStation; + import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.table.*; diff --git a/src/dell_anchor/Dell_BaseStation.java b/src/dell_anchor/Dell_BaseStation.java deleted file mode 100644 index c24b160..0000000 --- a/src/dell_anchor/Dell_BaseStation.java +++ /dev/null @@ -1,89 +0,0 @@ -package dell_anchor; -import databases.DBConnector; -import targets.LocationBaseStation; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -public class Dell_BaseStation { - static List<LocationBaseStation> baseStations; - - public static List<LocationBaseStation> getBaseStations() throws SQLException { - baseStations = new ArrayList<>(); - ResultSet rs = DBConnector.queryTableData("location_base_station"); - - while (rs.next()) { - LocationBaseStation baseStation = new LocationBaseStation(); - baseStation.setId((int) rs.getLong("id")); - baseStation.setCode(rs.getString("base_station_id")); - baseStation.setStatus(rs.getString("statuss")); - baseStation.setXCoordinate(rs.getString("x_coordinate")); - baseStation.setYCoordinate(rs.getString("y_coordinate")); - baseStation.setZCoordinate(rs.getString("z_coordinate")); - baseStation.setLongitude(rs.getString("longitude")); - baseStation.setLatitude(rs.getString("latitude")); - baseStation.setElevation(rs.getString("elevation")); - baseStation.setHorizontalAngle(rs.getString("horizontal_angle")); - baseStation.setPitchAngle(rs.getString("pitch_angle")); - baseStation.setFloor(rs.getString("located_layer")); - baseStation.setGroup(rs.getString("located_group")); - baseStation.setRange(rs.getString("range")); - baseStation.setSyncStatus(rs.getString("sync_status")); - baseStation.setSyncType(rs.getString("sync_type")); - baseStation.setSyncBaseStation(rs.getString("sync_base_station")); - baseStation.setIpAddress(rs.getString("ip_address")); - baseStation.setPort(rs.getString("ports")); - baseStation.setFirmwareVersion(rs.getString("firmware_version")); - baseStation.setJudgmentDistance(rs.getString("judgment_distance")); - baseStation.setBattery(rs.getString("battery")); - baseStation.setCalibrationDistance(rs.getString("calibration_distance")); - baseStation.setSignalSendTime(rs.getString("signal_transmission_time")); - baseStation.setCommunicationGroup(rs.getString("communication_group")); - baseStation.setIconAddress(rs.getString("icon_url")); - baseStation.setOnlineTime(rs.getString("online_time")); - baseStation.setOfflineTime(rs.getString("offline_time")); - baseStation.setOfflineDuration(rs.getString("offline_duration")); - baseStation.setAlgorithmDimension(rs.getString("algorithm_dimension")); - baseStation.setBottomHeight(rs.getString("located_bottom_height")); - baseStation.setTopHeight(rs.getString("located_top_height")); - baseStation.setIsBarometricStation(rs.getString("barometric_base_station")); - baseStation.setSwitchDistance(rs.getString("handover_distance")); - baseStation.setMaxDistance(rs.getString("maximum_distance")); - baseStation.setOutputAllRanging(rs.getString("output_all_base_station_ranging")); - baseStation.setCompany(rs.getString("company")); - baseStation.setCrossLayerHeight(rs.getString("cross_layer_height")); - baseStation.setCrossLayerGroup(rs.getString("cross_layer_group")); - baseStation.setRequiredDistance(rs.getString("must_pass_distance")); - baseStation.setAdjacent1(rs.getString("adjacent1")); - baseStation.setAdjacent2(rs.getString("adjacent2")); - baseStation.setAdjacent3(rs.getString("adjacent3")); - baseStation.setAdjacent4(rs.getString("adjacent4")); - baseStation.setAdjacent5(rs.getString("adjacent5")); - baseStation.setAdjacent6(rs.getString("adjacent6")); - baseStation.setAdjacent7(rs.getString("adjacent7")); - baseStation.setAdjacent8(rs.getString("adjacent8")); - baseStation.setAdjacent9(rs.getString("adjacent9")); - baseStation.setAdjacent10(rs.getString("adjacent10")); - baseStation.setReserved1(rs.getString("reserved1")); - baseStation.setReserved2(rs.getString("reserved2")); - baseStation.setReserved3(rs.getString("reserved3")); - baseStation.setReserved4(rs.getString("reserved4")); - baseStation.setReserved5(rs.getString("reserved5")); - baseStation.setReserved6(rs.getString("reserved6")); - baseStation.setReserved7(rs.getString("reserved7")); - baseStation.setReserved8(rs.getString("reserved8")); - baseStation.setReserved9(rs.getString("reserved9")); - baseStation.setReserved10(rs.getString("reserved10")); - baseStation.setReserved11(rs.getString("reserved11")); - baseStation.setReserved12(rs.getString("reserved12")); - baseStation.setReserved13(rs.getString("reserved13")); - baseStation.setReserved14(rs.getString("reserved14")); - baseStation.setReserved15(rs.getString("reserved15")); - baseStation.setReserved16(rs.getString("reserved16")); - - baseStations.add(baseStation); - } - return baseStations; - } -} \ No newline at end of file diff --git a/src/dell_system/MessageViewPanel.java b/src/dell_system/MessageViewPanel.java index da83577..3dcb4a2 100644 --- a/src/dell_system/MessageViewPanel.java +++ b/src/dell_system/MessageViewPanel.java @@ -7,13 +7,11 @@ 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; @@ -28,7 +26,7 @@ // 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显示 @@ -46,15 +44,16 @@ // 状态变量 private static boolean isCapturing = false; // 是否正在捕获数据的标志 - // 存储所有远程设备(IP:端口) - private static Set<String> remoteDevices = new HashSet<>(); - // 修改为Map存储设备及其本地端口 + // 修改为Map存储设备及其本地端口 private static Map<String, Integer> remoteDeviceLocalPortMap = new HashMap<>(); // 构造函数 public MessageViewPanel(ResourceBundle messages) { this.messages = messages; // 初始化消息资源包 initializeUI(); // 初始化用户界面 } + + + public void addNotify() { super.addNotify(); @@ -66,7 +65,7 @@ public void windowClosing(WindowEvent e) { isWindowVisible = false; } - + @Override public void windowClosed(WindowEvent e) { isWindowVisible = false; @@ -199,22 +198,22 @@ // 创建发送选项面板 JPanel sendOptionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); sendOptionsPanel.setBackground(new Color(240, 245, 249)); - + // 创建单选按钮组 ButtonGroup sendFormatGroup = new ButtonGroup(); - + // 创建HEX发送单选按钮 rdoSendHex = createStyledRadioButton(messages.getString("MESSAGE_VIEW_SEND_HEX")); // 创建ASCII发送单选按钮 rdoSendAscii = createStyledRadioButton(messages.getString("MESSAGE_VIEW_SEND_ASCII")); - + // 将单选按钮添加到按钮组 sendFormatGroup.add(rdoSendHex); sendFormatGroup.add(rdoSendAscii); - + // 默认选中ASCII发送 rdoSendAscii.setSelected(true); - + // 回车换行复选框 chkAppendNewline = createStyledCheckbox(messages.getString("MESSAGE_VIEW_APPEND_NEWLINE")); @@ -266,18 +265,18 @@ checkBox.setForeground(new Color(70, 70, 70)); // 设置前景色 return checkBox; } - + // 创建带样式的单选按钮 private JRadioButton createStyledRadioButton(String text) { JRadioButton radioButton = new JRadioButton(text); // 创建单选按钮 radioButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体 radioButton.setBackground(new Color(240, 245, 249)); // 设置背景色 radioButton.setForeground(new Color(70, 70, 70)); // 设置前景色 - + // 美化选中效果 radioButton.setIcon(new RadioButtonIcon(false)); radioButton.setSelectedIcon(new RadioButtonIcon(true)); - + // 添加鼠标悬停效果 radioButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { @@ -287,7 +286,7 @@ radioButton.setForeground(new Color(70, 70, 70)); } }); - + return radioButton; } @@ -295,21 +294,21 @@ private static class RadioButtonIcon implements Icon { private static final int SIZE = 14; private final boolean selected; - + public RadioButtonIcon(boolean selected) { this.selected = selected; } - + @Override public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - + if (selected) { // 选中状态 - 蓝色填充 g2d.setColor(new Color(70, 130, 180)); g2d.fillOval(x, y, SIZE, SIZE); - + // 内圆 - 白色 g2d.setColor(Color.WHITE); g2d.fillOval(x + SIZE/4, y + SIZE/4, SIZE/2, SIZE/2); @@ -318,39 +317,31 @@ g2d.setColor(new Color(150, 150, 150)); g2d.drawOval(x, y, SIZE-1, SIZE-1); } - + g2d.dispose(); } - + @Override public int getIconWidth() { return SIZE; } - + @Override public int getIconHeight() { return SIZE; } } - // 加载设备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")); } // 设置按钮动作 @@ -385,21 +376,23 @@ // 发送数据到远程设备 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; } - + // 获取本地端口 Integer localPort = remoteDeviceLocalPortMap.get(selectedDevice); if (localPort == null) { JOptionPane.showMessageDialog(this, "无法确定设备的接收端口", - messages.getString("ERROR"), + currentMessages.getString("ERROR"), JOptionPane.ERROR_MESSAGE); return; } @@ -408,8 +401,8 @@ 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; } @@ -420,8 +413,8 @@ 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; } @@ -429,8 +422,8 @@ 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; } @@ -458,7 +451,7 @@ // 传入是否HEX发送的标志 UDPPortBReceiver.sendData(ip, port, dataToSend, true); } - + } else { // ASCII格式发送 displayData.append(dataToSend); @@ -477,7 +470,7 @@ txtDataView.setCaretPosition(txtDataView.getDocument().getLength()); }); } - + // 修改添加远程设备方法 // 在MessageViewPanel类中修改addRemoteDevice方法 public static void addRemoteDevice(String ip, int port, int localPort) { @@ -494,65 +487,133 @@ break; } } - + if (!exists) { cbRemoteDevice.addItem(device); } }); } } - + // 捕获数据的核心方法 - 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); // 格式化数据 - if(isCapturing) { + + // 获取当前选择 + 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构建格式化字符串 - - // 如果启用了显示来源,添加时间戳和源地址 + // 修改格式显示方法,支持混合格式 + private static String formatData(String rawData, String ip, int port, String timestamp) { + 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); + } } // 将字符串转换为十六进制表示 @@ -563,7 +624,25 @@ } 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"); // 文件日期格式 diff --git a/src/dell_targets/Dell_BaseStation.java b/src/dell_targets/Dell_BaseStation.java new file mode 100644 index 0000000..67002d3 --- /dev/null +++ b/src/dell_targets/Dell_BaseStation.java @@ -0,0 +1,137 @@ +package dell_targets; +import databases.DBConnector; +import targets.LocationBaseStation; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class Dell_BaseStation { + static List<LocationBaseStation> baseStations; + private static ConcurrentHashMap<String, LocationBaseStation> baseStationMap; // 以基站ID为键的映射 + + public static List<LocationBaseStation> getBaseStations() throws SQLException { + baseStations = new ArrayList<>(); + baseStationMap = new ConcurrentHashMap<>(); // 修复:初始化映射 + ResultSet rs = DBConnector.queryTableData("location_base_station"); + + while (rs.next()) { + LocationBaseStation baseStation = new LocationBaseStation(); + baseStation.setId((int) rs.getLong("id")); + baseStation.setCode(rs.getString("base_station_id")); + baseStation.setStatus(rs.getString("statuss")); + baseStation.setXCoordinate(rs.getString("x_coordinate")); + baseStation.setYCoordinate(rs.getString("y_coordinate")); + baseStation.setZCoordinate(rs.getString("z_coordinate")); + baseStation.setLongitude(rs.getString("longitude")); + baseStation.setLatitude(rs.getString("latitude")); + baseStation.setElevation(rs.getString("elevation")); + baseStation.setHorizontalAngle(rs.getString("horizontal_angle")); + baseStation.setPitchAngle(rs.getString("pitch_angle")); + baseStation.setFloor(rs.getString("located_layer")); + baseStation.setGroup(rs.getString("located_group")); + baseStation.setRange(rs.getString("range")); + baseStation.setSyncStatus(rs.getString("sync_status")); + baseStation.setSyncType(rs.getString("sync_type")); + baseStation.setSyncBaseStation(rs.getString("sync_base_station")); + baseStation.setIpAddress(rs.getString("ip_address")); + baseStation.setPort(rs.getString("ports")); + baseStation.setFirmwareVersion(rs.getString("firmware_version")); + baseStation.setJudgmentDistance(rs.getString("judgment_distance")); + baseStation.setBattery(rs.getString("battery")); + baseStation.setCalibrationDistance(rs.getString("calibration_distance")); + baseStation.setSignalSendTime(rs.getString("signal_transmission_time")); + baseStation.setCommunicationGroup(rs.getString("communication_group")); + baseStation.setIconAddress(rs.getString("icon_url")); + baseStation.setOnlineTime(rs.getString("online_time")); + baseStation.setOfflineTime(rs.getString("offline_time")); + baseStation.setOfflineDuration(rs.getString("offline_duration")); + baseStation.setAlgorithmDimension(rs.getString("algorithm_dimension")); + baseStation.setBottomHeight(rs.getString("located_bottom_height")); + baseStation.setTopHeight(rs.getString("located_top_height")); + baseStation.setIsBarometricStation(rs.getString("barometric_base_station")); + baseStation.setSwitchDistance(rs.getString("handover_distance")); + baseStation.setMaxDistance(rs.getString("maximum_distance")); + baseStation.setOutputAllRanging(rs.getString("output_all_base_station_ranging")); + baseStation.setCompany(rs.getString("company")); + baseStation.setCrossLayerHeight(rs.getString("cross_layer_height")); + baseStation.setCrossLayerGroup(rs.getString("cross_layer_group")); + baseStation.setRequiredDistance(rs.getString("must_pass_distance")); + baseStation.setAdjacent1(rs.getString("adjacent1")); + baseStation.setAdjacent2(rs.getString("adjacent2")); + baseStation.setAdjacent3(rs.getString("adjacent3")); + baseStation.setAdjacent4(rs.getString("adjacent4")); + baseStation.setAdjacent5(rs.getString("adjacent5")); + baseStation.setAdjacent6(rs.getString("adjacent6")); + baseStation.setAdjacent7(rs.getString("adjacent7")); + baseStation.setAdjacent8(rs.getString("adjacent8")); + baseStation.setAdjacent9(rs.getString("adjacent9")); + baseStation.setAdjacent10(rs.getString("adjacent10")); + baseStation.setReserved1(rs.getString("reserved1")); + baseStation.setReserved2(rs.getString("reserved2")); + baseStation.setReserved3(rs.getString("reserved3")); + baseStation.setReserved4(rs.getString("reserved4")); + baseStation.setReserved5(rs.getString("reserved5")); + baseStation.setReserved6(rs.getString("reserved6")); + baseStation.setReserved7(rs.getString("reserved7")); + baseStation.setReserved8(rs.getString("reserved8")); + baseStation.setReserved9(rs.getString("reserved9")); + baseStation.setReserved10(rs.getString("reserved10")); + baseStation.setReserved11(rs.getString("reserved11")); + baseStation.setReserved12(rs.getString("reserved12")); + baseStation.setReserved13(rs.getString("reserved13")); + baseStation.setReserved14(rs.getString("reserved14")); + baseStation.setReserved15(rs.getString("reserved15")); + baseStation.setReserved16(rs.getString("reserved16")); + baseStations.add(baseStation); + baseStationMap.put(baseStation.getCode(), baseStation); // 以基站ID为键存入映射 + } + return baseStations; + } + + /** + * 根据基站ID高效修改属性值 + * @param baseStationId 基站ID(base_station_id) + * @param propertyName 属性名(需与setter方法匹配) + * @param value 新属性值 + */ + public static void updateBaseStationProperty(String baseStationId, String propertyName, String value) { + LocationBaseStation station = baseStationMap.get(baseStationId); + if (station == null) return; // 基站不存在则忽略 + + // 根据属性名调用对应setter(高效匹配高频属性) + switch (propertyName) { + case "status": + station.setStatus(value); break; // 更新状态 + case "battery": + station.setBattery(value); break; // 更新电量 + case "ipAddress": + station.setIpAddress(value); break; // 更新IP地址 + case "onlineTime": + station.setOnlineTime(value); break; // 更新上线时间 + case "offlineTime": + station.setOfflineTime(value); break; // 更新离线时间 + case "offlineDuration": + station.setOfflineDuration(value); break; // 更新离线时长 + case "syncStatus": + station.setSyncStatus(value); break; //同步状态 + case "barometerReading": + station.setBarometerReading(value); break; //同步状态 + + // 添加其他高频属性... + default: + throw new IllegalArgumentException("不支持属性: " + propertyName); + } + } + + /** + * 根据基站ID获取基站对象(高效访问) + * @param baseStationId 基站ID + * @return 基站对象(不存在则返回null) + */ + public static LocationBaseStation getBaseStationById(String baseStationId) { + return baseStationMap.get(baseStationId); // O(1)复杂度直接获取 + } + +} \ No newline at end of file diff --git a/src/dell_targets/Dell_SystemConfiguration.java b/src/dell_targets/Dell_SystemConfiguration.java index 8f0bb80..7d0a9f9 100644 --- a/src/dell_targets/Dell_SystemConfiguration.java +++ b/src/dell_targets/Dell_SystemConfiguration.java @@ -14,6 +14,7 @@ static List<SystemConfiguration> configs; public static boolean xytognssOpen=false; public static boolean gnsstoxyOpen=false; + public static String language="0"; // 获取系统配置列表 public static List<SystemConfiguration> getSystemConfigurations() { // 创建配置对象列表 @@ -158,8 +159,10 @@ config.setRealTimeTrajectoryDuration(rs.getString("real_time_trajectory_duration")); // 实时轨迹颜色 config.setRealTimeTrajectoryColor(rs.getString("real_time_trajectory_color")); + String langua=rs.getString("system_language"); + language=langua; // 系统语言 - config.setSystemLanguage(rs.getString("system_language")); + config.setSystemLanguage(langua); // JNA日志开关 config.setJnaLogSwitch(rs.getString("jna_log_switch")); // 时间片分配方式 diff --git a/src/publicsWay/Languages.java b/src/publicsWay/Languages.java new file mode 100644 index 0000000..39e974e --- /dev/null +++ b/src/publicsWay/Languages.java @@ -0,0 +1,53 @@ +package publicsWay; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.Locale; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import dell_targets.Dell_SystemConfiguration; + +public class Languages { + // 修改后的资源加载方法 + public static ResourceBundle getCurrentMessages() { + // 根据系统配置决定语言 + Locale locale = "1".equals(Dell_SystemConfiguration.language) ? + Locale.ENGLISH : Locale.SIMPLIFIED_CHINESE; + + // 使用与Windows.java相同的加载逻辑 + String fileName = locale.equals(Locale.ENGLISH) ? + "Messages_en.properties" : "Messages_zh.properties"; + + File langFile = new File("systemfile/" + fileName); + + if (!langFile.exists()) { + System.err.println("默认资源文件未找到: " + langFile.getAbsolutePath()); + try { + return ResourceBundle.getBundle("systemfile.Messages", locale); + } catch (Exception e) { + System.err.println("后备资源加载失败: " + e.getMessage()); + // 返回空包避免崩溃 + return new ResourceBundle() { + @Override + protected Object handleGetObject(String key) { + return "!" + key + "!"; + } + @Override + public Enumeration<String> getKeys() { + return java.util.Collections.emptyEnumeration(); + } + }; + } + } + + try (InputStream inputStream = new FileInputStream(langFile)) { + return new PropertyResourceBundle(inputStream); + } catch (IOException e) { + System.err.println("无法加载资源文件: " + e.getMessage()); + return ResourceBundle.getBundle("systemfile.Messages", locale); + } + } +} diff --git a/src/publicsWay/UwbDataParser.java b/src/publicsWay/UwbDataParser.java index af69f73..4886720 100644 --- a/src/publicsWay/UwbDataParser.java +++ b/src/publicsWay/UwbDataParser.java @@ -130,11 +130,6 @@ this.battery = battery; this.buttonStatus = buttonStatus; } - - @Override - public String toString() { - return String.format("包序: %d, 标签: %s, 基站: %s, 距离: %d mm, 电量: %d%%, 按键: %d", - sequence, tagId, baseId, distance, battery, buttonStatus); - } + } } \ No newline at end of file diff --git a/src/targets/LocationBaseStation.java b/src/targets/LocationBaseStation.java index 6a47aaf..41dd5b1 100644 --- a/src/targets/LocationBaseStation.java +++ b/src/targets/LocationBaseStation.java @@ -66,6 +66,7 @@ private String reserved14; // 备用 14 private String reserved15; // 备用 15 private String reserved16; // 备用 16 + private String barometerReading;//气压计值 // Getter and Setter methods public int getId() { @@ -595,4 +596,36 @@ public void setReserved16(String reserved16) { this.reserved16 = reserved16; } + + public String getxCoordinate() { + return xCoordinate; + } + + public String getyCoordinate() { + return yCoordinate; + } + + public String getzCoordinate() { + return zCoordinate; + } + + public String getBarometerReading() { + return barometerReading; + } + + public void setxCoordinate(String xCoordinate) { + this.xCoordinate = xCoordinate; + } + + public void setyCoordinate(String yCoordinate) { + this.yCoordinate = yCoordinate; + } + + public void setzCoordinate(String zCoordinate) { + this.zCoordinate = zCoordinate; + } + + public void setBarometerReading(String barometerReading) { + this.barometerReading = barometerReading; + } } diff --git a/src/udptcp/DellHexBaowen.java b/src/udptcp/DellHexBaowen.java deleted file mode 100644 index 213bb5c..0000000 --- a/src/udptcp/DellHexBaowen.java +++ /dev/null @@ -1,167 +0,0 @@ -package udptcp; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.util.Vector; -/** - * 处理原始报文 - */ -public class DellHexBaowen implements Runnable { - static int sleeptime = 1; - static Thread t; - static Vector<HexBaowen> allReceivedHexMessages = new Vector<HexBaowen>(); - static int a = 0; - public static void intsert(String ip, String hex, String time, int port,int timestamp) { - HexBaowen HexBaowen = new HexBaowen(); - HexBaowen.setHex(hex); - HexBaowen.setIp(ip); - HexBaowen.setAddtime(time); - HexBaowen.setTimestamp(timestamp); - HexBaowen.setPort(port); - allReceivedHexMessages.add(HexBaowen); - } - - - /** - * 处理原始报文 - */ - public void dellhex() { - int size = allReceivedHexMessages.size(); - if (size == 0) { - sleeptime = 50; - return; - } - if (size > 100000) {//如果数据大于10万条没有处理则清空 - allReceivedHexMessages.removeAllElements(); - } else { - sleeptime = 0; - HexBaowen HexBaowen0 = allReceivedHexMessages.get(0); - String ip = HexBaowen0.getIp(); - int port = HexBaowen0.getPort(); - String hex = HexBaowen0.getHex(); - String time = HexBaowen0.getAddtime(); - int timestamp = HexBaowen0.getTimestamp(); - int lenth = hex.length(); - try { - dellhex2(ip, port, hex, time, timestamp, lenth);//处理原始数据 - - } catch (Exception e) { - logger.info("errorData:"+hex); - e.printStackTrace(); - } - allReceivedHexMessages.remove(HexBaowen0);//删除处理过的报文 - } - } - - - /** - * 启动线程的方法 - */ - public void startThread() { - t = new Thread(this); - t.start(); - } - - public void run() { - while (true) { - try { - dellhex(); - Thread.sleep(sleeptime);//休眠时间 - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - - public static Vector<HexBaowen> get allReceivedHexMessages() { - return allReceivedHexMessages; - } - - /** - * yang2023.07.08 - */ - public static void dellhex2(String ip, int port, String hex, String time, int timestamp, int lenth) { - Have_Yuanshi_Do.Dell_yuanshi(ip, hex, time); -//// if (AnchorSet.isReadpeizhi()) {//如果设备处于读取配置模式} -// else if (hex.startsWith("55AA02") && lenth == 32) { -// Dell_55AA02.dellrgs(hex, ip, port); -// } else - if (hex != null) { - if (hex.startsWith("55AA01") && lenth == 42) {//如果是合法的55AA01数据 - Dell_55AA01.dell_55AA01(ip, hex, time, timestamp, port); - HexBaowenShow.ok("2", "55AA01", hex, ip, LanguageTools.getTranslation(CLYSBW));//报文显示 - //如果是合法的测距数据 - } else if (hex.startsWith("55AA0C")) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - } else if (hex.startsWith("55AA12")) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AA22")) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AA24")) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AA23")) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AA0A")) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - } else if (hex.startsWith("55AA1A") ) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - } else if (hex.startsWith("55AA20") ) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AACC") ) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AACD") ) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AACF") ) { - Dell_HexBaowen_55AA0C.intsert(ip, hex, time, port,"0"); - }else if (hex.startsWith("55AA07")) { - //修改返回信息 - Dell_55AA07.dell(ip, hex.toString()); - HexBaowenShow.ok("2", "55AA07", hex, ip, LanguageTools.getTranslation(CLYSBW)); - //基站收到批量修改标签信息55AA09080B0C00000000D7FFio - } else if (hex.startsWith("55AA09") ) { - HexBaowenShow.ok("2", "55AA09", hex, ip, LanguageTools.getTranslation(CLYSBW)); - //基站返回状态值55AA100E18980100000000000000000030 - } else if (hex.startsWith("55AA10") ) { - //调用处理注册信息的方法 - Dell_55AA10.dell(hex); - HexBaowenShow.ok("2", "55AA10", hex, ip, LanguageTools.getTranslation(CLYSBW)); - - } else if (hex.startsWith("55AA0E")) { - HexBaowenShow.ok("2", "55AA0E", hex, ip, LanguageTools.getTranslation(CLYSBW)); - Dell_55AA0E.dell(hex); - }else if (hex.startsWith("55AA02")) { - Dell_55AA02.dellrgs(hex, ip, port); - - } else if (hex.startsWith("55AA31")) { - Dell_55AA31.dellrgs(hex, ip, port); - //基站心跳包 - }else if (hex.startsWith("55AA32")) { - Dell_55AA32.dellrgs(hex, ip, port); - //处理升级进度 - }else if (hex.startsWith("55AA34")) { - Dell_55AA34.dellrgs(hex, ip, port); - //处理注册报文 - }else if (hex.startsWith("55AA03")) { - HexBaowenShow.ok("2", "55AA03", hex, ip, LanguageTools.getTranslation(CLYSBW)); - Dell_55AA03.dell(ip, hex,port); - //如果是心跳包 - }else if (hex.startsWith("55AA39")) { - HexBaowenShow.ok("2", "55AA39", hex, ip, LanguageTools.getTranslation(CLYSBW)); - Dell_55AA39.dell(ip, hex,port); - //如果是心跳包 - } else if (hex.startsWith("55AA14")) { - HexBaowenShow.ok("2", "55AA14", hex, ip, LanguageTools.getTranslation(CLYSBW)); - Dell_55AA14.dell_14(ip, time, hex, timestamp, port); - - }else { - Dell_uanshi_byt.intsert(ip, hex, time, timestamp, port); - } - } - } - - - public static Logger getLogger() { - return logger; - } -} - diff --git a/src/udptcp/HexBaowen.java b/src/udptcp/HexBaowen.java deleted file mode 100644 index ac0eb7c..0000000 --- a/src/udptcp/HexBaowen.java +++ /dev/null @@ -1,87 +0,0 @@ -package udptcp; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import dell_system.MessageViewPanel; -public class HexBaowen { - String hex; - String ip; - String addtime; - int port; - int localPort; // 添加本地端口字段 - String dataFrom; - static List<HexBaowen> allReceivedHexMessages = new CopyOnWriteArrayList<>(); - public static void intsert(String ip, String hex, String time, int port, int localPort, int timestamp) { - HexBaowen baowen = new HexBaowen(); - baowen.setHex(hex); - baowen.setIp(ip); - baowen.setAddtime(time); - baowen.setTimestamp(timestamp); - baowen.setPort(port); - baowen.setLocalPort(localPort); // 设置本地端口 - allReceivedHexMessages.add(baowen); - if (MessageViewPanel.isWindowVisible) { - MessageViewPanel.captureData(hex, ip, port, localPort, time); - } - } - - // 添加本地端口的getter和setter - public int getLocalPort() { - return localPort; - } - - public void setLocalPort(int localPort) { - this.localPort = localPort; - } - - - public String getDataFrom() { - return dataFrom; - } - - public void setDataFrom(String dataFrom) { - this.dataFrom = dataFrom; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - int timestamp; - - public String getHex() { - return hex; - } - - public String getIp() { - return ip; - } - - public String getAddtime() { - return addtime; - } - - public int getTimestamp() { - return timestamp; - } - - public void setHex(String hex) { - this.hex = hex; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public void setAddtime(String addtime) { - this.addtime = addtime; - } - - public void setTimestamp(int timestamp) { - this.timestamp = timestamp; - } -} \ No newline at end of file diff --git a/src/udptcp/PacketParser.java b/src/udptcp/PacketParser.java new file mode 100644 index 0000000..43f8429 --- /dev/null +++ b/src/udptcp/PacketParser.java @@ -0,0 +1,163 @@ +package udptcp; + +import java.util.ArrayList; +import java.util.List; + +// 重命名为PacketParser,表示数据包解析器 +public class PacketParser { + // 添加十六进制字符数组常量 + private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + // 缓冲区字节数组 + private byte[] buffer = new byte[4096]; + // 当前缓冲区有效数据长度 + private int bufferLength = 0; + + // 追加新数据到缓冲区 + public void appendData(byte[] newData, int length) { + // 检查缓冲区是否足够 + if (bufferLength + length > buffer.length) { + // 创建新的更大缓冲区 + byte[] newBuffer = new byte[bufferLength + length]; + // 复制原有数据 + System.arraycopy(buffer, 0, newBuffer, 0, bufferLength); + buffer = newBuffer; + } + // 追加新数据 + System.arraycopy(newData, 0, buffer, bufferLength, length); + // 更新缓冲区长度 + bufferLength += length; + } + + // 新增方法:字节数组转十六进制字符串 + public static String bytesToHexString(byte[] bytes) { + if (bytes == null) return ""; + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars); + } + + // 解析缓冲区中的所有完整数据包 + public List<DataPacket> parsePackets() { + List<DataPacket> packets = new ArrayList<>(); + int index = 0; // 当前解析位置索引 + + // 遍历缓冲区查找完整数据包 + while (index <= bufferLength - 4) { // 确保有足够数据检查包头 + // 检查包头标识 0x55 0xAA + if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) { + // 获取包类型(第3字节) + int packetType = buffer[index + 2] & 0xFF; + // 获取数据长度(第4字节) + int dataLenField = buffer[index + 3] & 0xFF; + // 计算完整包长度(包头+数据+校验) + int totalPacketLen = 4 + dataLenField + 2; // 增加2字节校验位 + + // 检查是否有足够数据构成完整包 + if (index + totalPacketLen > bufferLength) { + break; // 数据不足,等待更多数据 + } + + // 提取完整数据包 + byte[] packetData = new byte[totalPacketLen]; + System.arraycopy(buffer, index, packetData, 0, totalPacketLen); + + // 验证校验和 + if (verifyChecksum(packetData)) { + // 解析单个数据包 + DataPacket packet = parseSinglePacket(packetType, packetData); + if (packet != null) { + packets.add(packet); // 添加到结果列表 + } + index += totalPacketLen; // 移动到下一个包 + } else { + index++; // 校验失败,跳过当前字节 + } + } else { + index++; // 非包头标识,继续查找 + } + } + + // 清理已处理数据 + if (index > 0) { + int remaining = bufferLength - index; + if (remaining > 0) { + // 移动剩余数据到缓冲区开头 + System.arraycopy(buffer, index, buffer, 0, remaining); + } + bufferLength = remaining; // 更新缓冲区长度 + } + + return packets; + } + + // 校验数据包完整性 + private boolean verifyChecksum(byte[] packet) { + int len = packet.length; + if (len < 4) return false; // 长度不足 + + int sum = 0; + // 计算从第3字节到倒数第3字节的和(跳过包头和校验位) + for (int i = 2; i < len - 2; i++) { + sum += packet[i] & 0xFF; + } + // 取反得到16位校验和 + sum = ~sum & 0xFFFF; + + // 提取包中的校验和(小端格式) + int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF); + + // 比较校验和 + return sum == receivedChecksum; + } + + // 解析单个数据包 + private DataPacket parseSinglePacket(int packetType, byte[] packet) { + + // 创建数据包对象(包含包类型) + return new DataPacket(packetType, packet); + } + + // 数据包内部类 + public static class DataPacket { + private final int packetType; // 包类型 + private final byte[] packet;//包数据 + + public DataPacket(int packetType, byte[] packet) { + this.packetType = packetType; + this.packet = packet; + } + + // 获取包类型 + public int getPacketType() { + return packetType; + } + + // 包数据 + public byte[] getPacket() { + return packet; + } + + } + + // HEX字符串转字节数组 + public static byte[] hexStringToBytes(String hex) { + // 移除空格 + hex = hex.replaceAll("\\s", ""); + int len = hex.length(); + // 创建结果数组 + byte[] data = new byte[len / 2]; + // 每两个字符转换一个字节 + for (int i = 0; i < len; i += 2) { + // 高位转换 + int high = Character.digit(hex.charAt(i), 16) << 4; + // 低位转换 + int low = Character.digit(hex.charAt(i + 1), 16); + data[i / 2] = (byte) (high | low); + } + return data; + } +} \ No newline at end of file diff --git a/src/udptcp/PacketProcessingSystem.java b/src/udptcp/PacketProcessingSystem.java new file mode 100644 index 0000000..9ab4b4d --- /dev/null +++ b/src/udptcp/PacketProcessingSystem.java @@ -0,0 +1,104 @@ +package udptcp; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import dell55AAData.Dell55AA01Parser; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class PacketProcessingSystem { + // 线程安全的报文存储队列(集合A) + private static final ConcurrentLinkedQueue<HexPacket> packetQueue = new ConcurrentLinkedQueue<>(); + private static final AtomicBoolean isRunning = new AtomicBoolean(false); + private static final ExecutorService parserExecutor = Executors.newSingleThreadExecutor(); + private static Thread parserThread; + + // 报文存储结构 + public static class HexPacket { + public final String ip; + public final int port; + public final String hexData; + public final long timestamp; + + public HexPacket(String ip, int port, String hexData, long timestamp) { + this.ip = ip; + this.port = port; + this.hexData = hexData; + this.timestamp = timestamp; + } + } + + // 接收端存储报文(UDPPortAReceiver中调用) + public static void storePacket(String ip, int port, String hexData) { + if (packetQueue.size() < 100000) { // 限制队列大小防止OOM + packetQueue.offer(new HexPacket(ip, port, hexData, System.currentTimeMillis())); + } + } + + // 启动解析系统 + public static void startProcessing() { + if (isRunning.get()) return; + + isRunning.set(true); + parserThread = new Thread(() -> { + PacketParser bufferManager = new PacketParser(); + + while (isRunning.get()) { + HexPacket packet = packetQueue.poll(); + if (packet == null) { + Thread.yield(); // 队列为空时让出CPU + continue; + } + + try { + // 转换HEX为字节数据 + byte[] rawData = PacketParser.hexStringToBytes(packet.hexData); + // 追加到缓冲区并解析 + bufferManager.appendData(rawData, rawData.length); + List<PacketParser.DataPacket> parsedPackets = bufferManager.parsePackets(); + + // 处理解析后的数据包 + for (PacketParser.DataPacket p : parsedPackets) { + // 根据包头类型路由到不同解析器 + switch (p.getPacketType()) { + case 0x01: + processType01(p);break; + case 0x02: + processType02(p);break; + + default: + System.err.println("未知包类型: " + p.getPacketType()); + } + } + } catch (Exception e) { + System.err.println("解析错误: " + e.getMessage()); + } + } + }); + + parserThread.setDaemon(true); + parserThread.start(); + } + + // 停止解析系统 + public static void stopProcessing() { + isRunning.set(false); + parserExecutor.shutdownNow(); + if (parserThread != null) { + parserThread.interrupt(); + } + } + + // 示例解析方法(需根据实际协议实现) + private static void processType01(PacketParser.DataPacket packet) { + String hexData = PacketParser.bytesToHexString(packet.getPacket()); + Dell55AA01Parser.parse(hexData); + } + + private static void processType02(PacketParser.DataPacket packet) { + System.out.println("处理55AA02包: " + packet); + // 实际业务逻辑 + } + + // 其他类型处理方法... +} diff --git a/src/udptcp/TCPDiffDataReceiver.java b/src/udptcp/TCPDiffDataReceiver.java deleted file mode 100644 index 7effd27..0000000 --- a/src/udptcp/TCPDiffDataReceiver.java +++ /dev/null @@ -1,151 +0,0 @@ -package udptcp; -import java.net.ServerSocket; -import java.net.Socket; -import java.sql.SQLException; -import java.util.*; -import java.util.concurrent.*; -import dell_targets.Dell_differentialBaseStation; -import dell_targets.Dell_tag; -import targets.DifferentialBaseStation; -import targets.LocationTag; - -public class TCPDiffDataReceiver { - private static final int PORT = 7002; - private static final Map<String, Socket> deviceConnections = new ConcurrentHashMap<>(); - private static final ExecutorService executor = Executors.newCachedThreadPool(); - - public static void main(String[] args) { - // 启动设备连接监听器 - new Thread(TCPDiffDataReceiver::listenForDeviceConnections).start(); - - // 启动差分基站数据处理器 - new Thread(TCPDiffDataReceiver::processDifferentialData).start(); - } - - // 监听设备连接 - private static void listenForDeviceConnections() { - try (ServerSocket serverSocket = new ServerSocket(PORT)) { - System.out.println("TCP Differential Server started on port " + PORT); - - while (true) { - Socket deviceSocket = serverSocket.accept(); - String deviceId = "device_" + UUID.randomUUID(); // 实际应从设备获取ID - deviceConnections.put(deviceId, deviceSocket); - } - } catch (Exception e) { - System.err.println("Device connection listener crashed: " + e.getMessage()); - } - } - - // 处理差分基站数据 - private static void processDifferentialData() { - while (true) { - try { - // 1. 获取所有差分基站 - List<DifferentialBaseStation> baseStations = Dell_differentialBaseStation.getAllBaseStations(); - - // 2. 处理每个基站的数据 - for (DifferentialBaseStation station : baseStations) { - // 模拟接收数据 - byte[] diffData = receiveDataFromBaseStation(station); - station.setReceivenum(station.getReceivenum() + 1); // 更新接收计数 - - // 3. 获取在线设备 - List<LocationTag> onlineDevices = Dell_tag.getlocationTags().stream() - .filter(tag -> "1".equals(tag.getOnlineStatus())) - .toList(); - - // 4. 转发数据到设备 - forwardToDevices(station, diffData, onlineDevices); - } - - // 每秒处理一次 - Thread.sleep(1000); - } catch (Exception e) { - System.err.println("Differential data processing error: " + e.getMessage()); - } - } - } - - // 转发数据到设备 - private static void forwardToDevices(DifferentialBaseStation station, - byte[] data, - List<LocationTag> devices) throws SQLException { - if (devices.isEmpty()) return; - - // 单基站情况:广播到所有设备 - if (devices.size() == 1) { - broadcastData(data); - return; - } - - // 多基站情况:选择最近的基站 - for (LocationTag device : devices) { - DifferentialBaseStation nearestStation = findNearestBaseStation( - device, - Dell_differentialBaseStation.getAllBaseStations() - ); - - if (nearestStation.getId().equals(station.getId())) { - sendToDevice(device.getDeviceNumber(), data); - } - } - } - - // 查找最近的基站 - private static DifferentialBaseStation findNearestBaseStation(LocationTag device, - List<DifferentialBaseStation> stations) { - return stations.stream() - .min(Comparator.comparingDouble(station -> - calculateDistance( - Double.parseDouble(device.getLatitude()), - Double.parseDouble(device.getLongitude()), - Double.parseDouble(station.getLatitude()), - Double.parseDouble(station.getLongitude()) - )) - .orElse(null); - } - - // 计算距离(Haversine公式) - private static double calculateDistance(double lat1, double lon1, double lat2, double lon2) { - final int R = 6371; // 地球半径(km) - double dLat = Math.toRadians(lat2 - lat1); - double dLon = Math.toRadians(lon2 - lon1); - double a = Math.sin(dLat/2) * Math.sin(dLat/2) + - Math.cos(Math.toRadians(lat1)) * - Math.cos(Math.toRadians(lat2)) * - Math.sin(dLon/2) * Math.sin(dLon/2); - double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); - return R * c; - } - - // 广播数据到所有设备 - private static void broadcastData(byte[] data) { - deviceConnections.forEach((id, socket) -> { - executor.execute(() -> sendData(socket, data)); - }); - } - - // 发送数据到特定设备 - private static void sendToDevice(String deviceId, byte[] data) { - Socket socket = deviceConnections.get(deviceId); - if (socket != null) { - executor.execute(() -> sendData(socket, data)); - } - } - - // 实际发送数据 - private static void sendData(Socket socket, byte[] data) { - try { - socket.getOutputStream().write(data); - socket.getOutputStream().flush(); - } catch (Exception e) { - System.err.println("Data sending failed: " + e.getMessage()); - } - } - - // 模拟基站数据接收 - private static byte[] receiveDataFromBaseStation(DifferentialBaseStation station) { - return ("Data from " + station.getDeviceNumber()).getBytes(); - } -} \ No newline at end of file diff --git a/src/udptcp/UDPPortAReceiver.java b/src/udptcp/UDPPortAReceiver.java index 455da6e..a72e207 100644 --- a/src/udptcp/UDPPortAReceiver.java +++ b/src/udptcp/UDPPortAReceiver.java @@ -2,8 +2,6 @@ import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; @@ -12,41 +10,35 @@ public class UDPPortAReceiver { public static final int PORT = 8234; - private static final int MAX_DEVICES = 50000; + @SuppressWarnings("unused") + private static final int MAX_DEVICES = 50000; private static final AtomicLong packetCount = new AtomicLong(0); private static final ExecutorService executor = Executors.newFixedThreadPool(10); private static DatagramSocket socket; private static volatile boolean isRunning = false; private static Thread receiverThread; - private static final int LOCAL_PORT = PORT; // 定义本地端口 + @SuppressWarnings("unused") + private static final int LOCAL_PORT = PORT; // 定义本地端口 // 启动接收器的静态方法 public static void startReceiver() { - if (isRunning) return; - + if (isRunning) return; isRunning = true; receiverThread = new Thread(() -> { try { socket = new DatagramSocket(PORT); - byte[] buffer = new byte[2048]; - + byte[] buffer = new byte[2048]; while (isRunning) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); - socket.receive(packet); - + socket.receive(packet); executor.execute(() -> { try { String ip = packet.getAddress().getHostAddress(); int port = packet.getPort(); String hexData = bytesToHex(packet.getData(), packet.getLength()); - packetCount.incrementAndGet(); - // 获取当前时间和时间戳 - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String time = sdf.format(new Date()); - int timestamp = (int)(System.currentTimeMillis() / 1000); - - // 保存到HexBaowen集合 - // 调用时添加本地端口参数 - HexBaowen.intsert(ip, hexData, time, port, LOCAL_PORT, timestamp); + // 调用时添加本地端口参数 + PacketProcessingSystem.storePacket(ip, port, hexData); + // 报文查看窗口显示数据 + MessageViewPanel.showData(hexData, ip, port, PORT,"1"); } catch (Exception e) { System.err.println("Error processing UDP-A packet: " + e.getMessage()); diff --git a/src/udptcp/UDPPortBReceiver.java b/src/udptcp/UDPPortBReceiver.java index 4e8a5cd..9e006a4 100644 --- a/src/udptcp/UDPPortBReceiver.java +++ b/src/udptcp/UDPPortBReceiver.java @@ -2,22 +2,21 @@ import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; -import dell_system.MessageViewPanel; public class UDPPortBReceiver { public static final int PORT = 7000; - private static final int MAX_DEVICES = 50000; + @SuppressWarnings("unused") + private static final int MAX_DEVICES = 50000; private static final AtomicLong packetCount = new AtomicLong(0); private static final ExecutorService executor = Executors.newFixedThreadPool(10); private static DatagramSocket socket; private static volatile boolean isRunning = false; private static Thread receiverThread; - private static final int LOCAL_PORT = PORT; // 定义本地端口 + @SuppressWarnings("unused") + private static final int LOCAL_PORT = PORT; // 定义本地端口 // 启动接收器的静态方法 public static void startReceiver() { if (isRunning) return; @@ -37,15 +36,8 @@ String ip = packet.getAddress().getHostAddress(); int port = packet.getPort(); String hexData = bytesToHex(packet.getData(), packet.getLength()); - packetCount.incrementAndGet(); - // 获取当前时间和时间戳 - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String time = sdf.format(new Date()); - int timestamp = (int)(System.currentTimeMillis() / 1000); - - // 保存到HexBaowen集合 - // 调用时添加本地端口参数 - HexBaowen.intsert(ip, hexData, time, port, LOCAL_PORT, timestamp); + // 调用时添加本地端口参数 + PacketProcessingSystem.storePacket(ip, port, hexData); } catch (Exception e) { System.err.println("Error processing UDP-A packet: " + e.getMessage()); @@ -74,7 +66,6 @@ } // 发送数据到指定设备 - // 发送数据到指定设备 public static void sendData(String ip, int port, String data, boolean isHex) { try { byte[] sendBytes; diff --git a/src/window/Windows.java b/src/window/Windows.java index 0114e00..52b17cc 100644 --- a/src/window/Windows.java +++ b/src/window/Windows.java @@ -17,6 +17,7 @@ import dell_map.Dell_Map; import dell_map.MapViewer; +import dell_targets.Dell_SystemConfiguration; import targets.Mapdata; public class Windows extends JFrame { @@ -82,6 +83,16 @@ createLanguageMenu(); } + // 新增方法:根据系统配置获取当前语言环境 + public Locale getSystemLocale() { + return "1".equals(Dell_SystemConfiguration.language) ? + Locale.ENGLISH : Locale.SIMPLIFIED_CHINESE; + } + + // 新增方法:供其他类获取当前语言环境 + public Locale getCurrentLocale() { + return this.currentLocale; + } private ResourceBundle loadResourceBundle(Locale locale) { String fileName = locale.equals(Locale.ENGLISH) ? diff --git a/systemfile/Messages_en.properties b/systemfile/Messages_en.properties index 1a9a709..ea593dd 100644 --- a/systemfile/Messages_en.properties +++ b/systemfile/Messages_en.properties @@ -1,3 +1,17 @@ +# New message viewing related resources +MESSAGE_VIEW_ALL_TYPES=All Types +MESSAGE_VIEW_UDP_PORT_A=UDP Port A +MESSAGE_VIEW_UDP_PORT_B=UDP Port B +MESSAGE_VIEW_TCP_PORT=TCP Port +MESSAGE_VIEW_MQTT_PORT=MQTT Port +MESSAGE_VIEW_ALL_DEVICES=All Devices +MESSAGE_VIEW_ALL_PROTOCOLS=All Protocols +MESSAGE_VIEW_SHOW_DATA=Show Data +MESSAGE_VIEW_DATA_SOURCE=Data Source +MESSAGE_VIEW_FILTERED_DATA=Filtered Data +MESSAGE_VIEW_HEX_FORMAT=HEX Format +MESSAGE_VIEW_ASCII_FORMAT=ASCII Format +MESSAGE_VIEW_MIXED_FORMAT=Mixed Format # New Resource Key-Value Pairs packet.count.format=Packets Received: %d label.id=Label ID diff --git a/systemfile/Messages_zh.properties b/systemfile/Messages_zh.properties index 3fd7abd..f809f94 100644 --- a/systemfile/Messages_zh.properties +++ b/systemfile/Messages_zh.properties @@ -1,3 +1,17 @@ +# 鏂板鐨勬姤鏂囨煡鐪嬬浉鍏宠祫婧� +MESSAGE_VIEW_ALL_TYPES=鎵�鏈夌被鍨� +MESSAGE_VIEW_UDP_PORT_A=UDP绔彛A +MESSAGE_VIEW_UDP_PORT_B=UDP绔彛B +MESSAGE_VIEW_TCP_PORT=TCP绔彛 +MESSAGE_VIEW_MQTT_PORT=MQTT绔彛 +MESSAGE_VIEW_ALL_DEVICES=鎵�鏈夎澶� +MESSAGE_VIEW_ALL_PROTOCOLS=鎵�鏈夊崗璁� +MESSAGE_VIEW_SHOW_DATA=鏄剧ず鏁版嵁 +MESSAGE_VIEW_DATA_SOURCE=鏁版嵁鏉ユ簮 +MESSAGE_VIEW_FILTERED_DATA=宸茶繃婊ゆ暟鎹� +MESSAGE_VIEW_HEX_FORMAT=HEX鏍煎紡 +MESSAGE_VIEW_ASCII_FORMAT=ASCII鏍煎紡 +MESSAGE_VIEW_MIXED_FORMAT=娣峰悎鏍煎紡 # 鏂板璧勬簮閿�煎 packet.count.format=鏀跺埌鏁版嵁:%d鏉� label.id=鏍囩缂栧彿 diff --git a/systemfile/logfile/openlog.txt b/systemfile/logfile/openlog.txt index 1950da1..f8a393f 100644 --- a/systemfile/logfile/openlog.txt +++ b/systemfile/logfile/openlog.txt @@ -634,3 +634,70 @@ 程序关闭: 2025-08-08 23:06:23 工作时长: 0小时 0分钟 41秒 ----------------------------------- +程序启动: 2025-08-09 10:43:53 +程序关闭: 2025-08-09 15:09:35 +工作时长: 4小时 25分钟 41秒 +----------------------------------- +程序启动: 2025-08-09 15:09:38 +程序关闭: 2025-08-09 15:09:41 +工作时长: 0小时 0分钟 2秒 +----------------------------------- +程序启动: 2025-08-09 15:21:34 +程序启动: 2025-08-09 15:26:45 +程序关闭: 2025-08-09 15:26:49 +工作时长: 0小时 5分钟 15秒 +----------------------------------- +程序启动: 2025-08-09 15:26:51 +程序启动: 2025-08-09 15:28:12 +程序关闭: 2025-08-09 15:29:23 +工作时长: 0小时 1分钟 10秒 +----------------------------------- +程序启动: 2025-08-09 15:29:25 +程序关闭: 2025-08-09 15:30:53 +工作时长: 0小时 1分钟 27秒 +----------------------------------- +程序启动: 2025-08-09 15:30:55 +程序关闭: 2025-08-09 15:31:19 +工作时长: 0小时 0分钟 23秒 +----------------------------------- +程序启动: 2025-08-09 15:31:22 +程序关闭: 2025-08-09 15:36:19 +工作时长: 0小时 4分钟 57秒 +----------------------------------- +程序启动: 2025-08-09 15:36:21 +程序关闭: 2025-08-09 15:38:36 +工作时长: 0小时 2分钟 15秒 +----------------------------------- +程序启动: 2025-08-09 15:38:39 +程序关闭: 2025-08-09 16:03:25 +工作时长: 0小时 24分钟 46秒 +----------------------------------- +程序启动: 2025-08-09 16:03:28 +程序关闭: 2025-08-09 16:03:42 +工作时长: 0小时 0分钟 14秒 +----------------------------------- +程序启动: 2025-08-09 16:13:27 +程序关闭: 2025-08-09 16:16:14 +工作时长: 0小时 2分钟 46秒 +----------------------------------- +程序启动: 2025-08-09 16:16:17 +程序关闭: 2025-08-09 16:16:37 +工作时长: 0小时 0分钟 19秒 +----------------------------------- +程序启动: 2025-08-09 16:19:34 +程序关闭: 2025-08-09 16:21:03 +工作时长: 0小时 1分钟 29秒 +----------------------------------- +程序启动: 2025-08-09 16:21:05 +程序关闭: 2025-08-09 16:22:09 +工作时长: 0小时 1分钟 3秒 +----------------------------------- +程序启动: 2025-08-09 16:22:10 +程序关闭: 2025-08-09 16:28:22 +工作时长: 0小时 6分钟 11秒 +----------------------------------- +程序启动: 2025-08-09 16:28:24 +程序关闭: 2025-08-09 16:32:37 +工作时长: 0小时 4分钟 12秒 +----------------------------------- +程序启动: 2025-08-09 16:32:39 -- Gitblit v1.9.3