diff --git a/ATBUpdateTool.pro b/ATBUpdateTool.pro index 8785582..c12ccae 100644 --- a/ATBUpdateTool.pro +++ b/ATBUpdateTool.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = Check Show DownloadDCFirmware DownloadDCJsonFiles Opkg Sync UpdatePTUDevCtrl +SUBDIRS = Check Show DownloadDCFirmware DownloadDCJsonFiles Git Opkg Sync UpdatePTUDevCtrl diff --git a/Check/Check.pro b/Check/Check.pro index b2fec1f..37e2057 100644 --- a/Check/Check.pro +++ b/Check/Check.pro @@ -65,11 +65,13 @@ contains( CONFIG, DesktopLinux ) { SOURCES += \ main.cpp \ ismas_client.cpp \ - message_handler.cpp + message_handler.cpp \ + ../common/src/utils_internal.cpp HEADERS += \ ismas_client.h \ - message_handler.h + message_handler.h \ + ../common/include/utils_internal.h ########################################################################################## # for running program on target through QtCreator diff --git a/Check/main.cpp b/Check/main.cpp index b1d5f4f..afab05c 100644 --- a/Check/main.cpp +++ b/Check/main.cpp @@ -19,6 +19,7 @@ #include #include "message_handler.h" +#include "utils_internal.h" #include "ismas_client.h" @@ -40,6 +41,7 @@ int main(int argc, char **argv) { setDebugLevel(LOG_NOTICE); } + int exitCode = 0; QCommandLineParser parser; QCommandLineOption ismasConnectOption("ismas-connected"); QCommandLineOption updateRequestedOption("update-requested"); @@ -49,8 +51,9 @@ int main(int argc, char **argv) { parser.addOption(verboseOption); parser.process(a); - QString connectionStatus{"not connected"}; - QString updateRequestStatus{"not requested"}; + QString connectionStatus{internal::ISMAS_NOT_CONNECTED}; + QString updateRequestStatus{internal::UPDATE_NOT_REQUESTED}; + QDebug debug = qCritical(); if (std::optional result = IsmasClient::sendRequestReceiveResponse( @@ -64,20 +67,20 @@ int main(int argc, char **argv) { if (it != o.constEnd()) { // value for "Broker" QString const &v = it->toString(); - if (v.contains("connected", Qt::CaseInsensitive)) { - connectionStatus = "connected"; + if (v.contains(internal::ISMAS_CONNECTED, Qt::CaseInsensitive)) { + connectionStatus = internal::ISMAS_CONNECTED; } else - if (v.contains("not connected", Qt::CaseInsensitive)) { - connectionStatus = "not connected"; + if (v.contains(internal::ISMAS_NOT_CONNECTED, Qt::CaseInsensitive)) { + connectionStatus = internal::ISMAS_NOT_CONNECTED; } else - if (v.contains("disconnected", Qt::CaseInsensitive)) { - connectionStatus = "not connected"; + if (v.contains(internal::ISMAS_DISCONNECTED, Qt::CaseInsensitive)) { + connectionStatus = internal::ISMAS_NOT_CONNECTED; } else - if (v.contains("connecting", Qt::CaseInsensitive)) { - connectionStatus = "not connected"; + if (v.contains(internal::ISMAS_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) { + connectionStatus = internal::ISMAS_NOT_CONNECTED; } else - if (v.contains("disconnecting", Qt::CaseInsensitive)) { - connectionStatus = "not connected"; + if (v.contains(internal::ISMAS_DISCONNECTING, Qt::CaseInsensitive)) { + connectionStatus = internal::ISMAS_NOT_CONNECTED; } break; } @@ -85,65 +88,68 @@ int main(int argc, char **argv) { } } + if (connectionStatus != internal::ISMAS_CONNECTED) { + if (internal::customerRepoExists() == false) { + debug.noquote() << internal::NO_CUSTOMER_REPOSITORY; + } + } + if (parser.isSet(updateRequestedOption)) { - if (connectionStatus == "connected") { - if (std::optional result - = IsmasClient::sendRequestReceiveResponse( - IsmasClient::APISM::DIRECT_PORT, - "#M=APISM#C=REQ_ISMASPARAMETER#J={}")) { + if (internal::customerRepoExists() == false) { + // if the customer repository does not exists, it does not matter is + // ISMAS is connected or how the setting for the WAIT-button is. + updateRequestStatus = internal::NO_CUSTOMER_REPOSITORY; + } else { + if (connectionStatus == internal::ISMAS_CONNECTED) { + if (std::optional result + = IsmasClient::sendRequestReceiveResponse( + IsmasClient::APISM::DIRECT_PORT, + "#M=APISM#C=REQ_ISMASPARAMETER#J={}")) { - QJsonDocument d = QJsonDocument::fromJson(result.value().toUtf8()); - for (QString const &k : d.object().keys()) { - if (k.contains("REQ_ISMASPARAMETER")) { - QJsonObject o = d.object()[k].toObject(); - - QJsonObject::const_iterator it = o.find("Aknoledge"); - if (it == o.constEnd()) continue; - - QString const &v = it->toString(); - if (v != "OK") break; - - for (QString const &k : d.object().keys()) { // request ack - if (!k.contains("FileUpload", Qt::CaseInsensitive)) continue; + QJsonDocument d = QJsonDocument::fromJson(result.value().toUtf8()); + for (QString const &k : d.object().keys()) { + if (k.contains("REQ_ISMASPARAMETER")) { QJsonObject o = d.object()[k].toObject(); - QJsonObject::const_iterator it = o.find("TRG"); - if (it == o.constEnd()) break; + QJsonObject::const_iterator it = o.find("Aknoledge"); + if (it == o.constEnd()) continue; QString const &v = it->toString(); - if (v == "WAIT") { - updateRequestStatus = "requested"; - } else - if (v.isEmpty()) { - QFile f("/mnt/system_data/cust_nr"); - if (!f.exists()) break; - if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) break; + if (v != "OK") break; - QTextStream in(&f); - in.setCodec("UTF-8"); - if(!in.atEnd()) { - unsigned custNr = in.readLine().toInt(); - if (custNr > 0) { - QString custRepo = QString("/opt/app/tools/atbupdate/customer_%1").arg(custNr); - if (!QDir(custRepo).exists()) { - updateRequestStatus = "not necessary"; - } - } + for (QString const &m : d.object().keys()) { // request ack + if (!m.contains("FileUpload", Qt::CaseInsensitive)) continue; + QJsonObject o = d.object()[m].toObject(); + + QJsonObject::const_iterator it = o.find("TRG"); + if (it == o.constEnd()) break; + + QString const &v = it->toString(); + if (v == "WAIT") { + updateRequestStatus = internal::UPDATE_REQUESTED; + } else { + updateRequestStatus = internal::UPDATE_NOT_NECESSARY; } + break; } break; } - break; } } + } else { + // not connected (so its unknown if update has been requested), + // and customer repository exists. Assume 'not requested'. + updateRequestStatus = internal::UPDATE_NOT_REQUESTED; + exitCode = -1; } } - qCritical() << updateRequestStatus; - } - + debug.noquote() << updateRequestStatus; + } else if (parser.isSet(ismasConnectOption)) { - qCritical() << connectionStatus; + debug.noquote() << connectionStatus; } - return 0; + qCritical() << __func__ << ":" << __LINE__ << exitCode; + + return exitCode; } diff --git a/Git/Git.pro b/Git/Git.pro index e69de29..cb18089 100644 --- a/Git/Git.pro +++ b/Git/Git.pro @@ -0,0 +1,84 @@ +QT += core + +TARGET = ATBUpdateGit + +VERSION="1.0.0" +win32 { + BUILD_DATE=$$system("date /t") + BUILD_TIME=$$system("time /t") +} else { + BUILD_DATE=$$system("date +%d-%m-%y") + BUILD_TIME=$$system("date +%H:%M:%S") +} + +GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1") + +EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}" + + +INCLUDEPATH += \ + plugins \ + $${INCLUDEINTERFACES} \ + $${_PRO_FILE_PWD_}/../common/include + +CONFIG += c++17 + +DEFINES+=APP_VERSION=\\\"$$VERSION\\\" +DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\" +DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\" +DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\" + +# keep comments, as /* fall through */ +QMAKE_CXXFLAGS += -C +QMAKE_CXXFLAGS += -g +QMAKE_CXXFLAGS += -Wno-deprecated-copy -O + +contains( CONFIG, PTU5 ) { + CONFIG += link_pkgconfig + QMAKE_CXXFLAGS += -O2 -std=c++17 # for GCC >= 4.7 + # QMAKE_CXXFLAGS += -Wno-deprecated-copy + PTU5BASEPATH = /opt/devel/ptu5 + + INCLUDEPATH += $$PTU5BASEPATH/qt/libs/devicecontroller/include + LIBS += -L$$PTU5BASEPATH/qt/libs/devicecontroller/library + + ARCH = PTU5 + DEFINES+=PTU5 +} +contains( CONFIG, PTU5_YOCTO ) { + QMAKE_CXXFLAGS += -std=c++17 # for GCC >= 4.7 + # QMAKE_CXXFLAGS += -Wno-deprecated-copy + PTU5BASEPATH = /opt/devel/ptu5 + ARCH = PTU5 + DEFINES+=PTU5 +} +contains( CONFIG, DesktopLinux ) { + # QMAKE_CC = ccache $$QMAKE_CC + # QMAKE_CXX = ccache $$QMAKE_CXX + QMAKE_CXXFLAGS += -std=c++17 + # QMAKE_CXXFLAGS += -Wno-deprecated-copy + linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments } + ARCH = DesktopLinux + DEFINES+=DesktopLinux +} + +SOURCES += \ + main.cpp \ + message_handler.cpp \ + ../common/src/utils_internal.cpp \ + ../common/src/command.cpp \ + git_command.cpp + +HEADERS += \ + message_handler.h \ + ../common/include/utils_internal.h \ + ../common/include/command.h \ + git_command.h + +########################################################################################## +# for running program on target through QtCreator +contains( CONFIG, PTU5 ) { + qnx: target.path = /tmp/$${TARGET}/bin + else: unix:!android: target.path = /opt/app/tools/atbupdate/ + !isEmpty(target.path): INSTALLS += target +} diff --git a/Git/git_command.cpp b/Git/git_command.cpp new file mode 100644 index 0000000..7fb926c --- /dev/null +++ b/Git/git_command.cpp @@ -0,0 +1,96 @@ +#include "git_command.h" + +#include "command.h" +#include "utils_internal.h" +using namespace internal; + +#include +#include +#include +#include +#include + +bool GitCommand::initEnv = false; +static bool initEnv() { + QString gitSSHCommand{""}; + QByteArray const v = qgetenv("GIT_SSH_COMMAND"); + if (v.isEmpty()) { + QString sshKeyFile("/opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig"); + if (QFileInfo(sshKeyFile).exists()) { + if (qgetenv("GIT_SSH_COMMAND").isNull()) { + gitSSHCommand = "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig"; + if (!qputenv("GIT_SSH_COMMAND", QByteArray(gitSSHCommand.toStdString().c_str()))) { + qCritical() << "ERROR: GIT_SSH_COMMAND not put into env. Exiting..."; + return false; + } + } + } else { + qCritical() << "ERROR ssh-key-file" << sshKeyFile << "does not exists. Exiting..."; + return false; + } + } else { + gitSSHCommand = QString(v.toStdString().c_str()); + qCritical() << "WARNING GIT_SSH_COMMAND already set in enviroment:" + << gitSSHCommand; + if (gitSSHCommand != "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig") { + qCritical() << "ERROR" << gitSSHCommand << "wrong. Exiting..."; + return false; + } + } + // qCritical() << __func__ << ":" << __LINE__ << gitSSHCommand; + return true; +} + +GitCommand::GitCommand() + : m_workingDirectory(customerRepoDir()) { + // qCritical() << __func__ << ":" << __LINE__ << m_workingDirectory; + if (!GitCommand::initEnv) { + GitCommand::initEnv = ::initEnv(); + } +} + +bool GitCommand::exec(QStringList const &options, int start_timeout, int finish_timeout) { + if (GitCommand::initEnv) { + Command cmd(QString("git"), options, m_workingDirectory, + start_timeout, finish_timeout); + return cmd.exec(); + } + return 0; +} + +bool GitCommand::check(int start_timeout, int finish_timeout) { + QStringList const lst{"fsck"}; + return exec(lst, start_timeout, finish_timeout); +} + +bool GitCommand::checkout(int start_timeout, int finish_timeout) { + int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr"); + if (zoneNr != -1) { + QStringList const lst{"checkout", QString("zg1/zone%1").arg(zoneNr)}; + // qCritical() << __func__ << __LINE__ << lst; + return exec(lst, start_timeout, finish_timeout); + } + return false; +} + +bool GitCommand::clone(int start_timeout, int finish_timeout) { + m_workingDirectory = customerRepoRoot(); // /opt/app/tools/atbupdate ! + QDir const repoDir{customerRepoDir()}; + if (repoDir.exists() && repoDir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries).count() != 0) { + qCritical() << "clone error:" << repoDir << "exists and is not empty"; + return false; + } + // git clone "gitea@ptu-config.atb-comm.de:ATB/customer_999" + QStringList const lst{"clone", repositoryUrl() + customerRepoDirName()}; + return exec(lst, start_timeout, finish_timeout); +} + +bool GitCommand::pull(int start_timeout, int finish_timeout) { + QStringList const lst{"pull"}; + return exec(lst, start_timeout, finish_timeout); +} + +bool GitCommand::status(int start_timeout, int finish_timeout) { + QStringList const lst{"status"}; + return exec(lst, start_timeout, finish_timeout); +} diff --git a/Git/git_command.h b/Git/git_command.h new file mode 100644 index 0000000..88d1f02 --- /dev/null +++ b/Git/git_command.h @@ -0,0 +1,25 @@ +#ifndef GIT_COMMAND_H_INCLUDED +#define GIT_COMMAND_H_INCLUDED + +#include +#include + +class QProcess; +class GitCommand { + static bool initEnv; + QString m_workingDirectory; + + bool exec(QStringList const &options, int start_timeout = 100000, + int finish_timeout = 100000); +public: + GitCommand(); + + + bool status(int start_timeout = 100000, int finish_timeout = 100000); + bool check(int start_timeout = 100000, int finish_timeout = 100000); + bool checkout(int start_timeout = 100000, int finish_timeout = 100000); + bool clone(int start_timeout = 100000, int finish_timeout = 100000); + bool pull(int start_timeout = 100000, int finish_timeout = 100000); +}; + +#endif // GIT_COMMAND_H_INCLUDED diff --git a/Git/main.cpp b/Git/main.cpp index e69de29..96a5ab7 100644 --- a/Git/main.cpp +++ b/Git/main.cpp @@ -0,0 +1,105 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "message_handler.h" +#include "utils_internal.h" +#include "git_command.h" + +int main(int argc, char **argv) { + QByteArray const value = qgetenv("LC_ALL"); + if (value.isEmpty() || value != "C") { + qputenv("LC_ALL", "C"); + } + + openlog("ATB-UPDATE-GIT", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + + QCoreApplication a(argc, argv); + QCoreApplication::setApplicationName("ATBUpdateGit"); + QCoreApplication::setApplicationVersion(APP_VERSION); + + if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling + atbInstallMessageHandler(nullptr); + //atbInstallMessageHandler(atbDebugOutput); + setDebugLevel(LOG_NOTICE); + } + + QCommandLineParser parser; + parser.setApplicationDescription("git-commands for the update-system"); + + QCommandLineOption const checkCustomerRepositoryOption{"check"}; + QCommandLineOption const cloneCustomerRepositoryOption{"clone"}; + QCommandLineOption const pullBranchOption{"pull"}; + QCommandLineOption const checkoutBranchOption("checkout"); + + parser.addOption(checkCustomerRepositoryOption); + parser.addOption(cloneCustomerRepositoryOption); + parser.addOption(pullBranchOption); + parser.addOption(checkoutBranchOption); + + QCommandLineOption verboseOption{parser.addVersionOption()}; + parser.process(a); + + if (parser.isSet(verboseOption)) { + parser.showVersion(); + return 0; + } + + GitCommand gitCmd; + + if (parser.isSet(checkCustomerRepositoryOption)) { + if (!gitCmd.check()) { + return -1; + } + } else + if (parser.isSet(checkoutBranchOption)) { + if (!gitCmd.checkout()) { + return -2; + } + } else + if (parser.isSet(cloneCustomerRepositoryOption)) { + if (!gitCmd.clone()) { + return -3; + } + } else + if (parser.isSet(pullBranchOption)) { + if (!gitCmd.pull()) { + return -4; + } + } else { + if (internal::customerRepoExists()) { + if (!gitCmd.checkout()) { + return -2; + } + if (!gitCmd.pull()) { + return -4; + } + } else { + if (!gitCmd.clone()) { + return -3; + } + } + } + + //int const machineNr = read1stLineOfFile("/mnt/system_data/machine_nr"); + //int const customerNr = read1stLineOfFile("/mnt/system_data/cust_nr"); + //int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr"); + + return 0; +} diff --git a/Git/message_handler.cpp b/Git/message_handler.cpp new file mode 100755 index 0000000..996bd2f --- /dev/null +++ b/Git/message_handler.cpp @@ -0,0 +1,97 @@ +#include "message_handler.h" + +#include +#include +#include +#include +#include + + +static char const *DBG_NAME[] = { "DBG ", "WARN ", "CRIT ", "FATAL", "INFO " }; +static bool installedMsgHandler = false; +static int debugLevel = LOG_NOTICE; + +int getDebugLevel() { return debugLevel; } +void setDebugLevel(int newDebugLevel) { + debugLevel = newDebugLevel; +} + +bool messageHandlerInstalled() { + return installedMsgHandler; +} + +QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) { + installedMsgHandler = (handler != 0); + static QtMessageHandler prevHandler = nullptr; + if (handler) { + prevHandler = qInstallMessageHandler(handler); + return prevHandler; + } else { + return qInstallMessageHandler(prevHandler); + } +} + +/// +/// \brief Print message according to given debug level. +/// +/// \note Install this function using qInstallMsgHandler(). +/// +/// int main(int argc, char **argv) { +/// installMsgHandler(atbDebugOutput); +/// QApplication app(argc, argv); +/// ... +/// return app.exec(); +/// } +/// +#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) +void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + Q_UNUSED(context); + QString const localMsg = QString(DBG_NAME[type]) + msg.toLocal8Bit(); + + switch (debugLevel) { + case LOG_DEBUG: { // debug-level message + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } break; + case LOG_INFO: { // informational message + if (type != QtDebugMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_NOTICE: { // normal, but significant, condition + if (type != QtDebugMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_WARNING: { // warning conditions + if (type != QtInfoMsg && type != QtDebugMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_ERR: { // error conditions + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_CRIT: { // critical conditions + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_ALERT: { // action must be taken immediately + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_EMERG: { // system is unusable + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + default: { + //fprintf(stderr, "%s No ErrorLevel defined! %s\n", + // datetime.toStdString().c_str(), msg.toStdString().c_str()); + } + } +} +#endif + diff --git a/Git/message_handler.h b/Git/message_handler.h new file mode 100755 index 0000000..98c4d7e --- /dev/null +++ b/Git/message_handler.h @@ -0,0 +1,23 @@ +#ifndef MESSAGE_HANDLER_H_INCLUDED +#define MESSAGE_HANDLER_H_INCLUDED + +#include +#ifdef __linux__ +#include +#endif + +int getDebugLevel(); +void setDebugLevel(int newDebugLevel); + +bool messageHandlerInstalled(); +QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler); + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +// typedef void (*QtMessageHandler)(QtMsgType, const char *); +void atbDebugOutput(QtMsgType type, const char *msg); +#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +// typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &); +void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); +#endif + +#endif // MESSAGE_HANDLER_H_INCLUDED diff --git a/UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro b/UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro index 5f386b5..b0e9e1b 100644 --- a/UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro +++ b/UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro @@ -216,7 +216,9 @@ GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1") EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}" -INCLUDEPATH += plugins +# INCLUDEPATH += plugins +INCLUDEPATH += plugins \ + $${_PRO_FILE_PWD_}/../common/include CONFIG += c++17 # CONFIG -= app_bundle @@ -291,7 +293,8 @@ SOURCES += \ message_handler.cpp \ worker.cpp \ commandline_parser.cpp \ - work_process_list.cpp + work_process_list.cpp \ + ../common/src/utils_internal.cpp HEADERS += \ update.h \ @@ -315,7 +318,8 @@ HEADERS += \ message_handler.h \ worker.h \ commandline_parser.h \ - work_process_list.h + work_process_list.h \ + ../common/include/utils_internal.h OTHER_FILES += \ diff --git a/UpdatePTUDevCtrl/main.cpp b/UpdatePTUDevCtrl/main.cpp index 4319e29..89c6d45 100644 --- a/UpdatePTUDevCtrl/main.cpp +++ b/UpdatePTUDevCtrl/main.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #if defined (Q_OS_UNIX) || defined (Q_OS_LINUX) #include @@ -48,6 +49,17 @@ #define SERIAL_PORT "ttyUSB0" #endif +//QString Orientation(Qt::ScreenOrientation orientation) { +// switch (orientation) { +// case Qt::PrimaryOrientation : return "Primary"; +// case Qt::LandscapeOrientation : return "Landscape"; +// case Qt::PortraitOrientation : return "Portrait"; +// case Qt::InvertedLandscapeOrientation : return "Inverted landscape"; +// case Qt::InvertedPortraitOrientation : return "Inverted portrait"; +// default : return "Unknown"; +// } +//} + // argv[1]: file to send to dc int main(int argc, char *argv[]) { QByteArray const value = qgetenv("LC_ALL"); @@ -70,6 +82,15 @@ int main(int argc, char *argv[]) { setDebugLevel(LOG_NOTICE); } + //qCritical() << "Number of screens:" << QGuiApplication::screens().size(); + //qCritical() << "Primary screen:" << QGuiApplication::primaryScreen()->name(); + + //foreach (QScreen *screen, QGuiApplication::screens()) { + // qDebug() << "Information for screen:" << screen->name(); + // qDebug() << " Orientation:" << Orientation(screen->orientation()); + //} + //return 0; + CommandLineParser parser; parser.process(a); parser.readSettings(); diff --git a/UpdatePTUDevCtrl/mainwindow.cpp b/UpdatePTUDevCtrl/mainwindow.cpp index 727a48f..f1725bf 100644 --- a/UpdatePTUDevCtrl/mainwindow.cpp +++ b/UpdatePTUDevCtrl/mainwindow.cpp @@ -2,6 +2,7 @@ #include "ui_mainwindow.h" #include "worker.h" #include "utils.h" +#include "utils_internal.h" #include "progress_event.h" #include "update_dc_event.h" #include "process/update_command.h" @@ -158,14 +159,27 @@ void MainWindow::onShowISMASConnectivity(QString status) { tmp += " "; } + bool const custRepoExists = internal::customerRepoExists(); + if (status.contains(UpdateCommand::ISMAS_CONNECTED, Qt::CaseInsensitive)) { - s += QString("%1 connected
").arg(tmp); + if (custRepoExists) { + s += QString("%1 connected
").arg(tmp); + } else { + s += QString("%1 connected (initial configuration)
").arg(tmp); + } + } else + if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) { + s += QString("%1 NOT CONNECTED
").arg(tmp); } else if (status.contains(UpdateCommand::ISMAS_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) { s += QString("%1 connecting
").arg(tmp); } else if (status.contains(UpdateCommand::ISMAS_NOT_CONNECTED, Qt::CaseInsensitive)) { - s += QString( "%1 NOT CONNECTED
").arg(tmp); + if (custRepoExists) { + s += QString( "%1 NOT CONNECTED. STOP
").arg(tmp); + } else { + s += QString( "%1 not connected. (initial configuration)
").arg(tmp); + } } else { s += QString( "%1 UNKNOWN STATUS
").arg(tmp); } @@ -291,16 +305,29 @@ void MainWindow::onShowUpdateRequest(QString status) { tmp += " "; } + bool const custRepoExists = internal::customerRepoExists(); + if (status.contains(UpdateCommand::UPDATE_NOT_REQUESTED, Qt::CaseInsensitive)) { - s += QString( "%1 NOT REQUESTED
").arg(tmp); + if (custRepoExists) { + s += QString( "%1 NOT REQUESTED. STOP.
").arg(tmp); + } else { + s += QString("%1 not requested (initial configuration)
").arg(tmp); + } } else if (status.contains(UpdateCommand::UPDATE_REQUESTED, Qt::CaseInsensitive)) { - s += QString("%1 requested
").arg(tmp); + if (custRepoExists) { + s += QString("%1 requested
").arg(tmp); + } else { + s += QString("%1 requested (initial configuration)
").arg(tmp); + } } else if (status.contains(UpdateCommand::UPDATE_NOT_NECESSARY, Qt::CaseInsensitive)) { s += QString("%1 not necessary
").arg(tmp); + } else + if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) { + s += QString("%1 UNKNOWN (ISMAS not connected)
").arg(tmp); } else { - s += QString( "%1 UNKNOWN STATUS
").arg(tmp); + s += QString( "%1 UNKNOWN
").arg(tmp); } ui->stepLabel->setText(s); diff --git a/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.cpp b/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.cpp index bc42aa6..06e98cc 100644 --- a/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.cpp +++ b/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.cpp @@ -1,21 +1,44 @@ #include "process/check_and_fetch_customer_repository_command.h" #include "worker.h" +#include "utils_internal.h" CheckAndFetchCustomerRepositoryCommand::CheckAndFetchCustomerRepositoryCommand( - QString const &command, Worker *worker, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + QString const &command, Worker *worker, int nextCommandIndex, + int start_timeout, int finish_timeout) + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + +void CheckAndFetchCustomerRepositoryCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + qCritical() << __func__ << ":" << __LINE__ << command() << exitCode << exitStatus; + Worker *w = worker(); + if (w) { + switch (exitCode) { + case -2: + emit w->showCustRepoStatus(internal::GIT_CUSTOMER_REPO_CHECKOUT_ERROR); + break; + case -4: + emit w->showCustRepoStatus(internal::GIT_CUSTOMER_REPO_PULL_ERROR); + break; + case 0: + emit w->showCustRepoStatus(internal::GIT_CUSTOMER_REPO_UP_TO_DATE); + default:; + } + } + + return UpdateCommand::finished(exitCode, exitStatus); } void CheckAndFetchCustomerRepositoryCommand::readyReadStandardOutput() { - QProcess *p = (QProcess *)sender(); - if (p) { - QString s = p->readAllStandardOutput(); + //QProcess *p = (QProcess *)sender(); + //if (p) { + // Worker *w = worker(); + // if (w) { + // QString s = p->readAllStandardOutput().trimmed(); + // + // qCritical() << __func__ << ":" << __LINE__ << s; - // TODO - Worker *w = worker(); - if (w) { // static constexpr const char *GIT_CUSTOMER_REPO_UP_TO_DATE{"up to date"}; - emit w->showCustRepoStatus(UpdateCommand::GIT_CUSTOMER_REPO_UP_TO_DATE); - } - } + // emit w->showCustRepoStatus(UpdateCommand::GIT_CUSTOMER_REPO_UP_TO_DATE); + // } + //} } diff --git a/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.h b/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.h index 2c43a5b..71054b5 100644 --- a/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.h +++ b/UpdatePTUDevCtrl/process/check_and_fetch_customer_repository_command.h @@ -7,10 +7,12 @@ class CheckAndFetchCustomerRepositoryCommand : public UpdateCommand { public: explicit CheckAndFetchCustomerRepositoryCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // CHECK_AND_FETCH_CUSTOMER_REPOSITORY_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.cpp b/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.cpp index dd94aa9..e707592 100644 --- a/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.cpp +++ b/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.cpp @@ -5,23 +5,34 @@ CheckIsmasConnectivityCommand::CheckIsmasConnectivityCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + +void CheckIsmasConnectivityCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + return UpdateCommand::finished(exitCode, exitStatus); } void CheckIsmasConnectivityCommand::readyReadStandardOutput() { QProcess *p = (QProcess *)sender(); if (p) { - QString s = p->readAllStandardOutput(); - - // TODO Worker *w = worker(); if (w) { - //static constexpr const char *ISMAS_CONNECTED{"connected"}; - //static constexpr const char *ISMAS_NOT_CONNECTED{"not connected"}; - //static constexpr const char *ISMAS_CONNECTION_IN_PROGRESS{"connecting"}; - emit w->showISMASConnectivity(UpdateCommand::ISMAS_CONNECTED); + QString s = p->readAllStandardOutput().trimmed(); + if (s == UpdateCommand::ISMAS_CONNECTED) { + emit w->showISMASConnectivity(UpdateCommand::ISMAS_CONNECTED); + } else + if (s == UpdateCommand::NO_CUSTOMER_REPOSITORY) { + emit w->showISMASConnectivity(UpdateCommand::NO_CUSTOMER_REPOSITORY); + } else + if (s == UpdateCommand::ISMAS_NOT_CONNECTED) { + emit w->showISMASConnectivity(UpdateCommand::ISMAS_NOT_CONNECTED); + } else + if (s == UpdateCommand::ISMAS_CONNECTION_IN_PROGRESS) { + emit w->showISMASConnectivity(UpdateCommand::ISMAS_CONNECTION_IN_PROGRESS); + } } } } diff --git a/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.h b/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.h index cf4bb78..6733147 100644 --- a/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.h +++ b/UpdatePTUDevCtrl/process/check_ismas_connectivity_command.h @@ -7,10 +7,12 @@ class CheckIsmasConnectivityCommand : public UpdateCommand { public: explicit CheckIsmasConnectivityCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // CHECK_ISMAS_CONNECTIVITY_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/check_update_activation_command.cpp b/UpdatePTUDevCtrl/process/check_update_activation_command.cpp index 1d7960f..3210796 100644 --- a/UpdatePTUDevCtrl/process/check_update_activation_command.cpp +++ b/UpdatePTUDevCtrl/process/check_update_activation_command.cpp @@ -5,23 +5,35 @@ CheckUpdateActivationCommand::CheckUpdateActivationCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + +void CheckUpdateActivationCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + qCritical() << __func__ << ":" << __LINE__ << command() << exitCode << exitStatus; + return UpdateCommand::finished(exitCode, exitStatus); } void CheckUpdateActivationCommand::readyReadStandardOutput() { QProcess *p = (QProcess *)sender(); if (p) { - QString s = p->readAllStandardOutput(); - - // TODO Worker *w = worker(); if (w) { - //static constexpr const char *UPDATE_NOT_NECESSARY{"not necessary"}; - //static constexpr const char *UPDATE_NOT_REQUESTED{"not requested"}; - //static constexpr const char *UPDATE_REQUESTED{"requested"}; - emit w->showUpdateRequest(UpdateCommand::UPDATE_REQUESTED); + QString s = p->readAllStandardOutput().trimmed(); + if (s == UpdateCommand::UPDATE_REQUESTED) { + emit w->showUpdateRequest(UpdateCommand::UPDATE_REQUESTED); + } else + if (s == UpdateCommand::UPDATE_NOT_NECESSARY) { + emit w->showUpdateRequest(UpdateCommand::UPDATE_NOT_NECESSARY); + } else + if (s == UpdateCommand::UPDATE_NOT_REQUESTED) { + emit w->showUpdateRequest(UpdateCommand::UPDATE_NOT_REQUESTED); + } else + if (s == UpdateCommand::NO_CUSTOMER_REPOSITORY) { + emit w->showUpdateRequest(UpdateCommand::NO_CUSTOMER_REPOSITORY); + } } } } diff --git a/UpdatePTUDevCtrl/process/check_update_activation_command.h b/UpdatePTUDevCtrl/process/check_update_activation_command.h index a738630..7f19511 100644 --- a/UpdatePTUDevCtrl/process/check_update_activation_command.h +++ b/UpdatePTUDevCtrl/process/check_update_activation_command.h @@ -7,10 +7,12 @@ class CheckUpdateActivationCommand : public UpdateCommand { public: explicit CheckUpdateActivationCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // CHECK_UPDATE_ACTIVATION_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/exec_opkg_command.cpp b/UpdatePTUDevCtrl/process/exec_opkg_command.cpp index d428d47..9c49a7f 100644 --- a/UpdatePTUDevCtrl/process/exec_opkg_command.cpp +++ b/UpdatePTUDevCtrl/process/exec_opkg_command.cpp @@ -3,13 +3,18 @@ ExecOpkgCommand::ExecOpkgCommand(QString const &command, Worker *worker, + int nextCommandIndex, bool noaction, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) , m_noaction(noaction) { } +void ExecOpkgCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + return UpdateCommand::finished(exitCode, exitStatus); +} + void ExecOpkgCommand::readyReadStandardOutput() { QProcess *p = (QProcess *)sender(); if (p) { diff --git a/UpdatePTUDevCtrl/process/exec_opkg_command.h b/UpdatePTUDevCtrl/process/exec_opkg_command.h index 3ae124c..0931d06 100644 --- a/UpdatePTUDevCtrl/process/exec_opkg_command.h +++ b/UpdatePTUDevCtrl/process/exec_opkg_command.h @@ -9,11 +9,13 @@ class ExecOpkgCommand : public UpdateCommand { public: explicit ExecOpkgCommand(QString const &command, Worker *worker, + int nextCommandIndex, bool noaction, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // EXEC_OPKG_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/show_software_status_command.cpp b/UpdatePTUDevCtrl/process/show_software_status_command.cpp index 588081c..b364e69 100644 --- a/UpdatePTUDevCtrl/process/show_software_status_command.cpp +++ b/UpdatePTUDevCtrl/process/show_software_status_command.cpp @@ -4,9 +4,14 @@ ShowSoftwareStatusCommand::ShowSoftwareStatusCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + +void ShowSoftwareStatusCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + return UpdateCommand::finished(exitCode, exitStatus); } void ShowSoftwareStatusCommand::readyReadStandardOutput() { diff --git a/UpdatePTUDevCtrl/process/show_software_status_command.h b/UpdatePTUDevCtrl/process/show_software_status_command.h index a13739b..7c14542 100644 --- a/UpdatePTUDevCtrl/process/show_software_status_command.h +++ b/UpdatePTUDevCtrl/process/show_software_status_command.h @@ -7,9 +7,11 @@ class ShowSoftwareStatusCommand : public UpdateCommand { public: explicit ShowSoftwareStatusCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // SHOW_SOFTWARE_STATUS_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/update_command.cpp b/UpdatePTUDevCtrl/process/update_command.cpp index fcd529c..ee414c0 100644 --- a/UpdatePTUDevCtrl/process/update_command.cpp +++ b/UpdatePTUDevCtrl/process/update_command.cpp @@ -6,9 +6,11 @@ UpdateCommand::UpdateCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : Command(command, start_timeout, finish_timeout) { + : Command(command, start_timeout, finish_timeout) + , m_nextCommandIndex(nextCommandIndex) { setWorker(worker); } @@ -22,10 +24,15 @@ void UpdateCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { << "exitCode" << exitCode << "exitStatus" << exitStatus; - QProcess *p = (QProcess *)sender(); + QProcess *p = qobject_cast(sender()); if (p) { // read all remaining data sent to the process, just in case - m_commandResult += p->readAllStandardOutput(); + QString s = p->readAllStandardOutput().trimmed(); + if (!s.isEmpty()) { + qCritical() << __func__ << ":" << __LINE__ << s; + m_commandResult += s; + } + qCritical() << __func__ << ":" << __LINE__ << "next command" << m_nextCommandIndex; disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardOutput())); disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardError())); @@ -34,10 +41,12 @@ void UpdateCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { if (!m_worker->workList().empty()) { if (exitCode == 0 && exitStatus == QProcess::ExitStatus::NormalExit) { + qCritical() << __func__ << ":" << __LINE__; if (m_worker->workList().nextExec()) { m_worker->workList().exec(); } } else { + qCritical() << __func__ << ":" << __LINE__; bool execShowStatus = true; m_worker->workList().exec(execShowStatus); } diff --git a/UpdatePTUDevCtrl/process/update_command.h b/UpdatePTUDevCtrl/process/update_command.h index 334e5e5..a884f6e 100644 --- a/UpdatePTUDevCtrl/process/update_command.h +++ b/UpdatePTUDevCtrl/process/update_command.h @@ -5,11 +5,13 @@ class Worker; class UpdateCommand : public Command { + int m_nextCommandIndex{0}; public: static constexpr const char *UPDATE_NOT_NECESSARY{"not necessary"}; static constexpr const char *UPDATE_NOT_REQUESTED{"not requested"}; static constexpr const char *UPDATE_REQUESTED{"requested"}; + static constexpr const char *NO_CUSTOMER_REPOSITORY{"no customer repository"}; static constexpr const char *ISMAS_CONNECTED{"connected"}; static constexpr const char *ISMAS_NOT_CONNECTED{"not connected"}; static constexpr const char *ISMAS_CONNECTION_IN_PROGRESS{"connecting"}; @@ -21,12 +23,15 @@ public: explicit UpdateCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); + int nextCommandIndex() { return m_nextCommandIndex; } + virtual bool stopUpdateOnFailure(); -private slots: +public slots: virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; diff --git a/UpdatePTUDevCtrl/process/update_dc_command.cpp b/UpdatePTUDevCtrl/process/update_dc_command.cpp index 2b83ccc..f802358 100644 --- a/UpdatePTUDevCtrl/process/update_dc_command.cpp +++ b/UpdatePTUDevCtrl/process/update_dc_command.cpp @@ -3,9 +3,14 @@ UpdateDCCommand::UpdateDCCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + +void UpdateDCCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + return UpdateCommand::finished(exitCode, exitStatus); } void UpdateDCCommand::readyReadStandardOutput() { diff --git a/UpdatePTUDevCtrl/process/update_dc_command.h b/UpdatePTUDevCtrl/process/update_dc_command.h index 18754b2..65e5c00 100644 --- a/UpdatePTUDevCtrl/process/update_dc_command.h +++ b/UpdatePTUDevCtrl/process/update_dc_command.h @@ -7,10 +7,12 @@ class UpdateDCCommand : public UpdateCommand { public: explicit UpdateDCCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // UPDATE_DC_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/update_filesystem_command.cpp b/UpdatePTUDevCtrl/process/update_filesystem_command.cpp index 089d5b4..bc6ef23 100644 --- a/UpdatePTUDevCtrl/process/update_filesystem_command.cpp +++ b/UpdatePTUDevCtrl/process/update_filesystem_command.cpp @@ -3,9 +3,14 @@ UpdateFileSystemCommand::UpdateFileSystemCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + +void UpdateFileSystemCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + return UpdateCommand::finished(exitCode, exitStatus); } void UpdateFileSystemCommand::readyReadStandardOutput() { diff --git a/UpdatePTUDevCtrl/process/update_filesystem_command.h b/UpdatePTUDevCtrl/process/update_filesystem_command.h index 1858a45..4dc01cc 100644 --- a/UpdatePTUDevCtrl/process/update_filesystem_command.h +++ b/UpdatePTUDevCtrl/process/update_filesystem_command.h @@ -7,10 +7,12 @@ class UpdateFileSystemCommand : public UpdateCommand { public: explicit UpdateFileSystemCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // UPDATE_FS_COMMAND_H_INCLUDED diff --git a/UpdatePTUDevCtrl/process/update_json_command.cpp b/UpdatePTUDevCtrl/process/update_json_command.cpp index 80d3cc6..79dc1f7 100644 --- a/UpdatePTUDevCtrl/process/update_json_command.cpp +++ b/UpdatePTUDevCtrl/process/update_json_command.cpp @@ -6,9 +6,15 @@ UpdateJsonCommand::UpdateJsonCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout, int finish_timeout) - : UpdateCommand(command, worker, start_timeout, finish_timeout) { + : UpdateCommand(command, worker, nextCommandIndex, start_timeout, finish_timeout) { +} + + +void UpdateJsonCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { + return UpdateCommand::finished(exitCode, exitStatus); } void UpdateJsonCommand::readyReadStandardOutput() { diff --git a/UpdatePTUDevCtrl/process/update_json_command.h b/UpdatePTUDevCtrl/process/update_json_command.h index a87f915..6deee62 100644 --- a/UpdatePTUDevCtrl/process/update_json_command.h +++ b/UpdatePTUDevCtrl/process/update_json_command.h @@ -7,10 +7,12 @@ class UpdateJsonCommand : public UpdateCommand { public: explicit UpdateJsonCommand(QString const &command, Worker *worker, + int nextCommandIndex, int start_timeout = 100000, int finish_timeout = 100000); -protected slots: +public slots: virtual void readyReadStandardOutput() override; + virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; }; #endif // UPDATE_JSON_HANDLER_H_INCLUDED diff --git a/UpdatePTUDevCtrl/worker.cpp b/UpdatePTUDevCtrl/worker.cpp index 5e25e4e..ecd88b9 100644 --- a/UpdatePTUDevCtrl/worker.cpp +++ b/UpdatePTUDevCtrl/worker.cpp @@ -27,7 +27,8 @@ #include "ismas/ismas_client.h" #include "progress_event.h" #include "mainwindow.h" -#include "utils.h" +#include "utils.h" // deprecated +#include "utils_internal.h" #include "process/command.h" #include "process/update_command.h" #include "process/check_ismas_connectivity_command.h" @@ -194,61 +195,75 @@ Worker::Worker(int customerNr, //, m_withoutIsmasDirectPort(true) /* useful for testing */ { , m_withoutIsmasDirectPort(false) /* useful for testing */ { - // check ISMAS connectivity + // *** check ISMAS connectivity *** + // NOTE: if the customer repository does not exist, then it does not matter + // if there is a connection to ISMAS (via APISM). + // NOTE: the several processes will be started WorkList::exec(). + int next = 1; m_workList.push_back( std::make_unique( //QString("echo CheckIsmasConnectivityCommand") QString("/opt/app/tools/atbupdate/ATBUpdateCheck --ismas-connected") - , this)); + , this, ++next)); - // check if update activated in ISMAS + // *** check if update activated in ISMAS *** + // NOTE: if the customer repository does not exist, then it does not matter + // if the update has been activated via ISMAS. m_workList.push_back( std::make_unique( - QString("echo CheckUpdateActivationCommand") - , this)); + //QString("echo CheckUpdateActivationCommand") + QString("/opt/app/tools/atbupdate/ATBUpdateCheck --update-requested") + , this, ++next)); - // check and fetch git-customer repository + // *** check and fetch git-customer repository *** + // (1): if the customer repository does not exist, clone the repository. + // (2): if the repository exists, pull the repository. Optionally, checkout + // the corresponding branch, and check the integrity of the repository. m_workList.push_back( std::make_unique( - QString("echo CheckAndFetchCustomerRepositoryCommand") - , this)); + // QString("echo CheckAndFetchCustomerRepositoryCommand") + QString("/opt/app/tools/atbupdate/ATBUpdateGit") + , this, ++next)); - // exec opkg-commands - // first with no action -> dry-run + // *** exec opkg-commands (noaction) *** + // NOTE: first run the opkg commands with no action -> dry-run m_workList.push_back( std::make_unique( - QString("echo ExecOpkgCommand") - , this, true)); + QString("echo ExecOpkgCommand dry-run") + , this, ++next, true)); - // exec opkg-commands - // now with action -> no dry-run + // *** exec opkg-commands *** + // NOTE: first run the opkg commands with action -> no dry-run + m_workList.push_back( + std::make_unique( + QString("echo ExecOpkgCommand run") + , this, ++next, true)); - // send json files down to device controller + // *** send json files down to device controller *** m_workList.push_back( std::make_unique( QString("echo UpdateJsonCommand") //QString("/opt/app/tools/atbupdate/ATBDownloadDCJsonFiles --set-ppid %1").arg(QCoreApplication::applicationPid()) - , this, false)); + , this, ++next, false)); // sync json files in repo etc-directory with /etc fs-directory m_workList.push_back( std::make_unique( QString("echo UpdateFileSystemCommand") - , this)); - + , this, ++next)); // send device-controller firmware down to device-controller-hardware m_workList.push_back( std::make_unique( QString("echo UpdateDCCommand") // QString("/opt/app/tools/atbupdate/ATBDownloadDCFirmware --read-dc-version true") - , this)); + , this, ++next)); // show/send software-status m_workList.push_back( std::make_unique( QString("echo ShowSoftwareStatusCommand") - , this)); + , this, -1)); // reboot machine /////////////////////////////////////////////////////////// diff --git a/common/include/command.h b/common/include/command.h new file mode 100644 index 0000000..66cd633 --- /dev/null +++ b/common/include/command.h @@ -0,0 +1,44 @@ +#ifndef COMMAND_H_INCLUDED +#define COMMAND_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +class Command : public QObject { + Q_OBJECT + + QString m_command; + QString m_commandResult; + + int m_waitForStartTimeout; + int m_waitForFinishTimeout; + int m_exitCode; + QString m_workingDirectory; + + QScopedPointer m_p; + + QStringList m_args; + +public: + Command(QString command, + QStringList args, + QString workingDirectory, + int start_timeout = 100000, + int finish_timeout = 100000); + + QString getCommandResult(bool reset = false); + QString command() const { return m_command; } + + bool exec(); + int exitCode() const { return m_exitCode; } + +private slots: + virtual void readyReadStandardOutput(); + virtual void readyReadStandardError(); +}; + +#endif // COMMAND_H_INCLUDED diff --git a/common/include/utils.h b/common/include/utils.h new file mode 100644 index 0000000..121d1bf --- /dev/null +++ b/common/include/utils.h @@ -0,0 +1,16 @@ +#ifndef UTILS_INTERNAL_H_INCLUDED +#define UTILS_INTERNAL_H_INCLUDED + +#include + +namespace internal { + int read1stLineOfFile(QString fileName); + QString customerRepoRoot(); + QString customerRepoDir(); + QString customerRepoDirName(); + QString repositoryUrl(); + QString branchName(); + bool customerRepoExists(); +} + +#endif // UTILS_INTERNAL_H_INCLUDED diff --git a/common/include/utils_internal.h b/common/include/utils_internal.h new file mode 100644 index 0000000..b6db836 --- /dev/null +++ b/common/include/utils_internal.h @@ -0,0 +1,34 @@ +#ifndef UTILS_INTERNAL_H_INCLUDED +#define UTILS_INTERNAL_H_INCLUDED + +#include + +namespace internal { + + static constexpr const char *UPDATE_NOT_NECESSARY{"not necessary"}; + static constexpr const char *UPDATE_NOT_REQUESTED{"not requested"}; + static constexpr const char *UPDATE_REQUESTED{"requested"}; + static constexpr const char *NO_CUSTOMER_REPOSITORY{"no customer repository"}; + static constexpr const char *ISMAS_CONNECTED{"connected"}; + static constexpr const char *ISMAS_DISCONNECTED{"disconnected"}; + static constexpr const char *ISMAS_DISCONNECTING{"disconnecting"}; + static constexpr const char *ISMAS_NOT_CONNECTED{"not connected"}; + static constexpr const char *ISMAS_CONNECTION_IN_PROGRESS{"connecting"}; + static constexpr const char *GIT_CUSTOMER_REPO_CHECKOUT_ERROR{"checkout error"}; + static constexpr const char *GIT_CUSTOMER_REPO_PULL_ERROR{"pull error"}; + static constexpr const char *GIT_CUSTOMER_REPO_UP_TO_DATE{"up to date"}; + static constexpr const char *EXEC_OPKG_COMMANDS_SUCCESS{"success"}; + static constexpr const char *UPDATE_DC_JSON_FILES_SUCCESS{"success"}; + static constexpr const char *SYNC_CUSTOMER_REPO_FILES_SUCCESS{"success"}; + static constexpr const char *UPDATE_DC_FIRMARE_SUCCESS{"success"}; + + int read1stLineOfFile(QString fileName); + QString customerRepoRoot(); + QString customerRepoDir(); + QString customerRepoDirName(); + QString repositoryUrl(); + QString branchName(); + bool customerRepoExists(); +} + +#endif // UTILS_INTERNAL_H_INCLUDED diff --git a/common/src/command.cpp b/common/src/command.cpp new file mode 100644 index 0000000..eae49e6 --- /dev/null +++ b/common/src/command.cpp @@ -0,0 +1,121 @@ +#include "command.h" + +#include +#include +#include +#include +#include + +Command::Command(QString command, QStringList args, QString workingDirectory, + int start_timeout, int finish_timeout) + : m_command(command.trimmed()) + , m_commandResult("") + , m_waitForStartTimeout(start_timeout) + , m_waitForFinishTimeout(finish_timeout) + , m_exitCode(-1) + , m_workingDirectory(workingDirectory) + , m_args(args) { + m_p.reset(new QProcess(this)); + if (m_p) { + m_p->setWorkingDirectory(workingDirectory); + m_p->setProcessChannelMode(QProcess::MergedChannels); + + connect(m_p.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput())); + connect(m_p.get(), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError())); + } +} + +void Command::readyReadStandardOutput() { + QProcess *p = (QProcess *)sender(); + if (p) { + qCritical().noquote() << p->readAllStandardOutput(); + } +} + +void Command::readyReadStandardError() { + QProcess *p = (QProcess *)sender(); + if (p) { + qCritical().noquote() << p->readAllStandardError(); + } +} + + +QString Command::getCommandResult(bool reset) { + if (reset == false) { + return m_commandResult; + } + + QString commandResult = m_commandResult; + m_commandResult.clear(); + + return commandResult; +} + +bool Command::exec() { + + if (!m_args.isEmpty()) { + m_p->start(m_command, m_args); + } else { + m_p->start(m_command); + } + + qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch(); + + bool started = false; + if ((started = m_p->waitForStarted(m_waitForStartTimeout)) == true) { + // qCritical() << "PROCESS" << m_command << "STARTED IN" << m_p->workingDirectory(); + if (m_p->state() == QProcess::ProcessState::Running) { + // qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory(); + // wait forever for git/opkg-commands to finish + int wait = m_waitForFinishTimeout; + if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) || + m_command.trimmed().startsWith("opkg", Qt::CaseInsensitive)) { + wait = -1; + } + bool const no_timeout = m_p->waitForFinished(wait); + if (no_timeout) { + // qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory(); + if (m_p->exitStatus() == QProcess::NormalExit) { + if ((m_exitCode = m_p->exitCode()) == 0) { + qCritical().noquote() << m_p->readAllStandardOutput(); + //qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch(); + //qDebug() << "EXECUTED" << m_command + // << QString("(runtime %1ms)").arg(end-start) + // << "with code" << m_exitCode + // << "IN" << m_p->workingDirectory(); + return true; + } else { + qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch(); + qCritical() << "EXECUTED" << m_command + << QString("(runtime %1ms)").arg(end-start) + << "with code" << m_exitCode + << "IN" << m_p->workingDirectory(); + } + } else { + qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch(); + qCritical() << "PROCESS" << m_command << "CRASHED with code" + << m_p->exitCode() + << QString("(after %1ms)").arg(end-start) + << "IN" << m_p->workingDirectory(); + } + } else { + qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch(); + qCritical() << "PROCESS" << m_command + << "DID NOT FINISH WITH" << wait + << "MS IN" << m_p->workingDirectory() + << QString("(runtime %1ms)").arg(end-start); + } + } else { + qCritical() << "WRONG PROCESS STATE" << m_p->state() + << "IN" << m_p->workingDirectory(); + } + } else { + qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch(); + qCritical() << "PROCESS" << m_command << "TIMEOUT AT START" + << QString("(runtime %1ms)").arg(end-start) + << "IN" << m_p->workingDirectory() << m_waitForStartTimeout; + } + + return false; +} + diff --git a/common/src/utils.cpp b/common/src/utils.cpp new file mode 100644 index 0000000..145bd0a --- /dev/null +++ b/common/src/utils.cpp @@ -0,0 +1,55 @@ +#include "utils.h" + +#include +#include +#include + +namespace internal { + +int read1stLineOfFile(QString fileName) { + QFile f(fileName); + if (f.exists()) { + if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&f); + in.setCodec("UTF-8"); + while(!in.atEnd()) { + return in.readLine().toInt(); + } + } + } + return -1; +} + +QString customerRepoRoot() { + return "/opt/app/tools/atbupdate/"; +} + +QString customerRepoDirName() { + int const customerNr = read1stLineOfFile("/mnt/system_data/cust_nr"); + return (customerNr != -1) ? QString("customer_%1").arg(customerNr) : ""; +} + +QString customerRepoDir() { + QString const &n = customerRepoDirName(); + QString const &r = customerRepoRoot(); + return !n.isEmpty() ? QDir::cleanPath(r + QDir::separator() + n) : ""; +} + +bool customerRepoExists() { + QString const repoDir{customerRepoDir()}; + return !repoDir.isEmpty() ? QDir(repoDir).exists() : false; +} + +QString repositoryUrl() { + return "gitea@ptu-config.atb-comm.de:ATB/"; +} + +QString branchName() { + int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr"); + if (zoneNr != -1) { + return QString("zg1/zone%1").arg(zoneNr); + } + return ""; +} + +} // namespace internal diff --git a/common/src/utils_internal.cpp b/common/src/utils_internal.cpp new file mode 100644 index 0000000..145bd0a --- /dev/null +++ b/common/src/utils_internal.cpp @@ -0,0 +1,55 @@ +#include "utils.h" + +#include +#include +#include + +namespace internal { + +int read1stLineOfFile(QString fileName) { + QFile f(fileName); + if (f.exists()) { + if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&f); + in.setCodec("UTF-8"); + while(!in.atEnd()) { + return in.readLine().toInt(); + } + } + } + return -1; +} + +QString customerRepoRoot() { + return "/opt/app/tools/atbupdate/"; +} + +QString customerRepoDirName() { + int const customerNr = read1stLineOfFile("/mnt/system_data/cust_nr"); + return (customerNr != -1) ? QString("customer_%1").arg(customerNr) : ""; +} + +QString customerRepoDir() { + QString const &n = customerRepoDirName(); + QString const &r = customerRepoRoot(); + return !n.isEmpty() ? QDir::cleanPath(r + QDir::separator() + n) : ""; +} + +bool customerRepoExists() { + QString const repoDir{customerRepoDir()}; + return !repoDir.isEmpty() ? QDir(repoDir).exists() : false; +} + +QString repositoryUrl() { + return "gitea@ptu-config.atb-comm.de:ATB/"; +} + +QString branchName() { + int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr"); + if (zoneNr != -1) { + return QString("zg1/zone%1").arg(zoneNr); + } + return ""; +} + +} // namespace internal