checkin for saving current state

This commit is contained in:
Gerhard Hoffmann 2025-02-14 13:20:42 +01:00
parent ef9cc23093
commit 8db818f6cd
37 changed files with 1063 additions and 131 deletions

View File

@ -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

View File

@ -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

View File

@ -19,6 +19,7 @@
#include <optional>
#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<QString> 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,8 +88,19 @@ 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 (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<QString> result
= IsmasClient::sendRequestReceiveResponse(
IsmasClient::APISM::DIRECT_PORT,
@ -103,47 +117,39 @@ int main(int argc, char **argv) {
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;
QJsonObject o = d.object()[k].toObject();
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 = "requested";
updateRequestStatus = internal::UPDATE_REQUESTED;
} else {
updateRequestStatus = internal::UPDATE_NOT_NECESSARY;
}
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;
}
}
debug.noquote() << updateRequestStatus;
} else
if (v.isEmpty()) {
QFile f("/mnt/system_data/cust_nr");
if (!f.exists()) break;
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) 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";
}
}
}
}
break;
}
break;
}
}
}
}
qCritical() << updateRequestStatus;
}
if (parser.isSet(ismasConnectOption)) {
qCritical() << connectionStatus;
debug.noquote() << connectionStatus;
}
return 0;
qCritical() << __func__ << ":" << __LINE__ << exitCode;
return exitCode;
}

View File

@ -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
}

96
Git/git_command.cpp Normal file
View File

@ -0,0 +1,96 @@
#include "git_command.h"
#include "command.h"
#include "utils_internal.h"
using namespace internal;
#include <QProcess>
#include <QByteArray>
#include <QFileInfo>
#include <QDebug>
#include <QDir>
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);
}

25
Git/git_command.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef GIT_COMMAND_H_INCLUDED
#define GIT_COMMAND_H_INCLUDED
#include <QStringList>
#include <QScopedPointer>
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

View File

@ -0,0 +1,105 @@
#include <QtGlobal>
#include <QCoreApplication>
#include <QByteArray>
#include <QProcess>
#include <QCommandLineParser>
#include <QStandardPaths>
#include <QSettings>
#include <QDir>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QRegularExpression>
#include <QFile>
#include <QTextStream>
#include <optional>
#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;
}

97
Git/message_handler.cpp Executable file
View File

@ -0,0 +1,97 @@
#include "message_handler.h"
#include <QDateTime>
#include <cstring>
#include <QString>
#include <QFileInfo>
#include <QMessageLogContext>
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

23
Git/message_handler.h Executable file
View File

@ -0,0 +1,23 @@
#ifndef MESSAGE_HANDLER_H_INCLUDED
#define MESSAGE_HANDLER_H_INCLUDED
#include <QtGlobal>
#ifdef __linux__
#include <syslog.h>
#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

View File

@ -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 += \

View File

@ -36,6 +36,7 @@
#include <QThread>
#include <QtWidgets>
#include <QScopedPointer>
#include <QScreen>
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
#include <unistd.h>
@ -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();

View File

@ -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 += "&nbsp;";
}
bool const custRepoExists = internal::customerRepoExists();
if (status.contains(UpdateCommand::ISMAS_CONNECTED, Qt::CaseInsensitive)) {
if (custRepoExists) {
s += QString("%1 <font color='Green'>connected</font><br />").arg(tmp);
} else {
s += QString("%1 <font color='Green'>connected&nbsp;(initial configuration)</font><br />").arg(tmp);
}
} else
if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Blue'>NOT CONNECTED</font><br />").arg(tmp);
} else
if (status.contains(UpdateCommand::ISMAS_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>connecting</font><br />").arg(tmp);
} else
if (status.contains(UpdateCommand::ISMAS_NOT_CONNECTED, Qt::CaseInsensitive)) {
s += QString( "%1 <font color='Red'>NOT CONNECTED</font><br />").arg(tmp);
if (custRepoExists) {
s += QString( "%1 <font color='Red'>NOT CONNECTED. STOP</font><br />").arg(tmp);
} else {
s += QString( "%1 <font color='Red'>not connected.&nbsp;(initial configuration)</font><br />").arg(tmp);
}
} else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp);
}
@ -291,16 +305,29 @@ void MainWindow::onShowUpdateRequest(QString status) {
tmp += "&nbsp;";
}
bool const custRepoExists = internal::customerRepoExists();
if (status.contains(UpdateCommand::UPDATE_NOT_REQUESTED, Qt::CaseInsensitive)) {
s += QString( "%1 <font color='Red'>NOT REQUESTED</font><br />").arg(tmp);
if (custRepoExists) {
s += QString( "%1 <font color='Red'>NOT REQUESTED. STOP.</font><br />").arg(tmp);
} else {
s += QString("%1 <font color='Blue'>not requested&nbsp;(initial configuration)</font><br />").arg(tmp);
}
} else
if (status.contains(UpdateCommand::UPDATE_REQUESTED, Qt::CaseInsensitive)) {
if (custRepoExists) {
s += QString("%1 <font color='Green'>requested</font><br />").arg(tmp);
} else {
s += QString("%1 <font color='Blue'>requested&nbsp;(initial configuration)</font><br />").arg(tmp);
}
} else
if (status.contains(UpdateCommand::UPDATE_NOT_NECESSARY, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>not necessary</font><br />").arg(tmp);
} else
if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Blue'>UNKNOWN (ISMAS not connected)</font><br />").arg(tmp);
} else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp);
s += QString( "%1 <font color='Red'>UNKNOWN</font><br />").arg(tmp);
}
ui->stepLabel->setText(s);

View File

@ -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);
// }
//}
}

View File

@ -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

View File

@ -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"};
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);
}
}
}
}

View File

@ -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

View File

@ -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"};
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);
}
}
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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<QProcess *>(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);
}

View File

@ -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;
};

View File

@ -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() {

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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<CheckIsmasConnectivityCommand>(
//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<CheckUpdateActivationCommand>(
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<CheckAndFetchCustomerRepositoryCommand>(
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<ExecOpkgCommand>(
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<ExecOpkgCommand>(
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<UpdateJsonCommand>(
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<UpdateFileSystemCommand>(
QString("echo UpdateFileSystemCommand")
, this));
, this, ++next));
// send device-controller firmware down to device-controller-hardware
m_workList.push_back(
std::make_unique<UpdateDCCommand>(
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<ShowSoftwareStatusCommand>(
QString("echo ShowSoftwareStatusCommand")
, this));
, this, -1));
// reboot machine
///////////////////////////////////////////////////////////

44
common/include/command.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef COMMAND_H_INCLUDED
#define COMMAND_H_INCLUDED
#include <QObject>
#include <QCoreApplication>
#include <QString>
#include <QStringList>
#include <QProcess>
#include <QScopedPointer>
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<QProcess> 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

16
common/include/utils.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef UTILS_INTERNAL_H_INCLUDED
#define UTILS_INTERNAL_H_INCLUDED
#include <QString>
namespace internal {
int read1stLineOfFile(QString fileName);
QString customerRepoRoot();
QString customerRepoDir();
QString customerRepoDirName();
QString repositoryUrl();
QString branchName();
bool customerRepoExists();
}
#endif // UTILS_INTERNAL_H_INCLUDED

View File

@ -0,0 +1,34 @@
#ifndef UTILS_INTERNAL_H_INCLUDED
#define UTILS_INTERNAL_H_INCLUDED
#include <QString>
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

121
common/src/command.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "command.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
#include <QDateTime>
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;
}

55
common/src/utils.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "utils.h"
#include <QFile>
#include <QDir>
#include <QTextStream>
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

View File

@ -0,0 +1,55 @@
#include "utils.h"
#include <QFile>
#include <QDir>
#include <QTextStream>
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