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

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

Страниц: 1 ... 24 25 [26] 27 28 ... 88   Вниз
  Печать  
Автор Тема: Создаю библиотеку для работы с последовательными портами. [УШЕЛ ИЗ ПРОЕКТА].  (Прочитано 752691 раз)
b-s-a
Гость
« Ответ #375 : Июнь 15, 2011, 10:46 »

"Ловушки удобства "
Я это уже смотрел. Сначала думал отказаться от setup, но затем решил, что не стоит. Он настраивает именно так, как предполагает пользователь:
Код
C++ (Qt)
setup(baud115200); //115200n1
setup(baud57600, SerialDevice::Even); //57600e1
setup(baud9600, SerialDevice::Mark, SerialDevice::Two); //9600m2
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #376 : Июнь 15, 2011, 10:50 »

Цитата: b-s-a
Сначала думал отказаться от setup, но затем решил, что не стоит. Он настраивает именно так, как предполагает пользователь:
Код
C++ (Qt)
setup(baud115200); //115200n1
setup(baud57600, SerialDevice::Even); //57600e1
setup(baud9600, SerialDevice::Mark, SerialDevice::Two); //9600m2
 
Но это неявно! Зачем усложнять интерфейс лишними методами?
Пользователю придется "телепатить" и смотреть в документацию: а что будет, если я напишу только baud115200 ? И т.п.

Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #377 : Июнь 15, 2011, 10:51 »

НО! Я против предустановки параметров порта при его открытии и т.п. ,
т.к. вдруг пользователю понадовится не 1 стоп бит и 8 бит данных - а иное значение,
и получается, что классу приходится дважды изменять параметры:
один раз при открытии/конструкторе
второй раз - пользователь меняет.

Предлагаю вообще при открытии порта всё оставить так как есть сейчас:
определяются текущие параметры по умолчанию и ими заполняются внутренние переменные класса. И всё!
И пользователь уже сам решает: или его удовлетворяет то что определилось, или он выборочно сам установит то что ему нужно.
А я разве говорил, что против? Я всегда был за! Именно для этого я ввел метод setup, чтобы пользователь мог САМ после открытия настроить порт одним махом:
Код
C++ (Qt)
SerialDevice *port = new SerialDevice("COM1");
if (!port->open(QIODevice::ReadWrite)) {}
port->setup(baud9600, SerialDevice::Odd);
//...

Ладно. Предлагаю не "сраться" из-за ерунды. Не нравится метод setup(), можно его не вводить. Надо закончить с интерфейсом класса SerialDevice и переключиться на SerialDeviceEnumerator. Который меня лично пугает еще больше.
« Последнее редактирование: Июнь 15, 2011, 10:53 от b-s-a » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #378 : Июнь 15, 2011, 11:55 »

Цитировать
Ладно. Предлагаю не "сраться" из-за ерунды. Не нравится метод setup(), можно его не вводить. Надо закончить с интерфейсом класса SerialDevice

Код
C++ (Qt)
/*
   License...
*/

 
#ifndef SERIALDEVICE_H
#define SERIALDEVICE_H
 
#include <QtCore/QIODevice>
 
class SerialDevicePrivate;
 
class QSERIALDEVICE_EXPORT SerialDevice : public QIODevice
{
   Q_OBJECT
 
   Q_PROPERTY(BaudRate baudRate READ baudRate WRITE setBaudRate)
   Q_PROPERTY(DataBits dataBits READ dataBits WRITE setDataBits)
   Q_PROPERTY(Parity parity READ parity WRITE setParity)
   Q_PROPERTY(StopBits stopBits READ stopBits WRITE setStopBits)
   Q_PROPERTY(FlowControl flowControl READ flowControl WRITE setFlowControl)
   Q_PROPERTY(DataErrorPolicy dataErrorPolicy READ dataErrorPolicy WRITE setDataErrorPolicy)
   Q_PROPERTY(bool dtr READ dtr WRITE setDtr)
   Q_PROPERTY(bool rts READ rts WRITE setRts)
   Q_PROPERTY(SerialError error READ error RESET unsetError)
 
   Q_ENUMS( Directions BaudRate DataBits Parity StopBits FlowControl Lines DataErrorPolicy SerialError )
 
public:
 
   enum Direction  { Input = 1, Output = 2 };
   Q_DECLARE_FLAGS(Directions, Direction)
 
   enum BaudRate {
       Baud1200 = 1200, Baud2400 = 2400, Baud4800 = 4800,  
       Baud9600 = 9600, Baud19200 = 19200, Baud38400 = 38400,  
       Baud57600 = 57600, Baud115200 = 115200,
       UnknownBaudRate = -1
   };
 
   enum DataBits {
       Data5 = 5, Data6 = 6,
       Data7 = 7, Data8 = 8,
       UnknownDataBits = -1
   };
 
   enum Parity {
       NoParity = 0, EvenParity = 2, OddParity = 3,        
       SpaceParity = 4, MarkParity = 5,        
       UnknownParity = -1
   };
 
   enum StopBits {
       OneStop = 1, OneAndHalfStop = 3, TwoStop = 2,
       UnknownStopBits = -1
   };
 
   enum FlowControl {
       NoControl,      
       HardwareControl,
       SoftwareControl,
       UnknownFlowControl = -1
   };
 
   enum Line {
       Le = 0x01, Dtr = 0x02, Rts = 0x04,
       St = 0x08, Sr = 0x10, Cts = 0x20,
       Dcd = 0x40, Ri = 0x80, Dsr = Le    
   };
   Q_DECLARE_FLAGS(Lines, Line)
 
   enum DataErrorPolicy {
       SkipPolicy,
       PassZeroPolicy,
       IgnorePolicy,
       StopReceivingPolicy
   };
 
   enum SerialError {
       NoError,                
       NoSuchDeviceError,          
       PermissionDeniedError,      
       DeviceAlreadyOpenedError,    
       DeviceIsNotOpenedError,      
       ParityError,
       IoError
   };
 
   explicit SerialDevice(QObject *parent = 0);
   explicit SerialDevice(const QString &deviceName, QObject *parent = 0);
   virtual ~SerialDevice();
 
   void setDeviceName(const QString &deviceName);
   QString deviceName() const;
 
   virtual bool open(OpenMode mode);
   virtual void close();
 
   bool setBaudRate(qint32 baud, Directions dir = Input | Output);
   qint32 baudRate(Directions dir = Input | Output) const;
 
   bool setDataBits(DataBits dataBits);
   DataBits dataBits() const;
 
   bool setParity(Parity parity);
   Parity parity() const;
 
   bool setStopBits(StopBits stopBits);
   StopBits stopBits() const;
 
   bool setFlowControl(FlowControl flow);
   FlowControl flowControl() const;
 
   void setDataInterval(int usecs = 0);
   int dataInterval() const;
 
   void setReadTimeout(int msecs = 0);
   int readTimeout() const;
 
   bool dtr() const;
   bool rts() const;
 
   Lines lines() const;
 
   bool flush();
   virtual bool reset();
 
   void setDataErrorPolicy(DataErrorPolicy policy = IgnorePolicy);
   DataErrorPolicy dataErrorPolicy() const;
 
   SerialError error() const;
   void unsetError();
 
   virtual bool isSequential() const;
 
   virtual qint64 bytesAvailable() const;
   virtual qint64 bytesToWrite() const;
 
   virtual bool waitForReadyRead(int msecs);
   virtual bool waitForBytesWritten(int msecs);
 
public Q_SLOTS:
   bool setDtr(bool set);
   bool setRts(bool set);
   bool sendBreak(int duration = 0);
   bool setBreak(bool set = true);
   bool clearBreak(bool clear = true);
 
protected:
   virtual qint64 readData(char *data, qint64 maxSize);
   virtual qint64 writeData(const char *data, qint64 maxSize);
 
private:
   SerialDevicePrivate * const d_ptr;
 
   Q_DECLARE_PRIVATE(SerialDevice)
   Q_DISABLE_COPY(SerialDevice)
};
 
inline bool SerialDevice::clearBreak(bool clear)
{ return setBreak(!clear); }
 
Q_DECLARE_OPERATORS_FOR_FLAGS(SerialDevice::Directions)
Q_DECLARE_OPERATORS_FOR_FLAGS(SerialPort::Lines)
 
#endif // SERIALDEVICE_H
 
 

И в, в аттаче.

Цитировать
и переключиться на SerialDeviceEnumerator. Который меня лично пугает еще больше.
Ну, начинай критику Улыбающийся

Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #379 : Июнь 15, 2011, 12:30 »

1. Какому стилю соответствует размещение нескольких элементов enum'а в строке?
2. Не нравится NoControl, SoftwareControl... Тогда уж лучше NoFlowControl...
3. Забыл метод QList<int> standardBauds() const; (или нет? см. ниже)

SerialDeviceEnumerator.
предлагаю от него вообще отказаться. Так как непрерывное слежение за появлением/пропаданием портов мало кому может понадобиться. А если вдруг и понадобится, то никто не мешает посадить на таймер опрос списка доступных портов.

Поэтому, вместо этого класса предлагаю ввести SerialDeviceInfo (по аналогии QPrinterInfo):
Код
C++ (Qt)
class SerialDevice;
class SerialDeviceInfoPrivate;
 
class SerialDeviceInfo
{
public:
  SerialDeviceInfo(); //produces NULL info
  SerialDeviceInfo(const SerialDeviceInfo &other); //copy constructor
  explicit SerialDeviceInfo(const SerialDevice &device);
  SerialDeviceInfo& operator=(const SerialDeviceInfo &other);
  void swap(SerialDeviceInfo &other);
 
  QString deviceName() const;   //OS depended (/dev/ttyS0)
  QString name() const;  //frendly name like COM1, ttyS0...
  bool isNull() const;
  bool isBusy() const;
  QList<int> standardBauds() const;
  static QList<SerialDeviceInfo> availableDevices();
private:
   Q_DECLARE_PRIVATE(SerialDeviceInfo)
   SerialDeviceInfoPrivate *d_ptr;
};
Извиняйте народ, но я убрал всякие driver(), deviceId(), bus() и пр. Так как не уверен, что под системами, отличными от Windows, это можно вменяемо реализовать. Если есть простые способы сделать под *nix, то можно и оставить. Но не уверен, что тролли это пропустят, если вдруг будут включать в Qt.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #380 : Июнь 15, 2011, 13:20 »

Цитировать
1. Какому стилю соответствует размещение нескольких элементов enum'а в строке?
2. Не нравится NoControl, SoftwareControl... Тогда уж лучше NoFlowControl...
3. Забыл метод QList<int> standardBauds() const; (или нет? см. ниже)
Вроде исправил, см. аттач.

Цитировать
предлагаю от него вообще отказаться. Так как непрерывное слежение за появлением/пропаданием портов мало кому может понадобиться. А если вдруг и понадобится, то никто не мешает посадить на таймер опрос списка доступных портов.
Слишком уж упрощается/урезается Грустный

Цитировать
Извиняйте народ, но я убрал всякие driver(), deviceId(), bus() и пр. Так как не уверен, что под системами, отличными от Windows, это можно вменяемо реализовать. Если есть простые способы сделать под *nix, то можно и оставить. Но не уверен, что тролли это пропустят, если вдруг будут включать в Qt.
Блин, оставь хоть:
Код
C++ (Qt)
....
  QString deviceName() const;   //OS depended (/dev/ttyS0)
  QString shortName() const;     //Обрезаное имя, COM1, ttyUSB0 и т.п. +++
  QString friendlyName() const;  //+++
  QString description() const;     //+++
  QString manufacturer() const;     //+++
 
  bool isNull() const;   //Что сие значит?
  bool isBusy() const; //Насчет этого метода не уверен, т.к. тормозит в винде.
....
 

Хотя, почему бы не оставить и другие методы (vid,pid и т.п.) ?
Ну подумаешь, в некоторых ОС они будут пустую строку возвращать, ну и пусть.

Это ж класс - ИНФО в конце то концов.  Улыбающийся

Насчет списка стандартных скоростей: а может и вправду этот метод сюда сунуть вместо класса порта?

Причем, если бы была возможность определить реальные типы скоростей поддерживаемые тем или иным портом/драйвером - это было б здорово.
Записан

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

Сообщений: 3880


Просмотр профиля WWW
« Ответ #381 : Июнь 15, 2011, 13:32 »

>>то всегда при открытии порта надо будет ручками задавать следующие свойства:
а почему всегда? Порт что после закрытия забывает настройки?

я вижу применение так:
Код
C++ (Qt)
QSerialDevice *port = new QSerialDevice();
 
setBodeRate(...);
setParity(...);
// и так далее
 
// где-то в коде
if (!port->open())
   ERROR
// пользуемся
 
port->close();
 
 
// где-то опять в коде
if (!port->open())
   ERROR
// пользуемся
 
port->close();
 
 
Записан

Юра.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #382 : Июнь 15, 2011, 13:40 »

>>а почему всегда? Порт что после закрытия забывает настройки?
Только если мы перед закрытием эти настройки (в системе) не восстанавливаем.
В противном случае (если только закрываем дескриптор), то настройки порта (в системе) сохраняются.  

>>я вижу применение так:
Не, не, не, сначала нужно порт открыть, а потом уже конфигурировать (ИМХО).
Это само собой разумеется и естественней.
« Последнее редактирование: Июнь 15, 2011, 13:43 от kuzulis » Записан

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

Сообщений: 3880


Просмотр профиля WWW
« Ответ #383 : Июнь 15, 2011, 13:42 »

>>Не, не, не, сначала нужно порт открыть, а потом уже конфигурировать (ИМХО).
это для меня открытие!

Насколько помню винАПИ:
Заполняем всякие DCB и т.п. потом открываем файл
Записан

Юра.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #384 : Июнь 15, 2011, 13:44 »

Цитировать
это для меня открытие!

Насколько помню винАПИ:
Заполняем всякие DCB и т.п. потом открываем файл
Нет, чтобы получить/установить DCB - нужно сначала получить дескриптор !
А чтобы получить дескриптор - нужно открыть порт!  Подмигивающий

В *nix аналогично.
« Последнее редактирование: Июнь 15, 2011, 13:46 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #385 : Июнь 15, 2011, 13:57 »

Блин, оставь хоть:
Код
C++ (Qt)
....
  QString deviceName() const;   //OS depended (/dev/ttyS0)
  QString shortName() const;     //Обрезаное имя, COM1, ttyUSB0 и т.п. +++
  QString friendlyName() const;  //+++
  QString description() const;     //+++
  QString manufacturer() const;     //+++
 
  bool isNull() const;   //Что сие значит?
  bool isBusy() const; //Насчет этого метода не уверен, т.к. тормозит в винде.
....
 
Чем shortName() от friendlyName() будет отличаться? Или ты хотел friendlyName() чтобы возвращала "последовательный порт 1 на шине USB"? Думаю, достаточно "COM1". Как вариант: "Serial1", "Serial2"... Но при переводе будет не очень коротко... Думаю, лучше оставить "COM1"... Пусть в разных системах называется по разному. Думаю, ничего в этом страшного нет.
manufacturer()/description() - ну зачем? Это же для работы особо не нужно. Так, "рюшечки".

Хотя, почему бы не оставить и другие методы (vid,pid и т.п.) ?
Ну подумаешь, в некоторых ОС они будут пустую строку возвращать, ну и пусть.

Это ж класс - ИНФО в конце то концов.  Улыбающийся
Вот решит какой-то программер использовать это все в своей проге. Под виндой все пашет, а под *nix вообще не работает - порты не находятся или названий не имеют.
Причем, если бы была возможность определить реальные типы скоростей поддерживаемые тем или иным портом/драйвером - это было б здорово.
Можно попробовать перебором задать все стандартные скорости и определить, какие из них не вызывают ошибок. Но не уверен, что оно того стоит.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #386 : Июнь 15, 2011, 14:06 »

Цитировать
Чем shortName() от friendlyName() будет отличаться? Или ты хотел friendlyName() чтобы возвращала "последовательный порт 1 на шине USB"?
1. shortName() - это то что у тебя было как: name()
2. friendlyName() - да, будет возвращать примерно то что ты написал (т.е. тот же функционал что и реализован на данный момент в библиотеке)

Цитировать
Но при переводе будет не очень коротко..
Зачем переводить?

Цитировать
manufacturer()/description() - ну зачем? Это же для работы особо не нужно. Так, "рюшечки".
Ну да, рюшки. Но это же класс который поставляет информацию!

Цитировать
Вот решит какой-то программер использовать это все в своей проге. Под виндой все пашет, а под *nix вообще не работает - порты не находятся или названий не имеют.
Имеют, по крайней мере в linux и macOSX. В остальных случаях, если какой-то параметр не будет найден,
можно возвращать что-то типа "Не найдено".

Я же не зря добавлял эти методы и искал соответствие в разных ОС.
И, по крайней мере, в трёх ОС: Windows, Linux, MacOSX они совпадают.

И в конце концов: а почему бы и нет?

Цитировать
Можно попробовать перебором задать все стандартные скорости и определить, какие из них не вызывают ошибок. Но не уверен, что оно того стоит.
Согласен, оно не нужно, можно просто выводить "стандартный" список.
« Последнее редактирование: Июнь 15, 2011, 14:08 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #387 : Июнь 15, 2011, 14:57 »

Хорошо. Пусть будут. Но без фанатизма. Кому-нибудь нужны всякие низкоуровневые вещи (bus, vendorId, ...)?
Тогда надо разобраться с кучей name, например:
1. Заменить название deviceName на deviceId (под nix* будет /dev/ttyS0..., под Windows \\\\.\\COMx) в т.ч. и в SerialDevice
2. Заменить shortName() на name() ("ttySx", "COMx")
Итого, будет 2 типа имени: просто и "дружественное", а так же нестандартизированный (содержимое QString) идентификатор порта.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #388 : Июнь 15, 2011, 15:10 »

Цитировать
1. Заменить название deviceName на deviceId (под nix* будет /dev/ttyS0..., под Windows \\\\.\\COMx) в т.ч. и в SerialDevice
Может тогда на devicePath() (или pathToDevice())?

Но, если заменим и в SerialDevice, то нужно будет в SerialDevice изменить метод setDeviceName() на setName(),
а deviceName() на name() ?
 
Записан

ArchLinux x86_64 / Win10 64 bit
b-s-a
Гость
« Ответ #389 : Июнь 15, 2011, 16:55 »

Цитировать
1. Заменить название deviceName на deviceId (под nix* будет /dev/ttyS0..., под Windows \\\\.\\COMx) в т.ч. и в SerialDevice
Может тогда на devicePath() (или pathToDevice())?

Но, если заменим и в SerialDevice, то нужно будет в SerialDevice изменить метод setDeviceName() на setName(),
а deviceName() на name() ?
 
Ты не понял. Я предлагаю заменить на: SerialDevice::setDeviceId()
Записан
Страниц: 1 ... 24 25 [26] 27 28 ... 88   Вверх
  Печать  
 
Перейти в:  


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