--- /dev/null
+#include "rgb_serial_reader.h"\r
+#include <QDebug>\r
+#include <QMessageBox>\r
+#include <QByteArray>\r
+#include <QDataStream>\r
+#include <QTimer>\r
+\r
+RgbSerialReader::RgbSerialReader(int port_index, QObject *parent)\r
+ : QObject(parent)\r
+ , m_port_index(port_index)\r
+ , m_rgb_serial(new QSerialPort(this))\r
+{\r
+ // 连接串口信号\r
+ connect(m_rgb_serial, &QSerialPort::readyRead, this, &RgbSerialReader::onReadyRead);\r
+ connect(m_rgb_serial, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::error),\r
+ this, &RgbSerialReader::onError);\r
+}\r
+\r
+RgbSerialReader::~RgbSerialReader()\r
+{\r
+ disconnectPort();\r
+}\r
+\r
+void RgbSerialReader::connectPort(const QString& com_name, int baud_rate)\r
+{\r
+ if (m_rgb_serial->isOpen()) {\r
+ qDebug() << tr("端口%1 RGB串口已经打开,先关闭").arg(m_port_index + 1);\r
+ m_rgb_serial->close();\r
+ }\r
+ \r
+ // 检查是否选择了 "None"\r
+ if (com_name.isEmpty() || com_name == tr("None") || com_name == "None") {\r
+ qDebug() << tr("端口%1未选择RGB串口(选择了None),跳过打开串口操作").arg(m_port_index + 1);\r
+ emit connectionStatusChanged(false);\r
+ return;\r
+ }\r
+ \r
+ qDebug() << tr("=== 开始连接RGB串口%1 ===").arg(m_port_index + 1);\r
+ qDebug() << tr("RGB串口名称:") << com_name;\r
+ qDebug() << tr("波特率:") << baud_rate;\r
+ \r
+ m_rgb_serial->setPortName(com_name);\r
+ m_rgb_serial->setBaudRate(baud_rate);\r
+ m_rgb_serial->setDataBits(QSerialPort::Data8);\r
+ m_rgb_serial->setParity(QSerialPort::NoParity);\r
+ m_rgb_serial->setStopBits(QSerialPort::OneStop);\r
+ m_rgb_serial->setFlowControl(QSerialPort::NoFlowControl);\r
+ m_rgb_serial->setReadBufferSize(MAX_BUFFER_SIZE);\r
+ \r
+ // 清空接收缓冲区\r
+ m_receive_buffer.clear();\r
+ \r
+ if (m_rgb_serial->open(QIODevice::ReadWrite)) { // RGB串口需要读写(发送指令)\r
+ qDebug() << tr("端口%1 RGB串口打开成功").arg(m_port_index + 1);\r
+ emit connectionStatusChanged(true);\r
+ \r
+ // 连接成功后自动发送初始化指令\r
+ QTimer::singleShot(100, this, [this]() {\r
+ sendCloseLedCommand(); // 关闭LED\r
+ QTimer::singleShot(50, this, [this]() {\r
+ sendSaveLedCommand(); // 保存LED设置\r
+ QTimer::singleShot(50, this, [this]() {\r
+ sendQueryRgbcCommand(); // 查询RGBC数据\r
+ });\r
+ });\r
+ });\r
+ } else {\r
+ QString errorMsg = tr("端口%1 RGB串口打开失败: %2").arg(m_port_index + 1).arg(m_rgb_serial->errorString());\r
+ qDebug() << errorMsg;\r
+ emit errorOccurred(errorMsg);\r
+ emit connectionStatusChanged(false);\r
+ }\r
+}\r
+\r
+void RgbSerialReader::disconnectPort()\r
+{\r
+ if (m_rgb_serial->isOpen()) {\r
+ qDebug() << tr("端口%1关闭RGB串口").arg(m_port_index + 1);\r
+ m_rgb_serial->close();\r
+ emit connectionStatusChanged(false);\r
+ }\r
+ \r
+ // 清空接收缓冲区\r
+ m_receive_buffer.clear();\r
+}\r
+\r
+void RgbSerialReader::onReadyRead()\r
+{\r
+ const QByteArray data = m_rgb_serial->readAll();\r
+ \r
+ if (data.isEmpty()) {\r
+ return;\r
+ }\r
+ \r
+ // 将新数据添加到缓冲区\r
+ m_receive_buffer.append(data);\r
+ \r
+ // 保持缓冲区大小合理,避免内存溢出\r
+ if (m_receive_buffer.length() > MAX_BUFFER_SIZE) {\r
+ // 保留最近的数据\r
+ m_receive_buffer = m_receive_buffer.right(MAX_BUFFER_SIZE);\r
+ qDebug() << tr("端口%1 RGB串口缓冲区过大,保留最近%2字节").arg(m_port_index + 1).arg(MAX_BUFFER_SIZE);\r
+ }\r
+ \r
+ // 发送原始数据信号(仅发送新接收的数据)\r
+ emit dataReceived(data);\r
+ emit rgbDataReceived(m_port_index, data);\r
+ \r
+ // 解析RGBC数据(从整个缓冲区中查找Byte2=0x15的数据包)\r
+ parseRgbcData(m_receive_buffer);\r
+}\r
+\r
+void RgbSerialReader::onError(QSerialPort::SerialPortError error)\r
+{\r
+ if (error == QSerialPort::NoError) {\r
+ return;\r
+ }\r
+ \r
+ QString errorMsg;\r
+ switch (error) {\r
+ case QSerialPort::DeviceNotFoundError:\r
+ errorMsg = tr("端口%1 RGB串口设备未找到").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::PermissionError:\r
+ errorMsg = tr("端口%1 RGB串口权限错误").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::OpenError:\r
+ errorMsg = tr("端口%1 RGB串口打开错误").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::WriteError:\r
+ errorMsg = tr("端口%1 RGB串口写入错误").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::ReadError:\r
+ errorMsg = tr("端口%1 RGB串口读取错误").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::ResourceError:\r
+ errorMsg = tr("端口%1 RGB串口资源错误(设备可能已断开)").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::UnsupportedOperationError:\r
+ errorMsg = tr("端口%1 RGB串口不支持的操作").arg(m_port_index + 1);\r
+ break;\r
+ case QSerialPort::TimeoutError:\r
+ errorMsg = tr("端口%1 RGB串口超时错误").arg(m_port_index + 1);\r
+ break;\r
+ default:\r
+ errorMsg = tr("端口%1 RGB串口未知错误: %2").arg(m_port_index + 1).arg(error);\r
+ break;\r
+ }\r
+ \r
+ qDebug() << errorMsg;\r
+ emit errorOccurred(errorMsg);\r
+ \r
+ // 如果是资源错误,自动断开连接\r
+ if (error == QSerialPort::ResourceError) {\r
+ disconnectPort();\r
+ }\r
+}\r
+\r
+void RgbSerialReader::sendCloseLedCommand()\r
+{\r
+ if (!m_rgb_serial || !m_rgb_serial->isOpen()) {\r
+ return;\r
+ }\r
+ \r
+ // 关闭LED指令: A5 6A 0F\r
+ QByteArray cmd;\r
+ cmd.append((char)0xA5);\r
+ cmd.append((char)0x6A);\r
+ cmd.append((char)0x0F);\r
+ \r
+ qint64 bytesWritten = m_rgb_serial->write(cmd);\r
+ if (bytesWritten == cmd.size()) {\r
+ qDebug() << tr("端口%1 RGB串口发送关闭LED指令成功").arg(m_port_index + 1);\r
+ } else {\r
+ qDebug() << tr("端口%1 RGB串口发送关闭LED指令失败").arg(m_port_index + 1);\r
+ }\r
+}\r
+\r
+void RgbSerialReader::sendSaveLedCommand()\r
+{\r
+ if (!m_rgb_serial || !m_rgb_serial->isOpen()) {\r
+ return;\r
+ }\r
+ \r
+ // 保存LED亮度设置指令: A5 CC 71\r
+ QByteArray cmd;\r
+ cmd.append((char)0xA5);\r
+ cmd.append((char)0xCC);\r
+ cmd.append((char)0x71);\r
+ \r
+ qint64 bytesWritten = m_rgb_serial->write(cmd);\r
+ if (bytesWritten == cmd.size()) {\r
+ qDebug() << tr("端口%1 RGB串口发送保存LED设置指令成功").arg(m_port_index + 1);\r
+ } else {\r
+ qDebug() << tr("端口%1 RGB串口发送保存LED设置指令失败").arg(m_port_index + 1);\r
+ }\r
+}\r
+\r
+void RgbSerialReader::sendQueryRgbcCommand()\r
+{\r
+ if (!m_rgb_serial || !m_rgb_serial->isOpen()) {\r
+ return;\r
+ }\r
+ \r
+ // 查询RGBC原始AD值指令: A5 51 F6\r
+ QByteArray cmd;\r
+ cmd.append((char)0xA5);\r
+ cmd.append((char)0x51);\r
+ cmd.append((char)0xF6);\r
+ \r
+ qint64 bytesWritten = m_rgb_serial->write(cmd);\r
+ if (bytesWritten == cmd.size()) {\r
+ qDebug() << tr("端口%1 RGB串口发送查询RGBC指令成功").arg(m_port_index + 1);\r
+ } else {\r
+ qDebug() << tr("端口%1 RGB串口发送查询RGBC指令失败").arg(m_port_index + 1);\r
+ }\r
+}\r
+\r
+bool RgbSerialReader::findRgbcFrame(const QByteArray& buffer, int& startPos, int& endPos)\r
+{\r
+ // 查找数据帧:5A 5A 15 XX ... (Byte2=0x15)\r
+ // 帧头:5A 5A\r
+ // Byte2: 0x15 (RGBC数据类型)\r
+ // Byte3: 数据长度(不包括帧头、Byte2和长度本身)\r
+ \r
+ startPos = -1;\r
+ endPos = -1;\r
+ \r
+ // 查找帧头 5A 5A,至少需要4个字节才能判断\r
+ for (int i = 0; i <= buffer.size() - 4; i++) {\r
+ if ((quint8)buffer[i] == 0x5A && (quint8)buffer[i + 1] == 0x5A) {\r
+ // 检查Byte2是否为0x15\r
+ if ((quint8)buffer[i + 2] == 0x15) {\r
+ // 获取数据长度(Byte3)\r
+ quint8 dataLength = (quint8)buffer[i + 3];\r
+ // 完整帧长度 = 帧头(2) + Byte2(1) + 长度(1) + 数据(dataLength) = 4 + dataLength\r
+ int frameLength = 4 + dataLength;\r
+ \r
+ // 检查是否有足够的数据\r
+ if (i + frameLength <= buffer.size()) {\r
+ startPos = i;\r
+ endPos = i + frameLength;\r
+ return true;\r
+ } else {\r
+ // 数据不完整,等待更多数据\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ return false;\r
+}\r
+\r
+void RgbSerialReader::parseRgbcData(const QByteArray& buffer)\r
+{\r
+ int startPos, endPos;\r
+ \r
+ // 查找所有完整的RGBC数据帧(Byte2=0x15)\r
+ // 注意:这里使用局部变量buffer,实际修改的是成员变量m_receive_buffer\r
+ QByteArray tempBuffer = buffer;\r
+ \r
+ while (findRgbcFrame(tempBuffer, startPos, endPos)) {\r
+ if (startPos >= 0 && endPos > startPos && endPos <= tempBuffer.size()) {\r
+ // 提取完整的数据帧\r
+ QByteArray frame = tempBuffer.mid(startPos, endPos - startPos);\r
+ \r
+ // 验证帧格式:5A 5A 15 XX [数据]\r
+ // 至少需要12字节:帧头(2) + Byte2(1) + 长度(1) + RGBC数据(8) = 12\r
+ if (frame.size() >= 12) {\r
+ // 解析RGBC数据\r
+ // 帧格式:5A 5A 15 08 R_H R_L G_H G_L B_H B_L C_H C_L ...\r
+ // 索引: 0 1 2 3 4 5 6 7 8 9 10 11\r
+ \r
+ // 提取RGBC数据(每个值2字节,高字节在前)\r
+ quint8 r_high = (quint8)frame[4];\r
+ quint8 r_low = (quint8)frame[5];\r
+ quint8 g_high = (quint8)frame[6];\r
+ quint8 g_low = (quint8)frame[7];\r
+ quint8 b_high = (quint8)frame[8];\r
+ quint8 b_low = (quint8)frame[9];\r
+ quint8 c_high = (quint8)frame[10];\r
+ quint8 c_low = (quint8)frame[11];\r
+ \r
+ // 计算RGBC值:高8位左移8位后与低8位或运算\r
+ quint16 red = ((quint16)r_high << 8) | r_low;\r
+ quint16 green = ((quint16)g_high << 8) | g_low;\r
+ quint16 blue = ((quint16)b_high << 8) | b_low;\r
+ quint16 clear = ((quint16)c_high << 8) | c_low;\r
+ \r
+ // 输出调试信息(包含原始十六进制数据)\r
+ QString hexFrame = frame.toHex(' ').toUpper();\r
+ qDebug() << tr("端口%1 RGB串口解析RGBC数据帧: %2").arg(m_port_index + 1).arg(hexFrame);\r
+ qDebug() << tr("端口%1 RGB串口RGBC值: R=%2, G=%3, B=%4, C=%5")\r
+ .arg(m_port_index + 1).arg(red).arg(green).arg(blue).arg(clear);\r
+ \r
+ // 发送解析后的RGBC数据信号\r
+ emit rgbcDataParsed(m_port_index, red, green, blue, clear);\r
+ }\r
+ \r
+ // 从临时缓冲区中移除已处理的数据帧,继续查找\r
+ tempBuffer.remove(startPos, endPos - startPos);\r
+ \r
+ // 同时从成员变量缓冲区中移除已处理的数据帧\r
+ m_receive_buffer.remove(startPos, endPos - startPos);\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+#ifndef RGB_SERIAL_READER_H\r
+#define RGB_SERIAL_READER_H\r
+\r
+#include <QObject>\r
+#include <QSerialPort>\r
+#include <QByteArray>\r
+#include <QString>\r
+\r
+// RGB串口读取器类 - 专门处理RGB串口的数据读取\r
+class RgbSerialReader : public QObject\r
+{\r
+ Q_OBJECT\r
+\r
+public:\r
+ explicit RgbSerialReader(int port_index, QObject *parent = nullptr);\r
+ ~RgbSerialReader();\r
+\r
+ // 端口索引 (0-3)\r
+ int portIndex() const { return m_port_index; }\r
+\r
+ // 串口对象访问\r
+ QSerialPort* serialPort() const { return m_rgb_serial; }\r
+\r
+ // 公共接口函数\r
+ void connectPort(const QString& com_name, int baud_rate);\r
+ void disconnectPort();\r
+ bool isConnected() const { return m_rgb_serial && m_rgb_serial->isOpen(); }\r
+ \r
+ // RGB传感器控制指令\r
+ void sendCloseLedCommand(); // 关闭LED指令: A5 6A 0F\r
+ void sendSaveLedCommand(); // 保存LED亮度设置: A5 CC 71\r
+ void sendQueryRgbcCommand(); // 查询RGBC原始AD值: A5 51 F6\r
+\r
+signals:\r
+ // 数据接收信号\r
+ void dataReceived(const QByteArray& data); // 接收到原始数据\r
+ void textReceived(const QString& text); // 接收到文本数据\r
+ void rgbDataReceived(int port_index, const QByteArray& data); // 带端口索引的数据信号\r
+ \r
+ // RGBC数据解析信号(当Byte2=0x15时)\r
+ void rgbcDataParsed(int port_index, quint16 red, quint16 green, quint16 blue, quint16 clear); // 解析后的RGBC数据\r
+ \r
+ // 状态信号\r
+ void connectionStatusChanged(bool connected); // 连接状态变化\r
+ void errorOccurred(const QString& error); // 错误信号\r
+\r
+private slots:\r
+ void onReadyRead(); // 串口数据就绪\r
+ void onError(QSerialPort::SerialPortError error); // 串口错误处理\r
+\r
+private:\r
+ // 端口索引 (0-3)\r
+ int m_port_index;\r
+\r
+ // 串口对象\r
+ QSerialPort *m_rgb_serial;\r
+\r
+ // 数据缓冲区(用于处理分包数据)\r
+ QByteArray m_receive_buffer;\r
+ \r
+ // 最大缓冲区大小(防止内存溢出)\r
+ static const int MAX_BUFFER_SIZE = 32768; // 32KB\r
+ \r
+ // 数据解析函数\r
+ void parseRgbcData(const QByteArray& data); // 解析RGBC数据(查找Byte2=0x15的数据包)\r
+ bool findRgbcFrame(const QByteArray& buffer, int& startPos, int& endPos); // 查找完整的RGBC数据帧\r
+};\r
+\r
+#endif // RGB_SERIAL_READER_H\r
+\r