package home;
|
|
import javax.swing.*;
|
import PublicPannel.AntiCollisionPanel;
|
import PublicPannel.BaseParameterPanel;
|
import PublicPannel.BaseStationPanel;
|
import PublicPannel.TagPanel;
|
import PublicPannel.UpgradePanel;
|
import jiexi.DellTag55AA03;
|
import java.awt.*;
|
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionListener;
|
import java.net.InetAddress;
|
import java.net.NetworkInterface;
|
import java.net.SocketException;
|
import java.util.ArrayList;
|
import java.util.Enumeration;
|
import java.util.List;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.function.Consumer;
|
|
public class NetworkCommunicationPanel extends JPanel {
|
/**
|
*
|
*/
|
private static final long serialVersionUID = 1L;
|
private MainFrame mainFrame;
|
private JComboBox<String> protocolCombo;
|
private JComboBox<String> hostAddressCombo; // 改为下拉框
|
private JTextField portField;
|
private JLabel protocolTypeLabel, hostLabel, portLabel;
|
private JButton openBtn;
|
private JTabbedPane rightTabbedPane;
|
private BaseParameterPanel baseParamPanel;
|
private BaseStationPanel baseStationPanel;
|
private TagPanel tagPanel;
|
private AntiCollisionPanel antiCollisionPanel;
|
private UpgradePanel upgradePanel;
|
private JButton readParamsBtn, saveParamsBtn, restartDeviceBtn, resetFactoryBtn;
|
private boolean isOpen = false;
|
|
// 在类变量声明部分添加新按钮
|
private JButton readRelayParamsBtn, saveRelayParamsBtn;
|
|
// 新增:数据日志面板引用
|
private DataLogPanel dataLogPanel;
|
|
private JComboBox<String> clientCombo; // 客户端/发送端下拉框
|
private NetworkBase currentNetwork;
|
private java.util.List<String> connectedClients = new java.util.ArrayList<>();
|
|
// 配置命令常量 - 新增
|
private static final String READ_CONFIG_CMD = "55AA03060102800073FF"; // 读取配置命令
|
private static final String READ_CONFIG_CMD2 = "55AA03060102F800FBFE"; // 读取配置命令
|
private static final String RESTART_DEVICE_CMD = "55AA03016001FF"; // 重启设备命令
|
private static final String RESET_FACTORY_CMD = "55AA03016002FF"; // 恢复出厂设置命令
|
|
public NetworkCommunicationPanel(MainFrame mainFrame) {
|
this.mainFrame = mainFrame;
|
initializeUI();
|
setupButtonListeners(); // 新增:设置按钮监听器
|
}
|
|
private void initializeUI() {
|
setLayout(new BorderLayout());
|
|
// 控制面板
|
add(createControlPanel(), BorderLayout.NORTH);
|
|
// 主分割面板 - 使用水平分割
|
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
mainSplitPane.setDividerLocation(320);
|
|
// 基础参数面板
|
JPanel leftPanel = createBaseParameterPanel();
|
|
// 右侧功能面板
|
JPanel rightPanel = createRightPanel();
|
rightPanel.setBorder(null); // 移除面板边框
|
|
mainSplitPane.setLeftComponent(leftPanel);
|
mainSplitPane.setRightComponent(rightPanel);
|
|
add(mainSplitPane, BorderLayout.CENTER);
|
|
// 底部按钮面板
|
add(createBottomButtonPanel(), BorderLayout.SOUTH);
|
}
|
|
/**
|
* 设置按钮监听器 - 新增方法
|
*/
|
private void setupButtonListeners() {
|
readParamsBtn.addActionListener(e -> readParameters());
|
saveParamsBtn.addActionListener(e -> saveParameters());
|
restartDeviceBtn.addActionListener(e -> restartDevice());
|
resetFactoryBtn.addActionListener(e -> resetFactory());
|
// 新增继电器参数按钮监听器
|
readRelayParamsBtn.addActionListener(e -> readRelayParameters());
|
saveRelayParamsBtn.addActionListener(e -> saveRelayParameters());
|
}
|
|
// 修改后的读取继电器参数方法
|
private void readRelayParameters() {
|
if (!isOpen || currentNetwork == null) {
|
JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 继电器参数读取命令 - 需要根据实际协议定义
|
String readRelayCommand = "55AA03060102800073FF"; // 示例命令,需要替换为实际的继电器读取命令
|
byte[] data = hexStringToByteArray(readRelayCommand);
|
|
if (data == null) {
|
JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 在数据日志窗口显示发送的指令
|
if (dataLogPanel != null) {
|
dataLogPanel.addLogData(data, getString("send.read.relay.command"));
|
}
|
|
AtomicBoolean responseReceived = new AtomicBoolean(false);
|
AtomicBoolean operationCompleted = new AtomicBoolean(false);
|
|
// 按钮视觉反馈
|
readRelayParamsBtn.setBackground(Color.CYAN);
|
readRelayParamsBtn.setEnabled(false);
|
|
// 设置响应消费者
|
Consumer<byte[]> responseConsumer = responseData -> {
|
if (operationCompleted.get()) return;
|
|
currentNetwork.setResponseConsumer(null);
|
operationCompleted.set(true);
|
|
String hexResponse = bytesToHex(responseData);
|
|
if (hexResponse.startsWith("55AA03")) {
|
// 使用解析器解析继电器响应数据
|
DellTag55AA03.ParseResult result = DellTag55AA03.parse3(hexResponse, "127.0.0.1", 0);
|
|
if (result != null) {
|
SwingUtilities.invokeLater(() -> {
|
// 这里可以添加更新继电器参数字段的逻辑
|
// 如果继电器参数需要更新到特定面板,可以在这里调用相应的方法
|
updateParameterFields2(result);
|
responseReceived.set(true);
|
JOptionPane.showMessageDialog(this, getString("relay_read_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
|
|
// 恢复按钮状态
|
readRelayParamsBtn.setBackground(new Color(70, 130, 180));
|
readRelayParamsBtn.setEnabled(true);
|
});
|
return;
|
}
|
}
|
|
// 响应数据不合法
|
SwingUtilities.invokeLater(() -> {
|
JOptionPane.showMessageDialog(this, getString("invalid_response_data"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
readRelayParamsBtn.setBackground(new Color(70, 130, 180));
|
readRelayParamsBtn.setEnabled(true);
|
});
|
};
|
|
// 在独立线程中执行网络操作
|
new Thread(() -> {
|
currentNetwork.setResponseConsumer(responseConsumer);
|
|
boolean success = sendNetworkDataInternal(data, getString("read.relay.parameters"));
|
if (!success) {
|
SwingUtilities.invokeLater(() -> {
|
JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
currentNetwork.setResponseConsumer(null);
|
readRelayParamsBtn.setBackground(new Color(70, 130, 180));
|
readRelayParamsBtn.setEnabled(true);
|
});
|
return;
|
}
|
|
// 等待响应,最长5秒
|
long startTime = System.currentTimeMillis();
|
while (!operationCompleted.get() && (System.currentTimeMillis() - startTime) < 5000) {
|
try {
|
Thread.sleep(100);
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
break;
|
}
|
}
|
|
// 检查是否超时
|
if (!operationCompleted.get()) {
|
operationCompleted.set(true);
|
SwingUtilities.invokeLater(() -> {
|
JOptionPane.showMessageDialog(this, getString("relay_read_timeout"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
currentNetwork.setResponseConsumer(null);
|
readRelayParamsBtn.setBackground(new Color(70, 130, 180));
|
readRelayParamsBtn.setEnabled(true);
|
});
|
}
|
}).start();
|
}
|
|
// 修改后的保存继电器参数方法
|
private void saveRelayParameters() {
|
if (!isOpen || currentNetwork == null) {
|
JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
try {
|
// 从防撞面板获取继电器参数并构建配置数据
|
byte[] relayConfigData = PanelFieldUpdater.collectParametersToConfig2(antiCollisionPanel);
|
|
if (relayConfigData == null) {
|
JOptionPane.showMessageDialog(this, getString("invalid_relay_config"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 在数据日志窗口显示发送的配置数据
|
if (dataLogPanel != null) {
|
dataLogPanel.addLogData(relayConfigData, getString("send.save.relay.command"));
|
}
|
|
// 按钮视觉反馈
|
saveRelayParamsBtn.setBackground(Color.CYAN);
|
saveRelayParamsBtn.setEnabled(false);
|
|
boolean success = sendNetworkDataInternal(relayConfigData, getString("save.relay.parameters"));
|
|
SwingUtilities.invokeLater(() -> {
|
if (success) {
|
JOptionPane.showMessageDialog(this, getString("relay_save_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
|
} else {
|
JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
}
|
|
// 恢复按钮状态
|
saveRelayParamsBtn.setBackground(new Color(70, 130, 180));
|
saveRelayParamsBtn.setEnabled(true);
|
});
|
|
} catch (Exception e) {
|
SwingUtilities.invokeLater(() -> {
|
JOptionPane.showMessageDialog(this, getString("relay_save_failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
|
saveRelayParamsBtn.setBackground(new Color(70, 130, 180));
|
saveRelayParamsBtn.setEnabled(true);
|
});
|
}
|
}
|
|
/**
|
* 更新参数字段到界面 - 新增方法用于继电器参数
|
*/
|
private void updateParameterFields2(DellTag55AA03.ParseResult result) {
|
PanelFieldUpdater.updateAllPanels2(result, antiCollisionPanel);
|
}
|
|
/**
|
* 读取参数 - 新增方法
|
*/
|
private void readParameters() {
|
if (!isOpen || currentNetwork == null) {
|
JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 根据当前选中的面板决定使用哪个指令和解析方法
|
String readCommand;
|
final boolean useParse2; // 声明为final
|
|
int selectedPanelIndex = getCurrentSelectedPanelIndex();
|
if (selectedPanelIndex == 2) { // 防撞面板的索引为2
|
readCommand = READ_CONFIG_CMD2;
|
useParse2 = true;
|
} else {
|
readCommand = READ_CONFIG_CMD;
|
useParse2 = false;
|
}
|
|
byte[] data = hexStringToByteArray(readCommand);
|
|
if (data == null) {
|
JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 新增:在数据日志窗口显示发送的指令
|
if (dataLogPanel != null) {
|
dataLogPanel.addLogData(data, getString("send.read.config.command"));
|
}
|
|
AtomicBoolean responseReceived = new AtomicBoolean(false);
|
AtomicBoolean operationCompleted = new AtomicBoolean(false);
|
|
// 按钮视觉反馈
|
readParamsBtn.setBackground(Color.GREEN);
|
|
|
// 设置响应消费者
|
Consumer<byte[]> responseConsumer = responseData -> {
|
if (operationCompleted.get()) return;
|
|
// 清空响应消费者以避免重复处理
|
currentNetwork.setResponseConsumer(null);
|
operationCompleted.set(true);
|
|
String hexResponse = bytesToHex(responseData);
|
|
if (hexResponse.startsWith("55AA03")) {
|
// 根据面板选择使用parse还是parse2方法
|
DellTag55AA03.ParseResult result;
|
if (useParse2) {
|
result = DellTag55AA03.parse2(hexResponse, "127.0.0.1", 0);
|
} else {
|
result = DellTag55AA03.parse(hexResponse, "127.0.0.1", 0);
|
}
|
|
if (result != null) {
|
SwingUtilities.invokeLater(() -> {
|
updateParameterFields(result);
|
|
JOptionPane.showMessageDialog(this, getString("config_read_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
|
|
// 恢复按钮状态
|
readParamsBtn.setBackground(new Color(70, 130, 180));
|
|
});
|
return;
|
}
|
}
|
|
// 响应数据不合法
|
SwingUtilities.invokeLater(() -> {
|
//JOptionPane.showMessageDialog(this, getString("invalid_response_data"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
readParamsBtn.setBackground(new Color(70, 130, 180));
|
|
});
|
};
|
|
// 在独立线程中执行网络操作
|
new Thread(() -> {
|
currentNetwork.setResponseConsumer(responseConsumer);
|
|
boolean success = sendNetworkDataInternal(data, getString("read.parameters"));
|
if (!success) {
|
SwingUtilities.invokeLater(() -> {
|
//JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
currentNetwork.setResponseConsumer(null);
|
readParamsBtn.setBackground(new Color(70, 130, 180));
|
|
});
|
return;
|
}
|
|
// 等待响应,最长5秒
|
long startTime = System.currentTimeMillis();
|
while (!operationCompleted.get() && (System.currentTimeMillis() - startTime) < 5000) {
|
try {
|
Thread.sleep(100);
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
break;
|
}
|
}
|
|
// 检查是否超时
|
if (!operationCompleted.get()) {
|
operationCompleted.set(true);
|
SwingUtilities.invokeLater(() -> {
|
//JOptionPane.showMessageDialog(this, getString("config_read_timeout"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
currentNetwork.setResponseConsumer(null);
|
readParamsBtn.setBackground(new Color(70, 130, 180));
|
|
});
|
}
|
}).start();
|
}
|
|
/**
|
* 更新参数字段到界面 - 新增方法
|
*/
|
private void updateParameterFields(DellTag55AA03.ParseResult result) {
|
PanelFieldUpdater.updateAllPanels(result, baseParamPanel, baseStationPanel,
|
tagPanel, antiCollisionPanel, upgradePanel);
|
}
|
|
/**
|
* 保存参数 - 新增方法
|
*/
|
private void saveParameters() {
|
if (!isOpen || currentNetwork == null) {
|
JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
try {
|
// 使用工具类从各个面板收集参数并构建配置数据
|
byte[] configData = PanelFieldUpdater.collectParametersToConfig(
|
baseParamPanel, baseStationPanel, tagPanel, antiCollisionPanel, upgradePanel);
|
|
if (configData == null) {
|
JOptionPane.showMessageDialog(this, getString("invalid_config_data"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 新增:在数据日志窗口显示发送的配置数据
|
if (dataLogPanel != null) {
|
dataLogPanel.addLogData(configData, getString("send.save.config.command"));
|
}
|
|
boolean success = sendNetworkDataInternal(configData, getString("save.parameters"));
|
if (success) {
|
JOptionPane.showMessageDialog(this, getString("config_save_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
|
} else {
|
JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
}
|
|
} catch (Exception e) {
|
JOptionPane.showMessageDialog(this, getString("config_save_failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 按钮视觉反馈
|
saveParamsBtn.setBackground(Color.GREEN);
|
Timer timer = new Timer(500, e -> {
|
saveParamsBtn.setBackground(new Color(70, 130, 180));
|
});
|
timer.setRepeats(false);
|
timer.start();
|
}
|
|
/**
|
* 重启设备 - 新增方法
|
*/
|
private void restartDevice() {
|
if (!isOpen || currentNetwork == null) {
|
JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
byte[] data = hexStringToByteArray(RESTART_DEVICE_CMD);
|
if (data == null) {
|
JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 新增:在数据日志窗口显示发送的指令
|
if (dataLogPanel != null) {
|
dataLogPanel.addLogData(data, getString("send.restart.command"));
|
}
|
|
boolean success = sendNetworkDataInternal(data, getString("restart.device"));
|
if (success) {
|
JOptionPane.showMessageDialog(this, getString("restart_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
|
} else {
|
JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
}
|
|
// 按钮视觉反馈
|
restartDeviceBtn.setBackground(Color.ORANGE);
|
Timer timer = new Timer(500, e -> {
|
restartDeviceBtn.setBackground(new Color(70, 130, 180));
|
});
|
timer.setRepeats(false);
|
timer.start();
|
}
|
|
/**
|
* 恢复出厂设置 - 新增方法
|
*/
|
private void resetFactory() {
|
if (!isOpen || currentNetwork == null) {
|
JOptionPane.showMessageDialog(this, getString("open_network_first"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 恢复出厂设置命令
|
byte[] data = hexStringToByteArray(RESET_FACTORY_CMD);
|
if (data == null) {
|
JOptionPane.showMessageDialog(this, getString("invalid_hex_format"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 新增:在数据日志窗口显示发送的指令
|
if (dataLogPanel != null) {
|
dataLogPanel.addLogData(data, getString("send.reset.factory.command"));
|
}
|
|
boolean success = sendNetworkDataInternal(data, getString("reset.factory"));
|
if (success) {
|
JOptionPane.showMessageDialog(this, getString("reset_success"), getString("info"), JOptionPane.INFORMATION_MESSAGE);
|
} else {
|
JOptionPane.showMessageDialog(this, getString("send_data_failed"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
}
|
|
// 按钮视觉反馈
|
resetFactoryBtn.setBackground(Color.RED);
|
Timer timer = new Timer(500, e -> {
|
resetFactoryBtn.setBackground(new Color(70, 130, 180));
|
});
|
timer.setRepeats(false);
|
timer.start();
|
}
|
|
/**
|
* 内部发送网络数据方法 - 根据协议类型选择发送目标
|
*/
|
public boolean sendNetworkDataInternal(byte[] data, String description) {
|
if (currentNetwork == null || !isOpen) {
|
return false;
|
}
|
|
try {
|
String protocol = (String) protocolCombo.getSelectedItem();
|
boolean success = false;
|
|
if ("TCP Client".equals(protocol)) {
|
// TCP Client模式:直接发送到服务端
|
success = currentNetwork.sendData(new String(data, java.nio.charset.StandardCharsets.UTF_8));
|
} else {
|
// UDP或TCP Server模式:发送到选中的客户端
|
String selectedClient = (String) clientCombo.getSelectedItem();
|
if (selectedClient != null && !selectedClient.isEmpty()) {
|
if (currentNetwork instanceof UdpListener) {
|
// UDP模式:解析IP和端口
|
String[] parts = selectedClient.split(":");
|
if (parts.length == 2) {
|
String ip = parts[0];
|
int port = Integer.parseInt(parts[1]);
|
success = ((UdpListener) currentNetwork).sendDataTo(data, ip, port);
|
}
|
} else if (currentNetwork instanceof TcpServer) {
|
// TCP Server模式:发送到指定客户端
|
success = ((TcpServer) currentNetwork).sendDataToClient(selectedClient, data);
|
}
|
} else {
|
JOptionPane.showMessageDialog(this, getString("please.select.client"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return false;
|
}
|
}
|
|
if (success && dataLogPanel != null) {
|
dataLogPanel.addLogData(data, description);
|
}
|
|
return success;
|
} catch (Exception e) {
|
JOptionPane.showMessageDialog(this, getString("send.data.failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return false;
|
}
|
}
|
|
private JPanel createControlPanel() {
|
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
protocolTypeLabel = new JLabel(getString("protocol.type"));
|
panel.add(protocolTypeLabel);
|
protocolCombo = new JComboBox<>(new String[]{"UDP", "TCP Client", "TCP Server"});
|
protocolCombo.addActionListener(new ProtocolChangeListener());
|
panel.add(protocolCombo);
|
|
hostLabel = new JLabel(getString("local.host.address"));
|
panel.add(hostLabel);
|
|
// 创建主机地址下拉框并填充本地IP地址
|
hostAddressCombo = new JComboBox<>();
|
populateLocalIPAddresses();
|
hostAddressCombo.setEditable(false); // 默认不可编辑
|
panel.add(hostAddressCombo);
|
|
portLabel = new JLabel(getString("local.host.port"));
|
panel.add(portLabel);
|
|
portField = new JTextField(8);
|
panel.add(portField);
|
|
// 使用ButtonUtils创建蓝色样式按钮
|
openBtn = ButtonUtils.createBlueButton(getString("open"));
|
openBtn.addActionListener(e -> toggleConnection());
|
panel.add(openBtn);
|
|
// 添加客户端/发送端下拉框
|
clientCombo = new JComboBox<>();
|
clientCombo.setEnabled(false);
|
clientCombo.setPreferredSize(new Dimension(150, 25));
|
panel.add(clientCombo);
|
|
return panel;
|
}
|
|
/**
|
* 获取本地网卡的IP地址并填充到下拉框
|
*/
|
private void populateLocalIPAddresses() {
|
List<String> ipAddresses = new ArrayList<>();
|
|
try {
|
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
while (networkInterfaces.hasMoreElements()) {
|
NetworkInterface networkInterface = networkInterfaces.nextElement();
|
|
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
|
while (inetAddresses.hasMoreElements()) {
|
InetAddress inetAddress = inetAddresses.nextElement();
|
|
// 只添加IPv4地址
|
if (inetAddress.getAddress().length == 4) {
|
ipAddresses.add(inetAddress.getHostAddress());
|
}
|
}
|
}
|
} catch (SocketException e) {
|
e.printStackTrace();
|
// 如果获取失败,添加本地回环地址作为备选
|
ipAddresses.add("127.0.0.1");
|
}
|
|
// 如果没有找到任何IP地址,添加本地回环地址
|
if (ipAddresses.isEmpty()) {
|
ipAddresses.add("127.0.0.1");
|
}
|
|
// 清空下拉框并添加获取到的IP地址
|
hostAddressCombo.removeAllItems();
|
for (String ip : ipAddresses) {
|
hostAddressCombo.addItem(ip);
|
}
|
|
// 设置默认选择第一个IP地址
|
if (hostAddressCombo.getItemCount() > 0) {
|
hostAddressCombo.setSelectedIndex(0);
|
}
|
}
|
|
/**
|
* 清空下拉框并设置为可编辑状态(用于TCP Client模式)
|
*/
|
private void clearAndMakeEditable() {
|
hostAddressCombo.removeAllItems();
|
hostAddressCombo.setEditable(true);
|
hostAddressCombo.setSelectedItem(""); // 清空当前选择
|
}
|
|
/**
|
* 填充本地IP地址并设置为不可编辑状态(用于UDP和TCP Server模式)
|
*/
|
private void populateAndMakeNonEditable() {
|
populateLocalIPAddresses();
|
hostAddressCombo.setEditable(false);
|
}
|
|
private void toggleConnection() {
|
if (!isOpen) {
|
openConnection();
|
} else {
|
closeConnection();
|
refreshLocalIPAddresses();
|
}
|
|
}
|
|
private void openConnection() {
|
String protocol = (String) protocolCombo.getSelectedItem();
|
String host = getSelectedHostAddress();
|
String portText = portField.getText().trim();
|
|
if (host.isEmpty() || portText.isEmpty()) {
|
JOptionPane.showMessageDialog(this, getString("please.fill.host.port"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
try {
|
int port = Integer.parseInt(portText);
|
|
switch (protocol) {
|
case "UDP":
|
currentNetwork = new UdpListener(host, port);
|
break;
|
case "TCP Client":
|
currentNetwork = new TcpClient(host, port);
|
break;
|
case "TCP Server":
|
currentNetwork = new TcpServer(host, port);
|
((TcpServer) currentNetwork).setClientListListener(this::updateClientList);
|
break;
|
}
|
|
currentNetwork.setDataListener(new NetworkBase.NetworkDataListener() {
|
@Override
|
public void onDataReceived(byte[] data, String fromAddress) {
|
// 新增:将接收到的数据输出到数据日志面板
|
if (dataLogPanel != null && data != null ) {
|
|
String logDescription = "From: " + fromAddress ;
|
dataLogPanel.addLogData(data, logDescription);
|
}
|
|
// 新增:如果是UDP协议,将发送端地址添加到clientCombo中
|
if ("UDP".equals(protocol)) {
|
addUdpSenderToCombo(fromAddress);
|
}
|
}
|
|
@Override
|
public void onStatusChanged(String status, boolean isConnected) {
|
SwingUtilities.invokeLater(() -> {
|
System.out.println(status);
|
// 可选:将状态信息也记录到数据日志
|
if (dataLogPanel != null) {
|
dataLogPanel.addLog(status);
|
}
|
});
|
}
|
|
@Override
|
public void onError(String errorMessage) {
|
SwingUtilities.invokeLater(() -> {
|
JOptionPane.showMessageDialog(NetworkCommunicationPanel.this,
|
errorMessage, getString("error"), JOptionPane.ERROR_MESSAGE);
|
// 记录错误信息到数据日志
|
if (dataLogPanel != null) {
|
dataLogPanel.addLog(getString("error") + ": " + errorMessage);
|
}
|
if (!isOpen) {
|
// 如果连接失败,不更新打开按钮状态
|
return;
|
}
|
});
|
}
|
});
|
|
boolean success = currentNetwork.start();
|
if (success) {
|
isOpen = true;
|
openBtn.setText(getString("close"));
|
clientCombo.setEnabled(true);
|
|
// 记录连接成功信息到数据日志
|
if (dataLogPanel != null) {
|
String connectionInfo = protocol + " " + getString("connection.established") + " - " + host + ":" + port;
|
dataLogPanel.addLog(connectionInfo);
|
}
|
|
// 新增:UDP模式下设置客户端下拉框的提示文本
|
if ("UDP".equals(protocol)) {
|
clientCombo.setToolTipText(getString("data.sender.list"));
|
}
|
} else {
|
// 连接失败,不更新按钮状态
|
currentNetwork = null;
|
}
|
|
} catch (NumberFormatException e) {
|
JOptionPane.showMessageDialog(this, getString("port.must.be.number"), getString("error"), JOptionPane.ERROR_MESSAGE);
|
} catch (Exception e) {
|
JOptionPane.showMessageDialog(this, getString("connection.failed.msg") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
|
currentNetwork = null;
|
}
|
}
|
|
private void closeConnection() {
|
if (currentNetwork != null) {
|
// 记录关闭连接信息到数据日志
|
if (dataLogPanel != null) {
|
dataLogPanel.addLog(getString("network.connection.closed"));
|
}
|
|
currentNetwork.stop();
|
currentNetwork = null;
|
}
|
isOpen = false;
|
openBtn.setText(getString("open"));
|
clientCombo.setEnabled(false);
|
clientCombo.removeAllItems();
|
connectedClients.clear();
|
}
|
|
/**
|
* 设置数据日志面板引用
|
*/
|
public void setDataLogPanel(DataLogPanel dataLogPanel) {
|
this.dataLogPanel = dataLogPanel;
|
}
|
|
// 十六进制字符串转字节数组 (从SerialCommunicationPanel复制)
|
private byte[] hexStringToByteArray(String s) {
|
try {
|
int len = s.length();
|
byte[] data = new byte[len / 2];
|
for (int i = 0; i < len; i += 2) {
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
+ Character.digit(s.charAt(i+1), 16));
|
}
|
return data;
|
} catch (Exception e) {
|
return null;
|
}
|
}
|
|
// 字节数组转十六进制字符串 - 新增方法
|
private String bytesToHex(byte[] bytes) {
|
StringBuilder sb = new StringBuilder();
|
for (byte b : bytes) {
|
sb.append(String.format("%02X", b));
|
}
|
return sb.toString();
|
}
|
|
// 更新客户端列表
|
private void updateClientList(java.util.List<String> clients) {
|
SwingUtilities.invokeLater(() -> {
|
connectedClients = clients;
|
clientCombo.removeAllItems();
|
for (String client : connectedClients) {
|
clientCombo.addItem(client);
|
}
|
});
|
}
|
|
private JPanel createBaseParameterPanel() {
|
JPanel panel = new JPanel(new BorderLayout());
|
baseParamPanel = new BaseParameterPanel(mainFrame);
|
panel.add(baseParamPanel, BorderLayout.CENTER);
|
return panel;
|
}
|
|
private JPanel createRightPanel() {
|
JPanel panel = new JPanel(new BorderLayout());
|
panel.setBorder(null); // 移除面板边框
|
|
// 右侧选项卡
|
rightTabbedPane = new JTabbedPane();
|
|
// 创建各个功能面板
|
baseStationPanel = new BaseStationPanel(mainFrame);
|
tagPanel = new TagPanel(mainFrame);
|
antiCollisionPanel = new AntiCollisionPanel(mainFrame);
|
upgradePanel = new UpgradePanel(mainFrame);
|
|
rightTabbedPane.addTab(getString("base.station"), baseStationPanel);
|
rightTabbedPane.addTab(getString("tag"), tagPanel);
|
rightTabbedPane.addTab(getString("anti.collision"), antiCollisionPanel);
|
rightTabbedPane.addTab(getString("upgrade"), upgradePanel);
|
|
panel.add(rightTabbedPane, BorderLayout.CENTER);
|
|
return panel;
|
}
|
|
private JPanel createBottomButtonPanel() {
|
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
// 使用ButtonUtils创建蓝色样式按钮
|
readParamsBtn = ButtonUtils.createBlueButton(getString("read.parameters"));
|
saveParamsBtn = ButtonUtils.createBlueButton(getString("save.parameters"));
|
restartDeviceBtn = ButtonUtils.createBlueButton(getString("restart.device"));
|
resetFactoryBtn = ButtonUtils.createBlueButton(getString("reset.factory"));
|
// 新增继电器参数按钮
|
readRelayParamsBtn = ButtonUtils.createBlueButton(getString("read.relay.parameters"));
|
saveRelayParamsBtn = ButtonUtils.createBlueButton(getString("save.relay.parameters"));
|
|
panel.add(readParamsBtn);
|
panel.add(saveParamsBtn);
|
panel.add(restartDeviceBtn);
|
panel.add(resetFactoryBtn);
|
// 添加新按钮
|
panel.add(readRelayParamsBtn);
|
panel.add(saveRelayParamsBtn);
|
|
return panel;
|
}
|
|
public void updateLanguage() {
|
// 更新控制面板文本
|
openBtn.setText(isOpen ? getString("close") : getString("open"));
|
readParamsBtn.setText(getString("read.parameters"));
|
saveParamsBtn.setText(getString("save.parameters"));
|
restartDeviceBtn.setText(getString("restart.device"));
|
resetFactoryBtn.setText(getString("reset.factory"));
|
// 更新新按钮文本
|
readRelayParamsBtn.setText(getString("read.relay.parameters"));
|
saveRelayParamsBtn.setText(getString("save.relay.parameters"));
|
|
// 更新协议类型标签
|
if (protocolTypeLabel != null) {
|
protocolTypeLabel.setText(getString("protocol.type"));
|
}
|
|
// 更新主机标签和端口标签
|
String protocol = (String) protocolCombo.getSelectedItem();
|
if (protocol != null) {
|
updateHostAndPortLabels(protocol);
|
}
|
|
// 更新协议选择
|
protocolCombo.removeAllItems();
|
protocolCombo.addItem("UDP");
|
protocolCombo.addItem("TCP Client");
|
protocolCombo.addItem("TCP Server");
|
|
// 根据当前协议更新主机地址输入框状态
|
if (protocol != null) {
|
updateHostAddressFieldState(protocol);
|
}
|
|
// 更新选项卡标题
|
// 更新选项卡标题
|
if (rightTabbedPane != null) {
|
rightTabbedPane.setTitleAt(0, getString("base.station"));
|
rightTabbedPane.setTitleAt(1, getString("tag"));
|
rightTabbedPane.setTitleAt(2, getString("anti.collision"));
|
rightTabbedPane.setTitleAt(3, getString("upgrade"));
|
}
|
|
// 更新各个功能面板的语言
|
baseParamPanel.updateLanguage();
|
baseStationPanel.updateLanguage();
|
tagPanel.updateLanguage();
|
antiCollisionPanel.updateLanguage();
|
upgradePanel.updateLanguage();
|
|
revalidate();
|
repaint();
|
}
|
|
public boolean isOpen() {
|
return isOpen;
|
}
|
|
private class ProtocolChangeListener implements ActionListener {
|
@Override
|
public void actionPerformed(ActionEvent e) {
|
String protocol = (String) protocolCombo.getSelectedItem();
|
if (protocol == null) {
|
return;
|
}
|
|
updateHostAndPortLabels(protocol);
|
updateHostAddressFieldState(protocol);
|
|
// 根据协议类型更新客户端下拉框的提示文本
|
switch (protocol) {
|
case "UDP":
|
clientCombo.setToolTipText(getString("data.sender.list"));
|
break;
|
case "TCP Server":
|
clientCombo.setToolTipText(getString("client.connection.list"));
|
break;
|
case "TCP Client":
|
clientCombo.setToolTipText(getString("not.connected"));
|
clientCombo.setEnabled(false);
|
break;
|
}
|
}
|
}
|
|
/**
|
* 根据协议类型更新主机和端口标签
|
*/
|
private void updateHostAndPortLabels(String protocol) {
|
switch (protocol) {
|
case "UDP":
|
hostLabel.setText(getString("local.host.address"));
|
portLabel.setText(getString("local.host.port"));
|
break;
|
case "TCP Client":
|
hostLabel.setText(getString("remote.host.address"));
|
portLabel.setText(getString("remote.host.port"));
|
break;
|
case "TCP Server":
|
hostLabel.setText(getString("local.host.address"));
|
portLabel.setText(getString("local.host.port"));
|
break;
|
}
|
}
|
|
/**
|
* 根据协议类型更新主机地址输入框状态
|
*/
|
private void updateHostAddressFieldState(String protocol) {
|
switch (protocol) {
|
case "UDP":
|
case "TCP Server":
|
populateAndMakeNonEditable();
|
break;
|
case "TCP Client":
|
clearAndMakeEditable();
|
break;
|
}
|
}
|
|
private String getString(String key) {
|
return mainFrame.getString(key);
|
}
|
|
/**
|
* 获取当前选择的主机地址
|
* @return 选择的主机地址
|
*/
|
public String getSelectedHostAddress() {
|
return (String) hostAddressCombo.getSelectedItem();
|
}
|
|
/**
|
* 设置选中的主机地址
|
* @param address 要设置的IP地址
|
*/
|
public void setSelectedHostAddress(String address) {
|
hostAddressCombo.setSelectedItem(address);
|
}
|
|
/**
|
* 手动刷新本地IP地址列表
|
*/
|
public void refreshLocalIPAddresses() {
|
populateLocalIPAddresses();
|
}
|
|
// 添加清理资源的方法
|
public void cleanup() {
|
if (currentNetwork != null) {
|
currentNetwork.stop();
|
currentNetwork = null;
|
}
|
}
|
|
/**
|
* 将UDP发送端地址添加到客户端下拉框
|
* @param senderAddress 发送端地址 (格式: IP:端口)
|
*/
|
private void addUdpSenderToCombo(String senderAddress) {
|
SwingUtilities.invokeLater(() -> {
|
// 检查是否已存在相同的地址
|
boolean exists = false;
|
for (int i = 0; i < clientCombo.getItemCount(); i++) {
|
if (senderAddress.equals(clientCombo.getItemAt(i))) {
|
exists = true;
|
break;
|
}
|
}
|
|
// 如果不存在,则添加到下拉框
|
if (!exists) {
|
clientCombo.addItem(senderAddress);
|
System.out.println("添加UDP发送端: " + senderAddress);
|
}
|
});
|
}
|
|
/**
|
* 清空UDP发送端列表
|
*/
|
public void clearUdpSenders() {
|
SwingUtilities.invokeLater(() -> {
|
clientCombo.removeAllItems();
|
});
|
}
|
|
/**
|
* 获取当前选中的面板索引 - 新增方法
|
* @return 当前选中的面板索引 (0-基站, 1-标签, 2-防撞, 3-升级)
|
*/
|
public int getCurrentSelectedPanelIndex() {
|
if (rightTabbedPane == null) {
|
return 0; // 默认基站面板
|
}
|
return rightTabbedPane.getSelectedIndex();
|
}
|
|
/**
|
* 获取当前选中的客户端
|
*/
|
public String getSelectedClient() {
|
return (String) clientCombo.getSelectedItem();
|
}
|
|
/**
|
* 发送UDP数据到指定地址
|
*/
|
public boolean sendUdpData(byte[] data, String ip, int port, String description) {
|
if (currentNetwork instanceof UdpListener) {
|
UdpListener udp = (UdpListener) currentNetwork;
|
boolean success = udp.sendDataTo(data, ip, port);
|
|
if (success && dataLogPanel != null) {
|
dataLogPanel.addLogData(data, description + " -> " + ip + ":" + port);
|
}
|
|
return success;
|
}
|
return false;
|
}
|
|
/**
|
* 发送TCP数据到指定客户端
|
*/
|
public boolean sendTcpDataToClient(String clientKey, byte[] data, String description) {
|
if (currentNetwork instanceof TcpServer) {
|
TcpServer tcpServer = (TcpServer) currentNetwork;
|
try {
|
boolean success = tcpServer.sendDataToClient(clientKey, data);
|
|
if (success && dataLogPanel != null) {
|
dataLogPanel.addLogData(data, description + " -> " + clientKey);
|
}
|
|
return success;
|
} catch (Exception e) {
|
JOptionPane.showMessageDialog(this, getString("send.data.failed") + ": " + e.getMessage(), getString("error"), JOptionPane.ERROR_MESSAGE);
|
return false;
|
}
|
}
|
return false;
|
}
|
|
/**
|
* 获取当前网络实例
|
*/
|
public NetworkBase getCurrentNetwork() {
|
return currentNetwork;
|
}
|
|
|
}
|