299 lines
7.4 KiB
C++
299 lines
7.4 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 = [=](int type, QString data, QString enable) {
|
|
// 命令类型
|
|
QString t;
|
|
if (type == 2)
|
|
t = "02"; // 指示灯
|
|
else
|
|
t = "03"; // 使能
|
|
return QByteArray::fromHex(QString("A2 B2 08 %1 %2 %3 C2 D2")
|
|
.arg(t)
|
|
.arg(data)
|
|
.arg(enable)
|
|
.toLatin1());
|
|
};
|
|
|
|
cmdMap[PlaybackStart] = makeCommand(2, "01", "01");
|
|
cmdMap[PlaybackEnd] = makeCommand(2, "01", "00");
|
|
cmdMap[RecordStart] = makeCommand(2, "02", "01");
|
|
cmdMap[RecordEnd] = makeCommand(2, "02", "00");
|
|
cmdMap[PlayPause] = makeCommand(2, "03", "01");
|
|
cmdMap[PlayResume] = makeCommand(2, "03", "00");
|
|
cmdMap[DiskWillFull] = makeCommand(2, "04", "01");
|
|
cmdMap[DiskNotFull] = makeCommand(2, "04", "00");
|
|
cmdMap[PowerOn] = makeCommand(2, "05", "01");
|
|
cmdMap[PowerOff] = makeCommand(2, "05", "00");
|
|
cmdMap[Forward] = makeCommand(2, "08", "01");
|
|
cmdMap[LoopOn] = makeCommand(2, "07", "01");
|
|
cmdMap[LoopOff] = makeCommand(2, "07", "00");
|
|
cmdMap[Back] = makeCommand(2, "06", "01");
|
|
cmdMap[MainChannelOn] = makeCommand(2, "09", "01");
|
|
cmdMap[MainChannelOff] = makeCommand(2, "09", "00");
|
|
cmdMap[SecondaryChannelOn] = makeCommand(2, "0A", "01");
|
|
cmdMap[SecondaryChannelOff] = makeCommand(2, "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::error("reopen serial port: /dev/ttyAMA2 failed, ready to retry...");
|
|
timer->start();
|
|
} else {
|
|
Log::info("reopen serial port: /dev/ttyAMA2 success");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 读取并处理收到的串口指令
|
|
*/
|
|
void SerialPortTool::onReayRead()
|
|
{
|
|
// 当缓冲区中有大于8个字节的数据时才处理
|
|
if (serialPort->bytesAvailable() < 8)
|
|
return;
|
|
|
|
// 由于本项目串口的数据频率小,可以将全部读到的数据当做一条指令来解析
|
|
// 当发送数据频率很大时,可以使用另外的缓冲区来存储读到的数据,然后读取缓冲区的数据进行指令的解析
|
|
// 将缓冲区的数据全部读取出来
|
|
QByteArray data = serialPort->readAll();
|
|
qDebug() << "receive command:" << 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 btnMenuClicked();
|
|
break;
|
|
case 2:
|
|
// 上
|
|
emit btnUpClicked();
|
|
break;
|
|
case 3:
|
|
// 下
|
|
emit btnDownClicked();
|
|
break;
|
|
case 4:
|
|
// 左
|
|
emit btnLeftClicked();
|
|
break;
|
|
case 5:
|
|
// 右
|
|
emit btnRightClicked();
|
|
break;
|
|
case 6:
|
|
// 确认
|
|
emit btnConfirmClicked();
|
|
break;
|
|
case 7:
|
|
// 返回
|
|
emit btnReturnClicked();
|
|
break;
|
|
case 8:
|
|
emit btnVolumnUpClicked();
|
|
break;
|
|
case 9:
|
|
emit btnVolumnDownClicked();
|
|
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();
|
|
}
|
|
|