Здравствуйте! Работаю с com-port, и хочу сделать отправку и прием для нескольких портов.
В случае работы с одним портом предельно понятно, на каком-то уровне. Работаю с ним так:
#include "mainwindow.h"
#include "ui_mainwindow.h"
//----------------------------------------------------------------------------------------------------------------------------------------------------
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
m_ui(new Ui::MainWindow), m_timerWaitAnswer(new QTimer)
{
m_ui->setupUi(this);
//Получение списка портов и запись их в выпадающий список
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
m_ui->serialPortComboBox->addItem(info.portName());
// Отправка в сом-порт по нажатию на кнопку
connect(m_ui->sendComPortPushButton, SIGNAL(clicked(bool)), this, SLOT(writeComPort()));
// Подключаем чтение с порта по таймеру
connect(m_timerWaitAnswer, SIGNAL(timeout()), this, SLOT(readComPort()));
connect(m_ui->serialPortComboBox, SIGNAL(activated(QString)), this, SLOT(reopenComPort(QString)));
m_comPort = new QSerialPort;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
MainWindow::~MainWindow()
{
if(m_comPort->isOpen())
m_comPort->close();
delete m_ui;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
void MainWindow::openComPort(QString comName, QSerialPort::BaudRate baud, QSerialPort::DataBits dataBits, QSerialPort::Parity parity,
QSerialPort::StopBits stopBits, QSerialPort::FlowControl flowControl)
{
m_comPort->setPortName(comName);
// Настройка параметров com-порта
m_comPort->setBaudRate(baud);
m_comPort->setDataBits(dataBits);
m_comPort->setParity(parity);
m_comPort->setStopBits(stopBits);
m_comPort->setFlowControl(flowControl);
// Открываем com-порт. В случае неудачи, выводим ошибку в лог
if (!m_comPort->open(QIODevice::ReadWrite))
qDebug() << "failed";
else
qDebug() << "connected";
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
void MainWindow::readComPort()
{
m_waitAnswer = false;
QString data;
// Чтение данных и вывод
m_bufferRead.append(m_comPort->readAll());
qDebug() << m_comPort->readAll();
m_ui->textEdit->setText(m_bufferRead.data());
m_bufferRead.clear();
m_timerWaitAnswer->stop();
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
void MainWindow::writeComPort()
{
QByteArray toSend;
QString value = m_ui->sendComPortLineEdit->text();
if(value.isEmpty()) return;
toSend.append(value);
// Отправка в сом-порт
m_comPort->write(toSend);
m_ui->textEdit->setText(toSend);
// Запуск таймера ожидания ответа
m_timerWaitAnswer->start(m_ui->timeSpinBox->text().toInt());
m_waitAnswer = true;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
void MainWindow::reopenComPort(QString namePort)
{
m_comPort->close();
// Открываем новый com-порт
openComPort(namePort, QSerialPort::Baud9600, QSerialPort::Data8, QSerialPort::EvenParity,
QSerialPort::OneStop, QSerialPort::NoFlowControl);
}
Заголовочный файл:
<code lang="cpp">
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QTimer>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// Конструктор
explicit MainWindow(QWidget *parent = 0);
// Деструктор
~MainWindow();
public slots:
// Читает из com-порта
void readComPort();
// Записывает данные в com-порт
void writeComPort();
// Переоткрывает com-порт
void reopenComPort(QString namePort);
private:
// Форма окна
Ui::MainWindow *m_ui;
// Флаг ожидания ответа
bool m_waitAnswer;
// Открываемый com-порт
QSerialPort *m_comPort;
// Приемный буфер
QByteArray m_bufferRead;
// Таймер
QTimer *m_timerWaitAnswer;
// Открывает com-порт
void openComPort(QString comName, QSerialPort::BaudRate baud, QSerialPort::DataBits dataBits, QSerialPort::Parity parity,
QSerialPort::StopBits stopBits, QSerialPort::FlowControl flowControl);
};
#endif // MAINWINDOW_H
</code>
Так выглядит взаимодействие с одним портом:
<img src="https://habrastorage.org/webt/65/eb/f8/65ebf8a872479371143502.jpeg" alt="image"/>
В случае, когда работаем не с одним, а с двумя и более портами, как нужно организовать работу, чтобы все работало корректно?
Вопрос как в подходе, так как есть свои идеи, так и в некой реализации. Создавать несколько экземпляров com-портов - не гибко, если вдруг их количество увеличится.. Информация в интернетах, разумеется, есть, но не помогает прийти к какому-то решению для меня. Пробовал решить проблему следующим образом (пока без чтения и прочего):
<code lang="cpp">
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendToAllPorts()));
connectToAllPorts();
connect(this, SIGNAL(messageSentSuccessfully(QString)), this, SLOT(msgSentSuccessfully(QString)));
}
//------------------------------------------------------------------------------
MainWindow::~MainWindow()
{
delete ui;
}
//------------------------------------------------------------------------------
void MainWindow::msgSentSuccessfully(QString message)
{
qDebug() << "Сообщение успешно отправлено: " << message;
}
//------------------------------------------------------------------------------
void MainWindow::msgFailedToSend(QString message)
{
qDebug() << "Сообщение не удалось отправить: " << message;
}
//------------------------------------------------------------------------------
void MainWindow::sendMessage(QString message)
{
// Отправка сообщения на все порты
qDebug() << "Отправка сообщения: " << message;
// Проверка успешной отправки сообщения
bool messageSent = true; // Предположим, что сообщение успешно отправлено
if (messageSent) {
emit messageSentSuccessfully(message);
} else {
emit messageFailedToSend(message);
}
}
//------------------------------------------------------------------------------
void MainWindow::sendToAllPorts()
{
QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
message = "Hello, World!";
foreach (const QSerialPortInfo &portInfo, ports)
{
QSerialPort port;
port.setPort(portInfo);
if (port.open(QIODevice::WriteOnly))
{
qDebug() << "Sending message" << message << "to port" << portInfo.portName();
qint64 bytesWritten = port.write(message);
if (bytesWritten == -1)
{
qDebug() << "Failed to write to port" << portInfo.portName();
}
else
{
qDebug() << "Message sent to port" << portInfo.portName();
}
port.close();
}
else
{
qDebug() << "Failed to open port" << portInfo.portName();
}
}
}
//------------------------------------------------------------------------------
void MainWindow::connectToAllPorts()
{
QVector<QSerialPort*> ports; //availablePorts;
foreach (const QSerialPortInfo &portInfo, QSerialPortInfo::availablePorts())
{
QSerialPort *port = new QSerialPort(portInfo);
// Настройка параметров com-порта
m_comPort->setBaudRate(QSerialPort::Baud9600);
m_comPort->setDataBits(QSerialPort::Data8);
m_comPort->setParity(QSerialPort::EvenParity);
m_comPort->setStopBits(QSerialPort::OneStop);
m_comPort->setFlowControl(QSerialPort::NoFlowControl);
if (port->open(QIODevice::ReadWrite))
{
ports.append(port);
qDebug() << "Port " << portInfo.portName() << " opened successfully";
}
else
{
qDebug() << "Failed to open port " << portInfo.portName();
}
}
qDebug() << ports;
}
</code>
Заголовочный файл:
<code lang="cpp">
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSerialPortInfo>
#include <QSerialPort>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void sendMessage(QString message);
void msgSentSuccessfully(QString message);
void msgFailedToSend(QString message);
void ReadData();
signals:
void messageSentSuccessfully(const QString &message);
void messageFailedToSend(const QString &message);
private slots:
void sendToAllPorts();
private:
Ui::MainWindow *ui;
QList<QSerialPortInfo> ports;
QByteArray message;
QSerialPort *m_comPort;
void connectToAllPorts();
};
#endif // MAINWINDOW_H
</code>
При включении считываются доступные порты, записываются в QVector, через qDebug отображаю их и делаю автоматическое, на данный момент, подключение ко всем портам. Как впоследствии обращаться к ним для работы для отправки и приема?