新增设备管理器,修改和设备连接逻辑
This commit is contained in:
parent
2e4d09a03e
commit
4c75353129
485
src/DeviceConnectManagement.cpp
Normal file
485
src/DeviceConnectManagement.cpp
Normal file
|
|
@ -0,0 +1,485 @@
|
||||||
|
#include "DeviceConnectManagement.h"
|
||||||
|
#include "ui_DeviceConnectManagement.h"
|
||||||
|
#include "MeasureClient.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QShowEvent>
|
||||||
|
|
||||||
|
DeviceConnectManagement::DeviceConnectManagement(MeasureClient* client, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::DeviceConnectManagement)
|
||||||
|
, m_measureClient(client)
|
||||||
|
, m_isMeasuring(false)
|
||||||
|
, m_isConnected(false)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
if (m_measureClient) {
|
||||||
|
//设备列表
|
||||||
|
connect(m_measureClient, &MeasureClient::getDeviceListResult, this,
|
||||||
|
[this](bool success, const QString& msg, const QStringList& devices) {
|
||||||
|
Q_UNUSED(msg);
|
||||||
|
updateDeviceList(devices, success);
|
||||||
|
emit deviceListUpdated(devices);
|
||||||
|
if (success) {
|
||||||
|
emit statusMessage(QStringLiteral(u"扫描完成,找到 %1 个设备").arg(devices.size()));
|
||||||
|
} else {
|
||||||
|
emit statusMessage(QStringLiteral(u"扫描设备失败"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//开始测量
|
||||||
|
connect(m_measureClient, &MeasureClient::startMeasureResult, this,
|
||||||
|
[this](bool success, const QString& msg) {
|
||||||
|
m_isMeasuring = success;
|
||||||
|
emit measureStarted(success, msg);
|
||||||
|
emit statusMessage(success ? QStringLiteral(u"启动测量成功") :
|
||||||
|
QStringLiteral(u"启动测量失败: %1").arg(msg));
|
||||||
|
});
|
||||||
|
//停止测量
|
||||||
|
connect(m_measureClient, &MeasureClient::stopMeasureResult, this,
|
||||||
|
[this](bool success, const QString& msg) {
|
||||||
|
m_isMeasuring = !success; // 成功则停止,失败则保持测量状态
|
||||||
|
emit measureStopped(success, msg);
|
||||||
|
emit statusMessage(success ? QStringLiteral(u"停止测量成功") :
|
||||||
|
QStringLiteral(u"停止测量失败: %1").arg(msg));
|
||||||
|
});
|
||||||
|
//运行状态信息
|
||||||
|
connect(m_measureClient, &MeasureClient::runningInfo, this,
|
||||||
|
[this](const QString& info) {
|
||||||
|
if (info.contains("连接到服务器")) {
|
||||||
|
m_isConnected = true;
|
||||||
|
emit serverConnected(getServerIp(), getServerPort().toUShort());
|
||||||
|
} else if (info.contains("断开服务器连接")) {
|
||||||
|
m_isConnected = false;
|
||||||
|
}
|
||||||
|
emit statusMessage(info);
|
||||||
|
});
|
||||||
|
//错误信息
|
||||||
|
connect(m_measureClient, &MeasureClient::errorOccurred, this,
|
||||||
|
[this](const QString& error) {
|
||||||
|
emit statusMessage(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceConnectManagement::~DeviceConnectManagement()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DeviceConnectManagement::connectToServer()
|
||||||
|
{
|
||||||
|
on_pBtn_connectService_clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::scanDevices()
|
||||||
|
{
|
||||||
|
on_pBtn_scanDevice_clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceConnectManagement::startMeasure()
|
||||||
|
{
|
||||||
|
if (!m_isConnected) {
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请先连接到服务器"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateDeviceSelected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap deviceConfig;
|
||||||
|
if (!loadDeviceConfig(deviceConfig)) {
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"提示"),
|
||||||
|
QStringLiteral(u"设备参数配置文件不存在或无效,请先配置设备参数"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
emit emitStartMeasure();//开始测量信号
|
||||||
|
|
||||||
|
QString deviceId = getCurrentDeviceId();
|
||||||
|
if (m_measureClient) {
|
||||||
|
m_measureClient->startMeasure(deviceId, deviceConfig);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::stopMeasure()
|
||||||
|
{
|
||||||
|
QString deviceId = getCurrentDeviceId();
|
||||||
|
if (deviceId.isEmpty() && !m_deviceList.isEmpty()) {
|
||||||
|
deviceId = m_deviceList.first();
|
||||||
|
}
|
||||||
|
if (m_measureClient && !deviceId.isEmpty()) {
|
||||||
|
m_measureClient->stopMeasure(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceConnectManagement::loadDeviceConfig(QVariantMap& outConfig)
|
||||||
|
{
|
||||||
|
QString configPath = getDeviceConfigFilePath();
|
||||||
|
QFile file(configPath);
|
||||||
|
if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray jsonData = file.readAll();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonData);
|
||||||
|
if (doc.isNull() || !doc.isObject()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outConfig = doc.object().toVariantMap();
|
||||||
|
return outConfig.contains(QStringLiteral(u"ChannelConfig"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DeviceConnectManagement::getServerIp() const
|
||||||
|
{
|
||||||
|
return ui->lineEdit_serviceIp->text().trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DeviceConnectManagement::getServerPort() const
|
||||||
|
{
|
||||||
|
return ui->lineEdit_port->text().trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DeviceConnectManagement::getCurrentDeviceId() const
|
||||||
|
{
|
||||||
|
return ui->comboBox->currentText().trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList DeviceConnectManagement::getDeviceList() const
|
||||||
|
{
|
||||||
|
return m_deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceConnectManagement::isMeasuring() const
|
||||||
|
{
|
||||||
|
return m_isMeasuring;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::updateDeviceList(const QStringList& devices, bool success)
|
||||||
|
{
|
||||||
|
if (success) {
|
||||||
|
m_deviceList = devices;
|
||||||
|
ui->comboBox->clear();
|
||||||
|
ui->comboBox->addItems(devices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DeviceConnectManagement::on_pBtn_connectService_clicked()
|
||||||
|
{
|
||||||
|
QString ip = getServerIp();
|
||||||
|
if (ip.isEmpty()) {
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请输入服务器IP地址"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 port = getServerPort().toUShort();
|
||||||
|
if (m_measureClient) {
|
||||||
|
m_measureClient->disconnectFromServer();
|
||||||
|
m_measureClient->connectToServer(ip, port);
|
||||||
|
m_isConnected = true;
|
||||||
|
ui->pBtn_scanDevice->setEnabled(true);
|
||||||
|
ui->pBtn_startMeasure->setEnabled(true);
|
||||||
|
ui->pBtn_stopMeasure->setEnabled(true);
|
||||||
|
emit serverConnected(ip, port);
|
||||||
|
emit statusMessage(QStringLiteral(u"正在连接到测量服务器: %1:%2 ...").arg(ip).arg(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::on_pBtn_scanDevice_clicked()
|
||||||
|
{
|
||||||
|
if (!m_isConnected) {
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请先连接到服务器"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_measureClient) {
|
||||||
|
m_measureClient->getDeviceList();
|
||||||
|
emit statusMessage(QStringLiteral(u"正在扫描测量设备..."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::on_pBtn_startMeasure_clicked()
|
||||||
|
{
|
||||||
|
if (!m_isConnected) {
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请先连接到服务器"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startMeasure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::on_pBtn_stopMeasure_clicked()
|
||||||
|
{
|
||||||
|
stopMeasure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::on_pBtn_save_clicked()
|
||||||
|
{
|
||||||
|
saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::on_pBtn_exit_clicked()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DeviceConnectManagement::validateDeviceSelected() const
|
||||||
|
{
|
||||||
|
QString deviceId = getCurrentDeviceId();
|
||||||
|
if (deviceId.isEmpty()) {
|
||||||
|
QMessageBox::warning(const_cast<DeviceConnectManagement*>(this),
|
||||||
|
QStringLiteral(u"提示"),
|
||||||
|
QStringLiteral(u"请选择测量设备"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::setDefaultServerIp()
|
||||||
|
{
|
||||||
|
ui->lineEdit_serviceIp->setText(QStringLiteral(u"127.0.0.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DeviceConnectManagement::loadConfig()
|
||||||
|
{
|
||||||
|
QString configPath = getConfigFilePath();
|
||||||
|
QFile file(configPath);
|
||||||
|
|
||||||
|
if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
setDefaultServerIp();
|
||||||
|
ui->lineEdit_port->setText(QStringLiteral(u"9999"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray jsonData = file.readAll();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(jsonData);
|
||||||
|
if (doc.isNull() || !doc.isObject()) {
|
||||||
|
setDefaultServerIp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject obj = doc.object();
|
||||||
|
|
||||||
|
if (obj.contains(QStringLiteral(u"server_ip"))) {
|
||||||
|
ui->lineEdit_serviceIp->setText(obj[QStringLiteral(u"server_ip")].toString());
|
||||||
|
} else {
|
||||||
|
setDefaultServerIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.contains(QStringLiteral(u"port"))) {
|
||||||
|
ui->lineEdit_port->setText(obj[QStringLiteral(u"port")].toString());
|
||||||
|
} else {
|
||||||
|
ui->lineEdit_port->setText(QStringLiteral(u"9999"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.contains(QStringLiteral(u"device_id"))) {
|
||||||
|
QString deviceId = obj[QStringLiteral(u"device_id")].toString();
|
||||||
|
if (!deviceId.isEmpty()) {
|
||||||
|
int idx = ui->comboBox->findText(deviceId);
|
||||||
|
if (idx >= 0) {
|
||||||
|
ui->comboBox->setCurrentIndex(idx);
|
||||||
|
} else {
|
||||||
|
ui->comboBox->addItem(deviceId);
|
||||||
|
ui->comboBox->setCurrentText(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceConnectManagement::saveConfig()
|
||||||
|
{
|
||||||
|
QString configPath = getConfigFilePath();
|
||||||
|
QJsonObject obj;
|
||||||
|
obj[QStringLiteral(u"server_ip")] = getServerIp();
|
||||||
|
obj[QStringLiteral(u"port")] = getServerPort();
|
||||||
|
obj[QStringLiteral(u"device_id")] = getCurrentDeviceId();
|
||||||
|
|
||||||
|
QJsonDocument doc(obj);
|
||||||
|
QFile file(configPath);
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
QMessageBox::critical(this, QStringLiteral(u"错误"),
|
||||||
|
QStringLiteral(u"保存配置失败:无法写入文件 %1\n错误:%2")
|
||||||
|
.arg(configPath).arg(file.errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(doc.toJson(QJsonDocument::Indented));
|
||||||
|
file.close();
|
||||||
|
QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"配置保存成功"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DeviceConnectManagement::getConfigFilePath() const
|
||||||
|
{
|
||||||
|
QString appDir = ProjectList::Instance()->GetCurrentProjectModel()->GetProjectDir();
|
||||||
|
// QString appDir = QApplication::applicationDirPath();
|
||||||
|
return QDir(appDir).filePath(QStringLiteral(u"设备连接配置.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DeviceConnectManagement::getDeviceConfigFilePath() const
|
||||||
|
{
|
||||||
|
QString appDir = ProjectList::Instance()->GetCurrentProjectModel()->GetProjectDir();
|
||||||
|
// QString appDir = QApplication::applicationDirPath();
|
||||||
|
return QDir(appDir).filePath(QStringLiteral(u"设备参数配置.mscfg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// QString DeviceConnectManagement::getDeviceId() const
|
||||||
|
// {
|
||||||
|
// return ui->comboBox->currentText().trimmed();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::on_pBtn_connectService_clicked()
|
||||||
|
// {
|
||||||
|
// // 连接服务器
|
||||||
|
// QString ip = getServerIp();
|
||||||
|
// if (ip.isEmpty()) {
|
||||||
|
// QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请输入服务器IP地址"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// emit connectServer(ip,ui->lineEdit_port->text().trimmed());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::on_pBtn_scanDevice_clicked()
|
||||||
|
// {
|
||||||
|
// // 扫描设备
|
||||||
|
// emit scanDevices();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::on_pBtn_startMeasure_clicked()
|
||||||
|
// {
|
||||||
|
// // 开始测量
|
||||||
|
// QString deviceId = getDeviceId();
|
||||||
|
// if (deviceId.isEmpty()) {
|
||||||
|
// QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请选择测量设备"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// emit startMeasure(deviceId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::on_pBtn_stopMeasure_clicked()
|
||||||
|
// {
|
||||||
|
// // 停止测量
|
||||||
|
// QString deviceId = getDeviceId();
|
||||||
|
// if (deviceId.isEmpty()) {
|
||||||
|
// QMessageBox::warning(this, QStringLiteral(u"提示"), QStringLiteral(u"请选择测量设备"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// emit stopMeasure(deviceId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::on_pBtn_save_clicked()
|
||||||
|
// {
|
||||||
|
// saveConfig();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::on_pBtn_exit_clicked()
|
||||||
|
// {
|
||||||
|
// this->close();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::onDeviceListReady(const QStringList &devices)
|
||||||
|
// {
|
||||||
|
// ui->comboBox->clear();
|
||||||
|
// ui->comboBox->addItems(devices);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::loadConfig()
|
||||||
|
// {
|
||||||
|
// // 读取JSON配置并回显到界面
|
||||||
|
// QString configPath = getConfigFilePath();
|
||||||
|
// QFile file(configPath);
|
||||||
|
// if (!file.exists()) {
|
||||||
|
// // 配置文件不存在,使用默认值
|
||||||
|
// ui->lineEdit_serviceIp->setText(QStringLiteral(u"127.0.0.1"));
|
||||||
|
// ui->lineEdit_port->setText(QStringLiteral(u"9999"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
// ui->lineEdit_serviceIp->setText(QStringLiteral(u"127.0.0.1"));
|
||||||
|
// ui->lineEdit_port->setText(QStringLiteral(u"9999"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// QByteArray jsonData = file.readAll();
|
||||||
|
// file.close();
|
||||||
|
// QJsonDocument doc = QJsonDocument::fromJson(jsonData);
|
||||||
|
// if (doc.isNull() || !doc.isObject()) {
|
||||||
|
// ui->lineEdit_serviceIp->setText(QStringLiteral(u"127.0.0.1"));
|
||||||
|
// ui->lineEdit_port->setText(QStringLiteral(u"9999"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// QJsonObject obj = doc.object();
|
||||||
|
// // 回显服务器IP
|
||||||
|
// if (obj.contains(QStringLiteral(u"server_ip"))) {
|
||||||
|
// ui->lineEdit_serviceIp->setText(obj[QStringLiteral(u"server_ip")].toString());
|
||||||
|
// } else {
|
||||||
|
// ui->lineEdit_serviceIp->setText(QStringLiteral(u"127.0.0.1"));
|
||||||
|
// }
|
||||||
|
// // 回显服务器port
|
||||||
|
// if (obj.contains(QStringLiteral(u"port"))) {
|
||||||
|
// ui->lineEdit_port->setText(obj[QStringLiteral(u"port")].toString());
|
||||||
|
// } else {
|
||||||
|
// ui->lineEdit_port->setText(QStringLiteral(u"9999"));
|
||||||
|
// }
|
||||||
|
// // 回显上次选择的设备ID
|
||||||
|
// if (obj.contains(QStringLiteral(u"device_id"))) {
|
||||||
|
// QString deviceId = obj[QStringLiteral(u"device_id")].toString();
|
||||||
|
// if (!deviceId.isEmpty()) {
|
||||||
|
// int idx = ui->comboBox->findText(deviceId);
|
||||||
|
// if (idx >= 0) {
|
||||||
|
// ui->comboBox->setCurrentIndex(idx);
|
||||||
|
// } else {
|
||||||
|
// ui->comboBox->addItem(deviceId);
|
||||||
|
// ui->comboBox->setCurrentText(deviceId);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void DeviceConnectManagement::saveConfig()
|
||||||
|
// {
|
||||||
|
|
||||||
|
// // 将界面配置保存为JSON
|
||||||
|
// QString configPath = getConfigFilePath();
|
||||||
|
// QJsonObject obj;
|
||||||
|
// obj[QStringLiteral(u"server_ip")] = getServerIp();
|
||||||
|
// obj[QStringLiteral(u"port")] = ui->lineEdit_port->text().trimmed();
|
||||||
|
// obj[QStringLiteral(u"device_id")] = getDeviceId();
|
||||||
|
// QJsonDocument doc(obj);
|
||||||
|
// QFile file(configPath);
|
||||||
|
// if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
||||||
|
// QMessageBox::critical(this, QStringLiteral(u"错误"),
|
||||||
|
// QStringLiteral(u"保存配置失败:无法写入文件 %1\n错误:%2")
|
||||||
|
// .arg(configPath).arg(file.errorString()));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// file.write(doc.toJson(QJsonDocument::Indented));
|
||||||
|
// file.close();
|
||||||
|
// QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"配置保存成功"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// QString DeviceConnectManagement::getConfigFilePath() const
|
||||||
|
// {
|
||||||
|
// QString appDir = ProjectList::Instance()->GetCurrentProjectModel()->GetProjectDir();
|
||||||
|
// // QString appDir = QApplication::applicationDirPath();
|
||||||
|
// return QDir(appDir).filePath(QStringLiteral(u"服务器连接配置.json"));
|
||||||
|
// }
|
||||||
|
|
||||||
72
src/DeviceConnectManagement.h
Normal file
72
src/DeviceConnectManagement.h
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
#ifndef DEVICECONNECTMANAGEMENT_H
|
||||||
|
#define DEVICECONNECTMANAGEMENT_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QLabel>
|
||||||
|
#include "MeasureAnalysisProjectModel.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class DeviceConnectManagement;
|
||||||
|
}
|
||||||
|
class MeasureClient;
|
||||||
|
class DeviceConnectManagement : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DeviceConnectManagement(MeasureClient* client, QWidget *parent = nullptr);
|
||||||
|
~DeviceConnectManagement();
|
||||||
|
// 连接服务器
|
||||||
|
void connectToServer();
|
||||||
|
// 扫描设备
|
||||||
|
void scanDevices();
|
||||||
|
// 开始测量(供主窗口菜单调用)
|
||||||
|
bool startMeasure();
|
||||||
|
// 停止测量(供主窗口菜单调用)
|
||||||
|
void stopMeasure();
|
||||||
|
// 加载设备参数配置
|
||||||
|
bool loadDeviceConfig(QVariantMap& outConfig);
|
||||||
|
//加载服务器配置
|
||||||
|
void loadConfig();
|
||||||
|
|
||||||
|
// 获取配置信息
|
||||||
|
QString getServerIp() const;
|
||||||
|
QString getServerPort() const;
|
||||||
|
QString getCurrentDeviceId() const;
|
||||||
|
QStringList getDeviceList() const;
|
||||||
|
bool isMeasuring() const;
|
||||||
|
|
||||||
|
// 设备列表更新(供MeasureClient回调调用)
|
||||||
|
void updateDeviceList(const QStringList& devices, bool success = true);
|
||||||
|
signals:
|
||||||
|
//点击开始测量时
|
||||||
|
void emitStartMeasure();
|
||||||
|
// 测量状态变化信号
|
||||||
|
void measureStarted(bool success, const QString& message);
|
||||||
|
void measureStopped(bool success, const QString& message);
|
||||||
|
void serverConnected(const QString& ip, quint16 port);
|
||||||
|
void deviceListUpdated(const QStringList& devices);
|
||||||
|
void statusMessage(const QString& msg);
|
||||||
|
private slots:
|
||||||
|
void on_pBtn_connectService_clicked();
|
||||||
|
void on_pBtn_scanDevice_clicked();
|
||||||
|
void on_pBtn_startMeasure_clicked();
|
||||||
|
void on_pBtn_stopMeasure_clicked();
|
||||||
|
void on_pBtn_save_clicked();
|
||||||
|
void on_pBtn_exit_clicked();
|
||||||
|
private:
|
||||||
|
void saveConfig();
|
||||||
|
QString getConfigFilePath() const;
|
||||||
|
QString getDeviceConfigFilePath() const;
|
||||||
|
bool validateDeviceSelected() const;
|
||||||
|
void setDefaultServerIp();
|
||||||
|
private:
|
||||||
|
Ui::DeviceConnectManagement *ui;
|
||||||
|
MeasureClient* m_measureClient;
|
||||||
|
QStringList m_deviceList;
|
||||||
|
bool m_isMeasuring;
|
||||||
|
bool m_isConnected; // 服务器连接状态
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEVICECONNECTMANAGEMENT_H
|
||||||
112
src/DeviceConnectManagement.ui
Normal file
112
src/DeviceConnectManagement.ui
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DeviceConnectManagement</class>
|
||||||
|
<widget class="QDialog" name="DeviceConnectManagement">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>418</width>
|
||||||
|
<height>189</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="2" column="7">
|
||||||
|
<widget class="QPushButton" name="pBtn_scanDevice">
|
||||||
|
<property name="text">
|
||||||
|
<string>扫描设备</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>设备ID:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="6">
|
||||||
|
<widget class="QPushButton" name="pBtn_connectService">
|
||||||
|
<property name="text">
|
||||||
|
<string>连接服务器</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2" colspan="6">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_serviceIp">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>端口号:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2" colspan="6">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_port"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>服务器ip:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="7">
|
||||||
|
<widget class="QPushButton" name="pBtn_exit">
|
||||||
|
<property name="text">
|
||||||
|
<string>退出</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="6">
|
||||||
|
<widget class="QPushButton" name="pBtn_save">
|
||||||
|
<property name="text">
|
||||||
|
<string>保存</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="6">
|
||||||
|
<widget class="QPushButton" name="pBtn_startMeasure">
|
||||||
|
<property name="text">
|
||||||
|
<string>开始测量</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="7">
|
||||||
|
<widget class="QPushButton" name="pBtn_stopMeasure">
|
||||||
|
<property name="text">
|
||||||
|
<string>停止测量</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2" colspan="6">
|
||||||
|
<widget class="QComboBox" name="comboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>0x01</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -103,23 +103,21 @@ MainWindow::MainWindow(QWidget* parent)
|
||||||
_status_bar = ui->statusbar;
|
_status_bar = ui->statusbar;
|
||||||
_gvfToCsv = new GvfToCsv;
|
_gvfToCsv = new GvfToCsv;
|
||||||
_measure_client = new MeasureClient;
|
_measure_client = new MeasureClient;
|
||||||
|
m_deviceMgr = new DeviceConnectManagement(_measure_client, this);
|
||||||
|
|
||||||
m_AddressCountTimer = new QTimer(this);
|
m_AddressCountTimer = new QTimer(this);
|
||||||
m_AddressCountTimer->setInterval(10000);//10秒刷新一次
|
m_AddressCountTimer->setInterval(10000);//10秒刷新一次
|
||||||
m_EnergyCountTimer = new QTimer(this);
|
m_EnergyCountTimer = new QTimer(this);
|
||||||
m_EnergyCountTimer->setInterval(10000);//10秒刷新一次
|
m_EnergyCountTimer->setInterval(10000);//10秒刷新一次
|
||||||
connect(m_AddressCountTimer, &QTimer::timeout, this, &MainWindow::on_AddressCountTimer);
|
connect(m_AddressCountTimer, &QTimer::timeout, this, &MainWindow::on_AddressCountTimer);
|
||||||
connect(m_EnergyCountTimer, &QTimer::timeout, this, &MainWindow::on_EnergyCountTimer);
|
connect(m_EnergyCountTimer, &QTimer::timeout, this, &MainWindow::on_EnergyCountTimer);
|
||||||
|
|
||||||
connect(_measure_client, &MeasureClient::getDeviceListResult, this, &MainWindow::onGetDeviceListResult);
|
|
||||||
connect(_measure_client, &MeasureClient::startMeasureResult, this, &MainWindow::onStartMeasureResult);
|
|
||||||
connect(_measure_client, &MeasureClient::stopMeasureResult, this, &MainWindow::onStopMeasureResult);
|
|
||||||
connect(_measure_client, &MeasureClient::setMeasureConfigParamsResult, this, &MainWindow::onSetMeasureConfigParamsResult);
|
|
||||||
connect(_measure_client, &MeasureClient::clearDataResult, this, &MainWindow::onClearDataResult);
|
|
||||||
connect(_measure_client, &MeasureClient::runningInfo, this, &MainWindow::onRunningInfo);
|
|
||||||
connect(_measure_client, &MeasureClient::errorOccurred, this, &MainWindow::onErrorOccurred);
|
|
||||||
connect(_measure_client, &MeasureClient::gvfData, this, &MainWindow::onGvfData);
|
connect(_measure_client, &MeasureClient::gvfData, this, &MainWindow::onGvfData);
|
||||||
_measure_client->connectToServer();
|
|
||||||
|
|
||||||
|
//接受设备管理传过来的信号
|
||||||
|
connect(m_deviceMgr,&DeviceConnectManagement::emitStartMeasure,this,&MainWindow::onUpdateParticleDataTreeStatus);
|
||||||
|
connect(m_deviceMgr, &DeviceConnectManagement::measureStarted, this, &MainWindow::onMeasureStarted);
|
||||||
|
connect(m_deviceMgr, &DeviceConnectManagement::measureStopped, this, &MainWindow::onMeasureStopped);
|
||||||
|
connect(m_deviceMgr, &DeviceConnectManagement::statusMessage, this, &MainWindow::onDeviceStatusMessage);
|
||||||
initMainWindow();
|
initMainWindow();
|
||||||
initAction();
|
initAction();
|
||||||
initStatusBar();
|
initStatusBar();
|
||||||
|
|
@ -130,9 +128,11 @@ MainWindow::MainWindow(QWidget* parent)
|
||||||
_gvfWorker->setGvfParser(_gvfToCsv);
|
_gvfWorker->setGvfParser(_gvfToCsv);
|
||||||
_gvfWorker->moveToThread(_gvfProcessThread);
|
_gvfWorker->moveToThread(_gvfProcessThread);
|
||||||
|
|
||||||
|
ui->action_stop_measure->setEnabled(false);
|
||||||
|
|
||||||
// 连接UI更新信号
|
// 连接UI更新信号
|
||||||
connect(_gvfWorker, &DataProcessWorkPool::RealtimeGvfDataWorker::particleDataWritten,
|
connect(_gvfWorker, &DataProcessWorkPool::RealtimeGvfDataWorker::particleDataWritten,
|
||||||
this, &MainWindow::updataTable);
|
this, &MainWindow::onParticleDatarefresh);
|
||||||
connect(_gvfWorker, &DataProcessWorkPool::RealtimeGvfDataWorker::addressCountViewNeedRefresh,
|
connect(_gvfWorker, &DataProcessWorkPool::RealtimeGvfDataWorker::addressCountViewNeedRefresh,
|
||||||
this, &MainWindow::onAddressCountViewNeedRefresh);
|
this, &MainWindow::onAddressCountViewNeedRefresh);
|
||||||
connect(_gvfWorker, &DataProcessWorkPool::RealtimeGvfDataWorker::energyCountViewNeedRefresh,
|
connect(_gvfWorker, &DataProcessWorkPool::RealtimeGvfDataWorker::energyCountViewNeedRefresh,
|
||||||
|
|
@ -156,6 +156,41 @@ MainWindow::~MainWindow()
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onMeasureStarted(bool success, const QString& message)
|
||||||
|
{
|
||||||
|
// Q_UNUSED(message);
|
||||||
|
// if (success) {
|
||||||
|
// ui->action_start_measure->setEnabled(false);
|
||||||
|
// ui->action_stop_measure->setEnabled(true);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onMeasureStopped(bool success, const QString& message)
|
||||||
|
{
|
||||||
|
Q_UNUSED(message);
|
||||||
|
if (success) {
|
||||||
|
// ui->action_start_measure->setEnabled(true);
|
||||||
|
// ui->action_stop_measure->setEnabled(false);
|
||||||
|
m_AddressCountTimer->stop();
|
||||||
|
m_EnergyCountTimer->stop();
|
||||||
|
// // 更新树节点状态:把"测量中"改回"已停止"
|
||||||
|
// if (!nodeMap.isEmpty()) {
|
||||||
|
// MeasureAnalysisProjectModel* models = ProjectList::Instance()->GetCurrentProjectModel();
|
||||||
|
// if (models) {
|
||||||
|
// QStandardItem* nodeItem = nodeMap[models->GetProjectName()];
|
||||||
|
// if (nodeItem) {
|
||||||
|
// ProjectList::Instance()->SetNodeStatus(nodeItem, "已停止", false);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onDeviceStatusMessage(const QString& msg)
|
||||||
|
{
|
||||||
|
ShowStatusBarMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::initMainWindow()
|
void MainWindow::initMainWindow()
|
||||||
{
|
{
|
||||||
ads::CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
|
ads::CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
|
||||||
|
|
@ -374,11 +409,11 @@ void MainWindow::initStatusBar()
|
||||||
|
|
||||||
void MainWindow::applyStyleSheet()
|
void MainWindow::applyStyleSheet()
|
||||||
{
|
{
|
||||||
// #ifdef ENABLE_DEBUG
|
// #ifdef ENABLE_DEBUG
|
||||||
// QString style_file_path = "D:/Workspace/EnergySpectrumAnalyerProject/EnergySpectrumAnalyer/style/stylesheet/";
|
// QString style_file_path = "D:/Workspace/EnergySpectrumAnalyerProject/EnergySpectrumAnalyer/style/stylesheet/";
|
||||||
// #else
|
// #else
|
||||||
QString style_file_path = ":/stylesheet/";
|
QString style_file_path = ":/stylesheet/";
|
||||||
// #endif
|
// #endif
|
||||||
QFile file_stylesheet_default(style_file_path + "default.qss");
|
QFile file_stylesheet_default(style_file_path + "default.qss");
|
||||||
if (file_stylesheet_default.open(QFile::ReadOnly)) {
|
if (file_stylesheet_default.open(QFile::ReadOnly)) {
|
||||||
const QString& str_stylesheet_default = file_stylesheet_default.readAll();
|
const QString& str_stylesheet_default = file_stylesheet_default.readAll();
|
||||||
|
|
@ -493,14 +528,12 @@ void MainWindow::resizeEvent(QResizeEvent *event)
|
||||||
|
|
||||||
void MainWindow::on_action_start_measure_triggered()
|
void MainWindow::on_action_start_measure_triggered()
|
||||||
{
|
{
|
||||||
LOG_INFO(QStringLiteral(u"查找测量设备... ..."));
|
m_deviceMgr->startMeasure();
|
||||||
_measure_client->getDeviceList();
|
}
|
||||||
LOG_INFO(QStringLiteral(u"开始测量... ..."));
|
|
||||||
QString device_guid;
|
//更新粒子数据树形节点状态
|
||||||
if(deviceList.size()>0)
|
void MainWindow::onUpdateParticleDataTreeStatus()
|
||||||
{
|
{
|
||||||
device_guid = deviceList.at(0);
|
|
||||||
}
|
|
||||||
MeasureAnalysisProjectModel* models = ProjectList::Instance()->GetCurrentProjectModel();
|
MeasureAnalysisProjectModel* models = ProjectList::Instance()->GetCurrentProjectModel();
|
||||||
QMap<QString, QMap<QString, QStandardItem *> > project_node_items = ProjectList::Instance()->getProjectNodeItems();
|
QMap<QString, QMap<QString, QStandardItem *> > project_node_items = ProjectList::Instance()->getProjectNodeItems();
|
||||||
nodeMap = project_node_items[models->GetProjectName()];
|
nodeMap = project_node_items[models->GetProjectName()];
|
||||||
|
|
@ -515,139 +548,13 @@ void MainWindow::on_action_start_measure_triggered()
|
||||||
QVariant analys_type = QVariant::fromValue(AnalysisType::ParticleData);
|
QVariant analys_type = QVariant::fromValue(AnalysisType::ParticleData);
|
||||||
QString item_name = QStringLiteral(u"测量粒子数据");
|
QString item_name = QStringLiteral(u"测量粒子数据");
|
||||||
QStandardItem * particleData = nodeMap[item_name];
|
QStandardItem * particleData = nodeMap[item_name];
|
||||||
ProjectList::Instance()->SetNodeStatus(particleData,status,true);
|
if (particleData) {
|
||||||
//创建通道道址计数文件夹
|
|
||||||
const QString& all_channel_particle_data_filename = models->GetAllChannelParticleDataFilename();
|
|
||||||
const QString& all_ch_count_dir = models->GetProjectDir();
|
|
||||||
|
|
||||||
if (!all_channel_particle_data_filename.isEmpty()) {
|
|
||||||
const QString& every_ch_count_dir = QDir(models->GetProjectDir()).filePath(QStringLiteral(u"通道道址计数"));
|
|
||||||
QDir every_ch_count_output_dir(every_ch_count_dir);
|
|
||||||
every_ch_count_output_dir.mkpath(every_ch_count_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString projectName;
|
|
||||||
QString deviceCfg;
|
|
||||||
if(models)
|
|
||||||
{
|
|
||||||
projectName = models->GetProjectName();
|
|
||||||
deviceCfg = models->GetMeasureDeviceParamsCfgFilename();
|
|
||||||
if(deviceCfg == "")
|
|
||||||
{
|
|
||||||
QMessageBox::information(this,"提示","设备参数配置未配置","确认","取消");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile json_file(deviceCfg);
|
|
||||||
if (!json_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
LOG_INFO(QStringLiteral(u"加载设备参数配置失败:%1").arg(deviceCfg));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QByteArray json_data = json_file.readAll();
|
|
||||||
json_file.close();
|
|
||||||
QJsonDocument json_doc = QJsonDocument::fromJson(json_data);
|
|
||||||
if (json_doc.isNull()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!json_doc.isObject())
|
|
||||||
return;
|
|
||||||
QVariantMap device_config_info = json_doc.object().toVariantMap();
|
|
||||||
if (!device_config_info.contains(QStringLiteral(u"ChannelConfig")))
|
|
||||||
return;
|
|
||||||
QVariantList channel_config_list = device_config_info[QStringLiteral(u"ChannelConfig")].toList();
|
|
||||||
if (channel_config_list.isEmpty()) {
|
|
||||||
LOG_INFO(QStringLiteral(u"测量设备通道配置参数为空."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_measure_client->startMeasure(device_guid, device_config_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onStartMeasureResult(bool success, const QString &info)
|
|
||||||
{
|
|
||||||
if(success)
|
|
||||||
{
|
|
||||||
LOG_INFO(QStringLiteral(u"启动测量成功"));
|
|
||||||
LOG_INFO(QStringLiteral(u"测量数据GVF文件: %1").arg(info));
|
|
||||||
MeasureAnalysisProjectModel* models = ProjectList::Instance()->GetCurrentProjectModel();
|
|
||||||
QMap<QString, QMap<QString, QStandardItem *> > project_node_items = ProjectList::Instance()->getProjectNodeItems();
|
|
||||||
QMap<QString, QStandardItem *> node = project_node_items[models->GetProjectName()];
|
|
||||||
QString dir = ProjectList::Instance()->GetCurrentProjectModel()->GetProjectDir();
|
|
||||||
QString csvPath = QStringLiteral(u"%1/%2").arg(dir).arg("粒子数据.csv");
|
|
||||||
models->SetAllChannelParticleDataFilename(csvPath);
|
|
||||||
bool status_ok = !models->GetAllChannelParticleDataFilename().isEmpty();
|
|
||||||
QString status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
|
|
||||||
QVariant analys_type = QVariant::fromValue(AnalysisType::ParticleData);
|
|
||||||
QString item_name = QStringLiteral(u"测量粒子数据");
|
|
||||||
QStandardItem * particleData = node[item_name];
|
|
||||||
ProjectList::Instance()->SetNodeStatus(particleData,status,true);
|
ProjectList::Instance()->SetNodeStatus(particleData,status,true);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
LOG_INFO(QStringLiteral(u"启动测量失败: %1").arg(info));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onStopMeasureResult(bool success, const QString &message)
|
|
||||||
{
|
|
||||||
if(success){
|
|
||||||
LOG_INFO(QStringLiteral(u"停止测量成功"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LOG_INFO(QStringLiteral(u"停止测量失败: %1").arg(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onSetMeasureConfigParamsResult(bool success, const QString &message)
|
|
||||||
{
|
|
||||||
if(success){
|
|
||||||
LOG_INFO(QStringLiteral(u"设置测量参数成功"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LOG_INFO(QStringLiteral(u"设置测量参数失败: %1").arg(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onClearDataResult(bool success, const QString &message)
|
|
||||||
{
|
|
||||||
if(success){
|
|
||||||
LOG_INFO(QStringLiteral(u"清除测量数据成功"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LOG_INFO(QStringLiteral(u"清除测量数据失败: %1").arg(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onGetDeviceListResult(bool success, const QString &message, const QStringList &devices)
|
|
||||||
{
|
|
||||||
if (success) {
|
|
||||||
deviceList = devices;
|
|
||||||
}
|
|
||||||
//测试
|
|
||||||
deviceList.append("0x01");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onErrorOccurred(const QString &error_string)
|
|
||||||
{
|
|
||||||
// LOG_INFO(QStringLiteral(u"错误: %1").arg(error_string));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onRunningInfo(const QString &run_info)
|
|
||||||
{
|
|
||||||
LOG_INFO(QStringLiteral(u"信息: %1").arg(run_info));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onGvfData(const QByteArray &data)
|
void MainWindow::onGvfData(const QByteArray &data)
|
||||||
{
|
{
|
||||||
// QList<ParticleData> particles = _gvfToCsv->parseParticleFrames(data);
|
|
||||||
// //处理粒子数据
|
|
||||||
// changeParticleData(particles);
|
|
||||||
// //处理道址计数
|
|
||||||
// changeChannelParticleCount(particles);
|
|
||||||
// //处理能谱数据
|
|
||||||
// changeParticleEnergyData(particles);
|
|
||||||
// //处理能量计数
|
|
||||||
// changeEnergyCountData(particles);
|
|
||||||
// //处理道址计数谱
|
|
||||||
// changeAddressCountView(particles);
|
|
||||||
// //处理能量计数谱
|
|
||||||
// changeEnergyCountView(particles);
|
|
||||||
MeasureAnalysisProjectModel *project_model = ProjectList::Instance()->GetCurrentProjectModel();
|
MeasureAnalysisProjectModel *project_model = ProjectList::Instance()->GetCurrentProjectModel();
|
||||||
if (!project_model) return;
|
if (!project_model) return;
|
||||||
|
|
||||||
|
|
@ -658,48 +565,6 @@ void MainWindow::onGvfData(const QByteArray &data)
|
||||||
Q_ARG(QString, project_model->GetProjectName()));
|
Q_ARG(QString, project_model->GetProjectName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//处理粒子数据
|
|
||||||
void MainWindow::changeParticleData(QList<ParticleData> &dataList)
|
|
||||||
{
|
|
||||||
if (dataList.isEmpty()) {
|
|
||||||
LOG_INFO(QStringLiteral(u"本次GVF数据未解析到有效粒子,跳过写入CSV"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString dir = ProjectList::Instance()->GetCurrentProjectModel()->GetProjectDir();
|
|
||||||
QString csvPath = QStringLiteral(u"%1/%2").arg(dir).arg("粒子数据.csv");
|
|
||||||
|
|
||||||
QFile outFile(csvPath);
|
|
||||||
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"无法打开CSV文件(追加模式): %1,错误: %2")
|
|
||||||
.arg(csvPath)
|
|
||||||
.arg(outFile.errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream out(&outFile);
|
|
||||||
out.setCodec("UTF-8");
|
|
||||||
|
|
||||||
if (outFile.size() == 0) {
|
|
||||||
out << QStringLiteral(u"板卡号,通道号,道址,时间计数\n");
|
|
||||||
LOG_INFO(QStringLiteral(u"CSV文件为空,已自动写入表头: %1").arg(csvPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString csvBuffer;
|
|
||||||
csvBuffer.reserve(dataList.size() * 64); // 单条数据约64字节,预分配足够内存
|
|
||||||
|
|
||||||
for (const auto &p : dataList) {
|
|
||||||
csvBuffer += QString("%1,%2,%3,%4\n")
|
|
||||||
.arg(p.boardId)
|
|
||||||
.arg(p.channelId)
|
|
||||||
.arg(p.address)
|
|
||||||
.arg(p.timestampCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
out << csvBuffer;
|
|
||||||
out.flush(); // 确保数据立即写入磁盘,避免程序崩溃丢失数据
|
|
||||||
outFile.close();
|
|
||||||
updataTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::updataTable()
|
void MainWindow::updataTable()
|
||||||
|
|
@ -713,20 +578,20 @@ void MainWindow::updataTable()
|
||||||
{
|
{
|
||||||
switch(view->GetAnalyzeType())
|
switch(view->GetAnalyzeType())
|
||||||
{
|
{
|
||||||
case AnalysisType::ParticleData:{
|
case AnalysisType::ParticleData:{
|
||||||
MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
||||||
table->AppendRow();
|
table->AppendRow();
|
||||||
};break;
|
};break;
|
||||||
// case AnalysisType::AddressCountData:
|
// case AnalysisType::AddressCountData:
|
||||||
// {
|
// {
|
||||||
// MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
// MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
||||||
// table->AppendRow();
|
// table->AppendRow();
|
||||||
// };break;
|
// };break;
|
||||||
case AnalysisType::ParticleEnergyData:
|
case AnalysisType::ParticleEnergyData:
|
||||||
{
|
{
|
||||||
MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
||||||
table->AppendRow();
|
table->AppendRow();
|
||||||
};break;
|
};break;
|
||||||
// case AnalysisType::EnergyCountData:
|
// case AnalysisType::EnergyCountData:
|
||||||
// {
|
// {
|
||||||
// MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
// MeasureAnalysisDataTableView* table = dynamic_cast<MeasureAnalysisDataTableView*>(view);
|
||||||
|
|
@ -737,465 +602,8 @@ void MainWindow::updataTable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::changeChannelParticleCount(QList<ParticleData> &data)
|
|
||||||
{
|
|
||||||
if (data.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<uint, QHash<uint, unsigned long long>> deltaCounts; // 通道号 -> 道址 -> 增量
|
|
||||||
int totalParticles = 0;
|
|
||||||
|
|
||||||
// 计算本次数据的增量计数
|
|
||||||
for (const auto &info : data) {
|
|
||||||
int channel_num = (info.boardId) * 4 + (info.channelId + 1);
|
|
||||||
uint address = info.address;
|
|
||||||
|
|
||||||
// 道址范围校验(防止越界)
|
|
||||||
if (address >= 4096) {
|
|
||||||
LOG_WARN(QStringLiteral(u"道址%1超出最大范围%2,已跳过").arg(address).arg(4096));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
deltaCounts[channel_num][address]++;
|
|
||||||
totalParticles++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaCounts.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MeasureAnalysisProjectModel* models = ProjectList::Instance()->GetCurrentProjectModel();
|
|
||||||
if (!models) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"当前没有打开的测量项目,无法写入道址计数数据"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& projectName = models->GetProjectName();
|
|
||||||
const QString& every_ch_count_dir = QDir(models->GetProjectDir()).filePath(QStringLiteral(u"通道道址计数"));
|
|
||||||
QDir every_ch_count_output_dir(every_ch_count_dir);
|
|
||||||
|
|
||||||
if (!every_ch_count_output_dir.exists()) {
|
|
||||||
if (!every_ch_count_output_dir.mkpath(every_ch_count_dir)) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"无法创建通道道址计数目录: %1").arg(every_ch_count_dir));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QMutexLocker locker(&m_channelCountMutex);
|
|
||||||
|
|
||||||
bool hasError = false;
|
|
||||||
QHash<uint, QString> newChannelFiles; // 本次新增的通道文件
|
|
||||||
|
|
||||||
for (auto channelIt = deltaCounts.constBegin(); channelIt != deltaCounts.constEnd(); ++channelIt) {
|
|
||||||
uint channel_num = channelIt.key();
|
|
||||||
const auto& addressDeltas = channelIt.value();
|
|
||||||
|
|
||||||
if (!channel_address_counts.contains(channel_num)) {
|
|
||||||
std::array<unsigned long long, 4096> initCounts;
|
|
||||||
initCounts.fill(0); // 所有道址初始化为0
|
|
||||||
channel_address_counts.insert(channel_num, initCounts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新内存中的总计数
|
|
||||||
auto& channelCounts = channel_address_counts[channel_num];
|
|
||||||
for (auto addressIt = addressDeltas.constBegin(); addressIt != addressDeltas.constEnd(); ++addressIt) {
|
|
||||||
uint address = addressIt.key();
|
|
||||||
unsigned long long delta = addressIt.value();
|
|
||||||
channelCounts[address] += delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString count_data_filename;
|
|
||||||
if (particle_count_filename_list.contains(channel_num)) {
|
|
||||||
count_data_filename = particle_count_filename_list[channel_num];
|
|
||||||
} else {
|
|
||||||
count_data_filename = every_ch_count_output_dir.filePath(QStringLiteral(u"通道%1粒子计数.csv").arg(channel_num));
|
|
||||||
models->SetChannelAddressCountDataFilename(channel_num, count_data_filename);
|
|
||||||
particle_count_filename_list.insert(channel_num, count_data_filename);
|
|
||||||
newChannelFiles.insert(channel_num, count_data_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile outFile(count_data_filename);
|
|
||||||
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"无法打开通道%1的计数文件: %2,错误: %3")
|
|
||||||
.arg(channel_num)
|
|
||||||
.arg(count_data_filename)
|
|
||||||
.arg(outFile.errorString()));
|
|
||||||
hasError = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream out(&outFile);
|
|
||||||
out.setCodec("UTF-8");
|
|
||||||
|
|
||||||
// 写入表头
|
|
||||||
out << QStringLiteral(u"道址,计数\n");
|
|
||||||
|
|
||||||
QString csvBuffer;
|
|
||||||
csvBuffer.reserve(4096 * 32);
|
|
||||||
for (int address = 0; address < 4096; ++address) {
|
|
||||||
unsigned long long total = channelCounts[address];
|
|
||||||
csvBuffer += QString("%1,%2\n").arg(address).arg(total);
|
|
||||||
}
|
|
||||||
|
|
||||||
out << csvBuffer;
|
|
||||||
out.flush(); // 确保数据立即写入磁盘
|
|
||||||
outFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新项目树节点状态
|
|
||||||
if (!newChannelFiles.isEmpty() || !hasError) {
|
|
||||||
for (auto it = newChannelFiles.constBegin(); it != newChannelFiles.constEnd(); ++it) {
|
|
||||||
models->SetChannelAddressCountDataFilename(it.key(), it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& adrr_count_item_name = QStringLiteral(u"道址计数");
|
|
||||||
if (nodeMap.contains(adrr_count_item_name)) {
|
|
||||||
auto adrr_count_item = nodeMap[adrr_count_item_name];
|
|
||||||
bool status_ok = !particle_count_filename_list.isEmpty();
|
|
||||||
QString status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
|
|
||||||
ProjectList::Instance()->SetNodeStatus(adrr_count_item, status, status_ok);
|
|
||||||
|
|
||||||
for (auto it = newChannelFiles.constBegin(); it != newChannelFiles.constEnd(); ++it) {
|
|
||||||
uint ch_num = it.key();
|
|
||||||
QString item_name = QStringLiteral(u"通道%1道址计数").arg(ch_num);
|
|
||||||
if (nodeMap.contains(item_name)) {
|
|
||||||
continue; // 节点已存在,跳过
|
|
||||||
}
|
|
||||||
models->SaveProjectModel();
|
|
||||||
const QVariant& analys_type = QVariant::fromValue(AnalysisType::AddressCountData);
|
|
||||||
QStandardItem* node_item = ProjectList::Instance()->AddChildNode(
|
|
||||||
adrr_count_item, item_name, status, analys_type, true, status_ok);
|
|
||||||
node_item->setData(projectName, Qt::UserRole + 2);
|
|
||||||
node_item->setData(ch_num, Qt::UserRole + 3);
|
|
||||||
nodeMap[item_name] = node_item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// updataTable();
|
|
||||||
|
|
||||||
if (hasError) {
|
|
||||||
LOG_WARN(QStringLiteral(u"部分通道的道址计数数据写入失败,请检查磁盘空间和文件权限"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//处理粒子能量数据
|
|
||||||
void MainWindow::changeParticleEnergyData(QList<ParticleData> &dataList)
|
|
||||||
{
|
|
||||||
if (dataList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetCurrentProjectModel();
|
|
||||||
if (!project_model) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"当前没有打开的测量项目,无法处理能谱数据"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& project_name = project_model->GetProjectName();
|
|
||||||
|
|
||||||
EnergyScaleDataModel energy_scale_data_model(project_model->GetEnergyScaleFilename());
|
|
||||||
if (!energy_scale_data_model.LoadData()) {
|
|
||||||
LOG_WARN(QStringLiteral(u"[%1]加载能量刻度文件失败,跳过本次能谱处理").arg(project_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!energy_scale_data_model.IsValid()) {
|
|
||||||
LOG_WARN(QStringLiteral(u"[%1]能量刻度数据无效,请检查刻度配置").arg(project_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMutexLocker locker(&m_energyDataMutex);
|
|
||||||
|
|
||||||
QString energy_spectrum_filename = QDir(project_model->GetProjectDir()).filePath(QStringLiteral(u"能谱数据.csv"));
|
|
||||||
|
|
||||||
QFile outFile(energy_spectrum_filename);
|
|
||||||
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"[%1]无法打开能谱文件: %2,错误: %3")
|
|
||||||
.arg(project_name)
|
|
||||||
.arg(energy_spectrum_filename)
|
|
||||||
.arg(outFile.errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream out(&outFile);
|
|
||||||
out.setCodec("UTF-8");
|
|
||||||
|
|
||||||
if ( outFile.size() == 0) {
|
|
||||||
out << QStringLiteral(u"板卡号,通道号,道址,能量(KeV),时间计数\n");
|
|
||||||
LOG_DEBUG(QStringLiteral(u"[%1]能谱文件为空,已写入标准表头").arg(project_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString csvBuffer;
|
|
||||||
csvBuffer.reserve(dataList.size() * 80); // 单条数据约80字节,预分配足够内存
|
|
||||||
|
|
||||||
int totalProcessed = dataList.size();
|
|
||||||
int successCount = 0;
|
|
||||||
int skipCount = 0;
|
|
||||||
|
|
||||||
for (const auto& particle : dataList) {
|
|
||||||
int channel_num = (particle.boardId) * 4 + (particle.channelId + 1);
|
|
||||||
const QString& channel_name = QStringLiteral(u"通道%1").arg(channel_num);
|
|
||||||
|
|
||||||
std::vector<double> coeffs = energy_scale_data_model.GetEnergyFitResultCoeffs(channel_name);
|
|
||||||
if (coeffs.empty()) {
|
|
||||||
skipCount++;
|
|
||||||
continue; // 该通道未配置能量刻度,跳过
|
|
||||||
}
|
|
||||||
|
|
||||||
double energy = GaussPolyCoe::Predict(coeffs, particle.address);
|
|
||||||
|
|
||||||
csvBuffer += QString("%1,%2,%3,%4,%5\n")
|
|
||||||
.arg(particle.boardId)
|
|
||||||
.arg(particle.channelId)
|
|
||||||
.arg(particle.address)
|
|
||||||
.arg(energy, 0, 'f', 4)
|
|
||||||
.arg(particle.timestampCount);
|
|
||||||
|
|
||||||
successCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!csvBuffer.isEmpty()) {
|
|
||||||
out << csvBuffer;
|
|
||||||
out.flush(); // 强制写入磁盘,防止程序崩溃丢失数据
|
|
||||||
}
|
|
||||||
|
|
||||||
outFile.close();
|
|
||||||
|
|
||||||
if (successCount > 0) {
|
|
||||||
project_model->SetParticleEnergyDataFilename(energy_spectrum_filename);
|
|
||||||
|
|
||||||
if (!project_model->SaveProjectModel()) {
|
|
||||||
LOG_WARN(QStringLiteral(u"[%1]保存项目模型失败,能谱文件路径未持久化").arg(project_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& energy_node_name = QStringLiteral(u"粒子能量数据");
|
|
||||||
QMap<QString, QMap<QString, QStandardItem *>> all_nodes = ProjectList::Instance()->getProjectNodeItems();
|
|
||||||
QMap<QString, QStandardItem *> project_nodes = all_nodes[project_name];
|
|
||||||
|
|
||||||
if (project_nodes.contains(energy_node_name)) {
|
|
||||||
QStandardItem* energy_node = project_nodes[energy_node_name];
|
|
||||||
ProjectList::Instance()->SetNodeStatus(energy_node, QStringLiteral(u"有效"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updataTable();
|
|
||||||
}
|
|
||||||
//处理能量计数
|
|
||||||
void MainWindow::changeEnergyCountData(QList<ParticleData> &dataList)
|
|
||||||
{
|
|
||||||
if (dataList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetCurrentProjectModel();
|
|
||||||
if (!project_model) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"当前没有打开的测量项目,无法处理能量计数数据"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const QString& project_name = project_model->GetProjectName();
|
|
||||||
|
|
||||||
// 加载能量刻度数据
|
|
||||||
EnergyScaleDataModel energy_scale_data_model(project_model->GetEnergyScaleFilename());
|
|
||||||
if (!energy_scale_data_model.LoadData()) {
|
|
||||||
LOG_WARN(QStringLiteral(u"[%1]加载能量刻度文件失败,跳过本次能量计数处理").arg(project_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!energy_scale_data_model.IsValid()) {
|
|
||||||
LOG_WARN(QStringLiteral(u"[%1]能量刻度数据无效,请检查刻度配置").arg(project_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 计算本次数据的增量计数
|
|
||||||
QHash<uint, QHash<double, unsigned long long>> deltaCounts; // 通道号 -> 能量值 -> 增量
|
|
||||||
QHash<double, unsigned long long> deltaAllChannelCounts; // 全通道增量
|
|
||||||
|
|
||||||
int totalParticles = 0;
|
|
||||||
int successCount = 0;
|
|
||||||
int skipCount = 0;
|
|
||||||
for (const auto &particle : dataList) {
|
|
||||||
int channel_num = (particle.boardId) * 4 + (particle.channelId + 1);
|
|
||||||
const QString& channel_name = QStringLiteral(u"通道%1").arg(channel_num);
|
|
||||||
|
|
||||||
// 获取该通道的能量刻度系数
|
|
||||||
std::vector<double> coeffs = energy_scale_data_model.GetEnergyFitResultCoeffs(channel_name);
|
|
||||||
if (coeffs.empty()) {
|
|
||||||
skipCount++;
|
|
||||||
continue; // 该通道未配置能量刻度,跳过
|
|
||||||
}
|
|
||||||
|
|
||||||
// 道址转能量(保留1位小数,作为分组键,避免浮点数精度问题)
|
|
||||||
double energy = GaussPolyCoe::Predict(coeffs, particle.address);
|
|
||||||
double energy_key = qRound(energy * 10.0) / 10.0; // 精确到0.1KeV
|
|
||||||
|
|
||||||
deltaCounts[channel_num][energy_key]++;
|
|
||||||
deltaAllChannelCounts[energy_key]++;
|
|
||||||
totalParticles++;
|
|
||||||
successCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaCounts.isEmpty()) {
|
|
||||||
if (skipCount > 0) {
|
|
||||||
LOG_DEBUG(QStringLiteral(u"本次%1个粒子全部因无能量刻度配置而跳过").arg(skipCount));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QString& energy_count_dir = QDir(project_model->GetProjectDir()).filePath(QStringLiteral(u"通道能量计数"));
|
|
||||||
QDir energy_count_output_dir(energy_count_dir);
|
|
||||||
|
|
||||||
if (!energy_count_output_dir.exists()) {
|
|
||||||
if (!energy_count_output_dir.mkpath(energy_count_dir)) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"无法创建通道能量计数目录: %1").arg(energy_count_dir));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QMutexLocker locker(&m_energyCountMutex);
|
|
||||||
|
|
||||||
bool hasError = false;
|
|
||||||
QHash<uint, QString> newChannelFiles; // 本次新增的通道文件
|
|
||||||
QMap<QString, QMap<QString, QStandardItem *>> all_nodes = ProjectList::Instance()->getProjectNodeItems();
|
|
||||||
QMap<QString, QStandardItem *> project_nodes = all_nodes[project_name];
|
|
||||||
|
|
||||||
for (auto channelIt = deltaCounts.constBegin(); channelIt != deltaCounts.constEnd(); ++channelIt) {
|
|
||||||
uint channel_num = channelIt.key();
|
|
||||||
const auto& energyDeltas = channelIt.value();
|
|
||||||
|
|
||||||
auto& channelCounts = channel_energy_counts[channel_num];
|
|
||||||
|
|
||||||
for (auto energyIt = energyDeltas.constBegin(); energyIt != energyDeltas.constEnd(); ++energyIt) {
|
|
||||||
double energy_key = energyIt.key();
|
|
||||||
unsigned long long delta = energyIt.value();
|
|
||||||
channelCounts[energy_key] += delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString count_data_filename;
|
|
||||||
if (energy_count_filename_list.contains(channel_num)) {
|
|
||||||
count_data_filename = energy_count_filename_list[channel_num];
|
|
||||||
} else {
|
|
||||||
count_data_filename = energy_count_output_dir.filePath(QStringLiteral(u"通道%1能量计数.csv").arg(channel_num));
|
|
||||||
project_model->SetChannelEnergyCountDataFilename(channel_num, count_data_filename);
|
|
||||||
energy_count_filename_list.insert(channel_num, count_data_filename);
|
|
||||||
newChannelFiles.insert(channel_num, count_data_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile outFile(count_data_filename);
|
|
||||||
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
|
||||||
LOG_ERROR(QStringLiteral(u"无法打开通道%1的能量计数文件: %2,错误: %3")
|
|
||||||
.arg(channel_num)
|
|
||||||
.arg(count_data_filename)
|
|
||||||
.arg(outFile.errorString()));
|
|
||||||
hasError = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream out(&outFile);
|
|
||||||
out.setCodec("UTF-8");
|
|
||||||
|
|
||||||
// 写入表头
|
|
||||||
out << QStringLiteral(u"能量(KeV),计数\n");
|
|
||||||
|
|
||||||
// 按能量值排序后输出
|
|
||||||
QList<double> sortedEnergies = channelCounts.keys();
|
|
||||||
std::sort(sortedEnergies.begin(), sortedEnergies.end());
|
|
||||||
|
|
||||||
QString csvBuffer;
|
|
||||||
csvBuffer.reserve(sortedEnergies.size() * 40);
|
|
||||||
for (double energy : sortedEnergies) {
|
|
||||||
unsigned long long total = channelCounts[energy];
|
|
||||||
csvBuffer += QString("%1,%2\n").arg(energy, 0, 'f', 1).arg(total);
|
|
||||||
}
|
|
||||||
|
|
||||||
out << csvBuffer;
|
|
||||||
out.flush(); // 确保数据立即写入磁盘
|
|
||||||
outFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!deltaAllChannelCounts.isEmpty()) {
|
|
||||||
// 更新内存中的全通道总计数
|
|
||||||
for (auto energyIt = deltaAllChannelCounts.constBegin(); energyIt != deltaAllChannelCounts.constEnd(); ++energyIt) {
|
|
||||||
double bin_energy = energyIt.key();
|
|
||||||
unsigned long long delta = energyIt.value();
|
|
||||||
all_channel_energy_counts[bin_energy] += delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 全通道输出文件路径
|
|
||||||
|
|
||||||
QString all_channel_energy_count_filename = energy_count_output_dir.filePath(QStringLiteral(u"全通道.csv"));
|
|
||||||
|
|
||||||
|
|
||||||
QFile allChannelFile(all_channel_energy_count_filename);
|
|
||||||
if (allChannelFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
|
||||||
QTextStream outAll(&allChannelFile);
|
|
||||||
outAll.setCodec("UTF-8");
|
|
||||||
|
|
||||||
// 写入表头
|
|
||||||
outAll << QStringLiteral(u"能量(KeV),计数\n");
|
|
||||||
|
|
||||||
// 按能量值升序排序
|
|
||||||
QList<double> sortedAllEnergies = all_channel_energy_counts.keys();
|
|
||||||
std::sort(sortedAllEnergies.begin(), sortedAllEnergies.end());
|
|
||||||
|
|
||||||
QString allCsvBuffer;
|
|
||||||
allCsvBuffer.reserve(sortedAllEnergies.size() * 40);
|
|
||||||
for (double bin_energy : sortedAllEnergies) {
|
|
||||||
unsigned long long total = all_channel_energy_counts[bin_energy];
|
|
||||||
allCsvBuffer += QString("%1,%2\n").arg(bin_energy, 0, 'f', 3).arg(total);
|
|
||||||
}
|
|
||||||
|
|
||||||
outAll << allCsvBuffer;
|
|
||||||
outAll.flush();
|
|
||||||
allChannelFile.close();
|
|
||||||
|
|
||||||
// 保存全通道文件路径到项目模型
|
|
||||||
project_model->SetAllChannelEnergyTotalCountDataFilename(all_channel_energy_count_filename);
|
|
||||||
} else {
|
|
||||||
LOG_ERROR(QStringLiteral(u"无法打开全通道能量计数文件: %1,错误: %2")
|
|
||||||
.arg(all_channel_energy_count_filename)
|
|
||||||
.arg(allChannelFile.errorString()));
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新项目树节点状态
|
|
||||||
if (!newChannelFiles.isEmpty() || !hasError) {
|
|
||||||
for (auto it = newChannelFiles.constBegin(); it != newChannelFiles.constEnd(); ++it) {
|
|
||||||
project_model->SetChannelEnergyCountDataFilename(it.key(), it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& energy_count_item_name = QStringLiteral(u"能量计数");
|
|
||||||
if (project_nodes.contains(energy_count_item_name)) {
|
|
||||||
auto energy_count_item = project_nodes[energy_count_item_name];
|
|
||||||
bool status_ok = !energy_count_filename_list.isEmpty();
|
|
||||||
QString status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
|
|
||||||
ProjectList::Instance()->SetNodeStatus(energy_count_item, status, status_ok);
|
|
||||||
|
|
||||||
for (auto it = newChannelFiles.constBegin(); it != newChannelFiles.constEnd(); ++it) {
|
|
||||||
uint ch_num = it.key();
|
|
||||||
QString item_name = QStringLiteral(u"通道%1能量计数").arg(ch_num);
|
|
||||||
if (project_nodes.contains(item_name)) {
|
|
||||||
continue; // 节点已存在,跳过
|
|
||||||
}
|
|
||||||
project_model->SaveProjectModel();
|
|
||||||
const QVariant& analys_type = QVariant::fromValue(AnalysisType::EnergyCountData);
|
|
||||||
QStandardItem* node_item = ProjectList::Instance()->AddChildNode(
|
|
||||||
energy_count_item, item_name, status, analys_type, true, status_ok);
|
|
||||||
node_item->setData(project_name, Qt::UserRole + 2);
|
|
||||||
node_item->setData(ch_num, Qt::UserRole + 3);
|
|
||||||
project_nodes[item_name] = node_item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新数据表格视图
|
|
||||||
// updataTable();
|
|
||||||
|
|
||||||
if (hasError) {
|
|
||||||
LOG_WARN(QStringLiteral(u"部分通道的能量计数数据写入失败,请检查磁盘空间和文件权限"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//处理道址计数谱
|
|
||||||
void MainWindow::changeAddressCountView(QList<ParticleData> &dataList)
|
void MainWindow::changeAddressCountView(QList<ParticleData> &dataList)
|
||||||
{
|
{
|
||||||
if (dataList.isEmpty()) {
|
if (dataList.isEmpty()) {
|
||||||
|
|
@ -1268,7 +676,7 @@ void MainWindow::on_AddressCountTimer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view->updateView(data_files_set);
|
view->updateView(data_files_set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1309,20 +717,34 @@ void MainWindow::on_EnergyCountTimer()
|
||||||
|
|
||||||
void MainWindow::on_action_stop_measure_triggered()
|
void MainWindow::on_action_stop_measure_triggered()
|
||||||
{
|
{
|
||||||
const QString& device_guid = deviceList.at(0);
|
m_deviceMgr->stopMeasure();
|
||||||
if (device_guid.isEmpty()) {
|
|
||||||
LOG_INFO(QStringLiteral(u"未选择测量设备GUID."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_measure_client->stopMeasure(device_guid);
|
|
||||||
m_AddressCountTimer->stop();
|
m_AddressCountTimer->stop();
|
||||||
|
m_EnergyCountTimer->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_action_device_connect_cfg_triggered()
|
void MainWindow::on_action_device_connect_cfg_triggered()
|
||||||
{
|
{
|
||||||
|
MeasureAnalysisProjectModel* projectModel = ProjectList::Instance()->GetCurrentProjectModel();
|
||||||
|
if (!projectModel) {
|
||||||
|
QMessageBox::information(this, "提示", "请先新建项目", "确认", "取消");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_deviceMgr->loadConfig();
|
||||||
|
m_deviceMgr->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onParticleDatarefresh()
|
||||||
|
{
|
||||||
|
MeasureAnalysisProjectModel *pro_model = ProjectList::Instance()->GetCurrentProjectModel();
|
||||||
|
if (!pro_model) return;
|
||||||
|
bool status_ok = !pro_model->GetAllChannelParticleDataFilename().isEmpty();
|
||||||
|
QString status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效");
|
||||||
|
QVariant analys_type = QVariant::fromValue(AnalysisType::ParticleData);
|
||||||
|
QString item_name = QStringLiteral(u"测量粒子数据");
|
||||||
|
QStandardItem * particleData = nodeMap[item_name];
|
||||||
|
ProjectList::Instance()->SetNodeStatus(particleData,status,true);
|
||||||
|
updataTable();
|
||||||
|
}
|
||||||
void MainWindow::onAddressCountViewNeedRefresh()
|
void MainWindow::onAddressCountViewNeedRefresh()
|
||||||
{
|
{
|
||||||
MeasureAnalysisProjectModel *pro_model = ProjectList::Instance()->GetCurrentProjectModel();
|
MeasureAnalysisProjectModel *pro_model = ProjectList::Instance()->GetCurrentProjectModel();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "GvfToCsv/GvfToCsv.h"
|
#include "GvfToCsv/GvfToCsv.h"
|
||||||
#include "MeasureAnalysisProjectModel.h"
|
#include "MeasureAnalysisProjectModel.h"
|
||||||
#include "DataProcessWorkPool.h"
|
#include "DataProcessWorkPool.h"
|
||||||
|
#include "DeviceConnectManagement.h"
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
@ -59,14 +60,7 @@ private:
|
||||||
//更新表格
|
//更新表格
|
||||||
void updataTable();
|
void updataTable();
|
||||||
|
|
||||||
//处理粒子数据
|
|
||||||
void changeParticleData(QList<ParticleData> &dataList);
|
|
||||||
//处理道址计数
|
|
||||||
void changeChannelParticleCount(QList<ParticleData> &data);
|
|
||||||
//处理粒子能量数据
|
|
||||||
void changeParticleEnergyData(QList<ParticleData> &dataList);
|
|
||||||
//处理能量计数
|
|
||||||
void changeEnergyCountData(QList<ParticleData> &dataList);
|
|
||||||
//处理道址计数谱
|
//处理道址计数谱
|
||||||
void changeAddressCountView(QList<ParticleData> &dataList);
|
void changeAddressCountView(QList<ParticleData> &dataList);
|
||||||
//处理能量计数谱
|
//处理能量计数谱
|
||||||
|
|
@ -83,27 +77,20 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void on_action_nuclideLib_triggered();
|
void on_action_nuclideLib_triggered();
|
||||||
void onShowBackgroundTaskList();
|
void onShowBackgroundTaskList();
|
||||||
|
//开始测量
|
||||||
void on_action_start_measure_triggered();
|
void on_action_start_measure_triggered();
|
||||||
|
//服务器传过来的数据
|
||||||
|
|
||||||
void onStartMeasureResult(bool success, const QString& info);
|
|
||||||
void onStopMeasureResult(bool success, const QString& message);
|
|
||||||
void onSetMeasureConfigParamsResult(bool success, const QString& message);
|
|
||||||
void onClearDataResult(bool success, const QString& message);
|
|
||||||
void onGetDeviceListResult(bool success, const QString &message, const QStringList &devices);
|
|
||||||
void onErrorOccurred(const QString &error_string);
|
|
||||||
void onRunningInfo(const QString &run_info);
|
|
||||||
void onGvfData(const QByteArray& data);
|
void onGvfData(const QByteArray& data);
|
||||||
|
//停止测量
|
||||||
void on_action_stop_measure_triggered();
|
void on_action_stop_measure_triggered();
|
||||||
|
//道址计数谱定时器
|
||||||
void on_AddressCountTimer();
|
void on_AddressCountTimer();
|
||||||
|
//能量计数谱定时器
|
||||||
void on_EnergyCountTimer();
|
void on_EnergyCountTimer();
|
||||||
//设备连接管理
|
//设备连接管理
|
||||||
void on_action_device_connect_cfg_triggered();
|
void on_action_device_connect_cfg_triggered();
|
||||||
|
|
||||||
|
void onParticleDatarefresh();
|
||||||
void onAddressCountViewNeedRefresh();
|
void onAddressCountViewNeedRefresh();
|
||||||
void onEnergyCountViewNeedRefresh();
|
void onEnergyCountViewNeedRefresh();
|
||||||
void onNewAddressCountChannelFile(uint channelNum, const QString &filename);
|
void onNewAddressCountChannelFile(uint channelNum, const QString &filename);
|
||||||
|
|
@ -111,6 +98,14 @@ private slots:
|
||||||
void onAllChannelEnergyCountFileUpdated(const QString &filename);
|
void onAllChannelEnergyCountFileUpdated(const QString &filename);
|
||||||
void onParticleEnergyDataUpdated(const QString &energySpectrumFilename);
|
void onParticleEnergyDataUpdated(const QString &energySpectrumFilename);
|
||||||
|
|
||||||
|
//更新粒子数据树形节点状态
|
||||||
|
void onUpdateParticleDataTreeStatus();
|
||||||
|
|
||||||
|
void onMeasureStarted(bool success, const QString& message);
|
||||||
|
|
||||||
|
void onMeasureStopped(bool success, const QString& message);
|
||||||
|
|
||||||
|
void onDeviceStatusMessage(const QString& msg);
|
||||||
private:
|
private:
|
||||||
QMutex _mutex_info_output;
|
QMutex _mutex_info_output;
|
||||||
QPlainTextEdit* _plain_edit_info_output;
|
QPlainTextEdit* _plain_edit_info_output;
|
||||||
|
|
@ -134,7 +129,6 @@ private:
|
||||||
|
|
||||||
QHash<uint, std::array<unsigned long long, 4096>> channel_address_counts; // 改为数组
|
QHash<uint, std::array<unsigned long long, 4096>> channel_address_counts; // 改为数组
|
||||||
QMap<uint, QString> particle_count_filename_list;
|
QMap<uint, QString> particle_count_filename_list;
|
||||||
//2026-06-11
|
|
||||||
QMap<QString, QStandardItem *> nodeMap;
|
QMap<QString, QStandardItem *> nodeMap;
|
||||||
QMutex m_channelCountMutex;//
|
QMutex m_channelCountMutex;//
|
||||||
QMutex m_energyDataMutex;//能量谱锁
|
QMutex m_energyDataMutex;//能量谱锁
|
||||||
|
|
@ -154,5 +148,8 @@ private:
|
||||||
QThread *_gvfProcessThread = nullptr;
|
QThread *_gvfProcessThread = nullptr;
|
||||||
DataProcessWorkPool::RealtimeGvfDataWorker *_gvfWorker = nullptr;
|
DataProcessWorkPool::RealtimeGvfDataWorker *_gvfWorker = nullptr;
|
||||||
|
|
||||||
|
DeviceConnectManagement* m_deviceMgr = nullptr; // 统一设备管理器,消除重复代码
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ SOURCES += \
|
||||||
CountRateAnalysisView/CountRateAnalysisView.cpp \
|
CountRateAnalysisView/CountRateAnalysisView.cpp \
|
||||||
CustomQwtPlot.cpp \
|
CustomQwtPlot.cpp \
|
||||||
DataProcessWorkPool.cpp \
|
DataProcessWorkPool.cpp \
|
||||||
|
DeviceConnectManagement.cpp \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
||||||
EnergyCountPeakFitView/PeakFitParamsDialog.cpp \
|
EnergyCountPeakFitView/PeakFitParamsDialog.cpp \
|
||||||
EnergyCountPeakFitView/PlotRectItem.cpp \
|
EnergyCountPeakFitView/PlotRectItem.cpp \
|
||||||
|
|
@ -133,6 +134,7 @@ HEADERS += \
|
||||||
CountRateAnalysisView/CountRateAnalysisView.h \
|
CountRateAnalysisView/CountRateAnalysisView.h \
|
||||||
CustomQwtPlot.h \
|
CustomQwtPlot.h \
|
||||||
DataProcessWorkPool.h \
|
DataProcessWorkPool.h \
|
||||||
|
DeviceConnectManagement.h \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
||||||
EnergyCountPeakFitView/PeakFitParamsDialog.h \
|
EnergyCountPeakFitView/PeakFitParamsDialog.h \
|
||||||
EnergyCountPeakFitView/PlotRectItem.h \
|
EnergyCountPeakFitView/PlotRectItem.h \
|
||||||
|
|
@ -183,6 +185,7 @@ FORMS += \
|
||||||
2DSpectralCompliance/TwoDSpectralCompliance.ui \
|
2DSpectralCompliance/TwoDSpectralCompliance.ui \
|
||||||
AboutDlg.ui \
|
AboutDlg.ui \
|
||||||
CountRateAnalysisView/CountRateAnalysisView.ui \
|
CountRateAnalysisView/CountRateAnalysisView.ui \
|
||||||
|
DeviceConnectManagement.ui \
|
||||||
EnergyScaleForm.ui \
|
EnergyScaleForm.ui \
|
||||||
MainWindow.ui \
|
MainWindow.ui \
|
||||||
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.ui \
|
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.ui \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user