1239 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1239 lines
		
	
	
		
			55 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 "message_handler.h"
 | |
| #include "plugins/interfaces.h"
 | |
| #include "ismas/ismas_client.h"
 | |
| #include "progress_event.h"
 | |
| #include "mainwindow.h"
 | |
| #include "utils.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]");
 | |
| 
 | |
| 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_SUCCESS),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::CHECK_ISMAS_TRIGGER_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::APPLY_REPOSITORY_CHANGES),
 | |
|         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_DEVICE_CONTROLLER),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_SUCCESS),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_FAILURE),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::APPLY_REPOSITORY_CHANGES_SUCCESS),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::APPLY_REPOSITORY_CHANGES_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_SUCCEEDED),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::UPDATE_FAILED),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::FINISHED),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::DEBUG),
 | |
|         INSERT_ELEMENT(UPDATE_STEP::ERROR)
 | |
| #undef INSERT_ELEMENT
 | |
| });
 | |
| 
 | |
| Worker *Worker::instance = nullptr;
 | |
| 
 | |
| Worker::Worker(int customerNr,
 | |
|                int machineNr,
 | |
|                int zoneNr,
 | |
|                QString branchName,
 | |
|                QString pluginName,
 | |
|                QString workingDirectory,
 | |
|                bool dryRun,
 | |
|                QObject *parent,
 | |
|                char const *serialInterface,
 | |
|                char const *baudrate)
 | |
|   : m_workerThread("workerThread")
 | |
|   , m_customerNr(customerNr)
 | |
|   , m_customerNrStr(QString("customer_") + QString::number(m_customerNr).rightJustified(3, '0'))
 | |
|   , m_machineNr(machineNr)
 | |
|   , m_zoneNr(zoneNr)
 | |
|   , m_pluginName(pluginName)
 | |
|   , m_workingDirectory(workingDirectory)
 | |
|   , m_branchName(branchName)
 | |
|   , m_customerRepositoryPath(QString("https://git.mimbach49.de/GerhardHoffmann/%1.git").arg(m_customerNrStr))
 | |
|   , m_customerRepository(QDir::cleanPath(m_workingDirectory + QDir::separator() + m_customerNrStr))
 | |
|   , m_dryRun(dryRun)
 | |
|   , m_parent(parent)
 | |
|   , m_serialInterface(serialInterface)
 | |
|   , m_baudrate(baudrate)
 | |
|   , m_gc(m_customerNrStr, m_customerRepository, m_workingDirectory, m_branchName, this)
 | |
|   , 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_returnCode(0)
 | |
|   , m_mainWindow(nullptr) /* contains plugin */
 | |
|   //, m_withoutIsmasDirectPort(true) /* useful for testing */ {
 | |
|   , m_withoutIsmasDirectPort(false) /* useful for testing */ {
 | |
| 
 | |
|     // TODO: turn object into singleton
 | |
|     instance = this;
 | |
| 
 | |
|     this->setObjectName("worker-object");
 | |
|     QDir::setCurrent(m_workingDirectory);
 | |
| 
 | |
|     if (std::optional<QString> v = getApismVersion()) {
 | |
|         m_apismVersion = v.value();
 | |
|     }
 | |
| 
 | |
|     this->moveToThread(&m_workerThread);
 | |
|     m_workerThread.start();
 | |
| 
 | |
|     int cnt = 0;
 | |
|     while (!m_workerThread.isRunning()) {
 | |
|         if (++cnt > 5) {
 | |
|             Utils::printCriticalErrorMsg("starting worker thread FAILED");
 | |
|             return;
 | |
|         }
 | |
|         QThread::sleep(1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| Worker::~Worker() {
 | |
|     int cnt = 0;
 | |
|     m_workerThread.quit();
 | |
|     while (!m_workerThread.isFinished()) {
 | |
|         if (!m_workerThread.wait(1000)) {
 | |
|             if (++cnt > 5) {
 | |
|                 Utils::printCriticalErrorMsg("stopping worker thread FAILED");
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 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::update() {
 | |
|     // 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 customerRepositoryEtc(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/"));
 | |
|         QDir customerRepositoryOpt(QDir::cleanPath(m_customerRepository + QDir::separator() + "opt/"));
 | |
|         QDir customerRepositoryGit(QDir::cleanPath(m_customerRepository + QDir::separator() + ".git/"));
 | |
|         if (!m_gc.gitFsck()
 | |
|             // etc-directory inside git-repository does not exist, which means the
 | |
|             // git-repository is corrupted -> remove it and start from scratch
 | |
|          || !customerRepositoryEtc.exists()
 | |
|          || !customerRepositoryGit.exists()
 | |
|          || !customerRepositoryOpt.exists()) {
 | |
|             // should never happen
 | |
|             Utils::printCriticalErrorMsg("CORRUPTED CUSTOMER REPOSITORY");
 | |
|             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;
 | |
| }
 | |
| 
 | |
| int Worker::sendCloneAndCheckoutFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_CLONE_AND_CHECKOUT_FAILURE,
 | |
|                           QString("CLONE OR CHECKOUT FAILED: ") + m_customerRepository);
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.errorGitClone(m_updateStatus.m_statusDescription));
 | |
| 
 | |
|     return CLONE_AND_CHECKOUT_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendCloneAndCheckoutSuccess() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_CLONE_AND_CHECKOUT_SUCCESS,
 | |
|                           QString("CLONED REPOSITORY %1 AND CHECKED OUT BRANCH %2")
 | |
|                             .arg(m_customerRepository)
 | |
|                             .arg(m_gc.branchName()));
 | |
| 
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|             QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|                 m_ismasClient.cloneAndCheckoutCustomerRepository(
 | |
|                     m_updateStatus.m_statusDescription));
 | |
| 
 | |
|     return CLONE_AND_CHECKOUT_SUCCESS;
 | |
| }
 | |
| 
 | |
| int Worker::sendIsmasTriggerFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::ISMAS_UPDATE_TRIGGER_SET_FAILURE,
 | |
|                         QString("ISMAS update trigger wrong"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "CHECK-UPDATE-TRIGGER",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
|     return ISMAS_TRIGGER_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendCustomerEnvironmentConfigurationFailed() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_CHECKOUT_BRANCH_FAILURE,
 | |
|                         QString("Configuring customer environment failed"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "GIT-CHECKOUT-BRANCH",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
|     return ENVIRONMENT_CONFIG_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendPullFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_FETCH_UPDATES_REQUEST_FAILURE,
 | |
|                         QString("No files to update"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "FETCH-FILES-TO-UPDATE",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
|     return GIT_PULL_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendFileUpdateFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::PSA_UPDATE_FILES_FAILED,
 | |
|                         QString("Updating files failed"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "UPDATE-FILES",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
|     return UPDATE_FILES_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendRsyncFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::RSYNC_UPDATES_FAILURE,
 | |
|                         QString("Syncing files to update failed"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "RSYNC-UPDATE-FILES",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
| 
 | |
|     return RSYNC_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendLastVersionFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::ISMAS_SEND_LAST_VERSION_FAILED,
 | |
|                         QString("Sending ISMAS last version failed"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "ISMAS-SEND-LAST-VERSION",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
|     return SEND_LAST_VERSION_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendSaveLogFilesFailure() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::SAVE_LOG_FILES_FAILED,
 | |
|                         QString("Saving log files failed"));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                             "SAVE-LOG-FILES",
 | |
|                                             m_updateStatus.m_statusDescription));
 | |
|     return SAVE_LOG_FILES_FAILURE;
 | |
| }
 | |
| 
 | |
| int Worker::sendFoundFilesToUpdateSuccess() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_CHECK_FILES_TO_UPDATE_SUCCESS,
 | |
|                         QString("Files to update: ") + m_filesToUpdate.join(','));
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAContinues("CHECK-FILES-TO-UPDATE",
 | |
|                                                m_updateStatus.m_statusDescription));
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int Worker::sendUpdateSucceededAndActivated() {
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSASucceeded(""));
 | |
| 
 | |
|     //m_ismasClient.setProgressInPercent(100);
 | |
| 
 | |
|     // mark update as activated -> this resets the WAIT button
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|         QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|             m_ismasClient.updateOfPSAActivated());
 | |
| 
 | |
|     return UPDATE_SUCCESS_AND_ACTIVATED;
 | |
| }
 | |
| 
 | |
| int Worker::sendFinalResult() {
 | |
|     m_updateStatus = UpdateStatus(UPDATE_STATUS::UPDATE_PROCESS_SUCCESS,
 | |
|                                   QString("Update process succeeded. Reset WAIT."));
 | |
|     if (std::optional<QString> s = m_ismasClient.finalResult(IsmasClient::RESULT_CODE::SUCCESS,
 | |
|                                                              m_updateStatus.m_statusDescription)) {
 | |
|         IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|             QString("#M=APISM#C=CMD_EVENT#J=") + s.value());
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void Worker::privateUpdate() {
 | |
|     if (!m_mainWindow) {
 | |
|         Utils::printCriticalErrorMsg("m_mainWindow NOT SET");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::STARTED));
 | |
| 
 | |
|     m_updateProcessRunning = true;
 | |
|     bool sentIsmasLastVersionNotification = false;
 | |
| 
 | |
|     emit disableExit();
 | |
| 
 | |
|     m_returnCode = -1;
 | |
|     startProgressLoop();
 | |
| 
 | |
|     QDir customerRepository(m_customerRepository);
 | |
|     QDir customerRepositoryEtc(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/"));
 | |
| 
 | |
|     CONSOLE() << UPDATE_STEP::CHECK_SANITY;
 | |
| 
 | |
|     bool initialClone = false;      // the customer repository is cloned without
 | |
|                                     // checking the ISMAS-trigger (WAIT-)button.
 | |
|                                     // but if there was a sane repository
 | |
|                                     // available, then the trigger-button must
 | |
|                                     // 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()) {
 | |
|         CONSOLE() << UPDATE_STEP::CHECK_SANITY_FAILURE;
 | |
|         if ((continueUpdate = repairCorruptedRepository()) == true) {
 | |
|             CONSOLE() << UPDATE_STEP::REPOSITORY_RECOVERED_SUCCESS;
 | |
|         } else {
 | |
|             CONSOLE() << UPDATE_STEP::REPOSITORY_RECOVERED_FAILURE;
 | |
|         }
 | |
|     } else {
 | |
|         CONSOLE() << UPDATE_STEP::CHECK_SANITY_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     if (continueUpdate) {
 | |
|         if ((continueUpdate = customerRepository.exists()) == false) {
 | |
|             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()) {
 | |
|                         GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY_SUCCESS));
 | |
|                         continueUpdate = true;
 | |
|                         initialClone = true;
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|                 QThread::sleep(1);  // maybe git needs more time
 | |
|             }
 | |
| 
 | |
|             if (continueUpdate == false) {
 | |
|                 GUI() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY_FAILURE);
 | |
|             }
 | |
| 
 | |
|         } else {
 | |
| 
 | |
|             CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY;
 | |
|             if (isRepositoryCorrupted()) {
 | |
|                 CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_FAILURE;
 | |
|                 continueUpdate = false;
 | |
|             } else {
 | |
|                 CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_SUCCESS;
 | |
|             }
 | |
|         }
 | |
|     }                       // repository is existent and not corrupted.
 | |
|                             // check now if the ISMAS-trigger (WAIT-button)
 | |
|     if (continueUpdate) {   // is activated even in case of initial checkout
 | |
|         if ((continueUpdate = updateTriggerSet()) == false) {
 | |
|             // if (initialClone) {
 | |
|             //
 | |
|             //}
 | |
|             m_returnCode = sendIsmasTriggerFailure();
 | |
|         }
 | |
|         if (continueUpdate) {   // configure customer environment -> checkout
 | |
|                                 // branch in case someone has change the zone_nr
 | |
|             //qDebug() << UPDATE_STEP::CHECK_ISMAS_TRIGGER;
 | |
|             if ((continueUpdate = customerEnvironment(30)) == false) {
 | |
|                 m_returnCode = sendCustomerEnvironmentConfigurationFailed();
 | |
|             }                   // determine which files has to be updated:
 | |
|         }                       // either sent to the hardware or rsynced with
 | |
|         if (continueUpdate) {   // the filesystem in case of tariff-files
 | |
|             //qDebug() << UPDATE_STEP::CHECKED_OUT_BRANCH;
 | |
|             if ((continueUpdate = filesToUpdate(50)) == false) {
 | |
|                 m_returnCode = sendPullFailure();
 | |
|             }
 | |
|         }                       // send message to ISMAS about files which have
 | |
|         if (continueUpdate) {   // been checked in into git repository
 | |
|             //qDebug() << UPDATE_STEP::COMPUTE_FILES_TO_UPDATE;
 | |
|             sendFoundFilesToUpdateSuccess();
 | |
|             if ((continueUpdate = updateFiles(60)) == false) {
 | |
|                 m_returnCode = sendFileUpdateFailure();
 | |
|             }
 | |
|         }
 | |
|         if (continueUpdate) {   // rsync (changed) files to file system
 | |
|             //qDebug() << UPDATE_STEP::DOWNLOAD_FILES_TO_UPDATE;
 | |
|             // TODO: rsync das komplette repository
 | |
|             if ((continueUpdate = syncCustomerRepositoryAndFS(70)) == false) {
 | |
|                 m_returnCode = sendRsyncFailure();
 | |
|             }
 | |
|         }
 | |
|         if (continueUpdate) {   // send message to ISMAS about installed versions
 | |
|             //qDebug() << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY;
 | |
|             if ((continueUpdate = sendIsmasLastVersionNotification(80)) == false) {
 | |
|                 m_returnCode = sendLastVersionFailure();
 | |
|             }
 | |
|         }
 | |
|         if (continueUpdate) {   // future use: save logs of update process
 | |
|             sentIsmasLastVersionNotification = true;
 | |
|             if ((continueUpdate = saveLogFile(90)) == false) {
 | |
|                 m_returnCode = sendSaveLogFilesFailure();
 | |
|             }
 | |
|         }                       // send message to ISMAS that update process
 | |
|         if (continueUpdate) {   // succeeded
 | |
|             //qDebug() << UPDATE_STEP::UPDATE_SUCCESS;
 | |
|             sendUpdateSucceededAndActivated();
 | |
|             m_returnCode = UPDATE_SUCCESS_AND_ACTIVATED;
 | |
|         }
 | |
| 
 | |
|         setProgress(100);
 | |
| 
 | |
|         if (m_returnCode != 0) {
 | |
|             stopProgressLoop();
 | |
|             emit appendText(QString("UPDATE "), UPDATE_STEP_FAIL);
 | |
|         } else {
 | |
|             emit appendText(QString("UPDATE "), UPDATE_STEP_SUCCESS);
 | |
|             sendFinalResult();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!sentIsmasLastVersionNotification) {
 | |
|         // try even if the backend is not connected
 | |
|         sendIsmasLastVersionNotification(100);
 | |
|     }
 | |
| 
 | |
|     stopProgressLoop();
 | |
| 
 | |
|     m_updateProcessRunning = false;
 | |
|     emit enableExit();
 | |
|     emit restartExitTimer();
 | |
| }
 | |
| 
 | |
| std::optional<QString> Worker::getApismVersion() {
 | |
|     for (int repeat = 0; repeat < 10; ++repeat) {
 | |
|         qInfo() << "REPEAT" << repeat << "In getApismVersion() -> #M=APISM#C=REQ_SELF#J={}";
 | |
|         std::optional<QString> result
 | |
|             = IsmasClient::sendRequestReceiveResponse(
 | |
|                 IsmasClient::APISM::DIRECT_PORT, "#M=APISM#C=REQ_SELF#J={}");
 | |
|         if (result) {
 | |
|             QString msg  = result.value();
 | |
|             qInfo() << "In getApismVersion() -> APISM response" << msg;
 | |
|             QJsonParseError parseError;
 | |
|             QJsonDocument document(QJsonDocument::fromJson(msg.toUtf8(), &parseError));
 | |
|             if (parseError.error != QJsonParseError::NoError) {
 | |
|                 qCritical() << "(1) INVALID JSON MSG: PARSING FAILED (msg=" << msg << "):"
 | |
|                             << parseError.error << parseError.errorString();
 | |
|                 m_updateStatus = UpdateStatus(UPDATE_STATUS::JSON_PARSE_FAILURE,
 | |
|                                               QString("(2) INVALID JSON %1 %2 %3")
 | |
|                                                 .arg(msg)
 | |
|                                                 .arg(parseError.error)
 | |
|                                                 .arg(parseError.errorString()));
 | |
|                 IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|                     QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|                         m_ismasClient.jsonParseFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                                       m_updateStatus.m_statusDescription));
 | |
|                 return std::nullopt;
 | |
|             }
 | |
|             if (!document.isObject()) {
 | |
|                 qCritical() << "FILE IS NOT A JSON OBJECT!";
 | |
|                 m_updateStatus = UpdateStatus(UPDATE_STATUS::JSON_PARSE_FAILURE,
 | |
|                                               QString("NOT A JSON-OBJECT %1").arg(msg));
 | |
|                 IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|                     QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|                         m_ismasClient.jsonParseFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR,
 | |
|                                                       m_updateStatus.m_statusDescription));
 | |
|                 return std::nullopt;
 | |
|             }
 | |
|             QJsonObject obj = document.object();
 | |
|             QStringList keys = obj.keys().filter("CMD_GET_APISMSTATUS_RESPONSE");
 | |
|             if (keys.size() != 1) {
 | |
|                 m_updateStatus = UpdateStatus(UPDATE_STATUS::BACKEND_CHECK_FAILURE,
 | |
|                                     "CMD_GET_APISMSTATUS_RESPONSE KEY NOT AVAILABLE");
 | |
|                 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 response", m_updateStatus.m_statusDescription);
 | |
|                 return std::nullopt;
 | |
|             } else {
 | |
|                 QString const key = keys.at(0);
 | |
|                 QJsonValue v = obj.value(key);
 | |
|                 return v.toObject().value("Version").toString();
 | |
|             }
 | |
|         } else {
 | |
|             QThread::sleep(1);
 | |
|         }
 | |
|     }
 | |
|     return std::nullopt;
 | |
| }
 | |
| 
 | |
| bool Worker::updateTriggerSet() {
 | |
| 
 | |
|     if (m_withoutIsmasDirectPort) { // useful for testing
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CHECK_ISMAS_TRIGGER));
 | |
| 
 | |
|     QString triggerValue("");
 | |
| 
 | |
|     for (int repeat = 1; repeat <= 100; ++repeat) {
 | |
|         CONSOLE(QStringList(FUNC_NAME) << QString("-> REPEAT=%1").arg(repeat)) << UPDATE_STEP::DEBUG;
 | |
| 
 | |
|         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);
 | |
|             CONSOLE(QStringList(FUNC_NAME) << s) << UPDATE_STEP::DEBUG;
 | |
|         } else {
 | |
|             CONSOLE(QStringList(FUNC_NAME)) << UPDATE_STEP::DEBUG;
 | |
|         }
 | |
| 
 | |
|         if ((repeat % 10) == 0) {
 | |
|             CONSOLE(QStringList(FUNC_NAME) << "RESTART APISM") << UPDATE_STEP::DEBUG;
 | |
|             Command c("systemctl restart apism");
 | |
|             if (c.execute("/tmp")) {
 | |
|                 QThread::sleep(20); // give APISM some time to reconnect
 | |
|                 CONSOLE(QStringList(FUNC_NAME) << "RESTART APISM DONE") << 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() + ")";
 | |
|             CONSOLE(QStringList(FUNC_NAME) << msg) << UPDATE_STEP::DEBUG;
 | |
| 
 | |
|             QJsonParseError parseError;
 | |
|             QJsonDocument document(QJsonDocument::fromJson(msg.toUtf8(), &parseError));
 | |
|             if (parseError.error != QJsonParseError::NoError) {
 | |
|                 QStringList const &lst
 | |
|                     = QStringList(QString("check update trigger")) << QString("invalid json ")
 | |
|                              + QString("INVALID JSON MSG: PARSING FAILED (msg=%1 %2 %3)")
 | |
|                                     .arg(msg).arg(parseError.error).arg(parseError.errorString()).mid(0, 20);
 | |
|                 GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                 break;
 | |
|             }
 | |
|             if (!document.isObject()) {
 | |
|                 QStringList const &lst =
 | |
|                     QStringList(QString("check update trigger")) << QString("not a json-object ") + msg;
 | |
|                 GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             QJsonObject obj = document.object();
 | |
| 
 | |
|             // always look for an 'error' first
 | |
|             if (obj.contains("error")) {
 | |
|                 CONSOLE(QStringList(obj.value("error").toString())) << 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) {
 | |
|                             QStringList const &lst =
 | |
|                                 QStringList(QString("check update trigger"))
 | |
|                                     << QString("CUSTOMER-NR (%1) != LOCAL CUSTOMER-NR (%2)")
 | |
|                                         .arg(customerNr).arg(m_customerNr);
 | |
|                             GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                             break;
 | |
|                         }
 | |
|                         if (machineNr != m_machineNr) {
 | |
|                             QStringList const &lst =
 | |
|                                 QStringList(QString("check update trigger"))
 | |
|                                     << QString("MACHINE-NR (%1) != LOCAL MACHINE-NR (%2)")
 | |
|                                         .arg(machineNr).arg(m_machineNr);
 | |
|                             GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                             break;
 | |
|                         }
 | |
|                     } else {
 | |
|                         QStringList const lst("Dev_ID DOES NOT CONTAIN Custom_ID AND/OR Device_ID");
 | |
|                         GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                         break;
 | |
|                     }
 | |
|                 } else {
 | |
|                     QStringList const lst("Dev_ID KEY NOT A JSON-OBJECT");
 | |
|                     GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                     break;
 | |
|                 }
 | |
|             } else {
 | |
|                 QStringList const lst("Dev_ID KEY NOT AVAILABLE");
 | |
|                 GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             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") {
 | |
|                             GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS));
 | |
|                             return true;
 | |
|                         } else
 | |
|                         if (QRegExp("\\s*").exactMatch(triggerValue)) { // check for whitespace
 | |
|                             QStringList const &lst =
 | |
|                                 QStringList(QString("check update trigger")) << QString("empty update trigger");
 | |
|                             GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                             QThread::sleep(6);
 | |
|                             continue;
 | |
|                         } else {
 | |
|                             // if the download-button once has the wrong value, it will never recover
 | |
|                             QStringList const &lst =
 | |
|                                 QStringList(QString("check update trigger"))
 | |
|                                     << QString("TRIGGER-VALUE=<%1> NOT 'WAIT'").arg(triggerValue);
 | |
|                             GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                             break;
 | |
|                         }
 | |
|                     } else {
 | |
|                         QStringList const &lst =
 | |
|                             QStringList(QString("check update trigger")) << QString("TRG key not available");
 | |
|                         GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                         break;
 | |
|                     }
 | |
|                 } else {
 | |
|                     QStringList const &lst =
 | |
|                         QStringList(QString("check update trigger")) << QString("Fileupload not a json-object");
 | |
|                     GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                     break;
 | |
|                 }
 | |
|             } else {
 | |
|                 QStringList const &lst =
 | |
|                     QStringList(QString("check update trigger")) << QString("Fileupload not available");
 | |
|                 GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|                 break;
 | |
|             }
 | |
|         } else {
 | |
|             QStringList const &lst =
 | |
|                 QStringList(QString("check update trigger")) << QString("no ISMAS response");
 | |
|             GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE);
 | |
|             QThread::sleep(6);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!triggerValue.contains("WAIT", Qt::CaseInsensitive)) {
 | |
|         QStringList const &lst =
 | |
|             QStringList(QString("check update trigger"))
 | |
|                 << QString("ISMAS_UPDATE-TRIGGER-NOT-SET-OR-WRONG: VALUE=(") + triggerValue + ")";
 | |
|         ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::CHECK_ISMAS_TRIGGER_FAILURE));
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool Worker::customerEnvironment(int progress) {
 | |
|     emit appendText("\nPrepare customer environment ...");
 | |
|     if (QDir(m_customerRepository).exists()) {
 | |
|         startProgressLoop();
 | |
|         // setProgress(m_mainWindow->progressValue()/10 + 11);
 | |
|         if (m_gc.gitCheckoutBranch()) {
 | |
|             stopProgressLoop();
 | |
|             m_ismasClient.setProgressInPercent(progress);
 | |
| 
 | |
|             m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_CHECKOUT_BRANCH,
 | |
|                                     QString("CHECKED-OUT BRANCH ") + m_gc.branchName());
 | |
| 
 | |
|             IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|                                     QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|                                         m_ismasClient.checkoutBranch(m_updateStatus.m_statusDescription, ""));
 | |
| 
 | |
|             emit replaceLast("Prepare customer environment ...", UPDATE_STEP_DONE);
 | |
|             qInfo() << "PREPARE CUSTOMER ENVIRONMENT DONE";
 | |
|             return true;
 | |
|         } else {
 | |
|             stopProgressLoop();
 | |
|             m_ismasClient.setProgressInPercent(0);
 | |
| 
 | |
|             emit showErrorMessage("cust-env",
 | |
|                                   QString("Checkout ") + m_customerRepository + " failed");
 | |
|             Utils::printCriticalErrorMsg(QString("CHECKOUT OF " + m_customerRepository + "FAILED"));
 | |
|         }
 | |
|     } else {
 | |
|         emit showErrorMessage("cust-env", m_customerRepository + " does not exist");
 | |
|         Utils::printCriticalErrorMsg(m_customerRepository + " DOES NOT EXIST");
 | |
|     }
 | |
| 
 | |
|     emit replaceLast("Prepare customer environment ...", UPDATE_STEP_FAIL);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool Worker::filesToUpdate(int progress) {
 | |
|     m_ismasClient.setProgressInPercent(progress);
 | |
| 
 | |
|     emit appendText("\nFetch changes files ...");
 | |
|     startProgressLoop();
 | |
| 
 | |
|     // always execute contents of opkg_commands-file
 | |
|     m_filesToUpdate << "etc/psa_update/opkg_commands";
 | |
| 
 | |
|     if (std::optional<QString> changes = m_gc.gitPull()) {
 | |
|         m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_FETCH_UPDATES,
 | |
|                                         QString("FETCHING OF ") + m_customerRepositoryPath +
 | |
|                                         QString(" INTO ") + m_customerRepository);
 | |
| 
 | |
|         if (std::optional<QStringList> changedFileNames = m_gc.gitDiff(changes.value())) {
 | |
|             if (m_gc.gitPull()) {
 | |
|                 emit replaceLast(QString("Fetch changes files ..."), UPDATE_STEP_DONE);
 | |
|                 m_filesToUpdate << changedFileNames.value();
 | |
|             } else {
 | |
|                 emit showErrorMessage("files to update", "pulling files failed");
 | |
|                 Utils::printCriticalErrorMsg("PULLING FILES FAILED");
 | |
| 
 | |
|                 emit replaceLast(QString("Fetch changes files ..."), UPDATE_STEP_FAIL);
 | |
|                 return false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         Utils::printInfoMsg("FILES-TO-UPDATE " + m_filesToUpdate.join(','));
 | |
| 
 | |
|         m_filesToUpdate.removeDuplicates();
 | |
|         int const size = m_filesToUpdate.size();
 | |
|         if (size > 1) {
 | |
|             emit appendText(QString("Found %1 files to update :").arg(size), UPDATE_STEP_DONE);
 | |
|             for (int i = 0; i < size; ++i) {
 | |
|                 emit appendText(QString("\n ") + m_filesToUpdate.at(i));
 | |
|             }
 | |
|         } else {
 | |
|             emit appendText("Found 1 file to update :", UPDATE_STEP_DONE);
 | |
|             emit appendText(QString("\n ") + m_filesToUpdate.at(0));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool Worker::updateFiles(int percent) {
 | |
|     m_filesToDownload.clear();
 | |
|     m_displayIndex = 0;
 | |
|     startProgressLoop();
 | |
|     for (int i = 0; i < m_filesToUpdate.size(); ++i) {
 | |
|         QString const fName = m_filesToUpdate.at(i);
 | |
|         Utils::printInfoMsg(QString("FNAME ") + fName);
 | |
| 
 | |
|         if (fName.contains("opkg_commands", Qt::CaseInsensitive)) {
 | |
|             emit appendText("\n( ) Update opkg pakets ...");
 | |
|             // execute opkg commands
 | |
|             if (QDir::setCurrent(m_customerRepository)) {
 | |
|                 QFile f(fName);
 | |
|                 if (f.exists()) {
 | |
|                     if (f.open(QIODevice::ReadOnly)) {
 | |
|                         QTextStream in(&f);
 | |
|                         QStringList opkgCommands;
 | |
|                         bool executeOpkgCommandFailed = false;
 | |
|                         while (!in.atEnd()) {
 | |
|                             QString line = in.readLine();
 | |
|                             static const QRegularExpression comment("^\\s*#.*$");
 | |
|                             if (line.indexOf(comment, 0) == -1) {
 | |
|                                 // found opkg command
 | |
|                                 QString opkgCommand = line.trimmed();
 | |
|                                 if (!executeOpkgCommand(opkgCommand)) {
 | |
|                                     executeOpkgCommandFailed = true;
 | |
|                                 } else {
 | |
|                                     QString cmd = "\n  " + opkgCommand;
 | |
|                                     emit appendText(cmd);
 | |
|                                     opkgCommands << cmd;
 | |
| 
 | |
|                                     m_ismasClient.setProgressInPercent(++percent);
 | |
|                                     m_updateStatus = UpdateStatus(UPDATE_STATUS::EXEC_OPKG_COMMAND,
 | |
|                                                         QString("EXEC OPKG-COMMAND ") + opkgCommand);
 | |
|                                     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|                                             QString("#M=APISM#C=CMD_EVENT#J=") +
 | |
|                                                 m_ismasClient.execOpkgCommand(m_updateStatus.m_statusDescription, ""));
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                         f.close();
 | |
|                         if (!executeOpkgCommandFailed) {
 | |
|                             if (opkgCommands.size() > 0) {
 | |
|                                 m_displayIndex = 1;
 | |
|                                 QString prepend = QString("(") + QString("%1").arg(m_displayIndex).rightJustified(3, ' ') + QString(")")
 | |
|                                                     + QString(" Update opkg pakets ... ");
 | |
|                                 opkgCommands.prepend(prepend);
 | |
|                                 emit replaceLast(opkgCommands, UPDATE_STEP_DONE);
 | |
|                             }
 | |
|                         } else {
 | |
|                             m_displayIndex = 1;
 | |
|                             emit replaceLast(QString("(") + QString("%1").arg(m_displayIndex).rightJustified(3, ' ') + QString(")")
 | |
|                                           + QString(" Update opkg pakets ... "), UPDATE_STEP_FAIL);
 | |
| 
 | |
|                             return false;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         } else
 | |
|         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 {
 | |
|             static const QRegularExpression version("^.*dc2c[.][0-9]{1,2}[.][0-9]{1,2}[.]bin.*$");
 | |
|             if (fName.contains(version)) {
 | |
|                 m_filesToDownload << fName; // download device controller
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (m_filesToDownload.size() > 0) {
 | |
|         Utils::printInfoMsg(QString("FILES_TO_DOWNLOAD_TO_PSA_HW ") + m_filesToDownload.join(','));
 | |
| 
 | |
|         Update *update = m_mainWindow->getUpdate();
 | |
|         if (update) {
 | |
|             return update->doUpdate(m_displayIndex, m_filesToDownload);
 | |
|         } else {
 | |
|             Utils::printCriticalErrorMsg("UPDATE NOT SET");
 | |
|         }
 | |
|     } else {
 | |
|         Utils::printCriticalErrorMsg("NO FILES_TO_DOWNLOAD_TO_PSA_HW");
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool Worker::syncCustomerRepositoryAndFS(int progress) {
 | |
|     m_ismasClient.setProgressInPercent(progress);
 | |
|     // this step is currently needed only for updating tariff-files
 | |
|     emit appendText("\nSync customer environment with filesystem ...");
 | |
|     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")) {
 | |
|                 qCritical() << "COULD NOT EXECUTE '" << md.command() << "' exitCode=(" << md.exitCode() << ")";
 | |
|             }
 | |
|             QString const params("-vvv                    "
 | |
|                                  "--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) {
 | |
|                 // 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)) {
 | |
|                     emit replaceLast(QString("Sync customer environment with filesystem ..."), UPDATE_STEP_DONE);
 | |
|                     return true;
 | |
|                 } else {
 | |
|                     // TODO: send message to ISMAS
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     emit replaceLast(QString("Sync customer environment with filesystem ..."), UPDATE_STEP_FAIL);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool Worker::sendIsmasLastVersionNotification(int progress) {
 | |
|     m_ismasClient.setProgressInPercent(progress);
 | |
|     IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
 | |
|             QString("#M=APISM#C=CMD_SENDVERSION#J=") +
 | |
|                 m_ismasClient.updateOfPSASendVersion(getPSAInstalled()));
 | |
|     emit appendText(QString("Send last version info "), UPDATE_STEP_DONE);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool Worker::saveLogFile(int progress) {
 | |
|     m_ismasClient.setProgressInPercent(progress);
 | |
|     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::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::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");
 | |
|     hwinf *hwi = m_mainWindow->getPlugin();
 | |
|     if (hwi) {
 | |
|         hwi->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 = hwi->dc_getHWversion().toUtf8();
 | |
|             sw = hwi->dc_getSWversion().toUtf8();
 | |
|             if (!hw.startsWith(cmp)) {
 | |
|                 lst.clear();
 | |
|                 qInfo() << hw << sw;
 | |
|                 lst << hw << sw;
 | |
|                 break;
 | |
|             }
 | |
|             QThread::sleep(1);
 | |
|         }
 | |
|     }
 | |
|     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 = "";
 | |
|     psaInstalled.versionInfo.reason = "";
 | |
|     psaInstalled.versionInfo.created = "";
 | |
| 
 | |
|     QStringList versionInfo = m_gc.gitShowReason(m_branchName);
 | |
|     if (versionInfo.size() == 3) {
 | |
|         psaInstalled.versionInfo.lastCommit = versionInfo.at(0);
 | |
|         psaInstalled.versionInfo.reason = versionInfo.at(1);
 | |
|         psaInstalled.versionInfo.created = versionInfo.at(2);
 | |
|     }
 | |
| 
 | |
|     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 = "Szeged";
 | |
|     psaInstalled.tariff.info = "N/A";
 | |
|     psaInstalled.tariff.version = "N/A";
 | |
| 
 | |
|     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;
 | |
| 
 | |
|     if (std::optional<QString> v = getApismVersion()) {
 | |
|         psaInstalled.sw.apismVersion = v.value();
 | |
|     }
 | |
|     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;
 | |
| 
 | |
|     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);
 | |
| 
 | |
|     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);
 | |
| 
 | |
|     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);
 | |
| 
 | |
|     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);
 | |
|     }
 | |
| 
 | |
|     return psaInstalled;
 | |
| }
 | |
| 
 | |
| hwinf *Worker::getPlugin() {
 | |
|     return m_mainWindow ? m_mainWindow->getPlugin() : nullptr;
 | |
| }
 | |
| 
 | |
| hwinf const *Worker::getPlugin() const {
 | |
|     return m_mainWindow ? m_mainWindow->getPlugin() : nullptr;
 | |
| }
 |