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

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

Страниц: 1 ... 54 55 [56] 57 58 ... 88   Вниз
  Печать  
Автор Тема: Создаю библиотеку для работы с последовательными портами. [УШЕЛ ИЗ ПРОЕКТА].  (Прочитано 786380 раз)
b-s-a
Гость
« Ответ #825 : Март 02, 2012, 19:39 »

Думаю, надо не из списка свойств исключать, а из переделать сами методы, чтобы void возвращали. А ошибку узнавать через свойство error.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #826 : Март 02, 2012, 20:26 »

Что-то сомневаюсь в таком подходе, т.к. придется
каждый раз после каждого конфигурирования отдельного свойства вызывать error():
Код
C++ (Qt)
...
setRate(value);
if (error()) {
}
...
...
...
setParity(value);
if (error()) {
}
...
...
 

также не факт, что мы сможем поймать ошибку именно от конфигурирования.

Например, у нас был подконнекчен слот readyRead() (или не был, неважно), порт был открыт,
мы устанавливаем свойство setRate(value), и в это время вдруг
у нас происходит ошибка I/O (или еще что), поэтому вызов error()
вернет именно ошибку I/O, а не конфигурирования.

Те. между вызовами setRate() и error()  эта цепочка может прерваться
и отработать что-то из EventLoop, которое может изменить код ошибки... (или не может?)

Тут блин сложный вопрос, как бы не прогадать...
« Последнее редактирование: Март 02, 2012, 20:35 от kuzulis » Записан

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

Сообщений: 2812


Просмотр профиля
« Ответ #827 : Март 02, 2012, 20:42 »

И кстати, b-s-a, зацени если будет время текущую реализацию как аддон на gerrit, я там смержил.

1) Теперь нужно добавить документацию (хотя бы ее шаблон, т.е. что на страницах показывать, какие страницы, о чем писать и т.п.),
2) ну и определиться с пропертями.
3) написать тесты ( я вообще не представляю что в тестах имплементировать, наверное из сокетов что-то по аналогии взять)
4) нужно ли выкинуть код для симбиана?
5) доделать политики
6) определиться с неймспейсами и именованием классов, т.к. нокиевцы не отвечают на мои вопросы по этому поводу
7) нарисовать парочку примеров, кстати, идеи что реализовывать в примерах приветствуются.
8 ) ну и выпустить первую "stable" версию в качестве аддона.

надо поторопиться, а то dbzhang800-qextserialport тоже начал что-то рефакторить для Qt4/Qt5, как бы не обогнал и как бы не приняли его вариант,
а наш похерили Улыбающийся
« Последнее редактирование: Март 02, 2012, 20:54 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #828 : Март 02, 2012, 20:53 »

если уж так хочется надежности, то можно проверять так:
Код
C++ (Qt)
port.setRate(rate);
if (rate != port.rate()) {
...
}
Но я сильно сомневаюсь, что вообще кто-то заморачивается на это.

Ты еще не вмержил свои изменения? Если нет, то давай. А то есть идеи, но реализовать их нельзя, например:

Сейчас всегда нужно вызывать 6 методов для инициализации порта. Это в корне не верно! Нужно, или устанавливать настройки "по-умолчанию" при открытии (добавить соответствующий флажок, для отключения начальной настройки), или добавить метод:
Код
C++ (Qt)
setup(
     qint32 rate = Rate9600,
     Parity parity = NoParity,
     DataBits dataBits = Data8,
     StopBits stopBits = OneStop,
     FlowControl flow = NoFlowControl,
     DataErrorPolicy policy = IgnorePolicy
     );
Я склоняюсь к первому варианту.

1. С документацией я никогда не работал. Даже не в курсе.
2. с пропертями у меня есть свое мнение Улыбающийся
3. с сокетами проще, для них не нужна аппаратная поддержка. А вот для RS232 она требуется
4. зачем его выкидывать? кому мешает?
5. что там осталось, а то я подзабыл?
6. тут без троллей никак
7. Qt5 довольно сырая еще. Я собрал ее, запустил лингвист, был неприятно удивлен ужасному виду. Думаю, до релиза Qt5 еще долго. нужно пока работать с 4.8
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #829 : Март 02, 2012, 21:08 »

Цитировать
Но я сильно сомневаюсь, что вообще кто-то заморачивается на это.
Ага, а потом ловят глюки т.к. не проверяют возвращаемые значения.
Многие уже на забугорных форумах писали, что библиотека не работает - помогите - а сами не проверяли
никаких значений после конфигурирования. Улыбающийся

Цитировать
Ты еще не вмержил свои изменения? Если нет, то давай.
Вмержил, все компилится и работает, проверял.

Даже QT += serialport работает (только для Qt5 проверял). Улыбающийся

Цитировать
Сейчас всегда нужно вызывать 6 методов для инициализации порта. Это в корне не верно! Нужно, или устанавливать настройки "по-умолчанию" при открытии (добавить соответствующий флажок, для отключения начальной настройки)

Так он и так при открытии открывается со своими настройками по умолчанию!!!
Только если ему не удается определить текущую конфигурацию - то св-во устанавливается в Unknown.

Т.е. если при открытии текущие настройки удовлетворяют пользователя - то ничего настраивать не нужно.

Цитировать
2. с пропертями у меня есть свое мнение Улыбающийся
Это понятно, но не отгребем ли мы в дальнейшем проблем с функционированием и неудовольство от юзания потенциальных пользователей?
Цитировать
3. с сокетами проще, для них не нужна аппаратная поддержка. А вот для RS232 она требуется
в принципе, на потом можно оставить..
Цитировать
4. зачем его выкидывать? кому мешает?
Ну, она наполовину реализована, тем более, в Qt5 вроде ж вычистили код от симбиана.
Цитировать
5. что там осталось, а то я подзабыл?
Да нам с тобой договорится об понимании политик, т.к. у меня понимание иное (под Win) нежели так, как реализовал ты (в Lin),
т.е. разные точки зрения.
Цитировать
6. тут без троллей никак
Ну это понятно, в принципе потом ничего не мешает тупо заменить макросы и переименовать классы.
Цитировать
7. Qt5 довольно сырая еще. Я собрал ее, запустил лингвист, был неприятно удивлен ужасному виду. Думаю, до релиза Qt5 еще долго. нужно пока работать с 4.8
А мне понравилось, виджеты в Win какие-то прям реактивные стали  Улыбающийся
« Последнее редактирование: Март 02, 2012, 21:11 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #830 : Март 02, 2012, 21:59 »

Так он и так при открытии открывается со своими настройками по умолчанию!!!
Только если ему не удается определить текущую конфигурацию - то св-во устанавливается в Unknown.

Т.е. если при открытии текущие настройки удовлетворяют пользователя - то ничего настраивать не нужно.
Он сохраняет текущие настройки порта. Т.е. открыв его пользователь не знает, как он настроен и должен проверять или тупо перенастраивать все, чтобы гарантированно работать с определенными его протоколом настройками.
Сохранение текущих настроек порта при открытии - это мало кому нужная вещь. Сейчас, после открытия, порт находится в неизвестном состоянии. Что провоцирует ошибки - в 9 случаях работает, а в одном нет.

Цитировать
2. с пропертями у меня есть свое мнение Улыбающийся
Это понятно, но не отгребем ли мы в дальнейшем проблем с функционированием и неудовольство от юзания потенциальных пользователей?
А с классами Qt как?
Цитировать
4. зачем его выкидывать? кому мешает?
Ну, она наполовину реализована, тем более, в Qt5 вроде ж вычистили код от симбиана.
Ну если вычистили, то да...
Цитировать
5. что там осталось, а то я подзабыл?
Да нам с тобой договорится об понимании политик, т.к. у меня понимание иное (под Win) нежели так, как реализовал ты (в Lin),
т.е. разные точки зрения.
        SkipPolicy - если произошла ошибка, то байт проглатывается (пользователь его не получает вообще)
        PassZeroPolicy - если произошла ошибка, то пользователь получает 0 вместо битого байта
        IgnorePolicy - если произошла ошибка, то пользователь получает то, что пришло
        StopReceivingPolicy - если произошла ошибка, то текущая операция чтения прерывается СРАЗУ ПОСЛЕ СЧИТЫВАНИЯ ПРОБЛЕМНОГО БАЙТА и выставляется соответствующая ошибка.

Цитировать
7. Qt5 довольно сырая еще. Я собрал ее, запустил лингвист, был неприятно удивлен ужасному виду. Думаю, до релиза Qt5 еще долго. нужно пока работать с 4.8
А мне понравилось, виджеты в Win какие-то прям реактивные стали  Улыбающийся
Я под Linux запускал  Подмигивающий
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #831 : Март 02, 2012, 22:44 »

Цитировать
Он сохраняет текущие настройки порта. Т.е. открыв его пользователь не знает, как он настроен и должен проверять или тупо перенастраивать все, чтобы гарантированно работать с определенными его протоколом настройками.
Сохранение текущих настроек порта при открытии - это мало кому нужная вещь. Сейчас, после открытия, порт находится в неизвестном состоянии. Что провоцирует ошибки - в 9 случаях работает, а в одном нет.
Но так как предлагаешь ты - было реализовано в ранних релизах (там устанавливался при открытии режим 9600 8N1).
Эта реализация была удалена, т.к. кто-то говорил что это неправильно и приводил конкретный пример с конкретным оборудованием.

Тем более если сделаем как ты предлагаешь, если вдруг при открытии порта с установкой параметров возникнет ошибка при устрановке
любого свойства - то возвращать open() как false? Т.е. приплыли, не смогли открыть порт и установить настройки по умолчанию.
Тем более, что могут быть у-ва, которые не поддерживают 9600 8N1 и получится, что порт никогда не откроется.

Но даже если open() возвратит false, и далее по error() мы узнаем точно причину (пусть она в установке свойства) - то придется опять же по очереди перебирать
св-ва rate(), dataBits(), parity() и т.п. чтобы узнать, в каком из методов возник касяк.

Так что, имхо, это не то. Или ты имеешь ввиду что-то еще?  Улыбающийся

Цитировать
А с классами Qt как?
в смысле?

Цитировать
SkipPolicy - если произошла ошибка, то байт проглатывается (пользователь его не получает вообще)
        PassZeroPolicy - если произошла ошибка, то пользователь получает 0 вместо битого байта
        IgnorePolicy - если произошла ошибка, то пользователь получает то, что пришло
        StopReceivingPolicy - если произошла ошибка, то текущая операция чтения прерывается СРАЗУ ПОСЛЕ СЧИТЫВАНИЯ ПРОБЛЕМНОГО БАЙТА и выставляется соответствующая ошибка.

Я не по это - я про факт установки parity/frame error. Да и вообще, про св-во error().
Т.е. в моем понимании error() - это не что иное - как код последней ошибки, т.е. следующая ошибка перетирает предыдущую!

Исходя из этого, при определении parity/frame error хотя бы в одном из принятых байтов в внутреннем буфере - должна быть установлена эта ошибка,
и не сниматься, пока пользователь не сбросит её.

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

У тебя же ошибка устанавливается только при StopReceivingPolicy ! Что не правильно!
Реально ошибку нужно выставлять и при SkipPolicy, PassZeroPolicy !!!

Это необходимо для  того, чтобы пользователь после сигнала readyRead (в слоте) до вызова метода read(), мог например, вызвать error() и проверить - а не битые ли где-то в кольцевом буфере SerialPort данные??!! Это просто для информации.
Например, если битые - то их точно незачем читать и можно весь этот буфер очистить, не принимая этих данных - отказаться от них.
А можно и прочитать - все на совести самого пользователя.

Т.е. идея в том, что пользователь должен знать заранее состояние принятых данных в кольцевом буфере класса перед их чтением!!!

С
Цитировать
StopReceivingPolicy - если произошла ошибка, то текущая операция чтения прерывается СРАЗУ ПОСЛЕ СЧИТЫВАНИЯ ПРОБЛЕМНОГО БАЙТА и выставляется
что ты подразумеваешь под "прерывается"? Вообще прерывается ?
т.е. если имеем последовательность байт в UART (где V-валидный байт, E-байт с ошибкой)

VVVEVVVV - то в результате класс в свой кольцевой буфер прочитает только VVV, установит ошибку паритета/фрейма  и все?
На этом процесс чтения остановится навсегда, пока пользователь не сбросит error() ?
Т.е. rearyRead() грубо излучится один раз при приеме VVV и всё, а подсистема нотификации  класса просто будет читать в dev/null
все приходящие символы из UART, или они будут тупо накапливаться в UART (драйвере), пока не произойдет переполнение UART?

Поясни конкретнее принцип по StopReceivingPolicy как ты его видишь.
Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #832 : Март 03, 2012, 08:15 »

Во-первых, должно быть два метода open. Один открывает со стандартными (или даже предустановленными - настройки менять можно до открытия) настройками, второй оставляет настройки неизменными. Если не удалось выставить настройки, то open не должна открывать порт с выставлением соответствующей ошибки. Как вариант, можно ввести функцию setup, которая за один вызов настроит все.
Как в стандартных Qt-шных классах подобные вещи сделаны? Там возвращаются коды ошибок или что? Например, у сокета.
Во-вторых, во всех режимах, кроме StopReceivingPolicy, мы сами внутри не контролируем возникновение ошибок (это стандартные режимы работы порта, поэтому нет никакого смысла что-то там придумывать). Думаю, если юзеру надо, то пусть он выставляет StopReceivingPolicy и уже тогда разбирается.
В режиме StopReceivingPolicy происходит следующее:
в порту есть данные VVVEVVVV. Пользователь по bytesAvailable() получает результат 8 (сможем победить фоновое буферизирование?). Читает. Метод read считывает только VVVE, а код ошибки выставляется Parity/Frame error. Таким образом, нет никаких проблем для продолжения чтения - ты сбрасываешь ошибку (или игнорируешь) и продолжаешь. Следующий read вернет уже VVVV.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #833 : Март 03, 2012, 14:12 »

Цитировать
Во-первых, должно быть два метода open. Один открывает со стандартными (или даже предустановленными - настройки менять можно до открытия) настройками, второй оставляет настройки неизменными. Если не удалось выставить настройки, то open не должна открывать порт с выставлением соответствующей ошибки. Как вариант, можно ввести функцию setup, которая за один вызов настроит все.
Нет, я против такого зоопарка. Я считаю, что пользователь сам напишет метод setup и т.п. если ему нужно.
И тот факт - что у нас куча конкретных методов для конкретных действий - это хорошо. Это юникс вей!
Эти методы - это кирпичики - минимальный и гибкий интерфейс класса.
Нагромождать/менять/добавлять еще что-то не имеет смысла.
Ну, можно только на крайняк переписать сеттеры так, чтобы они не возвращали значение,
а оно возвращалось в error(). Имхо, то что сейчас есть - это наилучший вариант и не нужно ничего сверху мудрить со всякими open(), setup() и т.п. !
Я против!  Улыбающийся

Цитировать
Как в стандартных Qt-шных классах подобные вещи сделаны? Там возвращаются коды ошибок или что? Например, у сокета.
В том то и дело, что сокет несколько отличается от порта.

Хотя, в сокетах сеттеры типа setSocketOption() возвращают только void, но нигде не устанавливается error(), хотя в приватных кишках метод engine->setOption() возвращает bool. Т.е. тут не так однозначно: почему они не возвращают нигде код ошибки в некоторых сеттерах, почему этого не сделано??

Короче, нужно хорошо проанализировать аналогии и что-то взять, а что-то нет.

Также тут покопался в сокетах и вспомнил, что они имеют еще дополнительно такие сигналы как:
Код
C++ (Qt)
 
void connected();
void disconnected();
void error(QAbstractSocket::SocketError);
 

может быть и нам ввсести что-то похожее:
Код
C++ (Qt)
 
void opened();
void closed();
void error(SerialPort::SerialPortError);
 

?

Цитировать
Во-вторых, во всех режимах, кроме StopReceivingPolicy, мы сами внутри не контролируем возникновение ошибок (это стандартные режимы работы порта, поэтому нет никакого смысла что-то там придумывать). Думаю, если юзеру надо, то пусть он выставляет StopReceivingPolicy и уже тогда разбирается.
Нифига!
Первична - это ошибка паритета/фрейма, вторично - это уже ее обработка при помощи разных политик!
Т.е. сама ошибка паритета/фрейма никуда не делась, и о ней необходимо сигнализировать во всех  политиках кроме Ignore,
т.к. только в этом режиме мы её не анализируем вообще!

Цитировать
В режиме StopReceivingPolicy происходит следующее:
в порту есть данные VVVEVVVV. Пользователь по bytesAvailable() получает результат 8 (сможем победить фоновое буферизирование?). Читает. Метод read считывает только VVVE, а код ошибки выставляется Parity/Frame error. Таким образом, нет никаких проблем для продолжения чтения - ты сбрасываешь ошибку (или игнорируешь) и продолжаешь. Следующий read вернет уже VVVV.
В том то и дело, что первично - фоновое буферизирование - это режим по умолчанию! И побеждать его не надо, нужно отталкиваться именно от него.  Улыбающийся

В буферизированном режиме bytesAvailable() возвращает кол-во байт, доступных в кольцевом буфере , а не в UART!!
В режиме же без буферизации - кол-во доступных байт в UART!!!

Поэтому в небуферизованном режиме - будет работать так как ты описал,
но в режиме с буферизацией - оно автоматом должно тогда вычитать в кольцевой буфер из UART набор VVVE, выставить ошибку,
и больше ничего в кольцевой буфер не принимать, до того как юзер сбросит error(). Т.е. остальные данные
будут накапливаться в UART пока мы не сбросим ошибку.

Но тут возникает проблема с дальнейшей генерацией сигнала readyRead(), т.е. допустим, в UART пришло именно столько байт VVVEVVVV,
подсистема нотификации по приходу первого байта вызвала внутренний обработчик для перезаписи этих данных в кольцевой буфер класса.
ОК, она записала VVV, дошла до E, записала его, выставила ошибку и все, ждем. Тут пользователь, сбросил ошибку, вычитал все данные (или не все)
из кольцевого буфера... И - что дальше? Подсистема нотификации больше не сработает (по крайней мере на винде) даже если в UART у нас
остались еще не прочитанными VVVV, поэтому юзет не получит сигнала readyRead().
Хотя, такое же поведение с отсутствием readyRead() будет и не в буферизованном режиме.

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

Также, с режимом StopReceivingPolicy  - есть опасность переполнения буфера UART, если пользователь не успеет снять ошибку error().
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #834 : Март 03, 2012, 14:20 »

2kuzulis
По последней проблеме для венды. Можно добавить, например, таймер, который будет генерировать сигнал при возвращении в цикл обработки событий (с тайоутом = 0). И по его сигналу переэмитить сигнал readyRead. Ну и отключать его, если данных в UART нет.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #835 : Март 03, 2012, 14:27 »

Хотя, и с заменой сеттеров на методы, возвращающие void с записью ошибки в error() не все гладко,
например:

метод setRate() может закончится хреново со следующими кодами ошибок: UnsupportedOperation (если rate такая, что не поддерживается)
или с чем нить вроде InternalError (чисто гипотетически), т.е. метод может вернуть одну из нескольких ошибок!

Токда, проверка типа:
Код
C++ (Qt)
...
setRate()
 
if (error() == UnsupportedOperation || error() == InternalError ) {
// то точно произошла ошибка при setRate() а не при каком-то
// действии до вызова setRate().
}
...
 

Не находишь, что это как-то кривовато.
Не будет же юзер перед каждым вызовом сеттера делать unsetError() ?
Это глупо.

ИМХО, лучше убрать эти проперти вообще, и оставить гетеры/сеттеры такими какие они сейчас. т.е. с возвратом bool,
т.к. проверка:
Код
C++ (Qt)
if (!setRate()) {
   qDebug() << error();
}
 
намного правильнее и проще и короче, не находишь?  Улыбающийся
Записан

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

Сообщений: 2812


Просмотр профиля
« Ответ #836 : Март 03, 2012, 14:28 »

2kuzulis
По последней проблеме для венды. Можно добавить, например, таймер, который будет генерировать сигнал при возвращении в цикл обработки событий (с тайоутом = 0). И по его сигналу переэмитить сигнал readyRead. Ну и отключать его, если данных в UART нет.

А Таймер не сильно будет грузить ОС? А если у меня мультипортовая плата с 32 портами, то 32 таймера нужно...
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #837 : Март 03, 2012, 14:44 »

А Таймер не сильно будет грузить ОС? А если у меня мультипортовая плата с 32 портами, то 32 таймера нужно...
Так они вообще ничего ждать не будут. Как только в eventloop дело дойдет до обработки таймеров, то все активные сработают и пользователи получат свои readyRead. Если в 32 портах будут не прочитанные данные, сработаю все 32.

« Последнее редактирование: Март 03, 2012, 22:39 от BRE » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #838 : Март 03, 2012, 14:50 »

Цитата: BRE
Так они вообще ничего ждать не будут. Как только в eventloop дело дойдет до обработки таймеров, то все активные сработают и пользователи получат свои readyRead. Если в 32 партах будут не прочитанные данные, сработаю все 32.
Ну ка, кинь примерчик как ты это представляешь, а то я не соображу.
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #839 : Март 03, 2012, 15:01 »

Ну ка, кинь примерчик как ты это представляешь, а то я не соображу.

Код
C++ (Qt)
// Создаем таймер
m_readyReadTimer = new QTimer;
connect( m_readyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead()) );
m_readyReadTimer->setInterval( 0 );
m_readyReadTimer->setSingleShot( false );
 
 
// Я давно не смотрел как там у тебя сейчас все внутри работает... просто предположу
// В месте где ты получаешь нотификацию от венды о появлении данных
m_readyReadTimer->start();
 
 
// В том месте, где данные вычитываются из UART
if( uartEmpty() )
   m_readyReadTimer->stop();
 

В таком варианте, пришли данные, венда сообщила, запустился таймер, пользователь получил свой сигнал readyRead, вычитал часть данных и вышел из слота. Управление вернулось в цикл обработки событий, произошла проверка запущенных таймеров, такой таймер есть (m_readyReadTimer), таймаут == 0, он срабатывает, формируется сигнал timeout -> readyRead, пользователь опять получает сигнал readyRead. И пока он не вычитает все он будет его получать.
Записан
Страниц: 1 ... 54 55 [56] 57 58 ... 88   Вверх
  Печать  
 
Перейти в:  


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