#include "calibrator.h" #include #include #include Calibrator::Calibrator(QObject *parent) : QObject(parent) , serialPort(new QSerialPort(this)) , calibrationTimer(new QTimer(this)) , receiveTimeoutTimer(new QTimer(this)) , consoleOutput(new QTextStream(stdout)) , currentState(Idle) , retryCount(0) , manualMode(false) { connect(serialPort, &QSerialPort::readyRead, this, &Calibrator::onSerialDataReceived); connect(calibrationTimer, &QTimer::timeout, this, &Calibrator::onCalibrationStepTimeout); connect(receiveTimeoutTimer, &QTimer::timeout, this, &Calibrator::onReceiveTimeout); receiveTimeoutTimer->setSingleShot(true); logInfo("CO2传感器校准工具已启动"); } Calibrator::~Calibrator() { if (serialPort->isOpen()) { serialPort->close(); } } bool Calibrator::connectSerialPort(const QString &portName, int baudRate) { serialPort->setPortName(portName); serialPort->setBaudRate(baudRate); serialPort->setDataBits(QSerialPort::Data8); serialPort->setParity(QSerialPort::NoParity); serialPort->setStopBits(QSerialPort::OneStop); serialPort->setFlowControl(QSerialPort::NoFlowControl); if (serialPort->open(QIODevice::ReadWrite)) { logSuccess(QString("串口已连接: %1, 波特率: %2").arg(portName).arg(baudRate)); return true; } else { logError(QString("无法打开串口: %1, 错误: %2").arg(portName).arg(serialPort->errorString())); return false; } } void Calibrator::disconnectSerialPort() { if (serialPort->isOpen()) { serialPort->close(); logInfo("串口已断开"); } if (currentState != Idle) { stopCalibration(); } } void Calibrator::startCalibration(double temperature) { if (!serialPort->isOpen()) { logError("请先连接串口!"); return; } // 将温度转换为5位数字格式,例如24.0 -> 00240 temperatureValue = QString("%1").arg(static_cast(temperature * 10), 5, 10, QChar('0')); logInfo(QString("开始校准流程,校准温度: %1℃ (编码: %2)").arg(temperature).arg(temperatureValue)); currentState = Step1_TC0; retryCount = 0; manualMode = false; nextCalibrationStep(); } void Calibrator::stopCalibration() { currentState = Idle; retryCount = 0; calibrationTimer->stop(); logInfo("校准已停止"); } void Calibrator::sendManualCommand(const QString &command) { if (!serialPort->isOpen()) { logError("请先连接串口!"); return; } manualMode = true; sendCommand(command); } void Calibrator::onSerialDataReceived() { // 将接收到的数据追加到缓冲区 receiveBuffer.append(serialPort->readAll()); // 重置超时定时器(每次收到新数据都重置) receiveTimeoutTimer->stop(); // 查找完整的响应(以换行符结尾) while (true) { int lineEnd = -1; int lineLength = 0; // 优先查找 \r\n if (receiveBuffer.contains("\r\n")) { lineEnd = receiveBuffer.indexOf("\r\n"); lineLength = 2; } else if (receiveBuffer.contains('\n')) { lineEnd = receiveBuffer.indexOf('\n'); lineLength = 1; } else if (receiveBuffer.contains('\r')) { lineEnd = receiveBuffer.indexOf('\r'); lineLength = 1; } if (lineEnd >= 0) { // 提取一行数据(不包含换行符) QByteArray line = receiveBuffer.left(lineEnd); receiveBuffer.remove(0, lineEnd + lineLength); QString response = QString::fromUtf8(line).trimmed(); if (!response.isEmpty()) { logMessage(QString("接收: %1").arg(response)); if (manualMode) { manualMode = false; continue; } processResponse(response); } } else { // 没有找到完整的行,启动超时定时器 // 如果200ms内没有新数据到达,认为当前缓冲区中的数据是完整的响应 if (!receiveBuffer.isEmpty()) { receiveTimeoutTimer->start(200); // 200ms超时 } // 等待更多数据 break; } } } void Calibrator::onReceiveTimeout() { // 超时后,处理缓冲区中的数据 if (!receiveBuffer.isEmpty()) { QString response = QString::fromUtf8(receiveBuffer).trimmed(); receiveBuffer.clear(); if (!response.isEmpty()) { logMessage(QString("接收(超时): %1").arg(response)); if (manualMode) { manualMode = false; return; } processResponse(response); } } } void Calibrator::onCalibrationStepTimeout() { logError("等待响应超时,重试当前步骤..."); retryCount++; if (retryCount > 3) { logError("重试次数过多,停止校准"); stopCalibration(); emit calibrationFailed("等待响应超时"); return; } nextCalibrationStep(); } void Calibrator::sendCommand(const QString &command) { if (!serialPort->isOpen()) { return; } QString cmd = command; if (!cmd.endsWith("\r\n") && !cmd.endsWith("\n")) { cmd += "\r\n"; } QByteArray data = cmd.toUtf8(); qint64 bytesWritten = serialPort->write(data); if (bytesWritten == -1) { logError(QString("发送失败: %1").arg(serialPort->errorString())); } else { logMessage(QString("发送: %1").arg(command)); serialPort->flush(); } } int timetry=0; void Calibrator::processResponse(const QString &response) { // 如果正在进行校准流程,处理响应 if (currentState != Idle) { // 检查响应是否匹配当前步骤的期望响应 bool stepComplete = false; switch (currentState) { case Step1_TC0: if (response.contains("$WI,TC=0") || response.contains("TC=0")) { stepComplete = true; logSuccess("步骤1完成: TC0设置成功"); } break; case Step2_KY18_First: if (response.contains("$WI,KY=18") || response.contains("KY=18")) { stepComplete = true; logSuccess("步骤2完成: KY18设置成功"); } break; case Step3_AC_First: if (response.contains("$WI,AC=") || response.contains("AC=")) { stepComplete = true; QString acValues = extractACValues(response); logSuccess(QString("步骤3完成: 第一次AC校准,返回值: %1").arg(acValues)); } break; case Step4_KY18_Second: if (response.contains("$WI,KY=18") || response.contains("KY=18")) { stepComplete = true; logSuccess("步骤4完成: 第二次KY18设置成功"); } break; case Step5_AC_Second: if (response.contains("$WI,AC=") || response.contains("AC=")) { QString acValues = extractACValues(response); logInfo(QString("步骤5: 第二次AC校准,返回值: %1").arg(acValues)); if (checkCalibrationComplete(response)) { stepComplete = true; logSuccess("校准完成!所有值均小于10"); } else { if (timetry>1) { stepComplete = true; logInfo("次数满了"); break; } timetry++; logInfo("校准未完成,需要重复步骤2-3,等待5秒后重试..."); // 重新开始步骤2 currentState = Step2_KY18_First; retryCount = 0; calibrationTimer->stop(); QTimer::singleShot(5000, this, &Calibrator::nextCalibrationStep); return; } } break; case Step6_Restore_KY18: if (response.contains("$WI,KY=18") || response.contains("KY=18")) { stepComplete = true; logSuccess("步骤6完成: 恢复模式KY18设置成功"); } break; case Step7_Restore_TC: if (response.contains("$WI,TC=00001") || response.contains("TC=00001")) { stepComplete = true; logSuccess("步骤7完成: 恢复模式TC设置成功,校准流程全部完成!"); stopCalibration(); emit calibrationCompleted(); return; } break; default: break; } if (stepComplete) { calibrationTimer->stop(); retryCount = 0; // 更新到下一步状态 switch (currentState) { case Step1_TC0: currentState = Step2_KY18_First; break; case Step2_KY18_First: currentState = Step3_AC_First; break; case Step3_AC_First: currentState = Step4_KY18_Second; break; case Step4_KY18_Second: currentState = Step5_AC_Second; break; case Step5_AC_Second: currentState = Step6_Restore_KY18; break; case Step6_Restore_KY18: currentState = Step7_Restore_TC; break; case Step7_Restore_TC: // 已完成,不需要更新状态 break; default: break; } QTimer::singleShot(500, this, &Calibrator::nextCalibrationStep); } } } void Calibrator::nextCalibrationStep() { if (currentState == Idle) { return; } // 设置超时定时器 calibrationTimer->stop(); calibrationTimer->setSingleShot(true); calibrationTimer->start(5000); // 5秒超时 switch (currentState) { case Step1_TC0: sendCommand("$01,TC0"); break; case Step2_KY18_First: sendCommand("$01,KY18"); break; case Step3_AC_First: { QString acCommand = QString("$01,AC%1^**").arg(temperatureValue); sendCommand(acCommand); } break; case Step4_KY18_Second: sendCommand("$01,KY18"); break; case Step5_AC_Second: { QString acCommand = QString("$01,AC%1^**").arg(temperatureValue); sendCommand(acCommand); } break; case Step6_Restore_KY18: sendCommand("$01,KY18"); break; case Step7_Restore_TC: sendCommand("$01,TC00001^**"); break; default: break; } } bool Calibrator::checkCalibrationComplete(const QString &response) { QString acValues = extractACValues(response); return allValuesLessThan10(acValues); } QString Calibrator::extractACValues(const QString &response) { // 提取AC=后面的所有值 // 格式: $WI,AC=01854,01853,01853,00927,00010,00010,00025,00025,00014,00013 QRegularExpression re(R"(\$WI,AC=(.+))"); QRegularExpressionMatch match = re.match(response); if (!match.hasMatch()) { // 尝试另一种格式 re.setPattern(R"(AC=(.+))"); match = re.match(response); } if (match.hasMatch()) { return match.captured(1); } return ""; } bool Calibrator::allValuesLessThan10(const QString &acValues) { if (acValues.isEmpty()) { return false; } // 分割所有值 QStringList values = acValues.split(','); if (values.isEmpty()) { return false; } // 检查从第5个值(包含)到最后一个值 // 示例: 01094,01094,01091,01094,000474 -> 检查第5个值(000474) // 如果有更多值,检查从第5个到最后一个 int startIndex = 4; // 第5个值(索引从0开始,所以是4) if (startIndex >= values.size()) { logError(QString("值数量不足5个,无法检查")); return false; } QStringList checkedValues; for (int i = startIndex; i < values.size(); i++) { QString valueStr = values[i].trimmed(); bool ok; int value = valueStr.toInt(&ok); if (!ok) { logError(QString("无法解析值: %1").arg(valueStr)); return false; } checkedValues << valueStr; if (value >= 10) { logInfo(QString("检查值: %1 (第%2到最后一个值: %3),值 %4 >= 10,校准未完成") .arg(valueStr) .arg(startIndex + 1) .arg(checkedValues.join(",")) .arg(value)); return false; } } logSuccess(QString("第%1到最后一个值均小于10 (值: %2),校准完成") .arg(startIndex + 1) .arg(checkedValues.join(","))); return true; } void Calibrator::logMessage(const QString &message) { QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); *consoleOutput << QString("[%1] %2\n").arg(timestamp).arg(message); consoleOutput->flush(); } void Calibrator::logError(const QString &message) { QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); *consoleOutput << QString("[%1] [错误] %2\n").arg(timestamp).arg(message); consoleOutput->flush(); } void Calibrator::logSuccess(const QString &message) { QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); *consoleOutput << QString("[%1] [成功] %2\n").arg(timestamp).arg(message); consoleOutput->flush(); } void Calibrator::logInfo(const QString &message) { QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); *consoleOutput << ("[%1] [信息] %2\n").arg(timestamp).arg(message); consoleOutput->flush(); }