#pragma once
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>
#include <QMutex>
#include <QThread>
#include <QtCore/qglobal.h>
#ifndef BUILD_STATIC
# if defined(BUSINESSMGR_LIB)
# define BUSINESSMGR_EXPORT Q_DECL_EXPORT
# else
# define BUSINESSMGR_EXPORT Q_DECL_IMPORT
# endif
#else
# define BUSINESSMGR_EXPORT
#endif
class BUSINESSMGR_EXPORT CSerialPort : public QObject
{
Q_OBJECT
public:
// 默认构造函数
CSerialPort() : m_serial(nullptr), m_icom(0), m_buffer(), m_mutex() {}
~CSerialPort();
//void run() override;
//CSerialPort(int icom, QObject* parent = nullptr);
//CSerialPort(const CSerialPort& other);
//CSerialPort& operator=(const CSerialPort& other);
bool init(int icom);
bool setIsOn(bool isOn);
bool getIsOn();
void ClosePort();
void ClosePort(int nName);
//bool SendData(QByteArray arry);
//bool DoReadSerial();
QByteArray PraseData(int len,char MsgCode);
QString GetPortName();
bool SendDataBySignal(QByteArray arry);
public slots:
void readData();
void SendData(QByteArray arry);
signals:
void sig_SendData(QByteArray data);
public:
QSerialPort* m_serial;
int m_icom;
QByteArray m_buffer; // 缓冲区用于存放未完整处理的数据
QMutex m_mutex;
QThread m_thread;
bool m_isOn = false;
};
#include "CSerialPort.h"
#define MAXBUFFERLEN 1024*4
//CSerialPort::CSerialPort(int icom, QObject* parent ) : QObject(parent), m_icom(icom), m_buffer(), m_mutex()
//{
//
// m_serial = new QSerialPort();
//
// if (m_serial)
// {
// m_serial->setPortName("COM" + QString::number(icom)); // 根据实际串口名称设置
// m_serial->setBaudRate(QSerialPort::Baud9600); // 波特率为9600
// m_serial->setDataBits(QSerialPort::Data8); // 8个数据位
// m_serial->setStopBits(QSerialPort::OneStop); // 1个停止位
// m_serial->setParity(QSerialPort::NoParity); // 无奇偶校验
// m_serial->setFlowControl(QSerialPort::NoFlowControl);
//
// connect(m_serial, &QSerialPort::readyRead, this, &CSerialPort::readData);
// }
//
//
//
//}
//
//CSerialPort::CSerialPort(const CSerialPort& other)
// : QObject(other.parent()), m_serial(other.m_serial), m_icom(other.m_icom),m_buffer(other.m_buffer), m_mutex()
//{
//
//}
//
//CSerialPort& CSerialPort::operator=(const CSerialPort& other)
//{
// if (this != &other)
// {
// // 复制其他成员变量
// m_serial = other.m_serial;
// m_buffer = other.m_buffer;
// m_icom = other.m_icom;
// }
// return *this;
//
//
// //if (this != &other)
// //{
// // // 删除原有的 QSerialPort 对象
// // delete m_serial;
// // // 深拷贝 QSerialPort 对象
// // m_serial = new QSerialPort(other.m_serial);
// // m_icom = other.m_icom;
// // m_buffer = other.m_buffer; // QByteArray 赋值运算符重载会进行深拷贝
// // // 不需要处理互斥量 m_mutex,因为它没有动态分配内存,直接使用默认构造函数即可
// //}
// //return *this;
//
//}
void CSerialPort::readData()
{
if (!m_serial)
return;
m_mutex.lock();
QByteArray responseData = m_serial->readAll();
m_buffer += responseData; // 将接收到的数据存入缓冲区
LOGINFO(("[COM%1]Recv:"+ QString(responseData)).arg(m_icom));
m_mutex.unlock();
}
CSerialPort::~CSerialPort()
{
if (m_serial)
{
m_serial->close();
delete m_serial;
m_serial = nullptr;
}
}
//void CSerialPort::run()
//{
// // 在子线程中循环读取串口数据
// while (!isInterruptionRequested())
// {
// //if (m_serial->waitForReadyRead(100))
// { // 等待串口数据
// if (!m_serial)
// return;
//
// if (!m_serial->isOpen())
// return;
//
// m_mutex.lock();
//
// QThread::msleep(500);
// QByteArray responseData;
// if (m_serial->bytesAvailable())//判断串口缓存区内部是否存在数据,存在数据再将数据读出来
// {
// responseData = m_serial->readAll();
// m_buffer += responseData; // 将接收到的数据存入缓冲区
// }
//
// LOGINFO(("[COM%1]Recv:" + QString(responseData)).arg(m_icom));
//
//
// m_mutex.unlock();
// }
// }
//}
bool CSerialPort::init(int icom)
{
m_serial = new QSerialPort();
m_icom = icom;
if (m_serial)
{
m_serial->setPortName("COM" + QString::number(icom)); // 根据实际串口名称设置
m_serial->setBaudRate(QSerialPort::Baud9600); // 波特率为9600
m_serial->setDataBits(QSerialPort::Data8); // 8个数据位
m_serial->setStopBits(QSerialPort::OneStop); // 1个停止位
m_serial->setParity(QSerialPort::NoParity); // 无奇偶校验
m_serial->setFlowControl(QSerialPort::NoFlowControl);
connect(m_serial, &QSerialPort::readyRead, this, &CSerialPort::readData,Qt::DirectConnection);
connect(this, &CSerialPort::sig_SendData, this, &CSerialPort::SendData);
this->moveToThread(&m_thread);
// 启动子线程
m_thread.start();
return true;
}
else
{
return false;
}
}
bool CSerialPort::setIsOn(bool isOn)
{
m_isOn = isOn;
return true;
}
bool CSerialPort::getIsOn()
{
return m_isOn;
}
void CSerialPort::ClosePort()
{
if (!m_serial)
return;
if (m_serial->isOpen())
{
m_serial->close();
if (m_serial->isOpen())
{
LOGINFO(tr("关闭软件时,close强固化串口失败!"));
}
}
else;
if (m_serial)
{
delete m_serial;
m_serial = nullptr;
}
}
void CSerialPort::ClosePort(int nName)
{
if (!m_serial)
return;
if (m_serial->isOpen())
{
m_serial->close();
if (m_serial->isOpen())
{
LOGINFO(tr("复位时,关闭串口COM%1失败!").arg(nName));
}
}
else;
if (m_serial)
{
delete m_serial;
m_serial = nullptr;
}
}
bool CSerialPort::SendDataBySignal(QByteArray arry)
{
emit sig_SendData(arry);
return true;
}
void CSerialPort::SendData(QByteArray arry)
{
qint64 bytesWritten = 0;
if (m_serial->isOpen())
{
bytesWritten = m_serial->write(arry);
if (bytesWritten != arry.size())
{
LOGINFO(tr("写入失败,[COM%1]写入数据时写入和实际数据不同").arg(m_icom));
//return false;
}
}
else
{
LOGINFO(tr("写入失败,[COM%1]写入数据时串口打开失败" ).arg(m_icom));
//return false;
}
//return true;
}
//bool CSerialPort::DoReadSerial()
//{
// while (true)
// {
// if (!m_serial)
// return;
//
// m_mutex.lock();
// QByteArray responseData = m_serial->readAll();
// m_buffer += responseData; // 将接收到的数据存入缓冲区
// LOGINFO(("[COM%1]Recv:" + QString(responseData)).arg(m_icom));
// m_mutex.unlock();
//
// QThread::msleep(100);
// }
//
// return false;
//}
QByteArray CSerialPort::PraseData(int len, char MsgCode)
{
//从数据包的末尾往前查找完整包,实时解析最新数据
QByteArray arr;//011000 010300
arr.append(char(0x01));
arr.append(MsgCode);
arr.append(char(0x00));
m_mutex.lock();
QByteArray packet;
int lastIndex = m_buffer.length() - 1; // 记录最后一个数据的索引
while (lastIndex >= 0 && m_buffer.length() >= len)
{
if (m_buffer.mid(lastIndex - len + 1, 3) == arr)
{
packet = m_buffer.mid(lastIndex - len + 1, len); // 获取符合条件的数据包
if (MsgCode == char(0x10))//写数据返回值
{
if (packet[4] != char(0x00) || packet[5] != char(0x04))
{
lastIndex--; // 索引减一,继续向前查找
continue;
}
else;
}
else if (MsgCode == char(0x03))//读数据返回值
{
if (packet[3] != char(0x0A))
{
lastIndex--; // 索引减一,继续向前查找
continue;
}
else;
}
else;
m_buffer = m_buffer.left(lastIndex - len + 1); // 删除已经读取的数据
break;
}
else
{
lastIndex--; // 索引减一,继续向前查找
}
}
//超多清空
if (m_buffer.length() > MAXBUFFERLEN)
{
m_buffer.clear();
}
else;
m_mutex.unlock();
return packet;
}
QString CSerialPort::GetPortName()
{
return m_serial->portName();
}
//调用
do
{
if (port && bconnect)
{
//先发送查询指令再解析返回数据
for (int i = 0; i < 1; i++)//4个通道,暂时读一个通道
{
//设备地址
requestData.append(char(0x01));
//功能码
requestData.append(char(0x03));
//寄存器起始地址CH1-CH4
requestData.append(char(0x00));
if (i == 0)
{
requestData.append(char(0x10));
}
else if (i == 1)
{
requestData.append(char(0x15));
}
else if (i == 2)
{
requestData.append(char(0x1A));
}
else if (i == 3)
{
requestData.append(char(0x20));
}
else;
//写寄存器个数
requestData.append(char(0x00));
requestData.append(char(0x05));
//crc校验
requestData += crc16(requestData);
m_SerialPortsArr[index].SendDataBySignal(requestData);
//等待返回数据,超时判断
ULONGLONG TimeOut = 5000; //5s
ULONGLONG nowTime = GetTickCount64();
bool issuccess = false;
while (true)
{
QByteArray arr_res = m_SerialPortsArr[index].PraseData(16, 0x03);
if (arr_res.size() == 16)//查询的返回结果
{
//查询结果
int ipower = (int)arr_res[7];
double dduration = 0.0;
QByteArray arr_duration;
arr_duration.append(arr_res[8]);
arr_duration.append(arr_res[9]);
QString hexString = arr_duration.toHex(); // 将 QByteArray 转换为十六进制字符串
bool ok;
int decimalValue = hexString.toInt(&ok, 16); // 将十六进制字符串转换为十进制数
if (ok)
{
dduration = (double)(decimalValue / 10.0);
powervalue = ipower;
duration = dduration;
issuccess = true;
break;
}
else
{
issuccess = false;
LOGERROR(m_SerialPortsArr[index].GetPortName() + "查询UV灯返回值数据时转换失败");
}
}
else;
if ((GetTickCount64() - nowTime) > TimeOut)
{
issuccess = false;
LOGERROR("查询串口" + m_SerialPortsArr[index].GetPortName() + "失败,超时");
break;
}
else;
QThread::msleep(1000);
}
if (issuccess == false)//有一个通道失败就退出
{
ReturnValue.m_bReturn = issuccess;
break;
}
else
{
ReturnValue.m_bReturn = issuccess;
}
}
}
else
{
LOGERROR(port->portName() + "未初始化并连接");
ReturnValue.m_bReturn = false;
}
} while (0);