LINUX.ORG.RU

Виснет QSerialPort

 


1

2


serial.write("COMMAND");
serial.waitForBytesWritten();
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));
buffer[how_many-1] = '\0';
qDebug()<<buffer;

//вплоть до этой точки работает верно


serial.write("COMMAND2");
serial.waitForBytesWritten();
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));
buffer[how_many-1] = '\0';
qDebug()<<buffer;


//fail


serial.write("COMMAND");
serial.waitForBytesWritten();
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));
buffer[how_many-1] = '\0';
qDebug()<<buffer;

//ужу не работает

Файл выглядит как нормально выведенная строка (или частично?). Но после него уже другие комманды не проходят. Устройство работает правильно. Во всех случаях принятое количество символов заведомо меньше размера буфера, но во втором случае символов чуть больше, и, вероятно, приходят они с некоторой задержкой (около секунды).

ЧЯДНТ?

ты типа жалуешься или хвастаешься?

anonymous ()

qserialdevice не переводит COM в raw мод самостоятельно(Qserialport - переводит), эту нужно делать руками, из-за этого COM'у может стать плохо ибо встретил он в бинарном потоке данных управляющий символ.

dhampire ★★★ ()
Ответ на: комментарий от anonymous

я типа случайно слишком рано запостил сообщение

next_time ★★★★ ()

ещё момент: это консольное приложение

next_time ★★★★ ()
Ответ на: комментарий от next_time

Беда в том что этот класс выведет первые залетевшие в ответ байты. Чтобы получить ответ целиком надо до определенного времени еще почитывать байты (bytesAvailable), и если ничего нет через некоторое время - значит всё. Увы, только так.

I-Love-Microsoft ★★★★★ ()

на какой именно строчке виснет?

dib2 ★★★★★ ()
Ответ на: комментарий от next_time

Попробуй сигнал readyRead, я даже консольные проги пишу с сигналами-слотами, ничего страшного (стыдно когда видно =)))

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

+1
QSerialPort как и любой другой поток данных так пользовать нельзя. Процедура чтения должна обязательно либо ориентироваться на требуемый размер полученных данных либо на interchar timeout посылки.

dib2 ★★★★★ ()
Ответ на: комментарий от dib2

после попытки чтения во втором абзаце порт становится неюзабельным

next_time ★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

мне желательно ещё, чтобы оно тянуло минимум либ. хотя, сигналы-слоты, наверное, по-любому притянутся. так что, наверное, так и сделаю.

next_time ★★★★ ()
Ответ на: комментарий от next_time

Если у тебя уже QSerialPort то считай ничего дополнительного не добавится, лишь зря вкуснятина (сигналы-слоты) болтается но не юзается - а так будет использоваться.

I-Love-Microsoft ★★★★★ ()
void ComPort:writeDataSlot(const QByteArray& data)
{
        qint64 bytesWritten = m_serial->write(data);
        if (bytesWritten == -1) {
                output_to_log(QString("Failed to write the data to port %1, error: %2").arg(m_serial->portName()).arg(m_serial->errorString()));
        } else if (bytesWritten != data.size()) {
                output_to_log(QString("Failed to write all the data to port %1, error: %2").arg(m_serial->portName()).arg(m_serial->errorString()));
        } else if (!m_serial->waitForBytesWritten(5000)) {
                output_to_log(QString("Operation timed out or an error occurred for port %1, error: %2").arg(m_serial->portName()).arg(m_serial->errorString()));
        }
}

как минимум ты не проверяешь код возврата из write .... про сигнал-слоты уже написали

dhampire ★★★ ()
Последнее исправление: dhampire (всего исправлений: 1)
Ответ на: комментарий от dhampire

+100500, тем более в случае ошибки значение -1 значит 4 миллиарда для unsigned, и это еще если повезет не оказаться на 64-битной тачке ;) how_many - какой тип?

В общем, с кодом что-то явно не так.

QSerialport из состава Qt5 - очень хорошая реализация, с ней нет проблем. Однако скажу что я писал программу, которая должна была допускать пропадание порта (USB-Serial) и восстанавливать связь когда он вернется. Так вот в случае пропадания порта - QSerialport продолжал лишь делать видимость работы (не вылетала программа) но сигналы не шли таймеры не срабатывали (но загрузки ЦП не было) - одним словом программа не могла восстановить работу с портом, а QExtSerialport этого недостатка лишен.

I-Love-Microsoft ★★★★★ ()
Последнее исправление: I-Love-Microsoft (всего исправлений: 2)

Интересно, мне одному пришла идея использовать socat в качестве транспорта?

QProcess *p = new QProcess(this);
connect(p, readyReadStandardOutput(), this, data_in());
p->start("socat", "- /dev/ttyS0,b115200,raw,echo=0");

nanoolinux ★★★★ ()

вылечил, вставив задержку


serial.write("COMMAND2");
serial.waitForBytesWritten();
QThread::msleep(100); //магия
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));

если бы оно было парой строчек выше или ниже , я бы ещё понял, но тут-то оно как влияет? о_0

next_time ★★★★ ()

Про Event Loop слышали? Вот QSerialPort так же на него завязан.(конкретно - в реальности вы вообще не запишете ничего в порт пока не обработается EventLoop). Иными словами вам надо что бы EventLoop нормально работал, т.е. как костыль вставить принудительную обработку эвентлупа, а лучше просто сделать чтение по слоту ReadyToRead (или как-то так, точное незвание не помню) - а по-хорошему вы читать должны как раз только по ReadyToRead сигналу.

RiseOfDeath ★★★★ ()
Последнее исправление: RiseOfDeath (всего исправлений: 3)

Наивный, ты надеешься прочитать весь ответ одним read? Так не бывает, куски ответа обычно рандомной длины. Нужно читать и склеивать куски, пока в конце не будет оконечного символа. Я вообще буфер делал в 1 байт, ибо рандомная длина кусков заколебала.

anonymous ()
Ответ на: комментарий от RiseOfDeath

документации написано, что как раз QSerialPort умеет работать без EventLoop, с помощью waitForReadyRead. в принципе, меня уже убедили, что евенты лучше, но покамест оставлю как есть, ибо горит. позже переделаю.

next_time ★★★★ ()
Ответ на: комментарий от next_time

Ну известен, и что? Как это помешает ему прочитаться не за 1 раз? Если ты имел в виду размер буфера, то я не про тот, в который ты читаешь, а про тот, который setReadBufferSize().

anonymous ()
Ответ на: комментарий от next_time

Можно просто вызвать после записи QApplication::processEvents(); Но это костыль, а не нормальное решение.

RiseOfDeath ★★★★ ()
Последнее исправление: RiseOfDeath (всего исправлений: 2)
Ответ на: комментарий от I-Love-Microsoft

попробовал. та же фигня и почти лечится также. почему «почти» — выяснилось, что некоторые запросы замусориваются. и я уже хз, как лечить. за основу брал немного подпиленный пример из qt.

так что, проблема всё ещё актуальна, и походу, это баг qt.

next_time ★★★★ ()
Ответ на: комментарий от RiseOfDeath

не, не помогает, наоборот, частично помогло большие задержки ставить

next_time ★★★★ ()
Ответ на: комментарий от dhampire

в продакшен без обмотки проверками на ошибки пихать, конечно, нельзя. но подобные рода проверки только мешают во время отладки, поэтому я их ставлю в последнюю очередь. ну вернёт он не 9 а -1, ну вылетит во время отладки прога — так это пофиг, пока программа даже до альфа версии не дошла. в данном же частном случае, практика показала, что запись таки не фейлится, сообщение всегда доходит прекрасно до устройства, фейлится именно чтение.

next_time ★★★★ ()
Ответ на: комментарий от next_time

очевидно, и раньше беда, на самом деле, была в тотальном замусоривании/неполном считывании данных

next_time ★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

хотя не, поправил код — уже не мусорится, но всё равно задержки (слишком здоровые для времени записи) нужны. нахрена нам waitForBytesWritten() и waitForReadyRead(-1) тогда — непонятно.

next_time ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.