/*! \file piserial.h * \ingroup IO * \~\brief * \~english Serial device * \~russian Последовательный порт */ /* PIP - Platform Independent Primitives COM Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PISERIAL_H #define PISERIAL_H #include "piiodevice.h" #include "pitimer.h" //! \ingroup IO //! \~\brief //! \~english Serial device. //! \~russian Последовательный порт. class PIP_EXPORT PISerial: public PIIODevice { PIIODEVICE(PISerial, "ser"); public: //! \~english Contructs an empty %PISerial //! \~russian Создает пустой %PISerial explicit PISerial(); virtual ~PISerial(); //! \~english Parameters of PISerial //! \~russian Параметры PISerial enum Parameters { ParityControl /*! \~english Enable parity check and generate \~russian Включить генерацию и проверку контроля чётности */ = 0x1, ParityOdd /*! \~english Parity is odd instead of even \~russian Нечётный контроль чётности вместо чётного */ = 0x2, TwoStopBits /*! \~english Two stop bits instead of one \~russian Два стоповых бита вместо одного */ = 0x4 }; //! \~english Speed of PISerial //! \~russian Скорость PISerial enum Speed { S50 /*! 50 baud */ = 50, S75 /*! 75 baud */ = 75, S110 /*! 110 baud */ = 110, S300 /*! 300 baud */ = 300, S600 /*! 600 baud */ = 600, S1200 /*! 1200 baud */ = 1200, S2400 /*! 2400 baud */ = 2400, S4800 /*! 4800 baud */ = 4800, S9600 /*! 9600 baud */ = 9600, S14400 /*! 14400 baud */ = 14400, S19200 /*! 19200 baud */ = 19200, S38400 /*! 38400 baud */ = 38400, S57600 /*! 57600 baud */ = 57600, S115200 /*! 115200 baud */ = 115200, S230400 /*! 230400 baud */ = 230400, S460800 /*! 460800 baud */ = 460800, S500000 /*! 500000 baud */ = 500000, S576000 /*! 576000 baud */ = 576000, S921600 /*! 921600 baud */ = 921600, S1000000 /*! 1000000 baud */ = 1000000, S1152000 /*! 1152000 baud */ = 1152000, S1500000 /*! 1500000 baud */ = 1500000, S2000000 /*! 2000000 baud */ = 2000000, S2500000 /*! 2500000 baud */ = 2500000, S3000000 /*! 3000000 baud */ = 3000000, S3500000 /*! 3500000 baud */ = 3500000, S4000000 /*! 4000000 baud */ = 4000000 }; //! \ingroup IO //! \~\brief //! \~english Information about serial device //! \~russian Информация о последовательном устройстве struct PIP_EXPORT DeviceInfo { //! \~english Returns string representation of USB ID in format "xxxx:xxxx" (vID:pID) //! \~russian Возвращает строковое представление USB ID в формате "xxxx:xxxx" (vID:pID) PIString id() const; //! \~english USB Vendor ID //! \~russian USB Vendor ID uint vID = 0; //! \~english USB Product ID //! \~russian USB Product ID uint pID = 0; //! \~english Path to device, e.g. "COM2" or "/dev/ttyUSB0" //! \~russian Путь к устройству, например "COM2" или "/dev/ttyUSB0" PIString path; //! \~english Device description //! \~russian Описание устройства PIString description; //! \~english Device manufacturer //! \~russian Описание производителя PIString manufacturer; }; //! \~english Contructs %PISerial with device name "device", speed "speed" and parameters "params" //! \~russian Создает %PISerial с именем устройства "device", скоростью "speed" и параметрами "params" explicit PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags params = 0); //! \~english Set both input and output speed to "speed" //! \~russian Устанавливает скорости приема и передачи в "speed" void setSpeed(PISerial::Speed speed) { setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings(); } //! \~english Set output speed to "speed" //! \~russian Устанавливает скорость передачи в "speed" void setOutSpeed(PISerial::Speed speed) { setProperty("outSpeed", (int)speed); applySettings(); } //! \~english Set input speed to "speed" //! \~russian Устанавливает скорость приема в "speed" void setInSpeed(PISerial::Speed speed) { setProperty("inSpeed", (int)speed); applySettings(); } //! \~english Set device name to "dev" //! \~russian Устанавливает имя устройства в "dev" void setDevice(const PIString & dev) { setPath(dev); if (isOpened()) { close(); open(); }; } //! \~english Set parameters to "parameters_" //! \~russian Устанавливает параметры в "parameters_" void setParameters(PIFlags parameters_) { setProperty("parameters", (int)parameters_); applySettings(); } //! \~english Set parameter "parameter" to "on" state //! \~russian Устанавливает параметр "parameter" в "on" void setParameter(PISerial::Parameters parameter, bool on = true); //! \~english Returns if parameter "parameter" is set //! \~russian Возвращает установлен ли параметр "parameter" bool isParameterSet(PISerial::Parameters parameter) const; //! \~english Returns parameters //! \~russian Возвращает параметры PIFlags parameters() const { return (PIFlags)(property("parameters").toInt()); } //! \~english Set data bits count. Valid range is from 5 to 8, befault is 8 //! \~russian Устанавливает количество бит данных. Разрешены значения от 5 до 8, по умолчанию 8 void setDataBitsCount(int bits) { setProperty("dataBitsCount", bits); applySettings(); } //! \~english Returns data bits count //! \~russian Возвращает количество бит данных int dataBitsCount() const { return property("dataBitsCount").toInt(); } //! \~english Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS) //! \~russian Устанавливает пин с номером "number" в логический уровень "on". Разрешены номера 4 (DTR) и 7 (RTS) bool setPin(int number, bool on); //! \~english Returns pin number "number" logic level. Valid numbers range is from 1 to 9 //! \~russian Возвращает логический уровень пина с номером "number". Разрешены номера от 1 до 9 bool isPin(int number) const; bool setLE(bool on); // useless function, just formally bool setDTR(bool on); bool setRTS(bool on); bool setCTS(bool on); // useless function, just formally bool setST(bool on); // useless function, just formally bool setSR(bool on); // useless function, just formally bool setCAR(bool on); // useless function, just formally bool setRNG(bool on); // useless function, just formally bool setDSR(bool on); // useless function, just formally bool isLE() const; bool isDTR() const; bool isRTS() const; bool isCTS() const; bool isST() const; bool isSR() const; bool isCAR() const; bool isRNG() const; bool isDSR() const; //! \~english Switch transmission line in break //! \~russian Переключает состояние передачи в break bool setBreak(bool enabled); void setVTime(int t) { vtime = t; applySettings(); } //! \~english Returns device name //! \~russian Возвращает имя устройства PIString device() const { return path(); } //! \~english Returns output speed //! \~russian Возвращает скорость передачи PISerial::Speed outSpeed() const { return (PISerial::Speed)(property("outSpeed").toInt()); } //! \~english Returns input speed //! \~russian Возвращает скорость приема PISerial::Speed inSpeed() const { return (PISerial::Speed)(property("inSpeed").toInt()); } int VTime() const { return vtime; } //! \~english Discard all buffered input and output data //! \~russian Откидывает все буферизированные данные для передачи и приема virtual void flush() override; int read(void * read_to, int max_size) { return readDevice(read_to, max_size); } //! \~english Read from device no more "max_size" bytes into "read_to" with "timeout_ms" timeout //! \~russian Читает из устройства не более "max_size" байт в "read_to" с таймаутом "timeout_ms" bool read(void * read_to, int max_size, double timeout_ms); //! \~english Read from device for "timeout_ms" timeout or for "size" bytes //! \~russian Читает из устройства в течении таймаута "timeout_ms" или до "size" байт PIString readString(int size = -1, double timeout_ms = 1000.); //! \~english Read from device for "timeout_ms" timeout or for "size" bytes //! \~russian Читает из устройства в течении таймаута "timeout_ms" или до "size" байт PIByteArray readData(int size = -1, double timeout_ms = 1000.); //! \~english Write to device data "data" with maximum size "size". Returns if sended bytes count = "size" //! \~russian Пишет в порт не более "size" байт данных "data". Возвращает если количество записанных байт = "size" bool send(const void * data, int size); //! \~english Write to device byte array "data". Returns if sended bytes count = size of "data" //! \~russian Пишет в порт байтовый массив "data". Возвращает если количество записанных байт = размер "data" bool send(const PIByteArray & data) { return send(data.data(), data.size_s()); } void interrupt() override; //! \~english Returns all available speeds for serial devices //! \~russian Возвращает все возможные скорости для устройств static PIVector availableSpeeds(); //! \~english Returns all available system devices path. If "test" each device will be tried to open //! \~russian Возвращает пути всех доступных устройств в системе. Если "test", то каждое устройство будет опробовано на открытие static PIStringList availableDevices(bool test = false); //! \~english Returns all available system devices. If "test" each device will be tried to open //! \~russian Возвращает все доступные устройства в системе. Если "test", то каждое устройство будет опробовано на открытие static PIVector availableDevicesInfo(bool test = false); //! \ioparams //! \{ #ifdef DOXYGEN //! \~english device, default "" //! \~russian устройство, по умолчанию "" string device; //! \~english input/output speed, default 115200 //! \~russian скорость чтения/записи, по умолчанию 115200 int speed; //! \~english dataBitsCount, default 8 //! \~russian количесво бит данных, по умолчанию 8 int dataBitsCount; //! \~english parityControl, default false //! \~russian контроль четности, по умолчанию false bool parityControl; //! \~english parityOdd, default false //! \~russian нечётный контроль четности, по умолчанию false bool parityOdd; //! \~english twoStopBits, default false //! \~russian два стоповых бита, по умолчанию false bool twoStopBits; #endif //! \} protected: PIString constructFullPathDevice() const override; void configureFromFullPathDevice(const PIString & full_path) override; PIPropertyStorage constructVariantDevice() const override; void configureFromVariantDevice(const PIPropertyStorage & d) override; bool configureDevice(const void * e_main, const void * e_parent = 0) override; void optionsChanged() override; void threadedReadBufferSizeChanged() override; //! \~english Basic read function //! \~russian Базовое чтение ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t writeDevice(const void * data, ssize_t max_size) override; DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Sequential; } //! Executes when any read function was successful. Default implementation does nothing virtual void received(const void * data, int size) { ; } void construct(); void applySettings(); void setTimeouts(); int convertSpeed(PISerial::Speed speed); bool setBit(int bit, bool on, const PIString & bname); bool isBit(int bit, const PIString & bname) const; bool openDevice() override; bool closeDevice() override; PRIVATE_DECLARATION(PIP_EXPORT) int fd = -1, vtime = 10; std::atomic_bool sending; PITimeMeasurer tm_; }; //! \relatesalso PICout //! \~english Output operator to \a PICout //! \~russian Оператор вывода в \a PICout inline PICout operator<<(PICout s, const PISerial::DeviceInfo & v) { s << v.path << " (" << v.id() << ", \"" << v.manufacturer << "\", \"" << v.description << "\")"; return s; } //! \~english Compare operator //! \~russian Оператор сравнения inline bool operator==(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) { return v0.path == v1.path; } //! \~english Compare operator //! \~russian Оператор сравнения inline bool operator!=(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) { return v0.path != v1.path; } //! \relatesalso PIBinaryStream //! \~english Store operator. //! \~russian Оператор сохранения. BINARY_STREAM_WRITE(PISerial::DeviceInfo) { s << v.vID << v.pID << v.path << v.description << v.manufacturer; return s; } //! \relatesalso PIBinaryStream //! \~english Restore operator. //! \~russian Оператор извлечения. BINARY_STREAM_READ(PISerial::DeviceInfo) { s >> v.vID >> v.pID >> v.path >> v.description >> v.manufacturer; return s; } #endif // PISERIAL_H