276 lines
6.9 KiB
C++
276 lines
6.9 KiB
C++
|
#include "SerialPortTool.h"
|
||
|
#include "Log.h"
|
||
|
|
||
|
SerialPortTool::SerialPortTool(QObject* parent)
|
||
|
: QObject(parent)
|
||
|
{
|
||
|
|
||
|
serialPort = new QSerialPort();
|
||
|
connect(serialPort, SIGNAL(readyRead()), this, SLOT(onReayRead()));
|
||
|
connect(serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onSerialError(QSerialPort::SerialPortError)));
|
||
|
|
||
|
timer = new QTimer();
|
||
|
timer->setInterval(3000);
|
||
|
timer->stop();
|
||
|
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||
|
|
||
|
auto makeCommand = [=](QString lightNum, QString enable) {
|
||
|
return QByteArray::fromHex(QString("A2 B2 08 02 %1 %2 C2 D2").arg(lightNum).arg(enable).toLatin1());
|
||
|
};
|
||
|
|
||
|
cmdMap[PlaybackStart] = makeCommand("01", "01");
|
||
|
cmdMap[PlaybackEnd] = makeCommand("01", "00");
|
||
|
cmdMap[RecordStart] = makeCommand("02", "01");
|
||
|
cmdMap[RecordEnd] = makeCommand("02", "00");
|
||
|
cmdMap[PlayPause] = makeCommand("03", "01");
|
||
|
cmdMap[PlayResume] = makeCommand("03", "00");
|
||
|
cmdMap[DiskWillFull] = makeCommand("04", "01");
|
||
|
cmdMap[DiskNotFull] = makeCommand("04", "00");
|
||
|
cmdMap[PowerOn] = makeCommand("05", "01");
|
||
|
cmdMap[PowerOff] = makeCommand("05", "00");
|
||
|
cmdMap[Forward] = makeCommand("06", "01");
|
||
|
cmdMap[LoopOn] = makeCommand("07", "01");
|
||
|
cmdMap[LoopOff] = makeCommand("07", "00");
|
||
|
cmdMap[Back] = makeCommand("08", "01");
|
||
|
cmdMap[MainChannelOn] = makeCommand("09", "01");
|
||
|
cmdMap[MainChannelOff] = makeCommand("09", "00");
|
||
|
cmdMap[SecondaryChannelOn] = makeCommand("0A", "01");
|
||
|
cmdMap[SecondaryChannelOff] = makeCommand("0A", "00");
|
||
|
}
|
||
|
|
||
|
SerialPortTool::~SerialPortTool()
|
||
|
{
|
||
|
serialPort->close();
|
||
|
delete serialPort;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 打开串口
|
||
|
*/
|
||
|
void SerialPortTool::open()
|
||
|
{
|
||
|
serialPort->setPortName("ttyAMA2");
|
||
|
serialPort->setBaudRate(QSerialPort::Baud115200);
|
||
|
serialPort->setDataBits(QSerialPort::Data8);
|
||
|
serialPort->setParity(QSerialPort::NoParity);
|
||
|
serialPort->setStopBits(QSerialPort::OneStop);
|
||
|
serialPort->setFlowControl(QSerialPort::NoFlowControl);
|
||
|
if (serialPort->open(QIODevice::ReadWrite)) {
|
||
|
Log::info("open serial port: /dev/ttyAMA2 success");
|
||
|
} else {
|
||
|
Log::error("open serial port: /dev/ttyAMA2 failed, ready to retry...");
|
||
|
timer->start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 关闭串口
|
||
|
*/
|
||
|
void SerialPortTool::close()
|
||
|
{
|
||
|
serialPort->close();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 串口报错槽函数
|
||
|
*/
|
||
|
void SerialPortTool::onSerialError(QSerialPort::SerialPortError error)
|
||
|
{
|
||
|
if (error == QSerialPort::ResourceError) {
|
||
|
Log::error("serial port break, try to reopen");
|
||
|
serialPort->close();
|
||
|
timer->start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 重连串口
|
||
|
*/
|
||
|
void SerialPortTool::onTimeout()
|
||
|
{
|
||
|
timer->stop();
|
||
|
bool ret = serialPort->open(QIODevice::ReadWrite);
|
||
|
if (!ret) {
|
||
|
Log::info("reopen serial port: /dev/ttyAMA2 success");
|
||
|
timer->start();
|
||
|
} else {
|
||
|
Log::error("reopen serial port: /dev/ttyAMA2 failed, ready to retry...");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 读取并处理收到的串口指令
|
||
|
*/
|
||
|
void SerialPortTool::onReayRead()
|
||
|
{
|
||
|
// 当缓冲区中有大于8个字节的数据时才处理
|
||
|
if (serialPort->bytesAvailable() < 8)
|
||
|
return;
|
||
|
|
||
|
// 由于本项目串口的数据频率小,可以将全部读到的数据当做一条指令来解析
|
||
|
// 当发送数据频率很大时,可以使用另外的缓冲区来存储读到的数据,然后读取缓冲区的数据进行指令的解析
|
||
|
// 将缓冲区的数据全部读取出来
|
||
|
QByteArray data = serialPort->readAll();
|
||
|
qDebug() << "data:" << data;
|
||
|
// 对接受的数据进行协议解析
|
||
|
|
||
|
// 查找包头和包尾
|
||
|
QByteArray head = QByteArray::fromHex("A2 B2");
|
||
|
QByteArray tail = QByteArray::fromHex("C2 D2");
|
||
|
//... 0xA2 0xB2 0x08 0x01 0x01 0x00 0xC2 0xD2 ...
|
||
|
// || ||
|
||
|
// indexHead indexTail
|
||
|
int indexHead = data.indexOf(head);
|
||
|
int indexTail = data.indexOf(tail);
|
||
|
// 没有查找到包头和包尾
|
||
|
if (indexHead == -1 || indexTail == -1)
|
||
|
return;
|
||
|
|
||
|
// 从接收的数据中截取出一帧数据
|
||
|
QByteArray frame = data.mid(indexHead, indexTail + 2 - indexHead);
|
||
|
if (frame.length() <= 4)
|
||
|
return;
|
||
|
// 对一帧数据进行校验
|
||
|
// 长度校验不通过
|
||
|
if (frame[2] != frame.length())
|
||
|
return;
|
||
|
// 命令类型
|
||
|
if (data.at(3) != 0x01)
|
||
|
return;
|
||
|
|
||
|
switch (frame[4]) {
|
||
|
case 1:
|
||
|
emit btnPlaybackClicked();
|
||
|
break;
|
||
|
case 2:
|
||
|
emit btnPreviousClicked();
|
||
|
break;
|
||
|
case 3:
|
||
|
emit btnPauseClicked();
|
||
|
break;
|
||
|
case 4:
|
||
|
emit btnReturnClicked();
|
||
|
break;
|
||
|
case 5:
|
||
|
emit btnBackClicked();
|
||
|
break;
|
||
|
case 6:
|
||
|
emit btnNextClicked();
|
||
|
break;
|
||
|
case 7:
|
||
|
emit btnForwardClicked();
|
||
|
break;
|
||
|
case 8:
|
||
|
emit btnDoneClicked();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onPlaybackStart()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(PlaybackStart));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onPlaybackEnd()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(PlaybackEnd));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onRecordStart()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(RecordStart));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onRecordEnd()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(RecordEnd));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onPlayPause()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(PlayPause));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onPlayResume()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(PlayResume));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onDiskWillFull()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(DiskWillFull));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onDiskNotFull()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(DiskNotFull));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
void SerialPortTool::onPowerOn()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(PowerOn));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
void SerialPortTool::onPowerOff()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(PowerOff));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onFoward()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(Forward));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onBack()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(Back));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onLoopOn()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(LoopOn));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onLoopOff()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(LoopOff));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onMainChannelOn()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(MainChannelOn));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onMainChannelOff()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(MainChannelOff));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onSecondaryChannelOn()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(SecondaryChannelOn));
|
||
|
serialPort->flush();
|
||
|
}
|
||
|
|
||
|
void SerialPortTool::onSecondaryChannelOff()
|
||
|
{
|
||
|
serialPort->write(cmdMap.value(SecondaryChannelOff));
|
||
|
serialPort->flush();
|
||
|
}
|