解决偶发单反唤起失败问题; 任务文件要求: 1、高光谱必须在前面,没有顺序要求,因为在执行高光谱任务前会预热卤素灯,所有高光谱任务完成后才关闭卤素灯; 2、单反/深度必须在后面,没有顺序要求; 3、必须要有高光谱任务:单反存在唤醒程序和一定反应时间,所以必须依赖前一个任务进行唤醒; (1)当单反已经是唤醒状态时,重新上电(先下电后上电)后可马上重新唤醒单反:单反适配器剩余电量马上耗尽,所以才能马上重新唤醒单反; (2)当单反在上电的状态下,从唤醒状态自动进入休眠状态时,重新下电后需要等待2分15秒(135秒)后,再重新上电才能唤醒单反:等待135秒的目的是将适配器中电容的剩余电量耗尽;
606 lines
18 KiB
C++
606 lines
18 KiB
C++
#include "TimedDataCollectionDataStructures.h"
|
||
#include <QJsonDocument>
|
||
#include <QJsonObject>
|
||
#include <QJsonArray>
|
||
#include <QFile>
|
||
#include <QTextStream>
|
||
#include <QDebug>
|
||
|
||
// ==================== 公共接口实现 ====================
|
||
|
||
bool TimedDataCollectionDataStructuresReaderWriter::saveTasksToFile(const QString& filePath, const QVector<TimedTask>& tasks)
|
||
{
|
||
QJsonObject root;
|
||
root["version"] = "1.0";
|
||
root["taskCount"] = tasks.size();
|
||
|
||
QJsonArray tasksArray;
|
||
for (const auto& task : tasks) {
|
||
tasksArray.append(timedTaskToJson(task));
|
||
}
|
||
root["tasks"] = tasksArray;
|
||
|
||
QJsonDocument doc(root);
|
||
QFile file(filePath);
|
||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||
qWarning() << "Failed to open file for writing:" << filePath;
|
||
return false;
|
||
}
|
||
|
||
QTextStream out(&file);
|
||
//out.setEncoding(QStringConverter::Utf8);
|
||
out << doc.toJson(QJsonDocument::Indented);
|
||
file.close();
|
||
|
||
return true;
|
||
}
|
||
|
||
bool TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(const QString& filePath, QVector<TimedTask>& tasks)
|
||
{
|
||
QFile file(filePath);
|
||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||
qWarning() << "Failed to open file for reading:" << filePath;
|
||
return false;
|
||
}
|
||
|
||
QByteArray jsonData = file.readAll();
|
||
file.close();
|
||
|
||
QJsonParseError parseError;
|
||
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
|
||
if (parseError.error != QJsonParseError::NoError) {
|
||
qWarning() << "JSON parse error:" << parseError.errorString();
|
||
return false;
|
||
}
|
||
|
||
if (!doc.isObject()) {
|
||
qWarning() << "Invalid JSON root object";
|
||
return false;
|
||
}
|
||
|
||
QJsonObject root = doc.object();
|
||
QJsonArray tasksArray = root["tasks"].toArray();
|
||
tasks.clear();
|
||
tasks.reserve(tasksArray.size());
|
||
|
||
for (const auto& taskValue : tasksArray) {
|
||
if (!taskValue.isObject()) continue;
|
||
TimedTask task;
|
||
if (jsonToTimedTask(taskValue.toObject(), task)) {
|
||
tasks.append(task);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// ==================== 枚举转换函数 ====================
|
||
|
||
QString TimedDataCollectionDataStructuresReaderWriter::taskStatusToString(TaskStatus status)
|
||
{
|
||
switch (status) {
|
||
case TaskStatus::Waiting: return "Waiting";
|
||
case TaskStatus::Running: return "Running";
|
||
case TaskStatus::Finished: return "Finished";
|
||
default: return "Waiting";
|
||
}
|
||
}
|
||
|
||
TaskStatus TimedDataCollectionDataStructuresReaderWriter::stringToTaskStatus(const QString& str)
|
||
{
|
||
if (str == "Running") return TaskStatus::Running;
|
||
if (str == "Finished") return TaskStatus::Finished;
|
||
return TaskStatus::Waiting;
|
||
}
|
||
|
||
QString TimedDataCollectionDataStructuresReaderWriter::subTaskTypeToString(SubTaskType type)
|
||
{
|
||
switch (type) {
|
||
case SubTaskType::HyperSpectual400_1000nm: return "HyperSpectual400_1000nm";
|
||
case SubTaskType::HyperSpectual1000_1700nm: return "HyperSpectual1000_1700nm";
|
||
case SubTaskType::SingleLensReflex: return "SingleLensReflex";
|
||
case SubTaskType::DepthCamera: return "DepthCamera";
|
||
default: return "Unknown";
|
||
}
|
||
}
|
||
|
||
SubTaskType TimedDataCollectionDataStructuresReaderWriter::stringToSubTaskType(const QString& str)
|
||
{
|
||
if (str == "HyperSpectual400_1000nm") return SubTaskType::HyperSpectual400_1000nm;
|
||
if (str == "HyperSpectual1000_1700nm") return SubTaskType::HyperSpectual1000_1700nm;
|
||
if (str == "SingleLensReflex") return SubTaskType::SingleLensReflex;
|
||
if (str == "DepthCamera") return SubTaskType::DepthCamera;
|
||
return SubTaskType::SingleLensReflex;
|
||
}
|
||
|
||
// ==================== SubTask序列化 ====================
|
||
|
||
QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const SubTask& subTask)
|
||
{
|
||
QJsonObject obj;
|
||
obj["type"] = subTaskTypeToString(subTask.type);
|
||
obj["startTime"] = subTask.startTime.toString(Qt::ISODate);
|
||
obj["endTime"] = subTask.endTime.toString(Qt::ISODate);
|
||
obj["durationSeconds"] = subTask.durationSeconds;
|
||
obj["estimatedDurationSeconds"] = subTask.estimatedDurationSeconds;
|
||
obj["pathLineFilePath"] = subTask.pathLineFilePath;
|
||
obj["status"] = taskStatusToString(subTask.status);
|
||
obj["frameRate"] = subTask.frameRate;
|
||
obj["exposureTime"] = subTask.exposureTime;
|
||
obj["defaultRenderBand"] = subTask.defaultRenderBand;
|
||
obj["captureIntervalSeconds"] = subTask.captureIntervalSeconds;
|
||
return obj;
|
||
}
|
||
|
||
bool TimedDataCollectionDataStructuresReaderWriter::jsonToSubTask(const QJsonObject& json, SubTask& subTask)
|
||
{
|
||
subTask.type = stringToSubTaskType(json["type"].toString());
|
||
subTask.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
|
||
subTask.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
|
||
subTask.durationSeconds = json["durationSeconds"].toInt();
|
||
subTask.estimatedDurationSeconds = json["estimatedDurationSeconds"].toInt();
|
||
subTask.pathLineFilePath = json["pathLineFilePath"].toString();
|
||
subTask.status = stringToTaskStatus(json["status"].toString());
|
||
subTask.frameRate = json["frameRate"].toDouble();
|
||
subTask.exposureTime = json["exposureTime"].toDouble();
|
||
subTask.defaultRenderBand = json["defaultRenderBand"].toInt();
|
||
subTask.captureIntervalSeconds = json["captureIntervalSeconds"].toInt();
|
||
return true;
|
||
}
|
||
|
||
// ==================== TimedTask序列化 ====================
|
||
|
||
QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const TimedTask& task)
|
||
{
|
||
QJsonObject obj;
|
||
obj["id"] = task.id;
|
||
obj["scheduledTime"] = task.scheduledTime.toString(Qt::ISODate);
|
||
obj["startTime"] = task.startTime.toString(Qt::ISODate);
|
||
obj["endTime"] = task.endTime.toString(Qt::ISODate);
|
||
obj["durationSeconds"] = task.durationSeconds;
|
||
obj["savePath"] = task.savePath;
|
||
obj["status"] = taskStatusToString(task.status);
|
||
obj["HalogenLampPreheatingTime_Minute"] = task.HalogenLampPreheatingTime_Minute;
|
||
|
||
QJsonArray subTasksArray;
|
||
for (const auto& subTask : task.subTasks) {
|
||
subTasksArray.append(subTaskToJson(subTask));
|
||
}
|
||
obj["subTasks"] = subTasksArray;
|
||
|
||
return obj;
|
||
}
|
||
|
||
bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonObject& json, TimedTask& task)
|
||
{
|
||
task.id = json["id"].toInt();
|
||
task.scheduledTime = QDateTime::fromString(json["scheduledTime"].toString(), Qt::ISODate);
|
||
task.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
|
||
task.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
|
||
task.durationSeconds = json["durationSeconds"].toInt();
|
||
task.savePath = json["savePath"].toString();
|
||
task.status = stringToTaskStatus(json["status"].toString());
|
||
task.HalogenLampPreheatingTime_Minute = json["HalogenLampPreheatingTime_Minute"].toDouble();
|
||
|
||
QJsonArray subTasksArray = json["subTasks"].toArray();
|
||
task.subTasks.clear();
|
||
task.subTasks.reserve(subTasksArray.size());
|
||
|
||
for (const auto& subTaskValue : subTasksArray) {
|
||
if (!subTaskValue.isObject()) continue;
|
||
SubTask subTask;
|
||
if (jsonToSubTask(subTaskValue.toObject(), subTask)) {
|
||
task.subTasks.append(subTask);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// ==================== TaskExecutor 实现 ====================
|
||
|
||
TaskExecutor::TaskExecutor(QObject* parent)
|
||
: QObject(parent)
|
||
, m_currentSubTaskIndex(0)
|
||
, m_isRunning(false)
|
||
{
|
||
}
|
||
|
||
TaskExecutor::~TaskExecutor()
|
||
{
|
||
stop();
|
||
}
|
||
|
||
void TaskExecutor::execute(const TimedTask& task)
|
||
{
|
||
if (m_isRunning) {
|
||
qWarning() << "TaskExecutor: Already running, ignoring execute request";
|
||
return;
|
||
}
|
||
|
||
m_task = task;
|
||
m_currentSubTaskIndex = 0;
|
||
m_isRunning = true;
|
||
|
||
qDebug() << "TaskExecutor: Starting task" << task.id;
|
||
|
||
// 打开卤素灯预热
|
||
emit switchHalogenLampSignal(1);
|
||
printMsgAndTime("open HalogenLamp");
|
||
|
||
makeFolder(m_task.savePath);
|
||
|
||
// 开始执行第一个子任务
|
||
double sleepTimeSecond = m_task.HalogenLampPreheatingTime_Minute * 60;
|
||
QTimer::singleShot(sleepTimeSecond *1000, this, &TaskExecutor::executeNextSubTask);
|
||
}
|
||
|
||
void TaskExecutor::printMsgAndTime(QString msg)
|
||
{
|
||
QDateTime now = QDateTime::currentDateTime();
|
||
QString timeString = now.toString("yyyy-MM-dd hh:mm:ss.zzz");
|
||
qDebug() << msg + " time:" << timeString;
|
||
}
|
||
|
||
void TaskExecutor::stop()
|
||
{
|
||
if (!m_isRunning) return;
|
||
|
||
qDebug() << "TaskExecutor: Stopping task" << m_task.id;
|
||
|
||
m_isRunning = false;
|
||
emit finished(false);
|
||
}
|
||
|
||
void TaskExecutor::makeFolder(QString savePath)
|
||
{
|
||
QDir dir(savePath);
|
||
if (!dir.exists()) {
|
||
if (dir.mkpath(".")) {
|
||
qDebug() << "TaskExecutor: Created data folder:" << savePath;
|
||
} else {
|
||
qWarning() << "TaskExecutor: Failed to create data folder:" << savePath;
|
||
}
|
||
} else {
|
||
qDebug() << "TaskExecutor: Data folder already exists:" << savePath;
|
||
}
|
||
}
|
||
|
||
QString TaskExecutor::makeSubTaskDataFolder(QString suffix)
|
||
{
|
||
QString dateStr = QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss");
|
||
QString folderPath = m_task.savePath + QDir::separator() + dateStr + "_" + suffix;
|
||
makeFolder(folderPath);
|
||
|
||
return folderPath;
|
||
}
|
||
|
||
void TaskExecutor::onSequenceComplete(int status)
|
||
{
|
||
if (!m_isRunning) return;
|
||
|
||
qDebug() << "TaskExecutor: Sequence complete, status:" << status;
|
||
|
||
// 更新当前子任务状态
|
||
if (m_currentSubTaskIndex < m_task.subTasks.size()) {
|
||
SubTask& subTask = m_task.subTasks[m_currentSubTaskIndex];
|
||
subTask.status = (status == 0) ? TaskStatus::Finished : TaskStatus::Waiting;
|
||
|
||
emit subTaskFinished(m_currentSubTaskIndex, subTask.type, (status == 0));
|
||
}
|
||
|
||
//
|
||
switch (m_task.subTasks[m_currentSubTaskIndex].type)
|
||
{
|
||
case SubTaskType::SingleLensReflex:
|
||
{
|
||
emit switchD65LampSignal(0);
|
||
emit switchSlrSignal(0);
|
||
break;
|
||
}
|
||
case SubTaskType::DepthCamera:
|
||
{
|
||
emit switchD65LampSignal(0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 判断下一次的任务是否为高光谱任务,如果不是关闭卤素灯
|
||
int nestSubTaskIndex = m_currentSubTaskIndex + 1;
|
||
if (nestSubTaskIndex >= m_task.subTasks.size())
|
||
{
|
||
emit switchHalogenLampSignal(0);
|
||
return;
|
||
}
|
||
switch (m_task.subTasks[nestSubTaskIndex].type)
|
||
{
|
||
case SubTaskType::SingleLensReflex:
|
||
{
|
||
emit switchHalogenLampSignal(0);
|
||
break;
|
||
}
|
||
case SubTaskType::DepthCamera:
|
||
{
|
||
emit switchHalogenLampSignal(0);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void TaskExecutor::onBack2Origin()
|
||
{
|
||
// 检查是否还有更多子任务
|
||
m_currentSubTaskIndex++;
|
||
if (m_currentSubTaskIndex < m_task.subTasks.size()) {
|
||
// 执行下一个子任务
|
||
if(m_task.subTasks[m_currentSubTaskIndex].type== SubTaskType::SingleLensReflex)
|
||
{
|
||
printMsgAndTime("Slr task,for weak up,please wait 135 seconds!");
|
||
emit switchSlrSignal(0);
|
||
|
||
QTimer::singleShot(135*1000, this, &TaskExecutor::executeNextSubTask);
|
||
}
|
||
else
|
||
{
|
||
QTimer::singleShot(1000, this, &TaskExecutor::executeNextSubTask);
|
||
}
|
||
}
|
||
else {
|
||
// 所有子任务完成
|
||
m_isRunning = false;
|
||
qDebug() << "TaskExecutor: All subtasks completed";
|
||
emit finished(true);
|
||
}
|
||
}
|
||
|
||
void TaskExecutor::onError(const QString& error)
|
||
{
|
||
if (!m_isRunning) return;
|
||
|
||
qWarning() << "TaskExecutor: Error occurred:" << error;
|
||
m_isRunning = false;
|
||
emit errorOccurred(error);
|
||
emit finished(false);
|
||
}
|
||
|
||
void TaskExecutor::executeNextSubTask()
|
||
{
|
||
if (!m_isRunning || m_currentSubTaskIndex >= m_task.subTasks.size()) {
|
||
return;
|
||
}
|
||
|
||
SubTask& subTask = m_task.subTasks[m_currentSubTaskIndex];
|
||
subTask.status = TaskStatus::Running;
|
||
subTask.startTime = QDateTime::currentDateTime();
|
||
|
||
QString tmp = "TaskExecutor: Starting subtask" + QString::number(m_currentSubTaskIndex) + "type:" + static_cast<int>(subTask.type);
|
||
printMsgAndTime(tmp);
|
||
//printMsgAndTime("excute " + QString::number(m_currentSubTaskIndex) + " subTask: ");
|
||
|
||
//qDebug() << "TaskExecutor: Starting subtask" << m_currentSubTaskIndex
|
||
// << "type:" << static_cast<int>(subTask.type);
|
||
|
||
emit subTaskStarted(m_currentSubTaskIndex, subTask.type);
|
||
|
||
emit motorParm(subTask.pathLineFilePath);
|
||
|
||
int camType;
|
||
switch (subTask.type)
|
||
{
|
||
case SubTaskType::HyperSpectual400_1000nm:
|
||
{
|
||
camType = 0;
|
||
emit hyperCamParm(camType, subTask.frameRate, subTask.exposureTime, makeSubTaskDataFolder("L"), "test");
|
||
|
||
break;
|
||
}
|
||
case SubTaskType::HyperSpectual1000_1700nm:
|
||
{
|
||
camType = 1;
|
||
emit hyperCamParm(camType, subTask.frameRate, subTask.exposureTime, makeSubTaskDataFolder("NIR"), "test");
|
||
|
||
break;
|
||
}
|
||
case SubTaskType::SingleLensReflex:
|
||
{
|
||
camType = 2;
|
||
emit camParm(camType, 3, makeSubTaskDataFolder("SLR"));
|
||
|
||
emit switchD65LampSignal(1);
|
||
|
||
|
||
emit switchSlrSignal(1);
|
||
|
||
break;
|
||
}
|
||
case SubTaskType::DepthCamera:
|
||
{
|
||
camType = 3;
|
||
emit camParm(camType, 3, makeSubTaskDataFolder("DepthCamera"));
|
||
|
||
emit switchD65LampSignal(1);
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
emit startRecordSignal(camType);
|
||
}
|
||
|
||
// ==================== TaskScheduler 实现 ====================
|
||
|
||
TaskScheduler::TaskScheduler(QObject* parent)
|
||
: QObject(parent)
|
||
, m_timer(nullptr)
|
||
, m_currentExecutor(nullptr)
|
||
, m_currentTaskId(-1)
|
||
{
|
||
}
|
||
|
||
TaskScheduler::~TaskScheduler()
|
||
{
|
||
stop();
|
||
}
|
||
|
||
void TaskScheduler::loadTasks(const QVector<TimedTask>& tasks)
|
||
{
|
||
m_tasks = tasks;
|
||
qDebug() << "TaskScheduler: Loaded" << tasks.size() << "tasks";
|
||
}
|
||
|
||
void TaskScheduler::start()
|
||
{
|
||
if (m_timer) {
|
||
qDebug() << "TaskScheduler: Already running";
|
||
return;
|
||
}
|
||
|
||
qDebug() << "TaskScheduler: Starting";
|
||
|
||
m_timer = new QTimer(this);
|
||
connect(m_timer, &QTimer::timeout, this, &TaskScheduler::checkTasks);
|
||
m_timer->start(1000); // 每秒检查一次
|
||
|
||
emit schedulerStateChanged(true);
|
||
}
|
||
|
||
void TaskScheduler::stop()
|
||
{
|
||
if (m_timer) {
|
||
m_timer->stop();
|
||
delete m_timer;
|
||
m_timer = nullptr;
|
||
}
|
||
|
||
if (m_currentExecutor) {
|
||
m_currentExecutor->stop();
|
||
m_currentExecutor->deleteLater();
|
||
m_currentExecutor = nullptr;
|
||
}
|
||
|
||
qDebug() << "TaskScheduler: Stopped";
|
||
emit schedulerStateChanged(false);
|
||
}
|
||
|
||
void TaskScheduler::checkTasks()
|
||
{
|
||
QDateTime now = QDateTime::currentDateTime();
|
||
|
||
for (auto& task : m_tasks) {
|
||
if (task.status != TaskStatus::Waiting) continue;
|
||
|
||
// 超过计划时间1分钟以上,认为任务已过时,跳过
|
||
if (task.scheduledTime.addSecs(60) < now) {
|
||
std::cerr << "TaskScheduler::checkTasks,任务已过时,跳过:" << task.id << std::endl;
|
||
task.status = TaskStatus::Finished;
|
||
continue;
|
||
}
|
||
|
||
if (task.scheduledTime > now) continue;
|
||
|
||
// 到达计划时间,启动任务
|
||
std::cerr << "TaskScheduler::checkTasks,到达计划时间,启动任务" << std::endl;
|
||
executeTask(task);
|
||
break; // 一次只执行一个任务
|
||
}
|
||
}
|
||
|
||
void TaskScheduler::onTaskFinished(bool success)
|
||
{
|
||
if (m_currentTaskId > 0) {
|
||
TaskStatus status = success ? TaskStatus::Finished : TaskStatus::Waiting;
|
||
updateTaskStatus(m_currentTaskId, status);
|
||
emit taskFinished(m_currentTaskId, success);
|
||
}
|
||
|
||
// 清理执行器
|
||
if (m_currentExecutor) {
|
||
m_currentExecutor->deleteLater();
|
||
m_currentExecutor = nullptr;
|
||
}
|
||
m_currentTaskId = -1;
|
||
}
|
||
|
||
void TaskScheduler::onSubTaskStarted(int subTaskIndex, SubTaskType type)
|
||
{
|
||
if (m_currentTaskId > 0) {
|
||
emit subTaskStarted(m_currentTaskId, subTaskIndex);
|
||
}
|
||
}
|
||
|
||
void TaskScheduler::onSubTaskFinished(int subTaskIndex, SubTaskType type, bool success)
|
||
{
|
||
if (m_currentTaskId > 0) {
|
||
emit subTaskFinished(m_currentTaskId, subTaskIndex);
|
||
}
|
||
}
|
||
|
||
void TaskScheduler::onExecutorError(const QString& error)
|
||
{
|
||
emitError(error);
|
||
}
|
||
|
||
void TaskScheduler::executeTask(TimedTask& task)
|
||
{
|
||
qDebug() << "TaskScheduler: Executing task" << task.id;
|
||
|
||
updateTaskStatus(task.id, TaskStatus::Running);
|
||
m_currentTaskId = task.id;
|
||
|
||
emit taskStarted(task.id);
|
||
|
||
// 创建任务执行器
|
||
m_currentExecutor = new TaskExecutor(this);
|
||
|
||
// 连接信号
|
||
connect(m_currentExecutor, &TaskExecutor::finished,
|
||
this, &TaskScheduler::onTaskFinished);
|
||
connect(m_currentExecutor, &TaskExecutor::subTaskStarted,
|
||
this, &TaskScheduler::onSubTaskStarted);
|
||
connect(m_currentExecutor, &TaskExecutor::subTaskFinished,
|
||
this, &TaskScheduler::onSubTaskFinished);
|
||
connect(m_currentExecutor, &TaskExecutor::errorOccurred,
|
||
this, &TaskScheduler::onExecutorError);
|
||
|
||
// 采集相关信号透传
|
||
connect(m_currentExecutor, &TaskExecutor::hyperCamParm,
|
||
this, &TaskScheduler::hyperCamParm);
|
||
connect(m_currentExecutor, &TaskExecutor::camParm,
|
||
this, &TaskScheduler::camParm);
|
||
connect(m_currentExecutor, &TaskExecutor::motorParm,
|
||
this, &TaskScheduler::motorParm);
|
||
connect(m_currentExecutor, &TaskExecutor::startRecordSignal,
|
||
this, &TaskScheduler::startRecordSignal);
|
||
|
||
connect(m_currentExecutor, &TaskExecutor::switchHalogenLampSignal, this, &TaskScheduler::switchHalogenLampSignal);
|
||
connect(m_currentExecutor, &TaskExecutor::switchD65LampSignal, this, &TaskScheduler::switchD65LampSignal);
|
||
connect(m_currentExecutor, &TaskExecutor::switchSlrSignal, this, &TaskScheduler::switchSlrSignal);
|
||
|
||
connect(this, &TaskScheduler::sequenceCompleteSignal, m_currentExecutor, &TaskExecutor::onSequenceComplete);
|
||
connect(this, &TaskScheduler::Back2OriginSignal, m_currentExecutor, &TaskExecutor::onBack2Origin);
|
||
|
||
// 开始执行
|
||
m_currentExecutor->execute(task);
|
||
}
|
||
|
||
void TaskScheduler::updateTaskStatus(int taskId, TaskStatus status)
|
||
{
|
||
for (auto& task : m_tasks) {
|
||
if (task.id == taskId) {
|
||
task.status = status;
|
||
if (status == TaskStatus::Running) {
|
||
task.startTime = QDateTime::currentDateTime();
|
||
} else if (status == TaskStatus::Finished) {
|
||
task.endTime = QDateTime::currentDateTime();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void TaskScheduler::emitError(const QString& error)
|
||
{
|
||
qWarning() << "TaskScheduler: Error:" << error;
|
||
emit errorOccurred(error);
|
||
}
|