From f5198efab3228e8a52ec438f75573f41f7af779c Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Fri, 14 Jul 2023 13:32:00 +0200 Subject: [PATCH] Added worker/worker-thread-pair. Worker uses event-loop of worker-thread. Worker itself is used as work-horse for the update-process. --- worker.cpp | 292 +++++++++++++++++++++++++++++++++++++++++++++++------ worker.h | 50 ++++++++- 2 files changed, 308 insertions(+), 34 deletions(-) diff --git a/worker.cpp b/worker.cpp index c9954c2..762ff17 100644 --- a/worker.cpp +++ b/worker.cpp @@ -7,20 +7,33 @@ #include #include #include +#include #include +#include +#include +#include #include "message_handler.h" #include "plugins/interfaces.h" #include "ismas/ismas_client.h" #include "apism/apism_client.h" -Worker::Worker(hwinf *hw, QString update_ctrl_file, QString workingDir, - bool maintenanceMode, bool testMode, bool executeScriptOnly, - bool dryRun, QObject *parent, char const *serialInterface, - char const *baudrate) +Worker::Worker(hwinf *hw, QString update_ctrl_file, QString repositoryPath, + QString customerId, QString branchName, QString workingDirectory, bool maintenanceMode, + bool testMode, bool executeScriptOnly, bool dryRun, QObject *parent, + char const *serialInterface, char const *baudrate) : m_workerThread("workerThread") - , m_apismClient(0, 0, 0, this) - , m_gc("/opt/app/tools/atbupdate/customer_999", "zg1/zone1", this) { + , m_apismClient(0, 0, 0, this) // TODO + , m_gc(repositoryPath, customerId, workingDirectory, branchName, this) + , m_customerId(customerId) + , m_workingDirectory(workingDirectory) + , m_branchName(branchName) + , m_customerRepository(QDir::cleanPath(m_workingDirectory + + QDir::separator() + + m_customerId)) + , m_maintenanceMode(maintenanceMode) + , m_ismasUpdateRequests(ISMAS_UPDATE_REQUESTS) + , m_waitForNewUpdates(this) { this->moveToThread(&m_workerThread); //m_apismClient.moveToThread(&m_workerThread); @@ -35,21 +48,41 @@ Worker::Worker(hwinf *hw, QString update_ctrl_file, QString workingDir, QThread::sleep(1); } - m_update = new Update(hw, update_ctrl_file, workingDir, + m_update = new Update(hw, update_ctrl_file, repositoryPath, customerId, + branchName, workingDirectory, maintenanceMode, testMode, executeScriptOnly, dryRun, parent, serialInterface, baudrate); connect(&m_apismClient, SIGNAL(ismasResponseAvailable(QJsonObject)), this, SLOT(onIsmasResponseReceived(QJsonObject))); - connect(this, SIGNAL(executeOpkgCommands()), this, - SLOT(onExecuteOpkgCommands()), Qt::QueuedConnection); + connect(this, SIGNAL(executeOpkgCommands(QStringList)), this, + SLOT(onExecuteOpkgCommands(QStringList)), Qt::QueuedConnection); + connect(this, SIGNAL(executeOpkgCommand(QString)), this, + SLOT(onExecuteOpkgCommand(QString)), Qt::QueuedConnection); + connect(this, SIGNAL(summarizeRepositoryStatus()), this, + SLOT(onSummarizeRepositoryStatus()), Qt::QueuedConnection); + connect(this, SIGNAL(sendCmdSendVersionToIsmas()), this, + SLOT(onSendCmdSendVersionToIsmas()), Qt::QueuedConnection); + connect(this, SIGNAL(summarizeUpload(QStringList)), this, + SLOT(onSummarizeUpload(QStringList)), Qt::QueuedConnection); + connect(this, SIGNAL(handleChangedFiles(QStringList)), this, + SLOT(onHandleChangedFiles(QStringList)), Qt::QueuedConnection); + connect(this, SIGNAL(finishUpdateProcess(bool)), this, + SLOT(onFinishUpdateProcess(bool)), Qt::QueuedConnection); + connect(this, SIGNAL(terminateUpdateProcess()), this, + SLOT(onTerminateUpdateProcess()), Qt::QueuedConnection); //connect(this, SIGNAL(workNow()), this, SLOT(work()), Qt::QueuedConnection); - connect(&m_timer, SIGNAL(timeout()), this, SLOT(runUpdate()), Qt::QueuedConnection); - m_timer.setSingleShot(true); - m_timer.start(1000); + connect(&m_startUpdateProcess, SIGNAL(timeout()), this, SLOT(askIsmasForNewData()), Qt::QueuedConnection); + m_startUpdateProcess.setSingleShot(true); + m_startUpdateProcess.start(1000); + connect(&m_waitForNewUpdates, SIGNAL(timeout()), this, SLOT(askIsmasForNewData()), Qt::QueuedConnection); + m_waitForNewUpdates.setSingleShot(false); + + m_machineNr = 996; + m_customerNr = 281; } Worker::~Worker() { @@ -68,34 +101,233 @@ Worker::~Worker() { } } -void Worker::onExecuteOpkgCommands() { - qCritical() << "ON EXECUTE OPKG COMMANDS"; +void Worker::onHandleChangedFiles(QStringList changedFiles) { + qCritical() << QDir::currentPath() << "ON HANDLE CHANGED FILES" << changedFiles; + if (QDir(m_customerRepository).exists()) { + if (QDir::setCurrent(m_customerRepository)) { + QString const params("--recursive " + "--progress " + "--checksum " + "--exclude=.* " + "--include=*.bin " + "--include=*.json " + "--include=opkg_commands " + "--include=*.ini"); + QStringList cmds; + cmds << QString("rsync ") + params.simplified() + " etc/ /etc"; + cmds << QString("rsync ") + params.simplified() + " opt/ /opt"; + + QString cmd; + bool error = false; + foreach (cmd, cmds) { + if (!error) { + Command c("bash"); + qInfo() << "EXCUTING CMD..." << cmd; + if (c.execute(m_customerRepository, QStringList() << "-c" << cmd)) { + qDebug() << c.getCommandResult(); + } else { + qCritical() << "CMD" << cmd << "FAILED"; + error = true; + } + } + } + if (!error) { + onFinishUpdateProcess(true); + return; + } + } + } + onTerminateUpdateProcess(); +} + +void Worker::onSummarizeUpload(QStringList changedFiles) { + QDateTime const c = QDateTime::currentDateTime(); + QDate const d = c.date(); + QTime const t = c.time(); + + QString uploadHistoryFile = QString("upload_history_%1%2%3T%4%5%6.txt") + .arg(d.year()).arg(d.month()).arg(d.day()) + .arg(t.hour()).arg(t.minute()).arg(t.second()); + + QFile f(uploadHistoryFile); + if (f.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&f); + QString fName; + foreach (fName, changedFiles) { + QString lastCommit = m_gc.gitLastCommit(fName); + out << fName << ":" << lastCommit << "\n"; + } + } else { + // TODO: error an ISMAS + } +} + +void Worker::onSummarizeRepositoryStatus() { + // TODO + QString dir("/opt/app/tools/atbupdate/customer_999"); + QDirIterator it(dir, QStringList() << "*.jpg", + QDir::Files, QDirIterator::Subdirectories); + while (it.hasNext()) { + qDebug() << it.next(); + if (m_gc.gitIsFileTracked(it.next())) { + QString lastCommit = m_gc.gitLastCommit(it.next()); + } + } + + /* + QString repoStatusHistoryFile = QString("repo_status_history_%1%2%3T%4%5%6.txt") + .arg(d.year()).arg(d.month()).arg(d.day()) + .arg(t.hour()).arg(t.minute()).arg(t.second()); + if (f.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&f); + QString fName; + foreach (fName, changedFiles) { + QString lastCommit = m_gc.gitLastCommit(fName); + out << fName << ":" << lastCommit << "\n"; + } + } else { + // TODO: error an ISMAS + } + */ +} + +void Worker::onExecuteOpkgCommands(QStringList opkgCommands) { + QString opkgCommand; + foreach (opkgCommand, opkgCommands) { + emit this->executeOpkgCommand(opkgCommand); + } +} + +void Worker::onExecuteOpkgCommand(QString opkgCommand) { + Command c(opkgCommand); + if (c.execute(m_workingDirectory)) { + QString const r = c.getCommandResult(); + qDebug() << opkgCommand << ": RESULT" << r; + } } // sollte ParameterResponse heissen void Worker::onIsmasResponseReceived(QJsonObject ismasResponse) { - QJsonValue v = ismasResponse.value("TRG"); - if (v.type() == QJsonValue::String) { - QString s = v.toString(); - if (s == "WAIT") { - // updates available - // git anwerfen - qCritical() << "GIT ANWERFEN"; - emit m_gc.ismasUpdatesAvailable(); + if (!ismasResponse.isEmpty()) { + QStringList const keys = ismasResponse.keys(); + static QRegularExpression re("^REQ_ISMASPARAMETER.*"); + if(keys.indexOf(re) >= 0) { + m_waitForNewUpdates.stop(); // stop asking ISMAS for updates + + // sanity check: cust_nr and machine_nr of PSA correct ? + if (keys.contains("Dev_ID", Qt::CaseInsensitive)) { + QJsonObject const devId = ismasResponse["Dev_ID"].toObject(); + QStringList const keys = devId.keys(); + if (keys.contains("Custom_ID") && keys.contains("Device_ID")) { + QJsonValue const c = devId.value("Custom_ID"); + QJsonValue const m = devId.value("Device_ID"); + int customerNr = c.toInt(-1); + int machineNr = m.toInt(-1); + if (customerNr != m_customerNr) { + qCritical() << "CUSTOMER-NR (" << customerNr << ") !=" + << "LOCAL CUSTOMER-NR (" << m_customerNr << ")"; + m_updateStatus = UPDATE_STATUS::ERROR_BACKEND; + return; + } + if (machineNr != m_machineNr) { + qCritical() << "MACHINE-NR (" << machineNr << ") !=" + << "LOCAL MACHINE-NR (" << m_machineNr << ")"; + m_updateStatus = UPDATE_STATUS::ERROR_BACKEND; + return; + } + } + } + if (keys.contains("Fileupload", Qt::CaseInsensitive)) { + QJsonObject fileUpload = ismasResponse["Fileupload"].toObject(); + QJsonValue v = fileUpload.value("TRG"); + if (!v.isNull() && !v.isUndefined()) { + QString const s = v.toString(""); + if (s == "WAIT") { + m_ismasUpdateRequests = ISMAS_UPDATE_REQUESTS; + qCritical() << "ISMAS UPDATES AVAILABLE"; + emit m_gc.ismasUpdatesAvailable(); + } + } + } } } - - //m_workerThread.quit(); - //QApplication::quit(); } -void Worker::runUpdate() { - QThread::sleep(2); +void Worker::onFinishUpdateProcess(bool changes) { + qCritical() << "ON FINISH UPDATE PROCESS. CHANGES=" << changes; + m_workerThread.quit(); + QApplication::quit(); +} - IsmasClient is; - QString data = is.setUpdatesAvailable(); - m_apismClient.sendUpdateInfoToIsmas(data); +void Worker::onTerminateUpdateProcess() { + qCritical() << "ON TERMINATE UPDATE PROCESS"; + m_workerThread.quit(); + QApplication::quit(); +} + +void Worker::onSendCmdSendVersionToIsmas() { + + QString const tariffVersion = "0.0.1"; + QString const tariffProject = "test_project"; + int tariffZone = 1; + QString const tariffInfo = "test_tariff_info"; + QString const tariffLoadTime = QDateTime::currentDateTime().toString(Qt::ISODateWithMs); + QString const linuxVersion = "test_linux_version"; + QString const cpuSerial = "test_cpu_serial"; + QString const deviceControllerVersion = "test_dc_version"; + QString const deviceControllerGitBlob = "test_dc_blob_2a3b4f50"; + QString const deviceControllerGitLastCommit = "test_dc_commit_12345abc"; + QString const raucVersion = "test_rauc_version"; + QString const opkgVersion = "test_opkg_version"; + QString const atbQTVersion = "test_qtbqt_version"; + QString const atbQTGitDescribe = "test_atbqt_git_describe"; + QString const deviceControllerPluginVersion = "test_CAmaster_version"; + QString const ingenicoISelfCCPluginVersion = "test_ingenico_plugin_version"; + QString const mobilisisCalculatePricePluginVersion = "test_mobilisis_plugin_version"; + QString const mobilisisCalculatePriceConfigUiVersion = "test_mobilisis_config_ui_plugin"; + QString const prmCalculatePricePluginVersion = "test_prm_calculate_price_plugin"; + QString const prmCalculatePriceConfigUiPluginVersion = "test_prm_calculate_price_config_ui_plugin"; + QString const tcpZVTPluginVersion = "test_tcp_zvt_plugin"; + + QString data = m_ismasClient.updateOfPSASendVersion(tariffVersion, + tariffProject, + tariffZone, + tariffInfo, + tariffLoadTime, + linuxVersion, + cpuSerial, + deviceControllerVersion, + deviceControllerGitBlob, + deviceControllerGitLastCommit, + raucVersion, + opkgVersion, + atbQTVersion, + atbQTGitDescribe, + deviceControllerPluginVersion, + ingenicoISelfCCPluginVersion, + mobilisisCalculatePricePluginVersion, + mobilisisCalculatePriceConfigUiVersion, + prmCalculatePricePluginVersion, + prmCalculatePriceConfigUiPluginVersion, + tcpZVTPluginVersion); + m_apismClient.sendCmdSendVersionToIsmas(data); +} + +void Worker::askIsmasForNewData() { + if (m_maintenanceMode) { + QString data = m_ismasClient.setUpdatesAvailable(); + m_apismClient.sendUpdateInfoToIsmas(data); + } m_apismClient.requestAvailableIsmasUpdates(); + + if (--m_ismasUpdateRequests > 0) { + // if the timer is already running, it will be stopped and restarted. + m_waitForNewUpdates.start(10000); + } else { + qCritical() << "REQUESTING ISMAS FOR UPDATES TIMED OUT"; + m_workerThread.quit(); + QApplication::quit(); + } } diff --git a/worker.h b/worker.h index 6070972..fca8b6b 100644 --- a/worker.h +++ b/worker.h @@ -3,9 +3,11 @@ #include #include +#include #include #include #include +#include #include "worker_thread.h" #include "update.h" @@ -25,14 +27,37 @@ class Worker : public QObject { Q_OBJECT WorkerThread m_workerThread; - QTimer m_timer; + QTimer m_startUpdateProcess; Update *m_update; ApismClient m_apismClient; GitClient m_gc; + QString const m_customerId; + QString const m_workingDirectory; + QString const m_branchName; + QString const m_customerRepository; + bool m_maintenanceMode; + int m_ismasUpdateRequests; + QTimer m_waitForNewUpdates; + IsmasClient m_ismasClient; + + int m_machineNr; // setzen + int m_customerNr; + + + enum { ISMAS_UPDATE_REQUESTS = 6 }; + + enum class UPDATE_STATUS : quint8 { + STARTED, + STOPPED, + ERROR_BACKEND + } m_updateStatus; public: explicit Worker(hwinf *hw, QString update_ctrl_file, + QString repositoryPath, + QString customerId, + QString branchName, QString workingDir = ".", bool maintenanceMode = false, bool testMode = false, @@ -45,14 +70,31 @@ public: void quit() { return m_workerThread.quit(); } signals: - void executeOpkgCommands(); + void executeOpkgCommands(QStringList); + void executeOpkgCommand(QString); + void handleChangedFiles(QStringList); + void summarizeUpload(QStringList); + void summarizeRepositoryStatus(); + void sendCmdSendVersionToIsmas(); + void finishUpdateProcess(bool changes); + void terminateUpdateProcess(); public slots: void onIsmasResponseReceived(QJsonObject ismasResponse); - void onExecuteOpkgCommands(); + void onExecuteOpkgCommands(QStringList opkgCommands); + void onExecuteOpkgCommand(QString opkgCommand); private slots: - void runUpdate(); + void askIsmasForNewData(); + void onSendCmdSendVersionToIsmas(); + void onSummarizeRepositoryStatus(); + void onFinishUpdateProcess(bool changes); + void onTerminateUpdateProcess(); + void onSummarizeUpload(QStringList); + void onHandleChangedFiles(QStringList); }; +//Q_DECLARE_METATYPE((QHash)) +//Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash) + #endif // WORKER_H_INCLUDED