增加串口接收线程支持,重构串口数据处理逻辑
This commit is contained in:
parent
204b1653da
commit
ba586bf2ee
@ -142,6 +142,15 @@ win32 {
|
|||||||
LIBS += Advapi32.lib
|
LIBS += Advapi32.lib
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Default rules for deployment.
|
||||||
|
unix {
|
||||||
|
target.path = /usr/lib
|
||||||
|
# Link real-time library for POSIX shared memory functions
|
||||||
|
LIBS += -lrt
|
||||||
|
}
|
||||||
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
|
|
||||||
# Default rules for deployment.
|
# Default rules for deployment.
|
||||||
qnx: target.path = /tmp/$${TARGET}/bin
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
|
|||||||
@ -6,6 +6,12 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
#include "ProtocolCommon.h"
|
#include "ProtocolCommon.h"
|
||||||
|
|
||||||
#include <QSerialPort>
|
#include <QSerialPort>
|
||||||
@ -114,11 +120,36 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::string BuildDataProtocol(const MultiTargetData& multiTargetData, uint16_t cameraId);
|
std::string BuildDataProtocol(const MultiTargetData& multiTargetData, uint16_t cameraId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 阻塞式串口数据接收线程函数
|
||||||
|
*/
|
||||||
|
void SerialReceiveThreadFunction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 启动串口接收线程
|
||||||
|
*/
|
||||||
|
void StartReceiveThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止串口接收线程
|
||||||
|
*/
|
||||||
|
void StopReceiveThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 处理接收到的数据(线程安全)
|
||||||
|
*/
|
||||||
|
void ProcessReceivedData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSerialPort* m_pSerialPort; // 串口对象
|
QSerialPort* m_pSerialPort; // 串口对象
|
||||||
SerialStatus m_serialStatus; // 串口状态
|
SerialStatus m_serialStatus; // 串口状态
|
||||||
QString m_receiveBuffer; // 接收缓冲区
|
QString m_receiveBuffer; // 接收缓冲区
|
||||||
|
|
||||||
|
// 线程相关
|
||||||
|
std::thread m_receiveThread; // 接收线程
|
||||||
|
std::atomic<bool> m_threadRunning; // 线程运行标志
|
||||||
|
std::mutex m_bufferMutex; // 缓冲区互斥锁
|
||||||
|
|
||||||
// 回调函数
|
// 回调函数
|
||||||
ConnectionCallback m_connectionCallback; // 连接状态回调
|
ConnectionCallback m_connectionCallback; // 连接状态回调
|
||||||
WorkSignalCallback m_workSignalCallback; // 工作信号回调
|
WorkSignalCallback m_workSignalCallback; // 工作信号回调
|
||||||
|
|||||||
@ -228,7 +228,7 @@ int GrabBagPresenter::Init()
|
|||||||
m_pStatus->OnStatusUpdate("设备初始化完成");
|
m_pStatus->OnStatusUpdate("设备初始化完成");
|
||||||
|
|
||||||
CheckAndUpdateWorkStatus();
|
CheckAndUpdateWorkStatus();
|
||||||
|
#if 0
|
||||||
// 初始化配置管理器
|
// 初始化配置管理器
|
||||||
m_pConfigManager = std::make_unique<ConfigManager>();
|
m_pConfigManager = std::make_unique<ConfigManager>();
|
||||||
if (!m_pConfigManager->Initialize(configPath.toStdString())) {
|
if (!m_pConfigManager->Initialize(configPath.toStdString())) {
|
||||||
@ -239,7 +239,7 @@ int GrabBagPresenter::Init()
|
|||||||
|
|
||||||
// 注册为配置变化监听器
|
// 注册为配置变化监听器
|
||||||
m_pConfigManager->AddConfigChangeListener(std::shared_ptr<IConfigChangeListener>(this, [](IConfigChangeListener*){}));
|
m_pConfigManager->AddConfigChangeListener(std::shared_ptr<IConfigChangeListener>(this, [](IConfigChangeListener*){}));
|
||||||
|
#endif
|
||||||
m_pStatus->OnStatusUpdate("配置管理器初始化成功");
|
m_pStatus->OnStatusUpdate("配置管理器初始化成功");
|
||||||
LOG_INFO("ConfigManager initialized successfully\n");
|
LOG_INFO("ConfigManager initialized successfully\n");
|
||||||
|
|
||||||
@ -947,9 +947,8 @@ void GrabBagPresenter::_SendDetectionResultToRobot(const DetectionResult& detect
|
|||||||
if (m_pStatus) {
|
if (m_pStatus) {
|
||||||
m_pStatus->OnStatusUpdate("没有检测到目标,发送空的多目标数据");
|
m_pStatus->OnStatusUpdate("没有检测到目标,发送空的多目标数据");
|
||||||
}
|
}
|
||||||
return;
|
// 即使检测结果为0,也要发送空数据,所以不return,继续执行后面的发送逻辑
|
||||||
}
|
} else {
|
||||||
|
|
||||||
// 获取检测到的目标位置(已经是机械臂坐标系)
|
// 获取检测到的目标位置(已经是机械臂坐标系)
|
||||||
const auto& positions = detectionResult.positions;
|
const auto& positions = detectionResult.positions;
|
||||||
multiTargetData.count = static_cast<uint16_t>(positions.size());
|
multiTargetData.count = static_cast<uint16_t>(positions.size());
|
||||||
@ -968,6 +967,7 @@ void GrabBagPresenter::_SendDetectionResultToRobot(const DetectionResult& detect
|
|||||||
// 添加到多目标数据
|
// 添加到多目标数据
|
||||||
multiTargetData.targets.push_back(robotTarget);
|
multiTargetData.targets.push_back(robotTarget);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 发送到机械臂(网络ModbusTCP)
|
// 发送到机械臂(网络ModbusTCP)
|
||||||
bool robotSent = false;
|
bool robotSent = false;
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <QSerialPortInfo>
|
#include <QSerialPortInfo>
|
||||||
|
|
||||||
@ -19,16 +21,20 @@ const QString SerialProtocol::SEPARATOR = ",";
|
|||||||
SerialProtocol::SerialProtocol(QObject* parent)
|
SerialProtocol::SerialProtocol(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_serialStatus(STATUS_DISCONNECTED)
|
, m_serialStatus(STATUS_DISCONNECTED)
|
||||||
|
, m_threadRunning(false)
|
||||||
{
|
{
|
||||||
m_pSerialPort = new QSerialPort(this);
|
m_pSerialPort = new QSerialPort(this);
|
||||||
|
|
||||||
// 连接信号和槽
|
// 连接信号和槽(保留原有的信号槽机制作为备用)
|
||||||
connect(m_pSerialPort, &QSerialPort::readyRead, this, &SerialProtocol::OnSerialDataReceived);
|
connect(m_pSerialPort, &QSerialPort::readyRead, this, &SerialProtocol::OnSerialDataReceived);
|
||||||
connect(m_pSerialPort, &QSerialPort::errorOccurred, this, &SerialProtocol::OnSerialError);
|
connect(m_pSerialPort, &QSerialPort::errorOccurred, this, &SerialProtocol::OnSerialError);
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialProtocol::~SerialProtocol()
|
SerialProtocol::~SerialProtocol()
|
||||||
{
|
{
|
||||||
|
// 先停止接收线程
|
||||||
|
StopReceiveThread();
|
||||||
|
// 再关闭串口
|
||||||
CloseSerial();
|
CloseSerial();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +102,9 @@ int SerialProtocol::OpenSerial(const std::string& portName, int baudRate,
|
|||||||
m_serialStatus = STATUS_CONNECTED;
|
m_serialStatus = STATUS_CONNECTED;
|
||||||
LOG_INFO("Serial port opened successfully: %s\n", portName.c_str());
|
LOG_INFO("Serial port opened successfully: %s\n", portName.c_str());
|
||||||
|
|
||||||
|
// 启动接收线程
|
||||||
|
StartReceiveThread();
|
||||||
|
|
||||||
// 触发连接状态回调
|
// 触发连接状态回调
|
||||||
if (m_connectionCallback) {
|
if (m_connectionCallback) {
|
||||||
m_connectionCallback(true);
|
m_connectionCallback(true);
|
||||||
@ -108,6 +117,11 @@ void SerialProtocol::CloseSerial()
|
|||||||
{
|
{
|
||||||
if (m_pSerialPort && m_pSerialPort->isOpen()) {
|
if (m_pSerialPort && m_pSerialPort->isOpen()) {
|
||||||
LOG_INFO("Closing serial port: %s\n", m_pSerialPort->portName().toStdString().c_str());
|
LOG_INFO("Closing serial port: %s\n", m_pSerialPort->portName().toStdString().c_str());
|
||||||
|
|
||||||
|
// 先停止接收线程
|
||||||
|
StopReceiveThread();
|
||||||
|
|
||||||
|
// 再关闭串口
|
||||||
m_pSerialPort->close();
|
m_pSerialPort->close();
|
||||||
m_serialStatus = STATUS_DISCONNECTED;
|
m_serialStatus = STATUS_DISCONNECTED;
|
||||||
|
|
||||||
@ -163,29 +177,32 @@ bool SerialProtocol::IsOpen() const
|
|||||||
|
|
||||||
void SerialProtocol::OnSerialDataReceived()
|
void SerialProtocol::OnSerialDataReceived()
|
||||||
{
|
{
|
||||||
LOG_DEBUG("OnSerialDataReceived() called\n");
|
// 注意:这个方法现在主要作为Qt信号槽的备用机制
|
||||||
LOG_DEBUG("OnSerialDataReceived() called\n");
|
// 主要的数据接收由独立线程处理
|
||||||
LOG_DEBUG("OnSerialDataReceived() called\n");
|
LOG_DEBUG("[Signal] OnSerialDataReceived() called (backup mechanism)\n");
|
||||||
LOG_DEBUG("OnSerialDataReceived() called\n");
|
|
||||||
LOG_DEBUG("OnSerialDataReceived() called\n");
|
|
||||||
|
|
||||||
|
// 如果线程正在运行,优先使用线程处理
|
||||||
|
if (m_threadRunning.load()) {
|
||||||
|
LOG_DEBUG("[Signal] Thread is running, skipping signal-based processing\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_pSerialPort) {
|
if (!m_pSerialPort) {
|
||||||
LOG_ERROR("Serial port is null in OnSerialDataReceived\n");
|
LOG_ERROR("[Signal] Serial port is null in OnSerialDataReceived\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_pSerialPort->isOpen()) {
|
if (!m_pSerialPort->isOpen()) {
|
||||||
LOG_ERROR("Serial port is not open in OnSerialDataReceived\n");
|
LOG_ERROR("[Signal] Serial port is not open in OnSerialDataReceived\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查可用字节数
|
// 检查可用字节数
|
||||||
qint64 bytesAvailable = m_pSerialPort->bytesAvailable();
|
qint64 bytesAvailable = m_pSerialPort->bytesAvailable();
|
||||||
LOG_INFO("Bytes available to read: %lld\n", bytesAvailable);
|
LOG_INFO("[Signal] Bytes available to read: %lld\n", bytesAvailable);
|
||||||
|
|
||||||
if (bytesAvailable <= 0) {
|
if (bytesAvailable <= 0) {
|
||||||
LOG_WARNING("No bytes available but readyRead signal was triggered\n");
|
LOG_WARNING("[Signal] No bytes available but readyRead signal was triggered\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,18 +210,21 @@ void SerialProtocol::OnSerialDataReceived()
|
|||||||
QByteArray data = m_pSerialPort->readAll();
|
QByteArray data = m_pSerialPort->readAll();
|
||||||
QString receivedData = QString::fromUtf8(data);
|
QString receivedData = QString::fromUtf8(data);
|
||||||
|
|
||||||
LOG_INFO("Actually read %d bytes from serial port\n", data.size());
|
LOG_INFO("[Signal] Actually read %d bytes from serial port\n", data.size());
|
||||||
|
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
LOG_WARNING("readAll() returned empty data\n");
|
LOG_WARNING("[Signal] readAll() returned empty data\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加到接收缓冲区
|
// 使用互斥锁保护缓冲区
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_bufferMutex);
|
||||||
m_receiveBuffer += receivedData;
|
m_receiveBuffer += receivedData;
|
||||||
|
}
|
||||||
|
|
||||||
// 打印接收到的数据
|
// 打印接收到的数据
|
||||||
LOG_INFO("Received [%d bytes]: \"%s\"\n", data.size(), receivedData.toStdString().c_str());
|
LOG_INFO("[Signal] Received [%d bytes]: \"%s\"\n", data.size(), receivedData.toStdString().c_str());
|
||||||
|
|
||||||
// 如果包含不可打印字符,额外打印ASCII码
|
// 如果包含不可打印字符,额外打印ASCII码
|
||||||
bool hasNonPrintable = false;
|
bool hasNonPrintable = false;
|
||||||
@ -224,34 +244,11 @@ void SerialProtocol::OnSerialDataReceived()
|
|||||||
asciiInfo += QString("[%1] ").arg((unsigned char)c);
|
asciiInfo += QString("[%1] ").arg((unsigned char)c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_INFO("%s\n", asciiInfo.toStdString().c_str());
|
LOG_INFO("[Signal] %s\n", asciiInfo.toStdString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找完整的协议帧
|
// 处理接收到的数据
|
||||||
int startIndex = -1;
|
ProcessReceivedData();
|
||||||
int endIndex = -1;
|
|
||||||
|
|
||||||
while ((startIndex = m_receiveBuffer.indexOf(PROTOCOL_START)) != -1) {
|
|
||||||
endIndex = m_receiveBuffer.indexOf(PROTOCOL_END, startIndex);
|
|
||||||
if (endIndex != -1) {
|
|
||||||
// 提取完整的协议帧
|
|
||||||
QString protocolFrame = m_receiveBuffer.mid(startIndex, endIndex - startIndex + 1);
|
|
||||||
|
|
||||||
// 解析协议数据
|
|
||||||
ParseProtocolData(protocolFrame);
|
|
||||||
|
|
||||||
// 移除已处理的数据
|
|
||||||
m_receiveBuffer.remove(0, endIndex + 1);
|
|
||||||
} else {
|
|
||||||
// 没有找到结束标识,等待更多数据
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果缓冲区太大,清空一部分(防止内存溢出)
|
|
||||||
if (m_receiveBuffer.length() > 1024) {
|
|
||||||
m_receiveBuffer.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialProtocol::OnSerialError(QSerialPort::SerialPortError error)
|
void SerialProtocol::OnSerialError(QSerialPort::SerialPortError error)
|
||||||
@ -331,22 +328,32 @@ void SerialProtocol::ParseProtocolData(const QString& data)
|
|||||||
// 按分隔符分割数据
|
// 按分隔符分割数据
|
||||||
QStringList parts = cleanData.split(SEPARATOR);
|
QStringList parts = cleanData.split(SEPARATOR);
|
||||||
|
|
||||||
if (parts.isEmpty()) {
|
// 移除空的部分
|
||||||
LOG_WARNING("Empty protocol data received\n");
|
QStringList validParts;
|
||||||
|
for (const QString& part : parts) {
|
||||||
|
if (!part.isEmpty()) {
|
||||||
|
validParts.append(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (validParts.isEmpty()) {
|
||||||
|
LOG_WARNING("No valid parts found in protocol data\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString command = parts[0];
|
QString command = validParts[0];
|
||||||
|
LOG_DEBUG("Extracted command: '%s'\n", command.toStdString().c_str());
|
||||||
|
|
||||||
if (command == CMD_START) {
|
if (command == CMD_START) {
|
||||||
// 处理开始命令:$,START,#
|
// 处理开始命令:$,START,# 或 $,START,cameraId,#
|
||||||
LOG_INFO("Received START command\n");
|
LOG_INFO("Received START command\n");
|
||||||
|
|
||||||
// 默认相机ID为1,如果有更多参数可以解析
|
// 默认相机ID为1,如果有更多参数可以解析
|
||||||
int cameraId = 1;
|
int cameraId = 1;
|
||||||
if (parts.size() > 1) {
|
if (validParts.size() > 1) {
|
||||||
bool ok;
|
bool ok;
|
||||||
cameraId = parts[1].toInt(&ok);
|
cameraId = validParts[1].toInt(&ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
cameraId = 1;
|
cameraId = 1;
|
||||||
}
|
}
|
||||||
@ -355,8 +362,7 @@ void SerialProtocol::ParseProtocolData(const QString& data)
|
|||||||
// 触发工作信号回调
|
// 触发工作信号回调
|
||||||
if (m_workSignalCallback) {
|
if (m_workSignalCallback) {
|
||||||
bool result = m_workSignalCallback(true, cameraId);
|
bool result = m_workSignalCallback(true, cameraId);
|
||||||
LOG_INFO("Work signal callback result: %s, camera ID: %d\n",
|
LOG_INFO("Work signal callback result: %s, camera ID: %d\n", result ? "success" : "failed", cameraId);
|
||||||
result ? "success" : "failed", cameraId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_serialStatus = STATUS_WORKING;
|
m_serialStatus = STATUS_WORKING;
|
||||||
@ -400,11 +406,6 @@ int SerialProtocol::SendData(const std::string& data)
|
|||||||
// 立即刷新缓冲区
|
// 立即刷新缓冲区
|
||||||
m_pSerialPort->flush();
|
m_pSerialPort->flush();
|
||||||
|
|
||||||
// 等待数据发送完成
|
|
||||||
if (!m_pSerialPort->waitForBytesWritten(3000)) {
|
|
||||||
LOG_ERROR("Timeout waiting for data to be written\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("Sent %lld bytes to serial port\n", bytesWritten);
|
LOG_DEBUG("Sent %lld bytes to serial port\n", bytesWritten);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@ -432,3 +433,118 @@ std::string SerialProtocol::BuildDataProtocol(const MultiTargetData& multiTarget
|
|||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 线程方法实现
|
||||||
|
void SerialProtocol::StartReceiveThread()
|
||||||
|
{
|
||||||
|
if (m_threadRunning.load()) {
|
||||||
|
LOG_WARNING("Receive thread is already running\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Starting serial receive thread\n");
|
||||||
|
m_threadRunning.store(true);
|
||||||
|
|
||||||
|
// 启动接收线程
|
||||||
|
m_receiveThread = std::thread(&SerialProtocol::SerialReceiveThreadFunction, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialProtocol::StopReceiveThread()
|
||||||
|
{
|
||||||
|
if (!m_threadRunning.load()) {
|
||||||
|
LOG_DEBUG("Receive thread is not running\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Stopping serial receive thread\n");
|
||||||
|
m_threadRunning.store(false);
|
||||||
|
|
||||||
|
// 等待线程结束
|
||||||
|
if (m_receiveThread.joinable()) {
|
||||||
|
m_receiveThread.join();
|
||||||
|
LOG_INFO("Serial receive thread stopped\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialProtocol::SerialReceiveThreadFunction()
|
||||||
|
{
|
||||||
|
LOG_INFO("Serial receive thread started\n");
|
||||||
|
|
||||||
|
while (m_threadRunning.load()) {
|
||||||
|
// 检查串口是否打开
|
||||||
|
if (!m_pSerialPort || !m_pSerialPort->isOpen()) {
|
||||||
|
// 串口未打开,短暂休眠后继续检查
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 使用waitForReadyRead进行阻塞式等待,超时时间100ms
|
||||||
|
if (m_pSerialPort->waitForReadyRead(100)) {
|
||||||
|
// 有数据可读
|
||||||
|
qint64 bytesAvailable = m_pSerialPort->bytesAvailable();
|
||||||
|
if (bytesAvailable > 0) {
|
||||||
|
LOG_INFO("[Thread] Bytes available to read: %lld\n", bytesAvailable);
|
||||||
|
|
||||||
|
// 读取所有可用数据
|
||||||
|
QByteArray data = m_pSerialPort->readAll();
|
||||||
|
if (!data.isEmpty()) {
|
||||||
|
QString receivedData = QString::fromUtf8(data);
|
||||||
|
|
||||||
|
LOG_INFO("[Thread] Actually read %d bytes from serial port\n", data.size());
|
||||||
|
LOG_INFO("[Thread] Received [%d bytes]: \"%s\"\n", data.size(), receivedData.toStdString().c_str());
|
||||||
|
|
||||||
|
// 使用互斥锁保护缓冲区
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_bufferMutex);
|
||||||
|
m_receiveBuffer += receivedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理接收到的数据
|
||||||
|
ProcessReceivedData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG_ERROR("[Thread] Exception in receive thread: %s\n", e.what());
|
||||||
|
} catch (...) {
|
||||||
|
LOG_ERROR("[Thread] Unknown exception in receive thread\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Serial receive thread finished\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialProtocol::ProcessReceivedData()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_bufferMutex);
|
||||||
|
|
||||||
|
// 查找完整的协议帧
|
||||||
|
int startIndex = -1;
|
||||||
|
int endIndex = -1;
|
||||||
|
|
||||||
|
while ((startIndex = m_receiveBuffer.indexOf(PROTOCOL_START)) != -1) {
|
||||||
|
endIndex = m_receiveBuffer.indexOf(PROTOCOL_END, startIndex);
|
||||||
|
if (endIndex != -1) {
|
||||||
|
// 提取完整的协议帧
|
||||||
|
QString protocolFrame = m_receiveBuffer.mid(startIndex, endIndex - startIndex + 1);
|
||||||
|
|
||||||
|
LOG_INFO("[Thread] Found complete protocol frame: %s\n", protocolFrame.toStdString().c_str());
|
||||||
|
|
||||||
|
// 解析协议数据
|
||||||
|
ParseProtocolData(protocolFrame);
|
||||||
|
|
||||||
|
// 移除已处理的数据
|
||||||
|
m_receiveBuffer.remove(0, endIndex + 1);
|
||||||
|
} else {
|
||||||
|
// 没有找到结束标识,等待更多数据
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果缓冲区太大,清空一部分(防止内存溢出)
|
||||||
|
if (m_receiveBuffer.length() > 1024) {
|
||||||
|
LOG_WARNING("[Thread] Receive buffer too large (%d bytes), clearing\n", m_receiveBuffer.length());
|
||||||
|
m_receiveBuffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#define GRABBAG_VERSION_STRING "1.0.1"
|
#define GRABBAG_VERSION_STRING "1.0.1"
|
||||||
#define GRABBAG_BUILD_STRING "1"
|
#define GRABBAG_BUILD_STRING "3"
|
||||||
#define GRABBAG_FULL_VERSION_STRING "V1.0.1_1"
|
#define GRABBAG_FULL_VERSION_STRING "V1.0.1_3"
|
||||||
|
|
||||||
// 获取版本信息的便捷函数
|
// 获取版本信息的便捷函数
|
||||||
inline const char* GetGrabBagVersion() {
|
inline const char* GetGrabBagVersion() {
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
# 1.0.1
|
|
||||||
```
|
|
||||||
1. 增加串口通信
|
|
||||||
```
|
|
||||||
# 1.0.0
|
|
||||||
```
|
|
||||||
初始版本
|
|
||||||
```
|
|
||||||
@ -1,3 +1,7 @@
|
|||||||
|
# 1.0.1 2025-07-14
|
||||||
|
1. 增加串口通信
|
||||||
|
|
||||||
|
|
||||||
# 1.0.0.7 2025-06-29
|
# 1.0.0.7 2025-06-29
|
||||||
1. 增加双相机界面: 通过配置文件config.xml 配置双相机参数,如果没有没有配置,搜索相机进行打开
|
1. 增加双相机界面: 通过配置文件config.xml 配置双相机参数,如果没有没有配置,搜索相机进行打开
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
* @brief 共享内存接口类
|
* @brief 共享内存接口类
|
||||||
* 提供跨平台的共享内存创建、映射、读写操作
|
* 提供跨平台的共享内存创建、映射、读写操作
|
||||||
*/
|
*/
|
||||||
class VRSHAREMEM_EXPORT IVrShareMem
|
class IVrShareMem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IVrShareMem() = default;
|
virtual ~IVrShareMem() = default;
|
||||||
@ -94,12 +94,12 @@ public:
|
|||||||
* @brief 创建共享内存实例
|
* @brief 创建共享内存实例
|
||||||
* @return 共享内存实例指针
|
* @return 共享内存实例指针
|
||||||
*/
|
*/
|
||||||
VRSHAREMEM_EXPORT IVrShareMem* CreateShareMemInstance();
|
IVrShareMem* CreateShareMemInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 销毁共享内存实例
|
* @brief 销毁共享内存实例
|
||||||
* @param instance 实例指针
|
* @param instance 实例指针
|
||||||
*/
|
*/
|
||||||
VRSHAREMEM_EXPORT void DestroyShareMemInstance(IVrShareMem* instance);
|
void DestroyShareMemInstance(IVrShareMem* instance);
|
||||||
|
|
||||||
#endif // IVRSHAREMEM_H
|
#endif // IVRSHAREMEM_H
|
||||||
@ -1,6 +1,7 @@
|
|||||||
#CONFIG -= qt
|
#CONFIG -= qt
|
||||||
|
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
|
CONFIG += staticlib
|
||||||
DEFINES += VRSHAREMEM_LIBRARY
|
DEFINES += VRSHAREMEM_LIBRARY
|
||||||
|
|
||||||
CONFIG += c++11
|
CONFIG += c++11
|
||||||
|
|||||||
@ -300,12 +300,12 @@ bool VrShareMem::CheckBounds(size_t offset, size_t size) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 导出函数实现
|
// 导出函数实现
|
||||||
VRSHAREMEM_EXPORT IVrShareMem* CreateShareMemInstance()
|
IVrShareMem* CreateShareMemInstance()
|
||||||
{
|
{
|
||||||
return new VrShareMem();
|
return new VrShareMem();
|
||||||
}
|
}
|
||||||
|
|
||||||
VRSHAREMEM_EXPORT void DestroyShareMemInstance(IVrShareMem* instance)
|
void DestroyShareMemInstance(IVrShareMem* instance)
|
||||||
{
|
{
|
||||||
delete instance;
|
delete instance;
|
||||||
}
|
}
|
||||||
@ -17,7 +17,11 @@ struct DeviceInfo
|
|||||||
*/
|
*/
|
||||||
struct SerialConfig
|
struct SerialConfig
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
std::string portName = "COM8"; // 串口名称
|
||||||
|
#else
|
||||||
std::string portName = "/dev/ttyS3"; // 串口名称
|
std::string portName = "/dev/ttyS3"; // 串口名称
|
||||||
|
#endif
|
||||||
int baudRate = 115200; // 波特率
|
int baudRate = 115200; // 波特率
|
||||||
int dataBits = 8; // 数据位
|
int dataBits = 8; // 数据位
|
||||||
int stopBits = 1; // 停止位
|
int stopBits = 1; // 停止位
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user