|
|
@@ -1,319 +1,392 @@
|
|
|
#include "serial_manager.h"
|
|
|
+#include <QDebug>
|
|
|
+#include <QDateTime>
|
|
|
+#include <QJsonDocument>
|
|
|
#include <QJsonArray>
|
|
|
#include <QJsonObject>
|
|
|
-#include <QJsonDocument>
|
|
|
-#include <QDateTime>
|
|
|
-#include <QDebug>
|
|
|
|
|
|
-// SerialManager 类管理串口的发现、打开、关闭和数据读写
|
|
|
-SerialManager::SerialManager(QObject *parent) : QObject(parent)
|
|
|
+SerialManager::SerialManager(SoftBusCore *busCore, QObject *parent)
|
|
|
+ : QObject(parent),
|
|
|
+ m_busCore(busCore),
|
|
|
+ m_discoveryTimer(new QTimer(this)),
|
|
|
+ m_serialConfig()
|
|
|
{
|
|
|
- m_discoveryTimer = new QTimer(this);
|
|
|
+ // 连接定时器信号
|
|
|
connect(m_discoveryTimer, &QTimer::timeout, this, &SerialManager::discoverSerialPorts);
|
|
|
-
|
|
|
- // 初始化串口配置
|
|
|
- m_serialConfig.baudRate = QSerialPort::Baud9600;
|
|
|
- m_serialConfig.dataBits = QSerialPort::Data8;
|
|
|
- m_serialConfig.parity = QSerialPort::NoParity;
|
|
|
- m_serialConfig.stopBits = QSerialPort::OneStop;
|
|
|
- m_serialConfig.flowControl = QSerialPort::NoFlowControl;
|
|
|
}
|
|
|
|
|
|
SerialManager::~SerialManager()
|
|
|
{
|
|
|
+ stopDiscovery();
|
|
|
closeAllPorts();
|
|
|
}
|
|
|
|
|
|
-// 启动串口发现定时器,并立即尝试发现一次串口
|
|
|
void SerialManager::startDiscovery(int intervalMs)
|
|
|
{
|
|
|
- m_discoveryTimer->start(intervalMs);
|
|
|
- discoverSerialPorts(); // 立即执行一次发现
|
|
|
+ // 立即执行一次发现
|
|
|
+ discoverSerialPorts();
|
|
|
+
|
|
|
+ // 启动定时器
|
|
|
+ if (intervalMs > 0)
|
|
|
+ {
|
|
|
+ m_discoveryTimer->start(intervalMs);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-// 停止串口发现定时器
|
|
|
void SerialManager::stopDiscovery()
|
|
|
{
|
|
|
m_discoveryTimer->stop();
|
|
|
}
|
|
|
|
|
|
-// 发现可用的串口,并处理新发现的和已移除的串口
|
|
|
-void SerialManager::discoverSerialPorts()
|
|
|
-{
|
|
|
- QList<QSerialPortInfo> availablePorts = QSerialPortInfo::availablePorts();
|
|
|
- QSet<QString> currentPorts;
|
|
|
-
|
|
|
- // 检查新端口
|
|
|
- for (const QSerialPortInfo &portInfo : availablePorts) {
|
|
|
- QString portName = portInfo.portName();
|
|
|
- currentPorts.insert(portName);
|
|
|
-
|
|
|
- if (!m_openedPorts.contains(portName)) {
|
|
|
- // 尝试打开新端口
|
|
|
- if (openSerialPort(portInfo)) {
|
|
|
- emit portDiscovered(portName, portInfo.description());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 检查已关闭的端口
|
|
|
- QSet<QString> removedPorts = m_openedPorts - currentPorts;
|
|
|
- for (const QString &portName : removedPorts) {
|
|
|
- closeSerialPort(portName);
|
|
|
- emit portRemoved(portName);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 根据提供的串口信息打开串口
|
|
|
bool SerialManager::openSerialPort(const QSerialPortInfo &portInfo)
|
|
|
{
|
|
|
- QString portName = portInfo.portName();
|
|
|
-
|
|
|
- if (m_openedPorts.contains(portName)) {
|
|
|
- return true; // 已经打开
|
|
|
+ // 如果端口已经打开,直接返回成功
|
|
|
+ if (m_serialPorts.contains(portInfo.portName()))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- QSerialPort *serialPort = new QSerialPort(this);
|
|
|
- serialPort->setPort(portInfo);
|
|
|
+ // 创建新的串口对象
|
|
|
+ QSerialPort *serialPort = new QSerialPort(portInfo, this);
|
|
|
+
|
|
|
+ // 应用配置
|
|
|
serialPort->setBaudRate(m_serialConfig.baudRate);
|
|
|
serialPort->setDataBits(m_serialConfig.dataBits);
|
|
|
serialPort->setParity(m_serialConfig.parity);
|
|
|
serialPort->setStopBits(m_serialConfig.stopBits);
|
|
|
serialPort->setFlowControl(m_serialConfig.flowControl);
|
|
|
|
|
|
- if (serialPort->open(QIODevice::ReadWrite)) {
|
|
|
- m_openedPorts.insert(portName);
|
|
|
- m_serialPorts[portName] = serialPort;
|
|
|
+ // 尝试打开串口
|
|
|
+ if (serialPort->open(QIODevice::ReadWrite))
|
|
|
+ {
|
|
|
+ // 添加到管理列表
|
|
|
+ m_serialPorts.insert(portInfo.portName(), serialPort);
|
|
|
+ m_openedPorts.insert(portInfo.portName());
|
|
|
|
|
|
- connect(serialPort, &QSerialPort::readyRead, this, [this, portName]() {
|
|
|
- onDataReceived(portName);
|
|
|
- });
|
|
|
-
|
|
|
- connect(serialPort, &QSerialPort::errorOccurred, this, [this, portName](QSerialPort::SerialPortError error) {
|
|
|
- if (error != QSerialPort::NoError) {
|
|
|
- qWarning() << "Serial port error:" << portName << error;
|
|
|
- closeSerialPort(portName);
|
|
|
- }
|
|
|
- });
|
|
|
+ // 连接数据接收信号
|
|
|
+ connect(serialPort, &QSerialPort::readyRead, this, [this, portInfo]()
|
|
|
+ { onReadyRead(portInfo.portName()); });
|
|
|
|
|
|
+ qDebug() << "Opened serial port:" << portInfo.portName();
|
|
|
return true;
|
|
|
- } else {
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 打开失败,清理资源
|
|
|
+ qWarning() << "Failed to open port" << portInfo.portName() << ":" << serialPort->errorString();
|
|
|
delete serialPort;
|
|
|
- qWarning() << "Failed to open serial port:" << portName << serialPort->errorString();
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 关闭并删除指定名称的串口
|
|
|
void SerialManager::closeSerialPort(const QString &portName)
|
|
|
{
|
|
|
- if (m_serialPorts.contains(portName)) {
|
|
|
- QSerialPort *serialPort = m_serialPorts.take(portName);
|
|
|
- serialPort->close();
|
|
|
- serialPort->deleteLater();
|
|
|
+ if (m_serialPorts.contains(portName))
|
|
|
+ {
|
|
|
+ QSerialPort *port = m_serialPorts.take(portName);
|
|
|
+ port->close();
|
|
|
+ delete port;
|
|
|
m_openedPorts.remove(portName);
|
|
|
+ emit portRemoved(portName);
|
|
|
+ qDebug() << "Closed serial port:" << portName;
|
|
|
}
|
|
|
}
|
|
|
+bool SerialManager::isPortOpen(const QString &portName)
|
|
|
+{
|
|
|
+ return m_serialPorts.contains(portName) && m_serialPorts[portName]->isOpen();
|
|
|
+}
|
|
|
|
|
|
-// 关闭并删除所有已打开的串口
|
|
|
void SerialManager::closeAllPorts()
|
|
|
{
|
|
|
- for (QSerialPort *serialPort : m_serialPorts) {
|
|
|
- serialPort->close();
|
|
|
- serialPort->deleteLater();
|
|
|
+ for (QSerialPort *port : m_serialPorts.values())
|
|
|
+ {
|
|
|
+ port->close();
|
|
|
+ delete port;
|
|
|
}
|
|
|
m_serialPorts.clear();
|
|
|
m_openedPorts.clear();
|
|
|
+ qDebug() << "All serial ports closed";
|
|
|
}
|
|
|
|
|
|
-// 处理接收到的数据
|
|
|
-void SerialManager::onDataReceived(const QString &portName)
|
|
|
+void SerialManager::setSerialConfig(const SerialConfig &config)
|
|
|
{
|
|
|
- if (!m_serialPorts.contains(portName)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- QSerialPort *serialPort = m_serialPorts[portName];
|
|
|
- QByteArray data = serialPort->readAll();
|
|
|
-
|
|
|
- if (!data.isEmpty()) {
|
|
|
- // 存储原始数据
|
|
|
- storeRawData(portName, data);
|
|
|
-
|
|
|
- // 解析数据
|
|
|
- parseData(portName, data);
|
|
|
+ m_serialConfig = config;
|
|
|
|
|
|
- emit dataReceived(portName, data);
|
|
|
+ // 更新所有已打开端口的配置
|
|
|
+ for (QSerialPort *port : m_serialPorts.values())
|
|
|
+ {
|
|
|
+ port->setBaudRate(config.baudRate);
|
|
|
+ port->setDataBits(config.dataBits);
|
|
|
+ port->setParity(config.parity);
|
|
|
+ port->setStopBits(config.stopBits);
|
|
|
+ port->setFlowControl(config.flowControl);
|
|
|
}
|
|
|
+
|
|
|
+ qDebug() << "Serial configuration updated";
|
|
|
}
|
|
|
|
|
|
-// 存储接收到的原始数据
|
|
|
-void SerialManager::storeRawData(const QString &portName, const QByteArray &data)
|
|
|
+SerialManager::SerialConfig SerialManager::getSerialConfig() const
|
|
|
{
|
|
|
- qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
|
|
|
- QString key = QString("%1_%2").arg(timestamp).arg(portName);
|
|
|
-
|
|
|
- // 这里应该调用存储服务存储原始数据
|
|
|
- // m_storageService->storeRawData(key, data);
|
|
|
+ return m_serialConfig;
|
|
|
+}
|
|
|
|
|
|
- qDebug() << "Stored raw data:" << key << "Size:" << data.size();
|
|
|
+QStringList SerialManager::getOpenedPorts() const
|
|
|
+{
|
|
|
+ return m_openedPorts.values();
|
|
|
}
|
|
|
|
|
|
-// 解析接收到的数据
|
|
|
-void SerialManager::parseData(const QString &portName, const QByteArray &data)
|
|
|
+QStringList SerialManager::getAvailablePorts() const
|
|
|
{
|
|
|
- // 尝试解析为Modbus协议
|
|
|
- if (data.size() >= 4) { // Modbus RTU最小帧长度
|
|
|
- parseModbus(data, portName);
|
|
|
+ QStringList ports;
|
|
|
+ foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
|
|
|
+ {
|
|
|
+ if (isRealSerialPort(info))
|
|
|
+ {
|
|
|
+ // qDebug() << "Available port:" << info.portName() << "-" << info.description();
|
|
|
+ ports << info.portName();
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 可以添加其他协议解析
|
|
|
- parseCustomProtocol(data, portName);
|
|
|
+ return ports;
|
|
|
}
|
|
|
|
|
|
-// 解析Modbus RTU协议数据
|
|
|
-void SerialManager::parseModbus(const QByteArray &data, const QString &portName)
|
|
|
+bool SerialManager::isRealSerialPort(const QSerialPortInfo &info) const
|
|
|
{
|
|
|
- // 简单的Modbus RTU帧检查
|
|
|
- if (data.size() < 4) return;
|
|
|
+ // 1. 尝试打开串口进行验证
|
|
|
+ QSerialPort testPort;
|
|
|
+ testPort.setPort(info);
|
|
|
+
|
|
|
+ if (testPort.open(QIODevice::ReadWrite))
|
|
|
+ {
|
|
|
+ testPort.close();
|
|
|
+ return true; // 能成功打开关闭的是真实串口
|
|
|
+ }
|
|
|
|
|
|
- // 计算CRC校验(简化版本)
|
|
|
- uint16_t crc = calculateCRC(data.constData(), data.size() - 2);
|
|
|
- uint16_t receivedCrc = static_cast<uint8_t>(data[data.size()-2]) << 8 |
|
|
|
- static_cast<uint8_t>(data[data.size()-1]);
|
|
|
+ // 2. 检查系统特定的虚拟串口标识
|
|
|
+#ifdef Q_OS_WIN
|
|
|
+ // Windows: 过滤蓝牙虚拟串口
|
|
|
+ if (info.description().contains("Bluetooth", Qt::CaseInsensitive) ||
|
|
|
+ info.manufacturer().contains("Standard Serial over Bluetooth", Qt::CaseInsensitive))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+#elif defined(Q_OS_LINUX)
|
|
|
+ // Linux: 过滤虚拟终端
|
|
|
+ if (info.portName().startsWith("ttyS") &&
|
|
|
+ info.description().contains("virtual terminal", Qt::CaseInsensitive))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+#elif defined(Q_OS_MACOS)
|
|
|
+ // macOS: 过滤蓝牙虚拟串口
|
|
|
+ if (info.portName().startsWith("Bluetooth-") ||
|
|
|
+ info.description().contains("Bluetooth", Qt::CaseInsensitive))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+#endif
|
|
|
|
|
|
- if (crc != receivedCrc) {
|
|
|
- return; // CRC校验失败
|
|
|
+ // 3. 检查是否有物理设备属性
|
|
|
+ if (info.vendorIdentifier() == 0 && info.productIdentifier() == 0)
|
|
|
+ {
|
|
|
+ // 没有硬件ID的可能是虚拟端口
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- uint8_t slaveId = static_cast<uint8_t>(data[0]);
|
|
|
- uint8_t functionCode = static_cast<uint8_t>(data[1]);
|
|
|
+ // 4. 检查串口是否在系统设备列表中
|
|
|
+ if (info.isNull())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- QJsonObject modbusData;
|
|
|
- modbusData["timestamp"] = QDateTime::currentMSecsSinceEpoch();
|
|
|
- modbusData["port"] = portName;
|
|
|
- modbusData["slave_id"] = slaveId;
|
|
|
- modbusData["function_code"] = functionCode;
|
|
|
- modbusData["raw_data"] = QString(data.toHex());
|
|
|
+ return true;
|
|
|
+}
|
|
|
|
|
|
- // 解析数据部分
|
|
|
- QJsonArray dataArray;
|
|
|
- if (functionCode == 0x03 || functionCode == 0x04) {
|
|
|
- // 读保持寄存器/输入寄存器
|
|
|
- uint8_t byteCount = static_cast<uint8_t>(data[2]);
|
|
|
- for (int i = 0; i < byteCount; i += 2) {
|
|
|
- if (i + 3 < data.size()) {
|
|
|
- uint16_t value = static_cast<uint8_t>(data[3 + i]) << 8 |
|
|
|
- static_cast<uint8_t>(data[4 + i]);
|
|
|
- dataArray.append(value);
|
|
|
- }
|
|
|
+bool SerialManager::writeData(const QString &portName, const QByteArray &data)
|
|
|
+{
|
|
|
+ if (m_serialPorts.contains(portName))
|
|
|
+ {
|
|
|
+ qint64 bytesWritten = m_serialPorts[portName]->write(data);
|
|
|
+ if (bytesWritten == data.size())
|
|
|
+ {
|
|
|
+ qDebug() << "Data written to" << portName << ":" << data.toHex();
|
|
|
+ return true;
|
|
|
}
|
|
|
- } else if (functionCode == 0x06 || functionCode == 0x10) {
|
|
|
- // 写单个/多个寄存器
|
|
|
- uint16_t address = static_cast<uint8_t>(data[2]) << 8 |
|
|
|
- static_cast<uint8_t>(data[3]);
|
|
|
- dataArray.append(address);
|
|
|
-
|
|
|
- if (functionCode == 0x06) {
|
|
|
- uint16_t value = static_cast<uint8_t>(data[4]) << 8 |
|
|
|
- static_cast<uint8_t>(data[5]);
|
|
|
- dataArray.append(value);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ qWarning() << "Failed to write all data to" << portName
|
|
|
+ << ". Written:" << bytesWritten << "of" << data.size();
|
|
|
}
|
|
|
}
|
|
|
+ return false;
|
|
|
+}
|
|
|
|
|
|
- modbusData["parsed_data"] = dataArray;
|
|
|
- modbusData["crc"] = receivedCrc;
|
|
|
-
|
|
|
- // 发射解析后的数据信号
|
|
|
- emit modbusDataParsed(modbusData);
|
|
|
-
|
|
|
- // 存储到软总线格式
|
|
|
- storeBusMessage(modbusData);
|
|
|
+void SerialManager::setBusCore(SoftBusCore *busCore)
|
|
|
+{
|
|
|
+ m_busCore = busCore;
|
|
|
+ qDebug() << "Bus core set for SerialManager";
|
|
|
}
|
|
|
|
|
|
-// 解析自定义协议数据
|
|
|
-void SerialManager::parseCustomProtocol(const QByteArray &data, const QString &portName)
|
|
|
+SoftBusCore *SerialManager::getBusCore() const
|
|
|
{
|
|
|
- // 自定义协议解析逻辑
|
|
|
- // 这里可以实现您的自定义协议解析
|
|
|
-
|
|
|
- if (data.size() > 2) {
|
|
|
- QJsonObject customData;
|
|
|
- customData["timestamp"] = QDateTime::currentMSecsSinceEpoch();
|
|
|
- customData["port"] = portName;
|
|
|
- customData["protocol"] = "custom";
|
|
|
- customData["data_length"] = data.size();
|
|
|
- customData["raw_data"] = QString(data.toHex());
|
|
|
-
|
|
|
- emit customDataParsed(customData);
|
|
|
- storeBusMessage(customData);
|
|
|
- }
|
|
|
+ return m_busCore;
|
|
|
}
|
|
|
|
|
|
-// 存储解析后的软总线格式数据
|
|
|
-void SerialManager::storeBusMessage(const QJsonObject &message)
|
|
|
+void SerialManager::discoverSerialPorts()
|
|
|
{
|
|
|
- // 这里应该调用存储服务存储软总线格式数据
|
|
|
- // m_storageService->storeBusMessage(message);
|
|
|
+ // 获取当前所有可用串口
|
|
|
+ QSet<QString> currentPorts;
|
|
|
+ foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
|
|
|
+ {
|
|
|
+ QString portName = info.portName();
|
|
|
+ currentPorts.insert(portName);
|
|
|
+
|
|
|
+ // 如果是新发现的端口
|
|
|
+ if (!m_lastDiscoveredPorts.contains(portName))
|
|
|
+ {
|
|
|
+ emit portDiscovered(portName, info.description());
|
|
|
+ qDebug() << "New port discovered:" << portName << "-" << info.description();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- qDebug() << "Stored bus message:" << QJsonDocument(message).toJson(QJsonDocument::Compact);
|
|
|
+ // 检查是否有端口被移除
|
|
|
+ QSet<QString> removedPorts = m_lastDiscoveredPorts - currentPorts;
|
|
|
+ for (const QString &portName : removedPorts)
|
|
|
+ {
|
|
|
+ // 如果端口是打开的,先关闭它
|
|
|
+ if (m_openedPorts.contains(portName))
|
|
|
+ {
|
|
|
+ closeSerialPort(portName);
|
|
|
+ }
|
|
|
+ emit portRemoved(portName);
|
|
|
+ qDebug() << "Port removed:" << portName;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新上次发现的端口列表
|
|
|
+ m_lastDiscoveredPorts = currentPorts;
|
|
|
}
|
|
|
|
|
|
-// 计算CRC校验值
|
|
|
-uint16_t SerialManager::calculateCRC(const char *data, int length)
|
|
|
+void SerialManager::onReadyRead(const QString &portName)
|
|
|
{
|
|
|
- uint16_t crc = 0xFFFF;
|
|
|
-
|
|
|
- for (int pos = 0; pos < length; pos++) {
|
|
|
- crc ^= static_cast<uint8_t>(data[pos]);
|
|
|
-
|
|
|
- for (int i = 8; i != 0; i--) {
|
|
|
- if ((crc & 0x0001) != 0) {
|
|
|
- crc >>= 1;
|
|
|
- crc ^= 0xA001;
|
|
|
- } else {
|
|
|
- crc >>= 1;
|
|
|
- }
|
|
|
+ if (m_serialPorts.contains(portName))
|
|
|
+ {
|
|
|
+ QSerialPort *port = m_serialPorts[portName];
|
|
|
+ QByteArray data = port->readAll();
|
|
|
+
|
|
|
+ if (!data.isEmpty())
|
|
|
+ {
|
|
|
+ // 发出数据接收信号
|
|
|
+ qDebug()<< "receive data" << data.toHex();
|
|
|
+ emit dataReceived(portName, data);
|
|
|
+
|
|
|
+ // 存储原始数据
|
|
|
+ storeRawData(portName, data);
|
|
|
+
|
|
|
+ // 解析数据
|
|
|
+ parseData(portName, data);
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- return crc;
|
|
|
+void SerialManager::parseData(const QString &portName, const QByteArray &data)
|
|
|
+{
|
|
|
+ // 这里可以根据实际需求选择解析协议
|
|
|
+ // 简单实现:根据数据长度判断协议类型
|
|
|
+ if (data.size() >= 6)
|
|
|
+ { // Modbus RTU最小帧长度
|
|
|
+ parseModbus(data, portName);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ parseCustomProtocol(data, portName);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-// 设置串口配置,并更新所有已打开串口的配置
|
|
|
-void SerialManager::setSerialConfig(const SerialConfig &config)
|
|
|
+void SerialManager::parseModbus(const QByteArray &data, const QString &portName)
|
|
|
{
|
|
|
- m_serialConfig = config;
|
|
|
+ // 简化的Modbus解析
|
|
|
+ if (data.size() < 4)
|
|
|
+ return; // 最小长度检查
|
|
|
|
|
|
- // 更新所有已打开端口的配置
|
|
|
- for (QSerialPort *serialPort : m_serialPorts) {
|
|
|
- serialPort->setBaudRate(config.baudRate);
|
|
|
- serialPort->setDataBits(config.dataBits);
|
|
|
- serialPort->setParity(config.parity);
|
|
|
- serialPort->setStopBits(config.stopBits);
|
|
|
- serialPort->setFlowControl(config.flowControl);
|
|
|
+ uint8_t slaveId = static_cast<uint8_t>(data[0]);
|
|
|
+ uint8_t functionCode = static_cast<uint8_t>(data[1]);
|
|
|
+
|
|
|
+ // 创建消息对象
|
|
|
+ BusMessage message;
|
|
|
+ message.id = QString("%1_%2_%3").arg(portName).arg(slaveId).arg(functionCode);
|
|
|
+ message.source = portName;
|
|
|
+ message.destination = "data_processor";
|
|
|
+ message.timestamp = QDateTime::currentMSecsSinceEpoch();
|
|
|
+
|
|
|
+ // 创建payload
|
|
|
+ QJsonObject payload;
|
|
|
+ payload["protocol"] = "modbus";
|
|
|
+ payload["slave_id"] = slaveId;
|
|
|
+ payload["function_code"] = functionCode;
|
|
|
+
|
|
|
+ // 提取数据部分(跳过地址和功能码)
|
|
|
+ QJsonArray dataArray;
|
|
|
+ for (int i = 2; i < data.size() - 2; i++)
|
|
|
+ { // 跳过CRC
|
|
|
+ dataArray.append(static_cast<uint8_t>(data[i]));
|
|
|
+ }
|
|
|
+ payload["data"] = dataArray;
|
|
|
+
|
|
|
+ message.payload = payload;
|
|
|
+
|
|
|
+ // 存储总线消息
|
|
|
+ if (m_busCore)
|
|
|
+ {
|
|
|
+ m_busCore->storeBusMessage(message);
|
|
|
}
|
|
|
+
|
|
|
+ // 发出信号
|
|
|
+ emit modbusDataParsed(payload);
|
|
|
+ qDebug() << "Modbus data parsed from" << portName << ":" << payload;
|
|
|
}
|
|
|
|
|
|
-// 获取当前的串口配置
|
|
|
-SerialManager::SerialConfig SerialManager::getSerialConfig() const
|
|
|
+void SerialManager::parseCustomProtocol(const QByteArray &data, const QString &portName)
|
|
|
{
|
|
|
- return m_serialConfig;
|
|
|
+ // 创建消息对象
|
|
|
+ BusMessage message;
|
|
|
+ message.id = QString("%1_custom_%2").arg(portName).arg(QDateTime::currentMSecsSinceEpoch());
|
|
|
+ message.source = portName;
|
|
|
+ message.destination = "data_processor";
|
|
|
+ message.timestamp = QDateTime::currentMSecsSinceEpoch();
|
|
|
+
|
|
|
+ // 创建payload
|
|
|
+ QJsonObject payload;
|
|
|
+ payload["protocol"] = "custom";
|
|
|
+ payload["raw_data"] = QString(data.toHex());
|
|
|
+
|
|
|
+ message.payload = payload;
|
|
|
+
|
|
|
+ // 存储总线消息
|
|
|
+ if (m_busCore)
|
|
|
+ {
|
|
|
+ m_busCore->storeBusMessage(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 发出信号
|
|
|
+ emit customDataParsed(payload);
|
|
|
+ qDebug() << "Custom protocol data parsed from" << portName << ":" << payload;
|
|
|
}
|
|
|
|
|
|
-// 获取所有已打开的串口名称列表
|
|
|
-QStringList SerialManager::getOpenedPorts() const
|
|
|
+void SerialManager::storeRawData(const QString &portName, const QByteArray &data)
|
|
|
{
|
|
|
- return m_openedPorts.values();
|
|
|
+ if (m_busCore)
|
|
|
+ {
|
|
|
+ m_busCore->storeRawData(portName, data);
|
|
|
+ qDebug() << "Raw data stored for" << portName << ":" << data.toHex();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-// 向指定名称的串口写入数据
|
|
|
-bool SerialManager::writeData(const QString &portName, const QByteArray &data)
|
|
|
+uint16_t SerialManager::calculateCRC(const char *data, int length)
|
|
|
{
|
|
|
- if (m_serialPorts.contains(portName)) {
|
|
|
- QSerialPort *serialPort = m_serialPorts[portName];
|
|
|
- qint64 bytesWritten = serialPort->write(data);
|
|
|
- return serialPort->waitForBytesWritten(1000) && bytesWritten == data.size();
|
|
|
+ // 简化的CRC计算(实际应用中应使用标准CRC算法)
|
|
|
+ uint16_t crc = 0;
|
|
|
+ for (int i = 0; i < length; i++)
|
|
|
+ {
|
|
|
+ crc += static_cast<uint8_t>(data[i]);
|
|
|
}
|
|
|
- return false;
|
|
|
-}
|
|
|
+ return crc;
|
|
|
+}
|