1588 lines
71 KiB
C++
1588 lines
71 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 <QMessageBox>
|
|
#include <QPushButton>
|
|
#include <QJsonParseError>
|
|
#include <Qt>
|
|
#include <QScopedPointer>
|
|
#include <QRegularExpression>
|
|
#include <QJsonArray>
|
|
|
|
#include "message_handler.h"
|
|
#include <DeviceController/interfaces.h>
|
|
#include "ismas/ismas_client.h"
|
|
#include "progress_event.h"
|
|
#include "mainwindow.h"
|
|
#include "utils.h"
|
|
#include "process/command.h"
|
|
|
|
QString const Worker::UPDATE_STEP_OK ( " [ ok]");
|
|
QString const Worker::UPDATE_STEP_DONE ( " [done]");
|
|
QString const Worker::UPDATE_STEP_WRONG ( "[WRONG]");
|
|
QString const Worker::UPDATE_STEP_FAIL ( " [FAIL]");
|
|
QString const Worker::UPDATE_STEP_SUCCESS(" [SUCCESS]");
|
|
|
|
bool Worker::sendLastVersionOnce = false;
|
|
|
|
using UPDATE_STEP = Worker::UPDATE_STEP;
|
|
const QMap<UPDATE_STEP, const char*> Worker::smap (
|
|
std::initializer_list<std::pair<UPDATE_STEP, const char*>>{
|
|
#define INSERT_ELEMENT(p) std::pair(p, #p)
|
|
INSERT_ELEMENT(UPDATE_STEP::STARTED),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_REPOSITORY),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_REPOSITORY_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_REPOSITORY_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_SANITY),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_SANITY_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_SANITY_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::REPOSITORY_RECOVERED_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::REPOSITORY_RECOVERED_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::CLONE_REPOSITORY),
|
|
INSERT_ELEMENT(UPDATE_STEP::CLONE_REPOSITORY_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CLONE_REPOSITORY_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECKOUT_REPOSITORY),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECKOUT_REPOSITORY_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECKOUT_REPOSITORY_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_ISMAS_TRIGGER),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_ISMAS_TRIGGER_WRONG_VALUE),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::INITIAL_CLONE_WITHOUT_ACTIVE_ISMAS_TRIGGER),
|
|
INSERT_ELEMENT(UPDATE_STEP::INITIAL_CLONE_WITH_ACTIVE_ISMAS_TRIGGER),
|
|
INSERT_ELEMENT(UPDATE_STEP::PULL_NEW_BRANCH),
|
|
INSERT_ELEMENT(UPDATE_STEP::PULL_NEW_BRANCH_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::PULL_NEW_BRANCH_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECKOUT_BRANCH),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECKOUT_BRANCH_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECKOUT_BRANCH_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_REPOSITORY),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_REPOSITORY_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_REPOSITORY_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_FOR_REPOSITORY_CHANGES),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_FOR_REPOSITORY_CHANGES_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::CHECK_FOR_REPOSITORY_CHANGES_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::FILES_TO_UPDATE),
|
|
INSERT_ELEMENT(UPDATE_STEP::FILES_TO_DOWNLOAD),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMANDS),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_1),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_2),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_3),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_4),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_5),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_6),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_7),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_8),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_9),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_LAST),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::EXEC_OPKG_COMMAND_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY),
|
|
INSERT_ELEMENT(UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::SAVE_LOGS),
|
|
INSERT_ELEMENT(UPDATE_STEP::SAVE_LOGS_SUCCESS),
|
|
INSERT_ELEMENT(UPDATE_STEP::SAVE_LOGS_FAILURE),
|
|
INSERT_ELEMENT(UPDATE_STEP::SEND_LAST_VERSION),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_FINALIZE),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_SUCCEEDED),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_NOT_NECESSARY),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_FAILED),
|
|
INSERT_ELEMENT(UPDATE_STEP::UPDATE_ACTIVATED),
|
|
INSERT_ELEMENT(UPDATE_STEP::FINISHED),
|
|
INSERT_ELEMENT(UPDATE_STEP::DEBUG),
|
|
INSERT_ELEMENT(UPDATE_STEP::ERROR),
|
|
INSERT_ELEMENT(UPDATE_STEP::NONE)
|
|
#undef INSERT_ELEMENT
|
|
});
|
|
|
|
Worker *Worker::instance = nullptr;
|
|
|
|
Worker::Worker(int customerNr,
|
|
int machineNr,
|
|
int zoneNr,
|
|
QString repositoryUrl,
|
|
QString branchName,
|
|
QString pluginDir,
|
|
QString pluginName,
|
|
QString workingDirectory,
|
|
bool noUpdatePsaHardware,
|
|
bool alwaysDownloadConfig,
|
|
bool alwaysDownloadDC,
|
|
bool dryRun,
|
|
QObject *parent,
|
|
char const *serialInterface,
|
|
char const *baudrate)
|
|
: m_customerNr(customerNr)
|
|
, m_customerNrStr(QString("customer_") + QString::number(m_customerNr))
|
|
, m_machineNr(machineNr)
|
|
, m_zoneNr(zoneNr)
|
|
, m_pluginDir(pluginDir)
|
|
, m_pluginName(pluginName)
|
|
, m_workingDirectory(workingDirectory)
|
|
, m_branchName(branchName)
|
|
, m_customerRepositoryPath(QString("%1/%2.git").arg(repositoryUrl).arg(m_customerNrStr))
|
|
, m_customerRepository(QDir::cleanPath(m_workingDirectory + QDir::separator() + m_customerNrStr))
|
|
, m_noUpdatePsaHardware(noUpdatePsaHardware)
|
|
, m_alwaysDownloadConfig(alwaysDownloadConfig)
|
|
, m_alwaysDownloadDC(alwaysDownloadDC)
|
|
, m_dryRun(dryRun)
|
|
, m_parent(parent)
|
|
, m_serialInterface(serialInterface)
|
|
, m_baudrate(baudrate)
|
|
, m_gc(m_customerRepositoryPath, m_customerNrStr, m_customerRepository, m_workingDirectory, m_branchName, this)
|
|
, m_versionInfo(QStringList())
|
|
, m_osVersion(getOsVersion())
|
|
, m_atbqtVersion(getATBQTVersion())
|
|
, m_atbUpdateToolVersion(getATBUpdateToolVersion())
|
|
, m_cpuSerial(getCPUSerial())
|
|
, m_pluginVersionATBDeciceController(getPluginVersion("/opt/app/ATBAPP/plugins/libATBDeviceControllerPlugin.so"))
|
|
, m_pluginVersionIngenicoISelf(getPluginVersion("/opt/app/ATBAPP/plugins/libIngenicoISelf_CCPlugin.so"))
|
|
, m_pluginVersionMobilisisCalc(getPluginVersion("/opt/app/ATBAPP/plugins/libMOBILISIS_CalculatePricePlugin.so"))
|
|
, m_pluginVersionMobilisisCalcConfig(getPluginVersion("/opt/app/ATBAPP/plugins/libMOBILISIS_CalculatePricePlugin_ConfigUi.so"))
|
|
, m_pluginVersionPrmCalc(getPluginVersion("/opt/app/ATBAPP/plugins/libPRM_CalculatePricePlugin.so"))
|
|
, m_pluginVersionPrmCalcConfig(getPluginVersion("/opt/app/ATBAPP/plugins/libPRM_CalculatePricePlugin_ConfigUi.so"))
|
|
, m_pluginVersionTcpZvt(getPluginVersion("/opt/app/ATBAPP/plugins/libTCP_ZVT_CCPlugin.so"))
|
|
, m_ismasUpdateRequests(ISMAS_UPDATE_REQUESTS)
|
|
, m_waitForNewUpdates(this)
|
|
, m_filesToUpdate()
|
|
, m_updateProcessRunning(true)
|
|
, m_mainWindow(nullptr) /* contains plugin */
|
|
, m_dcDownloadFirmware(new Command("/opt/app/tools/atbupdate/ATBDownloadDCFirmware --read-dc-version true"))
|
|
//, m_withoutIsmasDirectPort(true) /* useful for testing */ {
|
|
, m_withoutIsmasDirectPort(false) /* useful for testing */ {
|
|
|
|
|
|
m_start = QDateTime::currentDateTime();
|
|
m_dcDownloadFirmware->setWorker(this);
|
|
|
|
// TODO: turn object into singleton
|
|
instance = this;
|
|
m_lastFailedUpdateStep = UPDATE_STEP::NONE;
|
|
|
|
if (m_noUpdatePsaHardware == false) {
|
|
m_update = new Update(this,
|
|
QDir::cleanPath(m_workingDirectory + QDir::separator() + m_customerNrStr),
|
|
m_customerNrStr,
|
|
m_branchName,
|
|
m_pluginDir,
|
|
m_pluginName,
|
|
m_workingDirectory);
|
|
}
|
|
|
|
this->setObjectName("worker-object");
|
|
QDir::setCurrent(m_workingDirectory);
|
|
|
|
m_apismVersion = getAPISMYoctoVersion();
|
|
}
|
|
|
|
Worker::~Worker() {
|
|
if (m_update != nullptr) {
|
|
delete m_update;
|
|
m_update = nullptr;
|
|
}
|
|
}
|
|
|
|
void Worker::displayProgressInMainWindow(int progress) {
|
|
if (m_mainWindow) {
|
|
QApplication::postEvent(m_mainWindow,
|
|
new ProgressEvent(this, progress));
|
|
}
|
|
}
|
|
|
|
void Worker::setProgress(int progress) {
|
|
m_ismasClient.setProgressInPercent(progress);
|
|
displayProgressInMainWindow(progress);
|
|
}
|
|
|
|
|
|
void Worker::startProgressLoop() {
|
|
displayProgressInMainWindow(MainWindow::START_PROGRESS_LOOP);
|
|
}
|
|
|
|
void Worker::stopProgressLoop() {
|
|
displayProgressInMainWindow(MainWindow::STOP_PROGRESS_LOOP);
|
|
}
|
|
|
|
static std::once_flag once;
|
|
void Worker::run() {
|
|
// user should not start the update process several times
|
|
std::call_once(once, &Worker::privateUpdate, this);
|
|
}
|
|
|
|
bool Worker::isRepositoryCorrupted() {
|
|
QDir customerRepository(m_customerRepository);
|
|
if (customerRepository.exists()) {
|
|
QDir customerRepositoryGit(QDir::cleanPath(m_customerRepository + QDir::separator() + ".git/"));
|
|
if (!m_gc.gitFsck()) {
|
|
// should never happen
|
|
Utils::printCriticalErrorMsg("CORRUPTED CUSTOMER REPOSITORY: GIT_FSCK FAILED");
|
|
return true;
|
|
}
|
|
// .git-directory inside git-repository does not exist, which means the
|
|
// git-repository is corrupted -> remove it and start from scratch
|
|
if (!customerRepositoryGit.exists()) {
|
|
// should never happen
|
|
Utils::printCriticalErrorMsg("CORRUPTED CUSTOMER REPOSITORY .GIT DOES NOT EXIST");
|
|
return true;
|
|
}
|
|
QDir customerRepositoryEtc(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/"));
|
|
if (!customerRepositoryEtc.exists()) {
|
|
// should never happen
|
|
Utils::printCriticalErrorMsg(QString("CORRUPTED CUSTOMER REPOSITORY %1/etc DOES NOT EXIST").arg(m_customerRepository));
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Worker::repairCorruptedRepository() {
|
|
QDir customerRepository(m_customerRepository);
|
|
if (!customerRepository.removeRecursively()) {
|
|
|
|
Utils::printCriticalErrorMsg("ERROR REMOVING CORR. CUST-REPOSITORY");
|
|
|
|
//m_updateStatus = UpdateStatus(UPDATE_STATUS::REMOVE_GIT_REPOSITORY_FAILED,
|
|
// QString("REMOVAL OF GIT-REPOSITORY %1 FAILED").arg(m_customerRepository));
|
|
//IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
|
|
// QString("#M=APISM#C=CMD_EVENT#J=") +
|
|
// m_ismasClient.sanityCheckFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
|
|
// m_updateStatus.m_statusDescription));
|
|
//emit showErrorMessage("apism sanity check", m_updateStatus.m_statusDescription);
|
|
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Worker::privateUpdate() {
|
|
if (!m_mainWindow) {
|
|
Utils::printCriticalErrorMsg("m_mainWindow NOT SET");
|
|
return;
|
|
}
|
|
|
|
return;
|
|
|
|
QString func(__PRETTY_FUNCTION__);
|
|
|
|
GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::STARTED));
|
|
|
|
QScopedPointer<UpdateProcessRunning> upr(new UpdateProcessRunning(this));
|
|
QStringList lst;
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CHECK UPDATE TRIGGER
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// NOTE: make sure that nothing is sent to ISMAS during updateTriggerSet
|
|
ISMAS() << UPDATE_STEP::CHECK_ISMAS_TRIGGER;
|
|
m_ismasTriggerActive = false;
|
|
m_updateNotNecessary = false;
|
|
|
|
if (QDir(m_customerRepository).exists()) { // ignore a possibly corrupted repository
|
|
m_ismasTriggerActive = updateTriggerSet();
|
|
if (m_ismasTriggerActive == false) {
|
|
QDateTime const ¤t = QDateTime::currentDateTime();
|
|
m_automaticUpdate = (current.time().hour() < 4);
|
|
m_versionInfo = m_gc.gitShowReason(m_branchName);
|
|
|
|
qCritical() << "***";
|
|
qCritical() << "privateUpdate ............. m_versionInfo:" << m_versionInfo;
|
|
qCritical() << "privateUpdate ......... m_automaticUpdate:" << m_automaticUpdate;
|
|
|
|
if (m_automaticUpdate) { // update has been triggered within [00:00:00, 00:03:59]
|
|
m_updateNotNecessary = true;
|
|
m_ismasTriggerStatusMessage = QStringList(QString("NO UPDATE NECESSARY (%1)").arg(current.toString(Qt::ISODate)));
|
|
|
|
qCritical() << "privateUpdate m_ismasTriggerStatusMessage:"
|
|
<< QStringList(m_ismasTriggerStatusMessage);
|
|
qCritical() << "***";
|
|
|
|
// the customer-repository does exist, and the ISMAS-trigger is
|
|
// *NOT* "WAIT", but from 00:00:00 - 00:03:59 this counts as an
|
|
// automatic update
|
|
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
// trigger message to ISMAS and CONSOLE
|
|
CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS);
|
|
// overwrite m_lastFailedUpdateStep
|
|
m_lastFailedUpdateStep = UPDATE_STEP::NONE;
|
|
return;
|
|
}
|
|
|
|
qCritical() << "***";
|
|
|
|
// the customer-repository does exist, but the ISMAS-trigger is
|
|
// *NOT* "WAIT", so STOP the update procedure
|
|
return;
|
|
}
|
|
// the customer-repository does exist, and the ISMAS-trigger is "WAIT",
|
|
// so continue the update procedure
|
|
} else {
|
|
// the customer-repository does not exist, so PROCEED with the
|
|
// update procedure, even if ISMAS-trigger is not correctly set ("WAIT")
|
|
}
|
|
|
|
emit this->disableExit();
|
|
|
|
QDir customerRepository(m_customerRepository);
|
|
|
|
CONSOLE() << (ISMAS() << UPDATE_STEP::CHECK_SANITY);
|
|
|
|
m_clone = false;
|
|
m_repairClone = false;
|
|
m_initialClone = false;
|
|
m_pulledNewBranch = false;
|
|
// the customer repository is cloned or
|
|
// repaired/re-cloned without checking the
|
|
// ISMAS-trigger (WAIT-)button.
|
|
|
|
// Case 1: no existing repository:
|
|
|
|
// if there was a sane repository
|
|
// available, then the trigger-button is
|
|
// checked:
|
|
// 1: trigger == WAIT: then
|
|
// have been activated in ISMAS.
|
|
|
|
bool continueUpdate = true; // check if git-clone command has timed-out,
|
|
// resulting in a corrupted git-repository, which
|
|
// does not contain an ./etc-directory
|
|
|
|
if (isRepositoryCorrupted()) { // a not-existing repository is not meant
|
|
// to be corrupted
|
|
CONSOLE() << (ISMAS() << UPDATE_STEP::CHECK_SANITY_FAILURE);
|
|
if ((continueUpdate = repairCorruptedRepository()) == true) {
|
|
m_repairClone = true;
|
|
CONSOLE() << (ISMAS() << UPDATE_STEP::REPOSITORY_RECOVERED_SUCCESS);
|
|
} else {
|
|
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::REPOSITORY_RECOVERED_FAILURE));
|
|
return;
|
|
}
|
|
}
|
|
|
|
CONSOLE() << (ISMAS() << UPDATE_STEP::CHECK_SANITY_SUCCESS);
|
|
|
|
if (continueUpdate) {
|
|
if ((continueUpdate = customerRepository.exists()) == false) {
|
|
m_initialClone = (m_repairClone == false);
|
|
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY));
|
|
for (int i = 0; i < 5; ++i) { // try to checkout git repository
|
|
setProgress(i); // and switch to branch
|
|
if (m_gc.gitCloneAndCheckoutBranch()) {
|
|
if (!isRepositoryCorrupted()) {
|
|
m_versionInfo = m_gc.gitShowReason(m_branchName);
|
|
GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY_SUCCESS));
|
|
continueUpdate = true;
|
|
m_clone = true;
|
|
break;
|
|
}
|
|
}
|
|
QThread::sleep(1); // maybe git needs more time
|
|
}
|
|
|
|
if (continueUpdate == false) {
|
|
GUI() << (ISMAS() << (CONSOLE() << (m_lastFailedUpdateStep = UPDATE_STEP::CLONE_REPOSITORY_FAILURE)));
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT_X(m_clone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "clone failed");
|
|
|
|
} else {
|
|
|
|
Q_ASSERT_X(!m_clone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "m_clone not false");
|
|
Q_ASSERT_X(!m_initialClone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "m_initialClone not false");
|
|
Q_ASSERT_X(!m_repairClone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "m_repairClone not false");
|
|
|
|
CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY;
|
|
if (isRepositoryCorrupted()) {
|
|
ISMAS() << (GUI() << (CONSOLE() << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_REPOSITORY_FAILURE)));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
m_versionInfo = m_gc.gitShowReason(m_branchName);
|
|
|
|
CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_SUCCESS;
|
|
setProgress(_CHECKOUT_REPOSITORY_SUCCESS);
|
|
|
|
if (m_clone == false) {
|
|
if (m_ismasTriggerActive == false) {
|
|
return;
|
|
} else {
|
|
GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS));
|
|
setProgress(_CHECK_ISMAS_TRIGGER_SUCCESS);
|
|
}
|
|
} else {
|
|
if (m_initialClone) {
|
|
GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::INITIAL_CLONE_WITHOUT_ACTIVE_ISMAS_TRIGGER));
|
|
}
|
|
}
|
|
|
|
if (m_ismasTriggerActive == false) {// make it explicit again: only if the
|
|
// ismas trigger is active ('WAIT'),
|
|
// then proceed
|
|
|
|
if (m_clone == false) { // if it is an (initial) clone, then
|
|
return; // run the whole update process:
|
|
} // sync tariff-files, download jsons,
|
|
} // download device controller
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CHECK-OUT BRANCH
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
if ((continueUpdate = customerEnvironment()) == false) {
|
|
// even if something goes wrong creating the environment, try to execute
|
|
// opkg_commands
|
|
if (QDir(m_customerRepository).exists()) {
|
|
// always execute contents of opkg_commands-file
|
|
m_filesToUpdate.clear();
|
|
m_filesToUpdate << "etc/psa_update/opkg_commands";
|
|
execOpkgCommands();
|
|
}
|
|
return;
|
|
}
|
|
m_versionInfo = m_gc.gitShowReason(m_branchName);
|
|
lst = QStringList(QString(smap[UPDATE_STEP::CHECKOUT_BRANCH_SUCCESS]));
|
|
ISMAS(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECKOUT_BRANCH);
|
|
setProgress(_CHECKOUT_BRANCH_SUCCESS);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// COMPUTE CHANGED FILES OF CUSTOMER REPOSITORY
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
if ((continueUpdate = filesToUpdate()) == false) {
|
|
// even if something goes wrong in filesToUpdate, try to execute
|
|
// opkg_commands
|
|
if (QDir(m_customerRepository).exists()) {
|
|
// always execute contents of opkg_commands-file
|
|
m_filesToUpdate.clear();
|
|
m_filesToUpdate << "etc/psa_update/opkg_commands";
|
|
execOpkgCommands();
|
|
}
|
|
return;
|
|
}
|
|
m_versionInfo = m_gc.gitShowReason(m_branchName);
|
|
lst = QStringList(QString(smap[UPDATE_STEP::UPDATE_REPOSITORY_SUCCESS]));
|
|
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_REPOSITORY));
|
|
setProgress(_UPDATE_REPOSITORY_SUCCESS);
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (R)SYNC THE REPOSITORY WITH THE LOCAL FILEYSTEM
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
if ((continueUpdate = syncCustomerRepositoryAndFS()) == false) {
|
|
// even if something goes wrong with rsync, try to execute
|
|
// opkg_commands
|
|
if (QDir(m_customerRepository).exists()) {
|
|
// always execute contents of opkg_commands-file
|
|
m_filesToUpdate.clear();
|
|
m_filesToUpdate << "etc/psa_update/opkg_commands";
|
|
execOpkgCommands();
|
|
}
|
|
return;
|
|
}
|
|
lst = QStringList(QString(smap[UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS]));
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS));
|
|
setProgress(_SYNC_CUSTOMER_REPOSITORY_SUCCESS);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// EXECUTE OPKG COMMANDS
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
if ((continueUpdate = execOpkgCommands()) == false) {
|
|
return;
|
|
}
|
|
lst = QStringList(QString(smap[UPDATE_STEP::EXEC_OPKG_COMMAND_SUCCESS]));
|
|
GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::EXEC_OPKG_COMMANDS);
|
|
setProgress(_EXEC_OPKG_COMMAND_SUCCESS);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UPDATE THE PSA USING THE CHANGED FILES
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
if ((continueUpdate = downloadFilesToPSAHardware()) == false) {
|
|
return;
|
|
}
|
|
lst = QStringList(QString("DONE"));
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS));
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FUTURE: SAVE LOG FILES
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
if ((continueUpdate = saveLogFile()) == false) {
|
|
return;
|
|
}
|
|
// ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::SAVE_LOGS_SUCCESS));
|
|
setProgress(_SAVE_LOGS_SUCCESS);
|
|
|
|
// final messages: see destructor of UpdateProcessRunning subclass
|
|
m_lastFailedUpdateStep = UPDATE_STEP::NONE;
|
|
}
|
|
|
|
bool Worker::updateTriggerSet() {
|
|
// repository is existent and not corrupted. check now if the ISMAS-trigger
|
|
// (WAIT-button) is activated even in case of initial checkout
|
|
static const QString func = "UPDATE-TRIGGER-SET";
|
|
|
|
// if (m_withoutIsmasDirectPort) { // useful for testing
|
|
// return true;
|
|
//}
|
|
|
|
m_ismasTriggerStatusMessage.clear();
|
|
|
|
GUI() << (CONSOLE() << UPDATE_STEP::CHECK_ISMAS_TRIGGER);
|
|
|
|
bool const automaticUpdate = (QDateTime::currentDateTime().time().hour() < 4);
|
|
|
|
QString triggerValue("NOT CHECKED YET");
|
|
static constexpr int const repeats = 15;
|
|
for (int repeat = 1; repeat <= repeats; ++repeat) {
|
|
|
|
if (repeat > 1) {
|
|
int const startMs = QTime::currentTime().msecsSinceStartOfDay();
|
|
int const durationMs = QTime::currentTime().msecsSinceStartOfDay() - startMs;
|
|
QString const &s = QString("elapsed: %1.%2s").arg(durationMs / 1000).arg(durationMs % 1000);
|
|
QStringList lst = (m_ismasTriggerStatusMessage = (QStringList(func) << s));
|
|
CONSOLE(lst) << UPDATE_STEP::DEBUG;
|
|
} else {
|
|
QStringList lst = (m_ismasTriggerStatusMessage = (QStringList(func) << QString("-> REPEAT=%1 (%2)").arg(repeat).arg(repeats-repeat)));
|
|
CONSOLE(lst) << UPDATE_STEP::DEBUG;
|
|
}
|
|
|
|
if ((repeat % 8) == 0) {
|
|
CONSOLE(QStringList(func) << "RESTART APISM") << UPDATE_STEP::DEBUG;
|
|
Command c("systemctl restart apism");
|
|
if (c.execute("/tmp")) {
|
|
QThread::sleep(20); // give APISM some time to reconnect
|
|
QStringList lst = (m_ismasTriggerStatusMessage = (QStringList(func) << "RESTART APISM DONE"));
|
|
CONSOLE(lst) << UPDATE_STEP::DEBUG;
|
|
}
|
|
}
|
|
|
|
if (std::optional<QString> result
|
|
= IsmasClient::sendRequestReceiveResponse(
|
|
IsmasClient::APISM::DIRECT_PORT, "#M=APISM#C=REQ_ISMASPARAMETER#J={}")) {
|
|
|
|
QString const &msg = QString("APISM RESPONSE(%1)=(").arg(repeat) + result.value() + ")";
|
|
QStringList lst = (m_ismasTriggerStatusMessage = (QStringList(func) << msg));
|
|
CONSOLE(lst) << UPDATE_STEP::DEBUG;
|
|
|
|
QJsonParseError parseError;
|
|
QJsonDocument document(QJsonDocument::fromJson(result.value().toUtf8(), &parseError));
|
|
if (parseError.error != QJsonParseError::NoError) {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("INVALID JSON MSG: PARSING FAILED (json=<START>%1<END> error=[%2] str=[%3] offset=[%4])")
|
|
.arg(msg)
|
|
.arg(parseError.error)
|
|
.arg(parseError.errorString())
|
|
.arg(parseError.offset));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
if (!document.isObject()) {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("not a json-object %1").arg(result.value()));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
|
|
QJsonObject obj = document.object();
|
|
|
|
// always look for an 'error' first
|
|
if (obj.contains("error")) {
|
|
m_ismasTriggerStatusMessage = QStringList(obj.value("error").toString());
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
CONSOLE(QStringList(lst)) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
|
|
QThread::sleep(6);
|
|
continue;
|
|
}
|
|
// sanity check: cust_nr and machine_nr of PSA correct ?
|
|
// note: this check has to be done here, as the cust_nr and the machine_nr
|
|
// of the PSA are sent by ISMAS.
|
|
if (obj.contains("Dev_ID")) {
|
|
QJsonValue v = obj.value("Dev_ID");
|
|
if (v.isObject()) {
|
|
QJsonObject obj = v.toObject();
|
|
if (obj.contains("Custom_ID") && obj.contains("Device_ID")) {
|
|
int const customerNr = obj.value("Custom_ID").toInt(-1);
|
|
int const machineNr = obj.value("Device_ID").toInt(-1);
|
|
if (customerNr != m_customerNr) {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("CUSTOMER-NR (%1) != LOCAL CUSTOMER-NR (%2)")
|
|
.arg(customerNr).arg(m_customerNr));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
if (machineNr != m_machineNr) {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("MACHINE-NR (%1) != LOCAL MACHINE-NR (%2)")
|
|
.arg(machineNr).arg(m_machineNr));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
} else {
|
|
QStringList lst(QString("Dev_ID DOES NOT CONTAIN Custom_ID AND/OR Device_ID (LINE=%1)").arg(__LINE__));
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("Dev_ID KEY NOT A JSON-OBJECT (LINE=%1)").arg(__LINE__));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("Dev_ID KEY NOT AVAILABLE (LINE=%1)").arg(__LINE__));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
|
|
if (obj.contains("Fileupload")) {
|
|
QJsonValue v = obj.value("Fileupload");
|
|
if (v.isObject()) {
|
|
obj = v.toObject();
|
|
if (obj.contains("TRG")) {
|
|
if ((triggerValue = obj.value("TRG").toString()) == "WAIT") {
|
|
m_ismasTriggerStatusMessage = QStringList("ISMAS_UPDATE-TRIGGER SET TO WAIT");
|
|
m_ismasTriggerActive = true;
|
|
return m_ismasTriggerActive;
|
|
} else
|
|
if (QRegExp("\\s*").exactMatch(triggerValue)) { // check for whitespace
|
|
m_ismasTriggerStatusMessage = QStringList(QString("%1 EMPTY UPDATE TRIGGER (%2)").arg(repeat).arg(repeats-repeat));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
if (m_clone) {
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_WRONG_VALUE)));
|
|
// if the customer repository has just been cloned
|
|
return false; // it is OK the ISMAS trigger might not be 'WAIT'
|
|
}
|
|
// not a clone and empty update-trigger
|
|
if (automaticUpdate) {
|
|
// do not inform ISMAS in case of automatic update, because the
|
|
// update is not necessary as the trigger-button is not set to WAIT.
|
|
GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_WRONG_VALUE));
|
|
return false;
|
|
}
|
|
|
|
CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
|
|
|
|
QThread::sleep(6);
|
|
continue;
|
|
} else {
|
|
// if the download-button once has a wrong value, it will never recover
|
|
if (m_clone) {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("TRIGGER-VALUE='%1' != 'WAIT'").arg(triggerValue));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
if (automaticUpdate) {
|
|
// do not inform ISMAS in case of automatic update
|
|
GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_WRONG_VALUE));
|
|
} else {
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_WRONG_VALUE)));
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("TRIGGER-VALUE='%1' != 'WAIT'").arg(triggerValue));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
if (automaticUpdate) {
|
|
// do not inform ISMAS in case of automatic update
|
|
GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_WRONG_VALUE));
|
|
} else {
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("TRG key not available (LINE=%1)").arg(__LINE__));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("Fileupload not a json-object (LINE=%1)").arg(__LINE__));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("Fileupload not available (LINE=%1)").arg(__LINE__));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
} else {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("no ISMAS response (LINE=%1)").arg(__LINE__));
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
|
|
QThread::sleep(6);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (m_initialClone == false) {
|
|
if (!triggerValue.contains("WAIT", Qt::CaseInsensitive)) {
|
|
m_ismasTriggerStatusMessage = QStringList(QString("ISMAS_UPDATE-TRIGGER-NOT-SET-OR-WRONG: VALUE=(") + triggerValue + ")");
|
|
QStringList lst = m_ismasTriggerStatusMessage;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE)));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Worker::customerEnvironment() {
|
|
// configure customer environment -> checkout branch in case someone has
|
|
// changed the zone_nr
|
|
|
|
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::CHECKOUT_BRANCH));
|
|
|
|
if (QDir(m_customerRepository).exists()) {
|
|
if (m_clone == false) {
|
|
if (m_gc.branchExistsRemotely()) {
|
|
QString msg;
|
|
QStringList lst;
|
|
if (!m_gc.branchExistsLocally()) {
|
|
lst.clear();
|
|
msg = QString("PULLING OF NEW BRANCH " + m_branchName + " DOES NOT EXIST LOCALLY");
|
|
lst << msg;
|
|
CONSOLE(lst) << UPDATE_STEP::PULL_NEW_BRANCH;
|
|
if (!m_gc.gitPullNewBranches()) {
|
|
lst.clear();
|
|
msg = QString("PULLING OF NEW BRANCH " + m_branchName + " FAILED");
|
|
lst << msg;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::PULL_NEW_BRANCH_FAILURE)));
|
|
return false;
|
|
} else {
|
|
lst.clear();
|
|
msg = QString("PULLING OF NEW BRANCH " + m_branchName + " SUCCESS");
|
|
lst << msg;
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::PULL_NEW_BRANCH_SUCCESS)));
|
|
m_pulledNewBranch = true;
|
|
}
|
|
} else {
|
|
m_pulledNewBranch = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_gc.gitCheckoutBranch()) {
|
|
return true;
|
|
} else {
|
|
QStringList lst(QString("CHECKOUT OF " + m_customerRepository + "FAILED"));
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECKOUT_BRANCH_FAILURE)));
|
|
}
|
|
} else {// cannot happen
|
|
QStringList lst(QString(m_customerRepository + " DOES NOT EXIST"));
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECKOUT_BRANCH_FAILURE)));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Worker::filesToUpdate() {
|
|
// determine which files has to be updated: either sent to the hardware or
|
|
// rsynced with the filesystem in case of tariff-files
|
|
|
|
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_REPOSITORY));
|
|
|
|
// always execute contents of opkg_commands-file
|
|
m_filesToUpdate << "etc/psa_update/opkg_commands";
|
|
|
|
if ((m_clone || m_pulledNewBranch) && m_alwaysDownloadConfig) {
|
|
// always download all json-config files, even if none of them have been
|
|
// changed in the git repository. useful for first installation.
|
|
QDir dir(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_config"));
|
|
if (dir.exists()) {
|
|
QStringList jsons = dir.entryList(QStringList() << "DC2C*.json", QDir::Files);
|
|
if (!jsons.isEmpty()) {
|
|
for (QStringList::size_type i=0; i<jsons.size(); ++i) {
|
|
m_filesToUpdate << QDir::cleanPath(QString("etc/psa_config/") + jsons.at(i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((m_clone || m_pulledNewBranch) && m_alwaysDownloadConfig) {
|
|
// always download the last dc-binary, even if not changed in the
|
|
// git repository. useful for first installation.
|
|
QDir dir(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/dc"));
|
|
if (dir.exists()) {
|
|
QStringList dc = dir.entryList(QStringList() << "dc2c.bin", QDir::Files,
|
|
QDir::SortFlag::Time | QDir::SortFlag::Reversed);
|
|
if (!dc.isEmpty()) {
|
|
m_filesToUpdate << QDir::cleanPath(QString("etc/dc/") + dc.first());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (std::optional<QString> changes = m_gc.gitPull()) {
|
|
if (!changes.value().contains("Already up to date")) {
|
|
if (std::optional<QStringList> changedFileNames = m_gc.gitDiff(changes.value())) {
|
|
m_filesToUpdate << changedFileNames.value();
|
|
}
|
|
}
|
|
m_filesToUpdate.removeDuplicates();
|
|
|
|
qCritical() << "(" << __func__ << ":" << __LINE__ << ") FILES-TO-UPDATE" << m_filesToUpdate;
|
|
|
|
GUI(m_filesToUpdate) << (CONSOLE(m_filesToUpdate) << UPDATE_STEP::FILES_TO_UPDATE);
|
|
setProgress(_FILES_TO_UPDATE);
|
|
} else {
|
|
ISMAS() << (GUI() << (CONSOLE() << (m_lastFailedUpdateStep = UPDATE_STEP::UPDATE_REPOSITORY_FAILURE)));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Worker::computeFilesToDownload() {
|
|
m_filesToDownload.clear();
|
|
for (int i = 0; i < m_filesToUpdate.size(); ++i) {
|
|
QString const fName = m_filesToUpdate.at(i);
|
|
if (fName.contains("DC2C_print", Qt::CaseInsensitive) ||
|
|
fName.contains("DC2C_device", Qt::CaseInsensitive) ||
|
|
fName.contains("DC2C_conf", Qt::CaseInsensitive) ||
|
|
fName.contains("DC2C_cash", Qt::CaseInsensitive)) {
|
|
m_filesToDownload << fName; // download printer-config-files
|
|
} else {
|
|
if (fName.contains("dc2c.bin")) {
|
|
m_filesToDownload << fName; // download device controller
|
|
}
|
|
}
|
|
}
|
|
|
|
return (m_filesToDownload.size() > 0);
|
|
}
|
|
|
|
|
|
bool Worker::cleanUpOpkgCache() {
|
|
bool removedFiles = true;
|
|
QDir dir("/var/cache/opkg");
|
|
if (dir.exists()) {
|
|
dir.setNameFilters(QStringList() << ".gz" << ".ipk");
|
|
dir.setFilter(QDir::Files);
|
|
foreach(QString dirFile, dir.entryList()) {
|
|
removedFiles &= dir.remove(dirFile);
|
|
}
|
|
}
|
|
return removedFiles;
|
|
}
|
|
|
|
bool Worker::execOpkgCommands() {
|
|
if (!cleanUpOpkgCache()) {
|
|
CONSOLE() << "INFO: some cached opkg files not removed";
|
|
}
|
|
for (int i = 0; i < m_filesToUpdate.size(); ++i) {
|
|
QString const fName = m_filesToUpdate.at(i);
|
|
if (fName.contains("opkg_commands", Qt::CaseInsensitive)) {
|
|
GUI() << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMANDS);
|
|
// execute opkg commands
|
|
if (QDir::setCurrent(m_customerRepository)) {
|
|
QFile f(fName);
|
|
if (f.exists()) {
|
|
if (f.open(QIODevice::ReadOnly)) {
|
|
QTextStream in(&f);
|
|
m_opkgCommands.clear();
|
|
QStringList opkgErrorLst;
|
|
while (!in.atEnd()) {
|
|
QString line = in.readLine();
|
|
// TODO: "^\\s*[#]{0,}$" : empty line or comment line starting with #
|
|
static const QRegularExpression comment("^\\s*[#].*$");
|
|
static const QRegularExpression emptyLine("^\\s*$");
|
|
if (line.indexOf(emptyLine, 0) == -1 &&
|
|
line.indexOf(comment, 0) == -1) {
|
|
QString opkgCommand = line.trimmed();
|
|
qCritical() << "Found opkg-command" << opkgCommand;
|
|
if (!executeOpkgCommand(opkgCommand)) {
|
|
opkgErrorLst << opkgCommand;
|
|
} else {
|
|
QString cmd = "\n " + opkgCommand;
|
|
emit appendText(cmd);
|
|
m_opkgCommands << cmd;
|
|
|
|
QStringList const opkgLst(opkgCommand);
|
|
QStringList const cmdLst(cmd);
|
|
|
|
switch(m_opkgCommands.size()) {
|
|
case 1:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_1));
|
|
setProgress(_EXEC_OPKG_COMMAND_1);
|
|
break;
|
|
case 2:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_2));
|
|
setProgress(_EXEC_OPKG_COMMAND_2);
|
|
break;
|
|
case 3:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_3));
|
|
setProgress(_EXEC_OPKG_COMMAND_3);
|
|
break;
|
|
case 4:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_4));
|
|
setProgress(_EXEC_OPKG_COMMAND_4);
|
|
break;
|
|
case 5:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_5));
|
|
setProgress(_EXEC_OPKG_COMMAND_5);
|
|
break;
|
|
case 6:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_6));
|
|
setProgress(_EXEC_OPKG_COMMAND_6);
|
|
break;
|
|
case 7:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_7));
|
|
setProgress(_EXEC_OPKG_COMMAND_7);
|
|
break;
|
|
case 8:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_8));
|
|
setProgress(_EXEC_OPKG_COMMAND_8);
|
|
break;
|
|
case 9:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_9));
|
|
setProgress(_EXEC_OPKG_COMMAND_9);
|
|
break;
|
|
default:
|
|
ISMAS(opkgLst) << (GUI(cmdLst) << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_LAST));
|
|
setProgress(_EXEC_OPKG_COMMAND_LAST);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
f.close();
|
|
if (opkgErrorLst.size() == 0) {
|
|
if (m_opkgCommands.size() > 0) {
|
|
m_displayIndex = 1;
|
|
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::EXEC_OPKG_COMMAND_SUCCESS));
|
|
setProgress(_EXEC_OPKG_COMMAND_SUCCESS);
|
|
}
|
|
} else {
|
|
m_displayIndex = 1;
|
|
ISMAS(opkgErrorLst) << (GUI(opkgErrorLst) << (CONSOLE() << (m_lastFailedUpdateStep = UPDATE_STEP::EXEC_OPKG_COMMAND_FAILURE)));
|
|
GUI() << UPDATE_STEP::EXEC_OPKG_COMMAND_FAILURE;
|
|
setProgress(_EXEC_OPKG_COMMAND_FAILURE);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Worker::downloadFilesToPSAHardware() {
|
|
m_displayIndex = 0;
|
|
QStringList lst(QString("START"));
|
|
|
|
ISMAS(lst) << (GUI(m_filesToDownload) << (CONSOLE(m_filesToDownload) << UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
|
|
|
|
if (m_noUpdatePsaHardware == false) {
|
|
if (computeFilesToDownload() > 0) {
|
|
lst.clear();
|
|
for (int i = 0; i < m_filesToDownload.size(); ++i) {
|
|
lst << QFileInfo(m_filesToDownload.at(i)).fileName();
|
|
}
|
|
ISMAS(lst) << (CONSOLE(lst) << UPDATE_STEP::FILES_TO_DOWNLOAD);
|
|
|
|
if (m_update && m_update->doUpdate(m_displayIndex, m_filesToDownload)) {
|
|
// prepared for use: at the moment, the dc-library does not work
|
|
// as expected.
|
|
|
|
// static const QRegularExpression re("^.*\\.json$");
|
|
// return update.checkDownloadedJsonVersions(m_filesToDownload.filter(re));
|
|
|
|
return true;
|
|
}
|
|
|
|
ISMAS(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE));
|
|
setProgress(_DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Worker::syncCustomerRepositoryAndFS() {
|
|
QString msg("START");
|
|
QStringList lst(msg);
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY));
|
|
lst.clear();
|
|
|
|
if (QDir(m_customerRepository).exists()) {
|
|
if (QDir::setCurrent(m_customerRepository)) {
|
|
Command md("bash");
|
|
if (!md.execute(m_customerRepository,
|
|
QStringList() << "-c" << "mkdir -p /etc/psa_config /etc/dc /etc/psa_tariff")) {
|
|
msg = QString("COULD NOT EXECUTE '%1', exitCode=%2").arg(md.command()).arg(md.exitCode());
|
|
qCritical() << msg;
|
|
QStringList lst2(msg);
|
|
ISMAS(lst2) << (CONSOLE(lst2) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY);
|
|
}
|
|
QString const params("-v "
|
|
"--recursive "
|
|
"--progress "
|
|
"--checksum "
|
|
"--exclude=.* "
|
|
"--include=*.bin "
|
|
"--include=*.json "
|
|
"--include=*.ini");
|
|
QStringList cmds;
|
|
|
|
if (QDir(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/")).exists()) {
|
|
cmds << QString("rsync ") + params.simplified() + " etc/ /etc";
|
|
Utils::printInfoMsg(QString("CONFIGURED SYNCING TO /ETC"));
|
|
}
|
|
if (QDir(QDir::cleanPath(m_customerRepository + QDir::separator() + "opt/")).exists()) {
|
|
cmds << QString("rsync ") + params.simplified() + " opt/ /opt";
|
|
Utils::printInfoMsg(QString("CONFIGURED SYNCING TO /OPT"));
|
|
}
|
|
|
|
QString cmd;
|
|
bool error = false;
|
|
foreach (cmd, cmds) {
|
|
if (!error) {
|
|
Command c("bash");
|
|
qInfo() << "EXECUTING CMD..." << cmd;
|
|
Utils::printInfoMsg(QString("EXECUTING CMD %1...").arg(cmd));
|
|
if (c.execute(m_customerRepository, QStringList() << "-c" << cmd)) {
|
|
QStringList result = c.getCommandResult().split('\n');
|
|
QString const &p1 = "send_files mapped ";
|
|
QString const &p2 = "of size";
|
|
|
|
for (int i = 0; i < result.size(); ++i) {
|
|
QString line = result.at(i);
|
|
qInfo() << line;
|
|
|
|
// "send_files mapped etc/psa_tariff/tariff01.json of size 19339"
|
|
int sendFilesAtPos = line.indexOf(p1);
|
|
int ofSizeAtPos = line.indexOf(p2);
|
|
if (sendFilesAtPos != -1 && ofSizeAtPos != -1) {
|
|
sendFilesAtPos += p1.length();
|
|
QString const &s = line.mid(sendFilesAtPos, ofSizeAtPos - sendFilesAtPos).trimmed();
|
|
|
|
//m_updateStatus = UpdateStatus(UPDATE_STATUS::RSYNC_FILE_SUCCESS,
|
|
// QString("RSYNC FILE ") + s.split("/").last() +
|
|
// " LAST-COMMIT: " + m_gc.gitLastCommit(s));
|
|
//IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
|
|
// QString("#M=APISM#C=CMD_EVENT#J=") +
|
|
// m_ismasClient.rsyncFile(m_updateStatus.m_statusDescription, ""));
|
|
}
|
|
}
|
|
|
|
} else {
|
|
Utils::printCriticalErrorMsg(QString("CMD ") + cmd + " FAILED: "
|
|
+ c.getCommandResult() + QString(" EXIT_CODE=(%1)").arg(c.exitCode()));
|
|
error = true;
|
|
}
|
|
}
|
|
if (!error) {
|
|
lst.clear();
|
|
lst << QString("SUCCESS %1").arg(cmd);
|
|
ISMAS(lst) << (CONSOLE(lst) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY);
|
|
} else {
|
|
msg = QString("FAILURE %1").arg(cmd);
|
|
lst << msg;
|
|
QStringList lst2(msg);
|
|
ISMAS(lst2) << (CONSOLE(lst2) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY);
|
|
}
|
|
}
|
|
if (!error) {
|
|
// now check tariff-files in etc and /etc/psa_tariff
|
|
QDir dir1(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_tariff"));
|
|
QDir dir2("/etc/psa_tariff");
|
|
if (Utils::sameFilesInDirs(dir1, dir2) == false) {
|
|
CONSOLE() << QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_tariff")
|
|
<< "AND /etc/psa_tariff ARE DIFFERENT: CHANGED CUSTOMER-NUMBER?";
|
|
}
|
|
CONSOLE() << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS;
|
|
setProgress(_SYNC_CUSTOMER_REPOSITORY_SUCCESS);
|
|
return true;
|
|
}
|
|
} else {
|
|
lst << QString("CAN NOT CD TO CUST-REPO %1").arg(m_customerRepository);
|
|
}
|
|
} else {
|
|
lst << QString("CUST-REPO %1 DOES NOT EXIST").arg(m_customerRepository);
|
|
}
|
|
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_FAILURE)));
|
|
setProgress(_SYNC_CUSTOMER_REPOSITORY_FAILURE);
|
|
return false;
|
|
}
|
|
|
|
bool Worker::saveLogFile() {
|
|
// ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::SAVE_LOGS));
|
|
// ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::SAVE_LOGS_FAILURE));
|
|
return true;
|
|
}
|
|
|
|
QString Worker::getOsVersion() const {
|
|
QString const cmd = QString("echo -n $(cat /etc/os-release | head -n 1 | cut -d'\"' -f2 | tr -d '\"')");
|
|
Command c("bash");
|
|
if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult();
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getATBUpdateToolYoctoVersion() {
|
|
if (QFile::exists("/var/lib/opkg/status")) {
|
|
QString const cmd = QString("echo -n $(cat /var/lib/opkg/status | grep -A1 atbupdatetool | tail -n 1 | cut -d':' -f2 | cut -d' ' -f2)");
|
|
Command c("bash");
|
|
if (c.execute("/tmp", QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult(); // 1.3.9+git0+226553a8ab-r0
|
|
}
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getAPISMYoctoVersion() {
|
|
if (QFile::exists("/var/lib/opkg/status")) {
|
|
QString const cmd = QString("echo -n $(cat /var/lib/opkg/status | grep -A1 -e apism[[:space:]]*$ | tail -n 1 | cut -d':' -f2 | cut -d' ' -f2)");
|
|
Command c("bash");
|
|
if (c.execute("/tmp", QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult(); // 1.4.1.0-r4
|
|
}
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getATBUpdateToolYoctoInstallationStatus() {
|
|
if (QFile::exists("/var/lib/opkg/status")) {
|
|
QString const cmd = QString("echo -n $(cat /var/lib/opkg/status | grep -A3 atbupdatetool | tail -n 1 | cut -d':' -f2 | cut -d' ' -f2,3,4)");
|
|
Command c("bash");
|
|
if (c.execute("/tmp", QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult(); // 1.3.9+git0+226553a8ab-r0
|
|
}
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getAPISMYoctoInstallationStatus() {
|
|
if (QFile::exists("/var/lib/opkg/status")) {
|
|
QString const cmd = QString("echo -n $(cat /var/lib/opkg/status | grep -A3 apism | tail -n 1 | cut -d':' -f2 | cut -d' ' -f2,3,4)");
|
|
Command c("bash");
|
|
if (c.execute("/tmp", QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult(); // 1.3.9+git0+226553a8ab-r0
|
|
}
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getDCVersionPreparedForDownload(QString const &filename) {
|
|
if (QFile::exists(filename)) { // <customer-repo/etc/dc/dc2c.bin>
|
|
QString const cmd = QString("strings %1 | grep -e DC2[Cc]\\. | head -n1").arg(filename);
|
|
Command c("bash");
|
|
if (c.execute("/tmp", QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult(); // DC2c.04.42 14.09.2023
|
|
}
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
|
|
QString Worker::getATBQTVersion() const {
|
|
QString const cmd = QString("echo -n $(/opt/app/ATBAPP/ATBQT -v | head -n 2 | cut -d':' -f2)");
|
|
Command c("bash");
|
|
if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult();
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getATBUpdateToolVersion() const {
|
|
return APP_EXTENDED_VERSION;
|
|
}
|
|
|
|
QString Worker::getCPUSerial() const {
|
|
QString const cmd = QString("echo -n $(cat /proc/cpuinfo | grep -i Serial | cut -d':' -f2)");
|
|
Command c("bash");
|
|
if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult();
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getRaucVersion() const {
|
|
QString const cmd = QString("echo -n $(rauc --version)");
|
|
Command c("bash");
|
|
if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult();
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getOpkgVersion() const {
|
|
QString const cmd = QString("echo -n $(opkg --version)");
|
|
Command c("bash");
|
|
if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult();
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QString Worker::getPluginVersion(QString const &pluginFileName) const {
|
|
QString const cmd = QString("echo -n $(strings %1 | grep \\\"Version\\\" | cut -d':' -f2 | tr -d '\"' | tr -d ',')").arg(pluginFileName);
|
|
Command c("bash");
|
|
if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) {
|
|
return c.getCommandResult();
|
|
}
|
|
return "N/A";
|
|
}
|
|
|
|
QStringList Worker::getDCVersion() const {
|
|
QStringList lst = (QStringList() << "N/A" << "N/A");
|
|
#if 0
|
|
Update const *up = update();
|
|
if (up) {
|
|
hwinf const *caPlugin = up->hw();
|
|
if (caPlugin) {
|
|
caPlugin->dc_autoRequest(true); // turn auto-request setting on
|
|
|
|
QByteArray const cmp(8, char(0));
|
|
QByteArray hw(""), sw("");
|
|
for (int i=0; i<5; ++i) {
|
|
hw = caPlugin->dc_getHWversion().toUtf8();
|
|
sw = caPlugin->dc_getSWversion().toUtf8();
|
|
if (!hw.startsWith(cmp)) {
|
|
lst.clear();
|
|
qInfo() << hw << sw;
|
|
lst << hw << sw;
|
|
break;
|
|
}
|
|
QThread::sleep(1);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return lst;
|
|
}
|
|
|
|
qint64 Worker::getFileSize(QString const &fileName) const {
|
|
// fileName has to be an absolute path
|
|
QFileInfo fInfo(fileName);
|
|
return fInfo.exists() ? fInfo.size() : -1;
|
|
}
|
|
|
|
bool Worker::executeOpkgCommand(QString opkgCommand) {
|
|
Command c(opkgCommand);
|
|
if (c.execute(m_workingDirectory)) {
|
|
QString const r = c.getCommandResult();
|
|
Utils::printInfoMsg(QString("EXECUTE OPKG COMMAND %1 OK: %2")
|
|
.arg(opkgCommand)
|
|
.arg(c.getCommandResult()));
|
|
return true;
|
|
} else {
|
|
Utils::printCriticalErrorMsg(QString("EXECUTE OPKG COMMAND %1 FAILED")
|
|
.arg(opkgCommand));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
PSAInstalled Worker::getPSAInstalled() {
|
|
QStringList const dcVersion = getDCVersion();
|
|
QString const deviceControllerVersionHW = dcVersion.first();
|
|
QString const deviceControllerVersionSW = dcVersion.last();
|
|
|
|
qInfo() << "CURRENT DC-HW-VERSION: " << deviceControllerVersionHW;
|
|
qInfo() << "CURRENT DC-SW-VERSION: " << deviceControllerVersionSW;
|
|
|
|
QString const deviceControllerGitBlob = "N/A";
|
|
QString const deviceControllerGitLastCommit = "N/A";
|
|
|
|
PSAInstalled psaInstalled;
|
|
QString printSysDir("/etc/psa_config");
|
|
QString tariffSysDir("/etc/psa_tariff");
|
|
QString tariffRepoDir("etc/psa_tariff");
|
|
QString opkgRepoDir("etc/psa_update");
|
|
QString const &absPathNameRepositoryOpkg = QDir::cleanPath(opkgRepoDir + QDir::separator() + "opkg_commands");
|
|
QString absPathName;
|
|
QString absPathNameRepository;
|
|
|
|
psaInstalled.versionInfo.lastCommit = "N/A";
|
|
psaInstalled.versionInfo.reason = "N/A";
|
|
psaInstalled.versionInfo.created = "N/A";
|
|
|
|
if (m_versionInfo.size() == 3) {
|
|
QString const &lastCommit = m_versionInfo.at(0);
|
|
QString reason = m_versionInfo.at(1);
|
|
QDateTime const dt = QDateTime::fromString(m_versionInfo.at(2), Qt::ISODate);
|
|
QString version{""};
|
|
QString date{""};
|
|
if (dt.isValid()) {
|
|
date += " ";
|
|
date += dt.date().toString(Qt::ISODate);
|
|
}
|
|
static const QRegularExpression re("^\\s*(\\d+)\\.(\\d+)\\.(\\d+)(.*$)");
|
|
QRegularExpressionMatch match = re.match(reason);
|
|
if (match.hasMatch()) {
|
|
int const lastCapturedIndex = match.lastCapturedIndex();
|
|
if (lastCapturedIndex >= 1) {
|
|
version += " v";
|
|
version += match.captured(1); // major
|
|
}
|
|
if (lastCapturedIndex >= 2) {
|
|
version += ".";
|
|
version += match.captured(2); // minor
|
|
}
|
|
if (lastCapturedIndex >= 3) {
|
|
version += ".";
|
|
version += match.captured(3); // patch
|
|
}
|
|
if (lastCapturedIndex >= 4) { // rest after version
|
|
reason = match.captured(4);
|
|
}
|
|
}
|
|
|
|
psaInstalled.versionInfo.lastCommit = QString("%1%2").arg(lastCommit).arg(version);
|
|
psaInstalled.versionInfo.reason = reason;
|
|
psaInstalled.versionInfo.created = m_versionInfo.at(2);
|
|
}
|
|
|
|
//qCritical() << "";
|
|
//qCritical() << "VERSION-INFO";
|
|
//qCritical() << "LAST-COMMIT" << psaInstalled.versionInfo.lastCommit;
|
|
//qCritical() << "REASON" << psaInstalled.versionInfo.reason;
|
|
//qCritical() << "CREATED" << psaInstalled.versionInfo.created;
|
|
//qCritical() << "";
|
|
|
|
if (m_zoneNr != 0) {
|
|
QString const &n = QString("%1").arg(m_zoneNr).rightJustified(2, '0');
|
|
psaInstalled.tariff.name = QString("tariff%1.json").arg(n);
|
|
absPathName = QDir::cleanPath(tariffSysDir + QDir::separator() + psaInstalled.tariff.name);
|
|
psaInstalled.tariff.blob = m_gc.gitBlob(absPathName);
|
|
absPathNameRepository = QDir::cleanPath(tariffRepoDir + QDir::separator() + psaInstalled.tariff.name);
|
|
psaInstalled.tariff.lastCommit = m_gc.gitLastCommit(absPathNameRepository);
|
|
psaInstalled.tariff.size = getFileSize(absPathName);
|
|
psaInstalled.tariff.zone = m_zoneNr;
|
|
psaInstalled.tariff.loadTime = Utils::getTariffLoadTime(absPathName);
|
|
psaInstalled.tariff.project = Utils::getLocation(absPathName);
|
|
psaInstalled.tariff.version = Utils::getTariffVersion(absPathName);
|
|
psaInstalled.tariff.info = Utils::getTariffInfo(absPathName);
|
|
}
|
|
|
|
psaInstalled.hw.linuxVersion = getOsVersion();
|
|
psaInstalled.hw.cpuSerial = m_cpuSerial;
|
|
|
|
psaInstalled.opkg.blob = m_gc.gitBlob(absPathNameRepositoryOpkg);
|
|
// psaInstalled.opkg.size = getFileSize(absPathNameRepositoryOpkg);
|
|
// psaInstalled.opkg.loadTime = Utils::getTariffLoadTime(absPathNameRepositoryOpkg);
|
|
psaInstalled.opkg.lastCommit = m_gc.gitLastCommit(absPathNameRepositoryOpkg);
|
|
|
|
psaInstalled.dc.versionHW = deviceControllerVersionHW;
|
|
psaInstalled.dc.versionSW = deviceControllerVersionSW;
|
|
psaInstalled.dc.gitBlob = "N/A";
|
|
psaInstalled.dc.gitLastCommit = "N/A";
|
|
psaInstalled.dc.size = -1;
|
|
|
|
psaInstalled.sw.apismVersion = getAPISMYoctoVersion();
|
|
psaInstalled.sw.atbQTVersion = getATBQTVersion();
|
|
psaInstalled.sw.atbUpdateToolVersion = m_atbUpdateToolVersion;
|
|
|
|
psaInstalled.pluginVersion.deviceController = m_pluginVersionATBDeciceController;
|
|
psaInstalled.pluginVersion.ingenicoISelfCC = m_pluginVersionIngenicoISelf;
|
|
psaInstalled.pluginVersion.mobilisisCalculatePrice = m_pluginVersionMobilisisCalc;
|
|
psaInstalled.pluginVersion.mobilisisCalculatePriceConfigUi = m_pluginVersionMobilisisCalcConfig;
|
|
psaInstalled.pluginVersion.prmCalculatePrice = m_pluginVersionPrmCalc;
|
|
psaInstalled.pluginVersion.prmCalculatePriceConfigUi = m_pluginVersionPrmCalcConfig;
|
|
psaInstalled.pluginVersion.tcpZVT = m_pluginVersionTcpZvt;
|
|
|
|
// key: conf-json-filename; value: installed version on DC
|
|
QMap<QString, QString> map;
|
|
if (m_update) {
|
|
map = m_update->getInstalledJsonVersions();
|
|
}
|
|
|
|
psaInstalled.cash.name = "DC2C_cash.json";
|
|
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.cash.name);
|
|
|
|
psaInstalled.cash.blob = m_gc.gitBlob(absPathName);
|
|
psaInstalled.cash.size = getFileSize(absPathName);
|
|
if (map.contains("DC2C_cash.json")) {
|
|
psaInstalled.cash.blob = map.value("DC2C_cash.json", "inst.vers.not.avail");
|
|
}
|
|
|
|
psaInstalled.conf.name = "DC2C_conf.json";
|
|
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.conf.name);
|
|
psaInstalled.conf.blob = m_gc.gitBlob(absPathName);
|
|
psaInstalled.conf.size = getFileSize(absPathName);
|
|
if (map.contains("DC2C_conf.json")) {
|
|
psaInstalled.conf.blob = map.value("DC2C_conf.json", "inst.vers.not.avail");
|
|
}
|
|
|
|
psaInstalled.device.name = "DC2C_device.json";
|
|
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.device.name);
|
|
psaInstalled.device.blob = m_gc.gitBlob(absPathName);
|
|
psaInstalled.device.size = getFileSize(absPathName);
|
|
if (map.contains("DC2C_device.json")) {
|
|
psaInstalled.device.blob = map.value("DC2C_device.json", "inst.vers.not.avail");
|
|
}
|
|
|
|
for (int i=0; i < 32; ++i) {
|
|
QString const &n = QString("%1").arg(i+1).rightJustified(2, '0');
|
|
psaInstalled.print[i].name = QString("DC2C_print%1.json").arg(n);
|
|
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.print[i].name);
|
|
psaInstalled.print[i].blob = m_gc.gitBlob(absPathName);
|
|
psaInstalled.print[i].size = getFileSize(absPathName);
|
|
if (map.contains(psaInstalled.print[i].name)) {
|
|
psaInstalled.print[i].blob = map.value(psaInstalled.print[i].name, "inst.vers.not.avail");
|
|
}
|
|
}
|
|
|
|
psaInstalled.ptuPackageVersion = "{}";
|
|
if (QFile::exists("/usr/bin/ptuPackageVersions")) {
|
|
Command c("/usr/bin/ptuPackageVersions -i -o json");
|
|
if (c.execute(m_workingDirectory)) {
|
|
QString r = c.getCommandResult();
|
|
// ptuPackageVersions returns a json-array
|
|
QJsonArray const &ja = QJsonDocument::fromJson(r.remove(QRegExp("\\n")).toUtf8()).array();
|
|
if (!ja.empty()) {
|
|
// transform the array into an object, containing the objects
|
|
// of the array (christian needs it this way)
|
|
QJsonObject o;
|
|
foreach (QJsonValue const &value, ja) {
|
|
if (value.isObject()) {
|
|
QJsonObject obj = value.toObject();
|
|
QStringList keys = obj.keys();
|
|
if (!keys.isEmpty()) {
|
|
QString const &k = obj.keys().first();
|
|
QJsonValue const &v = obj.value(k);
|
|
o.insert(k, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
psaInstalled.ptuPackageVersion =
|
|
QJsonDocument(o).toJson(QJsonDocument::Compact);
|
|
|
|
} else {
|
|
qCritical() << __func__ << ":" << __LINE__
|
|
<< "ERROR array return by ptuPackageVersions empty";
|
|
}
|
|
} else {
|
|
qCritical() << __func__ << ":" << __LINE__
|
|
<< "ERROR executing ptuPackageVersions";
|
|
}
|
|
}
|
|
|
|
return psaInstalled;
|
|
}
|
|
|
|
bool Worker::dcUpdate() {
|
|
return m_dcDownloadFirmware->start("/opt/app/tools/atbupdate");
|
|
}
|
|
|
|
void Worker::summary() {
|
|
|
|
QString summary, first, second, line, tmp;
|
|
QVector<QPair<QString, QString>> vec = Utils::installedPackages();
|
|
|
|
int max_first = 0, max_second = 0;
|
|
for (int i = 0; i < vec.size(); ++i) {
|
|
max_first = std::max(max_first, vec[i].first.length());
|
|
max_second = std::max(max_second, vec[i].second.length());
|
|
}
|
|
|
|
max_first += 5;
|
|
|
|
summary = "UPDATE SUMMARY\n\n";
|
|
|
|
first = QString("%1").arg("start", max_first, QChar(' '));
|
|
tmp = QString("%1").arg(start().toString(Qt::ISODate));
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
|
|
first = QString("%1").arg("update tool version", max_first, QChar(' '));
|
|
tmp = QString("%1 - %2 %3").arg(APP_VERSION).arg(APP_BUILD_DATE).arg(APP_BUILD_TIME);
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
|
|
first = QString("%1").arg("machine number", max_first, QChar(' '));
|
|
tmp = QString("%1").arg(machineNr());
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
|
|
first = QString("%1").arg("customer number", max_first, QChar(' '));
|
|
tmp = QString("%1").arg(customerNr());
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
|
|
first = QString("%1").arg("zone number", max_first, QChar(' '));
|
|
tmp = QString("%1").arg(zoneNr());
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
|
|
if (m_mainWindow) {
|
|
tmp = m_mainWindow->targetDcVersion();
|
|
if (!tmp.isEmpty()) {
|
|
first = QString("%1").arg("target device controller", max_first, QChar(' '));
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
}
|
|
}
|
|
|
|
first = QString("%1").arg("apism", max_first, QChar(' '));
|
|
tmp = QString("%1").arg(apismVersion());
|
|
second = QString("%1").arg(tmp, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
|
|
for (int i = 0; i < vec.size(); ++i) {
|
|
first = QString("%1").arg(vec[i].first, max_first, QChar(' '));
|
|
second = QString("%1").arg(vec[i].second, -max_second, QChar(' '));
|
|
line = first + ": " + second;
|
|
summary += line + "\n";
|
|
}
|
|
|
|
emit showSummary(summary);
|
|
}
|