QModbus в потоке выдает ошибки в Qt - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть рабочий поток (QThread), который собирает данные от приборов, которые подключены либо через RS232 (который работает нормально, это легко реализовать). Другой прибор подключен через RS485 и использует протокол Modbus, но, похоже, что сам QModbus работает в отдельном потоке, что делает необходимым подключение сигнала ответа от QModbus к слоту, который затем собирает ответ от QModbus, поэтому Я должен ждать, пока этот слот будет вызван и выполнен, для этого я должен убедиться, что мой поток входит в событие l oop, что мой слот может быть вызван, я сделал это так:

do
{
    QEventLoop(this).processEvents();
} while (!answerReceived);

Но это вызывает у меня тонны таких сообщений об ошибках в QtCreator:

QBasicTimer::start: Timers cannot be started from another thread

Я попробовал также эти два предложения здесь: Как сообщить QThread, что нужно дождаться окончания работы, а затем fini sh? но, к сожалению, я все еще получаю эти ошибки. Что я могу сделать, чтобы избавиться от этих ошибок, или я должен жить с этим?


Обновление.
Вот код соответствующих функций:

void Worker::requestValue(int address, int length)
{
    answerReceived = false;
    qDebug() << "Read values";
    read(address, length);
    do
    {
        QEventLoop(this).processEvents();
    } while (!answerReceived);
}

void Worker::read(int address, int length)
{
    if (!modbusDevice)
        return;
    if (auto *reply = modbusDevice->sendReadRequest(readRequest(address, length), 10)) {
        if (!reply->isFinished())
            connect(reply, &QModbusReply::finished, this, &Worker::onReceiveValues);
        else
            delete reply; // broadcast replies return immediately
    } else {
        qDebug() << tr("Read error: ") + modbusDevice->errorString();
    }
}

void Worker::onReceiveValues()
{
    auto reply = qobject_cast<QModbusReply *>(sender());
    if (!reply)
        return;

if (reply->error() == QModbusDevice::NoError) {
    const QModbusDataUnit unit = reply->result();
    QVector<quint16> receivedValues = unit.values();
    switch(answerType)
    {
    case AnswerType::Flow:
    {
        prominentPumvValues.flow = processFloatValue(receivedValues);
    }
        break;
    case AnswerType::Stroke:
    {
        prominentPumvValues.stroke = processFloatValue(receivedValues);
    }
        break;
    case AnswerType::Frequency:
        prominentPumvValues.frequency = receivedValues.at(0);
        break;
    case AnswerType::SerialNumber:
    {
        prominentPumvValues.serialNumber = processString(receivedValues);
    }
    default:
        break;
    }
} else if (reply->error() == QModbusDevice::ProtocolError) {
    qDebug() << tr("Read response error: %1 (Mobus exception: 0x%2)").
                                arg(reply->errorString()).
                                arg(reply->rawResult().exceptionCode(), -1, 16);
} else {
    qDebug() << tr("Read response error: %1 (code: 0x%2)").
                                arg(reply->errorString()).
                                arg(reply->error(), -1, 16);
}

reply->deleteLater();
answerReceived = true;
}

Я нашел эту ветку здесь: https://forum.qt.io/topic/82819/qbasictimer-start-timers-cannot-be-started-from-another-thread-issue/10 и изменил функцию чтения следующим образом:

void Worker::read(int address, int length)
{
    if (!modbusDevice)
        return;
    if (auto *reply = modbusDevice->sendReadRequest(readRequest(address, length), 10)) {
        if (!reply->isFinished())
        {
            qDebug() << "Reply not finished";
            qDebug() << "Connect: " << connect(reply, &QModbusReply::finished, [reply, this]() {
                qDebug() << "connect";
                if(reply->error() == QModbusClient::NoError)
                {
                    const QModbusDataUnit unit = reply->result();
                    receivedValues = unit.values();
                    qDebug() << "Lambda: " << receivedValues.length();
                }
                else
                    qDebug() << "Reply error";
                reply->deleteLater();
                qDebug() << "Bye";
            });
            qDebug() << "Ade";
        }
        else
        {
            qDebug() << "Reply finished";
            delete reply; // broadcast replies return immediately
        }
    } else {
        qDebug() << tr("Read error: ") + modbusDevice->errorString();
    }
    qDebug() <<receivedValues[0] << receivedValues[1];
}

Ответ соединения верен, но выглядит так код внутри лямбды не выполняется, внутри лямбды нет вывода функций qDebug ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...