ATBUpdateTool/worker.cpp
Gerhard Hoffmann f5198efab3 Added worker/worker-thread-pair.
Worker uses event-loop of worker-thread.
Worker itself is used as work-horse for the update-process.
2023-07-14 13:32:00 +02:00

334 lines
14 KiB
C++

#include "worker.h"
#include "update.h"
#include <QCoreApplication>
#include <QApplication>
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
#include <QDir>
#include <QDirIterator>
#include <QThread>
#include <QRegularExpression>
#include <QDateTime>
#include <QString>
#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 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) // 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);
m_workerThread.start();
int cnt = 0;
while (!m_workerThread.isRunning()) {
if (++cnt > 5) {
qCritical() << "starting worker thread FAILED";
return;
}
QThread::sleep(1);
}
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(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_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() {
int cnt = 0;
m_workerThread.quit();
while (!m_workerThread.isFinished()) {
if (!m_workerThread.wait(1000)) {
if (++cnt > 5) {
qCritical() << "stopping worker thread FAILED";
return;
}
}
}
if (m_update) {
delete m_update;
}
}
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) {
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();
}
}
}
}
}
}
void Worker::onFinishUpdateProcess(bool changes) {
qCritical() << "ON FINISH UPDATE PROCESS. CHANGES=" << changes;
m_workerThread.quit();
QApplication::quit();
}
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();
}
}