1.运行结果

2. 主程序调用
- #include "dialog.h"
-
- #include
-
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- Dialog dialog;
- dialog.show();
- return app.exec();
- }
3. 对话框类实现
//dialog.h
- #ifndef DIALOG_H
- #define DIALOG_H
-
- #include "masterthread.h"
-
- #include
-
- QT_BEGIN_NAMESPACE
-
- class QLabel;
- class QLineEdit;
- class QSpinBox;
- class QPushButton;
- class QComboBox;
-
- QT_END_NAMESPACE
-
- class Dialog : public QDialog
- {
- Q_OBJECT
-
- public:
- explicit Dialog(QWidget *parent = nullptr);
-
- private slots:
- void transaction();
- void showResponse(const QString &s);
- void processError(const QString &s);
- void processTimeout(const QString &s);
-
- private:
- void setControlsEnabled(bool enable);
-
- private:
- int m_transactionCount = 0;
- QLabel *m_serialPortLabel = nullptr;
- QComboBox *m_serialPortComboBox = nullptr;
- QLabel *m_waitResponseLabel = nullptr;
- QSpinBox *m_waitResponseSpinBox = nullptr;
- QLabel *m_requestLabel = nullptr;
- QLineEdit *m_requestLineEdit = nullptr;
- QLabel *m_trafficLabel = nullptr;
- QLabel *m_statusLabel = nullptr;
- QPushButton *m_runButton = nullptr;
-
- MasterThread m_thread;
- };
-
- #endif // DIALOG_H
//dialog.cpp
- #include "dialog.h"
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- Dialog::Dialog(QWidget *parent) :
- QDialog(parent),
- m_serialPortLabel(new QLabel(tr("Serial port:"))),
- m_serialPortComboBox(new QComboBox),
- m_waitResponseLabel(new QLabel(tr("Wait response, msec:"))),
- m_waitResponseSpinBox(new QSpinBox),
- m_requestLabel(new QLabel(tr("Request:"))),
- m_requestLineEdit(new QLineEdit(tr("Who are you?"))),
- m_trafficLabel(new QLabel(tr("No traffic."))),
- m_statusLabel(new QLabel(tr("Status: Not running."))),
- m_runButton(new QPushButton(tr("Start")))
- {
- const auto infos = QSerialPortInfo::availablePorts();
- for (const QSerialPortInfo &info : infos)
- m_serialPortComboBox->addItem(info.portName());
-
- m_waitResponseSpinBox->setRange(0, 10000);
- m_waitResponseSpinBox->setValue(1000);
-
- auto mainLayout = new QGridLayout;
- mainLayout->addWidget(m_serialPortLabel, 0, 0);
- mainLayout->addWidget(m_serialPortComboBox, 0, 1);
- mainLayout->addWidget(m_waitResponseLabel, 1, 0);
- mainLayout->addWidget(m_waitResponseSpinBox, 1, 1);
- mainLayout->addWidget(m_runButton, 0, 2, 2, 1);
- mainLayout->addWidget(m_requestLabel, 2, 0);
- mainLayout->addWidget(m_requestLineEdit, 2, 1, 1, 3);
- mainLayout->addWidget(m_trafficLabel, 3, 0, 1, 4);
- mainLayout->addWidget(m_statusLabel, 4, 0, 1, 5);
- setLayout(mainLayout);
-
- setWindowTitle(tr("Blocking Master"));
- m_serialPortComboBox->setFocus();
-
- connect(m_runButton, &QPushButton::clicked, this, &Dialog::transaction);
- connect(&m_thread, &MasterThread::response, this, &Dialog::showResponse);
- connect(&m_thread, &MasterThread::error, this, &Dialog::processError);
- connect(&m_thread, &MasterThread::timeout, this, &Dialog::processTimeout);
- }
-
- void Dialog::transaction()
- {
- setControlsEnabled(false);
- m_statusLabel->setText(tr("Status: Running, connected to port %1.")
- .arg(m_serialPortComboBox->currentText()));
- m_thread.transaction(m_serialPortComboBox->currentText(),
- m_waitResponseSpinBox->value(),
- m_requestLineEdit->text());
- }
-
- void Dialog::showResponse(const QString &s)
- {
- setControlsEnabled(true);
- m_trafficLabel->setText(tr("Traffic, transaction #%1:"
- "\n\r-request: %2"
- "\n\r-response: %3")
- .arg(++m_transactionCount)
- .arg(m_requestLineEdit->text())
- .arg(s));
- }
-
- void Dialog::processError(const QString &s)
- {
- setControlsEnabled(true);
- m_statusLabel->setText(tr("Status: Not running, %1.").arg(s));
- m_trafficLabel->setText(tr("No traffic."));
- }
-
- void Dialog::processTimeout(const QString &s)
- {
- setControlsEnabled(true);
- m_statusLabel->setText(tr("Status: Running, %1.").arg(s));
- m_trafficLabel->setText(tr("No traffic."));
- }
-
- void Dialog::setControlsEnabled(bool enable)
- {
- m_runButton->setEnabled(enable);
- m_serialPortComboBox->setEnabled(enable);
- m_waitResponseSpinBox->setEnabled(enable);
- m_requestLineEdit->setEnabled(enable);
- }
4.串口服务器线程实现
//masterthread.h
- #ifndef MASTERTHREAD_H
- #define MASTERTHREAD_H
-
- #include
- #include
- #include
-
- class MasterThread : public QThread
- {
- Q_OBJECT
-
- public:
- explicit MasterThread(QObject *parent = nullptr);
- ~MasterThread();
-
- void transaction(const QString &portName, int waitTimeout, const QString &request);
- QByteArray HexStringToByteArray(QString HexString);
-
- signals:
- void response(const QString &s);
- void error(const QString &s);
- void timeout(const QString &s);
-
- private:
- void run() override;
-
- QString m_portName;
- QString m_request;
- int m_waitTimeout = 0;
- QMutex m_mutex;
- QWaitCondition m_cond;
- bool m_quit = false;
- };
-
- #endif // MASTERTHREAD_H
//masterthread.cpp
- #include "masterthread.h"
-
- #include
- #include
- #include
-
- MasterThread::MasterThread(QObject *parent) :
- QThread(parent)
- {
- }
-
- MasterThread::~MasterThread()
- {
- m_mutex.lock();
- m_quit = true;
- m_cond.wakeOne();
- m_mutex.unlock();
- wait();
- }
-
- void MasterThread::transaction(const QString &portName, int waitTimeout, const QString &request)
- {
- const QMutexLocker locker(&m_mutex);
- m_portName = portName;
- m_waitTimeout = waitTimeout;
- m_request = request;
- if (!isRunning())
- start();
- else
- m_cond.wakeOne();
- }
-
- void MasterThread::run()
- {
- bool currentPortNameChanged = false;
-
- m_mutex.lock();
- QString currentPortName;
- if (currentPortName != m_portName) {
- currentPortName = m_portName;
- currentPortNameChanged = true;
- }
-
- int currentWaitTimeout = m_waitTimeout;
- QString currentRequest = m_request;
- m_mutex.unlock();
- QSerialPort serial;
-
- if (currentPortName.isEmpty()) {
- emit error(tr("No port name specified"));
- return;
- }
-
- while (!m_quit) {
- if (currentPortNameChanged) {
- serial.close();
- serial.setPortName(currentPortName);
- serial.setBaudRate(57600);
- serial.setStopBits(QSerialPort::TwoStop);
-
- if (!serial.open(QIODevice::ReadWrite)) {
- emit error(tr("Can't open %1, error code %2")
- .arg(m_portName).arg(serial.error()));
- return;
- }
- }
- // write request
- //const QByteArray requestData = currentRequest.toUtf8();
- const QByteArray requestData = HexStringToByteArray(currentRequest);
-
- serial.write(requestData);
- if (serial.waitForBytesWritten(m_waitTimeout)) {
- // read response
- if (serial.waitForReadyRead(currentWaitTimeout)) {
- QByteArray responseData = serial.readAll();
- while (serial.waitForReadyRead(10))
- responseData += serial.readAll();
-
- const QString response = QString::fromUtf8(responseData);
- emit this->response(response);
- } else {
- emit timeout(tr("Wait read response timeout %1")
- .arg(QTime::currentTime().toString()));
- }
- } else {
- emit timeout(tr("Wait write request timeout %1")
- .arg(QTime::currentTime().toString()));
- }
- m_mutex.lock();
- m_cond.wait(&m_mutex);
- if (currentPortName != m_portName) {
- currentPortName = m_portName;
- currentPortNameChanged = true;
- } else {
- currentPortNameChanged = false;
- }
- currentWaitTimeout = m_waitTimeout;
- currentRequest = m_request;
- m_mutex.unlock();
- }
- }
-
- QByteArray MasterThread::HexStringToByteArray(QString HexString)
- {
- bool ok;
- QByteArray ret;
- HexString = HexString.trimmed();
- HexString = HexString.simplified();
- QStringList sl = HexString.split(" ");
-
- foreach (QString s, sl) {
- if(!s.isEmpty())
- {
- char c = s.toInt(&ok,16) & 0xFF;
- if(ok){
- ret.append(c);
- }else{
- qDebug()<<"invalid hex string"<
- }
- }
- }
- //qDebug()<
- return ret;
- }