Russian Qt Forum
Ноябрь 22, 2024, 21:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 3 4 [5] 6 7 ... 88   Вниз
  Печать  
Автор Тема: Создаю библиотеку для работы с последовательными портами. [УШЕЛ ИЗ ПРОЕКТА].  (Прочитано 785051 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #60 : Сентябрь 09, 2009, 09:17 »

Цитировать
1) В примере sreader Вы забыли поправить pro файл- пути старые, в результате пример не комплится без их правки вручную.
ну эт ладно

Цитировать
2) Пример reader работает, но через скаждую строчку ругается на
Цитировать
 Windows: NativeSerialEnginePrivate::nativeSelect->function WaitForSingleObject returned WAIT_TIMEOUT :  258
это не ошибка, так задумано... просто отключите вывод в консоль всего этого

Цитировать
Программа была запущена примерно 30 сек...после первого редирида больше ничего не делала...хотя данные идут по 2-5 сообщений в секунду
в файле abstractserial.cpp нужно поменять одну строчку в методе readData : d->emittedReadyRead = false;
Код:
qint64 AbstractSerial::readData(char *data, qint64 maxSize)
{
Q_D(AbstractSerial);

qint64 ret = d->serialEngine->read(data, maxSize);
if (ret < 0)
emitStatusString(EReadDataIO);
d->emittedReadyRead = false;
return ret;
}

« Последнее редактирование: Сентябрь 09, 2009, 09:20 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #61 : Сентябрь 09, 2009, 16:02 »

В общем вроде всё подправил, должно работать...

В аттаче архив прицепил Улыбающийся
« Последнее редактирование: Июнь 28, 2011, 14:39 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #62 : Сентябрь 09, 2009, 20:30 »

Обнаружились досадные баги:
1. В Linux - неправильно отрабатывает вызов ::select в методе
Код:
int NativeSerialEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
bool *selectForRead, bool *selectForWrite)
{
...
int ret = ::select(fd + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
...
}
см. файл nativeserialengine_unix.cpp

Неправильность заключается в том, что select почему-то всегда возвращает 1 !!! Хотя не должен этого делать.
Касяк заключается в присутствии &fdwrite, т.е. если это убрать и написать так:
Код:
int ret = ::select(fd + 1, &fdread, 0, 0, timeout < 0 ? 0 : &tv);
то все правильно отрабатывает! Убирая &fdwrite я тем самым отключаю возможность нотификации записи в порт...

В дальнейшем думаю вообще убрать нотификатор writeNotifier, т.к в принципе он не нужен нигде.. Нужна только возможность нотификации чтения!!!

2. В Windows - не всегда полностью отрабатывает нотификатор для чтения байт, суть например такая:

- в аппликухе /sreader или /reader я устанавливаю к примеру читать 4096 байт!!!
- в аппликухе /writer я передаю 4097 !!! байт!!!
- аппликуха /sreader или /reader вычитывает только 4096 байт! , хотя после этого она должна прочитать еше 1 байт! Улыбающийся

если же я /writer шлю 5000 байт - то аппликуха /sreader или /reader правильно их читает: сначала читает 4096 а потом 904 байта

я пока не разобрался в таком странном поведении

На текущий момент библа впринципе готова к употреблению, только нужно аккуратно следить за ней Улыбающийся





« Последнее редактирование: Июнь 28, 2011, 14:39 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #63 : Сентябрь 09, 2009, 21:29 »

Обнаружились досадные баги:
1. В Linux - неправильно отрабатывает вызов ::select в методе
Что значит баг? select работает точно согласно документации...
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #64 : Сентябрь 09, 2009, 21:50 »

Цитировать
Что значит баг? select работает точно согласно документации...

ну потому, что пстоянно срабатывает select и возвращает 1 !!! ведь по идее , если я не писал в порт до этого, то не должно ничего срабатывать, а вызов select должен возвратить 0 (т.е. таимаут)

а так получается, что если я вызваю waitForReadyRead(1000) (ожидаем в течении 1 секунды) - то он вечно зацикливается от того, что waitForReadOrWrite никогда не возвратит 0!!! а всегда возвращает 1

Код:
int NativeSerialEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
bool *selectForRead, bool *selectForWrite) const
{
fd_set fdread;
FD_ZERO(&fdread);
if (checkRead)
FD_SET(fd, &fdread);

fd_set fdwrite;
FD_ZERO(&fdwrite);
if (checkWrite)
FD_SET(fd, &fdwrite);


struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;

//int ret = ::select(fd + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); // <- ЕСЛИ ТАК - ТО НЕ РАБОТАЕТ, А ВСЕГДА ВОЗВРАЩАЕТ 1
int ret = ::select(fd + 1, &fdread, 0, 0, timeout < 0 ? 0 : &tv); // <- ЕСЛИ ТАК -ТО РАБОТАЕТ, НО БЕЗ НОТИФИКАЦИИ ЗАПИСИ

if (ret <= 0)
return ret;

*selectForRead = FD_ISSET(fd, &fdread);
*selectForWrite = FD_ISSET(fd, &fdwrite);

return ret;
}

Код:
bool NativeSerialEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut) const
{
Q_D(const NativeSerialEngine);

int ret = d->nativeSelect(msecs, checkRead, checkWrite, readyToRead, readyToWrite);

if (ret == 0) {
if (timedOut)
*timedOut = true;
if (checkRead) {
//
}
if (checkWrite) {
//
}
return false;
}
return ret > 0;
}

Код:
bool AbstractSerial::waitForReadyRead(int msecs)
{
Q_D(AbstractSerial);

if (!isOpen()) {
emitStatusString(EDeviceIsNotOpen);
return false;
}

QTime stopWatch;
stopWatch.start();

d->stopSerialNotifiers();
forever {
bool readyToRead = false;
bool readyToWrite = false;
if (!d->serialEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, true,
qt_timeout_value(msecs, stopWatch.elapsed()))) {
emitStatusString(EWaitReadyReadTimeout);
d->startSerialNotifiers();
return false;
}
if (readyToRead) {
d->waitForReadyReadCalled = true;
if (d->canReadNotification()) {
d->startSerialNotifiers();
return true;
}
}
if (readyToWrite)
d->canWriteNotification();
}
}

Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #65 : Сентябрь 09, 2009, 21:55 »

ну потому, что пстоянно срабатывает select и возвращает 1 !!! ведь по идее , если я не писал в порт до этого, то не должно ничего срабатывать, а вызов select должен возвратить 0 (т.е. таимаут)
Ты не правильно понимаешь. select возвращает количество установленных бит во всех (!) массивах.
Он тебе скорее всего сообщает что запись не приведет к блокировки.
Проверять результаты работы select нужно только по битовым массивам. Код возврата проверяется только на случай ошибки.
Записан
Denjs
Гость
« Ответ #66 : Сентябрь 09, 2009, 22:10 »

Возможно будет автору в помощь:
смотреть OTPD, класс
t_seriallink_otpd (каталог исходников OTPD/classes/hardware_comm)

кросс-платформенный класс, "тупо в лоб"  заточенный под свои нужды и нужды работы с чековым принтером.
Возможно будет полезен как источник идей для функций/интерфейсов, и как пример "компоненты транспортного уровня" -
там рядом t_tcpiplink_otpd лежит который полностью может заменить данный класс - у него полностью идентичный интерфейс - только строку параметров при запуске надо другую передать.
« Последнее редактирование: Сентябрь 09, 2009, 22:16 от Denjs » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #67 : Сентябрь 10, 2009, 10:00 »

Цитировать
Ты не правильно понимаешь. select возвращает количество установленных бит во всех (!) массивах.
Он тебе скорее всего сообщает что запись не приведет к блокировки.
Проверять результаты работы select нужно только по битовым массивам. Код возврата проверяется только на случай ошибки.

дык я эти методы полностью передрал из сокетов! Почему они там работают норматьно, а тут нет? Непонятно

в доке по селекту следующее:
Цитировать
writefds
 Этот набор мониторится на возможность записи данных в один или несколько дескрипторов. После возврата из select набор writefds будет очищен от всех дескрипторов, кроме тех, в которые можно немедленно записать данные функциями send() (для сокетов) или write() (для каналов pipe, файлов и сокетов).

т.е. получается что ничо непонятно... т.е. в моем случае срабатывает селект writefds, т.к. в порт уже можно записать данные и он свободен для записи... НО почему-то это не срабатывает в реализации QAbstractSocket... !?

2 Denjs, спасибо, а как там из CVS не качая исходники, просмотреть просто нужные файлы? А то у меня что-то не получилось Улыбающийся
А то неохото качать ~1.5 Mb
« Последнее редактирование: Сентябрь 10, 2009, 10:06 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #68 : Сентябрь 10, 2009, 11:36 »

kuzulis, потому что в Qt вызов waitForReadOrWrite из функции waitForReadyRead происходит с отключенным флажком checkWrite, если d->writeBuffer.isEmpty().
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #69 : Сентябрь 10, 2009, 11:40 »

Ну, да, я уже тож "догадался" об этом...

И все-таки вопрос к заинтересованным людям: убрать ли лучше мне в библиотеке нотификацию записи? т.к. в принципе судя по идеологии она не нужна тут вообще.

Я склоняюсь у "убиранию " лишнего.
Оставлю только испускание сигнала bytesWritten(nbytes)  и все...
« Последнее редактирование: Сентябрь 10, 2009, 11:43 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
yesrus
Гость
« Ответ #70 : Сентябрь 10, 2009, 18:31 »

Чуть-чуть потестил сегодня последний билд - нашел баг...Вы писали, что если после сигнана редирид считать не все из буфера (пришло 2 байта, я мы считываем 1 - read(1)) - после считывания редирид имитится еще раз....вообщем он не имитится...считываются только по 1 байту каждый раз когда приходит сообщение (оно больше 1 байта 100%) - что с остальными данным я не проверял..может они удаляются при чтении (это может объяснить почему после чтения не имитится редирид) либо они остаются в буфере-хз.
« Последнее редактирование: Сентябрь 10, 2009, 19:36 от yesrus » Записан
BRE
Гость
« Ответ #71 : Сентябрь 10, 2009, 18:55 »

Чуть-чуть потестил сегодня последний билд - нашел баг...Вы писали, что если после сигнана редирид считать не все из буфера (пришло 2 байта, я мы считываем 1 - read(1)) - после считывания редирид имитится еще раз....вообщем он не имитится...считываются только по 1 байту каждый раз когда приходит сообщение (оно больше 1 байта 100%) - что с отсальными данным и не проверял..может они удаляются при чтении 11 (это может объяснить почму после чтения не имитится редирид) либо они остаются в буфере-хз.
А под какой платформой тестил?
Записан
yesrus
Гость
« Ответ #72 : Сентябрь 10, 2009, 18:59 »

windows
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #73 : Сентябрь 11, 2009, 08:07 »

Цитировать
Чуть-чуть потестил сегодня последний билд - нашел баг...Вы писали, что если после сигнана редирид считать не все из буфера (пришло 2 байта, я мы считываем 1 - read(1)) - после считывания редирид имитится еще раз....вообщем он не имитится...считываются только по 1 байту каждый раз когда приходит сообщение (оно больше 1 байта 100%) - что с остальными данным я не проверял..может они удаляются при чтении (это может объяснить почему после чтения не имитится редирид) либо они остаются в буфере-хз.

в буфере байты остаются, т.к. если во второй раз опять в вашем случае послать например 1 байт - то считается 2 байта... т.е. это какой то касяк.. я пока не могу понять в чем дело.. Виндовс меня угнетает Грустный
Записан

ArchLinux x86_64 / Win10 64 bit
yesrus
Гость
« Ответ #74 : Сентябрь 11, 2009, 19:18 »

Вообщем потестил еще чуть-чуть...новости 2...
1) Если по ready read читать всю информацию из буфера то все ок...информация не теряется как в случае qt_comport!
2) несколько раз порт отваливался...в дебаге видел это:
Цитировать
Windows: NativeSerialEnginePrivate::nativeSelect->function WaitForSingleObject returned WAIT_TIMEOUT :  258 . Warning!
Readed:  "C8037F01B5"
Readed:  "7F04BF024187"
Windows: NativeSerialEnginePrivate::nativeLineStatus->function ClearCommError(err =  4 )
QIODevice::read: Called with maxSize < 0
Readed:  ""

Readed находится в блоке вызываемом по сигналу из readyread, выводит прочитаные данные в HEX.


Далее вопрос- как отключить дебаг...моя прога и так дебага выводит по 5 страниц за несколько секунд....а тут еще  библиотека спамит....кстати таймауты это вообще нормально ?
Записан
Страниц: 1 ... 3 4 [5] 6 7 ... 88   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.052 секунд. Запросов: 23.