#ifndef SERIAL_PORT_WORKER_H_INCLUDED #define SERIAL_PORT_WORKER_H_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include struct Command { enum : uint16_t {PRIORITY_1, PRIORITY_2, PRIORITY_3, PRIORITY_4, END_MARK}; enum : uint16_t {QUIT_SENTINEL = 0x1000, SEND_BLOCK_SIZE = 160}; uint32_t m_priority; uint16_t m_priorityClass; uint16_t m_cmdId; char *m_sendBuffer; char *m_recvBuffer; uint8_t m_sendBufferLength; uint8_t m_recvBufferLength; // expected result length static std::atomic m_nextSendBufferIndex; static std::atomic m_nextRecvBufferIndex; static char m_sendBuffers[256][SEND_BLOCK_SIZE]; static char m_recvBuffers[256][SEND_BLOCK_SIZE]; static uint32_t getNextCommandPriority(uint8_t cmdType); static char *getNextSendBuffer(); static char *getNextRecvBuffer(); public: Command(uint16_t cmdId, uint8_t sendBufferLength, uint8_t recvBufferLength, uint8_t priorityClass); Command(); friend bool operator< (Command const& lhs, Command const& rhs) { return lhs.m_priority < rhs.m_priority; } friend std::ostream& operator<< (std::ostream& os, Command const& cmd) { return os << "{ " << cmd.m_priority << ", '" << cmd.m_priority << "' } "; } }; /// \brief SerialPortWorker /// /// SerialPortWorker sends and receives data from serial port /// class SerialPortWorker : public QThread { Q_OBJECT /// \brief Internal serial port. QSerialPort m_serialPort; /// \brief Internal serial port info. QSerialPortInfo m_serialPortInfo; /// \brief Flag indicating if serial port is opened. bool m_serialPortOpened; /// \brief Port name of serial port. QString m_portName; /// \brief Baudrate of internal serial port. enum QSerialPort::BaudRate m_baudRate; std::priority_queue> m_sendQueue; std::deque m_recvQueue; std::mutex m_sendQueueMutex; std::mutex m_recvQueueMutex; std::condition_variable m_sendQueueCondVar; std::condition_variable m_recvQueueCondVar; std::atomic m_bytesWritten; std::atomic m_bytesAvailable; SerialPortWorker(QString portName, QSerialPort::BaudRate baudRate, QObject *parent = nullptr); Command getNextCommand(); void insertResult(Command const &result); enum : uint16_t {TIMEOUT = 100, WAIT_TIME_MAX = 1000}; public: ~SerialPortWorker(); SerialPortWorker(SerialPortWorker const &) = delete; void operator=(SerialPortWorker const &) = delete; // serial port im plugin anlegen. erst dann kann getInstance() benutzt werden static SerialPortWorker &getInstance(QString portName, QSerialPort::BaudRate baudRate, QObject *parent = nullptr) { static SerialPortWorker serialPortWorker(portName, baudRate, parent); return serialPortWorker; } bool openSerialPort(); void closeSerialPort(); bool isPortOpen() const { return m_serialPortOpened; } void insertCommand(Command const &cmd); bool getNextResult(Command &result, int timeout = 1000); virtual void run() override; void quit(); private slots: void getBytesAvailable(); bool getNumberOfBytesWritten(qint64); }; #endif // SERIAL_PORT_WORKER_H_INCLUDED