添加获取通道CRC

This commit is contained in:
zhangsheng 2026-03-09 19:59:23 +08:00
parent 129d4bbc93
commit 1704ae9aa0
12 changed files with 599 additions and 1 deletions

View File

@ -10,10 +10,12 @@ CONFIG += c++11
SOURCES += \ SOURCES += \
MyTcpClient.cpp \ MyTcpClient.cpp \
TableHeaderView.cpp \
acceleration.cpp \ acceleration.cpp \
cardbase.cpp \ cardbase.cpp \
channel_1_2.cpp \ channel_1_2.cpp \
channel_3_4.cpp \ channel_3_4.cpp \
channel_crc.cpp \
common.cpp \ common.cpp \
config_mgr.cpp \ config_mgr.cpp \
connect.cpp \ connect.cpp \
@ -21,6 +23,7 @@ SOURCES += \
dc_output_channel.cpp \ dc_output_channel.cpp \
dc_outputs.cpp \ dc_outputs.cpp \
ethconfig.cpp \ ethconfig.cpp \
headerView.cpp \
keyphase.cpp \ keyphase.cpp \
keyphase_data.cpp \ keyphase_data.cpp \
macconfig.cpp \ macconfig.cpp \
@ -48,11 +51,13 @@ SOURCES += \
HEADERS += \ HEADERS += \
MyTcpClient.h \ MyTcpClient.h \
TableHeaderView.h \
acceleration.h \ acceleration.h \
acceleration_ds.h \ acceleration_ds.h \
cardbase.h \ cardbase.h \
channel_1_2.h \ channel_1_2.h \
channel_3_4.h \ channel_3_4.h \
channel_crc.h \
common.h \ common.h \
config_mgr.h \ config_mgr.h \
connect.h \ connect.h \
@ -62,6 +67,7 @@ HEADERS += \
dc_outputs.h \ dc_outputs.h \
displacement_ds.h \ displacement_ds.h \
ethconfig.h \ ethconfig.h \
headerView.h \
keyphase.h \ keyphase.h \
keyphase_data.h \ keyphase_data.h \
macconfig.h \ macconfig.h \
@ -92,6 +98,7 @@ FORMS += \
acceleration.ui \ acceleration.ui \
channel_1_2.ui \ channel_1_2.ui \
channel_3_4.ui \ channel_3_4.ui \
channel_crc.ui \
connect.ui \ connect.ui \
copy_channel.ui \ copy_channel.ui \
dc_output_channel.ui \ dc_output_channel.ui \

206
TableHeaderView.cpp Normal file
View File

@ -0,0 +1,206 @@
#include "TableHeaderView.h"
#include <QCheckBox>
#include <QApplication>
#include <QMouseEvent>
#include <qmessagebox.h>
#ifdef _MSC_VER
#pragma execution_character_set("utf-8")
#endif
#define CHECK_BOX_COLUMN 0
TableHeaderView::TableHeaderView(Qt::Orientation orientation, QWidget *parent)
: QHeaderView(orientation, parent),
m_bPressed(false),
m_bChecked(false),
m_bTristate(false),
m_bNoChange(false),
m_bMoving(false)
{
setSectionsClickable(true); // 响应鼠标
}
TableHeaderView::~TableHeaderView()
{
}
// 槽函数,用于更新复选框状态
void TableHeaderView::onStateChanged(int state)
{
if (state == Qt::PartiallyChecked) {
m_bTristate = true;
m_bNoChange = true;
}
else {
m_bNoChange = false;
}
m_bChecked = (state != Qt::Unchecked);
update();
}
// 绘制复选框
void TableHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == CHECK_BOX_COLUMN )
{
QStyleOptionButton option;
option.initFrom(this);
if (m_bChecked)
option.state |= QStyle::State_Sunken;
if (m_bTristate && m_bNoChange)
option.state |= QStyle::State_NoChange;
else
option.state |= m_bChecked ? QStyle::State_On : QStyle::State_Off;
if (testAttribute(Qt::WA_Hover) && underMouse()) {
if (m_bMoving)
option.state |= QStyle::State_MouseOver;
else
option.state &= ~QStyle::State_MouseOver;
}
QCheckBox checkBox;
option.iconSize = QSize(20, 20);
option.rect = rect;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &checkBox);
}
}
// 鼠标按下表头
void TableHeaderView::mousePressEvent(QMouseEvent *event)
{
int nColumn = logicalIndexAt(event->pos());
if ((event->buttons() & Qt::LeftButton) && (nColumn == CHECK_BOX_COLUMN))
{
m_bPressed = true;
}
else
{
QHeaderView::mousePressEvent(event);
}
}
// 鼠标从表头释放发送信号更新model数据
void TableHeaderView::mouseReleaseEvent(QMouseEvent *event)
{
if (m_bPressed)
{
if (m_bTristate && m_bNoChange)
{
m_bChecked = true;
m_bNoChange = false;
}
else
{
m_bChecked = !m_bChecked;
}
update();
Qt::CheckState state = m_bChecked ? Qt::Checked : Qt::Unchecked;
emit stateChanged(state);
updateSection(0);
}
else
{
QHeaderView::mouseReleaseEvent(event);
}
m_bPressed = false;
}
// 鼠标滑过、离开,更新复选框状态
bool TableHeaderView::event(QEvent *event)
{
updateSection(0);
if (event->type() == QEvent::Enter || event->type() == QEvent::Leave)
{
QMouseEvent *pEvent = static_cast<QMouseEvent *>(event);
int nColumn = logicalIndexAt(pEvent->x());
if (nColumn == CHECK_BOX_COLUMN)
{
m_bMoving = (event->type() == QEvent::Enter);
update();
return true;
}
}
return QHeaderView::event(event);
}
CheckBoxDelegate::CheckBoxDelegate(QObject *parent) :QStyledItemDelegate(parent)
{
}
CheckBoxDelegate::~CheckBoxDelegate()
{
}
// 绘制复选框
void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
QStyledItemDelegate::paint(painter, viewOption, index);
if (index.column() == CHECK_BOX_COLUMN )
{
bool data = index.model()->data(index, Qt::UserRole).toBool();
QStyleOptionButton checkBoxStyle;
checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;
checkBoxStyle.state |= QStyle::State_Enabled;
checkBoxStyle.iconSize = QSize(20, 20);
checkBoxStyle.rect = option.rect;
QCheckBox checkBox;
checkBoxStyle.iconSize = QSize(20, 20);
checkBoxStyle.rect = option.rect;
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox);
checkBox.setEnabled(false);
}
}
// 响应鼠标事件,更新数据
bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
QRect decorationRect = option.rect;
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos()))
{
if (index.column() == CHECK_BOX_COLUMN )
{
bool data = model->data(index, Qt::UserRole).toBool();
model->setData(index, !data, Qt::UserRole);
}
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}

57
TableHeaderView.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef CCHECKBOXMODEL_H
#define CCHECKBOXMODEL_H
#include <QAbstractTableModel>
#include <QStyledItemDelegate>
#include <QEvent>
#include <QHeaderView>
#include <QPainter>
class TableHeaderView :public QHeaderView
{
Q_OBJECT
public:
TableHeaderView(Qt::Orientation orientation, QWidget *parent);
~TableHeaderView();
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
bool event(QEvent *e) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
public slots:
void onStateChanged(int state);
signals:
void stateChanged(int state);
private:
bool m_bPressed;
bool m_bChecked;
bool m_bTristate;
bool m_bNoChange;
bool m_bMoving;
};
class CheckBoxDelegate :public QStyledItemDelegate
{
Q_OBJECT
public:
CheckBoxDelegate(QObject *parent);
~CheckBoxDelegate();
// painting
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
protected:
bool editorEvent(QEvent *event, QAbstractItemModel *model,
const QStyleOptionViewItem &option, const QModelIndex &index);
};
#endif // TABLE_MODEL_H

73
channel_crc.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "channel_crc.h"
#include "ui_channel_crc.h"
#include "config_mgr.h"
#include "data_config.h"
ChannelCRC::ChannelCRC(QWidget *parent) :
QWidget(parent),
ui(new Ui::ChannelCRC)
{
ui->setupUi(this);
initable();
m_tcpClient = MyTcpClient::instance();
connect(m_tcpClient, SIGNAL(dataReceived(const QByteArray &)), this, SLOT(readData(const QByteArray &)));
}
ChannelCRC::~ChannelCRC()
{
delete ui;
}
void ChannelCRC::initable()
{
headerStr = QObject::tr("板卡,通道1,通道2,通道3,通道4");
myHeader = new TableHeaderView(Qt::Horizontal, ui->tableView);
model = new QStandardItemModel(ui->tableView);
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
QStringList headerList = headerStr.split(",");
model->setHorizontalHeaderLabels(headerList);
model->setColumnCount(headerList.size());
ui->tableView->setModel(model);
}
void ChannelCRC::on_pushButton_get_clicked()
{
model->removeRows(0, model->rowCount());
int rows = 0;
for (int slot = 1; slot <= SLOT_NUM; slot ++ ) {
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(slot);
if(base_ptr == nullptr)
continue;
if(base_ptr->card_type_ == kCardVibSingle ||
base_ptr->card_type_ == kCardSpeedSingle ||
base_ptr->card_type_ == kCardKeyphaseSingle){
for (int ch = 1 ; ch <= 4 ; ch ++ ) {
model->setRowCount(rows + 1);
model->setData(model->index(rows,0,QModelIndex()),slot);
rows_slot[slot] = rows;
GetChannelCRCCountReq get_ch_crc_req = { {0xAA, 0x55, 0xAA}, kGetChannelCRCValue, 1,(uint8_t)slot,(uint8_t)ch };
int length = sizeof(GetChannelCRCCountReq);
qint64 bytesWritten = m_tcpClient->sendData((char*)&get_ch_crc_req, length);
m_tcpClient->waitForRead();
qDebug() << "bytesWritten: " << bytesWritten;
}
rows ++ ;
}
}
}
void ChannelCRC::readData(const QByteArray &data) {
qDebug() << "Received from server111:" << data;
uint8_t cmd = data[3];
if (cmd == kGetChannelCRCValue) {
GetChannelCRCCountRsp get_ch_crc_rsp;
memcpy(&get_ch_crc_rsp, data.data(), sizeof(GetChannelCRCCountRsp));
qDebug() << "get_ch_crc_rsp code" << get_ch_crc_rsp.code << get_ch_crc_rsp.card_id << get_ch_crc_rsp.channel_id << get_ch_crc_rsp.count << rows_slot[(int)get_ch_crc_rsp.card_id] ;
model->setData(model->index(rows_slot[(int)get_ch_crc_rsp.card_id],((int)get_ch_crc_rsp.channel_id),QModelIndex()),get_ch_crc_rsp.count);
}
}

36
channel_crc.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef CHANNEL_CRC_H
#define CHANNEL_CRC_H
#include <QWidget>
#include <QStandardItemModel> //数据模型类
#include <QMessageBox>
#include "headerView.h"
#include "TableHeaderView.h"
#include "MyTcpClient.h"
namespace Ui {
class ChannelCRC;
}
class ChannelCRC : public QWidget
{
Q_OBJECT
public:
explicit ChannelCRC(QWidget *parent = nullptr);
~ChannelCRC();
private slots:
void on_pushButton_get_clicked();
void readData(const QByteArray&);
private:
Ui::ChannelCRC *ui;
TableHeaderView *myHeader;
QStandardItemModel *model;
QString headerStr ;
MyTcpClient* m_tcpClient;
QMap<int,int> rows_slot;//<row,slot>
void initable();
};
#endif // CHANNEL_CRC_H

59
channel_crc.ui Normal file
View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChannelCRC</class>
<widget class="QWidget" name="ChannelCRC">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>766</width>
<height>519</height>
</rect>
</property>
<property name="windowTitle">
<string>获取通道CRC</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<widget class="QPushButton" name="pushButton_get">
<property name="geometry">
<rect>
<x>650</x>
<y>50</y>
<width>81</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>获取</string>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTableView" name="tableView"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -239,6 +239,7 @@ enum CMTCommand {
kGetVoltageRangeValue = 33, // 获取子板动态电压范围 kGetVoltageRangeValue = 33, // 获取子板动态电压范围
kGetVibAuxProcessVersion = 34, kGetVibAuxProcessVersion = 34,
kGetProcessID = 38, // 获取进程号 kGetProcessID = 38, // 获取进程号
kGetChannelCRCValue = 39, // 获取振动与转速板通道的CRC计数
kGetProductInfo = 101, // 获取产品信息 kGetProductInfo = 101, // 获取产品信息
kSetProductInfo = 102 // 填写产品信息 kSetProductInfo = 102 // 填写产品信息
}; };
@ -976,6 +977,24 @@ typedef struct {
uint8_t code; // 0: 成功, 1失败 uint8_t code; // 0: 成功, 1失败
} SetProductInfoRsp; } SetProductInfoRsp;
typedef struct {
uint8_t head[3]; // 固定值0xAA55AA
uint8_t cmd; // kGetChannelCRCValue
uint8_t version; // 版本号默认为1
uint8_t card_id;
uint8_t channel_id;
} GetChannelCRCCountReq;
typedef struct {
uint8_t head[3]; // 固定值0xAA55AA
uint8_t cmd; // kGetChannelCRCValue
uint8_t version; // 版本号默认为1
uint8_t code;
uint8_t card_id;
uint8_t channel_id;
uint32_t count; // crc计数值
} GetChannelCRCCountRsp;
struct BaseHeader { struct BaseHeader {
uint8_t head[3]; // 固定 0xAA 0x55 0xAA uint8_t head[3]; // 固定 0xAA 0x55 0xAA
uint8_t cmd; uint8_t cmd;

75
headerView.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "headerView.h"
#include <QPainter>
#include <QCheckBox>
#include <QDebug>
CHeaderView::CHeaderView(Qt::Orientation orientation, QWidget *parent)
: QHeaderView(orientation, parent)
{
//设置Section可点击若不设置则不能发出sectionClicked信号
this->setSectionsClickable(true);
//当发出sectionClicked就进入匿名函数
connect(this, &CHeaderView::sectionClicked, [=](int logicalIndex)
{
//判断map容器是否包含当前点击列包含则更新并发出columnSectionClicked
if(m_columpnCheckedMap.contains(logicalIndex))
{
//更新当前值
m_columpnCheckedMap[logicalIndex] = !m_columpnCheckedMap[logicalIndex];
//发出信号
emit columnSectionClicked(logicalIndex, m_columpnCheckedMap[logicalIndex]);
}
});
}
void CHeaderView::setColumnCheckable(int column, bool checkable)
{
//当可选值为true
if(checkable)
{
//将指定列添加到map容器中
m_columpnCheckedMap[column] = false;
}
else if(m_columpnCheckedMap.contains(column)) //当可选值为false且map容器包含指定列
{
//移除指定列
m_columpnCheckedMap.remove(column);
}
}
bool CHeaderView::getColumnCheckable(int column)
{
return m_columpnCheckedMap[column];
}
void CHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
qDebug()<<"paintSection" << endl;
painter->save(); //保存当前画笔状态
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore(); //恢复保存的画笔状态
//当map容器包含当前列才绘制复选框
if(m_columpnCheckedMap.contains(logicalIndex))
{
//创建样式对象并设置区域
QStyleOptionButton styleOption;
styleOption.rect = rect.adjusted(10, 0, 0, 0);
styleOption.state = QStyle::State_Enabled;
//根据map中的值设置状态
if(m_columpnCheckedMap[logicalIndex])
{
styleOption.state |= QStyle::State_On;
}
else
{
styleOption.state |= QStyle::State_Off;
}
//调用this的style对象绘制复选框
this->style()->drawControl(QStyle::CE_CheckBox, &styleOption, painter);
}
}

47
headerView.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef HEADERVIEW_H
#define HEADERVIEW_H
#include <QObject>
#include <QHeaderView>
#include <QMap>
class CHeaderView : public QHeaderView
{
Q_OBJECT
public:
/**
* @brief CHeaderView * @param orientation
* @param parent
*/
CHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr);
/**
* @brief setColumnCheckable * @param column * @param checkable */
void setColumnCheckable(int column, bool checkable);
bool getColumnCheckable(int column);
signals:
/**
* @brief columnSectionClicked Section鐐瑰嚮淇彿
* @param logicalIndex
* @param checked */
void columnSectionClicked(int logicalIndex, bool checked);
// QHeaderView interface
protected:
/**
* @brief paintSection
* @param painter
* @param rect
* @param logicalIndex
*/
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
private:
QMap<int, bool> m_columpnCheckedMap; //鍖呭惈澶嶉€夋鍒楃殑map瀹瑰櫒
};
#endif // HEADERVIEW_H

View File

@ -32,6 +32,7 @@
#include <QDesktopServices> #include <QDesktopServices>
#include <QUrl> #include <QUrl>
#include <QFileInfo> #include <QFileInfo>
#include "channel_crc.h"
QString g_strServerIp; QString g_strServerIp;
QString g_version; QString g_version;
@ -113,6 +114,7 @@ MainWindow::MainWindow(QWidget *parent)
QObject::connect(ui->action_get_deviceID, &QAction::triggered, this, &MainWindow::onGetDeviceID); QObject::connect(ui->action_get_deviceID, &QAction::triggered, this, &MainWindow::onGetDeviceID);
QObject::connect(ui->action_close, &QAction::triggered, this, &MainWindow::onCloseConfig); QObject::connect(ui->action_close, &QAction::triggered, this, &MainWindow::onCloseConfig);
QObject::connect(ui->action_user_manual, &QAction::triggered, this, &MainWindow::onOpenUserManual); QObject::connect(ui->action_user_manual, &QAction::triggered, this, &MainWindow::onOpenUserManual);
QObject::connect(ui->action_get_channel_crc, &QAction::triggered, this, &MainWindow::onGetChannelCRC);
QSettings settingsread(QCoreApplication::applicationDirPath() + "\\config\\config.ini", QSettings::IniFormat); QSettings settingsread(QCoreApplication::applicationDirPath() + "\\config\\config.ini", QSettings::IniFormat);
g_strServerIp = settingsread.value("Server/IP").toString(); g_strServerIp = settingsread.value("Server/IP").toString();
@ -122,7 +124,7 @@ MainWindow::MainWindow(QWidget *parent)
//qInstallMessageHandler(messageHandler); //qInstallMessageHandler(messageHandler);
#endif #endif
QDate buildDate = QLocale( QLocale::English ).toDate( QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); QDate buildDate = QLocale( QLocale::English ).toDate( QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy");
QString Version = "V1.0_" + buildDate.toString("yyyyMMdd") + "_8102"; QString Version = "V1.0_" + buildDate.toString("yyyyMMdd") + "_129d";
ui->label_version->setText(Version); ui->label_version->setText(Version);
} }
@ -1361,6 +1363,16 @@ void MainWindow::UploadConfigFile(uint8_t sub_cmd){
free(send_buf); free(send_buf);
} }
} }
void MainWindow::onGetChannelCRC(){
if(tsi_config_file == ""){
QMessageBox::warning(this, QStringLiteral("警告"), "请先打开配置!");
return;
}
ChannelCRC *channel_crc = new ChannelCRC();
channel_crc->setWindowModality(Qt::ApplicationModal);
channel_crc->show();
}
void MainWindow::on_pushButton_upload_clicked(){ void MainWindow::on_pushButton_upload_clicked(){
UploadConfigFile(0x0); UploadConfigFile(0x0);
} }

View File

@ -87,6 +87,7 @@ private slots:
void onGetDeviceID(); void onGetDeviceID();
void onCloseConfig(); void onCloseConfig();
void onOpenUserManual(); void onOpenUserManual();
void onGetChannelCRC();
void onMenuActionTriggered(); void onMenuActionTriggered();

View File

@ -1117,6 +1117,7 @@
<addaction name="action_mqtt"/> <addaction name="action_mqtt"/>
<addaction name="action_deviveID"/> <addaction name="action_deviveID"/>
<addaction name="action_get_deviceID"/> <addaction name="action_get_deviceID"/>
<addaction name="action_get_channel_crc"/>
</widget> </widget>
<addaction name="menu_start"/> <addaction name="menu_start"/>
<addaction name="menu_tool"/> <addaction name="menu_tool"/>
@ -1198,6 +1199,11 @@
<string>使用手册</string> <string>使用手册</string>
</property> </property>
</action> </action>
<action name="action_get_channel_crc">
<property name="text">
<string>获取通道CRC</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>