Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Обсуждение исходников с сайта _ QSerialDevice - Библиотека для работы с COM-портами

Автор: kuzulis 1.7.2009, 20:05

Доброго времени суток!

Я создал библиотеку для работы с последовательными портами, которая является альтернативой QextSerialPort и хочу выложить её на этот ресурс..
На главной странице этого сайта написано, что если я хочу чем-то поделиться - то я должен в соответствующем разделе форума об этом заявить.. так вот вопрос: ЧТО это за раздел? И как мне это сделать?

Автор: Litkevich Yuriy 1.7.2009, 21:05

Сайт:
В боковой панели сайта (http://www.crossplatform.ru/) выбери "Создать материал" -> "Исходники", заполни необходимые.
Если не видишь пункта создать материал, то залогинься на сайте.

Форум:
Административный -> Crossplatform.ru - все о нем -> Обсуждение исходников с сайта

Автор: ViGOur 1.7.2009, 22:28

На сайте не нужно логинится, достаточно быть залогиненым на форуме и после этого зайти на сайт.

Автор: kuzulis 2.7.2009, 9:38

Всем спасибо! Отправил запрос.. ждемс :)

Автор: Litkevich Yuriy 2.7.2009, 9:52

Цитата(kuzulis @ 2.7.2009, 13:38) *
Отправил запрос..
какой запрос?

Автор: kuzulis 2.7.2009, 10:35

ну типа с описанием либы , и там сказали что ответ ждать нужно 72 часа :)

ой! я ошибся.. я на fireforge.net отправил ... 8)

ЗЫ: заработался совсем

Автор: kuzulis 3.7.2009, 7:30

Всё, теперь и на crossplatform.ru я послал запрос :)

Автор: Litkevich Yuriy 3.7.2009, 7:56

Цитата(kuzulis @ 3.7.2009, 11:30) *
послал запрос
у нас нет ни каких запросов, просто пишешь и всё.

См. ещё моё сообщение №2, создай в указаном подфоруме тему. А на сайте сделай ссылку ( в поле "Обсудить на форуме:") на тему в форуме.
Тогда будешь иметь возможность обратной связи с пользователями.

(Посмотри как делает IMPOMEZIA, для своейго чата http://www.crossplatform.ru/node/856)


П.С. Новости на сайте ты аж 2 сделал

Автор: ViGOur 3.7.2009, 9:21

kuzulis, добавил ссылки скачать и обсудить на форуме...

Автор: CrazyDeath 10.7.2009, 1:37

kuzulis доброго дня суток.
увидел сегодня сообщение об альтернативе QextSerialPort
Просмотрев ваши исходники ничего нового, я не увидел, более того
называть вашу библиотеку альтернативой QextSerialPort
не совсем корректно, структура классов и исходников
одинаковая как и у библиотеке QextSerialPort.
Намного логичнее было бы оформить ваш труд ввиде
дополнительного класса для QextSerialPort.
Также вы пишете что

Цитата
QSerialDevice - реализует:
- асинхронный режим работы с последовательным портом


QextSerialPort вполне спокойно справляется с асинхронным режимом работы.
Так же я абсолютно не понял преимущества QSerialDevice перед QextSerialPort.

Автор: Litkevich Yuriy 10.7.2009, 1:45

Цитата(CrazyDeath @ 10.7.2009, 5:37) *
QextSerialPort вполне спокойно справляется с асинхронным режимом работы.
в версии qextserialport-1.1 асинхрон был написан только для виндовоза, да и тот закоментирован, как сейчас даже не знаю.
А QSerialDevice, так и не попробовал.

Автор: CrazyDeath 10.7.2009, 21:42

Наверно я делаю, что то не правильно но у меня работает асинхронный режим.
правда библиотека qextserialport из CVS.
http://qextserialport.cvs.sourceforge.net/qextserialport/

Автор: kuzulis 13.7.2009, 10:48

Цитата
увидел сегодня сообщение об альтернативе QextSerialPort
Просмотрев ваши исходники ничего нового, я не увидел, более того
называть вашу библиотеку альтернативой QextSerialPort
не совсем корректно, структура классов и исходников
одинаковая как и у библиотеке QextSerialPort.

Ну дык делал я её в основном брав исходники QextSerialPort . И я сделал максимально аналогичнее :)
И кстати я в cvs не смотрел, а делал на основе qextserialport-1.1.tar.gz

Цитата
Намного логичнее было бы оформить ваш труд ввиде
дополнительного класса для QextSerialPort.

Неа, не согласен.

Цитата
QextSerialPort вполне спокойно справляется с асинхронным режимом работы.

ну если считать, что задействуется структура OVERLAPPED - то можно согласится

Цитата
Так же я абсолютно не понял преимущества QSerialDevice перед QextSerialPort.

Для QextSerialPort
1. теряет байты при приеме - это раз (у меня по крайней мере)
2. не реализован метод ожидания прихода байтов
3. не полностью реализован в принципе асинхронный режим.. т.к. под асинхронным режимом подразумевается еще , помимо OVERLAPPED, и то, что операция чтения должна возвращатся немедленно!
4. И вообще не полностью используется функционал ядра при работе с последовательным устройством.

И я никого не заставляю использовать QSerialDevice, каждый выбирает сам ! Я просто иногда советую сравнить.

ЗЫ: я могу и еще накопать минусов QextSerialPort :) По крайней мере для МЕНЯ в моих проектах - QextSerialPort не нужен!

Автор: CrazyDeath 13.7.2009, 21:08

Цитата
1. теряет байты при приеме - это раз (у меня по крайней мере)

У меня на работе, тестирование QextSerialPort проводилось на довольно разном оборудывании от простых
встраиваемых компов до экзотических moxa плат
потерь или ошибок выше нормы не наблюдалось(1 -2 байта за 48 часов),
хотя скоро буду реализовывать протокол обмена
с тактом 5 милисекунд вот тогда все точно станет ясно.
Цитата
2. не реализован метод ожидания прихода байтов
3. не полностью реализован в принципе асинхронный режим.. т.к. под асинхронным режимом подразумевается еще , помимо OVERLAPPED, и то, что операция чтения должна возвращатся немедленно!

Посмотри на этот костыль для QextSerialPort http://www.qt-apps.org/content/show.php/QT_comport?content=95246, там все работает через события.
Цитата
не полностью используется функционал ядра

можно поподробнее, какой именно функционал.

Автор: kuzulis 14.7.2009, 7:54

Цитата
У меня на работе, тестирование QextSerialPort проводилось на довольно разном оборудывании от простых
встраиваемых компов до экзотических moxa плат
потерь или ошибок выше нормы не наблюдалось(1 -2 байта за 48 часов),
хотя скоро буду реализовывать протокол обмена
с тактом 5 милисекунд вот тогда все точно станет ясно.

А у меня в библиотеке не теряет ничего!
Ты в QextSerialPort попробуй прочитай 1000 байт - и увидиш всю прелесть ;)

Цитата
Посмотри на этот костыль для QextSerialPort Qt_comport, там все работает через события.

Я видел уже это... Считаю что реализовано действительно через "костыль":
/*QReceiveThread*/
void ReceiveThread::run()
{
    int count;
    forever
    {
        msleep(1);
        mutex.lock();
        count = comport->bytesAvailable();
        mutex.unlock();
        if (0 < count)
        {
            emit newDataInPortThread(count);
            QTime timedb;
            qDebug()<<"thread count= "<<count<<"time= "<<"\t"<<timedb.currentTime().second()<<" "<<timedb.currentTime().msec();
        }
    }
}


и сравни, как сделано у меня :) !

Цитата
можно поподробнее, какой именно функционал.

имеется ввиду для Win32 использование объектов ядра типа WaitFor и т.п. , а для *.nix select и т.п. .. что более правильно чем использования пококов и т.п. для ожидания прихода байтов и т.п.

кроме того у меня сделаны проверни возвращаемых значений всех функций, чтобы можно было легко диагностировать где случился касяк!
т.к. я создавал библиотеку для более "продвинутого" использования для разнообразных целей - а не так как авторы QextSerialPort и Qt_comport типа чтобы показать что типа что-то работает и то.. работает ли? :)

ИМХО!

Автор: CrazyDeath 15.7.2009, 1:14

Цитата
попробуй прочитай 1000 байт

ты не понял у меня идут потери 1 байт на 4gb,
то есть около 24 часов работы на скоросте 960kb(на moxa плате)
и не повине библиотеки а из-за аппаратуры,
но это норма, всегда есть ошибки.
В usb или tcp/ip на уровне протокола
идет автоматическая коррекция ошибок.
в uart этого нет, по этому люди и удивляются,
а потом реализовывают нормальный протокол обмена.


Цитата
while (1) {
if (MyDevice->waitForReadyRead(rrto)) {
ba.clear();
ba=MyDevice->read(len);
qDebug() << "Readed is : " << ba.size() << " bytes";
cout << "Rx : ";
printDataToHex(ba);
}
else {
qDebug() << "Timeout read data in time : " << QTime::currentTime();
}

Ну под это, тоже нужно создовать поток.
waitForReadyRead штука конечно хорошая,
но посути делает тоже самое что костыль Qt_comport,
только на уровне ядра системы, что намного лучше,
и теперь возвращаемся с чего начали

Цитата
Намного логичнее было бы оформить ваш труд ввиде
дополнительного класса для QextSerialPort.


Цитата
а не так как авторы QextSerialPort и Qt_comport типа чтобы показать что типа что-то работает и то.. работает ли?

Поверь мне на слово, есть очень много проектов которые используют QextSerialPort, и у них все работает.

Автор: BRE 15.7.2009, 7:30

Цитата(kuzulis @ 14.7.2009, 8:54) *
имеется ввиду для Win32 использование объектов ядра типа WaitFor и т.п. , а для *.nix select и т.п. .. что более правильно чем использования пококов и т.п. для ожидания прихода байтов и т.п.

Не знаю как в венде, а под линуксом для это использовал QSocketNotifier. Это встроенный в Qt механизм для select. Посмотри, может под линукс и Mac проще сделать через него.

Автор: kuzulis 15.9.2009, 8:52

Тихо и незаметно вышла в свет новая версия замечательной кросс платформенной библиотеки для работы с последовательными портами (устройствами) QSerialDevice v. 0.1.0

В этой версии очень много изменений в отличии от версии 0.0.3, можно сказать, что версия 0.1.0 написана практически с нуля!

Документацию по библиотеке можно найти в самом архиве.

Скачать можно тут:
http://fireforge.net/projects/qserialdevice/
и
http://qt-apps.org/content/show.php?content=112039

Автор: oldcolony 1.10.2009, 13:00

Библиотека хорошая,мне подошла лучше,чем qextserial, но хотелось бы ,чтобы автор разобрался с такой багой. Для проверки переделал пример qespta из qetxserial с применением этой либы. В нем экземпляр порта идет как поле обьекта. Так вот создание и инициализация в конструкторе идет- а вот дальше- любое обращение, и вылет. Чего-то в конструкторе AbstractSerial напутано. Если вместо члена класса обьявить порт как глобальную переменную- все окей.

Автор: Elfinit 3.10.2009, 23:29

Что-то не вижу я на главной "Создать материал". Хотел поделиться простой-примитивной тулзой для просмотра exif-метаданных изображения.

Автор: ViGOur 4.10.2009, 9:55

Я пока отключил общую авторизацию сайта и форума, ибо глючит она.
Немного подождете и я перенесу все на новую версию сайта и все будет ок. :)

Автор: rcdimon 29.10.2009, 21:47

Наблюдаются проблемы при работе с виртуальными COM портами. Что очень плохо для отладки, ведь это часто с компа, где COM портов нет. Я например работаю на ноутбуке. Я создал виртуальный нуль модемный кабель, на одной стороне у меня висит гипертерминал, на другой подключается моя программа. Обмен данными по нуль-модемному кабелю контролируется еще одной софтиной. И это очень удобно для отладки. К сожалению Ваша библиотека не может открыть такой порт, хотя обычный WinAPI работает с ним без проблем, проверено. В чем может быть дело? Может надо просто какие настройки исправить или пару строчек кода? :-) Было бы замечательно

Автор: rcdimon 29.10.2009, 22:19

Установил другую программу для создания виртуальных COM портов и все заработало ) Извиняюсь за беспокойство )

Автор: kuzulis 2.3.2010, 14:19

Доброго времени.

Скажите, а что нужно сделать, чтобы обновить информацию о библиотеке QSerialDevice ? т.к. скоро выйдет новая версия и я хочу, чтобы тут (в исходниках или новостях) это выло видно! :)

Автор: ViGOur 3.3.2010, 17:03

1. Заходишь в тему: http://www.crossplatform.ru/node/892 и так как ты автор, то редактируешь ее.
2. Добавляешь на форум описание...

Автор: kuzulis 3.3.2010, 19:44

Итак, анонсирую релиз: QSerialDevice v 0.2.0

Изменений много, писать нет смысла, поэтому предоставляю краткую вырезку аннотации:

QSerialDevice - это кросс-платформенная библиотека для работы с последовательными устройствами, которая использует фрэймворк Qt4 (см. http://qt.nokia.com/).

Требования:

OC : Win2K/WinXP/WinVista/Win7 или любой дистрибутив GNU/Linux
Qt4 : >= 4.5.0
Процессор : любой (который поддерживается Qt4)
Компилятор : любой (который поддерживается Qt4)

Заметки:

В силу того, что Я (автор) не имею возможности протестировать библиотеку на всех возможных операционных системах, всех компиляторах, процессорах и т.п. - то возможно что библиотека в некоторых случаях не будет работать :( .
Библиотека тестировалась только на:
OC : Windows XP Pro Sp3 (win32) и GNU ArchLinux x86_64
Qt4 : от 4.5.3 до 4.6.2
Процессор : AMD Athlon 4400+ 64x2 Socket AM2
Компилятор : gcc, MinGw
Теоретически (с небольшими исправлениями исходного кода) можно добиться того, чтобы библиотека работала и на других платформах.

Библиотека QSerialDevice содержит следующие классы:



AbstractSerial

Класс AbstractSerial - предоставляет самодостаточный набор методов и свойств для легкой и простой работы с последовательными устройствами (последовательными портами) вашего PC (или другого устройства).
Класс поддерживает следующие возможности:

(более подробно см. описание AbstractSerial и исходный код)

SerialDeviceWatcher

Класс SerialDeviceWatcher - является вспомогательным классом для мониторинга последовательных устройств.
Класс предоставляет следующие возможности:

(более подробно см. описание SerialDeviceWatcher и исходный код)

SerialDeviceInfo

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

(более подробно см. описание SerialDeviceInfo и исходный код)

Скачать релиз можно с домашней страницы проекта: http://fireforge.net/frs/?group_id=199
Скачать последние срезы SVN: http://fireforge.net/snapshots.php?group_id=199

Автор: mezmay 30.3.2010, 9:55

попробовал...

Сначала написал прогу по получению данных c GPSприемника по COM порту на QextSerialPort, упрощенный фрагмент:
// QextSerialPort
QextSerialPort *port = new QextSerialPort("COM1");
port->setBaudRate(BAUD4800);
port->setFlowControl(FLOW_OFF);
port->setDataBits(DATA_8);
port->setStopBits(STOP_1);
port->setParity(PAR_NONE);
if(port->open(QIODevice::ReadOnly))
QByteArray ba = port->read(100);

получает данные правильно, но иногда очень сильно тормозит на чтении

потом на QSerialDevice, вроде все тоже самое:
// QSerialDevice
AbstractSerial *port = new AbstractSerial();
port->setDeviceName("COM1");
port->setBaudRate(AbstractSerial::BaudRate4800);
port->setFlowControl(AbstractSerial::FlowControlOff);
port->setDataBits(AbstractSerial::DataBits8);
port->setStopBits(AbstractSerial::StopBits1);
port->setParity(AbstractSerial::ParityNone);
if(port->open(QIODevice::ReadOnly | QIODevice::Unbuffered))
QByteArray ba = port->read(100);

- получает некорректные данные... почему? Даже если QIODevice::Unbuffered убрать

Автор: Litkevich Yuriy 30.3.2010, 10:03

mezmay, не было ни какой нужды цитировать целое сообщение.
См. справку: http://www.forum.crossplatform.ru/index.php?showtopic=1455

Автор: kuzulis 31.3.2010, 11:31

mezmay,

Задание:
прочитать внимательнее документацию QSerialDevice и посмотреть внимательнее примеры QSerialDevice и найти отличия c тем что у вас и с тем что там

Автор: dekar 3.4.2010, 19:05

Хм. тут проблемка выползла. Он как-то не особо охотно разблокирует порты при ->close();

Linux: NativeSerialEnginePrivate::nativeOpen(QIODevice::OpenMode mode)
-> function: lockDevice(lockFileName) returned: false. Error!

Linux: NativeSerialEnginePrivate::nativeClose()
-> fd == -1. Error!

После чего, конечно же, повторно не открывает, но и не работает. Руками убираю lock-файл. Есть мысль, где копать?

Автор: kuzulis 3.4.2010, 22:00

Берите последний срез SVN, там эта проблема вроде решена... Да и поотключал я в этом срезе вывод отладки, чтоб не мозолил глаза. Проверьте.

Автор: Гость 4.4.2010, 19:30

Цитата(kuzulis @ 3.4.2010, 22:00) *
Берите последний срез SVN, там эта проблема вроде решена... Да и поотключал я в этом срезе вывод отладки, чтоб не мозолил глаза. Проверьте.

Увы. SVN просто не собирается.
Раскрывающийся текст
/usr/lib64/qt/bin/moc -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/lib64/qt/mkspecs/linux-g++-64 -I. -I/usr/lib64/qt/include/QtCore -I/usr/lib64/qt/include -Iqserialdevice -Iqserialdeviceinfo -Iqserialdevicewatcher -Ibuild/lib/qintegratedserialdevice/moc qserialdevice/abstractserial.h -o build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp
g++ -c -m64 -pipe -O2 -fPIC -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/lib64/qt/mkspecs/linux-g++-64 -I. -I/usr/lib64/qt/include/QtCore -I/usr/lib64/qt/include -Iqserialdevice -Iqserialdeviceinfo -Iqserialdevicewatcher -Ibuild/lib/qintegratedserialdevice/moc -o build/lib/qintegratedserialdevice/obj/moc_abstractserial.o build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:12:2: error: #error "The header file 'abstractserial.h' doesn't include <QObject>."
In file included from build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:10:
build/lib/qintegratedserialdevice/moc/../../../../qserialdevice/abstractserial.h:43: error: expected class-name before '{' token
build/lib/qintegratedserialdevice/moc/../../../../qserialdevice/abstractserial.h:44: error: 'Q_OBJECT' does not name a type
In file included from build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:10:
build/lib/qintegratedserialdevice/moc/../../../../qserialdevice/abstractserial.h:220: error: expected ')' before '*' token
build/lib/qintegratedserialdevice/moc/../../../../qserialdevice/abstractserial.h:307: error: 'd_func' is not a type
build/lib/qintegratedserialdevice/moc/../../../../qserialdevice/abstractserial.h:307: error: ISO C++ forbids declaration of 'Q_PRIVATE_SLOT' with no type
build/lib/qintegratedserialdevice/moc/../../../../qserialdevice/abstractserial.h:309: error: expected ';' before 'void'
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:49: error: 'QMetaObject' does not name a type
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:54: error: expected initializer before '*' token
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:59: error: no 'void* AbstractSerial::qt_metacast(const char*)' member function declared in class 'AbstractSerial'
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:67: error: 'int AbstractSerial::qt_metacall' is not a static member of 'class AbstractSerial'
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:67: error: 'QMetaObject' has not been declared
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:67: error: expected primary-expression before 'int'
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:67: error: expected primary-expression before 'void'
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:67: error: initializer expression list treated as compound expression
build/lib/qintegratedserialdevice/moc/moc_abstractserial.cpp:68: error: expected ',' or ';' before '{' token
make: *** [build/lib/qintegratedserialdevice/obj/moc_abstractserial.o] Error 1

Автор: kuzulis 5.4.2010, 7:25

Цитата
Увы. SVN просто не собирается.

Упс... Вы плавы.

1. Скачайте тут: http://fireforge.net/scm/viewvc.php/trunk/qserialdevice/abstractserial.h?root=qserialdevice&view=log

файл abstractserial.h ревизии 98!!!
(Он отличается только от этого же файла (ревизии 99) тем, что почему-то в более новом файле (ревизия 99) "слетела" кодировка с UTF-8 на ANSII! QtCreator меня замучал - он виноват :) )

2. Замените в вашем снапшоте abstractserial.h 99 ревизии на abstractserial.h 98 ревизии +
в файле abstractserial.h 98 ревизии добавьте:
...
#include <QtCore/QObject>
...

Автор: dekar 5.4.2010, 9:12

Ура. SVN я собрал. Првада, проблема всё равнон не решилась.

Закрываю порт. Все дебаги включил.

Цитата
Status: "Closed::Device is successfully closed. OK!" QDateTime("Mon Apr 5 06:07:58 2010")

Думаю - руль!

Открываю опять:
Цитата
AbstractSerial::setDeviceName(const QString &deviceName)
-> forbidden to set the name for the open device. Warning!
Status: "Device is already open. Error!" QDateTime("Mon Apr 5 06:08:04 2010")
ERROR: Serial device "/dev/ttyUSB0" can not be opened!

Автор: kuzulis 5.4.2010, 9:16

Лана, вечером доковыряю :)

Автор: kuzulis 6.4.2010, 19:08

Вроде исправил.. Пробуйте!

Автор: dekar 7.4.2010, 10:48

Теперь мне надо до работы доползти :)
А это будет не раньше четверга. Качать SVN?

Автор: kuzulis 7.4.2010, 13:31

Цитата
Качать SVN?

Да.

Автор: dekar 13.4.2010, 10:59

Увы. Опять тот же симптом.

Автор: Гость 13.4.2010, 11:01

Нет, огромное спасибо! Всё заработало отлично. Забыл просто проект пересобрать.

Автор: dekar 14.4.2010, 17:21

Решил всё-таки зарегистрироваться.

Итак
1) serialdeviceinfo.h обёрнут в #ifndef SERIALDEVICEWATCHER_H, что сильно мешает в одном проекте использовать оба класса.
2) Проблемы с lock-файлами остались. Просто теперь класс кладёт на них, что не совсем есть гут.
3) В качестве фичи - советую объединить watcher и info в один класс. Плохо себе представляю watcher без info для использования.f

И ещё тут придумал фичу -
QByteArray readTimeout (int length, int msec)
читает length байт с порта, и их возвращает. Также возвращает те байты, которые успела прочитать за время msec. Удобно для опроса всех портов на предмет наличия определённого ответа.


Автор: Litkevich Yuriy 14.4.2010, 20:03

Цитата(dekar @ 14.4.2010, 21:21) *
QByteArray readTimeout (int length, int msec)
читает length байт с порта, и их возвращает. Также возвращает те байты, которые успела прочитать за время msec. Удобно для опроса всех портов на предмет наличия определённого ответа.
название функции совершенно не ассоциируется с описанием.
Если откинуть аргументы и оставить только имя, то эта функция всего лишь читает величину таймаута, но почему-то возвращает её в неуклюжем виде.
Надо имя пересмотреть

Автор: kuzulis 17.4.2010, 17:27

Цитата
1) serialdeviceinfo.h обёрнут в #ifndef SERIALDEVICEWATCHER_H, что сильно мешает в одном проекте использовать оба класса.

исправил

Цитата
2) Проблемы с lock-файлами остались. Просто теперь класс кладёт на них, что не совсем есть гут.

изменил

Цитата
3) В качестве фичи - советую объединить watcher и info в один класс. Плохо себе представляю watcher без info для использования.f

нет.. не объединю...

Цитата
И ещё тут придумал фичу -
QByteArray readTimeout (int length, int msec)
читает length байт с порта, и их возвращает. Также возвращает те байты, которые успела прочитать за время msec. Удобно для опроса всех портов на предмет наличия определённого ответа.

пока не вижу в этом сакрального смысла

Автор: dekar 14.5.2010, 0:41

Вот и новая проблема. Не знаю, насколько она решаема, но...
Дело в том, что watcher не перехватывает события отключения порта, когда он... открыт. И я понимаю почему, он и из системы не пропадает. Собственно вопрос: можно ли с этим чего-либо сделать. И есть ли такая же проблема в венде?

Автор: Litkevich Yuriy 14.5.2010, 9:25

Цитата(dekar @ 14.5.2010, 4:41) *
не перехватывает события отключения порта
хорошо, если он в системе не пропадает, то как ты определяешь, что он отключен?

Автор: dekar 14.5.2010, 12:27

Цитата(Litkevich Yuriy @ 14.5.2010, 10:25) *
хорошо, если он в системе не пропадает, то как ты определяешь, что он отключен?

А очень просто. Надо перехватывать все события udev'а, а не только те, что связаны с rs232 портами. И смотреть, являлось ли отключённое устройство портом.

А может быть есть информация о том, есть ли такая же проблема в венде?

Автор: Litkevich Yuriy 14.5.2010, 16:29

я использую QxtSerialPort в виндовозе, для отлова отключения преобразователя USB-RS232 при открытом порте всегда проверяю кол-во принятых байт. Драйвер FTDI'ного преобразователя всегда отрицательное значение возвращает.

Автор: dekar 14.5.2010, 18:32

хм. Удачно. Только проблемка - у меня не FTDI, а програмный UART на меге 8.
usb 2-1: Product: USB-232
usb 2-1: Manufacturer: www.recursion.jp
Буду глядеть, что там с кол-вом принятых байт.

Автор: Litkevich Yuriy 14.5.2010, 20:34

ну а на ПК у тебя стандартный (аппаратный) COM-порт?

Автор: dekar 15.5.2010, 9:21

Цитата(Litkevich Yuriy @ 14.5.2010, 20:34) *
ну а на ПК у тебя стандартный (аппаратный) COM-порт?

Нет, конечно. Мегу подцепил к УСБ, а она уже, в частности, как УСБ -> UART ведёт себя. Очень не хотел делать устройство, которому нужны были дрова. Вот и прикидывается девайс "шнурком" :)

Автор: kuzulis 15.5.2010, 13:36

Цитата
А очень просто. Надо перехватывать все события udev'а, а не только те, что связаны с rs232 портами. И смотреть, являлось ли отключённое устройство портом.


Да так там и работает. Ловятся любые события от UDEV а потом просто смотрим что изменилось в директории /dev, и если там пропало у-во которое является tty* - то мы сообщаем об этом. Значит при выдергивании порта когда он открыт события не приходят от UDEV. Нужно проверить как нибудь попозже.

Цитата
я использую QxtSerialPort в виндовозе, для отлова отключения преобразователя USB-RS232 при открытом порте всегда проверяю кол-во принятых байт. Драйвер FTDI'ного преобразователя всегда отрицательное значение возвращает.


Так это не означает, что конвертер отключен. Это означает что произошла какая то ошибка ввода - вывода ИМХО.

---
Резюмирую: чтобы реализовать полностью такую фичу как "отлов втыкания/выдергивания" конвертеров в любых состояниях (открыт или закрыт или что-то там еще) необходимо найти те механизмы в ОС которые позволяли бы обнаружить втыкание/извлечение конвертера.

Вот к примеру, если конвертер (порт) закрыт, то его "втыкание/извлечение" в принципе легко отслеживается. Но, если он открыт и в этот момент его мы "выдернули" - то это проблема ОС ! Если в ней еще сохраняется состояние того что порт присутствует - то виноват "индус" который писал ОС! :)

Если вы найдете механизм, который четко и однозначно определял наличие порта в системе - то я это реализую. Присылайте патчи.. Я только ЗА всеми руками!





Автор: Litkevich Yuriy 15.5.2010, 14:26

Цитата(kuzulis @ 15.5.2010, 17:36) *
Так это не означает, что конвертер отключен.
само собой. Просто FTDI'ный драйвер гарантирует такое поведение при отключении устр-ва при открытом порте.

Справедливо для виндовоза:
Проблема большинства имитаторов COM-порта: при открытом порте вытаскиваем USB-устройство, далее если мы не закрываем порт и снова вставляем USB-устройство. То - приплыли. Больше мы этим портом воспользоватся не сможем, пока не проделаем следующую процедуру:
1) опять выдёргиваем USB-устройство
2) в диспетчере устройств делаем обновить, соответствующий COM-порт должен исчезнуть из списка
3) Вставляем USB-устройство вновь, оно должно определиться и снова должен появится COM-порт.

Тот трюк который проделываю я:
Если приняли отрицательное кол-во байт, порт сразу закрываю. Т.к. вставка USB-устройства при закрытом порте не приводит к выше описанному криминалу.


Цитата(kuzulis @ 15.5.2010, 17:36) *
Но, если он открыт и в этот момент его мы "выдернули" - то это проблема ОС ! Если в ней еще сохраняется состояние того что порт присутствует - то виноват "индус" который писал ОС!
индус прав. Открытый порт не может исчезнуть вдруг. Т.к. этот ресурс занят программой.

программа не может ни с того ни с сего лишиться ресурса. Представь себе ситуацию:
// ты создал переменную - тоже ресурс
int myvar = 10;
...
// далее ты хочешь воспользоваться ею
int var2 = myvar;
// но вот не задача, ресурс myvar исчез

Автор: dekar 15.5.2010, 16:19


Цитата(kuzulis @ 15.5.2010, 14:36) *
Да так там и работает. Ловятся любые события от UDEV а потом просто смотрим что изменилось в директории /dev, и если там пропало у-во которое является tty* - то мы сообщаем об этом. Значит при выдергивании порта когда он открыт события не приходят от UDEV. Нужно проверить как нибудь попозже.

---
Резюмирую: чтобы реализовать полностью такую фичу как "отлов втыкания/выдергивания" конвертеров в любых состояниях (открыт или закрыт или что-то там еще) необходимо найти те механизмы в ОС которые позволяли бы обнаружить втыкание/извлечение конвертера.

Вот к примеру, если конвертер (порт) закрыт, то его "втыкание/извлечение" в принципе легко отслеживается. Но, если он открыт и в этот момент его мы "выдернули" - то это проблема ОС ! Если в ней еще сохраняется состояние того что порт присутствует - то виноват "индус" который писал ОС! :)

Если вы найдете механизм, который четко и однозначно определял наличие порта в системе - то я это реализую. Присылайте патчи.. Я только ЗА всеми руками!


Мы подключаем устройство.

Вот события удева:

CODE
KERNEL[1273928448.612580] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)
KERNEL[1273928448.615458] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
KERNEL[1273928448.622468] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/tty/ttyACM0 (tty)
KERNEL[1273928448.622593] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
KERNEL[1273928448.622606] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)
UDEV [1273928448.626864] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)
UDEV [1273928448.627187] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
UDEV [1273928448.628576] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
UDEV [1273928448.640491] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/tty/ttyACM0 (tty)
UDEV [1273928448.644527] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)

Мы видим, что подключено устройство, связанное с tty

Теперь мы порт открываем, после чего вытаскиваем устройство. Результат:
CODE

KERNEL[1273928469.995045] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
KERNEL[1273928469.995079] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
KERNEL[1273928469.996906] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)
UDEV [1273928469.996923] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
KERNEL[1273928469.996937] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)
UDEV [1273928469.998121] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
UDEV [1273928469.999564] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)
UDEV [1273928469.999826] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)

Видно, что ttyACM0 не изчез. Но, если бы мы на прошлой итерации запомнили ещё и /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/, то тогда мы бы могли сейчас подать сигнал о том, что вынули именно ttyACM0.

Если устройство было подключено до старта watcher'а, то тогда его путь в ядре можно было бы отловить в самом начале, делая табличку интересующих нас устройств, т.е. tty* (да, знаю устройств много. Но, ИМХО, это полезая фича.

Автор: Litkevich Yuriy 15.5.2010, 19:43

Цитата(dekar @ 15.5.2010, 20:19) *
Но, ИМХО, это полезая фича
безусловно.

dekar, решение действительно хорошее, может kuzulis, возьмёт его на заметку.

П.С. по поводу оформления сообщений прочитай тему: http://www.forum.crossplatform.ru/index.php?showtopic=1455

Автор: dekar 16.5.2010, 23:59

А ты можешь пока проверить, есть ли сигнал от изчезновения уже открытого порта в венде? На той версии, что уже есть. Ибо у меня пока нет возможности что-то под оной собрать.

И, если не сложно, краткое описание того, как вообще в венде собирать что-то. Там gcc вообще есть? make? Или только их студия? Вот уже поставил себе семёрку в виртуалке.

А править посты тут можно? Что-то я кнопочку не нахожу.

Автор: kuzulis 17.5.2010, 7:27

Цитата
А ты можешь пока проверить, есть ли сигнал от изчезновения уже открытого порта в венде? На той версии, что уже есть. Ибо у меня пока нет возможности что-то под оной собрать.

Я проверил под виндой. Да, таже проблемка :) . Но я знаю как решить.. Просто нужно "слушать" другие ветки реестра и все должно быть нормуль.

Цитата
И, если не сложно, краткое описание того, как вообще в венде собирать что-то. Там gcc вообще есть? make? Или только их студия? Вот уже поставил себе семёрку в виртуалке.

Дык есть описние . Если используешь MinGW, то сборка ничем не отличается. Но если Студию - то там только nmake вместо make. В общем ничего сложного.

Цитата
А править посты тут можно? Что-то я кнопочку не нахожу.

А для этого нужно набрать сколько то там постов (вроде)

----

В общем проблему понял, идеи есть. Будем решать в ближайшее время :)

Автор: leech 18.5.2010, 22:04

Добрый день! Благодарю за отличный класс для работы с компортом!

Возникла долго не решаемая проблема с приёмом данных из порта, после востановления подключения к порту.
Использую приём по сигналу readyRead()

COMport = new AbstractSerial();
connect(COMport, SIGNAL(readyRead()), this, SLOT(slot_COMPortReadyRead()));


void SCPI_Generator::slot_COMPortReadyRead()
{
    qint64 ba_count= COMport->bytesAvailable();        // Количество пришёдших байт в буффере
    QByteArray ba = COMport->read(ba_count);          // Читаем данные из буфера

    inputBuffer.append(ba);
    if (inputBuffer.contains("\n"))                                 // Если пришёл конец строки
    {
        QString ba_str(inputBuffer);
        inputBuffer.clear();
        logText->append(QString("<b>&gt;</b> %1").arg(ba_str));       // Записываем посылаемые данные в лог
    }
}


При запуске программы открывается и настраивается COMпорт
bool SCPI_Generator::ComPortOpen()
{
    COMport->setDeviceName(comPortName);
    if (COMport->open(QIODevice::ReadWrite | QIODevice::Unbuffered))
    {
        COMport->reset();
        COMport->setBaudRate(QString("%1 baud").arg(comBaudRate));
        COMport->setDataBits(QString("%1 bit").arg(comDataBits));
        COMport->setStopBits(comStopBits);
        COMport->setParity(comParity);
        COMport->setFlowControl(comFlowControl);
        return true;
    }
    else // Ошибка открытия COM порта
    {
        QMessageBox::critical(this, tr("Critical error!"),
                                    tr("Error opened serial device %1.\n"
                                       "Select another COM port.").arg(COMport->deviceName()), QMessageBox::Ok);
        return false;
    }
}



пришедшие данные отлично отображаются. ОДнако, если закрыть COM порт и потом снова открыть, при приёме отображается такая ошибка

Windows: NativeSerialEnginePrivate::nativeSelect(int timeout, bool selectForRead) 
-> function: ::WaitForSingleObject(ovl.hEvent, timeout < 0 ? 0 : timeout),
returned: WAIT_TIMEOUT:  258 . Warning!


и данные не читаются. После этого сигнал readyRead() вообще не эмитируется. Зашел пока в тупик. Заранее благодарю за разъяснения!

Автор: kuzulis 19.5.2010, 7:32

leech

А попробуйте ка использовать версию библиотеки из SVN. Там по сравнению с 0.2.0 много чего изменилось, внимательно посмотрите примеры и abstractserial.h.
Если и там будет такая-же проблема - то будем разбираться.

Из SVN качайте SVN-клиентом. Описание как это делать находится тут: http://fireforge.net/scm/?group_id=199

Ни в коем случае не жмакайте на ссылку: [Загрузить свежую SVN базу репозитория]
т.к. получите не свежий срез - а 2010/04/05. . (какая то ошибка на сервере/сайте)

Т.е. свежак - это использование клиента!

Автор: leech 19.5.2010, 17:36

Благодарю! Скачал SVN, пересобрал, поправил вызовы в связи с миграцией класса AbstractSerial с QIODevice на QObject, и всё заработало! Проблема решилась.

Автор: Litkevich Yuriy 26.5.2010, 7:16

kuzulis, отредактируй пожалуйста первое сообщение темы. Чтобы в нём были актуальные ссылки на проект/исходники.
Т.к. новичкам может быть обременительно читать всю тему в поисках ссылок.

Автор: dekar 26.5.2010, 10:20

Уже удалось отслеживать отключение уже открытого порта?
Если да, то советую сделать новый snapshot.

Автор: kuzulis 26.5.2010, 15:52

Цитата
kuzulis, отредактируй пожалуйста первое сообщение темы. Чтобы в нём были актуальные ссылки на проект/исходники.
Т.к. новичкам может быть обременительно читать всю тему в поисках ссылок.


у меня не появляется ссылки типа "редактировать сообщение"

Цитата
Уже удалось отслеживать отключение уже открытого порта?
Если да, то советую сделать новый snapshot.


да, но пока только под Windows.

Также обнаружились некоторые проблемы при использовании метода waitForReadyRead() .
Сегфолт наблюдается в Win7 при использовании примера /examples/reader.
Там какая-то фигня с WaitCommEvent и т.п. Но вроде уже проблему победил (сделал костыль).
Скоро обновлю срез.

Автор: Litkevich Yuriy 26.5.2010, 16:06

kuzulis, такой кнопки: под первым сообщением темы нету?

Автор: kuzulis 26.5.2010, 20:17

Litkevich Yuriy,
не, нету. только зеленые кнопки типа "создать тему", "цитата" и т.п.

dekar,
всё, добавил изменения в SVN. Пробуйте.

Автор: dekar 26.5.2010, 22:23

Венда у меня только в виртуалке далеко. Завтра попробую.

Автор: panbaraban 27.5.2010, 12:18

а получение инфы об устройстве (serialdeviceinfo) у всех нормально работает? :unsure:

Автор: kuzulis 27.5.2010, 13:11

Цитата
а получение инфы об устройстве (serialdeviceinfo) у всех нормально работает? :unsure:


А вы лучше скажите что не работает лично у вас! :)
Какая ОС ? Что именно не устраивает?

Конкретики пжлста!!! Конкретики! :)

Автор: panbaraban 27.5.2010, 13:21

Цитата(kuzulis @ 27.5.2010, 15:11) *
Цитата
а получение инфы об устройстве (serialdeviceinfo) у всех нормально работает? :unsure:


А вы лучше скажите что не работает лично у вас! :)
Какая ОС ? Что именно не устраивает?

Конкретики пжлста!!! Конкретики! :)


ось -винда хп сп3

запускаю пример serialdeviceinfo, ввожу COM1 например. В результате - пустые строки, и что самое главное isExists=false. :(
На линуксе ещё не проверял

Автор: kuzulis 27.5.2010, 15:17

Цитата
и что самое главное isExists=false.

значит нету COM1 :)

Кстати, этот порт в мамку встроен или это USB\RS-232 конвертер?

Автор: panbaraban 27.5.2010, 17:15

Цитата(kuzulis @ 27.5.2010, 17:17) *
Цитата
и что самое главное isExists=false.

значит нету COM1 :)

Кстати, этот порт в мамку встроен или это USB\RS-232 конвертер?

Он есть, проверил все что были. Конвертер USB\RS-485 тоже не определяется

Автор: kuzulis 27.5.2010, 17:28

Цитата(panbaraban @ 27.5.2010, 18:15) *
Цитата(kuzulis @ 27.5.2010, 17:17) *
Цитата
и что самое главное isExists=false.

значит нету COM1 :)

Кстати, этот порт в мамку встроен или это USB\RS-232 конвертер?

Он есть, проверил все что были. Конвертер USB\RS-485 тоже не определяется


хм.. о_О. ,

а посмотрите в реестре, по пути:

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\Serenum\\Enum

есть ли там что нибудь?

Автор: kuzulis 27.5.2010, 20:37

Цитата(dekar @ 15.5.2010, 17:19) *
Цитата(kuzulis @ 15.5.2010, 14:36) *
Да так там и работает. Ловятся любые события от UDEV а потом просто смотрим что изменилось в директории /dev, и если там пропало у-во которое является tty* - то мы сообщаем об этом. Значит при выдергивании порта когда он открыт события не приходят от UDEV. Нужно проверить как нибудь попозже.

---
Резюмирую: чтобы реализовать полностью такую фичу как "отлов втыкания/выдергивания" конвертеров в любых состояниях (открыт или закрыт или что-то там еще) необходимо найти те механизмы в ОС которые позволяли бы обнаружить втыкание/извлечение конвертера.

Вот к примеру, если конвертер (порт) закрыт, то его "втыкание/извлечение" в принципе легко отслеживается. Но, если он открыт и в этот момент его мы "выдернули" - то это проблема ОС ! Если в ней еще сохраняется состояние того что порт присутствует - то виноват "индус" который писал ОС! :)

Если вы найдете механизм, который четко и однозначно определял наличие порта в системе - то я это реализую. Присылайте патчи.. Я только ЗА всеми руками!


Мы подключаем устройство.

Вот события удева:

CODE
KERNEL[1273928448.612580] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)
KERNEL[1273928448.615458] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
KERNEL[1273928448.622468] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/tty/ttyACM0 (tty)
KERNEL[1273928448.622593] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
KERNEL[1273928448.622606] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)
UDEV [1273928448.626864] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)
UDEV [1273928448.627187] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
UDEV [1273928448.628576] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
UDEV [1273928448.640491] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/tty/ttyACM0 (tty)
UDEV [1273928448.644527] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)

Мы видим, что подключено устройство, связанное с tty

Теперь мы порт открываем, после чего вытаскиваем устройство. Результат:
CODE

KERNEL[1273928469.995045] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
KERNEL[1273928469.995079] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
KERNEL[1273928469.996906] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)
UDEV [1273928469.996923] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0 (usb)
KERNEL[1273928469.996937] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)
UDEV [1273928469.998121] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1 (usb)
UDEV [1273928469.999564] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.112 (usb_device)
UDEV [1273928469.999826] remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1 (usb)

Видно, что ttyACM0 не изчез. Но, если бы мы на прошлой итерации запомнили ещё и /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/, то тогда мы бы могли сейчас подать сигнал о том, что вынули именно ttyACM0.

Если устройство было подключено до старта watcher'а, то тогда его путь в ядре можно было бы отловить в самом начале, делая табличку интересующих нас устройств, т.е. tty* (да, знаю устройств много. Но, ИМХО, это полезая фича.


только что проверил работу в Linux при таких обстоятельствах и получил это:
Цитата
[kuzulis@kuzulis release]$ ./serialdevicewatcher
Please remove or insert a serial device (eg USB/Serial controller) to see the notification.
Devices : ("/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyUSB0")
Devices : ("/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3")
Devices : ("/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyUSB1")


т.е. сначала открыл у-во /dev/ttyUSB0 потом запустил Watcher. Он мне выдал первую строку. Потом я выдернул шнурок - он мне выдал вторую строку в которой этот порт пропал. Далее я опять втыкнул шнурок - он мне показал третью строку /dev/ttyUSB1

как видно, у меня на компе все события обрабатываются "корректно" . хм.. непонятно почему у вас проблемы в Linux



Автор: Litkevich Yuriy 27.5.2010, 22:28

kuzulis, не цитируй целыми сообщениями - читать тяжело

Автор: panbaraban 28.5.2010, 6:03

Цитата(kuzulis @ 27.5.2010, 19:28) *
хм.. о_О. ,

а посмотрите в реестре, по пути:

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\Serenum\\Enum

есть ли там что нибудь?



Автор: kuzulis 28.5.2010, 7:39

хм. ну должно работать по идее.

а теперь посмотрите в :

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_067b&Pid_2303\\5&21b58723&0&1

и в:

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_067b&Pid_2303\\5&21b58723&0&1\\Device Parameters

Автор: panbaraban 30.5.2010, 20:38

Цитата(kuzulis @ 28.5.2010, 9:39) *
хм. ну должно работать по идее.

а теперь посмотрите в :

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_067b&Pid_2303\\5&21b58723&0&1

и в:

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_067b&Pid_2303\\5&21b58723&0&1\\Device Parameters


Как то так вот, например

Автор: kuzulis 31.5.2010, 7:39

В принципе все должно работать. Пробегитесь дебаггером в SerialDeviceInfo :).

Автор: panbaraban 31.5.2010, 20:13

Цитата(kuzulis @ 31.5.2010, 9:39) *
В принципе все должно работать. Пробегитесь дебаггером в SerialDeviceInfo :).

Пасиба, попробую)

Автор: panbaraban 8.6.2010, 17:43

Ещё такая бага: если порт открыть, а потом закрыть, то снова открыть его уже не получается. Делал полностью из примера reader.
В начале проги создал объект, при закрытии его не удалял. Затем снова вызываем open и всё, порт больше не открывается. Может быть я что-то не так делаю?


Автор: kuzulis 8.6.2010, 19:16

Цитата(panbaraban @ 8.6.2010, 18:43) *
Ещё такая бага: если порт открыть, а потом закрыть, то снова открыть его уже не получается. Делал полностью из примера reader.
В начале проги создал объект, при закрытии его не удалял. Затем снова вызываем open и всё, порт больше не открывается. Может быть я что-то не так делаю?


этот баг был в версии 0.2.0 (в релизе). в SVN это должно быть уже пофикшено.

к сожалению пока что fireforge.net лежит :( и невозможно получить срез.

Автор: panbaraban 8.6.2010, 20:28

Цитата(kuzulis @ 8.6.2010, 21:16) *
этот баг был в версии 0.2.0 (в релизе). в SVN это должно быть уже пофикшено.

к сожалению пока что fireforge.net лежит :( и невозможно получить срез.

хм, а я качал с svn в конце мая. попробую перекомпилить....

Автор: panbaraban 9.6.2010, 6:44

Нет, та же ерунда, причем выборочно. На одном порте работает отлично, а другой невозможно открыть повторно.

Автор: kuzulis 9.6.2010, 7:20

Цитата
Нет, та же ерунда, причем выборочно. На одном порте работает отлично, а другой невозможно открыть повторно.


Как качали SVN?
Включите отладочные сообщения (раскомментируйте в *.cpp файлах строки вида: #define blablabla_DEBUG) и посмотрите что оно выводить будет.
Пройдитесь дебагером. :)

Автор: panbaraban 9.6.2010, 7:54

Да, качал SVN, ревизия 132 кажется, конец мая.


Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode) 
-> trying to open device:  "COM6"

Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> opened device:  "COM6"  in mode:  3  succesfully. Ok!

Windows: NativeSerialEnginePrivate::nativeClose()
-> descriptor is invalid. Error!

Windows: NativeSerialEnginePrivate::nativeClose()
-> descriptor is invalid. Error!


не знает чего закрывать :wacko:

Автор: kuzulis 9.6.2010, 12:36

Хм... Вот я сделал пример, который открывает и закрывает порт. У меня все нормально.

Раскрывающийся текст

Cnt = 2
Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> trying to open device: "COM3"

Windows: NativeSerialEnginePrivate::detectDefaultFlowControl()
-> undefined flow, this->cc.dcb.fOutxCtsFlow is: 0 , this->cc.dcb.fRtsControl
is: 1 , this->cc.dcb.fInX is: 0 , this->cc.dcb.fOutX is: 0

Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> opened device: "COM3" in mode: 3 succesfully. Ok!

Serial device "COM3" open in 3
= Default parameters =
Device name : "COM3"
Baud rate : "1200 baud"
Data bits : "7 bit"
Parity : "None"
Stop bits : "1"
Flow : "Flow control undefined"
Char timeout, msec : 10
= New parameters =
Device name : "COM3"
Baud rate : "115200 baud"
Data bits : "8 bit"
Parity : "None"
Stop bits : "1"
Flow : "Disable"
Char timeout, msec : 50
Serial device "COM3" is closed
Cnt = 1
Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> trying to open device: "COM3"

Windows: NativeSerialEnginePrivate::detectDefaultFlowControl()
-> undefined flow, this->cc.dcb.fOutxCtsFlow is: 0 , this->cc.dcb.fRtsControl
is: 1 , this->cc.dcb.fInX is: 0 , this->cc.dcb.fOutX is: 0

Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> opened device: "COM3" in mode: 3 succesfully. Ok!

Serial device "COM3" open in 3
= Default parameters =
Device name : "COM3"
Baud rate : "1200 baud"
Data bits : "7 bit"
Parity : "None"
Stop bits : "1"
Flow : "Flow control undefined"
Char timeout, msec : 10
= New parameters =
Device name : "COM3"
Baud rate : "115200 baud"
Data bits : "8 bit"
Parity : "None"
Stop bits : "1"
Flow : "Disable"
Char timeout, msec : 50
Serial device "COM3" is closed
Cnt = 0
Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> trying to open device: "COM3"

Windows: NativeSerialEnginePrivate::detectDefaultFlowControl()
-> undefined flow, this->cc.dcb.fOutxCtsFlow is: 0 , this->cc.dcb.fRtsControl
is: 1 , this->cc.dcb.fInX is: 0 , this->cc.dcb.fOutX is: 0

Windows: NativeSerialEnginePrivate::nativeOpen(AbstractSerial::OpenMode mode)
-> opened device: "COM3" in mode: 3 succesfully. Ok!

Serial device "COM3" open in 3
= Default parameters =
Device name : "COM3"
Baud rate : "1200 baud"
Data bits : "7 bit"
Parity : "None"
Stop bits : "1"
Flow : "Flow control undefined"
Char timeout, msec : 10
= New parameters =
Device name : "COM3"
Baud rate : "115200 baud"
Data bits : "8 bit"
Parity : "None"
Stop bits : "1"
Flow : "Disable"
Char timeout, msec : 50
Serial device "COM3" is closed


Я прикрепил проект для теста. Попробуйте его у себя и воспроизведите в этом тесте вашу проблему.

 test.zip ( 43.26 килобайт ) : 164
 

Автор: panbaraban 9.6.2010, 13:52

Скомпилил



Автор: kuzulis 9.6.2010, 14:04

а добавте в :

bool NativeSerialEnginePrivate::nativeClose()
{
....
....
....
    
    qDebug() << "closeResult = " << closeResult;// ВОТ ЭТО ДОБАВТЕ!
    return closeResult;
}

что будет выводить в консоль?

Автор: panbaraban 9.6.2010, 14:25

closeResult=true

Автор: kuzulis 9.6.2010, 14:40

Ну значит какой-то касяк: с ОС или самим железом (портом) или драйвером порта, имхо

Автор: panbaraban 9.6.2010, 15:37

печально, а QextSerialPort корректно работает.

Автор: kuzulis 9.6.2010, 15:46

Да.. Странно всё это.

Можно попробовать перед закрытием дескриптора порта (т.е. перед CloseHandle(Handle)) вставить ф-ю: CancelIo(Handle) по аналогии с QextSerialPort и посмотреть что будет. Если вам не трудно - то попробуйте и отпишитесь.

Автор: panbaraban 10.6.2010, 6:28

Помогло!!!
добавляем ::CancelIo(this->hd); перед if (::CloseHandle(this->hd) == 0) в bool NativeSerialEnginePrivate::nativeClose()

Автор: kuzulis 17.6.2010, 8:38

Итак, я обновил на fireforge.net SVN с учетом послелних постов, а также подчистил и исправил код (где возможно).

Качать так: svn checkout svn://scm.fireforge.net/svnroot/qserialdevice

Автор: juvf 17.6.2010, 8:59

не заработал qserialdevice месячной давности. Библиотека собралась, а в свой проект не смог прикрутить. Сегодня из svn сделал новый checkout.
Теперь вообще не собирается библиотека.

Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

D:\Work\qt\serportN\trunk>qmake BuildIntegratedLibrary.pro

D:\Work\qt\serportN\trunk>mingw32-make
makefile:287: warning: overriding commands for target `build/lib/qintegratedseri
aldevice/obj/winregkeyreader.o'
makefile:272: warning: ignoring old commands for target `build/lib/qintegratedse
rialdevice/obj/winregkeyreader.o'
g++ -c -O2 -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT
-DQT_NO_DEBUG -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I"c:\Qt\2010.01\qt\include\QtCo
re" -I"c:\Qt\2010.01\qt\include" -I"qserialdevice" -I"qserialdeviceinfo" -I"qser
ialdeviceinfo" -I"qserialdeviceinfo" -I"qserialdevicewatcher" -I"c:\Qt\2010.01\q
t\include\ActiveQt" -I"build\lib\qintegratedserialdevice\moc" -I"c:\Qt\2010.01\q
t\mkspecs\default" -o build\lib\qintegratedserialdevice\obj\abstractserial.o qse
rialdevice\abstractserial.cpp
qserialdevice\abstractserial.cpp:1: error: stray '\239' in program
qserialdevice\abstractserial.cpp:1: error: stray '\187' in program
qserialdevice\abstractserial.cpp:1: error: stray '\191' in program
mingw32-make: *** [build/lib/qintegratedserialdevice/obj/abstractserial.o] Error
1

D:\Work\qt\serportN\trunk>


Что я делаю не так?

ps qt4.6.1


Автор: Litkevich Yuriy 17.6.2010, 9:24

Цитата(Гость_juvf_* @ 17.6.2010, 12:59) *
qserialdevice\abstractserial.cpp:1: error: stray '\239' in program
это на начало файла показывает, стало быть кодировка файла не правильная - UTF-8 c маркером, а надо без маркера (UTF-8 without BOM).

kuzulis, перекодируй файлы

Автор: kuzulis 17.6.2010, 10:15

Цитата
kuzulis, перекодируй файлы


Ок. Этот долбанный QtCreator меня достал! Я замучался уже перекодировать!
По-ходу придется Ru комментарии вообще убрать и оставить только En шоб не мучатся!

Автор: Гость 17.6.2010, 10:31

Цитата(Litkevich Yuriy @ 17.6.2010, 9:24) *
Цитата(Гость_juvf_* @ 17.6.2010, 12:59) *
qserialdevice\abstractserial.cpp:1: error: stray '\239' in program
это на начало файла показывает, стало быть кодировка файла не правильная - UTF-8 c маркером, а надо без маркера (UTF-8 without BOM).

kuzulis, перекодируй файлы


В общем ни чего не перекодировал, просто открыл проект и QTCreator-e и собрал проект. проект собрался, но с 2-мя варнингами
D:/Work/qt/serportM/trunk/makefile:287: warning: overriding commands for target `build/lib/qintegratedserialdevice/obj/winregkeyreader.o'
D:/Work/qt/serportM/trunk/makefile:272: warning: ignoring old commands for target `build/lib/qintegratedserialdevice/obj/winregkeyreader.o'


как варнинги победить?

Автор: kuzulis 17.6.2010, 10:48

Цитата
В общем ни чего не перекодировал, просто открыл проект и QTCreator-e и собрал проект. проект собрался, но с 2-мя варнингами

Понятно, а чем до этого и как собирали?

Цитата
как варнинги победить?

Да пока никак. Они не мешают.

Автор: Гость 17.6.2010, 11:07

Цитата(kuzulis @ 17.6.2010, 10:48) *
Понятно, а чем до этого и как собирали?


ээээ,,,, до чего "до этого"? тот что я смог месячной давности собрать? или до того как последний релиз собрал без перекодировки? Вообщем в обоих случаях собирал также как в 94-ом сообщении.
в Windows XP в шеле (cmd.exe). с помощью qt4.6.1 и mingw32-make. Но месяц назад всё собралось из шела, а последний релиз только из креатора.

ps

Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

C:\Documents and Settings\Прог>qmake -v
QMake version 2.01a
Using Qt version 4.6.1 in C:/Qt/2010.01/qt/lib

C:\Documents and Settings\Прог>mingw32-make -v
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-pc-mingw32

C:\Documents and Settings\Прог>

ну если нужно могу и кофигурацию компа скинуть ;)

Автор: kuzulis 17.6.2010, 11:26

Цитата
в Windows XP в шеле (cmd.exe). с помощью qt4.6.1 и mingw32-make. Но месяц назад всё собралось из шела, а последний релиз только из креатора.

вот только это я и хотел узнать

Автор: Litkevich Yuriy 17.6.2010, 11:46

Цитата(Гость_Гость_* @ 17.6.2010, 14:31) *
как варнинги победить?
pqo-файл исправить, где-то дважды засунут winregkeyreader.cpp в SOURCES

Автор: Boevik 5.7.2010, 19:32

Подскажите пожалуйста, как добавить данную библиотеку к моему проекту?
Скомпилировал библиотеку в интегрированном виде, получил "libqserialdevice.a". Положил её в "C:\Qt\2010.04\qt\lib\". В файл проекта добавил "LIBS += -lqserialdevice". В cpp-файл добавил "#include <AbstractSerial.h>". При компиляции ошибка:

Цитата
mainwindow.cpp:4:28: error: AbstractSerial.h: No such file or directory

Автор: Litkevich Yuriy 5.7.2010, 19:40

это всё потому-что kuzulis, не сделал нормального pri-файла, надо его пинать, чтобы сделал.

Автор: kuzulis 5.7.2010, 20:49

Boevik,

посмотрите как ЭТО сделано в примерах /examples.
И не нужно ничего копировать в "C:\Qt\2010.04\qt\lib\"


Litkevich Yuriy,

все там с *.pri нормуль. Хто хочет - сделает сам если что. :)

Автор: Litkevich Yuriy 5.7.2010, 21:40

Цитата(kuzulis @ 6.7.2010, 0:49) *
Хто хочет - сделает сам если что.
вот поэтому я и не использую твою библиотеку, также как и QxtSerialPort

Автор: Boevik 6.7.2010, 5:35

kuzulis, в примерах подключается "#include <abstractserial.h>", этот файл так же не находит при компиляции.


Автор: kuzulis 6.7.2010, 7:24

Цитата
kuzulis, в примерах подключается "#include <abstractserial.h>", этот файл так же не находит при компиляции.

Ёлки, посмотрите в любой файл *.pro из /examples . Там все видно что и как.

Цитата
вот поэтому я и не использую твою библиотеку, также как и QxtSerialPort

Да я тоже не использую ни QextSerialPort ни QSerialDevice. Ты не один такой! :)

Автор: Boevik 6.7.2010, 16:58

Цитата(kuzulis @ 6.7.2010, 8:24) *
Ёлки, посмотрите в любой файл *.pro из /examples . Там все видно что и как.

Мне не нужны в моем проекте чужие исходники. Какие еще есть способы установки данной библиотеки?

Автор: kuzulis 6.7.2010, 17:43

Ппц. :blink: :blink: :blink: :blink: :blink: :blink: :blink:

Автор: Litkevich Yuriy 7.7.2010, 9:12

Цитата(Boevik @ 6.7.2010, 20:58) *
Какие еще есть способы установки данной библиотеки?
видимо ни какого, как и в случае с любой другой библиотекой

Автор: bukap 2.8.2010, 12:11

Добрый день!

Регулярно работаю с устройствами, подключаемыми с помощью последовательного интерфейса к компьютеру. Интерфейсы разрабатываю на MFC, для связи с устройствами использую Windows API, ActiveX Microsoft Communication Control version 6.0.

Возникла необходимость разработать новый сложный интерфейс. Перед принятием решения о переходе на Qt, был проведен анализ и испытание уже готовых библиотек работы с последовательными портами.

Библиотеки:
QextSerialPort v.1.2 beta
QSerialSevice v 0.2.0

Среда разработки:
Qt Creator 2.0
Qt SDK 4.6.3

Платформа:
Microsoft Windows XP [Версия 5.1.2600] Service Pack 3

Последовательные порты:
1. Стандартный последовательный порт установленный на материнской плате
2. Prolific USB-to-Serial Comm Port
3. USB-SERIAL CH340
4. CP210x USB to UART Bridge Controller
5. PIC18F2550/4550 CDC RS-232 Emulation Microchip Technology Inc

QextSerialPort
Библиотека не поддерживает последовательные порты с нумерацией выше COM9. Устраняется добавлением в путь к открываемому порту указания на устройство “\\\\.\\” Для этого вносятся изменения в файл win_qextserialport.cpp.

CODE
bool Win_QextSerialPort::open(OpenMode mode) {
unsigned long confSize = sizeof(COMMCONFIG);
Win_CommConfig.dwSize = confSize;
DWORD dwFlagsAndAttributes = 0;
if (queryMode() == QextSerialBase::EventDriven)
dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;

LOCK_MUTEX();
if (mode == QIODevice::NotOpen)
return isOpen();
if (!isOpen()) {
/*open the port*/
Win_Handle=CreateFileA(("\\\\.\\" + port).toAscii(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);



}


QSerialSevice
Библиотека возвращает не верный статус линии. Устраняется исправлением типа данных с bool на ulong. Для этого вносятся изменения в файл abstractserial.cpp.

CODE
ulong AbstractSerial::lineStatus()
{
Q_D(AbstractSerial);
if (isOpen()) {
ulong ret = d->serialEngine->lineStatus();
if (!ret)
emitStatusString(ELineStatus);
return ret;
}
emitStatusString(EDeviceIsNotOpen);
return false;
}


Так же библиотека не смогла открыть последовательный порт PIC18F2550/4550 CDC RS-232 Emulation Microchip Technology Inc, при вызове функции открытия порта возникает ошибка из-за неудачного снятия состояния BREAK функцией ClearCommBreak. Устраняется комментированием строки ret = false;. После комментирования функциональность класса не изменяется, так как наличие вызова данной функции не обосновано.

CODE
bool NativeSerialEnginePrivate::nativeReset()
{



// cброс регистров порта. (reset device registers)
if (::ClearCommBreak(hd) == 0) {
#if defined (NATIVESERIALENGINE_WIN_DEBUG)
qDebug("Windows: NativeSerialEnginePrivate::nativeReset() \n"
" -> function: ::ClearCommBreak(hd) returned: 0. Error! \n");
#endif
// ret = false;



}


Автор: kuzulis 2.8.2010, 13:37

2 bukap,

Цитата
QSerialSevice
Библиотека возвращает не верный статус линии. Устраняется исправлением типа данных с bool на ulong. Для этого вносятся изменения в файл abstractserial.cpp.


Спс, мой косяк, недоглядел... Сегодня постараюсь исправить.

Цитата
Так же библиотека не смогла открыть последовательный порт PIC18F2550/4550 CDC RS-232 Emulation Microchip Technology Inc, при вызове функции открытия порта возникает ошибка из-за неудачного снятия состояния BREAK функцией ClearCommBreak. Устраняется комментированием строки ret = false;. После комментирования функциональность класса не изменяется, так как наличие вызова данной функции не обосновано.

Берите версию из http://gitorious.org/qserialdevice. Теперь там при открытии не используется метод nativeReset(), т.е. его вызов закоментирован.

Цитата
1. Стандартный последовательный порт установленный на материнской плате
2. Prolific USB-to-Serial Comm Port
3. USB-SERIAL CH340
4. CP210x USB to UART Bridge Controller
5. PIC18F2550/4550 CDC RS-232 Emulation Microchip Technology Inc


Со всеми ли этими устройствами корректно работает класс SerialDeviceWatcher и SerialDeviceInfo ?

Автор: bukap 2.8.2010, 18:36

Со всеми перечисленными устройствами была достигнута корректная работа.

Автор: good835 5.8.2010, 14:40

Добрый день!

Задача: Прошивка программного обеспечения через com порт в режиме с управлением потоком
на скоростях 115200 и 230400 бит/с

Опыт программирования на Qt и работы с com-портом минимальный, так что вопросы могут быть
соответствующие ...

Платформа:
Microsoft Windows XP Service Pack 2

Среда сборки
Qt Creator 2.0

Версии библиотеки
1. QSerialDevice 0.2.0
2. QSerialDevice из репозитария git http://gitorious.org/qserialdevice (от 3 августа)

Последовательные порты:
1. Cтандартный последовательный порт установленный на материнской плате
2. Prolific USB-to-Serial Comm Port
3. Moxa UPort 1110 1-портовый преобразователь USB в RS-232
4. Moxa NPort 510 преобразователь Ethernet в RS-232
5. Virtual Serial Ports Driver XP фирмы Eltima Software


Первый вопрос по QSerialDeviceWatcher:
Версия 0.2.0 - выдавался список всех портов в системе п.1-5 (с проверкой записи данных в порт)
Версия git - выдается только список "железных" портов в системе п.1-3
Первое что я заметил, это то что происходит чтение из другого места в реестре.

Второй вопрос по использованию нестандартной скорости передачи 230400 бит/с, которую поддерживают
порты Prolific USB2Comm и Moxa UPort 1110
Версия 0.2.0 - после добавления в список ряда скоростей соответствующей константы передача данных осуществлялась без ошибок
Версия git - на скорости 115200 бит/с передача данных осуществляется без ошибок, а на скорости 230400 бит/с порт успешно открывается,
задаются параметры, но далее при передаче данных происходит сбой с выдачей следующего сообщения
Windows: NativeSerialEnginePrivate::nativeWrite(const char *data, qint64 len)
-> function: ::::WaitForSingleObject(this->oTx.hEvent, 5000) returned: 258 . Error!

Третий вопрос:
Произвожу отправку данных в порт функцией qint64 AbstractSerial::write(const char *data, qint64 maxSize)
Каким образом можно задать таймаут на выполнение данной функции, так как в случае ошибки передачи данных поисходит зависание программы,
например, при разрыве кабеля

Автор: kuzulis 5.8.2010, 15:47

2 good835,

Цитата
Первый вопрос по QSerialDeviceWatcher:
Версия 0.2.0 - выдавался список всех портов в системе п.1-5 (с проверкой записи данных в порт)
Версия git - выдается только список "железных" портов в системе п.1-3
Первое что я заметил, это то что происходит чтение из другого места в реестре.

Да, из другого места. Я попробую сегодня скачать драйвер виртуального порта п. 5 и потестить с ним.
Также вы сами можете проверить наличие в реестре записей для этих портов по путям:

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\Serenum\\Enum
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\Ser2pl\\Enum
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\usbser\\Enum
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\lowcdc\\Enum

тут приведены пути в которых прописаны девайсы п.1-3 ... Для виртуальных портов наверное есть какие то другие пути.

Запустите диспетчер устройств, выберите девайс (п.4-5) и в вкладке "сведения" конкретного порта покажите мне что есть в значении :

"Код экземпляра устройства"
"Служба"
"Верхние фильтры устройства"

Цитата
Второй вопрос по использованию нестандартной скорости передачи 230400 бит/с, которую поддерживают
порты Prolific USB2Comm и Moxa UPort 1110
Версия 0.2.0 - после добавления в список ряда скоростей соответствующей константы передача данных осуществлялась без ошибок
Версия git - на скорости 115200 бит/с передача данных осуществляется без ошибок, а на скорости 230400 бит/с порт успешно открывается,
задаются параметры, но далее при передаче данных происходит сбой с выдачей следующего сообщения
Windows: NativeSerialEnginePrivate::nativeWrite(const char *data, qint64 len)
-> function: ::::WaitForSingleObject(this->oTx.hEvent, 5000) returned: 258 . Error!


Ну тут не знаю, тут почему-то WaitForSingleObject не дожидается события от порта что данные записаны.. Короче таймаут ожидания 5 секунд срабатывает.
Попробуйте выставить таймаут 10 секунд = 10000 ... Если честно, я не знаю почему эта ошибка происходит.
Код я брал "стандартный" предложенный $MS, так что не знаю... 8)

Цитата
Третий вопрос:
Произвожу отправку данных в порт функцией qint64 AbstractSerial::write(const char *data, qint64 maxSize)
Каким образом можно задать таймаут на выполнение данной функции, так как в случае ошибки передачи данных поисходит зависание программы,
например, при разрыве кабеля


Ух... тут это наверное возникает изза "режиме с управлением потоком" . Если это так, то я не сталкивался с этими особенностями и даж не представлю куда копать...
Хотя, попробуйте в методе:
void NativeSerialEnginePrivate::prepareOtherOptions()
{
    this->cc.dcb.fBinary = true;
    this->cc.dcb.fInX = this->cc.dcb.fOutX = this->cc.dcb.fAbortOnError = this->cc.dcb.fNull = false;
}

для this->cc.dcb.fAbortOnError = true; (вместо false)!!!

Автор: good835 5.8.2010, 18:02

2 kuzulis,
Насколько я понял QSerialDeviceWatcher версии 0.2.0 читал данные о портах в системе по следующей ветке:
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM]
она у меня выглядит следующим образом
"\\Device\\Serial0"="COM1"
"\\Device\\Serial1"="COM2"
"\\Device\\mxuport0"="COM14"
"\\Device\\mxuport1"="COM13"
"\\Device\\VSerial0"="COM20"
"\\Device\\VSerial1"="COM21"
"Npdrv8"="COM8"
"Npdrv7"="COM7"

В диспетчере устройств Виртуальные порты (COM20 COM21 из п.5) идут отдельной строкой
Eltima Virtual Serial Port(COM20->COM21)
Eltima Virtual Serial Port(COM21->COM20)
"Код экземпляра устройства" VSBUS\DEVICES\0000 и VSBUS\DEVICES\0001
"Служба" vserial
"Верхние фильтры устройства") пусто

по moxa ethernet 2 com - сейчас оно не подключено и возможно поэтому его нет в диспетчере устройств
а так это "Npdrv8"="COM8", "Npdrv7"="COM7"
в программе NPort Administrator они конфигурируются следующим образом но это вряд ли поможет
[Summary]
Total_Server=1

[Server1]
APID=0x80000312
HWID=0x322
IP=192.168.0.170
Port1=1,7,0,1,1,12,0,3,0,0,5000
Port2=1,8,0,1,1,12,0,3,0,0,5000

Данные из реестра для moxa nport 5210 Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npdrv]
"Group"="Extended base"
"Type"=dword:00000001
"Start"=dword:00000002
"ErrorControl"=dword:00000000
"ImagePath"=hex(2):5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,\
74,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,64,00,72,\
00,69,00,76,00,65,00,72,00,73,00,5c,00,6e,00,70,00,64,00,72,00,76,00,2e,00,\
73,00,79,00,73,00,00,00
"DisplayName"="npdrv"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npdrv\Parameters]
"Ports"=dword:00000002
"Servers"=dword:00000001
"SessionRecovery"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npdrv\Parameters\Server1]
"APID"=dword:80000312
"HWID"=dword:00000322
"IPAddress"=dword:c0a800aa
"PortFlag"=hex:01,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00
"COMNO"=hex:07,08,01,01,01,01,01,01,01,01,01,01,01,01,01,01
"TransmissionMode"=hex:01,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00
"FIFO"=hex:00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
"FastFlush"=hex:01,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00
"NetTimeOut"=hex:88,13,00,00,88,13,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npdrv\Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,\
00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,\
00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,\
05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,\
20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,\
00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,\
00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npdrv\Enum]
"0"="Root\\LEGACY_NPDRV\\0000"
"Count"=dword:00000001
"NextInstance"=dword:00000001

Данные из реестра для виртуальных портов
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\vserial]
"Type"=dword:00000001
"Start"=dword:00000003
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,44,00,\
52,00,49,00,56,00,45,00,52,00,53,00,5c,00,76,00,73,00,65,00,72,00,69,00,61,\
00,6c,00,2e,00,73,00,79,00,73,00,00,00
"DisplayName"="ELTIMA Virtual Serial Ports Driver"
"Group"="Extended Base"
"ForceFifoEnable"=dword:00000001
"RxFIFO"=dword:00000008
"TxFIFO"=dword:0000000e
"LogFifo"=dword:00000000

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\vserial\Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,\
00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,\
00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,\
05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,\
20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,\
00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,\
00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\vserial\Enum]
"0"="VSBUS\\DEVICES\\0000"
"Count"=dword:00000002
"NextInstance"=dword:00000002
"1"="VSBUS\\DEVICES\\0001"

Sorry, файлы не дает загрузить

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\Serenum\\Enum - есть
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\Ser2pl\\Enum - есть Ser2pl, но нет enum
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\usbser\\Enum - нет
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\lowcdc\\Enum - нет
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\mxuwdrv2\\ для moxa usb2com
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\vserial\\ для вирт портов
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\npdrv\\ для ethernet 2 com

остальное пока не пробовал
немного странно что версия 0.2.0 работала на скорости 230400 нормально, а последняя нет (




Автор: kuzulis 5.8.2010, 18:33

2 good835,

на основе ваших данных я попробовал добавить поддержку тех устройств которые вы перечислили. Обновляйте Git и пробуйте.

Автор: good835 6.8.2010, 11:54

2 kuzulis,

Еще раз по поводу списка портов в системе...
Все таки не могли бы вы пояснить почему сканируется реестр по ветке HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services
Сегодня еще раз попробовал версию 0.2.0 - она отлично видит список всех последовательных портов в системе
по [HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM] и нормально работает со всеми типами портов
с аппратными, usb2com, и ethernet2com на скорости 230400 бит/с
Я разговаривал с человеком который занимался подобным вопросом, он сказал что также работал с веткой
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM]

Версия из git
Теперь видит виртуальные порты (Eltima Virtual Serial Port), а порты ethernet2com по прежнему отсутствуют

2 kuzulis,

Подскажите существует ли возможность с помощью вашей библиотеки задать параметры таймаута для последовательного порта при записи данных
конкретнее, WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant http://msdn.microsoft.com/en-us/library/aa363190(v=VS.85).aspx

Автор: kuzulis 6.8.2010, 12:53

Цитата
Все таки не могли бы вы пояснить почему сканируется реестр по ветке HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services
Сегодня еще раз попробовал версию 0.2.0 - она отлично видит список всех последовательных портов в системе
по [HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM] и нормально работает со всеми типами портов
с аппратными, usb2com, и ethernet2com на скорости 230400 бит/с
Я разговаривал с человеком который занимался подобным вопросом, он сказал что также работал с веткой
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM]


См. почему я изменил ветку от http://www.forum.crossplatform.ru/index.php?showtopic=3012&view=findpost&p=34397поста и ниже по постам.

Цитата
Теперь видит виртуальные порты (Eltima Virtual Serial Port), а порты ethernet2com по прежнему отсутствуют


Напишите сюда что точно видно в диспетчере устройств по тэгу "Служба" при наличии ethernet2com порта. Я так понимаю это девайс от MOXA?

Цитата
Подскажите существует ли возможность с помощью вашей библиотеки задать параметры таймаута для последовательного порта при записи данных
конкретнее, WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant http://msdn.microsoft.com/en-us/library/aa...0(v=VS.85).aspx


В данной реализации в этом нет никакого смысла. Сейчас в библиотеки эи таймауты все нули, т.е. ф-я Write возвращает управление немедленно не дожидаясь пока данные отправятся. Поэтому ИМХО, проблема не в этом - а в том, что вы устанавливаете режим контроля потока (я попробую вечером проверить эту идею) или же это косяки драйвера или еще что-то.





Автор: good835 6.8.2010, 14:37

ethernet2com - это moxa nport 5210 - в диспетчере устройств его нет
в реестре, это HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM]"Npdrv8"="COM8" "Npdrv7"="COM7"
плюс HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npdrv, но вы его уже добавили в список
(подробнее этот параметр я приводил выше)

Если я правильно понимаю, смена ветки нужна для корректного слежения за физически подключенными портами в системе?
Может это конечно и лучше, но для каждого нового типа порта вам придется править программу...что тоже не есть хорошо

По поводу таймаутов пока думаю, разбираюсь что к чему.

Автор: kuzulis 6.8.2010, 14:58

Цитата
Если я правильно понимаю, смена ветки нужна для корректного слежения за физически подключенными портами в системе?


Нет. Это нужно для этого, пример:

1. Допустим либа 0.2.0
1.0. Запустили SerialDeviceWatcher.
1.1. Открыли порт методом open и работаем с ним.
1.2. Выдернули физически сам usb/serial конвертер из USB порта компутера.

Результат: SerialDeviceWatcher не зафиксирует событие о том что порт извлечен, т.к. записи в реестре для этого порта по путям (в 0.2.0.) останутся неизменными.

2. Допустим либа Git
2.0. Запустили SerialDeviceWatcher.
2.1. Открыли порт методом open и работаем с ним.
2.2. Выдернули физически сам usb/serial конвертер из USB порта компутера.

Результат: SerialDeviceWatcher зафиксирует момент извлечения устройства, т.к. записи по путям (в Git) автоматически удалятся!!!

Цитата
Может это конечно и лучше, но для каждого нового типа порта вам придется править программу...что тоже не есть хорошо

Ну, за все нужно платить. Это закон природы: в чемто выигрываем, а в чем то проигрываем.
На то и имеются исходники чтобы добавлять туда поддержку новых девайсов.
Тем более, их не стопицот тыщ, а с несколько десятков. :)
Тем более, если вы соберете библиотеку как *.dll/*.so то вам не придется перекомпилировать все приложение, а только библиотеку! ;)

Цитата
ethernet2com - это moxa nport 5210 - в диспетчере устройств его нет

ну так и не будет значит и либа детектить эти порты!

Автор: good835 6.8.2010, 16:40

Из документации MOXA NPORT
"Обратите внимание, что виртуальные порты MOXA НЕ отображаются в списке последовательных
портов в «Диспетчере Устройств» Windows. Это нормальное поведение для виртуальных COM-
портов: они не будут отображены в списке устройств Windows, но, при корректной настройке, будут
доступны для работы любому приложению." ???

Автор: kuzulis 6.8.2010, 17:21

Цитата
Из документации MOXA NPORT
"Обратите внимание, что виртуальные порты MOXA НЕ отображаются в списке последовательных
портов в «Диспетчере Устройств» Windows. Это нормальное поведение для виртуальных COM-
портов: они не будут отображены в списке устройств Windows, но, при корректной настройке, будут
доступны для работы любому приложению." ???


Ну, имхо, тогда никак не получится.

Автор: kuzulis 12.8.2010, 19:59

Сегодня добавил новый класс SerialDeviceEnumerator который в будущем должен заменить два класса: SerialDeviceWatcher+SerialDeviceInfo (т.е. я их планирую удалить вообще). В новом классе по идее должны работать любые девайсы.. Прошу потестить.

Автор: Litkevich Yuriy 12.8.2010, 20:30

Цитата(kuzulis @ 12.8.2010, 23:59) *
класс SerialDeviceEnumerator который в будущем должен заменить два класса: SerialDeviceWatcher+SerialDeviceInfo (т.е. я их планирую удалить вообще)
не согласен с именованием и объединением.
Название SerialDeviceEnumerator удачно и привычно. Он может заменить SerialDeviceInfo
А вот SerialDeviceWatcher всё-таки должен быть автономным (пусть внутри он и обращается к перечислителю портов, его можно сделать дружественным для перечислителя).

Автор: kuzulis 12.8.2010, 20:54

Цитата
не согласен с именованием и объединением.


Я тоже сомневался. Просто я "существенно" изменил алгоритм и реализацию SerialDeviceInfo и поэтому "пришлось" их объединить.

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


Поподробнее пжлста.

Автор: Litkevich Yuriy 12.8.2010, 21:00

Цитата(kuzulis @ 13.8.2010, 0:54) *
Поподробнее пжлста.
Я не знаю как он у тебя работает/должен_применятся.
Я думаю, что по аналогии с QFileSystemWatcher. Т.е. подключился к его сигналу, если сигнал сработает, то приложение как-то на него реагирует.

При статической сборке с приложением, если не нужен этот класс, можно его подключать - удобно

Автор: kuzulis 12.8.2010, 21:14

Цитата
Я не знаю как он у тебя работает/должен_применятся.


Ну так исходники SerialDeviceEnumerator же есть !

Фишка в том, что в реализации SerialDeviceEnumerator теперь всЁ упрощего и унифицировано, т.е.
при изменении (втыкании/вытыкании) порта теперь автоматом перечисляются все оставшиеся устройства в системе и обновляется инфа о них в мапе
QMap<QString, SerialInfo>


т.е. для получения инфы об нужном у-ве мы в данном случае просто берем уже готовую инфу для интересующего у-ва из мапы и нет необходимости для ее получения вызывать OS API. т.е. если у-во в наличии в мапе - то оно, естественно, в наличии и в ОС!!!

Получается еще удобнее чем было раньше.
Ну подумаешь, что теперь SerialDeviceEnumerator включает в себя Watcher + Info ... Ну и что с того?

Если делать как ты говоришь, то все-равно придется в Watcher включать код от Info и т.п. так какая разница? :)

Автор: good835 18.8.2010, 16:54

2 kuzulis,
если можно есть пара вопросов:
1. не получается обработать ошибку установки параметров скорости для порта, для порта на плате задаю скорость которую он не поддерживает 230400 бод, естественно возникает ошибка установки
Windows: NativeSerialEnginePrivate::nativeSetBaudRate(AbstractSerial::BaudRate baudRate)
-> function: ::SetCommConfig(this->m_descriptor, &this->cc, sizeof(COMMCONFIG)) returned: 0. Error
для обработки ошибки делаю так (как у вас в доке)
MyDevice = new AbstractSerial();
MyDevice->enableEmitStatus(true);
connect(MyDevice, SIGNAL(signalStatus(сonst QString,QDateTime)), this, SLOT(DisplayError(QString,QDateTime)));
и
void MyThread::DisplayError(QString& message, QDateTime cur_time){
qDebug() << "State: " << message << ", in time: " << cur_time.time().toString(); }
но в слот DisplayError я не попадаю, скорее всего, что это мой косяк, но пока не понимаю где...

2. можно ли сформировать список скоростей передачи поддерживаемых портом, аналогичный Диспетчер Устройств/Последовательный порт/Свойства/Параметры/Скорость передачи, что бы дать выбор при задании параметров порта, а не отлавливать ошибки при задании неверной конфигурации?

Автор: kuzulis 18.8.2010, 19:42

2 good835

1.

Цитата
не получается обработать ошибку установки параметров скорости для порта,

Т.е. вообще никакие ошибки не отлавливаются или только при установке скорости?

2.
Цитата
можно ли сформировать список скоростей передачи поддерживаемых портом, аналогичный Диспетчер Устройств/Последовательный порт/Свойства/Параметры/Скорость передачи, что бы дать выбор при задании параметров порта, а не отлавливать ошибки при задании неверной конфигурации?

Попробуйте использовать Win32 API ф-ю: GetCommProperties или что-нибудь подобное. Но не факт что оно получится. Иного решения я не знаю.
Но это не кроссплатформенное решение и поэтому я не буду это реализовывать (по крайней мере пока)

Автор: good835 19.8.2010, 10:34

2 kuzulis,

Цитата
Т.е. вообще никакие ошибки не отлавливаются или только при установке скорости?

Похоже что да, никакие, ни открытие, ни установка скорости, ни ошибка записи в порт

Автор: kuzulis 19.8.2010, 10:40

Значит что-то не так делаете

Автор: good835 19.8.2010, 12:00

2 kuzulis,
небольшое уточнение, попробовал поймать сигнал bytesWritten и вывести окошко, все получилось

connect(MyDevice, SIGNAL(bytesWritten(qint64)), this, SLOT(DisplayError3(qint64)));

а с
connect(MyDevice, SIGNAL(signalStatus(const QString,QDateTime)), this, SLOT(DisplayError(QString,QDateTime)));

по прежнему глухо, может что посоветуете?
MyDevice->enableEmitStatus(true);

нужно делать до коннекта или после?

Автор: good835 19.8.2010, 12:41

2 kuzulis,
sorry, с signalStatus разобрался, естественно это был мой косяк

Автор: rcdimon 11.10.2010, 19:23

Простите за ламерский вопрос, но как собрать и подключить библиотеку?

Открыл BuildLibrary.pro файл QTcreator'ом. Нажал собрать все. Получил какие-то файлы .o и .a... А где всякие .dll .lib? Или они не нужны?
И как теперь подключить их к своей программе?

Автор: Vatto 18.10.2010, 18:38

Здравствуйте. Во время использования библиотеки наткнулся на проблему : при открытии порта через библиотеку QSerialDevice порт открывается, но ничего принимать не хочет. Если открыть порт сначало в CommTest или в терминале, потом закрыть, и снова запустить приложение , то все работает отлично.
В чем может быть загвоздка. Версия из гита. Открываю порт как в примерах.

UsartTransmitter::UsartTransmitter(QObject *parent) 
UsartTransmitter::openPort()
UsartTransmitter::initPort()
Serial device  "COM4"  open in  OpenMode( "ReadWrite" )
= Defaults parameters =
Device name            :  "COM4"
Baud rate              :  "57600 baud"
Data bits              :  "8 bit"
Parity                 :  "None"
Stop bits              :  "1"
Flow                   :  "Disable"
Char timeout, msec     :  190

Автор: kuzulis 18.10.2010, 20:21

Цитата
Здравствуйте. Во время использования библиотеки наткнулся на проблему : при открытии порта через библиотеку QSerialDevice порт открывается, но ничего принимать не хочет.

Не имею ни малейшего понятия. У меня все работает как часы. Проверяйте сами.

Автор: Vatto 19.10.2010, 12:20

Прошу прощения. Ошибка видимо была моя. Сделал reset перед иницаилизацией праметров, и каждый задал жестко, без дефалтов и все заработало.

Автор: kuzulis 19.10.2010, 19:07

Цитата(Vatto @ 19.10.2010, 13:20) *
Прошу прощения. Ошибка видимо была моя. Сделал reset перед иницаилизацией праметров, и каждый задал жестко, без дефалтов и все заработало.

Все верно. QSerialDevive в отличии от других библиотек, при открытии порта не устанавливает параметры по умолчанию! Она только пытается определить текущие параметры! Пользователь должен сам конфигурировать порт после его открытия!
Читайте все-таки документацию!

Автор: lpn74 21.10.2010, 9:39

Добрый день!
Спасибо за библиотеку.
Существует ли такая проблемма:
При переоткрытии порта (методами OPEN и CLOSE соответственно) не вырабатывается сигнал ReadyRead?
Вернее, происходит следующее:
Переоткрыл - сигнал вырабатывается, ещё раз переоткрыл - НЕ вырабатывается, ещё раз переоткрыл - вырабатывается и т.д.
Заранее спасибо за ответы

В comport.h файле

private:
    AbstractSerial *port;

В comport.cpp

#include "comport.h"

ComPort::ComPort(QObject *parent) :
    QObject(parent)
{
    port = new AbstractSerial(this);
    port->setDeviceName("COM3");
    connect(port, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
}

void ComPort::sendData(const QByteArray &array)
{        

    port->close();
    qDebug()<< "Open port " << port->open(AbstractSerial::ReadWrite);
    qDebug() << "Write data" << port->write(array);        
}

void ComPort::slotReadyRead()
{
    qDebug() << "slotReadyRead()";
    QByteArray array = port->readAll();
    qDebug() << "array.size()=" << array.size();        
}

Автор: kuzulis 21.10.2010, 12:06

Какая ОС?

Автор: lpn74 21.10.2010, 12:25

Windows7

Автор: kuzulis 21.10.2010, 12:28

Только что пересмотрел тот код где вы переоткрываете и не увидел где вы конфигурируете порт! Может все-таки БУДЕМ ЧИТАТЬ ДОКУМЕНТАЦИЮ? ИЛИ КАК?

--
Упс, прощу прощения.. Действительно, данный косяк наблюдаю... Пробую исправить..

---

Вроде исправил, проверьте.

Автор: lpn74 22.10.2010, 5:25

Огромное спасибо!
Теперь работает :)

Автор: Гость 4.11.2010, 15:31

Возможно ли при установке параметров порта вместо:

commPort->setBaudRate(AbstractSerial::BaudRate19200);

использовать переменную типа QString, например:

QString baude = "19200";
commPort->setBaudRate(baude);

Если да то как правильно это реализовать?

Автор: kuzulis 4.11.2010, 15:48

Можно, только не

QString baude = "19200"

а
QString baude = "19200 baud"


Список всех имен скоростей которые можно подавать на вход см. вызвав метод: listBaudRate.

Автор: Гость 4.11.2010, 16:06

Спасибо работает.

Автор: Гость 12.11.2010, 18:08

Здравствуйте.
Можно ли с помощью вашей библиотеки открыть одновременно несколько портов?
В хедерном файле я прописал:
AbstractSerial *Por1t, *Port2, *Port3;
Инициализирую:
Port1->setDeviceName("/dev/ttyS0");
if(Port1->open(AbstractSerial::ReadWrite)){
.................
}

Port2->setDeviceName("/dev/ttyS1");
if(Port2->open(AbstractSerial::ReadWrite)){
.................
}

Port3->setDeviceName("/dev/ttyS2");
if(Port3->open(AbstractSerial::ReadWrite)){
.................
}
Открывает только первый.

Автор: kuzulis 13.11.2010, 18:49

Цитата
Можно ли с помощью вашей библиотеки открыть одновременно несколько портов?

Конечно можно!

Просто есть такой касяк/фича в *.nix , которая заключается в том, что при некорректном завершении программы (например при нажатии ctrl^c) библиотека не удаляет lock-файлы. И поэтому при следующем запуске оно не может открыть порт. Но если теперь еще раз запустить приложение - то порты корректно откроются... :)

Для меня это пока не существенный касяк, поэтому пока не исправляю его.

Просто необходимо перед закрытием приложения делать close() всем открытым портам и тогда всё будет хорошо.


Автор: Виталий 15.11.2010, 12:03

Просто есть такой касяк/фича в *.nix , которая заключается в том, что при некорректном завершении программы (например при нажатии ctrl^c) библиотека не удаляет lock-файлы. И поэтому при следующем запуске оно не может открыть порт. Но если теперь еще раз запустить приложение - то порты корректно откроются... :)

Мене кажется что проблема не в этом. Действительно если не закрыть порт при завершении роботы программы то он следующий раз не откроется. Но проблема состоит в том что после того как я инициирую и открываю первый из группы портов все следующие в списке не будут открыты, lock файл создается только для открытого порта (проверял через файловый менеджер /var/lock), если первый порт не будет открыт то открывается следующий из списка, а все остальные остаются закрытыми.

Автор: kuzulis 15.11.2010, 12:34

Я вчера проверял, открывал "/dev/ttyS0" и "/dev/ttyUSB0" (у меня только эти порты имеются). И все они открывались.

...
AbstractSerial port1;
AbstractSerial port2;

port1.setDeviceName("/dev/ttyS0");
port2.setDeviceName("/dev/ttyUSB0");

if (!port1.open(AbstractSerial::ReadWrite))
    qDebug("Port1 not open");
if (!port2.open(AbstractSerial::ReadWrite))
    qDebug("Port2 not open");

port1.close();
port2.close();
...
...


Не знаю в чем проблема... Попробуйте перед сборкой библиотеки раскомментировать в nativeserialengine_unix.cpp
строку вида:
//#define NATIVESERIALENGINE_UNIX_DEBUG


и после сборки и запуска посмотреть что оно в консоль сыпет...

ЗЫ: Какую версию используете?

Автор: Гость 15.11.2010, 15:49

Цитата(kuzulis @ 15.11.2010, 12:34) *
Я вчера проверял, открывал "/dev/ttyS0" и "/dev/ttyUSB0" (у меня только эти порты имеются). И все они открывались.
ЗЫ: Какую версию используете?


до этого использовал 0,2,0. сейчас пробую подключить библиотеку версии 0,3,0 из git, но после пересборки своего проекта получаю:
Цитата
./Lib/libqserialdevice.a(abstractserial.o):(.data.rel.ro._ZTV21AbstractSerialPrivate[vtable for AbstractSerialPrivate]+0x14): undefined reference to `QIODevicePrivate::peek(char*, long long)'
./Lib/libqserialdevice.a(abstractserial.o):(.data.rel.ro._ZTV21AbstractSerialPrivate[vtable for AbstractSerialPrivate]+0x18): undefined reference to `QIODevicePrivate::peek(long long)'
collect2: выполнение ld завершилось с кодом возврата 1

Автор: kuzulis 15.11.2010, 16:18

Это не 0.3.0, это уже новьё, поэтому может еще не собираться. :)
Должно собраться с >= Qt 4.7.0

Кстати, какая версия Qt4?

Чтобы собралось всё, скачайте пока что "стабильный" релиз 0.3.0. тут : http://gitorious.org/qserialdevice/qserialdevice/archive-tarball/0.3.0

Автор: Гость 15.11.2010, 16:38

Цитата(kuzulis @ 15.11.2010, 16:18) *
Кстати, какая версия Qt4?


Qt4.6.3

Большое спасибо за помощь, все работает!

Автор: megomark 16.11.2010, 16:23

Сперва хочу поблагодарить за клевую библиотеку.

Но сегодня решил использовать более новую версию библиотеки - 0.3.0 как было сказано здесь:

Цитата(kuzulis @ 15.11.2010, 15:18) *
Чтобы собралось всё, скачайте пока что "стабильный" релиз 0.3.0. тут : http://gitorious.org/qserialdevice/qserialdevice/archive-tarball/0.3.0


Я скачал, релиз 0.3.0 по указанному адресу, но заметил появившейся баг- Если подряд несколько раз открыть и закрыть устройство то программа неожиданно завершает работу. Это только у меня так или же и у других тоже ?

Автор: kuzulis 16.11.2010, 16:57

Цитата(megomark @ 16.11.2010, 16:23) *
Сперва хочу поблагодарить за клевую библиотеку.

Но сегодня решил использовать более новую версию библиотеки - 0.3.0 как было сказано здесь:
Цитата(kuzulis @ 15.11.2010, 15:18) *
Чтобы собралось всё, скачайте пока что "стабильный" релиз 0.3.0. тут : http://gitorious.org/qserialdevice/qserialdevice/archive-tarball/0.3.0


Я скачал, релиз 0.3.0 по указанному адресу, но заметил появившейся баг- Если подряд несколько раз открыть и закрыть устройство то программа неожиданно завершает работу. Это только у меня так или же и у других тоже ?


1. Какая ОС?
2. Приведи минимальный тестовый пример который воспроизводит касяк.

Если речь идет о падении тех примеров, которые идут в архиве - то оно и должно там падать, т.к. они реализованы кривоватенько, чисто чтобы показать использование. :rolleyes:

Автор: Litkevich Yuriy 16.11.2010, 17:56

Цитата(kuzulis @ 16.11.2010, 20:57) *
т.к. они реализованы кривоватенько, чисто чтобы показать использование.
дак ты их реализуй правильно, раз уж это пример

Автор: megomark 16.11.2010, 18:03

Спасибо kuzulis за быстрый ответ. Это был мой баг. Раньше устройство не закрывалось. Если я вызвал метод close(); то после не мог заново открыть устройство. Я тогда решил проблему так. Удалял объкт AbstractSerial и создавал его заново. Но в новой версии библиотеки теперь этого делать не надо. Видимо был исправлен баг.
Большое спасибо.

Автор: Виталий 18.11.2010, 11:50

Цитата(kuzulis @ 16.11.2010, 16:57) *
Цитата(megomark @ 16.11.2010, 16:23) *
Сперва хочу поблагодарить за клевую библиотеку.

Но сегодня решил использовать более новую версию библиотеки - 0.3.0 как было сказано здесь:
Цитата(kuzulis @ 15.11.2010, 15:18) *
Чтобы собралось всё, скачайте пока что "стабильный" релиз 0.3.0. тут : http://gitorious.org/qserialdevice/qserialdevice/archive-tarball/0.3.0


Я скачал, релиз 0.3.0 по указанному адресу, но заметил появившейся баг- Если подряд несколько раз открыть и закрыть устройство то программа неожиданно завершает работу. Это только у меня так или же и у других тоже ?


1. Какая ОС?
2. Приведи минимальный тестовый пример который воспроизводит касяк.

Если речь идет о падении тех примеров, которые идут в архиве - то оно и должно там падать, т.к. они реализованы кривоватенько, чисто чтобы показать использование. :rolleyes:


Автор: Виталий 18.11.2010, 11:57

Испробовал QSerialDevice с железками, неплохо сделано, однако есть пара предложений:
1. Дать возможность назначать любой BaudRate, у меня например есть железка которая нестандартный использует.
2. Дать возможность назначать структуру DCB напрямую, не все параметры нашел как менять, а железки некоторые капризные попадаются.

Автор: kuzulis 18.11.2010, 12:29

Цитата
1. Дать возможность назначать любой BaudRate, у меня например есть железка которая нестандартный использует.

С этим я в принципе согласен, но так просто добавить этот функционал не получится... Получится костыль на костыле... Для красивого решения придется оч хорошо подумать и, может быть, это приведет к изменению API библиотеки.
В общем надо подумать.

Хотя, а кто мешает переконфигурировать железку на стандартную скорость? ;)

Цитата
2. Дать возможность назначать структуру DCB напрямую, не все параметры нашел как менять, а железки некоторые капризные попадаются.

С этим не согласен, т.к. ломается кросс-платформенность и появляются ненужные методы и т.п.
Дайте пример конкретных параметров которые нужны для капризных железяк.





Автор: Виталий 18.11.2010, 14:06

Цитата(kuzulis @ 18.11.2010, 12:29) *
Цитата
1. Дать возможность назначать любой BaudRate, у меня например есть железка которая нестандартный использует.

С этим я в принципе согласен, но так просто добавить этот функционал не получится... Получится костыль на костыле... Для красивого решения придется оч хорошо подумать и, может быть, это приведет к изменению API библиотеки.
В общем надо подумать.

Хотя, а кто мешает переконфигурировать железку на стандартную скорость? ;)

Цитата
2. Дать возможность назначать структуру DCB напрямую, не все параметры нашел как менять, а железки некоторые капризные попадаются.

С этим не согласен, т.к. ломается кросс-платформенность и появляются ненужные методы и т.п.
Дайте пример конкретных параметров которые нужны для капризных железяк.


Не все железки можно переконфигурировать, ту с которой мне работать приходится спаял какой то "гений", он же видимо придумал и протокол, таких конечно мало, если есть в одном месте, значит есть и где то еще. Я добавил в исходники нужный мне BaudRate, работает, но заметил одну странность, не могу пока понять из за чего, но может из за правки исходников, завтра проверю.

Автор: Litkevich Yuriy 18.11.2010, 14:24

Цитата(Гость_Виталий_* @ 18.11.2010, 13:57) *
Дать возможность назначать структуру DCB напрямую
как ты её в Линухе собираешься использовать?

Виталий не цитируй целыми сообщениями.
Смотри http://www.forum.crossplatform.ru/index.php?showtopic=1455

Автор: Виталий 19.11.2010, 6:02

Цитата(Litkevich Yuriy @ 18.11.2010, 14:24) *
как ты её в Линухе собираешься использовать?

Ну да, вообщем то....а так удобно было бы )

kuzulis
Скачал исходники отсюда, версия 0.2.0
И вот заметил странность, ставлю AbstractSerial::BaudRate115200, а под отладчиком вижу что в setBaudRate он уже AbstractSerial::BaudRate128000 и так для любого BaudRate начиная с 9600, все передаются на одну ступень выше. Думал, что это из за того что добавлял нестандартный BaudRate, но заменил оригинальными исходниками, все пересобрал и тоже самое...может я чего то не понимаю....

Автор: kuzulis 19.11.2010, 8:55

Цитата
Скачал исходники отсюда, версия 0.2.0
И вот заметил странность, ставлю AbstractSerial::BaudRate115200, а под отладчиком вижу что в setBaudRate он уже AbstractSerial::BaudRate128000 и


Ну, эт мистика прям какая то. :)
Я 0.2.0 не поддерживаю. Текущая "типо стабильная" это 0.3.0.. Текущая "типо нестабильная" это 0.4.0, которая master ветка.

Автор: Гость 19.11.2010, 12:53

Использую порты в схеме мастер-слейв. Windows XP Pro SP3, MinGW 4.5.1, Qt 4.7.0
Возникла проблема: во время отправки данных мастером возникает замораживание GUI на несколько секунд. Поскольку я после определенного периода ожидания отправляю запросы вновь и вновь, то окна оказываются постоянно замороженными. Нашел на этом форуме решение проблемы:

Цитата
Цитата
Третий вопрос:
Произвожу отправку данных в порт функцией qint64 AbstractSerial::write(const char *data, qint64 maxSize)
Каким образом можно задать таймаут на выполнение данной функции, так как в случае ошибки передачи данных поисходит зависание программы,
например, при разрыве кабеля


Ух... тут это наверное возникает изза "режиме с управлением потоком" . Если это так, то я не сталкивался с этими особенностями и даж не представлю куда копать...
Хотя, попробуйте в методе:

void NativeSerialEnginePrivate::prepareOtherOptions()
{
this->cc.dcb.fBinary = true;
this->cc.dcb.fInX = this->cc.dcb.fOutX = this->cc.dcb.fAbortOnError = this->cc.dcb.fNull = false;
}

для this->cc.dcb.fAbortOnError = true; (вместо false)!!!


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

Это я победил, но осталась другая проблема. Использую VSPE - Virtual Serial Port Emulator - программа виртуальных COM-портов.
Создаю пару портов (Pair) в этой программе.
Запускаю программу-мастер (отправляет запросы слейву) - все нормально - порт открылся, запросы идут, GUI в порядке (использую один поток).
Запускаю программу Terminal.exe - она открывает второй порт пары и отображает полученные запросы (эмулирует слейва, но пока не отвечает) - тоже все нормально.
Отправляю любой набор байт в ответ - программа-мастер зависает на 5 секунд. Как быть? Другие программы подобным недугом не страдают.
Хочу сделать акцент на то, что такая штука возникает с VSPE, а прога очень удобная. Проверял с com0com - все нормально. Теряюсь в догадках. Help!

Автор: Гость 19.11.2010, 12:57

Еще одно дополнение: использую для чтения данных сигнал readyRead(), в слоте вызываю readAll() и посылаю дальше в программу QByteArray. Может это как-то разъяснит проблему.

Автор: Гость 19.11.2010, 13:27

Добавил setTotalReadConstantTimeout(1); после открытия порта - проблема вроде бы решилась. Правильно ли я сделал? Можно ли внести это в конструктор класса, как настройку по умолчанию

Автор: kuzulis 19.11.2010, 14:03

Цитата
Думаю, это можно было бы сделать раз и навсегда, чтобы подобных проблем не возникало.

Это я победил,

т.е. эта проблема у вас решена? а то я не стал делать this->cc.dcb.fAbortOnError = true; , т.к. тот человек мне так и не ответил, получилось у него или нет.

Цитата
Возникла проблема: во время отправки данных мастером возникает замораживание GUI на несколько секунд. Поскольку я после определенного периода ожидания отправляю запросы вновь и вновь, то окна оказываются постоянно замороженными.

Так и должно в принципе быть. Вы скорее всего используете режим Unbuffered? Если да - то при чтении данных в этом режиме функция чтения работает в блокирующем режиме, т.е. ждет данных. Поэтому желательно использовать I/O в отдельном потоке или попробовать небуферизированный режим работы или делать processEvent (или как то так).

Цитата
Отправляю любой набор байт в ответ - программа-мастер зависает на 5 секунд. Как быть? Другие программы подобным недугом не страдают.
Хочу сделать акцент на то, что такая штука возникает с VSPE, а прога очень удобная. Проверял с com0com - все нормально. Теряюсь в догадках.

Попробую разобраться что за беда.

Цитата
Еще одно дополнение: использую для чтения данных сигнал readyRead(), в слоте вызываю readAll() и посылаю дальше в программу QByteArray. Может это как-то разъяснит проблему.

В смысле?

Цитата
Добавил setTotalReadConstantTimeout(1); после открытия порта - проблема вроде бы решилась. Правильно ли я сделал? Можно ли внести это в конструктор класса, как настройку по умолчанию

Нет, нельзя. т.к. по умолчанию подразумевается работа в буферизованном режиме, и все таймауты равны 0. Только при работе в режиме Unbuffered они имеют значение (только 0 нельзя в этом режиме ставить). Да и вообще, я специально реализовал эти методы для более гибкой настройки порта и для того, чтобы вручную можно было их подобрать так, чтобы оптимальнее чтение происходило.

Почитайте ка документацию лучше, там я всё это расписал.








Автор: Гость 19.11.2010, 14:42

Цитата
т.е. эта проблема у вас решена?

Да, т.е. по всей видимости это правильный способ.

Цитата
Вы скорее всего используете режим Unbuffered?

По-моему, нет - использую метод open(AbstractSerial::ReadWrite) - как там по умолчанию не знаю. Посмотрю.

Цитата
Почитайте ка документацию лучше, там я всё это расписал.


Читал, но вскользь. Спасибо за ответ и за библиотеку :)

Автор: kuzulis 19.11.2010, 14:50

Цитата
По-моему, нет - использую метод open(AbstractSerial::ReadWrite) - как там по умолчанию не знаю. Посмотрю.

Если просто ReadWrite - то вообще никаких тормозов не должно быть.

Цитата
Читал, но вскользь. Спасибо за ответ и за библиотеку :)

Да незачто :)

Автор: panbaraban 1.12.2010, 20:50

Цитата(kuzulis @ 13.11.2010, 21:49) *
Конечно можно!

Просто есть такой касяк/фича в *.nix , которая заключается в том, что при некорректном завершении программы (например при нажатии ctrl^c) библиотека не удаляет lock-файлы. И поэтому при следующем запуске оно не может открыть порт. Но если теперь еще раз запустить приложение - то порты корректно откроются... :)

Для меня это пока не существенный касяк, поэтому пока не исправляю его.

Просто необходимо перед закрытием приложения делать close() всем открытым портам и тогда всё будет хорошо.


И снова в тред врываюсь я. Есть у меня переходник USB->RS232. Запускаю прогу, открываю порт. При открытом порте выдергиваю переходник, затем делаю close и удаляю порт.
Далее снова создаю порт и пытаюсь подключиться. Получаю кукиш. Могу подключиться только после перезапуска проги (или если удалить из /var/lock, но не пробовал ещё). Так что косяк иногда существенный, приходится прогу перезапускать, чего нехотелось бы. Поправимо ли это? Или же лучше вручную удалять локи, если таковые имеются, дабы не нарушить работу других устройств итд?
З.Ы. В системе только один подобный переходник(один юсб) , другие физически подключить некуда.

Автор: kuzulis 2.12.2010, 8:45

Цитата
Могу подключиться только после перезапуска проги (или если удалить из /var/lock, но не пробовал ещё). Так что косяк иногда существенный, приходится прогу перезапускать, чего нехотелось бы. Поправимо ли это?

В принципе всё поправимо. Пройдитесь дебаггером в момент закрытияи и посмотрите где оно косячит.

В принципе я догадываюсь в чем дело:
--------------------------------------
Суть в том, что за lock/unlock отвечает класс TTYLocker. В него передается имя порта для того, чтобы класс создавал соответствующие ему лок файлы в виде major/minor и имени (т.е. "/LCK.%1.%2" и /LCK..%1), т.е. создается сразу два лок-файла.

Для определения major/minor номера устройства используется POSIX функция stat(...) которая принимает два параметра :
один - имя устройства
второй - буфер куда будет записан major/minor.

Так вот, когда мы открыли порт open(), после этого вызывается метод TTYLocker::lock() , который создает два лок файла в которые записывает некоторые параметры.

Теперь мы закрываем порт close(), после этого вызывается метод TTYLocker::unlock(), который удаляет два лок-файла.

Но всё дело в том, что для получения имен лок-файлов, класс TTYLocker использует только имя самого порта!
Т.е. за это отвечают методы:

QString TTYLocker::getLockFileInNumericForm() const
QString TTYLocker::getLockFileInNamedForm() const


Теперь, если мы вызвали метод close(), и при этом, порт присутствует в системе, то метод
QString TTYLocker::getLockFileInNumericForm() const

вернет корректное имя лок-файла и удалит его.

НО в случае, когда мы выдернули шнурок, то порт из системы пропал, следовательно метод
QString TTYLocker::getLockFileInNumericForm() const

вернет пустое имя лок-файла, т.к. самого устройства в системе уже нет, и определить его major/minor не представляется возможным.

В данной ситуации TTYLocker удалит только один лок-файл (из двух), связанный только с именем порта, а лок-файл, связанный с major/minor останется в системе.

Теперь, мы вставляем снова шнурок и пытаемся открыть порт.. НО, класс TTYLocker видит, что уже есть лок-файл с major/minor этого порта и PID (идентификатор процесса использующего порт) равен PID-у нашего приложения, а также этот PID активен!
Поэтому TTYLocker "делает вывод" что порт уже занят!

Поэтому если мы перезапустим приложение, то TTYLocker увидит этот же лок-файл, но в нём PID уже не будет равен PID-у нашего приложения.
Поэтому TTYLocker "делает вывод" что порт свободен!
--------------------------------------

Вот вкратце чисто гипотетическое предположение что происходит.
Я пока не решил еще, правильный ли алгоритм у TTYLocker или нет. Но, хочу заметить, что я "передирал" реализацию TTYLocker из других опен сурц проектов, поэтому не думаю, что она некорректна (хотя ХЗ).

Т.е. временное решение - это в коде TTYLocker закомментировать вообще всё что связано с лок-файлом по major/minor, т.е. в итоге нужно чтобы будет создавался один лок-файл связанный только с именем устройства.
Я пока не буду трогать код, но вы для себя можете это сделать. :)

Автор: Aleksei 3.12.2010, 11:16

Добрый день
Вопрос к многоуважаемому автору.
Есть ли веские доводы при вызове AbstractSerial::close() не делать автоматом AbstractSerial::flush() ?

Автор: kuzulis 3.12.2010, 11:32

В смысле? Я ничо не понял.

Автор: BRE 3.12.2010, 12:24

Камрад спрашивает: происходит ли flush при закрытии порта? И почему? :)

Автор: panbaraban 20.12.2010, 16:57

А ещё такой вопрос. Одинаково ли работают релиз и дебаг сборки? У меня почему то не открывается порт если я компилю в релиз сборке, точнее открывается, но очень редко. :scratch_one-s_head:
Upd: Оказывается у меня руки кривые. Не знаю как удалить сообщение(

Автор: Alexk 26.12.2010, 1:22

Руки, понимаю, лечатся долго, я новичок, но никак не получается юзать либу:

Qt 4.7.0, WinXP sp3

Взял исходники из ветки master, отредактировал BuildLibrary.pro, qserialdevice.pro, qserialdeviceenumerator.pro на предмет CONFIG +=dll (+=staticlib закомментировал),
далее - qmake BuildLibrary.pro, mingw32-make (под виндой).
Переписал .dll и .a в Qt\2010.05\qt\lib, положил рядом с exe.

При запуске вылетает сразу с ошибкой 139 - проблема с точкой входа в dll.

Собирал и непосредственно qserialdevice.pro, удаляя makefile - то же самое.

В проекте INCLUDEPATH += C:\Qt\2010.05\sport\src\qserialdevice, LIBS += -lqserialdevice (c d тоже пробовал)

Ну никак! Помогите, плиз!




Автор: kuzulis 26.12.2010, 12:15

Как надо:
1. Редактировать нужно только в src.pro

Цитата
...
#CONFIG += staticlib
CONFIG += dll
...

2. Открываем BuildExamples.pro и собираем всё: и библиотеку и примеры.
3. Если хотим запустить /examples/enumerator, то копируем скомпиленную qserialdevice*.dll к екзешке enumerator*.exe
4. Запускаем QtCommandPromt , переходим к enumerator*.exe и запускаем его.

ЗЫ: эти манипуляции справедливы только в Windows.

Автор: Alexk 26.12.2010, 14:30

Библиотека и примеры компилируются, и сразу запускается AnyMaster, если с нуля, ничего не правя и записав qserialdevice-qserialdevice в например C:\Qt\2010.05, открыть QtCreator`ом BuildExamples.pro и нажать, так сказать, большую зеленую кнопку.

.a помещает в Qt\2010.05\BuildExamples-build-desktop\src\build\debug - это так и должно быть, или должно в Qt\2010.05\qserialdevice-qserialdevice\src ?

Пример так работает.

Если поправить CONFIG в src.pro, либа собирается, но примеры уже не компилит -

mingw32-make: Leaving directory `C:/Qt/2010.05/BuildExamples-build-desktop'

obj/anymaster.o: In function `AnyMaster':

C:\Qt\2010.05\BuildExamples-build-desktop\examples\anymaster/../../../qserialdevice-qserialdevice/examples/anymaster/anymaster.cpp:30: undefined reference to `operator<<(QDebug, AbstractSerial::BaudRate)'

и т.д. Вероятно, это нормально.

.dll помещает опять в Qt\2010.05\BuildExamples-build-desktop\src\build\debug.

С полученной .dll моя прога работать не хочет, опять 139 ошибка (там только создание экземпляра класса, больше совсем ничего, и #include <abstractserial.h>, как в примере, и dll лежит рядом с ехе), а примеры проверить не могу.


Охотно проверю любую версию)

Автор: kuzulis 26.12.2010, 15:38

Цитата
C:\Qt\2010.05\BuildExamples-build-desktop\examples\anymaster/../../../qserialdevice-qserialdevice/examples/anymaster/anymaster.cpp:30: undefined reference to `operator<<(QDebug, AbstractSerial::BaudRate)'

Возьмите сегодняшний master. Я там это исправил.

Цитата
так сказать, большую зеленую кнопку.

не надо нажимать кнопок. запускать надо через Qt Command Promt или заранее прописав в PATH пути к либам Qt и MinGW.

Цитата
.a помещает в Qt\2010.05\BuildExamples-build-desktop\src\build\debug - это так и должно быть, или должно в Qt\2010.05\qserialdevice-qserialdevice\src ?

Должно быть, всегда библиотеку помещает в \BuildExamples-build-desktop\src\build\debug(release).

Цитата
С полученной .dll моя прога работать не хочет, опять 139 ошибка (там только создание экземпляра класса, больше совсем ничего, и #include <abstractserial.h>, как в примере, и dll лежит рядом с ехе), а примеры проверить не могу.

Разбираться что у Вас не работает в Вашем приложении я не буду. Для Вас специально созданы примеры /examples , они работают так как задумано. Сделайте у себя по аналогии. В чем проблема?

Цитата
.dll помещает опять в Qt\2010.05\BuildExamples-build-desktop\src\build\debug.

А куда ей помещать?
Если хотите использовать shared (*.dll) библиотеку - то напишите сами себе *.pro файл так как Вам нужно чтобы оно помещало туда куда Вам надо.


В общем, почитайте assistent и что нить про разделяемые библиотеки.





Автор: Alexk 26.12.2010, 18:17

Спасибо большое!

Все компилируется и работает. Н-да, только в треде намусорил, виноват.

Автор: Sasha07 7.1.2011, 9:00

Доброго времени суток, форумчане!
Возникла проблема (видимо с руками) при чтении/записи с использованием QSerialDevice.
ОС ubuntu 10.10, usb-->rs переходник. На том конце управляемый коммутатор. Библиотеку стянул сегодня, собралась без проблем.
Вот только как отдать железке данные, понятные ей и забрать понятные мне не пойму...
Вывод QDebug :

Раскрывающийся текст
[/expand]
[expand]= New parameters =
Device name : "/dev/ttyUSB0"
Baud rate : "57600 baud"
Data bits : "8 bit"
Parity : "None"
Stop bits : "1"
Flow : "Disable"
Char timeout, msec : 0
open mode : OpenMode( "ReadOnly|WriteOnly" )
port error : "Unknown error"
port lineStatus : 6
log : 0x9939128
read : ""
log : 0x9939128
read : ""
log : 0x9939128
read : ""
log : 0x9939128
read : ""
log : 0x9939128
read : ""
log : 0x9939128
read : ""


Код:

Раскрывающийся текст
AbstractSerial *port = new AbstractSerial;
QByteArray a,b,inputBuffer;

QString *logText = new QString;


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
ui->setupUi(this);

port->setDeviceName("/dev/ttyUSB0");
connect( port, SIGNAL(readyRead()), this, SLOT(ReadData()));
connect( port, SIGNAL(signalStatus(QString,QDateTime)), this, SLOT(State(QString,QDateTime)));

if (port->open(AbstractSerial::ReadWrite))
     ui->label->setText("open!");

port->reset();
port->setBaudRate(AbstractSerial::BaudRate57600);
port->setFlowControl(AbstractSerial::FlowControlOff);
port->setDataBits(AbstractSerial::DataBits8);
port->setParity(AbstractSerial::ParityNone);
port->setStopBits(AbstractSerial::StopBits1);

qDebug() << "= New parameters =";
qDebug() << "Device name            : " << port->deviceName();
qDebug() << "Baud rate              : " << port->baudRate();
qDebug() << "Data bits              : " << port->dataBits();
qDebug() << "Parity                 : " << port->parity();
qDebug() << "Stop bits              : " << port->stopBits();
qDebug() << "Flow                   : " << port->flowControl();
qDebug() << "Char timeout, msec     : " << port->charIntervalTimeout();
qDebug() << "open mode              : " << port->openMode();
qDebug() << "port error             : " << port->errorString();
qDebug() << "port lineStatus        : " << port->lineStatus();

}

void MainWindow::ReadData()
{
   if (!port->waitForReadyRead(500))
        qDebug() << "Response timeout.";
  qint64 ba_count= port->bytesAvailable();
   QByteArray ba = port->read(ba_count);

   inputBuffer.append(ba);
       if (inputBuffer.contains("\n"))                                 // Если пришёл конец строки
       {
           QString ba_str(inputBuffer);
           inputBuffer.clear();
         logText->append(QString("<b>></b> %1").arg(ba_str));       // Записываем посылаемые данные в лог
       }

    QString ba1_str(ba);
    qDebug () << "log    : "  << logText;
    qDebug () << "read   : "  << ba1_str;
}

void MainWindow::State(QString stateMsg,QDateTime dt)
{

  qDebug() << "State: " << stateMsg << ", in time: " << dt.time().toString();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{


port->write(ui->lineEdit->text().toAscii() +'/r');
ui->lineEdit->clear();
// qDebug() << "port error             : " << port->errorString();
// qDebug() << "port line state        : " << port->lineStatus();

}

void MainWindow::on_pushButton_2_clicked()
{
  port->flush();
}



Сильно не пинайте - это моя первая программа на qt.

Автор: kuzulis 7.1.2011, 14:38

1. Зачем в слоте ReadData вы делаете port->waitForReadyRead(500) ?
2. Чтобы посмотреть что читается - понавставляйте qDebug-ов после QByteArray ba = port->read(ba_count);
3. А насчет того как отдавать/забирать данные железке - это вам виднее, читайте документацию, смотрите примеры.


Автор: Sasha07 7.1.2011, 19:46

1. Зачем в слоте ReadData вы делаете port->waitForReadyRead(500) ?
2. Чтобы посмотреть что читается - понавставляйте qDebug-ов после QByteArray ba = port->read(ba_count);
3. А насчет того как отдавать/забирать данные железке - это вам виднее, читайте документацию, смотрите примеры.

1. Не заработало корректно - начал лепить и перебирать что попало.
2. Изначально лепил qDebug, в ответ или то что ввожу (т.е. ответа от железки нет) или иероглифы.
3. Видимо у меня проблемы с кодировкой записи в порт, + кривые руки, поэтому и писал:

Цитата
Сильно не пинайте - это моя первая программа на qt.


Если кто - то сталкивался с такой проблемой дайте кусок кода в котором идет преобразование qstring -> to qbytearray при записи и наоборот при чтении. qstring-toASCII, UTF-8 и т.д. не спасает.
Заранее благодарен.

kuzulis, спасибо за библиотеку!

Автор: Litkevich Yuriy 7.1.2011, 22:49

Цитата(Sasha07 @ 7.1.2011, 21:46) *
Видимо у меня проблемы с кодировкой записи в порт
устройство в символьном (ASCII) режиме работает?

Автор: Sasha07 8.1.2011, 9:32

Цитата
устройство в символьном (ASCII) режиме работает?


Думаю да, гипертерминал и putty с ним нормально работают, в настройках putty по дефолту стоит unicode.

Автор: Sasha07 9.1.2011, 1:03

Цитата
устройство в символьном (ASCII) режиме работает?


Нашел serial port monitor 4, он разрешает писать следующие типы данных в порт : string, hex, oct, demical, bin. Так вот, при записи string строка пишется и читается корректно, но /r , /n, /r/n , CR - не отправляет железке команду перевода каретки, тип oct, ввожу 15 return отрабатывает. также с bin, и hex, demical.

Dump view : 45 6e 74 65 72 20 69 6e 74 6f 20 73 74 70 20 6d Enter into stp m - то что возвращается из порта.
Как отправить/ получить символ возврата каретки и символ новой строки (/n) используя данную библиотеку?
Заранее благодарен.






Автор: Litkevich Yuriy 9.1.2011, 5:41

управляющие символы ASCII используют обратный слэш:
\r
\n
\rn

Цитата(Sasha07 @ 9.1.2011, 3:03) *
Нашел serial port monitor 4
Это устройство так называется?

Автор: Sasha07 9.1.2011, 10:02

[quote]управляющие символы ASCII используют обратный слэш:
\r
\n
\rn
[quote]
Да как только не извращался уже - все равно их железка читает как обычные символы.

serial port monitor 4 - программа под винду для диагностики и дампа данных c com port.
Непосредственно с нее и работал с коммутатором, чтобы понять чего ему надо.
Строки коммутатор воспринимает, а вот управляющие символы в String отправить не получается, коммутатор воспринимает их как строку и все.

Автор: kuzulis 9.1.2011, 13:21

Цитата
Строки коммутатор воспринимает, а вот управляющие символы в String отправить не получается, коммутатор воспринимает их как строку и все.

Ну так смекнуть нужно и формировать данные в виде QByteArray и слать их устройству.
...
QString s("моя команда или хз что там")
QByteArray data;
data.append(s);
data.append('\r');
port.write(data);
...


Это же элементарно, Ватсон (с)

Автор: Алексей1153 9.1.2011, 13:33

Цитата(Litkevich Yuriy @ 9.1.2011, 7:41) *
\rn

вообще-то так:
\r\n

Автор: Sasha07 9.1.2011, 16:52

Цитата
Это же элементарно, Ватсон (с)

:rolleyes: , благодарю - работает.
Еще раз спасибо за библиотеку!

Автор: Litkevich Yuriy 9.1.2011, 18:57

Цитата(Алексей1153 @ 9.1.2011, 15:33) *
вообще-то так:
\r\n
да, ты прав

Автор: good835 11.1.2011, 19:32

Добрый день!
Работаю с некоторой железкой, которая работает в режиме С Управлением потоком. Обновил библиотеку из репозитария, появилось несколько вопросов:
1. Теперь после открытия порта IsOpenCorrectrly = MyDevice->open(AbstractSerial::ReadWrite) железка говорит, что RTS установлен, раньше такого не было
2. После успешного открытия порта и установки параметров пытаюсь установить RTS
порт сконфигурирован как (MyDevice->setFlowControl(AbstractSerial::FlowControlOff);
MyDevice->setRts(true) возвращает false?
Если же порт был сконфигурирован без управления потоком (MyDevice->setFlowControl(AbstractSerial::FlowControlOff), то RTS - успешно устанавливается
и ПРОГРАММА УСПЕШНО работает, так, как будто управление потоком установлено.
Спасибо.



Цитата(good835 @ 11.1.2011, 19:22) *
Добрый день!
Работаю с некоторой железкой, которая работает в режиме С Управлением потоком. Обновил библиотеку из репозитария, появилось несколько вопросов:
1. Теперь после открытия порта IsOpenCorrectrly = MyDevice->open(AbstractSerial::ReadWrite) железка говорит, что RTS установлен, раньше такого не было
2. После успешного открытия порта и установки параметров пытаюсь установить RTS
порт сконфигурирован как (MyDevice->setFlowControl(AbstractSerial::FlowControlOff);
MyDevice->setRts(true) возвращает false?
Если же порт был сконфигурирован без управления потоком (MyDevice->setFlowControl(AbstractSerial::FlowControlOff), то RTS - успешно устанавливается
Спасибо.


Автор: kuzulis 11.1.2011, 20:56

Вообще-то я не тестировал связь с управлением потоком. (Тестировал только без, т.к. влом было паять нуль-модемный кабель с подключением всех 9-ти пинов).
Так что проверить не смогу, имею только GND, RX, TX :)

Что за ОС?

Цитата
1. Теперь после открытия порта IsOpenCorrectrly = MyDevice->open(AbstractSerial::ReadWrite) железка говорит, что RTS установлен, раньше такого не было

Насчет установки RTS и DTR - то да, при открытии порта они устанавливаются (по крайней мере в винде)!
Просто в Винде (а я подозреваю, что вы в ней кодите) ранее метод lineStatus() не мог определять состояния линий DTR и RTS.
Эта фича (определение статуса этих линий) появилась буквально неделю назад. Если я правильно понял.

Я думаю (на днях) добавить в метод открытия порта еще возможность указания желаемого состояния линий DTR, RTS порта.
То, что происходит сейчас - хз что, я копипастил эти методы из QextSerialPort особо не проверяя их.

В общем, нужно разобраться. Попробуйте поиграться при открытии с флагами из DCB (для винды):
Цитата
...
fDtrControl
...
fRtsControl
...


и напишите что вышло и с какими комбинациями для разных режимов контроля потока.

Цитата
2. После успешного открытия порта и установки параметров пытаюсь установить RTS
порт сконфигурирован как (MyDevice->setFlowControl(AbstractSerial::FlowControlOff);
MyDevice->setRts(true) возвращает false?
Если же порт был сконфигурирован без управления потоком (MyDevice->setFlowControl(AbstractSerial::FlowControlOff), то RTS - успешно устанавливается
и ПРОГРАММА УСПЕШНО работает, так, как будто управление потоком установлено.


По идее, если установлен аппаратный контроль управления потоком - то setRts и не должен работать, т.к. всю работу делает драйвер, хотя ХЗ.
В общем, нужно упорно разбираться еще. :)

ЗЫ: Я тут пишу тестовое GUI приложение (с кнопочками, терминалом и т.п.) в котором можно будет опробовать все краеугольные моменты, думаю, завтра к вечеру (по мск.) выложу в Git. Вот тогда и начну вникать, а пока что, пробуйте сами понять в чем проблема.


Автор: good835 12.1.2011, 12:46

Продолжаю разобираться с работой порта в режиме упаравления потоком

fRtsControl - пробовал в двух вариантах RTS_CONTROL_ENABLE (это то что нужно моему приложению) и RTS_CONTROL_HANDSHAKE
в обоих вариантах - RTS устанавливается либо при открытии порта (по моему читается предыдущая конфигурация порта DCB, так как порт еще не конфигурился)
либо при конфигурировании setFlowControl(AbstractSerial::FlowControlOff)
при этом
1. функция setRTS(true) - возвращает false - но возможно это и правильно, так как RTS уже активен
2. функция lineStatus() - говорит что RTS - не установлен ??? вот это не понятно

если открыть порт без управления потоком, то связка setRTS(true) + lineStatus() - отрабатывает нормально

Автор: good835 12.1.2011, 14:06

небольшое дополнение
возможно вызов lineStatus() - должен быть с некоторый таймаутом после открытия и конфигурирования порта
если смотреть после открытия - то RTS - не установлен
если через паузу (не таймером просто некоторые задачки еще выполняются перед записью) - то RTS установлен

Автор: silver47 8.2.2011, 12:37

Доброго времени суток.
У меня такая проблема появилась. Заметил, что читаю из порта максимум 4096 байт. Чтение происходит таким образом:

QByteArray data(port->readAll());

Где я ошибся? Спасибо.

Автор: Litkevich Yuriy 8.2.2011, 14:03

дак наверное буфер порта имеет только 4к, смотри в настройках драйвера устройства

Автор: silver47 8.2.2011, 14:06

Цитата(Litkevich Yuriy @ 8.2.2011, 16:03) *
дак наверное буфер порта имеет только 4к, смотри в настройках драйвера устройства


Порт виртуальный - ELTIMA Virtual Serial Port. Порты, созданные другими программами (например, Virtual Serial Ports Emulator) не определяются этой библиотекой. Как понял, определяются только те порты, которые есть в диспетчере устройств в ветке "Порты LPT и COM". А где те, которые создаются Virtual Serial Ports Emulator не знаю. Но вопрос не в этом, а в том как получить все, что программа на другом конце записала в порт (~100 кб).

Программа, написанная другим человеком, на делфне читает всё полностью. Может можно как-то последовательно прочитать?

Windows 7; Qt 4.7

Автор: Litkevich Yuriy 8.2.2011, 14:35

Цитата(silver47 @ 8.2.2011, 16:06) *
Созданные другими программами не определяются этой библиотекой
не понял фразы

Автор: kuzulis 8.2.2011, 19:17

Цитата(silver47 @ 8.2.2011, 14:06) *
Порт виртуальный - ELTIMA Virtual Serial Port.

Самый хороший из всех эмуляторов! Имхо.

Цитата(silver47 @ 8.2.2011, 14:06) *
Порты, созданные другими программами (например, Virtual Serial Ports Emulator) не определяются этой библиотекой. Как понял, определяются только те порты, которые есть в диспетчере устройств в ветке "Порты LPT и COM". А где те, которые создаются Virtual Serial Ports Emulator не знаю.

Так и должно быть.

Цитата(silver47 @ 8.2.2011, 14:06) *
Программа, написанная другим человеком, на делфне читает всё полностью. Может можно как-то последовательно прочитать?

В ELTIMA Virtual Serial Port Driver включите эмуляцию baudrate и будет счастье.

Автор: silver47 8.2.2011, 19:41

Цитата(kuzulis @ 8.2.2011, 21:17) *
В ELTIMA Virtual Serial Port Driver включите эмуляцию baudrate и будет счастье.

На реальном железе это не вылезет?
Тогда еще вопрос, как получать состояние линий, в примере только про DSR и CTS. За библиотеку спасибо, мне кажется более логичной и удобной чем qextSerialDevice.

Автор: kuzulis 8.2.2011, 19:47

Цитата(silver47 @ 8.2.2011, 19:41) *
На реальном железе это не вылезет?

Нет, не вылезет, я только что проверил (на всякий случай).

Цитата(silver47 @ 8.2.2011, 19:41) *
Тогда еще вопрос, как получать состояние линий, в примере только про DSR и CTS.

Эммм.. посмотрите пример в /test/guiapp , читайте документацию и т.п.

PS: возьмите из git текущую ветку master : http://gitorious.org/qserialdevice/qserialdevice/archive-tarball/master

Автор: rcdimon 18.2.2011, 15:31

Какую максимальную скорость передачи данных Вам удавалось получить?

Я передаю в компьютер пакеты по 9 байт. С интервалом 200 мс между пакетами. Если быстрее- программа подвисает. Программа сама по себе не большая и не сложная. Какие есть способы повысить скорость приема данных?

Автор: kuzulis 18.2.2011, 16:48

Цитата(rcdimon @ 18.2.2011, 15:31) *
Какую максимальную скорость передачи данных Вам удавалось получить?

Я передаю в компьютер пакеты по 9 байт. С интервалом 200 мс между пакетами. Если быстрее- программа подвисает. Программа сама по себе не большая и не сложная. Какие есть способы повысить скорость приема данных?

1. Насчет скорости - зависит от типа UART , т.е. у разных м/сх (контроллеров и т.п.) разные верхние планки бод.
2. Самый "простой" способ - это использовать потоки (threads).

ЗЫ: Я только что сам попробовал на скорости 9600 бод передавать ~20 байт с интервалом ~10 мс и подтверждаю, тормозит :).
Я посмотрю что можно предпринять (если будет время) , может что-то в коде библиотеки не то, может еще что, а может иные причины, а может так и должно быть. :)

ЗЫЗЫ: Должно помочь редактирование файла nativeserialengine_win.cpp (если вы используете винду).
Нужно найти метод qint64 NativeSerialEnginePrivate::nativeWrite(const char *data, qint64 len), всё в нем удалить и
оставить только это:
qint64 NativeSerialEnginePrivate::nativeWrite(const char *data, qint64 len)
{
    if (!clear_overlapped(&this->oWrite))
        return qint64(-1);

    ::DWORD writeBytes = 0;
    ::WriteFile(this->descriptor, (LPCVOID)data, (DWORD)len, &writeBytes, &this->oWrite);

    return len;
}


Автор: rcdimon 18.2.2011, 20:58

Я, конечно, попробую Ваш совет, но не думаю что дело в этом.

Возьмем любую другую программу для работы с ком-портом, например Terminal. Когда идет большой поток данных она начинает захлебываться и терять данные. GUI тормозит.

А, например, драйвер модема не тормозит и отлично принимает данные даже на самых высоких скоростях. Наверное следует попробовать отвязать GUI от работы с портом. Наверное в этом дело. Запускать в разных потоках.

Автор: BRE 18.2.2011, 22:23

kuzulis, этот метод должен возвращать реальное число записанных байт (writeBytes), а не то количество? которое хотели записать (len).

qint64 NativeSerialEnginePrivate::nativeWrite(const char *data, qint64 len)
{
    if (!clear_overlapped(&this->oWrite))
        return qint64(-1);

    ::DWORD writeBytes = 0;
    ::WriteFile(this->descriptor, (LPCVOID)data, (DWORD)len, &writeBytes, &this->oWrite);

    return len;
}


Автор: kuzulis 18.2.2011, 22:36

Цитата
kuzulis, этот метод должен возвращать реальное число записанных байт (writeBytes), а не то количество? которое хотели записать (len).

По идее да, это так. Но на практике из-за того что нам надо знать реально сколько байт записалось - нам придется дождаться завершения операции I/O - и только после этого мы сможем узнать сколько байт записали. А ожидание I/O (через WaitSingleObject/GetOverlappedResult) - это фризы !
Т.е. WriteFile возвращается немедленно - но не факт что оно возвратит True и не факт что оно возвратит реальное кол-во записанных байт.

Поэтому всё нафик удаляем и считаем что сколько байт записали - столько и записалось! Иного способа (кроме потоков) я не вижу.

Цитата
Я, конечно, попробую Ваш совет, но не думаю что дело в этом.

В этом, в этом... Не сомневайтесь. Я проверил.

ЗЫ: Все-таки придется наверное что-то с этим делать.


Автор: BRE 18.2.2011, 22:45

Цитата(kuzulis @ 18.2.2011, 22:36) *
Поэтому всё нафик удаляем и считаем что сколько байт записали - столько и записалось! Иного способа (кроме потоков) я не вижу.

Такое допущение можно сделать в конкретной программе, работающей с конкретной железкой и будучи абсолютно уверенным что все будет реально записано, но, IMHO, для библиотеки это не выход.

Я так понимаю, что это ожидание происходит у тебя же в библиотеке, только уровнем выше?

Автор: kuzulis 19.2.2011, 10:23

Цитата
Такое допущение можно сделать в конкретной программе, работающей с конкретной железкой и будучи абсолютно уверенным что все будет реально записано, но, IMHO, для библиотеки это не выход.

Ну иначе (для винды) я не знаю иного выхода. В винде реальное кол-во записанных байт можно узнать только после завершения операции IO (т.е. не WriteFile их возвращает, а GetOverlappedResult).
Поэтому есть два выхода (для винды):
1. Или ждать завершения и получить реальное кол-во записанных байт (но это фризы)
2. Или не ждать завершения и считать что все что передали передастся.

BRE, если у тебя есть иные мысли то поделись. :)

Цитата
Я так понимаю, что это ожидание происходит у тебя же в библиотеке, только уровнем выше?

Нет, что касаемо записи - то нет. Если рассматривать винду - то ожидание происходит в nativeWrite (через WaitForSingleObject + GetOverlappedResult).
А если linux - то никакого ожидания нет в принципе вообще.

Автор: BRE 19.2.2011, 12:11

Цитата(kuzulis @ 19.2.2011, 10:23) *
BRE, если у тебя есть иные мысли то поделись. :)

Ну в свете твоих объяснений - мыслей нет. :)
Я не силен в том, как работает венда с последовательным портом, поэтому увидев эту функцию, по аналогии с linux, предположил, что стоит проверять, а что же реально записалось.
Если реально это значение возвращается и можно проверить где-то еще, то ты выбрал вполне нормальное решение.

Автор: Гость_kuzulis_* 19.2.2011, 12:54

Цитата
по аналогии с linux, предположил, что стоит проверять, а что же реально записалось.

Ну так в линуксе (если неблокирующий дескриптор/сокет) ,ИМХО, ф-я write тоже может возвратить меньшее кол-во байт чем мы пишем. Но это не значит, что записалось столько - сколько она возвратила.

Поэтому, ИМХО, судить о том сколько байт записалось по возвращаемому функциями write (что в винде, что в линуксе) нельзя. Хотя, могу ошибаться :).

Автор: kuzulis 19.2.2011, 12:55

Блин, зарегаться забыл. :)

Автор: rcdimon 19.2.2011, 13:31

Хм... Я вроде говорил, что тормозит при приеме, а не при отправке )

Автор: kuzulis 19.2.2011, 14:38

Цитата(rcdimon @ 19.2.2011, 13:31) *
Хм... Я вроде говорил, что тормозит при приеме, а не при отправке )

Ну тогда попробуй такой код:
qint64 NativeSerialEnginePrivate::nativeRead(char *data, qint64 len)
{
    if (!clear_overlapped(&this->oRead))
              return qint64(-1);

    ::DWORD readBytes = 0;
    if (::ReadFile(this->descriptor, (PVOID)data, (DWORD)len, &readBytes, &this->oRead)) {
    }
    else {
        ::DWORD rc = ::GetLastError();
        readBytes = (ERROR_IO_PENDING == rc) ? (0) : (-1);
    }

    return qint64(readBytes);
}

Автор: sh2ka 23.2.2011, 22:05

kuzulis
Windows XP/7, QSerialDevice (master), mingw32 4.5.2 dwarf2.

Я уже писал по поводу поддержки библиотекой виртуальных портов. В частности, о поддержке виртуальных портов VSPE (virtual serial port emulator). Аналогичная проблема наблюдается и для виртуальных портов для устройства MOXA NPort (удаленные порты через Ethernet). Люди используют виртуальные порты не чуть не реже, чем реальные (возможно, даже чаще: usb-com, ethernet-com, ...), а поддержки этих портов в библиотеке нет. Хотелось бы видеть эти порты в списке портов. Возможно разделение этих списков в API библиотеки:



Хотя это выглядит не хорошо. Может быть можно как-то отображать эти устройства в списке независимо от того, можно отслеживать их исчезновение или нет - если нет возможности отслеживать появление и исчезновение порта в системе, то пусть оно всегда будет в списке (это ведь не криминал).
Т.о. поскольку записи портов в реестре дублируются (но не всех портов), то можно отслеживать появление/исчезновение только реальных портов в ветке [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\...], а для прочих устройств (у которых нет двойника в указанной ветке) - нет. Под прочими портами подразумеваются порты из [HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM], которых нет в [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\...].

Как вариант, можно сделать опцию для включения/отключения поддержки виртуальных портов в qserialdeviceenumerator, хотя это странновато, т.к. порты спокойно открываются с помощью qserialdevice как реальные, так и виртуальные, однако, последних нет в списках - ДИСКРИМИНАЦИЯ!!!

Считаю, что это некоторое упущение, т.к. например, в ОС виртуальные приводы отображаются также, как и реальные и работа с ними выполняется аналогично. Библиотека как раз-таки должна выполнять роль унифицированного интерфейса для работы с однотипными элементами - портами - не важно, реальными или виртуальными, особенно, если этого не делает ОС.

Много написал, но смысл прост - люди недоумевают: почему нельзя показать в списке виртуальные порты (они что, какие-то не такие, недоделанные что-ли?), чтобы их можно было выбрать, тем более, что они имеют линейное пространство имен вместе с реальными: COM1, COM2, COM3, ...

И, собственно, вопрос: можно ли как-то сделать, чтобы в списке отображались все реальные и виртуальные порты системы?

Цитата
Цитата

А ты можешь пока проверить, есть ли сигнал от изчезновения уже открытого порта в венде? На той версии, что уже есть. Ибо у меня пока нет возможности что-то под оной собрать.


Я проверил под виндой. Да, таже проблемка :) . Но я знаю как решить.. Просто нужно "слушать" другие ветки реестра и все должно быть нормуль.


У меня это вызывает недоумение: как физический (настоящий) COM-порт может взять и исчезнуть из системы - "на горячую"? - но это аварийная тогда ситуация и нет смысла ее обрабатывать; или usb-com - тогда это уже виртуальный порт - опять неувязочка. Одним словом непонятно, чем не устраивает ветка реестра [HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM], в которой просто и понятно представлены все порты - ОС уже позаботилась о том, кому нужен список портов - просто возьми?

Есть еще один способ получить список портов системы, который мы использовали раньше в своем коде под WinAPI: QueryDosDevice, в которую передается имя утройства, которое проверяется на наличие - можно простым перебором от COM1 до COM255 быстро проверить наличие всех доступных портов, хотя это может быть не совсем правильным решением.

Автор: kuzulis 23.2.2011, 23:06

Цитата
или usb-com - тогда это уже виртуальный порт - опять неувязочка.

Ну так его же можно выдернуть, ведь правда?! И он же исчезнет!? ;)
Не вижу неувязочек.

Цитата
Я уже писал по поводу поддержки библиотекой виртуальных портов.

Поддержка имеется, и я не пойму к чему такая "экспрессия".

Цитата
В частности, о поддержке виртуальных портов VSPE (virtual serial port emulator).

Этот софт реализован через (Ж), и эти порты не определяются в диспетчере устройств.
Поэтому для енумератора их нет!
Тем более, нельзя вытянуть никакой информации об этом виртуальном устройстве (ну, кроме его имени).
Этот софт оставляет в реестре о себе информацию только в одном месте :
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM] и всё.
Какой черт я буду из-за какой-то хрени что-то переписывать? :)
Используйте вместо VSPE софт от Eltima (или com0com на крайняк).

Цитата
Аналогичная проблема наблюдается и для виртуальных портов для устройства MOXA NPort (удаленные порты через Ethernet).

Я в курсе что такое MOXA NPort.
Если после установки ПО от MOXA эти порты появляются в диспетчере устройств - то не вижу никаких проблем в том, чтобы добавить их поддержку.
Для этого мне нужна кое-какая дополнительная информация: class GUID этого устройства.
Если же оно оставляет о себе инфу аналогично VSPE - то увы...

Цитата
почему нельзя показать в списке виртуальные порты (они что, какие-то не такие, недоделанные что-ли?),

Зависит от производителя ПО, но в большинстве случаев - да, недоделанные.











Автор: kuzulis 24.2.2011, 12:50

Цитата(kuzulis @ 23.2.2011, 23:06) *
Я в курсе что такое MOXA NPort.
Если после установки ПО от MOXA эти порты появляются в диспетчере устройств - то не вижу никаких проблем в том, чтобы добавить их поддержку.
Для этого мне нужна кое-какая дополнительная информация: class GUID этого устройства.
Если же оно оставляет о себе инфу аналогично VSPE - то увы...

Сегодня проверил на MOXA NPort 5130 - и всё работает "из каропки"!!!
Так что вы сначала определитесь и проверьте - а потом что-то предъявляйте!

Автор: sh2ka 25.2.2011, 22:02

Нет, я все-таки против такой жесткой политики. Дело в том, что виртуальный порт VSPE как-то открывается системой, хоть он только в неподдерживаемой библиотекой ветке - система-то его поддерживает - CreateFile делает все правильно. Нужно только видеть этот порт в списке. Если можно как-то отследить исчезновение порта из системы и его появление, то никто не говорит, что этого делать не стоит. Но если отследить это невозможно в силу определенных условий, то и не нужно - пусть всегда будет в списке. Мне просто кажется, что библиотека выглядела бы более полноценно, если она помогала пользователю даже в том случае, когда разработчики драйверов портов (виртуальных и других - например, для мультипортовых плат) что-то недоделали, т.е. изловчиться, но дать пользователю как можно больше информации, а не упираться и говорить, что ее нет (когда она хоть частично, но есть). Примером такого являются интернет браузеры, которые исправляют столько ошибок на сайтах, чтобы пользователь смог увидеть страницу, пусть даже и не в первозданном виде. Это опыт разработчиков, накопленный за столько лет работы интернет сети, и он мне подсказывает, что нужно делать именно так. Это моя позиция.

Ну, да, ладно - реализуем сами и приставать больше не буду - тем более, что мы планируем в скорем времени переходить на Linux (думаем использовать Ubuntu). Надеюсь, там таких проблем не будет, т.к. все устройства в системе - это "реальные" файлы - и других вариантов нет.

А за библиотеку - отдельное СПАСИБО!

Еще хотел бы узнать: что значат комментарии в коде вида `//?`, если не секрет?

Автор: Litkevich Yuriy 26.2.2011, 7:31

Цитата(sh2ka @ 26.2.2011, 0:02) *
у, да, ладно - реализуем сами и приставать больше не буду
сделай на гиторусе клона, и работай. Если твоё решение окажется стабильным, можешь предложить автору воспользоваться твоими изменениями. От протестированной версии он вряд ли откажется :)

Автор: Гость 2.3.2011, 11:41

помогите собрать! как её вообще собирать ??? :) на vs2008 реально собрать? qtcreator? никак не получается в общем :( а почему сразу готовых откомпилированных файлов нет? =\

вот этот мокфайл :: error: [build/lib/qintegratedserialdevice/moc/moc_serialdevicewatcher.cpp] Error 1 всё время с ошибкой собирается

в vs2008 жалуется на строку

// case 1: d_func()->_q_processAvailableNotifier(); break;

если закомментировать то собирается но дллки нет! она должна быть вообще?

что такое qserialdevice0.dll.intermediate.manifest где сама длл?

:blush: :blush: :blush:

Автор: kuzulis 2.3.2011, 11:58

Цитата(Гость @ 2.3.2011, 11:41) *
помогите собрать! как её вообще собирать ??? :) на vs2008 реально собрать? qtcreator? никак не получается в общем :( а почему сразу готовых откомпилированных файлов нет? =\

вот этот мокфайл :: error: [build/lib/qintegratedserialdevice/moc/moc_serialdevicewatcher.cpp] Error 1 всё время с ошибкой собирается

в vs2008 жалуется на строку

// case 1: d_func()->_q_processAvailableNotifier(); break;

если закомментировать то собирается но дллки нет! она должна быть вообще?

что такое qserialdevice0.dll.intermediate.manifest где сама длл?

:blush: :blush: :blush:


Качайте отсюда: http://gitorious.org/qserialdevice/qserialdevice/trees/master
версию 0.4.0 или из master.

Как собирать - расписано в Readme или тут: http://www.wiki.crossplatform.ru/index.php/QSerialDevice:%D0%A1%D0%B1%D0%BE%D1%80%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8.

В VS - хз, не проверял, если что отпишитесь.

ЗЫ: То что Вы пытаетесь собирать - уже давным давно устарело и репозиторий переехал на http://gitorious.org/

Автор: Гость 2.3.2011, 12:08

спасибо! ;) сейчас качну! а на чем собирать лучше??? :)

Автор: kuzulis 2.3.2011, 12:28

Цитата(Гость @ 2.3.2011, 12:08) *
спасибо! ;) сейчас качну! а на чем собирать лучше??? :)

Без разницы. Если привыкли к VS компилятору и всё делаете в нём - то VS, если в MinGW - то MinGW.
PS: Я тестирую на MinGW.

Автор: Гость 2.3.2011, 12:43

на vs просит какой то заголовочный файл из мингв в ddk который поэтому забил на это!

на mingw собрал вначале static - появились .а и .о файлы
потом собрал dll появилась dll

а где теперь lib? :) как это всё дело в общем к проекту подключать? я потому что только свой код кодить умею а с библиотеками разбираться как их подключать не знаю :blush:

про .а и .о вообще нигде не могу найти!

Автор: kuzulis 2.3.2011, 12:55

Цитата(Гость @ 2.3.2011, 12:43) *
на vs просит какой то заголовочный файл из мингв в ddk который поэтому забил на это!

на mingw собрал вначале static - появились .а и .о файлы
потом собрал dll появилась dll

а где теперь lib? :) как это всё дело в общем к проекту подключать? я потому что только свой код кодить умею а с библиотеками разбираться как их подключать не знаю :blush:

про .а и .о вообще нигде не могу найти!

Посмотрите примеры как подключать в /examples .

По умолчанию библиотека собирается как статическая и все примеры линкуются со статической библиотекой (*.a),
поэтому после компиляции можно запускать любой пример не тяня за собой библиотеку.

Если же вам нужна динамическая (*.dll) - то меняем в /src/src.pro так:
Цитата
#CONFIG += staticlib
CONFIG += dll


В общем, собирайте что-то одно: или как статик или как длл.

Автор: Litkevich Yuriy 2.3.2011, 18:30

Цитата(Гость_Гость_* @ 2.3.2011, 14:43) *
а где теперь lib?
эти файлы генерит студийный компиллер, их эквивалент в MinGW - *.a

Автор: Гость 3.3.2011, 16:40

Цитата(Litkevich Yuriy @ 2.3.2011, 18:30) *
Цитата(Гость_Гость_* @ 2.3.2011, 14:43) *
а где теперь lib?
эти файлы генерит студийный компиллер, их эквивалент в MinGW - *.a

а судя по тому что в одном из срр файлов

используется мингвшный

#include <ddk/ntddser.h>

то на вс эту библиотеку не собрать?

в мингв вроде собирает но не запускаются примеры :(

Запускается C:\Qt\projs\qserialdevice-qserialdevice\examples\reader\release\reader.exe...
C:\Qt\projs\qserialdevice-qserialdevice\examples\reader\release\reader.exe завершился с кодом -1073741511

Автор: Гость 3.3.2011, 17:13

а там надо было попробовать кинуть в папку с проектом qtшные библиотеки..

в общем собрал через Ж на вс2008

для этого пришлось закомментить вот эту фигню

// Get DTR/RTS line states,
// where variable temp return states.
// ::DWORD bytesReturned = 0;
/* if (::DeviceIoControl(this->descriptor,
IOCTL_SERIAL_GET_DTRRTS,
0,
0,
&temp,
sizeof(::DWORD),
&bytesReturned,
0)) {

if (temp & SERIAL_DTR_STATE) status |= AbstractSerial::LineDTR;
if (temp & SERIAL_RTS_STATE) status |= AbstractSerial::LineRTS;
}
*/

и вот эту

//#include <ddk/ntddser.h>

но зато запустилось потом после сборки на вс компиляторе :D

Автор: kuzulis 3.3.2011, 20:32

>>для этого пришлось закомментить вот эту фигню
Теперь не будут определяться статусы линий DTR/RTS.


А чего-нить аналогичного #include <ddk/ntddser.h> разве нету в студийном компиляторе?
Может можно попробовать просто #include <ntddser.h> ?
И есть ли вообще такой заголовочник в студии?

Автор: Гость 3.3.2011, 23:44

я не знаю :( я вообще не знаю что это за заголовок! :)

библиотека откомпилированная на qtcreator компилятором вс2008, работает :D

только что проверил!

большое спасибо!

Автор: brauni 29.3.2011, 10:22

to kuzulis

Собственно говоря вопрос такой:
Мне нужно обеспечить обмен данными с железкой через COM порт. Есть 3 требования:
1. интерфейс должен быть отзывчивым
2. операцию должно быть можно прервать
3. тайм аут на операцию чтения записи, объективно, может быть 10+ секунд

Собственно говоря в чём вопрос: вот я в дочернем потоке запустил операцию чтения и она залипла на 10 секунд. И в течении этих 10 секунд пользователь хочет прервать операцию. Как мне сделать так чтобы дочерний поток отлип? Можно ли просто в главном потоке вызвать функцию close() для объекта AbstractSerial, чтобы в дочернем потоке операция чтения завершилась с ошибкой?

Автор: kuzulis 29.3.2011, 11:44

Перед чтением сначала надо открыть порт в асинхронном режиме (без Unbuffered), убедиться что байты для чтения уже доступны (к примеру, доступно N-ное их количество по readyRead() или bytesavailable()), а потом читать их.
В этом случае чтение будет "мгновенным" и ничего отменять не нужно будет, и, тем, более, не нужно ожидать пока они (байты) появятся.

В общем, класс порта работает также как и класс сокета, вот и пляшите от этого.
Ничего конкретного не подскажу, сами попробуйте.

PS: Если честно, то мне не совсем понятна суть работы с вашей железякой и зачем оно надо.

Автор: brauni 29.3.2011, 12:18

С TCP/IP сокетами у меня такой фокус прокатывал.

Дело в том, что железка ещё не готова, но программа под неё уже пишется. Так что техническое решение уже нужно а попробовать руками не могу :( иначе бы сам проверил.

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

Работа происходит так: отправляем железке данные, и ждём ответа от неё сколько ждать заранее не известно. Может и за сотые доли секунды справиться, а может и надолго зависнуть. Каждый раз ожидать 10 секунд(максимальное время работы) в асинхронном режиме не вариант, так как большая доля операций выполняется реально быстро.

Как я планировал написать программу: открываем новый поток в нем общаемся с железкой в небуфферизированном режиме(он понятнее, а дочерний поток можно и блокировать), в случае если пользователь выбирает сброс соединения, выполняем метод close(), дочерний поток завершает свою работу с ошибкой.

Автор: d2r 7.4.2011, 11:23

А как узнать, подключено ли к порту какое-либо устройство? То есть что бы при подключении устройства к com порту программа как либо сигнализировала об этом

Это необходимо будет по таймеру пытаться считывать данные с порта? Или есть другой способ?

Автор: kuzulis 7.4.2011, 19:35

Цитата(d2r @ 7.4.2011, 11:23) *
А как узнать, подключено ли к порту какое-либо устройство?

Никак.

Цитата(d2r @ 7.4.2011, 11:23) *
Это необходимо будет по таймеру пытаться считывать данные с порта? Или есть другой способ?

Открыть порт и приконектиться к сигналу readyRead().
И когда от устройства (если оно есть) придут данные - то прочитать их.
Никаких таймеров не нужно (за исключением, если необходимо просигнализировать о таймауте ожидания от устройства данных).

Как то так.


Автор: d2r 8.4.2011, 12:28

Не получается создать список AbstractSerial

QList<AbstractSerial> portList;
AbstractSerial *port = new AbstractSerial(this);
portList.push_back(port);
==========================
ошибка: no matching function for call to 'QList<AbstractSerial>::push_back(AbstractSerial*&)'

а если так:
QList<AbstractSerial> portList;
AbstractSerial port = new AbstractSerial(this);
portList.push_back(port);

то:
ошибка: conversion from 'AbstractSerial*' to non-scalar type 'AbstractSerial' requested

блин, понял что это нахрен не нужно)))) Как удалить сообщение)

можно обойтись и без списка, но все равно интересно

Автор: d2r 8.4.2011, 13:02

или как тогда слушать все порты в системе, если известно сколько портов открывать?

ps НЕ известно

Автор: kuzulis 8.4.2011, 20:35

Цитата(d2r @ 8.4.2011, 13:02) *
или как тогда слушать все порты в системе, если известно сколько портов открывать?

В смысле?
Открываем все порты которые нужно и слушаем...

QList<AbstractSerial *> portList;
AbstractSerial *port = new AbstractSerial(this);
connect(port, SIGNAL(readyRead()), this, SLOT(procRead()));
portList.append(port);



Автор: d2r 9.4.2011, 13:23

дада точняк))) тупанул

Автор: silver47 11.4.2011, 16:17

2 kuzulis
Доброго времени суток. Использую Вашу библиотеку для работы с COM. Устройство, к которому подключаюсь, работает на разных скоростях на прием и на отправку. Запрос отправляется на одной скорости, ответ принимается на другой. Столкнулся с такой проблемой: если после отправки запроса, сменить скорость, то до устройства доходит мусор. Пример в двух скринах. Повторить можно на физических COM портах. На виртуальных такого эффекта не наблюдал.
Код:

port->setDeviceName(COMPorts->currentText());
port->open(AbstractSerial::ReadWrite)
port->setBaudRate(AbstractSerial::BaudRate1200)
port->setDataBits(AbstractSerial::DataBits7)
port->setParity(AbstractSerial::ParityEven)
port->setStopBits(AbstractSerial::StopBits2)
port->setFlowControl(AbstractSerial::FlowControlOff)

port->setBaudRate(AbstractSerial::BaudRate300);

data.append(\"1234567890\");
port->write(data);

port->setBaudRate(AbstractSerial::BaudRate1200);


ОС: windows7, windowsXP
Qt 4.7.2

В чем может быть проблема? Спасибо.

COM1 - программа COM2 снифер на другом конце нульмодемного кабеля

 

Автор: Litkevich Yuriy 11.4.2011, 16:31

Цитата(silver47 @ 11.4.2011, 19:17) *
Столкнулся с такой проблемой: если после отправки запроса, сменить скорость, то до устройства доходит мусор.
нужно ждать завершения передачи и только потом менять скорость. Как это сделать в данной библиотеке я не знаю, нужно смотреть руководство

Автор: silver47 11.4.2011, 16:37

Цитата(Litkevich Yuriy @ 11.4.2011, 18:31) *
нужно ждать завершения передачи и только потом менять скорость. Как это сделать в данной библиотеке я не знаю, нужно смотреть руководство


Да я так и предполагаю, поэтому выставлял задержки в разных местах. Документацию пролистал, не заметил подобного.

В документации нашёл метод waitForBytesWritten(int msec) - который на настоящий момент не реализован и есть сигнал bytesWritten(qint64). Соединил сигнал со слотом, в котором меняю скорость, ситуацию это не изменило :(.

UPD. Подобрал задержку руками на ту сторону 5 байт ушло нормально, прием - каша. То есть уже удаленное устройство начинает писать ответ сразу, еще до того как скорость поменяю.

Автор: kuzulis 11.4.2011, 19:24

2 silver47

Цитата
В документации нашёл метод waitForBytesWritten(int msec) - который на настоящий момент не реализован

Реализован, но мной не опробован.
Реализован идентично тому-же методу из сокетов.
Цитата
есть сигнал bytesWritten(qint64)

На этот сигнал полагаться нельзя, т.к. оно может его слать в процессе передачи данных частями.
Т.е., к примеру отправили вы 100 байт, а оно может 10 раз по 10 байт этот сигнал емиттить.

---

1. Многое зависит от того с каким флагом открывали девайс: Unbuffered или нет.
2. Попробуйте открывать девайс c флагом Unbuffered и т.п.
3. ИМХО, лучше всего положиться на waitForBytesWritten() (может быть, придется его подправить и т.п.).

Я ничего конкретного не подскажу, т.к. не приходилось иметь дело с такими "фирдипёрсовыми" устройствами.
Если бы нужно было в Linux работать - то там проще: там есть методы для установки разных скоростей на прием/передачу,
а вот под виндой - увы.

В любом случае, пробуйте, разбирайтесь, отпишитесь о результатах и исправлениях кода библиотеки.

"Свежак" библиотеки тут: http://gitorious.org/qserialdevice/qserialdevice/trees/master

------

Хотя, может быть, даже лучше всё-таки полагаться на сигнал bytesWritten() , только контролируя кол-во переданных байт.
т.е. если нужно передать 100 байт, то мы подсчитываем в слоте (приконнекченом на bytesWritten) кол-во переданных от bytesWritten байт (суммируем их)
и если сумма равна 100 то меняем скорость.

Но всё-равно нужно проверять и экспериментировать.

Автор: nn1317 12.4.2011, 9:36

доброе утро)
блин, была у меня версия 0.1 - всем устраивала, только у заказчиков она хронически не собиралась, а у меня самого видимо чуть постарее кутишка и мингв, так что я как то давно собрал и забыл как это сделал. так вот, тем у кого 64битная юбунта как у меня - я просто копировал длл-ку и все работало. а тут попался человек с 32х биткой.
все собираю как dll.

1. пробую собрать версию 0.1 - везде одинаковые ошибки:

abstractserial.cpp: In member function ‘QString AbstractSerial::deviceName() const’:
abstractserial.cpp:636: error: call of overloaded ‘QString(int)’ is ambiguous
/usr/include/qt4/QtCore/qstring.h:428: note: candidates are: QString::QString(const QByteArray&)
/usr/include/qt4/QtCore/qstring.h:426: note:                 QString::QString(const char*)
/usr/include/qt4/QtCore/qstring.h:727: note:                 QString::QString(const QString&)
/usr/include/qt4/QtCore/qstring.h:106: note:                 QString::QString(QChar)
/usr/include/qt4/QtCore/qstring.h:105: note:                 QString::QString(const QChar*)
abstractserial.cpp: In member function ‘QString AbstractSerial::baudRate() const’:
abstractserial.cpp:706: error: call of overloaded ‘QString(int)’ is ambiguous
/usr/include/qt4/QtCore/qstring.h:428: note: candidates are: QString::QString(const QByteArray&)
/usr/include/qt4/QtCore/qstring.h:426: note:                 QString::QString(const char*)
/usr/include/qt4/QtCore/qstring.h:727: note:                 QString::QString(const QString&)
/usr/include/qt4/QtCore/qstring.h:106: note:                 QString::QString(QChar)
/usr/include/qt4/QtCore/qstring.h:105: note:                 QString::QString(const QChar*)
abstractserial.cpp: In member function ‘QString AbstractSerial::dataBits() const’:
abstractserial.cpp:800: error: call of overloaded ‘QString(int)’ is ambiguous
/usr/include/qt4/QtCore/qstring.h:428: note: candidates are: QString::QString(const QByteArray&)
/usr/include/qt4/QtCore/qstring.h:426: note:                 QString::QString(const char*)
/usr/include/qt4/QtCore/qstring.h:727: note:                 QString::QString(const QString&)
/usr/include/qt4/QtCore/qstring.h:106: note:                 QString::QString(QChar)
/usr/include/qt4/QtCore/qstring.h:105: note:                 QString::QString(const QChar*)
abstractserial.cpp: In member function ‘QString AbstractSerial::parity() const’:
abstractserial.cpp:894: error: call of overloaded ‘QString(int)’ is ambiguous
/usr/include/qt4/QtCore/qstring.h:428: note: candidates are: QString::QString(const QByteArray&)
/usr/include/qt4/QtCore/qstring.h:426: note:                 QString::QString(const char*)
/usr/include/qt4/QtCore/qstring.h:727: note:                 QString::QString(const QString&)
/usr/include/qt4/QtCore/qstring.h:106: note:                 QString::QString(QChar)
/usr/include/qt4/QtCore/qstring.h:105: note:                 QString::QString(const QChar*)
abstractserial.cpp: In member function ‘QString AbstractSerial::stopBits() const’:
abstractserial.cpp:988: error: call of overloaded ‘QString(int)’ is ambiguous
/usr/include/qt4/QtCore/qstring.h:428: note: candidates are: QString::QString(const QByteArray&)
/usr/include/qt4/QtCore/qstring.h:426: note:                 QString::QString(const char*)
/usr/include/qt4/QtCore/qstring.h:727: note:                 QString::QString(const QString&)
/usr/include/qt4/QtCore/qstring.h:106: note:                 QString::QString(QChar)
/usr/include/qt4/QtCore/qstring.h:105: note:                 QString::QString(const QChar*)
abstractserial.cpp: In member function ‘QString AbstractSerial::flowControl() const’:
abstractserial.cpp:1082: error: call of overloaded ‘QString(int)’ is ambiguous
/usr/include/qt4/QtCore/qstring.h:428: note: candidates are: QString::QString(const QByteArray&)
/usr/include/qt4/QtCore/qstring.h:426: note:                 QString::QString(const char*)
/usr/include/qt4/QtCore/qstring.h:727: note:                 QString::QString(const QString&)
/usr/include/qt4/QtCore/qstring.h:106: note:                 QString::QString(QChar)
/usr/include/qt4/QtCore/qstring.h:105: note:                 QString::QString(const QChar*)
make: *** [../build/lib/qserialdevice/obj/abstractserial.o] Error 1

если в строке с первой ошибкой меняю "QString res(0);" на "QString res;" то он начинает ругаеться на переменную "d", которая через одну строчку от прошлой ошибки - "wasn't declared in this scope"

2. слил новую 0.4. не собираеться из коробки.
ошибки - ругаеться на TTYLocker, говорит методы начиная с checkPid(..), деструктора, getShortName(..) и тд - "multiply definition"

версии qt и gcc (g++) самые последние из того что в стандартных репозиториях юбунты.

подскажите плиз как собрать!

Автор: kuzulis 12.4.2011, 10:58

Не знаю, что у Вас за проблема.
У меня версия из мастера прекрасно собирается на 32х битном Linux Mint Debian Edition, а также 64x битном Arch-е.

Может быть, в qserialdeviceenumerator.pri нужно закомментировать:

Цитата
HEADERS += $$PWD/../qserialdevice/ttylocker.h
SOURCES += $$PWD/../qserialdevice/ttylocker.cpp


Цитата
подскажите плиз как собрать!

Берем BuildLibrary.pro и собираем.

ЗЫ: По v0.1.0 ничо не подскажу.

Автор: nn1317 12.4.2011, 11:27

>Берем BuildLibrary.pro и собираем.
ну я CONFIG который был закомментил, а закомменченый раскомментил, чтобы была dll-версия.

>Может быть, в qserialdeviceenumerator.pri нужно закомментировать:
попробовал, только в обычном qserialdevice.pri - закомментил и собралось))
спасибо)

Автор: niklep 22.5.2011, 17:39

Доброго времени суток. Есть проблема при использовании данной библиотеки. Я пишу с помощью write данные в порт. Получаю корректный ответ. Тут же снова пишу в порт. Получаю 2 ответа (сигнал readyRead срабатывает дважды): корректный и пустой. В третий раз получу корректный ответ и 2 пустых. И так далее. Для чтения данных с порта использую readAll(). Вот фрагмент кода:

QByteArray ComHandler::readFromPort()
{
    QByteArray qba;
    qDebug() << "bytesAvailable1 " << port->bytesAvailable();
    qba = port->readAll();
    qDebug() << "bytesAvailable2 " << port->bytesAvailable();
    return qba;
}

Вывод:
Writed info:  ati
bytesAvailable1  2
bytesAvailable2  -1
slotReadCom:  "
1.0

OK
"

Writed info:  ati
bytesAvailable1  1
bytesAvailable2  0
slotReadCom:  "
1.0

OK
"
bytesAvailable1  0
bytesAvailable2  0
slotReadCom:  ""

Writed info:  ati
bytesAvailable1  1
bytesAvailable2  -1
slotReadCom:  "
1.0

OK
"
bytesAvailable1  0
bytesAvailable2  0
slotReadCom:  ""
bytesAvailable1  0
bytesAvailable2  0
slotReadCom:  ""

Также отмечу, что для облегчения отладки хотел использовать bytesAvailable(), но его вывод меня только запутал...

Автор: niklep 22.5.2011, 18:59

Прошу прощения, косяк был мой (стоило ожидать=)). просто я не в том месте делал привязку:
connect(temp_com->port, SIGNAL(readyRead()), this, SLOT(slotReadCom()));

Автор: kuzulis 22.5.2011, 20:24

Цитата(niklep @ 22.5.2011, 19:59) *
Прошу прощения, косяк был мой (стоило ожидать=)). просто я не в том месте делал привязку:
connect(temp_com->port, SIGNAL(readyRead()), this, SLOT(slotReadCom()));

Понятно. :)

Значит можешь не отвечать на мои сообщения на gitorious.org .

Автор: devnir 24.5.2011, 15:28

Здравствуйте, перечитал практически всю тему. Собственно читать то начал из-за своей проблемы:
работаю с AbstractSerial, собственно из под Linux - все хорошо и прекрасно. а вот в маст дае (Win) начинают "теряться" байты данных.
Ну собственно сам код:

Port = new AbstractSerial(this);
#if defined (Q_OS_UNIX)
    portNameStr = "/dev/ttyUSB0";
#elif defined (Q_OS_WIN)
    portNameStr = "COM1";
#endif


инициализация и открытие:
    Port->setDeviceName(Pname);
    if (Port->open(AbstractSerial::ReadWrite | AbstractSerial::Unbuffered)){

        if (!Port->setBaudRate(AbstractSerial::BaudRate115200)) {
        };
        if (!Port->setDataBits(AbstractSerial::DataBits8)) {
        };
        if (!Port->setParity(AbstractSerial::ParityNone)) {
        };
        if (!Port->setStopBits(AbstractSerial::StopBits1)) {
        };
        if (!Port->setFlowControl(AbstractSerial::FlowControlOff)) {
        };

#if defined (Q_OS_UNIX)
        if (Port->openMode() & AbstractSerial::Unbuffered)
            Port->setCharIntervalTimeout(10000);//5 msec
#elif defined (Q_OS_WIN)
        if (Port->openMode() & AbstractSerial::Unbuffered)
            Port->setTotalReadConstantTimeout(100);
#endif

#ifdef __Debug__
        dbg("Port Opened, timeout: %d\n", Port->charIntervalTimeout());
#endif
        connect(Port, SIGNAL(readyRead()), this, SLOT(slotReadPort()));
        return true;
    }
    else
    {
#ifdef __Debug__
        dbg("Port not OPENED!!! \n");
#endif
        return false;
    }



slotReadPort()
{
    QByteArray tmpBuff;
    quint64 len = Port->bytesAvailable();
    tmpBuff = Port->read(len);
    for(int i =0; i< tmpBuff.length(); i++)
    {
        dbg("0x%02X ", tmpBuff.at(i)&0xff);
        pRead(tmpBuff.at(i)&0xff);
    }
}


использую для пересылки файла через порт. Алгоритм простой как двери. отправил сообщение - получил подтверждение что со стороны приемника часть файла получена (0xAA)- отправил следующую часть(F_LEN = 4096 + 4 байта) с небольшой задержкой:
pRead(char c)
{
                if (c==0xAA) {
                    serial_timer.start(TR_WAIT);
                }
}


slotTimeout()
{
            if (offset >= file_data.size())
                return;

            this->Port->write(file_data.constData()+offset, F_LEN);
                offset+=F_LEN;
}


Собственно где я что упустил ? Есть идеи? Писал и отлаживал в Linux, вот понадобилось собрать под винду. собрал - а работает не корректно. примерно на пересылке 2-3 го блока все зависает :( из за того что не получена квитанция о пересылке предыдущего куска.

Автор: kuzulis 24.5.2011, 16:10

Попробуй пройтись сниффером типа free-serial-port-monitor на предмет того, а шлет ли клиент вообще 0хAA ?!
А также выложи минимальные компилябельные проекты "клиента<->сервера" в которых воспроизводится данная проблема.

Автор: devnir 24.5.2011, 17:07

Да мне кажется там просто переполнение идет буферов порта у винды. - рвется пакет который отправляется - ну а приемник собственно проверяет ЦРЦ свертку - которая не сходится - нет АА.

Проверил примерно так:
файл для передачи: нарезал на 4096 байт + 4байта ЦРЦ32. получил 4100 байт массива который передал кусками (с задержкой в 1 сек.) по 205 байт.
Покурил - сделал кофе - вернулся, пол файла передало. но ошибок нет.
Теперь вот думаю примерно какой кусок и с какой задержкой посылать - что бы не переполнить какуют там ФиФошку. Еще угнетает то что QT в виртуалке да еще и статической сборки. Проэкт линкуется минут 15 :(

Насчет снифера - то я уже мониторил. Собственно и дошел до того что ошибка именно в переполнении буферов винды(сервер) - так как порт начинал работать криво - терял байты. хотя с другой стороны(клиент) мониторя - я точно уверен в отправке сообщения, так как там такой же снифер стоял.

Автор: kuzulis 24.5.2011, 18:36

Цитата
файл для передачи: нарезал на 4096 байт + 4байта ЦРЦ32. получил 4100 байт массива который передал кусками (с задержкой в 1 сек.) по 205 байт.
Покурил - сделал кофе - вернулся, пол файла передало. но ошибок нет.

Попробуй тогда открывать порт в буферизованном режиме, т.е не использовать флаг Unbuffered (тут можно передавать неограниченное кол-во байт) и убрать вообще код где используются таймауты и т.п.
т.е смотри примеры в /test/guiapp(guiapp2)

ЗЫ:
А так - да, если читаешь из порта (открытого с флагом Unbuffered , как у тебя сейчас) то нужно использовать метод waitForReadyRead() , и т.п извращаться,
т.к. лимит по умолчанию в драйвере винды на 4096 байт (если не ошибаюсь) и нужно постоянно читать данные для того чтобы буфер драйера не переполнился.

В общем, используй буферизованный режим и будет всё ок.

Автор: Алексей1153 25.5.2011, 8:18

Извиняюсь, что вклиниваюсь, но, по-моему, я совсем только что по таким граблям прошёл ) Дело было с драйвером фирмы FTDI, преобразователь USB<->COM

на небольших скоростях всё было хорошо, но когда прибор стал валить в USB порт очень толстый поток данных, драйвер стал подглючитваь и зависать. В конце концов всё решилось так: в отдельном потоке раз в 1 мс (при помощи мультимедийного таймера) вытаскиваю все данные в буфер (размер я могу, конечно же, задать произвольный. Это - рассчитать, сколько нужно). Если буфер переполняется, то новые данные откидываю - иначе у драйвера крышу сносит. В основном потоке по обычному виндовому таймеру выделяю осмысленные куски данных и вычищаю их из буфера. Естественно, операции работы с буфером - через критическую секцию.

Уже 4 дня после этих исправлений полёт нормальный, тьфу, тьфу, тьфу

Автор: good835 3.6.2011, 13:45

Добрый день!
После изменений в классе SerialDeviceEnumerator (SerialDeviceEnumerator reimplemented as a singleton.) программа стала подвисать при создании объекта класса (пример quiapp)

    if (!this->enumerator)
        this->enumerator = SerialDeviceEnumerator::instance();

грузит процессор сервис Service Control Manager (SCM) (\Windows\System32\Services.exe) - под 100% - идет поиск устройств?
после того как сервис отработает появляется окно программы. До изменений такой проблемы не было, с чем это может быть связано?
ОС: WindowsXP, QT 4.7.1. mingw

Автор: kuzulis 3.6.2011, 15:01

2 good835

Да не должно грузить, т.к. в принципе ничего не изменилось (кроме того что теперь SerialDeviceEnumerator является одиночкой).

Я только что проверил : у меня приложение /gui/test, собранное в релизе,
не подвисает (ну, загружает, процентов на 30% - но не на 100 как у вас.).

В принципе, это нормально, любые иные приложения тоже при старте грузят процессор.

ЗЫ: Хотя, может быть, это связано с тем, что вы в конструкторе выполняете метод: isBusy() ?
И если ДА - то может из-за него проблемы, т.к. если порт открыт и метод пытается его опять открыть - то этот процесс тормозит N-ное кол-во времени.

Автор: good835 7.6.2011, 16:26

2 kuzulis

Разобрался я, почему грузит процессор. Как и предполагалось проблема была в методе SerialInfoMap SerialDeviceEnumeratorPrivate::updateInfo() const

   
static const ::GUID guidArray[] =
{
    /* Windows Ports Class GUID */
    { 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
    /* Virtual Ports Class GUIG (i.e. com0com, nmea and etc) */
    { 0xDF799E12, 0x3C56, 0x421B, { 0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78 } },
    /* Windows Modems Class GUID */
    { 0x4D36E96D, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } }
};
   int guidCount = sizeof(guidArray);
   for (int i = 0; i < guidCount; ++i) {

       ::HDEVINFO DeviceInfoSet = ::SetupDiGetClassDevs(&guidArray[i],
                                                        0,
                                                        0,
                                                        DIGCF_PRESENT);
  ....

Собственно говоря ошибка была в определении длины цикла guidCount, что и приводило к некорректной работе при поиске инфо об устройстве. Должно быть так:
   int guidCount = sizeof(guidArray)/sizeof(::GUID);

Автор: kuzulis 7.6.2011, 19:39

Спасибо! Исправил.

Автор: Алексей1153 7.6.2011, 19:49

а так красивше :)

int guidCount = sizeof(guidArray)/sizeof(*guidArray);

Автор: universeroot 13.6.2011, 20:06

Сегодня написал с применением этой библиотеки:

http://robocraft.ru/blog/544.html

Автор: kuzulis 13.6.2011, 22:17

Цитата(universeroot @ 13.6.2011, 21:06) *
Сегодня написал с применением этой библиотеки:

http://robocraft.ru/blog/544.html


О, зачетненько! :clapping:

Только если библиотека линкуется статически (а по умолчанию она статически линкуется), то нет нужды её куда-то копировать (а также копировать заголовки).
Также можно было её подключать "напрямую" к проекту чтобы не заморачиваться с копированием (см. примеры в /test/guiapp).
:)

Автор: grio 1.7.2011, 13:40

Объясните пожалуйста, как правильно инсталлировать
библиотеку QSerialDevice и прикрутить ее к проекту в Линуксе.

Автор: kuzulis 1.7.2011, 15:47

Цитата(grio @ 1.7.2011, 14:40) *
Объясните пожалуйста, как правильно инсталлировать
библиотеку QSerialDevice и прикрутить ее к проекту в Линуксе.

А по умолчанию не нужно её никуда инсталлировать.
Она является статической и линкуется с приложением,
т.е. её код встраивается в код приложения.

Можете использовать её классы напрямую, как в примере /test/quiapp

Автор: grio 1.7.2011, 16:33

Цитата(kuzulis @ 1.7.2011, 16:47) *
Цитата(grio @ 1.7.2011, 14:40) *
Объясните пожалуйста, как правильно инсталлировать
библиотеку QSerialDevice и прикрутить ее к проекту в Линуксе.

А по умолчанию не нужно её никуда инсталлировать.
Она является статической и линкуется с приложением,
т.е. её код встраивается в код приложения.

Можете использовать её классы напрямую, как в примере /test/quiapp


В моем случае, оказалось, что просто не хватало пакета libudev-dev.
Продолжаю эксперименты, спасибо.

Автор: shurilnik 12.8.2011, 11:05

kuzulis, Здравствуйте. Решил попробовать использовать вашу библиотеку на embedded девайсе mini2440 под linux. Столкнулся с проблемой что serialdeviceenumenator начинает грузить проц на 100% после того как в системе появляется или исчезает (если было включено до запуска конструктора класса) ttyUSB устройство. Звук непрерывно воспроизводимый прерывается 2-3 раза в секунду, независимо уже после этого появилось еще устройство или исчезло. Т.е. какой-то метод класса в периодом условно в миллисекунд 300 что-то делает что серьезно грузит процессор, а в остальное время приоритет операции пониже, но все равно грузит. Подскажите пожалуйста куда копать.
Если подключится straceом к процессу то после подключения устройства начинают с большой скорость проскакивать вот такие операции:
readlink("/sys/devices/virtual/tty/tty42/subsystem", "../../../../class/tty"..., 1024) = 21
lstat64("/dev/.udev/db/tty:tty42", {st_mode=S_IFLNK|0777, st_size=15, ...}) = 0
readlink("/dev/.udev/db/tty:tty42", "tty42 char/4:42"..., 1024) = 15
readlink("/sys/devices/virtual/tty/tty43", 0xbed2c680, 1024) = -1 EINVAL (Invalid argument)
stat64("/sys/devices/virtual/tty/tty43/uevent", {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0
open("/sys/devices/virtual/tty/tty43/uevent", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 21
fstat64(21, {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001f000
read(21, "MAJOR=4\nMINOR=43\nDEVNAME=tty43\n", 4096) = 31
read(21, "", 4096) = 0
close(21) = 0
munmap(0x4001f000, 4096) = 0
readlink("/sys/devices/virtual/tty/tty43/subsystem", "../../../../class/tty"..., 1024) = 21
lstat64("/dev/.udev/db/tty:tty43", {st_mode=S_IFLNK|0777, st_size=15, ...}) = 0
readlink("/dev/.udev/db/tty:tty43", "tty43 char/4:43"..., 1024) = 15
readlink("/sys/devices/virtual/tty/tty44", 0xbed2c680, 1024)usb 1-1.2: USB disconnect, address 3
ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
ftdi_sio 1-1.2:1.0: device disconnected
= -1 EINVAL (Invalid argument)
stat64("/sys/devices/virtual/tty/tty44/uevent", {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0
open("/sys/devices/virtual/tty/tty44/uevent", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 21
fstat64(21, {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001f000
read(21, "MAJOR=4\nMINOR=44\nDEVNAME=tty44\n", 4096) = 31
read(21, "", 4096) = 0
close(21) = 0
munmap(0x4001f000, 4096) = 0
readlink("/sys/devices/virtual/tty/tty44/subsystem", "../../../../class/tty"..., 1024) = 21
lstat64("/dev/.udev/db/tty:tty44", {st_mode=S_IFLNK|0777, st_size=15, ...}) = 0
readlink("/dev/.udev/db/tty:tty44", "tty44 char/4:44"..., 1024) = 15
readlink("/sys/devices/virtual/tty/tty45", 0xbed2c680, 1024) = -1 EINVAL (Invalid argument)
stat64("/sys/devices/virtual/tty/tty45/uevent", {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0
open("/sys/devices/virtual/tty/tty45/uevent", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 21
fstat64(21, {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001f000
read(21, "MAJOR=4\nMINOR=45\nDEVNAME=tty45\n", 4096) = 31
read(21, "", 4096) = 0
close(21) = 0
munmap(0x4001f000, 4096) = 0

причем номер и тип tty постоянно меняется...
Или может это нормальное поведение ?
Заранее спасибо.

Автор: kuzulis 12.8.2011, 11:49

2 shurilnik,

я даже и не знаю что посоветовать.

Что первое приходит на ум, так это - попробуйте скачать master ветку:

https://gitorious.org/qserialdevice/qserialdevice/trees/master

Цитата
Столкнулся с проблемой что serialdeviceenumenator начинает грузить проц на 100% после того как в системе появляется или исчезает (если было включено до запуска конструктора класса) ttyUSB устройство.

Это если используется только класс SerialDeviceEnumenator (и не используется AbstractSerial) такое поведение? Или как?

Иначе:
Такое может быть если Вы, используя класс AbstractSerial, открыли порт и выдернули его.
В этом случае QSocketNotifier будет вечно гнать евенты (почему-то такое поведение у функции select()).
т.е. может быть, начинает срабатывать вечно exceptionNotifier или readNotifier (см. nativeserialnotifier_unix.cpp).
Если это так - то я в курсе этой проблемы, но пока не могу найти решения,
т.к. правильным решением является принудительное закрытие дескриптора выдернутого порта при возникновении такой ситуации.
Но вот как отличить Exception/Read событие вызванную какой-либо другой причиной от Exception/Read события вызванной выдергиванием порта - я не знаю.

PS: Если используете AbstractSerial и вам не нужны уведомления о сигналах RTS/DTR/CTS и пр. то можете в
nativeserialnotifier_unix.cpp закомментировать всё что запускает поток run(), т.к. он тоже может быть причиной.

Автор: shurilnik 12.8.2011, 12:40

У меня как раз мастер ветка, недельной давности правда.
Да порт сразу открывается при появлении устройства. Но проблема появляется не только при выдергивании а и при вставлении. Т.е. пока устройств нету - все тихо. Появляется устройство и начинается. На самом деле я пробовал и без открытия порта - тоже самое происходит. Я serialenumerator и использую для отслеживания что устройство выдернули, (даже с открытым портом) и соответствующий ему Abstractserial класс удаляется с закрытием порта и удалением дескриптора.
По поводу, RTS/DTR/CTS попробую поправить как вы сказали. Отпишусь потом.
Кстати ttylocker пришлось править как вы раньше советовали, иначе после выдергивания порт при повторном подключении не давало открыть порт.... Закоментировал обработки pid локфайла.

Автор: kuzulis 12.8.2011, 14:16

Цитата
На самом деле я пробовал и без открытия порта - тоже самое происходит. Я serialenumerator и использую для отслеживания что устройство выдернули, (даже с открытым портом) и соответствующий ему Abstractserial класс удаляется с закрытием порта и удалением дескриптора.

Ну, если вы говорите, что ошибка в serialenumerator - значит нужно его ковырять.
Я не скажу навскидку что там происходит... Может udev шалит, а мож еще что.

PS: А на обычном PC с Linux пробовали?

Автор: sh2ka 17.8.2011, 12:53

Есть некоторая проблема при использовании QSerialDevice.

Вот, исходные данные:



шаги по воспроизведению:


ПРОБЛЕМА: прекращается обмен с устройством.

Проверил, работает ли в этой ситуации таймер запросов - оказалось, что работает, т.е. запросы идут (проверял с помощью разных терминалок) - на стороне слейва данные приходят и отправляется ответ, но он не приходит мастеру.

Думаю, что здесь что-то связано с использованием API-функции WaitForSingleObject, т.е. она не возвращает управление до тех пор, пока не отпустишь окно или не закроешь модальное окно.

Однако, это всего лишь мое предположение. Хотелось бы узнать, что на самом деле: я что-то не так делаю или это баг?

Автор: kuzulis 17.8.2011, 15:16

Да, подтверждаю. Есть такое дело.

По ходу блокируется метод: QWinEventNotifier::event(QEvent *e).
т.е. не блокируется - а перестает срабатывать при появлении события.

Цитата
Думаю, что здесь что-то связано с использованием API-функции WaitForSingleObject, т.е. она не возвращает управление до тех пор, пока не отпустишь окно или не закроешь модальное окно.

Хз в какой функции проблема - но точно она в QWinEventNotifier.
В этом случае я ничего не могу сделать. ИМХО.

Создавайте экземпляр класса порта тогда в другом потоке, может поможет.

Автор: Litkevich Yuriy 18.8.2011, 8:14

Цитата(sh2ka @ 17.8.2011, 15:53) *
хватаю окно мышью за заголовок и держу
В виндовозе главный поток сразу блокируется, поэтому коммуникационную часть нужно делать в отдельном окне

Автор: kuzulis 18.8.2011, 8:21

Цитата(Litkevich Yuriy @ 18.8.2011, 9:14) *
В виндовозе главный поток сразу блокируется, поэтому коммуникационную часть нужно делать в отдельном окне

Эмм... но если б он блокировался - то не срабатывал бы таймер и не излучался бы от него сигнал, по которому порт отправляет данные.
Но в данном случае порт их периодично (раз в 1 сек) отправляет, но вот обратно не принимает ответ!

Почему тогда срабатывает таймер и обрабатываются евенты, если гл. поток должен блокироваться!?

Автор: Litkevich Yuriy 18.8.2011, 12:33

у меня и таймер не срабатывает, отпущу мыша, и попёрла вся пачка накопившаяся в очереди.

Автор: kuzulis 18.8.2011, 14:34

Цитата(Litkevich Yuriy @ 18.8.2011, 13:33) *
у меня и таймер не срабатывает, отпущу мыша, и попёрла вся пачка накопившаяся в очереди.

Хм, странно. У меня таймер срабатывает (WinXP SP2). :blink:

Автор: sh2ka 19.8.2011, 6:56

Цитата(Litkevich Yuriy @ 18.8.2011, 14:33) *
у меня и таймер не срабатывает, отпущу мыша, и попёрла вся пачка накопившаяся в очереди.


Странно, у меня таймер подвисает на долю секунды пока рамочка вокруг окна отрисовывается (содержимое окна при перетаскивании не отрисовывается), а потом все нормально.

Аналогично с полями ввода (скорее всего там таймер и используется для моргания курсора).
Одно понять не могу: это баг виндовс или Qt? Может какие-то особые настройки нужны системе для генерации события от порта (прерывания-то должны возникать хоть как при получении данных в порт)?

Я программировал на чистом WinAPI одно время и сам делал модальные циклы - это обычный рекурсивный вызов бесконечного цикла обработки событий, который закрывается при закрытии модального окна. Исходя из этого непонятно, почему блокируется генерация событий от порта. С отдельным потоком не всегда удобно, когда нужно сделать быстро и без проблем примитивную програмку с модальными окнами.

Автор: kuzulis 19.8.2011, 9:19

Цитата(sh2ka @ 19.8.2011, 7:56) *
Одно понять не могу: это баг виндовс или Qt?

ИМХО - баг Qt, связанный с обработкой событий (или типа того, не охота копать глубоко).

Вот, я прикрепил небольшой тестовый примерчик где по таймеру раз в 1 сек в порт отправляется запрос на чтение регистров (Modbus) и принимается ответ. Так тут такое же поведение.

 testserialreadyread.zip ( 4.76 килобайт ) : 140
 

Автор: silver47 4.11.2011, 14:41

Добрый день. Обновился до ветки master от 17 сентября. На windows 7 не закрывает порт с модемом, который подключен по USB. Так и висит с открытым портом, до тех пор пока шнурок из модема не выдернешь. В чем может быть проблема?

спасибо.

P.S. под USB модемом подразумеваю zyxel OMNI 56K UNO, а не всякие GPRS/3G.

Автор: kuzulis 6.11.2011, 16:46

Цитата(silver47 @ 4.11.2011, 15:41) *
Добрый день. Обновился до ветки master от 17 сентября. На windows 7 не закрывает порт с модемом, который подключен по USB. Так и висит с открытым портом, до тех пор пока шнурок из модема не выдернешь. В чем может быть проблема?

спасибо.

P.S. под USB модемом подразумеваю zyxel OMNI 56K UNO, а не всякие GPRS/3G.

Не знаю, проверьте сами дебаггером.

Автор: silver47 6.11.2011, 19:10

Дебаггер встал на файле abstractserial.cpp На строке номер 800

d->serialEngine->close();
Если копать глубже, то в файле nativeserialengine_win.cpp на строке 176
::CancelIo(this->descriptor);


Прилагаю скриншот.

P.S. если выдернуть девайс в этот момент, то сразу же переходим к строке 178
if (0 == ::CloseHandle(this->descriptor)) {


 

Автор: kuzulis 6.11.2011, 21:05

Можно попробовать перед закрытием делать setFlowControl(FlowControlOff) или,
если не получится, закомментировать CancelIo().

Автор: silver47 7.11.2011, 6:08

Цитата
Можно попробовать перед закрытием делать setFlowControl(FlowControlOff)

Порт открывается с FlowControlOff, тем не менее, поставил вызов прямо перед закрытием порта - результат нулевой.

Закомментировал вызов ::CancelIO(this->descriptor); гм... тоже без результата. Может чего не так делаю, но деббагер упорно переходит на строку с комментом. Уже вычистил проект и пересобрал, все равно.

UPDATE:Прошу прощения, спросонья подумал что сегодня уже 8е число, и что это уже пересобранная библиотека, а оказалась что исходники поменял, а саму библиотеку QSerialDevice не перекомпилил. Все работает.

Спасибо.

 

Автор: sarge 7.11.2011, 14:54

Добрый день, сори за идиотские вопросы, но с qt столкнулся впервые и пытаюсь разобраться с работой с ком портом.

суть такова - имеется qt SDK, пишу в нем простые программки, все работае.
Скачал qserialdevice и попытался собрать примеры оттуда - в результате куча ошибок, попробовал собрать библиотеку (как описано в ридми) тоже куча ошибок.

мне надо как то по другому установить Qt чтобы все работало?

Автор: kuzulis 7.11.2011, 18:08

[/telepaty mode = ON]
См http://www.qtcentre.org/threads/39876-Help-with-serial-Problem?p=183195#post183195ответ.
Или тут на форуме или на prog.org.ru
[/telepaty mode]


Автор: sarge 7.11.2011, 20:48

Цитата(kuzulis @ 7.11.2011, 18:08) *
[/telepaty mode = ON]
См тут ответ.
Или тут на форуме или на prog.org.ru
[/telepaty mode]


если честно то не ожидал что тут ответят, т.к. сообщение набирал с полной мешаниной в голове и уже подготовил файлы и подробный пост на этот форум, но тут появились вы :)

спасибо большое, пока что все работает

Автор: shurilnik 7.12.2011, 18:36

kuzulis, Приветствую!

Наконец опять занялся своим устройством, сижу пытаюсь разобраться почему SerialDeviceEnumerator грузит проц... Пока что выяснил вот что:
в функции void SerialDeviceEnumeratorPrivate::setEnabled(bool enable)
создается коннект:
q->connect(this->notifier, SIGNAL(activated(int)), q, SLOT(_q_processWatcher()));

И в общем-то все нормально пока не воткнешь usb устройство. После вставки (или доставания, если сабжевый класс был инициализирован при воткнутом устройстве) начинаются бесконечные ивенты от этого QSocketNotifier (который udev_socket). И он постоянно дергает _q_processWatcher() и получается загрузка проца по плешку.
Пробовал на десктопе у себя - тоже самое. только грузится одно ядро (ну есесно прога а один поток работает).
Насколько я понимаю QSocketNotifier должен выдавать сигнал только когда udev увидел что действительно устройство появилось/исчезло? А оно почему-то выдает постоянно.

PS: Это все происходит вообще без участия AbstractSerial. Т.е. порт я даже не откываю.
Может есть идеи отчего так происходит ?

О, а может сокет не читается, поэтому сигнал все время заново посылается ?

Автор: kuzulis 7.12.2011, 20:05

Цитата
После вставки (или доставания, если сабжевый класс был инициализирован при воткнутом устройстве) начинаются бесконечные ивенты от этого QSocketNotifier (который udev_socket).


Да, есть такое дело. Если открыть порт и выдернуть шнурок то будут евенты сыпаться и будет загрузка.
Тут эта тема поднималась уже.
Решения нет и не будет в принципе, т.к. эта ветка библиотеки заморожена и больше не поддерживается.

Вместо этой ветки используй 2.0. : https://gitorious.org/qserialdevice/qserialdevice/archive-tarball/2.0
которую (тьфу-тьфу чтобы не сглазить), нокиевцы обещали добавить в Qt как аддон.

Здесь вместо SerialDeviceEnumerator использовать можно SerialPortInfo с проверкой портов по таймеру.




Автор: shurilnik 7.12.2011, 20:19

Цитата(kuzulis @ 7.12.2011, 20:05) *
Цитата
После вставки (или доставания, если сабжевый класс был инициализирован при воткнутом устройстве) начинаются бесконечные ивенты от этого QSocketNotifier (который udev_socket).


Да, есть такое дело. Если открыть порт и выдернуть шнурок то будут евенты сыпаться и будет загрузка.
Тут эта тема поднималась уже.

Решения нет и не будет в принципе, т.к. эта ветка библиотеки заморожена и больше не поддерживается.

Это я читал, но как я выше написал порт вообще не открывается. Т.е. проблема даже при неоткрытом порте, я инициализирую только класс SerialDeviceEnumerator, AbstractSerial я не трогаю... Он же сам не открывает порт при появлении устройства....
Смысл как я понял в том что на udev_motitor вешается QSocketNotifier который выдает событие что данные можно читать, а обработчик из этого сокета ничего не читает а запускает сразу udev_enumerator и уже из него читает.
добавление struct udev_device *udev_device =::udev_monitor_receive_device(this->udev_monitor);
в обработчик решает проблему, но эта функция блокирующая и есть свои нюансы.
Я до конца механизм еще не понял (мало знаний, начинающий я...), но попробую как-нибудь всетаки красиво это решить.

Цитата(kuzulis @ 7.12.2011, 20:05) *
Вместо этой ветки используй 2.0. : https://gitorious.org/qserialdevice/qserialdevice/archive-tarball/2.0
которую (тьфу-тьфу чтобы не сглазить), нокиевцы обещали добавить в Qt как аддон.

Здесь вместо SerialDeviceEnumerator использовать можно SerialPortInfo с проверкой портов по таймеру.

Эта ветка считается более стабильной ?
Спасибо, посмотрю, хотя если б ту доделать то в общем-то все красиво получалось... а по таймеру не всегда удобно в embedded системе ресурсы дороги...

Автор: kuzulis 7.12.2011, 20:55

Цитата
Я до конца механизм еще не понял (мало знаний, начинающий я...), но попробую как-нибудь всетаки красиво это решить.

Ok. Если у тебя получится, то сделай на гиториусе мерж-реквест и я волью твое решение в master ветку.

Цитата
Эта ветка считается более стабильной ?

Точнее сказать - более продуманной и правильной.
А от енумератора все-таки решили отказаться, т.к. все-таки не на всех платформах его можно реализовать да и дорого.

Если что - то его (енумератор) всегда можно самому сделать отдельным классом,
(для себя), если уж он так необходим.
И возложить на него урезанные функции - только определять имя появившегося устройства
и "скармливать" это имя в SerialPortInfo для получения подробной информации об устройстве.

И переименовать к примеру тогда этот класс из SerialDeviceEnumerator в SerialPortWatcher.

Автор: blinvip 11.12.2011, 16:10

Здравствуйте!

Пытаюсь написать программу для передачи AT-команд модему через COM-порт, используя библиотеку qserialdevice 2.0.

Подскажите, пожалуйста какими функциями можно реализовать подобную передачу команд (наподобие Hyperterminal).
На команду, переданную через тестовое приложение guiapp модем не реагирует.

Доступна ли документация на библиотеку?

Спасибо.

Автор: kuzulis 11.12.2011, 20:50

Цитата
Подскажите, пожалуйста какими функциями можно реализовать подобную передачу команд (наподобие Hyperterminal).

см. QIODevice::write()

Цитата
На команду, переданную через тестовое приложение guiapp модем не реагирует.

Да неужели? А не забыл ли кое кто добавить в конце команды что-то типа "\r\n" ?

Цитата
Доступна ли документация на библиотеку?

Да. Пока в виде комментариев в исходном коде.
В принципе см. методы в serialport.h , а комментарии в serialport.cpp

Автор: KocMak 11.12.2011, 21:01

Привет.

Использую Prolific USB-to-Serial Comm Port и библиотеку qserialdevice для передачи пакетов на свою железку.
Проблема в том, что после создания виртуального порта, пока я любым терминалом не открою/закрою нужный COM, данные не передаются, хотя порт открывается нормально. Потом всё работает как надо, могу отправлять и принимать данные.

Подскажите, в чём может быть проблема?

Автор: kuzulis 11.12.2011, 21:13

Цитата
Подскажите, в чём может быть проблема?

А конфигурировать порт кто будет после открытия?
Больше информации давай: какая ос, версия библиотеки, как открываешь и настраивашь порт,
код в студию.

Тут телепатов нет.

Автор: KocMak 11.12.2011, 23:05

Цитата(kuzulis @ 11.12.2011, 21:13) *
Цитата
Подскажите, в чём может быть проблема?

А конфигурировать порт кто будет после открытия?
Больше информации давай: какая ос, версия библиотеки, как открываешь и настраивашь порт,
код в студию.

Тут телепатов нет.


OC - Win XP и Win7, библиотека 0.4.0, код настройки порта:
void MainWindow::portInit()
{
    if(initSerial(("COM"+ui->comSelect->text()), ui->speedSelect->currentText().toInt()) == false)
    {
        QMessageBox::information(this,"Error", "Error Open COM"+ui->comSelect->text());
    }
}
bool MainWindow::initSerial(QString dev, int baudRate)
{
    serial = new AbstractSerial(this);
    serial->setDeviceName(dev);
    serial->setBaudRate(baudRate);
    serial->setDataBits(AbstractSerial::DataBits8);
    serial->setParity(AbstractSerial::ParityNone);
    serial->setStopBits(AbstractSerial::StopBits1);
    serial->setFlowControl(AbstractSerial::FlowControlOff);

    connect(this->serial, SIGNAL(readyRead()), this, SLOT(ReadData()));

    if(serial->open(AbstractSerial::ReadWrite))return true;
    else return false;
}

Автор: kuzulis 12.12.2011, 9:44

2 Гость_KocMak_*,

слушайте, парни, вы достали с такими вопросами уже.

Кто будет документацию читать?
Я не буду отвечать на ваш вопрос. Из принципа. Разбирайтесь сами где у вас накосячено.

ЗЫ:
Накипело.

ЗЫЗЫ:

Цитата
библиотека 0.4.0

Оно устарело. Используй ветку master или ветку 2.0.

Автор: KocMak 12.12.2011, 11:49

Цитата(kuzulis @ 12.12.2011, 9:44) *
Кто будет документацию читать?
Я не буду отвечать на ваш вопрос. Из принципа. Разбирайтесь сами где у вас накосячено.


Спасибо и на этом, буду разбираться.

Автор: blinvip 12.12.2011, 14:45

Спасибо, разобрался. действительно забыл вставить \r.

Автор: shurilnik 13.12.2011, 19:03

kuzulis, Подскажи это нормально что при использовании qserialdevice 2.0, для работы с usb serial если открыть порт и выдернуть usb устройство, то в основном процессе почему-то перестают выполняться все ивенты таймеров... они срабатывают только при любом ручном GUI ивенте. Можно ли как-то корректно отлавливать отключение usb устройства и закрывать открытый порт ? Или мы возвращаемся к схожей нерешенной ситуации что была в прошлой версии ?

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)