添加上传下载配置

This commit is contained in:
zhangsheng 2025-04-11 20:27:45 +08:00
parent 0eb563da4e
commit 69eecc6824
8 changed files with 194 additions and 56 deletions

View File

@ -70,8 +70,54 @@ void MyTcpClient::onConnected() {
}
void MyTcpClient::onReadyRead() {
QByteArray data = socket->readAll();
emit dataReceived(data);
while (socket->bytesAvailable() > 0) {
if (m_waitingForHeader) {
// 1. 先尝试读取头部(固定长度)
if (socket->bytesAvailable() < sizeof(PackageHead)) {
return; // 数据不够,等待下次触发
}
// 读取头部
socket->read(reinterpret_cast<char*>(&m_currentHead), sizeof(PackageHead));
// 验证头部标识0xAA55AA
if (m_currentHead.head[0] != 0xAA ||
m_currentHead.head[1] != 0x55 ||
m_currentHead.head[2] != 0xAA) {
qWarning() << "Invalid header! Disconnecting...";
return;
}
// 进入等待数据状态
m_waitingForHeader = false;
m_buffer.clear();
m_buffer.append(reinterpret_cast<char*>(&m_currentHead), sizeof(PackageHead)); // 先存头部
} else {
// 2. 根据头部的 len 读取剩余数据
qint64 remainingBytes = m_currentHead.len - (m_buffer.size() - sizeof(PackageHead));
if (remainingBytes <= 0) {
// 数据已经完整,触发信号
emit dataReceived(m_buffer);
m_waitingForHeader = true; // 重置状态,准备接收下一个包
break; // 继续处理缓冲区可能的下一个包
}
// 读取剩余数据(不超过 remainingBytes
QByteArray newData = socket->read(remainingBytes);
qDebug() << "Read" << newData.size() << "bytes";
m_buffer.append(newData);
// 检查是否已经读完
if (m_buffer.size() - sizeof(PackageHead) >= m_currentHead.len) {
qDebug() << "m_buffer" << m_buffer.size() << "bytes";
emit dataReceived(m_buffer);
m_waitingForHeader = true; // 准备接收下一个包
}
}
}
// QByteArray data = socket->readAll();
// emit dataReceived(data);
}
void MyTcpClient::onDisconnected() {

View File

@ -4,6 +4,7 @@
#include <QTcpSocket>
#include <QTimer>
#include <QObject>
#include "data_config.h"
class MyTcpClient : public QObject {
Q_OBJECT
@ -39,6 +40,10 @@ private:
quint16 serverPort;
bool shouldReconnect; // 标记是否需要重连
static MyTcpClient* m_instance;
QByteArray m_buffer; // 存储当前正在接收的数据
bool m_waitingForHeader = true; // 是否在等待头部
PackageHead m_currentHead; // 当前包的头部信息
};
#endif // MYTCPCLIENT_H

View File

@ -326,7 +326,7 @@ void ConfigMgr::Load(QString filename) {
// filter
QJsonArray filter_array = channel["filter"].toArray();
for (int k = 0; k < filter_array.size(); k++) {
QJsonObject filter_ele = filter_array[i].toObject();
QJsonObject filter_ele = filter_array[k].toObject();
variable->filter_[k].low = filter_ele["low"].toInt();
variable->filter_[k].high = filter_ele["high"].toInt();
variable->filter_[k].checked = filter_ele["checked"].toBool();

View File

@ -58,9 +58,28 @@ enum CMTCommand {
kGetVersionInfo = 4,
kRelaySetting = 5,
kRelayStatus = 6,
kUpgradeProgress = 7
kUpgradeProgress = 7,
kCalibrationMode = 8,
kGetDcValue = 9,
kSetCalibrationCoe = 10,
kGetCalibrationCoe = 11,
kClearCalibrationCoe = 12,
kGetWaveData = 13,
kUploadConfigFile = 14,
kDownloadConfigFile = 15,
kConfigSubCard = 16, // 请求无包体,响应有包体
kRS485BaudrateSet = 17, // RS485波特率配置
kRS485BaudrateGet = 18, // RS485波特率获取
};
enum RS485Baudrate {
kBaudrate2400 = 0,
kBaudrate4800 = 1,
kBaudrate9600 = 2, // 默认值
kBaudrate19200 = 3,
kBaudrate38400 = 4,
kBaudrate57600 = 5,
kBaudrate115200 = 6
};
// 振动板采样率
typedef enum {
kVibSR16K = 0, // 16k
@ -198,6 +217,7 @@ typedef struct {
double scale_factor;
} Transducer;
#pragma pack(1)
typedef struct {
uint8_t head[3]; // 固定值0xAA55AA
@ -244,6 +264,30 @@ typedef struct {
uint8_t status; // 7 测试状态,8 手动状态,9 工作状态
} RelayStatusRsp;
typedef struct {
char data[0];
} UploadConfigReq, DownloadConfigRsp;
typedef struct {
uint8_t code;
} UploadConfigRsp, DownloadConfigReq;
typedef struct {
uint8_t card_id;
} ConfigSubCardReq;
typedef struct {
uint8_t code; // 0: success 1: 无配置文件 2失败
} ConfigSubCardRsp;
typedef struct {
uint8_t baudrate; // kRS485BaudrateSet, kRS485BaudrateGet
} BaudrateSetReq, BaudrateGetRsp;
typedef struct {
uint8_t code; // 0: success
} BaudrateSetRsp;
#pragma pack()
#endif // DATA_CONFIG_H

View File

@ -87,7 +87,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(btnGroup_slot, SIGNAL(buttonClicked(QAbstractButton *)), this, SLOT(OnButtonGroup(QAbstractButton *)));
QSettings settingsread(QCoreApplication::applicationDirPath() + "\\config\\config.ini", QSettings::IniFormat);
g_strServerIp = settingsread.value("Server/IP").toString();
//connectServer();
connectServer();
// 设置自定义日志处理函数
#ifndef QT_DEBUG
qInstallMessageHandler(messageHandler);
@ -199,6 +199,7 @@ void MainWindow::createMenu(const QString &rootTitle, QPushButton *parent) {
QAction *proximitor_2 = proximitor_menu->addAction("/HAM824 三冗余板卡");
proximitor_2->setData(kCardVibTMRPrimary);
QAction *rpm_1 = rpm_menu->addAction("/OPM844 单板卡");
rpm_1->setData(kCardSpeedSingle);
// 创建第二层子菜单:/KPM834 键相模块
QAction *keyphasor_1 = keyphasor->addAction("/KPM834 单板卡");
keyphasor_1->setData(kCardKeyphaseSingle);
@ -342,7 +343,7 @@ void MainWindow::onMenuActionTriggered() {
button->setText(chan_display);
}
if (action->text() == "重置模块") {
if (map_slot_config[button_id].rack_type == "TMR1") {
if (ConfigMgr::Instance()->card_type_[button_id - 1] == kCardRelayTMRPrimary) {
map_slot_config[button_id].slot_type = "";
map_slot_config[button_id].rack_type = "0";
map_slot_config[button_id].slot_btn->setText("");
@ -355,7 +356,7 @@ void MainWindow::onMenuActionTriggered() {
map_slot_config[button_id + 2].rack_type = "0";
map_slot_config[button_id + 2].slot_btn->setText("");
map_slot_config[button_id + 2].chan_display = "";
} else if (map_slot_config[button_id].rack_type == "TMR2") {
} else if (ConfigMgr::Instance()->card_type_[button_id - 1] == kCardRelayTMRBackup) {
map_slot_config[button_id - 1].slot_type = "";
map_slot_config[button_id - 1].rack_type = "0";
map_slot_config[button_id - 1].slot_btn->setText("");
@ -368,44 +369,11 @@ void MainWindow::onMenuActionTriggered() {
map_slot_config[button_id + 1].rack_type = "0";
map_slot_config[button_id + 1].slot_btn->setText("");
map_slot_config[button_id + 1].chan_display = "";
} else if (map_slot_config[button_id].rack_type == "TMR3") {
map_slot_config[button_id - 2].slot_type = "";
map_slot_config[button_id - 2].rack_type = "0";
map_slot_config[button_id - 2].slot_btn->setText("");
map_slot_config[button_id - 2].chan_display = "";
map_slot_config[button_id - 1].slot_type = "";
map_slot_config[button_id - 1].rack_type = "0";
map_slot_config[button_id - 1].slot_btn->setText("");
map_slot_config[button_id - 1].chan_display = "";
map_slot_config[button_id].slot_type = "";
map_slot_config[button_id].rack_type = "0";
}else if (ConfigMgr::Instance()->card_type_[button_id - 1] == kCardVibSingle ||
ConfigMgr::Instance()->card_type_[button_id - 1] == kCardSpeedSingle ||
ConfigMgr::Instance()->card_type_[button_id - 1] == kCardKeyphaseSingle) {
ConfigMgr::Instance()->card_type_[button_id - 1] = kCardNone;
map_slot_config[button_id].slot_btn->setText("");
map_slot_config[button_id].chan_display = "";
}
if (map_slot_config[button_id].rack_type == "Double1") {
map_slot_config[button_id].slot_type = "";
map_slot_config[button_id].rack_type = "0";
map_slot_config[button_id].slot_btn->setText("");
map_slot_config[button_id].chan_display = "";
map_slot_config[button_id + 1].slot_type = "";
map_slot_config[button_id + 1].rack_type = "0";
map_slot_config[button_id + 1].slot_btn->setText("");
map_slot_config[button_id + 1].chan_display = "";
} else if (map_slot_config[button_id].rack_type == "Double2") {
map_slot_config[button_id - 1].slot_type = "";
map_slot_config[button_id - 1].rack_type = "0";
map_slot_config[button_id - 1].slot_btn->setText("");
map_slot_config[button_id - 1].chan_display = "";
map_slot_config[button_id].slot_type = "";
map_slot_config[button_id].rack_type = "0";
map_slot_config[button_id].slot_btn->setText("");
map_slot_config[button_id].chan_display = "";
}
if (map_slot_config[button_id].rack_type == "Single") {
map_slot_config[button_id].slot_type = "";
map_slot_config[button_id].rack_type = "0";
map_slot_config[button_id].slot_btn->setText("");
map_slot_config[button_id].chan_display = "";
}
} else if (action->text() == "升级固件") {
sendUpgradePackage(button_id);
@ -527,9 +495,64 @@ void MainWindow::onMenuAction_relay() {
relay_setting->setWindowModality(Qt::ApplicationModal);
relay_setting->show();
}
uint8_t calculate_crc(uint8_t c, const QByteArray &data) {
uint8_t crc = c;
for (int i = 0; i < data.size(); ++i) {
crc += static_cast<uint8_t>(data[i]); // 累加每个字节
}
return crc;
}
void MainWindow::on_pushButton_save_clicked() {
ConfigMgr::Instance()->Save();
// 读取文件内容
QFile file(QCoreApplication::applicationDirPath() + "\\config\\tsi_config_file.json");
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open update file.";
return;
}
QByteArray fileData = file.readAll();
int fileSize = fileData.size();
if (fileSize > 10 * 1024 * 1024) {
QMessageBox::information(this, QStringLiteral("提示"), "文件大小超过10M请重新选择");
file.close();
return;
}
qDebug() << "fileSize" << fileSize ;
// 创建 PackageHead 结构体
PackageHead header = { {0xAA, 0x55, 0xAA}, kUploadConfigFile, fileSize, 0, {} };
// 计算文件的 CRC 校验和
header.crc = calculate_crc(0, fileData);
header.len = fileSize;
char *send_buf = NULL;
send_buf = (char *)malloc(sizeof(PackageHead) + fileData.size() + 1);
memset(send_buf, 0, sizeof(PackageHead) + fileData.size() + 1);
memcpy(send_buf, &header, sizeof(PackageHead));
memcpy(send_buf + sizeof(PackageHead), fileData.data(), fileData.size());
int length = sizeof(PackageHead) + fileData.size();
const int MAX_CHUNK_SIZE = 50 * 1024; // 50 KB
qint64 bytesSent = 0;
qint64 totalBytes = length;
qDebug() << "totalBytes" << totalBytes ;
while (bytesSent < totalBytes) {
qint64 chunkSize = 0;
if (MAX_CHUNK_SIZE < totalBytes - bytesSent) {
chunkSize = MAX_CHUNK_SIZE;
} else {
chunkSize = totalBytes - bytesSent;
}
qint64 bytesWritten = m_tcpClient->sendData(send_buf + bytesSent, chunkSize);
qDebug() << "bytesWritten" << bytesWritten << "bytesSent" << bytesSent << "chunkSize" << chunkSize ;
if (bytesWritten == -1) {
break;
}
bytesSent += bytesWritten;
}
qDebug() << "bytesSent" << bytesSent;
m_tcpClient->waitForRead();
file.close();
if (send_buf != NULL) {
free(send_buf);
}
}
void MainWindow::on_pushButton_open_clicked() {
@ -559,13 +582,6 @@ void MainWindow::on_pushButton_open_clicked() {
}
}
uint8_t calculate_crc(uint8_t c, const QByteArray &data) {
uint8_t crc = c;
for (int i = 0; i < data.size(); ++i) {
crc += static_cast<uint8_t>(data[i]); // 累加每个字节
}
return crc;
}
uint32_t myHtonl(uint32_t value) {
return ((value >> 24) & 0x000000FF) | // 提取最高的8位
@ -702,5 +718,31 @@ void MainWindow::readData(const QByteArray &data) {
statusBar()->showMessage("升级完成!", 3000); // 显示3秒
}
//qDebug() << "Server response: " << upgrade_resp.code;
} else if(header.cmd == kDownloadConfigFile){
//qDebug() << "header.len" << header.len;
char *config_file = NULL;
config_file = (char*)malloc(header.len + 1);
memset(config_file,0,header.len + 1);
memcpy(config_file, data.data() + sizeof(PackageHead), header.len);
QString filename_ = QCoreApplication::applicationDirPath() + "\\config\\tsi_config_file2.json";
//qDebug() << config_file ;
QFile file(filename_);
file.open(QIODevice::WriteOnly);
file.write(config_file,header.len);
file.close();
if(config_file != NULL)
free(config_file);
}
}
void MainWindow::on_pushButton_download_clicked()
{
PackageHead header = { {0xAA, 0x55, 0xAA}, kDownloadConfigFile, 1, 0, {} };
char send_buf[20] = {0};
memcpy(send_buf, (char *)&header, sizeof(PackageHead));
int length = sizeof(PackageHead);
qint64 bytesWritten = m_tcpClient->sendData(send_buf, length);
m_tcpClient->waitForRead();
qDebug() << "bytesWritten: " << bytesWritten;
}

View File

@ -72,5 +72,6 @@ private slots:
void on_pushButton_point_name_clicked();
void on_pushButton_save_clicked();
void on_pushButton_open_clicked();
void on_pushButton_download_clicked();
};
#endif // MAINWINDOW_H

View File

@ -122,7 +122,7 @@
<string/>
</property>
</widget>
<widget class="QPushButton" name="pushButton_23">
<widget class="QPushButton" name="pushButton_download">
<property name="geometry">
<rect>
<x>140</x>
@ -144,7 +144,7 @@
</size>
</property>
<property name="text">
<string/>
<string>下载</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_24">

View File

@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>触发配置</string>
</property>
<widget class="QGroupBox" name="groupBox_2">
<property name="geometry">