RecordControlApplication/SerialPortTool.cpp

329 lines
8.5 KiB
C++
Raw Normal View History

#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[Reset] = makeCommand(2, "00", "00");
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");
cmdMap[MainChannelHDMI] = makeCommand(3, "03", "00");
cmdMap[MainChannelVGA] = makeCommand(3, "03", "01");
cmdMap[SecondaryChannelHDMI] = makeCommand(3, "04", "00");
cmdMap[SecondaryChanneVGA] = makeCommand(3, "04", "01");
}
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) {
2024-08-12 11:26:42 +08:00
Log::error("reopen serial port: /dev/ttyAMA2 failed, ready to retry...");
timer->start();
} else {
2024-08-12 11:26:42 +08:00
Log::info("reopen serial port: /dev/ttyAMA2 success");
}
}
/**
* @brief
*/
void SerialPortTool::onReayRead()
{
// 当缓冲区中有大于8个字节的数据时才处理
if (serialPort->bytesAvailable() < 8)
return;
// 由于本项目串口的数据频率小,可以将全部读到的数据当做一条指令来解析
// 当发送数据频率很大时,可以使用另外的缓冲区来存储读到的数据,然后读取缓冲区的数据进行指令的解析
// 将缓冲区的数据全部读取出来
QByteArray data = serialPort->readAll();
2024-08-12 11:26:42 +08:00
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:
2024-08-12 11:26:42 +08:00
// 菜单
emit btnMenuClicked();
break;
case 2:
2024-08-12 11:26:42 +08:00
// 上
emit btnUpClicked();
break;
case 3:
2024-08-12 11:26:42 +08:00
// 下
emit btnDownClicked();
break;
case 4:
2024-08-12 11:26:42 +08:00
// 左
emit btnLeftClicked();
break;
case 5:
2024-08-12 11:26:42 +08:00
// 右
emit btnRightClicked();
break;
case 6:
2024-08-12 11:26:42 +08:00
// 确认
emit btnConfirmClicked();
break;
case 7:
2024-08-12 11:26:42 +08:00
// 返回
emit btnReturnClicked();
break;
default:
break;
}
}
void SerialPortTool::onReset()
{
serialPort->write(cmdMap.value(Reset));
serialPort->flush();
}
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();
}
void SerialPortTool::onMainChannelHDMI()
{
2024-08-12 11:26:42 +08:00
qDebug() << "main channel hdmi:" << cmdMap.value(MainChannelHDMI);
serialPort->write(cmdMap.value(MainChannelHDMI));
serialPort->flush();
}
void SerialPortTool::onMainChannelVGA()
{
2024-08-12 11:26:42 +08:00
qDebug() << "main channel vga:" << cmdMap.value(MainChannelVGA);
serialPort->write(cmdMap.value(MainChannelVGA));
serialPort->flush();
}
void SerialPortTool::onSecondaryChannelHDMI()
{
2024-08-12 11:26:42 +08:00
qDebug() << "secondary channel hdmi:" << cmdMap.value(SecondaryChannelHDMI);
serialPort->write(cmdMap.value(SecondaryChannelHDMI));
serialPort->flush();
}
void SerialPortTool::onSecondaryChannelVGA()
{
2024-08-12 11:26:42 +08:00
qDebug() << "secondary channel vga:" << cmdMap.value(SecondaryChanneVGA);
serialPort->write(cmdMap.value(SecondaryChanneVGA));
serialPort->flush();
}