功能: - UDP端口监听,实时接收数据 - 解析16通道逗号分隔的ADC数据 - 实时波形绘制(支持滚轮缩放、右键拖拽、双击恢复) - 数据自动保存到 data_端口号/ 目录 - 支持打开历史CSV文件回放查看 - 16通道独立颜色,可切换显示/隐藏 - 深色主题界面
128 lines
2.9 KiB
C++
128 lines
2.9 KiB
C++
#include "datamanager.h"
|
||
#include <QDir>
|
||
#include <QDebug>
|
||
|
||
DataManager::DataManager(QObject *parent)
|
||
: QObject(parent)
|
||
, m_recording(false)
|
||
, m_headerWritten(false)
|
||
{
|
||
}
|
||
|
||
DataManager::~DataManager()
|
||
{
|
||
stopRecording();
|
||
}
|
||
|
||
bool DataManager::startRecording(const QString &dirPath)
|
||
{
|
||
stopRecording();
|
||
|
||
QDir dir(dirPath);
|
||
if (!dir.exists()) {
|
||
if (!dir.mkpath(".")) {
|
||
qWarning() << "无法创建目录:" << dirPath;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
QString fileName = QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss") + ".csv";
|
||
m_filePath = dir.filePath(fileName);
|
||
|
||
m_file.setFileName(m_filePath);
|
||
if (!m_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||
qWarning() << "无法创建文件:" << m_filePath;
|
||
return false;
|
||
}
|
||
|
||
m_stream.setDevice(&m_file);
|
||
m_headerWritten = false;
|
||
m_recording = true;
|
||
|
||
qDebug() << "开始记录数据到:" << m_filePath;
|
||
return true;
|
||
}
|
||
|
||
void DataManager::stopRecording()
|
||
{
|
||
if (m_recording) {
|
||
m_stream.flush();
|
||
m_file.close();
|
||
m_recording = false;
|
||
qDebug() << "停止记录, 文件:" << m_filePath;
|
||
}
|
||
}
|
||
|
||
bool DataManager::isRecording() const
|
||
{
|
||
return m_recording;
|
||
}
|
||
|
||
QString DataManager::currentFilePath() const
|
||
{
|
||
return m_filePath;
|
||
}
|
||
|
||
void DataManager::appendDataPoint(const QVector<int> &values)
|
||
{
|
||
if (!m_recording) return;
|
||
|
||
if (!m_headerWritten) {
|
||
// 写入表头
|
||
QStringList headers;
|
||
for (int i = 0; i < 16; ++i) {
|
||
headers << QString("ch%1").arg(i);
|
||
}
|
||
m_stream << headers.join(",") << "\n";
|
||
m_headerWritten = true;
|
||
}
|
||
|
||
QStringList parts;
|
||
for (int v : values) {
|
||
parts << QString::number(v);
|
||
}
|
||
m_stream << parts.join(",") << "\n";
|
||
}
|
||
|
||
QVector<QVector<double>> DataManager::loadFile(const QString &filePath, QString &error)
|
||
{
|
||
QVector<QVector<double>> result(16);
|
||
|
||
QFile file(filePath);
|
||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||
error = QString("无法打开文件: %1").arg(filePath);
|
||
return result;
|
||
}
|
||
|
||
QTextStream stream(&file);
|
||
bool firstLine = true;
|
||
|
||
while (!stream.atEnd()) {
|
||
QString line = stream.readLine().trimmed();
|
||
if (line.isEmpty()) continue;
|
||
|
||
// 跳过表头
|
||
if (firstLine) {
|
||
firstLine = false;
|
||
// 检查是否是表头(包含非数字字符如ch)
|
||
if (line.contains("ch", Qt::CaseInsensitive) && !line.at(0).isDigit()) {
|
||
continue;
|
||
}
|
||
}
|
||
|
||
QStringList parts = line.split(",");
|
||
if (parts.size() < 16) continue;
|
||
|
||
for (int i = 0; i < 16; ++i) {
|
||
bool ok;
|
||
double val = parts[i].toDouble(&ok);
|
||
if (ok) {
|
||
result[i].append(val);
|
||
}
|
||
}
|
||
}
|
||
|
||
file.close();
|
||
return result;
|
||
}
|