Compare commits

..

62 Commits

Author SHA1 Message Date
70d0ffb38d activate opkg with --noaction 2025-08-25 14:00:56 +02:00
f623b36421 after dc-download, check if device-controller reboots successfully 2025-08-25 13:55:49 +02:00
f415406672 test without ppid -> access etc/ in customer-repo 2025-08-25 13:54:44 +02:00
2c1afa463f download jsons after sync 2025-08-21 13:27:06 +02:00
927b488582 Mior: removed debug output 2025-08-21 13:26:11 +02:00
7712803ad6 Set pid into news to ISMAS (used by Christian to reorder events correctly) 2025-08-21 11:27:22 +02:00
bc88a9b0be Use ATBUpdateTool.ini for all child-processes (ATBUpdateDC etc.) 2025-08-21 11:03:51 +02:00
8b3f0991f7 Minor: add helpers lastFailedUpdateStep() and setLastFailedUpdateStep(). 2025-08-21 10:56:50 +02:00
8123526e11 Minor: add helper size() 2025-08-21 10:56:13 +02:00
57a093e9ae No timeout for running processes. 2025-08-21 10:55:33 +02:00
10536c81a5 Send to UPDATE SUCCEEDED to ISMAS when nothing else to do. 2025-08-21 10:54:18 +02:00
659dc69831 Replace TEST_DC_DOWNLOAD with m_debug. 2025-08-21 10:51:16 +02:00
a47dd60e9e Replace TEST_DC_DOWNLOAD with m_debug. 2025-08-20 11:15:09 +02:00
575a740692 Minor: init. m_debug to false. 2025-08-20 11:12:56 +02:00
e22d78cba8 read ATBUpdateDCsettings in *.ini file 2025-08-20 11:11:02 +02:00
ad8b9f26c0 add sections for child-applications 2025-08-20 11:10:17 +02:00
5b5a4504fa use ca-slave-plugin to download jsonfiles to DC 2025-08-20 10:03:11 +02:00
9ed8603dfb DCUpdate runs before download jsons and before sync. with ptu-filesystem. Show this in main-window. 2025-08-19 10:57:19 +02:00
7d367f7fa9 renamed target in *.pro 2025-08-19 10:30:39 +02:00
fc306a45f7 Renamed target ATBDownloadDCJsonFiles -> ATBUpdateJsonFiles (consistency). 2025-08-19 10:29:29 +02:00
df6f33a259 Add define for TEST_DC_DOWNLOAD and add corresponding code
to test the download without actual dc-controller on the PTU.
2025-08-19 10:14:12 +02:00
716543ec8c "after dc_download restart autorequest or else E255" 2025-08-18 13:06:25 +02:00
0f355c0c50 "shortened time to sendnextblock." 2025-08-18 13:04:50 +02:00
36a4d53df6 "increased BL_start Timer (500 -> 1000) " 2025-08-18 08:55:24 +02:00
b9e9688269 startBootloader():
set wait time to 1000ms.
    set try counter to 10.
    a message to ask for general bl installation (in hardware)
2025-08-13 11:16:15 +02:00
f5611cf826 turn dc-download on 2025-08-12 11:59:07 +02:00
8d5831286d testing... 2025-07-07 13:00:34 +02:00
2ab485454c make sure to delete QDebug before termination 2025-04-11 12:32:30 +02:00
cbb81b7260 Add update initial 2025-04-11 12:31:51 +02:00
487bbb8160 minor: add another constant 2025-04-11 12:30:46 +02:00
d36c7c1f72 provide for update logging using a file watcher 2025-04-11 12:30:08 +02:00
cf3e1d61dd provide for update logging using a file watcher 2025-04-11 12:29:38 +02:00
e12181dc5a start to implement progress bar 2025-04-11 12:28:53 +02:00
d1b3b81972 define file for update log 2025-04-11 12:27:35 +02:00
ac03f4ae91 define line for log-entry 2025-04-11 12:26:29 +02:00
0c0debb790 include headers 2025-04-11 12:25:57 +02:00
6fc62863c1 --ismas-connected: try to reach ismas 10x. Use "Broker" and "ISMAS" keys
in json-data. Timeout between tries: 5secs.
2025-03-07 13:50:40 +01:00
0dd731ff50 added new constants 2025-03-07 13:49:12 +01:00
19445ec4f5 minor 2025-03-07 13:48:47 +01:00
739010ba59 readyReadStandardOutput():
parse outout of ATBUpdateDC.
2025-03-07 12:20:40 +01:00
7ace073d12 finished():
start summary timer when binary  has finished.
2025-03-07 12:19:54 +01:00
e36ff70dd9 minor: rename name of binaries 2025-03-07 12:18:32 +01:00
57e65e2234 change for testing 2025-03-07 12:16:35 +01:00
79af890be6 set version to 2.0.0 2025-03-07 12:15:52 +01:00
24b83840cd handling of summary after installation 2025-03-07 12:15:16 +01:00
53946457ab minor: stepLabel format: rich text. 2025-03-07 12:11:41 +01:00
c3947e49ab cleaning up source code. move summary-handling to main-window. 2025-03-07 12:10:54 +01:00
7ecd45b547 cleaning up source. rename doUndate() to run(). 2025-03-07 12:09:07 +01:00
e7d8365c62 read ini-file and determine device controller to install 2025-03-07 12:06:03 +01:00
c304d1a78b readSettings()
read ini-file for binary (e.g. ATBUpdateTool, ATBUpdateDC etc).
	1: using optional path
	2: under /etc...
	3: under /opt...
2025-03-07 11:50:58 +01:00
a8d4ae3aee Minor: renamed binary to ATBUpdateShow 2025-03-07 11:44:48 +01:00
0fe318b291 preparing dc-update 2025-02-28 14:22:51 +01:00
ec08e04f2c return negative error codes 2025-02-26 16:58:31 +01:00
b26b65ee76 take over some code from mainwindow 2025-02-26 16:57:57 +01:00
674b572da5 to be removed 2025-02-26 16:57:01 +01:00
9a6ac85f99 use qcoreapplication -> no window or widgets 2025-02-26 16:56:33 +01:00
ae582b75d5 remove main-window (not needed) 2025-02-26 16:55:40 +01:00
3069c3bd65 Add and use m_updateSteps. 2025-02-24 16:16:00 +01:00
b5067ce044 Minor: add some constants 2025-02-24 16:14:23 +01:00
3573279dfa first implementation for sync-tool 2025-02-24 16:13:43 +01:00
39b5551e90 continued... 2025-02-21 13:39:46 +01:00
05974fd8ee started documentation 2025-02-21 13:10:36 +01:00
31 changed files with 1189 additions and 3855 deletions

View File

@@ -1,5 +1,5 @@
[REPOSITORY_URL] [REPOSITORY_URL]
repository-url="gitea@ptu-config.atb-comm.de:ATB/" repository-url="gitea@ptu-config.atb-comm.de:ATB"
[DIRECTORIES] [DIRECTORIES]
plugin-directory="/usr/lib/" plugin-directory="/usr/lib/"
@@ -19,3 +19,21 @@ yocto-version=false
yocto-install=false yocto-install=false
always-download-config=true always-download-config=true
always-download-dc=false always-download-dc=false
[ATBUpdateCheck]
[ATBUpdateDC]
debug=true
workingDir=/tmp
libca=/usr/lib/libCAslave.so
[ATBUpdateGit]
[ATBUpdateJsonFiles]
[ATBUpdateOpkg]
[ATBUpdateShow]
[ATBUpdateSync]

View File

@@ -16,6 +16,7 @@
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include <QDateTime> #include <QDateTime>
#include <QThread>
#include <optional> #include <optional>
@@ -54,8 +55,13 @@ int main(int argc, char **argv) {
QString connectionStatus{internal::ISMAS_NOT_CONNECTED}; QString connectionStatus{internal::ISMAS_NOT_CONNECTED};
QString updateRequestStatus{internal::UPDATE_NOT_REQUESTED}; QString updateRequestStatus{internal::UPDATE_NOT_REQUESTED};
{
QDebug debug = qCritical(); QDebug debug = qCritical();
int tries = 10;
while (--tries > 0) {
if (std::optional<QString> result if (std::optional<QString> result
= IsmasClient::sendRequestReceiveResponse( = IsmasClient::sendRequestReceiveResponse(
IsmasClient::APISM::DIRECT_PORT, IsmasClient::APISM::DIRECT_PORT,
@@ -64,23 +70,26 @@ int main(int argc, char **argv) {
for (QString const &k : d.object().keys()) { for (QString const &k : d.object().keys()) {
if (k.contains("CMD_GET_APISMSTATUS_RESPONSE")) { if (k.contains("CMD_GET_APISMSTATUS_RESPONSE")) {
QJsonObject o = d.object()[k].toObject(); QJsonObject o = d.object()[k].toObject();
QJsonObject::const_iterator it = o.find("Broker"); QJsonObject::const_iterator bit = o.find("Broker");
if (it != o.constEnd()) { QJsonObject::const_iterator ismit = o.find("ISMAS");
if (bit != o.constEnd() && ismit != o.constEnd()) {
// value for "Broker" // value for "Broker"
QString const &v = it->toString(); QString const &v = bit->toString();
if (v.contains(internal::ISMAS_CONNECTED, Qt::CaseInsensitive)) { bool ismas = ismit->toBool();
if (ismas && v.contains(internal::BROKER_CONNECTED, Qt::CaseInsensitive)) {
connectionStatus = internal::ISMAS_CONNECTED; connectionStatus = internal::ISMAS_CONNECTED;
break;
} else } else
if (v.contains(internal::ISMAS_NOT_CONNECTED, Qt::CaseInsensitive)) { if (v.contains(internal::BROKER_NOT_CONNECTED, Qt::CaseInsensitive)) {
connectionStatus = internal::ISMAS_NOT_CONNECTED; connectionStatus = internal::ISMAS_NOT_CONNECTED;
} else } else
if (v.contains(internal::ISMAS_DISCONNECTED, Qt::CaseInsensitive)) { if (v.contains(internal::BROKER_DISCONNECTED, Qt::CaseInsensitive)) {
connectionStatus = internal::ISMAS_NOT_CONNECTED; connectionStatus = internal::ISMAS_NOT_CONNECTED;
} else } else
if (v.contains(internal::ISMAS_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) { if (v.contains(internal::BROKER_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) {
connectionStatus = internal::ISMAS_NOT_CONNECTED; connectionStatus = internal::ISMAS_NOT_CONNECTED;
} else } else
if (v.contains(internal::ISMAS_DISCONNECTING, Qt::CaseInsensitive)) { if (v.contains(internal::BROKER_DISCONNECTING, Qt::CaseInsensitive)) {
connectionStatus = internal::ISMAS_NOT_CONNECTED; connectionStatus = internal::ISMAS_NOT_CONNECTED;
} }
break; break;
@@ -89,6 +98,13 @@ int main(int argc, char **argv) {
} }
} }
if (connectionStatus == internal::ISMAS_CONNECTED) {
break;
}
QThread::sleep(5);
}
if (connectionStatus != internal::ISMAS_CONNECTED) { if (connectionStatus != internal::ISMAS_CONNECTED) {
if (internal::customerRepoExists() == false) { if (internal::customerRepoExists() == false) {
debug.noquote() << internal::NO_CUSTOMER_REPOSITORY; debug.noquote() << internal::NO_CUSTOMER_REPOSITORY;
@@ -99,7 +115,7 @@ int main(int argc, char **argv) {
if (internal::customerRepoExists() == false) { if (internal::customerRepoExists() == false) {
// if the customer repository does not exists, it does not matter is // if the customer repository does not exists, it does not matter is
// ISMAS is connected or how the setting for the WAIT-button is. // ISMAS is connected or how the setting for the WAIT-button is.
updateRequestStatus = internal::NO_CUSTOMER_REPOSITORY; updateRequestStatus = internal::UPDATE_INITIAL;
} else { } else {
if (connectionStatus == internal::ISMAS_CONNECTED) { if (connectionStatus == internal::ISMAS_CONNECTED) {
if (std::optional<QString> result if (std::optional<QString> result
@@ -158,6 +174,7 @@ int main(int argc, char **argv) {
if (parser.isSet(ismasConnectOption)) { if (parser.isSet(ismasConnectOption)) {
debug.noquote() << connectionStatus; debug.noquote() << connectionStatus;
} }
}
return exitCode; return exitCode;
} }

View File

@@ -1,7 +1,6 @@
QT += core gui QT += core serialport
QT += widgets serialport network
TARGET = ATBDownloadDCFirmware TARGET = ATBUpdateDC
VERSION="0.1.0" VERSION="0.1.0"
win32 { win32 {
@@ -77,21 +76,21 @@ contains( CONFIG, DesktopLinux ) {
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
mainwindow.cpp \
../common/src/message_handler.cpp \ ../common/src/message_handler.cpp \
../UpdatePTUDevCtrl/commandline_parser.cpp \ ../UpdatePTUDevCtrl/commandline_parser.cpp \
update.cpp \ update.cpp \
dc_download.cpp \ ../common/src/System.cpp \
../common/src/System.cpp ../common/src/utils_internal.cpp \
../common/src/command.cpp
HEADERS += \ HEADERS += \
mainwindow.h \
../common/include/message_handler.h \ ../common/include/message_handler.h \
../UpdatePTUDevCtrl/commandline_parser.h \ ../UpdatePTUDevCtrl/commandline_parser.h \
update.h \ update.h \
dc_download.h \ ../common/include/System.h \
../common/include/System.h ../common/include/utils_internal.h \
../common/include/command.h
OTHER_FILES += \ OTHER_FILES += \

View File

@@ -1,7 +1,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <QCoreApplication> #include <QCoreApplication>
#include <QApplication>
#include <QByteArray> #include <QByteArray>
#include <QProcess> #include <QProcess>
@@ -11,12 +10,13 @@
#include <QDir> #include <QDir>
#include <QDebug> #include <QDebug>
#include <QThread> #include <QThread>
#include <QRegularExpression>
#include "message_handler.h" #include "message_handler.h"
#include "commandline_parser.h" #include "commandline_parser.h"
#include "utils.h" #include "utils.h"
#include "utils_internal.h"
#include "update.h" #include "update.h"
#include "mainwindow.h"
#include "System.h" #include "System.h"
#include <DeviceController/interfaces.h> #include <DeviceController/interfaces.h>
@@ -54,15 +54,20 @@ int main(int argc, char **argv) {
openlog("DC", LOG_PERROR | LOG_CONS, LOG_USER); openlog("DC", LOG_PERROR | LOG_CONS, LOG_USER);
QApplication a(argc, argv); QCoreApplication a(argc, argv);
QApplication::setApplicationName("ATBDownloadDCFirmware"); QCoreApplication::setOrganizationName("ATB Automatentechnik Baumann GmBH");
QApplication::setApplicationVersion(APP_VERSION); QCoreApplication::setApplicationName("ATBUpdateDC");
QCoreApplication::setApplicationVersion(APP_VERSION);
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(atbDebugOutput); atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(LOG_NOTICE); setDebugLevel(LOG_NOTICE);
} }
//return 0;
/*
CommandLineParser parser; CommandLineParser parser;
parser.process(a); parser.process(a);
parser.readSettings(); parser.readSettings();
@@ -127,6 +132,27 @@ int main(int argc, char **argv) {
QString const &customerRepo QString const &customerRepo
= QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr)); = QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr));
*/
QString const &psaDcDir = internal::customerRepoDcDir();
QString const &psaRepoRootDir = internal::customerRepoRoot();
QString const &psaRepoDir = internal::customerRepoDir();
QString const &branchName = internal::branchName();
bool debug = false;
bool noaction = true;
QString workingDir;
QString libca;
std::unique_ptr<QSettings> settings = internal::readSettings();
if (settings) {
settings->beginGroup("ATBUpdateDC");
debug = settings->value("debug", false).toBool();
workingDir = settings->value("workingdir", "/tmp").toString();
libca = settings->value("libca", "/usr/lib/libCAslave.so").toString();
settings->endGroup();
}
// etc/dc: located under mount-path // etc/dc: located under mount-path
std::optional<QString> mountPath = System::checkForUSBStick(psaDcDir); std::optional<QString> mountPath = System::checkForUSBStick(psaDcDir);
@@ -137,47 +163,32 @@ int main(int argc, char **argv) {
if ((mountPath = System::checkForSDCard(psaDcDir)).has_value()) { if ((mountPath = System::checkForSDCard(psaDcDir)).has_value()) {
fi.setFile(mountPath.value(), System::getDCFileOnSDCard(mountPath.value())); fi.setFile(mountPath.value(), System::getDCFileOnSDCard(mountPath.value()));
} else { } else {
qInfo() << "using customer repository" << customerRepo;
QDir dir(QDir::cleanPath(customerRepo + QDir::separator() + "etc/dc")); if (debug) {
if (dir.exists()) { qInfo() << "using customer repository" << psaRepoDir;
fi.setFile(dir, dir.absoluteFilePath("dc2c.bin")); }
} else {
qCritical() << "DIRECTORY" << dir << "DOES NOT EXIST"; std::unique_ptr<QString> c = internal::dcCandidateToInstall("/etc/dc/");
if (c) {
fi.setFile(*c);
if (fi.exists() == false) {
qCritical() << "dc2c.bin candidate" << *c << "does not exist. STOP.";
return -1; return -1;
} }
qInfo() << "dc2c.bin canditate" << fi.absoluteFilePath();
}
} }
qInfo() << "downloading dc-firmware .." << fi.absoluteFilePath(); if (debug) {
qInfo() << "dc-firmware size (bytes) ." << fi.size(); qInfo() << "downloading dc-firmware" << fi.absoluteFilePath();
if (readDCVersion) { qInfo() << "dc-firmware size (bytes)" << fi.size();
qInfo() << "dc-version ..............." << Update::dcVersion(fi.absoluteFilePath()); qInfo() << "dc-version" << Update::dcVersion(fi.absoluteFilePath());
} }
QThread::currentThread()->setObjectName("main thread"); Update u(fi.absoluteFilePath(), libca, debug, noaction);
// qInfo() << "Main thread" << QThread::currentThreadId(); u.run();
Update update(customerRepo,
QString::number(customerNr),
branchName,
plugInDir,
plugInName,
workingDir,
psaDcDir);
update.doUpdate(fi.absoluteFilePath());
// MainWindow mw;
// mw.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
// mw.showFullScreen();
// qCritical() << "SHOW";
// mw.show();
qInfo() << "<DC-UPDATE-FINISH>"; qInfo() << "<DC-UPDATE-FINISH>";
return 0; return 0;
// return a.exec();
} }

View File

@@ -1,10 +1,7 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer> #include <QTimer>
#include <QStatusBar>
#include <QWidget>
#include <QSerialPort> #include <QSerialPort>
#include <QSerialPortInfo> #include <QSerialPortInfo>

View File

@@ -24,10 +24,14 @@
#include <QMap> #include <QMap>
#include <QStringList> #include <QStringList>
#include <QString> #include <QString>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QSettings>
#define UPDATE_OPKG (1) #define UPDATE_OPKG (1)
#define UPDATE_DC (0) #define UPDATE_DC (0)
static const QMap<QString, int> baudrateMap = { static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3}, {"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
{"57600" , 4}, {"115200" , 5} {"57600" , 4}, {"115200" , 5}
@@ -35,25 +39,19 @@ static const QMap<QString, int> baudrateMap = {
QPluginLoader Update::pluginLoader; QPluginLoader Update::pluginLoader;
hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) { hwinf *Update::loadDCPlugin(QString const &libCA /* absolute file path */) {
hwinf *hw = nullptr; hwinf *hw = nullptr;
if (plugInDir.exists()) { QFileInfo libCAInfo(libCA);
QString pluginLibName(fname); if (libCAInfo.exists()) {
pluginLibName = plugInDir.absoluteFilePath(pluginLibName); pluginLoader.setFileName(libCA);
QFileInfo info(pluginLibName);
if (info.exists()) {
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
pluginLoader.setFileName(pluginLibName);
// static QPluginLoader pluginLoader(pluginLibName); // static QPluginLoader pluginLoader(pluginLibName);
if (!pluginLoader.load()) { if (!pluginLoader.load()) {
qCritical() << "in directory" << plugInDir.absolutePath();
qCritical() << "cannot load plugin" << pluginLoader.fileName(); qCritical() << "cannot load plugin" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
return nullptr; return nullptr;
} }
qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath(); // qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
if (!pluginLoader.isLoaded()) { if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
@@ -69,14 +67,10 @@ hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
return nullptr; return nullptr;
} }
} else { } else {
qCritical() << pluginLibName << "does not exist"; qCritical() << libCAInfo.absoluteFilePath() << "does not exist";
return nullptr;
}
} else {
qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist";
return nullptr; return nullptr;
} }
return hw; return hw;
} }
@@ -107,40 +101,12 @@ QString Update::dcVersion(QString const &dcBinFile) {
} }
class hwapi; class hwapi;
Update::Update(QString customerRepository, Update::Update(QString const &dcFileName, QString const &libCA, bool debug, bool noaction)
QString customerNrStr, : m_dcFileName(dcFileName)
QString branchName, , m_hw(loadDCPlugin(libCA))
QString plugInDir, , m_sys_areDCdataValid(false)
QString pluginName, , m_debug(debug)
QString workingDir, , m_noaction(noaction) {
QString psaDcDir,
bool dryRun,
QObject *parent,
char const *serialInterface,
char const *baudrate)
: QObject(parent) {
#if 0
, m_hw(loadDCPlugin(QDir(plugInDir), pluginName))
, m_serialInterface(serialInterface)
, m_baudrate(baudrate)
, m_customerRepository(customerRepository)
, m_customerNrStr(customerNrStr)
, m_branchName(branchName)
, m_pluginName(pluginName)
, m_workingDir(workingDir)
, m_psaDcDir(psaDcDir)
, m_dryRun(dryRun)
, m_sys_areDCdataValid(false) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin loaded ???";
} else {
// carun stoppen
}
#endif
m_start = QDateTime::currentDateTime();
} }
Update::~Update() { Update::~Update() {
@@ -166,15 +132,15 @@ Update::sendNextAddress(int bNum) const {
if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) { if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) {
// qDebug() << "addr-block" << bNum << "..."; // qDebug() << "addr-block" << bNum << "...";
while (noAnswerCount <= 250) { while (noAnswerCount <= 250) {
// TODO
// m_hw->bl_sendAddress(bNum);
QThread::msleep(100); DownloadResult res = DownloadResult::OK;
if (!m_debug) {
m_hw->bl_sendAddress(bNum);
// TODO QThread::msleep(10); //from 100ms to 20ms
// DownloadResult const res = sendStatus(m_hw->bl_wasSendingAddOK()); //###################################################################################
res = sendStatus(m_hw->bl_wasSendingAddOK());
DownloadResult const res = DownloadResult::OK; }
if (res != DownloadResult::NOP) { if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) { if (res == DownloadResult::ERROR) {
@@ -189,7 +155,7 @@ Update::sendNextAddress(int bNum) const {
} else { } else {
noAnswerCount += 1; // no answer by now noAnswerCount += 1; // no answer by now
} }
} } // while
// wait max. about 3 seconds // wait max. about 3 seconds
return DownloadResult::TIMEOUT; return DownloadResult::TIMEOUT;
} }
@@ -214,20 +180,20 @@ Update::sendNextDataBlock(QByteArray const &binary, int bNum) const {
qInfo() << s.toUtf8().constData(); qInfo() << s.toUtf8().constData();
QThread::msleep(200); QThread::msleep(20); //reduce from 200 to 50 ms
return DownloadResult::OK; //############################################################################
// QByteArray b((const char *)(&local[0]), 64); QByteArray b((const char *)(&local[0]), 64);
// qCritical() << "SNDB" << bNum << b.size() << b.toHex(); qCritical() << "SNDB" << bNum << b.size() << b.toHex();
while (noAnswerCount <= 250) { while (noAnswerCount <= 250) {
// TODO
// m_hw->bl_sendDataBlock(64, local);
// TODO DownloadResult res = DownloadResult::OK;
// DownloadResult const res = sendStatus(m_hw->bl_wasSendingDataOK());
DownloadResult const res = DownloadResult::OK; if (!m_debug) {
m_hw->bl_sendDataBlock(64, local);
res = sendStatus(m_hw->bl_wasSendingDataOK());
}
if (res != DownloadResult::NOP) { if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) { if (res == DownloadResult::ERROR) {
@@ -249,15 +215,13 @@ Update::sendNextDataBlock(QByteArray const &binary, int bNum) const {
} }
bool Update::startBootloader() const { bool Update::startBootloader() const {
QThread::msleep(1000); qDebug() << "starting bootloader...";
qInfo() << nextTimePoint().toUtf8().constData() << "starting bootloader ...done";
return true;
#if 0 if (!m_debug) {
int nTry = 5; int nTry = 10;
while (--nTry >= 0) { while (--nTry >= 0) {
m_hw->bl_startBL(); m_hw->bl_startBL();
QThread::msleep(5000); QThread::msleep(1000);
m_hw->bl_checkBL(); m_hw->bl_checkBL();
if (m_hw->bl_isUp()) { if (m_hw->bl_isUp()) {
qInfo() << "starting bootloader...OK"; qInfo() << "starting bootloader...OK";
@@ -265,24 +229,27 @@ bool Update::startBootloader() const {
return true; return true;
} else { } else {
qCritical() << "bootloader not up (" << nTry << ")"; qCritical() << "bootloader not up (" << nTry << ")";
qCritical() << "IS BOOTLOADER INSTALLED ???";
} }
} }
qCritical() << "starting bootloader...FAILED"; qCritical() << "starting bootloader...FAILED";
return false; return false;
#endif } else {
QThread::msleep(1000);
qInfo() << "starting bootloader...OK";
}
return true;
} }
bool Update::stopBootloader() const { bool Update::stopBootloader() const {
QThread::msleep(1000);
qInfo() << nextTimePoint().toUtf8().constData() << "stopping bootloader ...done";
return true;
#if 0
qDebug() << "stopping bootloader..."; qDebug() << "stopping bootloader...";
if (!m_debug) {
int nTry = 5; int nTry = 5;
while (--nTry >= 0) { while (--nTry >= 0) {
m_hw->bl_stopBL(); m_hw->bl_stopBL();
QThread::msleep(500); QThread::msleep(1000);
if (!m_hw->bl_isUp()) { if (!m_hw->bl_isUp()) {
qInfo() << "stopping bootloader...OK"; qInfo() << "stopping bootloader...OK";
return true; return true;
@@ -290,12 +257,21 @@ bool Update::stopBootloader() const {
} }
qCritical() << "stopping bootloader...FAILED"; qCritical() << "stopping bootloader...FAILED";
return false; return false;
#endif
} else {
QThread::msleep(1000);
qInfo() << "stopping bootloader...OK";
}
return true;
} }
bool Update::resetDeviceController() const { bool Update::resetDeviceController() const {
// TODO qInfo() << nextTimePoint().toUtf8().constData() << "resetting device controller";
// m_hw->bl_rebootDC();
if (!m_debug) {
m_hw->bl_rebootDC();
}
// wait maximally 3 seconds, before starting bootloader // wait maximally 3 seconds, before starting bootloader
QThread::sleep(1); QThread::sleep(1);
@@ -313,12 +289,12 @@ QByteArray Update::loadBinaryDCFile(QString const &filename) const {
if (!file.exists()) { if (!file.exists()) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ")" qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< file.fileName() << "does not exist"; << file.fileName() << "does not exist";
return QByteArray(); return QByteArray{};
} }
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ")" qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
<< "cannot open file" << file.fileName(); << "cannot open file" << file.fileName();
return QByteArray(); return QByteArray{};
} }
qInfo() << nextTimePoint().toUtf8().constData() qInfo() << nextTimePoint().toUtf8().constData()
@@ -408,19 +384,26 @@ QByteArray Update::loadBinaryDCFile(QString const &filename) const {
// There is no problem to repeat this command until the // There is no problem to repeat this command until the
// bootloader is really not running anymore. // bootloader is really not running anymore.
*/ */
bool Update::doUpdate(QString const &dcFileName) { int Update::run() {
qInfo() << "<DC-VERSION>" << Update::dcVersion(dcFileName); if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin loaded ???";
return -(int)Result::PLUGIN_LOAD_ERROR;
}
m_dcFileName = dcFileName; m_start = QDateTime::currentDateTime();
//QString const &fToWorkOn = usbStickDetected ? QDir::cleanPath(it->trimmed()) if (m_debug) {
//: QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed()); qInfo() << "start dc-update for" << m_dcFileName << "at" << m_start.toString(Qt::ISODate);
qInfo() << "<DC-VERSION>" << Update::dcVersion(m_dcFileName);
}
//if (!m_hw) { if (!m_debug) {
// qCritical() << "(" << __func__ << ":" << __LINE__ << "):" m_hw->dc_autoRequest(false);
// << "ERROR!!! m_hw == nullptr"; }
// return false;
//} qInfo() << "DC auto request OFF";
qCritical() << "start dc-update for" << m_dcFileName << "at" << m_start.toString(Qt::ISODate);
QByteArray ba = loadBinaryDCFile(m_dcFileName); QByteArray ba = loadBinaryDCFile(m_dcFileName);
if (ba.size() > 0) { if (ba.size() > 0) {
@@ -433,15 +416,14 @@ bool Update::doUpdate(QString const &dcFileName) {
resetDeviceController(); resetDeviceController();
if (startBootloader()) { if (startBootloader()) {
int currentBlock = 0; int currentBlock = 0;
DownloadResult res = DownloadResult::OK; DownloadResult res = DownloadResult::OK;
qInfo() << nextTimePoint().toUtf8().constData() << "64-byte block" << currentBlock; qInfo() << nextTimePoint().toUtf8().constData() << "64-byte block" << currentBlock;
while (res != DownloadResult::ERROR && currentBlock < m_totalBlocks) { while (res != DownloadResult::ERROR && currentBlock <= m_totalBlocks) {
if ((res = sendNextAddress(currentBlock)) != DownloadResult::ERROR) { if ((res = sendNextAddress(currentBlock)) != DownloadResult::ERROR) {
if ((res = sendNextDataBlock(ba, currentBlock)) != DownloadResult::ERROR) { if ((res = sendNextDataBlock(ba, currentBlock)) != DownloadResult::ERROR) {
// TODO
// m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
currentBlock += 1; currentBlock += 1;
} else break; } else break;
} }
@@ -470,243 +452,26 @@ bool Update::doUpdate(QString const &dcFileName) {
} }
stopBootloader(); // there is no harm in stopping the bootloader even stopBootloader(); // there is no harm in stopping the bootloader even
// if starting the bootloader failed // if starting the bootloader failed
// check if update was successful
if (!m_debug) {
m_hw->dc_autoRequest(true); //restart dc_autoRequest after download else E255!
}
for (int i = 0; i < 3; ++i) {
qInfo() << "waiting for device controller restart...(" << i << ")";
QThread::sleep(20);
resetDeviceController();
if (startBootloader()) {
qInfo() << nextTimePoint().toUtf8().constData() << "<DC-UPDATE-SUCCESS>"; qInfo() << nextTimePoint().toUtf8().constData() << "<DC-UPDATE-SUCCESS>";
return true; stopBootloader();
return -(int)Result::SUCCESS;
}
}
} }
qInfo() << nextTimePoint().toUtf8().constData() << "<DC-UPDATE-FAILURE>"; qInfo() << nextTimePoint().toUtf8().constData() << "<DC-UPDATE-FAILURE>";
//To Do Error handling if Dc doesnt start after download
return false; return false;
} }
#if 0
bool Update::checkJsonVersions(QStringList const& jsonFileNames) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return false;
}
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED";
return false;
}
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")";
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
uint8_t jsonNr = 0;
QString const &fName = jsonFileNames[i];
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 6=printer template 1 ..... 36= template 32
if (fName.endsWith("conf.json")) {
jsonNr = 1;
} else
if (fName.endsWith("device.json")) {
jsonNr = 2;
} else
if (fName.endsWith("cash.json")) {
jsonNr = 3;
} else {
QRegularExpressionMatch match;
static const QRegularExpression re("^(.*print)([0-3][0-9])\\.json\\s*$");
int idx = fName.indexOf(re, 0, &match);
if (idx != -1) {
QString captured = match.captured(match.lastCapturedIndex());
bool ok = false;
int n = captured.toInt(&ok);
if (ok) {
// note: use 5 (instead of 4 -> index has been shifted)
jsonNr = n + 5;
}
}
}
if (jsonNr != 0) {
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
m_hw->sys_requestJsonVersions(jsonNr);
QThread::msleep(500);
char buf[64];
memset(buf, 0x00, sizeof(buf));
m_hw->sys_getJsonVersions(jsonNr, buf);
buf[16] = '\0'; // the DC only handles 16 bytes
static const QByteArray cb(16, (char)0xff);
QString const installedVersion(QString::fromStdString(buf));
QString const fileVersion = getFileVersion(jsonFileNames[i]);
QFileInfo fi(jsonFileNames[i]);
qCritical() << endl;
qCritical() << " json request nr:" << jsonNr;
if (installedVersion == fileVersion) {
qCritical() << " json file:" << fi.fileName();
qCritical() << " installed version in DC:" << installedVersion;
} else
if (cb == QByteArray(buf) && fileVersion == "") {
qCritical() << "unknown json file (repo and DC):" << fi.fileName();
} else {
qCritical() << " json file:" << fi.fileName();
qCritical() << " installed version in DC:" << installedVersion;
qCritical() << " file version in repository:" << fileVersion;
}
} else {
qCritical() << "CANNOT FIND JSON-NR FOR" << fName;
}
}
return false;
}
QString Update::getFileVersion(QString const& jsonFileName) {
// "version":"15.10.2023 14:55 02.00.06",
static const QRegularExpression re("^.*(\\\"[Vv]ersion\\\":)([\\s\\\"]{0,})([^,\\\"]{0,}).*$");
QString fileVersion("");
QFile inputFile(QDir::cleanPath(m_customerRepository + QDir::separator() + jsonFileName));
if (inputFile.exists()) {
if (inputFile.open(QIODevice::ReadOnly)) {
QTextStream in(&inputFile);
while (!in.atEnd()) {
QString line = in.readLine();
QRegularExpressionMatch match;
int idx = line.indexOf(re, 0, &match);
if (idx != -1) {
int const lastCaptured = match.lastCapturedIndex();
// the dc only sends 16 Byte
fileVersion = match.captured(lastCaptured);
fileVersion.truncate(16);
break;
}
}
inputFile.close();
}
} else {
// qCritical() << "ERROR" << inputFile.fileName() << "does not exist";
}
return fileVersion;
}
bool Update::downloadJson(enum FileTypeJson type,
int templateIdx,
QString jsFileToSendToDC) const {
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
qDebug() << "SET AUTO-REQUEST=TRUE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
QStringList lst;
bool ready = false;
int nTry = 25;
while ((ready = m_hw->sys_ready4sending()) == false) {
QThread::msleep(200);
if (--nTry <= 0) {
qCritical() << "SYS NOT READY FOR SENDING AFTER 5 SECONDS";
break;
}
}
bool ret = false;
QString msg;
lst.clear();
if (ready) {
QFile file(jsFileToSendToDC);
QFileInfo fi(jsFileToSendToDC); // max. size of template file is 800 bytes
if (file.exists()) {
if (file.open(QIODevice::ReadOnly)) {
if (fi.size() > 0 && fi.size() <= 800) {
QByteArray ba = file.readAll();
// kindOfFile: 1=config, 2=device, 3=cash, 4=serial, 5=time, 6=printer
// nrOfTemplate=1...32 if kindOfFile==6
// content = content of the Json file, max 800byte ascii signs
if (m_hw->sys_sendJsonFileToDc((uint8_t)(type),
templateIdx,
(uint8_t *)ba.data())) {
/*
* Note: the machine id is contained in DC2C_conf.json.
* The idea was to use this to check if the download of
* the json-file was correct. It did not work, as the
* update of the PSA (to reflect a change in the
* machine id) did not happen immediately.
*
m_hw->dc_autoRequest(true);
QThread::msleep(500);
// testing
m_hw->request_ReadbackMachineID();
QThread::msleep(500);
uint8_t data[64];
memset(data, 0x00, sizeof(data));
uint8_t length = 0;
m_hw->readback_machineIDdata(&length, data);
QThread::msleep(500);
QByteArray ba((const char*)data, length);
qCritical() << length << "MACHINE ID =" << ba.toHex(':');
*/
ret = true;
} else {
qCritical() << QString("ERROR SEND JSON-FILE %1 TO DC").arg(file.fileName());
}
} else {
qCritical() << QString("SIZE OF %1 TOO BIG (%2 BYTES)").arg(jsFileToSendToDC).arg(fi.size());
}
} else {
qCritical() << QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING";
}
} else {
qCritical() << (QString(jsFileToSendToDC) + " DOES NOT EXIST");
}
}
m_hw->dc_autoRequest(false);
qDebug() << "SET AUTO-REQUEST=FALSE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
return ret;
}
bool Update::updatePrinterTemplate(int templateIdx, QString jsFile) const {
return downloadJson(FileTypeJson::PRINTER, templateIdx, jsFile);
}
bool Update::updateConfig(QString jsFile) {
return downloadJson(FileTypeJson::CONFIG, 0, jsFile);
}
bool Update::updateCashConf(QString jsFile) {
return downloadJson(FileTypeJson::CASH, 0, jsFile);
}
bool Update::updateDeviceConf(QString jsFile) {
return downloadJson(FileTypeJson::DEVICE, 0, jsFile);
}
#endif

View File

@@ -17,26 +17,21 @@
#ifdef PTU5 #ifdef PTU5
#define SERIAL_PORT "ttymxc2" #define SERIAL_PORT "ttymxc2"
#define BAUDRATE 115200
#else #else
#define SERIAL_PORT "ttyUSB0" #define SERIAL_PORT "ttyUSB0"
#define BAUDRATE 115200
#endif #endif
class QSerialPort;
class Update : public QObject { class Update : public QObject {
Q_OBJECT Q_OBJECT
QString m_dcFileName{};
hwinf *m_hw = nullptr; hwinf *m_hw = nullptr;
char const *m_serialInterface; bool m_sys_areDCdataValid{};
char const *m_baudrate; bool m_debug{false};
QString m_customerRepository; bool m_noaction;
QString m_customerNrStr;
QString m_branchName;
QString m_pluginName;
QString m_workingDir;
QString m_psaDcDir;
QString m_dcFileName;
bool m_maintenanceMode;
bool m_dryRun;
bool m_sys_areDCdataValid;
static QPluginLoader pluginLoader; static QPluginLoader pluginLoader;
@@ -48,27 +43,16 @@ class Update : public QObject {
public: public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP}; enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
enum class FileTypeJson {CONFIG=1, DEVICE=2, CASH=3, SERIAL=4, TIME=5, PRINTER=6}; enum class Result {SUCCESS=0, PLUGIN_LOAD_ERROR};
static hwinf *loadDCPlugin(QDir const &plugInDir, QString const &fn); static hwinf *loadDCPlugin(QString const &libCA = "/usr/lib/libCAslave.so");
static bool unloadDCPlugin(); static bool unloadDCPlugin();
static QStringList split(QString line, QChar sep = ','); static QStringList split(QString line, QChar sep = ',');
explicit Update(QString customerRepository, explicit Update(QString const &dcBinFile, QString const &libCA, bool debug, bool noaction);
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
QString psaDcDir,
bool dryRun = false,
QObject *parent = nullptr,
char const *serialInterface = SERIAL_PORT,
char const *baudrate = "115200");
virtual ~Update() override; virtual ~Update() override;
bool doUpdate(QString const &dcFileName); int run();
static QString dcVersion(QString const &dcBinFile); static QString dcVersion(QString const &dcBinFile);
private: private:

View File

@@ -1,7 +1,7 @@
QT += core QT += core
QT += serialport network QT += serialport network
TARGET = ATBDownloadDCJsonFiles TARGET = ATBUpdateJsonFiles
VERSION="0.1.0" VERSION="0.1.0"
win32 { win32 {

View File

@@ -144,7 +144,7 @@ int main(int argc, char **argv) {
} }
} }
// qCritical() << "JSON FILES TO UPDATE" << filesToUpdate; qCritical() << __LINE__ << "JSON FILES TO UPDATE" << filesToUpdate;
Update update(customerRepo, Update update(customerRepo,
QString::number(customerNr), QString::number(customerNr),
@@ -153,8 +153,10 @@ int main(int argc, char **argv) {
plugInName, plugInName,
workingDir); workingDir);
update.doUpdate(); if (!filesToUpdate.empty()) {
// update.doUpdate(filesToUpdate, mountPath.has_value()); update.doUpdate(filesToUpdate, mountPath.has_value());
}
// update.checkJsonVersions(); // update.checkJsonVersions();
//update.checkJsonVersions(filesToUpdate); //update.checkJsonVersions(filesToUpdate);

View File

@@ -107,7 +107,7 @@ Update::Update(QString customerRepository,
char const *serialInterface, char const *serialInterface,
char const *baudrate) char const *baudrate)
: QObject(parent) : QObject(parent)
// , m_hw(loadDCPlugin(QDir(plugInDir), pluginName)) , m_hw(loadDCPlugin(QDir(plugInDir), pluginName))
, m_serialInterface(serialInterface) , m_serialInterface(serialInterface)
, m_baudrate(baudrate) , m_baudrate(baudrate)
, m_customerRepository(customerRepository) , m_customerRepository(customerRepository)
@@ -145,7 +145,8 @@ Update::~Update() {
// unloadDCPlugin(); // unloadDCPlugin();
} }
bool Update::doUpdate() { #if 0
bool Update::doUpdate() { // test function
int numberOfFiles = 3; int numberOfFiles = 3;
@@ -178,6 +179,7 @@ bool Update::doUpdate() {
return true; return true;
} }
#endif
bool Update::doUpdate(QStringList const &filesToWorkOn, bool usbStickDetected) { bool Update::doUpdate(QStringList const &filesToWorkOn, bool usbStickDetected) {

View File

@@ -1,6 +1,6 @@
QT += core QT += core
TARGET = show_update TARGET = ATBUpdateShow
VERSION="1.0.0" VERSION="1.0.0"
win32 { win32 {

View File

@@ -26,11 +26,69 @@ int main(int argc, char **argv) {
QCoreApplication::setApplicationName("ATBUpdateSync"); QCoreApplication::setApplicationName("ATBUpdateSync");
QCoreApplication::setApplicationVersion(APP_VERSION); QCoreApplication::setApplicationVersion(APP_VERSION);
QDebug debug = qCritical();
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(nullptr); atbInstallMessageHandler(nullptr);
//atbInstallMessageHandler(atbDebugOutput); //atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(LOG_NOTICE); setDebugLevel(LOG_NOTICE);
} }
return 0; if (internal::customerRepoExists() == false) {
qCritical().noquote() << internal::NO_CUSTOMER_REPOSITORY;
return internal::NO_CUSTOMER_REPOSITORY_CODE;
}
QString const crd = internal::customerRepoDir();
QString const etcInRepo = QDir::cleanPath(crd + QDir::separator() + "etc/");
QString const optInRepo = QDir::cleanPath(crd + QDir::separator() + "opt/");
if (!QDir(etcInRepo).exists()) {
qCritical().noquote() << internal::NO_ETC_CUSTOMER_REPOSITORY;
return internal::NO_ETC_CUSTOMER_REPOSITORY_CODE;
}
if (!QDir(optInRepo).exists()) {
qCritical().noquote() << internal::NO_OPT_CUSTOMER_REPOSITORY;
return internal::NO_OPT_CUSTOMER_REPOSITORY_CODE;
}
#if 0
error codes for rsync:
https://stackoverflow.com/questions/20737204/comprehensive-list-of-rsync-error-codes
0 Success
1 Syntax or usage error
2 Protocol incompatibility
3 Errors selecting input/output files, dirs
4 Requested action not supported: an attempt was made to manipulate 64-bit
files on a platform that cannot support them; or an option was specified
that is supported by the client and not by the server.
5 Error starting client-server protocol
6 Daemon unable to append to log-file
10 Error in socket I/O
11 Error in file I/O
12 Error in rsync protocol data stream
13 Errors with program diagnostics
14 Error in IPC code
20 Received SIGUSR1 or SIGINT
21 Some error returned by waitpid()
22 Error allocating core memory buffers
23 Partial transfer due to error
24 Partial transfer due to vanished source files
25 The --max-delete limit stopped deletions
30 Timeout in data send/receive
35 Timeout waiting for daemon connection
#endif
QStringList options({"-v", "--recursive", "--progress", "--checksum",
"--exclude=.*", "--include=*.bin", "--include=*.json",
"--include=*.ini"});
int ret = SyncCommand().exec("rsync", options << etcInRepo << "/etc");
if (ret == 0) {
ret = SyncCommand().exec("rsync", options << optInRepo << "/opt");
}
return (ret > 0) ? -ret : ret;
} }

View File

@@ -12,7 +12,10 @@ using namespace internal;
SyncCommand::SyncCommand() { SyncCommand::SyncCommand() {
} }
bool SyncCommand::exec(QString const &cmd, QStringList const &options, int SyncCommand::exec(QString const &cmd, QStringList const &options,
int start_timeout, int finish_timeout) { int start_timeout, int finish_timeout) {
return false; Command c(cmd, options, internal::customerRepoDir(),
start_timeout, finish_timeout);
c.exec();
return c.exitCode();
} }

View File

@@ -7,7 +7,7 @@ class SyncCommand {
public: public:
SyncCommand(); SyncCommand();
bool exec(QString const &cmd, QStringList const &options, int exec(QString const &cmd, QStringList const &options,
int start_timeout = 100000, int finish_timeout = 100000); int start_timeout = 100000, int finish_timeout = 100000);
}; };

View File

@@ -147,7 +147,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
# 1.5.5 : Call into binary ptuPackageVersion to get installed package # 1.5.5 : Call into binary ptuPackageVersion to get installed package
# versions. # versions.
# 1.5.6 : Show additional update progress info in status bar. # 1.5.6 : Show additional update progress info in status bar.
VERSION="1.5.6" # 2.0.0 : Rewrite of UpdateTool.
VERSION="2.0.0"
# PLANNED TODOS: # PLANNED TODOS:
# 1: Das Repository wird repariert bwz. neu geklont. Unabhaengig vom WAIT. # 1: Das Repository wird repariert bwz. neu geklont. Unabhaengig vom WAIT.
# 2: Wenn der WAIT-Button aktiv ist, dann wird ein Repository repariert (neu # 2: Wenn der WAIT-Button aktiv ist, dann wird ein Repository repariert (neu
@@ -325,6 +326,7 @@ HEADERS += \
commandline_parser.h \ commandline_parser.h \
work_process_list.h \ work_process_list.h \
$${_PRO_FILE_PWD_}/../common/include/utils_internal.h \ $${_PRO_FILE_PWD_}/../common/include/utils_internal.h \
$${_PRO_FILE_PWD_}/../common/include/log_line_entry.h \
$${_PRO_FILE_PWD_}/../common/ismas/ApismClient.h \ $${_PRO_FILE_PWD_}/../common/ismas/ApismClient.h \
$${_PRO_FILE_PWD_}/../common/ismas/ApismTcpClient.h \ $${_PRO_FILE_PWD_}/../common/ismas/ApismTcpClient.h \
$${_PRO_FILE_PWD_}/../common/ismas/ISMASData.h \ $${_PRO_FILE_PWD_}/../common/ismas/ISMASData.h \

View File

@@ -21,6 +21,7 @@
#include <QThread> #include <QThread>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QCoreApplication>
#if 0 #if 0
######################## ########################
@@ -380,7 +381,7 @@ QString IsmasClient::updateNewsToIsmas(char const *event,
"{" "{"
"\"REASON\":\"SW_UP\"," "\"REASON\":\"SW_UP\","
"\"TIMESTAMP\":\"%s\"," "\"TIMESTAMP\":\"%s\","
"\"EVENT_ID\":\"0\"," "\"EVENT_ID\":\"%d\","
"\"EVENT\":\"%s\"," "\"EVENT\":\"%s\","
"\"EVENTSTATE\":1," "\"EVENTSTATE\":1,"
"\"PARAMETER\": {" "\"PARAMETER\": {"
@@ -390,7 +391,7 @@ QString IsmasClient::updateNewsToIsmas(char const *event,
"\"STEP_RESULT\" : \"%s\"," "\"STEP_RESULT\" : \"%s\","
"\"VERSION\" : \"%s\"" "\"VERSION\" : \"%s\""
"}" "}"
"}", ts.toStdString().c_str(), event, percent, resultCode, "}", ts.toStdString().c_str(), static_cast<int>(QCoreApplication::applicationPid()), event, percent, resultCode,
step, step_result, version); step, step_result, version);
return buf; return buf;
} }

View File

@@ -3,6 +3,7 @@
#include "worker.h" #include "worker.h"
#include "utils.h" #include "utils.h"
#include "utils_internal.h" #include "utils_internal.h"
#include "log_line_entry.h"
#include "progress_event.h" #include "progress_event.h"
#include "update_dc_event.h" #include "update_dc_event.h"
#include "process/update_command.h" #include "process/update_command.h"
@@ -16,17 +17,89 @@
#include <QColor> #include <QColor>
#include <QColorDialog> #include <QColorDialog>
#define CHECK_BACKEND_CONNECTION 0
#define CHECK_UPDATE_REQUEST 1
#define UPDATE_CUSTOMER_REPOSITORY 2
#define INSTALL_SW_PACKETS_DRY_RUN 3
#define INSTALL_SW_PACKETS 4
#define UPDATE_DC 5
#define SYNCHRONIZE_REPOSITORY 6
#define INSTALL_DC_CONFIGURATION 7
#define CHECK_ISMAS_CONNECT_PERCENT_START ( 1)
#define CHECK_ISMAS_CONNECT_PERCENT_END (10)
#define CHECK_UPDATE_REQUEST_PERCENT_START (10)
#define CHECK_UPDATE_REQUEST_PERCENT_END (20)
#define UPDATE_GIT_PERCENT_START (20)
#define UPDATE_GIT_PERCENT_END (21)
#define UPDATE_OPKG_NOACTION_PERCENT_START (21)
#define UPDATE_OPKG_NOACTION_PERCENT_END (25)
#define UPDATE_OPKG_PERCENT_START (25)
#define UPDATE_OPKG_PERCENT_END (40)
#define UPDATE_DOWNLOAD_DC_START (41)
#define UPDATE_DOWNLOAD_DC_END (80)
#define UPDATE_SYNC_START (81)
#define UPDATE_SYNC_END (90)
#define UPDATE_DOWNLOAD_JSON_START (91)
#define UPDATE_DOWNLOAD_JSON_END (100)
void MainWindow::onFileChanged(QString const& /*f*/) {
static int i = 30;
ui->updateProgress->setValue(++i);
// TODO: daten an ISMAS senden
}
QProgressBar *MainWindow::progressBar() {
return ui ? ui->updateProgress : nullptr;
}
MainWindow::MainWindow(Worker *worker, QWidget *parent) MainWindow::MainWindow(Worker *worker, QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
, ui(new Ui::MainWindow) , ui(new Ui::MainWindow)
, m_worker(worker) , m_worker(worker)
, m_width(70) , m_width(60)
, m_progressRunning(false) , m_progressRunning(false)
, m_updateStep(UpdateDcEvent::UpdateStep::NONE) { , m_updateStep(UpdateDcEvent::UpdateStep::NONE)
, m_updateLog("/opt/app/tools/atbupdate/update.log") { // TODO: in ini-file eintragen
ui->setupUi(this); ui->setupUi(this);
if (!m_updateLog.open(QIODevice::ReadWrite | QIODevice::Unbuffered)) {
qCritical() << "ERROR can not open" << m_updateLog.fileName();
}
m_updateSteps.resize(8);
m_updateSteps[CHECK_BACKEND_CONNECTION] = "Check backend connection (ISMAS) ";
m_updateSteps[CHECK_UPDATE_REQUEST] = "Check update request ";
m_updateSteps[UPDATE_CUSTOMER_REPOSITORY] = "Update customer repository ";
m_updateSteps[INSTALL_SW_PACKETS_DRY_RUN] = "Install SW packets (dry run) ";
m_updateSteps[INSTALL_SW_PACKETS] = "Install SW packets ";
m_updateSteps[UPDATE_DC] = "Update DC ";
m_updateSteps[SYNCHRONIZE_REPOSITORY] = "Synchronize repository/filesystem ";
m_updateSteps[INSTALL_DC_CONFIGURATION] = "Install DC configuration ";
QString text{};
for (int i = 0; i < m_updateSteps.size(); ++i) {
QString &tmp = m_updateSteps[i];
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
m_updateSteps[i] = tmp;
text += m_updateSteps[i];
}
ui->stepLabel->setTextFormat(Qt::RichText);
ui->stepLabel->setText(text);
this->setStatusBar(new QStatusBar(this)); this->setStatusBar(new QStatusBar(this));
QFont f; QFont f;
f.setStyleHint(QFont::Monospace); f.setStyleHint(QFont::Monospace);
@@ -45,7 +118,7 @@ MainWindow::MainWindow(Worker *worker, QWidget *parent)
lst << QString("Update tool version : %1 - %2 %3").arg(APP_VERSION).arg(APP_BUILD_DATE).arg(APP_BUILD_TIME).leftJustified(m_width-3); lst << QString("Update tool version : %1 - %2 %3").arg(APP_VERSION).arg(APP_BUILD_DATE).arg(APP_BUILD_TIME).leftJustified(m_width-3);
lst << QString("Machine number : %1 ").arg(m_worker->machineNr()).leftJustified(m_width-3); lst << QString("Machine number : %1 ").arg(m_worker->machineNr()).leftJustified(m_width-3);
lst << QString("Customer number : %1 ").arg(m_worker->customerNr()).leftJustified(m_width-3); lst << QString("Customer number : %1 ").arg(m_worker->customerNr()).leftJustified(m_width-3);
lst << QString("Zone number : %1 (%2)").arg(m_worker->zoneNr()).arg(Utils::zoneName(m_worker->zoneNr())).leftJustified(m_width-3); lst << QString("Zone number : %1 ").arg(m_worker->zoneNr()).leftJustified(m_width-3);
lst << QString("APISM version : %1").arg(m_worker->apismVersion()).leftJustified(m_width-3); lst << QString("APISM version : %1").arg(m_worker->apismVersion()).leftJustified(m_width-3);
lst << QString("").leftJustified(m_width-3, '='); lst << QString("").leftJustified(m_width-3, '=');
@@ -81,7 +154,12 @@ MainWindow::MainWindow(Worker *worker, QWidget *parent)
m_statusTimer->start(1000); m_statusTimer->start(1000);
} }
connect(m_worker->summaryTimer(), SIGNAL(timeout()), this, SLOT(onSummary()));
m_worker->summaryTimer()->setSingleShot(true);
m_worker->summaryTimer()->setInterval(5000);
connect(ui->exit, SIGNAL(clicked()),this,SLOT(onQuit())); connect(ui->exit, SIGNAL(clicked()),this,SLOT(onQuit()));
connect(m_worker, SIGNAL(summary()),this,SLOT(onSummary()));
connect(m_worker, SIGNAL(showSummary(QString)),this,SLOT(onShowSummary(QString))); connect(m_worker, SIGNAL(showSummary(QString)),this,SLOT(onShowSummary(QString)));
connect(m_worker, SIGNAL(disableExit()),this,SLOT(onDisableExit())); connect(m_worker, SIGNAL(disableExit()),this,SLOT(onDisableExit()));
connect(m_worker, SIGNAL(showDcDownload(QString)),this,SLOT(onShowDcDownload(QString))); connect(m_worker, SIGNAL(showDcDownload(QString)),this,SLOT(onShowDcDownload(QString)));
@@ -114,8 +192,91 @@ MainWindow::MainWindow(Worker *worker, QWidget *parent)
connect(m_worker, SIGNAL(replaceLast(QStringList,QString)),this, SLOT(onReplaceLast(QStringList,QString))); connect(m_worker, SIGNAL(replaceLast(QStringList,QString)),this, SLOT(onReplaceLast(QStringList,QString)));
} }
void MainWindow::onSummary() {
QThread::sleep(3);
QString summary, first, second, line, tmp;
QVector<QPair<QString, QString>> vec = Utils::installedPackages();
if (m_worker) {
vec.append(Utils::installedTariffFiles(m_worker, m_worker->customerRepository()));
vec.append(Utils::installedJsonFiles(m_worker, m_worker->customerRepository()));
}
int max_first = 0, max_second = 0;
for (int i = 0; i < vec.size(); ++i) {
max_first = std::max(max_first, vec[i].first.length());
max_second = std::max(max_second, vec[i].second.length());
}
max_first += 5;
summary = "UPDATE SUMMARY\n\n";
if (m_worker) {
first = QString("%1").arg("start", max_first, QChar(' '));
tmp = QString("%1").arg(m_worker->start().toString(Qt::ISODate));
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
first = QString("%1").arg("update tool version", max_first, QChar(' '));
tmp = QString("%1 - %2 %3").arg(APP_VERSION).arg(APP_BUILD_DATE).arg(APP_BUILD_TIME);
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
if (m_worker) {
first = QString("%1").arg("machine number", max_first, QChar(' '));
tmp = QString("%1").arg(m_worker->machineNr());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
first = QString("%1").arg("customer number", max_first, QChar(' '));
tmp = QString("%1").arg(m_worker->customerNr());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
first = QString("%1").arg("zone number", max_first, QChar(' '));
tmp = QString("%1").arg(m_worker->zoneNr());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
tmp = targetDcVersion();
if (!tmp.isEmpty()) {
first = QString("%1").arg("target device controller", max_first, QChar(' '));
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
if (m_worker) {
first = QString("%1").arg("apism", max_first, QChar(' '));
tmp = QString("%1").arg(m_worker->apismVersion());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
for (int i = 0; i < vec.size(); ++i) {
first = QString("%1").arg(vec[i].first, max_first, QChar(' '));
second = QString("%1").arg(vec[i].second, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
if (m_worker) {
emit m_worker->showSummary(summary);
emit m_worker->enableExit();
}
}
void MainWindow::onShowSummary(QString text) { void MainWindow::onShowSummary(QString text) {
// QString s = ui->updateLabel->text(); // QString s = ui->updateLabel->text();
QString s("\n"); QString s("\n");
@@ -133,6 +294,9 @@ void MainWindow::onSetDcDownloadProgress(int v) {
} }
void MainWindow::onShowTariffUpdate(QString) { void MainWindow::onShowTariffUpdate(QString) {
return;
ui->exit->setEnabled(false); ui->exit->setEnabled(false);
QString s = ui->stepLabel->text(); QString s = ui->stepLabel->text();
@@ -149,81 +313,105 @@ void MainWindow::onShowTariffUpdate(QString) {
} }
void MainWindow::onShowISMASConnectivity(QString status) { void MainWindow::onShowISMASConnectivity(QString status) {
// ausgabe: connected, not connected, connecting // qCritical() << __func__ << ":" << __LINE__ << "status" << status;
m_stepLabelChopCount = 0; QString stepResult;
qCritical() << __func__ << ":" << __LINE__ << "status" << status; QString s = m_updateSteps[CHECK_BACKEND_CONNECTION].trimmed();
QString s = ui->stepLabel->text();
QString tmp("Check backend connection (ISMAS) ");
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
bool const custRepoExists = internal::customerRepoExists(); bool const custRepoExists = internal::customerRepoExists();
if (status.contains(UpdateCommand::ISMAS_CONNECTED, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::ISMAS_CONNECTED, Qt::CaseInsensitive)) {
if (custRepoExists) { if (custRepoExists) {
s += QString("%1 <font color='Green'>connected</font><br />").arg(tmp); s += " <font color='Green'>connected</font>";
stepResult = "ISMAS connected";
} else { } else {
s += QString("%1 <font color='Green'>connected&nbsp;(initial configuration)</font><br />").arg(tmp); s += " <font color='Green'>connected&nbsp;(initial configuration)</font>";
stepResult = "ISMAS connected (initial configuration)";
} }
} else } else
if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Blue'>NOT CONNECTED</font><br />").arg(tmp); s += " <font color='Blue'>NOT CONNECTED</font>";
stepResult = "ISMAS not connected";
} else } else
if (status.contains(UpdateCommand::ISMAS_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::ISMAS_CONNECTION_IN_PROGRESS, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>connecting</font><br />").arg(tmp); s += " <font color='Green'>connecting</font>";
stepResult = "connecting ISMAS";
} else } else
if (status.contains(UpdateCommand::ISMAS_NOT_CONNECTED, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::ISMAS_NOT_CONNECTED, Qt::CaseInsensitive)) {
if (custRepoExists) { if (custRepoExists) {
s += QString( "%1 <font color='Red'>NOT CONNECTED. STOP</font><br />").arg(tmp); s += " <font color='Red'>NOT CONNECTED. STOP</font>";
stepResult = "ISMAS not connected";
} else { } else {
s += QString( "%1 <font color='Red'>not connected.&nbsp;(initial configuration)</font><br />").arg(tmp); s += " <font color='Red'>not connected.&nbsp;(initial configuration)</font>";
stepResult = "ISMAS not connected (initial configuration)";
} }
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp); s += " <font color='Red'>UNKNOWN STATUS</font>";
stepResult = "unknown status";
} }
m_stepLabelChopCount = -s.length(); struct LogLineEntry logLine =
s += "Check update request"; initLogLineEntry(1, // receiver
m_stepLabelChopCount += s.length(); QDateTime::currentDateTime().toString(Qt::ISODate).toUtf8().constData(),
_ISMAS_CONTINUE,
0, // eventState
CHECK_ISMAS_CONNECT_PERCENT_START,
ISMAS::RESULT_CODE::E_SUCCESS,
"show ISMAS connectivity", // step
stepResult.toUtf8().constData()); // stepResult
int w = 0;
if ((w = m_updateLog.write((char *)(&logLine), sizeof(logLine))) != sizeof(logLine)) {
qCritical() << __func__ << ":" << __LINE__ << "ERROR only" << w << "bytes written";
}
m_updateSteps[CHECK_BACKEND_CONNECTION] = s;
s.clear();
for (int i = 0; i < m_updateSteps.size(); ++i) {
s += m_updateSteps[i] + "<br />";
}
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
logLine =
initLogLineEntry(1, // receiver
QDateTime::currentDateTime().toString(Qt::ISODate).toUtf8().constData(),
_ISMAS_CONTINUE,
0, // eventState
CHECK_ISMAS_CONNECT_PERCENT_END,
ISMAS::RESULT_CODE::E_SUCCESS,
"show ISMAS connectivity", // step
stepResult.toUtf8().constData()); // stepResult
if ((w = m_updateLog.write((char *)(&logLine), sizeof(logLine))) != sizeof(logLine)) {
qCritical() << __func__ << ":" << __LINE__ << "ERROR only" << w << "bytes written";
}
} }
void MainWindow::onShowCustRepoStatus(QString status) { void MainWindow::onShowCustRepoStatus(QString status) {
qCritical() << __func__ << ":" << __LINE__ << "status" << status; // qCritical() << __func__ << ":" << __LINE__ << "status" << status;
QString s = ui->stepLabel->text(); QString s = m_updateSteps[UPDATE_CUSTOMER_REPOSITORY].trimmed();
s.chop(m_stepLabelChopCount);
QString tmp("Update customer repository ");
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
if (status.contains(internal::GIT_CUSTOMER_REPO_UP_TO_DATE, Qt::CaseInsensitive)) { if (status.contains(internal::GIT_CUSTOMER_REPO_UP_TO_DATE, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>%2</font><br />").arg(tmp).arg(internal::GIT_CUSTOMER_REPO_UP_TO_DATE); s += QString(" <font color='Green'>%1</font>").arg(internal::GIT_CUSTOMER_REPO_UP_TO_DATE);
} else } else
if (status.contains(internal::GIT_CUSTOMER_REPO_NOT_NECESSARY, Qt::CaseInsensitive)) { if (status.contains(internal::GIT_CUSTOMER_REPO_NOT_NECESSARY, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>%2</font><br />").arg(tmp).arg(internal::GIT_CUSTOMER_REPO_NOT_NECESSARY); s += QString(" <font color='Green'>%1</font>").arg(internal::GIT_CUSTOMER_REPO_NOT_NECESSARY);
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp); s += " <font color='Red'>UNKNOWN STATUS</font>";
} }
m_stepLabelChopCount = -s.length(); m_updateSteps[UPDATE_CUSTOMER_REPOSITORY] = s;
s += "Install SW packets (dry run)"; s.clear();
m_stepLabelChopCount += s.length(); for (int i = 0; i < m_updateSteps.size(); ++i) {
s += m_updateSteps[i] + "<br />";
}
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
} }
void MainWindow::onShowExecOpkgStatus(QString status) { void MainWindow::onShowExecOpkgStatus(QString status) {
qCritical() << __func__ << ":" << __LINE__ << "status" << status; qCritical() << __func__ << ":" << __LINE__ << "status" << status;
return;
QString s = ui->stepLabel->text(); QString s = ui->stepLabel->text();
@@ -245,6 +433,7 @@ void MainWindow::onShowExecOpkgStatus(QString status) {
void MainWindow::onShowExecOpkgCommand(QString cmd) { void MainWindow::onShowExecOpkgCommand(QString cmd) {
qCritical() << __func__ << ":" << __LINE__ << "cmd" << cmd; qCritical() << __func__ << ":" << __LINE__ << "cmd" << cmd;
return;
if (cmd.back() != QChar('\n')) { if (cmd.back() != QChar('\n')) {
cmd += "\n"; cmd += "\n";
@@ -253,109 +442,91 @@ void MainWindow::onShowExecOpkgCommand(QString cmd) {
} }
void MainWindow::onShowExecOpkgOverallResult(QString status, bool noaction) { void MainWindow::onShowExecOpkgOverallResult(QString status, bool noaction) {
qCritical() << __func__ << ":" << __LINE__ << "status" << status; //qCritical() << __func__ << ":" << __LINE__ << "status" << status;
QString s = ui->stepLabel->text(); QString s = noaction ?
s.chop(m_stepLabelChopCount); m_updateSteps[INSTALL_SW_PACKETS_DRY_RUN].trimmed() :
m_updateSteps[INSTALL_SW_PACKETS].trimmed();
QString tmp = noaction ? "Install SW packets (dry run) " : "Install SW packets ";
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
if (status.contains(internal::EXEC_OPKG_COMMANDS_SUCCESS, Qt::CaseInsensitive)) { if (status.contains(internal::EXEC_OPKG_COMMANDS_SUCCESS, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>success</font><br />").arg(tmp); s += " <font color='Green'>success</font>";
} else } else
if (status.contains(internal::EXEC_OPKG_COMMANDS_FAIL, Qt::CaseInsensitive)) { if (status.contains(internal::EXEC_OPKG_COMMANDS_FAIL, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Red'>%2</font><br />").arg(tmp).arg(internal::EXEC_OPKG_COMMANDS_FAIL); s += QString(" <font color='Red'>%1</font>").arg(internal::EXEC_OPKG_COMMANDS_FAIL);
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp); s += " <font color='Red'>UNKNOWN STATUS</font>";
} }
if (noaction) { if (noaction) {
m_stepLabelChopCount = -s.length(); m_updateSteps[INSTALL_SW_PACKETS_DRY_RUN] = s;
s += "Install SW packets";
m_stepLabelChopCount += s.length();
} else { } else {
m_stepLabelChopCount = -s.length(); m_updateSteps[INSTALL_SW_PACKETS] = s;
s += "Install DC configuration"; }
m_stepLabelChopCount += s.length();
s.clear();
for (int i = 0; i < m_updateSteps.size(); ++i) {
s += m_updateSteps[i] + "<br />";
} }
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
} }
void MainWindow::onShowDownloadDCJsonFilesStatus(QString status) { void MainWindow::onShowDownloadDCJsonFilesStatus(QString status) {
qCritical() << __func__ << ":" << __LINE__ << "status" << status; //qCritical() << __func__ << ":" << __LINE__ << "status" << status;
QString s = ui->stepLabel->text(); QString s = m_updateSteps[INSTALL_DC_CONFIGURATION].trimmed();
s.chop(m_stepLabelChopCount);
QString tmp = "Install DC configuration ";
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
if (status.contains(UpdateCommand::UPDATE_DC_JSON_FILES_SUCCESS, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::UPDATE_DC_JSON_FILES_SUCCESS, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>success</font><br />").arg(tmp); s += " <font color='Green'>success</font>";
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp); s += " <font color='Red'>UNKNOWN STATUS</font>";
} }
m_stepLabelChopCount = -s.length(); m_updateSteps[INSTALL_DC_CONFIGURATION] = s;
s += "Synchronize repository/filesystem"; s.clear();
m_stepLabelChopCount += s.length(); for (int i = 0; i < m_updateSteps.size(); ++i) {
s += m_updateSteps[i] + "<br />";
}
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
} }
void MainWindow::onShowSyncCustRepoStatus(QString status) { void MainWindow::onShowSyncCustRepoStatus(QString status) {
qCritical() << __func__ << ":" << __LINE__ << "status" << status; //qCritical() << __func__ << ":" << __LINE__ << "status" << status;
QString s = ui->stepLabel->text(); QString s = m_updateSteps[SYNCHRONIZE_REPOSITORY].trimmed();
s.chop(m_stepLabelChopCount);
QString tmp = "Synchronize repository/filesystem ";
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
if (status.contains(UpdateCommand::SYNC_CUSTOMER_REPO_FILES_SUCCESS, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::SYNC_CUSTOMER_REPO_FILES_SUCCESS, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>success</font><br />").arg(tmp); s += " <font color='Green'>success</font>";
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp); s += " <font color='Red'>UNKNOWN STATUS</font>";
} }
m_stepLabelChopCount = -s.length(); m_updateSteps[SYNCHRONIZE_REPOSITORY] = s;
s += "Update DC"; s.clear();
m_stepLabelChopCount += s.length(); for (int i = 0; i < m_updateSteps.size(); ++i) {
s += m_updateSteps[i] + "<br />";
}
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
} }
void MainWindow::onShowUpdateDCFirmware(QString status) { void MainWindow::onShowUpdateDCFirmware(QString status) {
qCritical() << __func__ << ":" << __LINE__ << "status" << status; // qCritical() << __func__ << ":" << __LINE__ << "status" << status;
QString s = ui->stepLabel->text(); QString s = m_updateSteps[UPDATE_DC].trimmed();
s.chop(m_stepLabelChopCount);
QString tmp = "Update DC "; if (status.contains(internal::UPDATE_DC_FIRMARE_SUCCESS, Qt::CaseInsensitive)) {
int len = m_showLineLength - tmp.length(); s += " <font color='Green'>success</font>";
} else {
while (--len > 0) { s += " <font color='Red'>UNKNOWN STATUS</font>";
tmp += "&nbsp;";
} }
if (status.contains(UpdateCommand::UPDATE_DC_FIRMARE_SUCCESS, Qt::CaseInsensitive)) { s.clear();
s += QString("%1 <font color='Green'>success</font><br />").arg(tmp); for (int i = 0; i < m_updateSteps.size(); ++i) {
if (i != UPDATE_DC) {
s += m_updateSteps[i] + "<br />";
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN STATUS</font><br />").arg(tmp); s += m_updateSteps[i];
}
} }
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
@@ -363,55 +534,53 @@ void MainWindow::onShowUpdateDCFirmware(QString status) {
void MainWindow::onShowUpdateRequest(QString status) { void MainWindow::onShowUpdateRequest(QString status) {
// qCritical() << __func__ << ":" << __LINE__ << "status" << status;
qCritical() << __func__ << ":" << __LINE__ << "status" << status; //ui->updateProgress->setValue(CHECK_UPDATE_REQUEST_PERCENT_START);
QString s = m_updateSteps[CHECK_UPDATE_REQUEST].trimmed();
QString s = ui->stepLabel->text();
s.chop(m_stepLabelChopCount);
QString tmp = "Check update request ";
int len = m_showLineLength - tmp.length();
while (--len > 0) {
tmp += "&nbsp;";
}
bool const custRepoExists = internal::customerRepoExists(); bool const custRepoExists = internal::customerRepoExists();
if (status.contains(UpdateCommand::UPDATE_NOT_REQUESTED, Qt::CaseInsensitive)) { if (status.contains(UpdateCommand::UPDATE_NOT_REQUESTED, Qt::CaseInsensitive)) {
if (custRepoExists) { if (custRepoExists) {
s += QString( "%1 <font color='Red'>NOT REQUESTED. STOP.</font><br />").arg(tmp); s += " <font color='Red'>NOT REQUESTED. STOP.</font>";
} else { } else {
s += QString("%1 <font color='Blue'>not requested&nbsp;(initial configuration)</font><br />").arg(tmp); s += " <font color='Blue'>not requested&nbsp;(initial configuration)</font>";
} }
} else } else
if (status.contains(UpdateCommand::UPDATE_REQUESTED, Qt::CaseInsensitive)) { if (status.contains(internal::UPDATE_REQUESTED, Qt::CaseInsensitive)) {
if (custRepoExists) { if (custRepoExists) {
s += QString("%1 <font color='Green'>requested</font><br />").arg(tmp); s += " <font color='Green'>requested</font>";
} else { } else {
s += QString("%1 <font color='Blue'>requested&nbsp;(initial configuration)</font><br />").arg(tmp); s += " <font color='Blue'>requested&nbsp;(initial configuration)</font>";
} }
} else } else
if (status.contains(UpdateCommand::UPDATE_NOT_NECESSARY, Qt::CaseInsensitive)) { if (status.contains(internal::UPDATE_INITIAL, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Green'>not necessary</font><br />").arg(tmp); s += " <font color='Green'>requested&nbsp;(initial configuration)</font>";
} else } else
if (status.contains(UpdateCommand::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) { if (status.contains(internal::UPDATE_NOT_NECESSARY, Qt::CaseInsensitive)) {
s += QString("%1 <font color='Blue'>UNKNOWN (ISMAS not connected)</font><br />").arg(tmp); s += " <font color='Green'>not necessary</font>";
} else
if (status.contains(internal::NO_CUSTOMER_REPOSITORY, Qt::CaseInsensitive)) {
s += " <font color='Blue'>UNKNOWN (ISMAS not connected)</font>";
} else { } else {
s += QString( "%1 <font color='Red'>UNKNOWN</font><br />").arg(tmp); s += " <font color='Red'>UNKNOWN</font>";
} }
m_stepLabelChopCount = -s.length(); m_updateSteps[CHECK_UPDATE_REQUEST] = s;
s += "Update customer repository"; s.clear();
m_stepLabelChopCount += s.length(); for (int i = 0; i < m_updateSteps.size(); ++i) {
s += m_updateSteps[i] + "<br />";
}
ui->stepLabel->setText(s); ui->stepLabel->setText(s);
//ui->updateProgress->setValue(CHECK_UPDATE_REQUEST_PERCENT_END);
} }
void MainWindow::onShowISMASChecks(QString) { void MainWindow::onShowISMASChecks(QString) {
// deprecated // deprecated
QString s = ui->stepLabel->text(); QString s = ui->stepLabel->text();
return;
QString tmp("Check ISMAS connectivity "); QString tmp("Check ISMAS connectivity ");
int len = m_showLineLength - tmp.length(); int len = m_showLineLength - tmp.length();
@@ -449,6 +618,9 @@ void MainWindow::onShowJsonDownload(QString) {
} }
void MainWindow::onShowDcDownload(QString version) { void MainWindow::onShowDcDownload(QString version) {
return;
m_targetDcVersion = version; m_targetDcVersion = version;
ui->exit->setEnabled(false); ui->exit->setEnabled(false);

View File

@@ -4,6 +4,9 @@
#include <QMainWindow> #include <QMainWindow>
#include <QTimer> #include <QTimer>
#include <QStatusBar> #include <QStatusBar>
#include <QVector>
#include <QString>
#include <QProgressBar>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
@@ -37,6 +40,7 @@ public:
void setUpdateStep(UpdateDcEvent::UpdateStep updateStep) { m_updateStep = updateStep; } void setUpdateStep(UpdateDcEvent::UpdateStep updateStep) { m_updateStep = updateStep; }
QString targetDcVersion() {return m_targetDcVersion; } QString targetDcVersion() {return m_targetDcVersion; }
QProgressBar *progressBar();
public slots: public slots:
void onAppendText(QString, QString suffix = ""); void onAppendText(QString, QString suffix = "");
@@ -66,6 +70,8 @@ public slots:
void onShowUpdateDCFirmware(QString); void onShowUpdateDCFirmware(QString);
void onSetDcDownloadProgress(int); void onSetDcDownloadProgress(int);
void onShowSummary(QString); void onShowSummary(QString);
void onSummary();
void onFileChanged(QString const&);
#if EMERGENCY_LEAVE_BL==1 #if EMERGENCY_LEAVE_BL==1
void emergencyLeaveBL(); void emergencyLeaveBL();
#endif #endif
@@ -97,5 +103,9 @@ private:
QTimer *m_statusTimer; QTimer *m_statusTimer;
QString m_targetDcVersion; QString m_targetDcVersion;
int m_stepLabelChopCount{}; int m_stepLabelChopCount{};
QVector<QString> m_updateSteps{};
QFile m_updateLog;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@@ -51,6 +51,9 @@
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="3"> <item row="3" column="0" colspan="3">

View File

@@ -34,6 +34,9 @@ void CheckUpdateActivationCommand::readyReadStandardOutput() {
} else } else
if (s == internal::NO_CUSTOMER_REPOSITORY) { if (s == internal::NO_CUSTOMER_REPOSITORY) {
emit w->showUpdateRequest(internal::NO_CUSTOMER_REPOSITORY); emit w->showUpdateRequest(internal::NO_CUSTOMER_REPOSITORY);
} else
if (s == internal::UPDATE_INITIAL) {
emit w->showUpdateRequest(internal::UPDATE_INITIAL);
} }
} }
} }

View File

@@ -50,7 +50,7 @@ void Command::readyReadStandardOutput() {
s = s.mid(0, i).trimmed(); s = s.mid(0, i).trimmed();
} }
} }
emit m_worker->showDcDownload(s); // emit m_worker->showDcDownload(s);
} else } else
if ((i = s.indexOf("<DC-PROGRESS>")) != -1) { if ((i = s.indexOf("<DC-PROGRESS>")) != -1) {
bool ok; bool ok;
@@ -61,14 +61,15 @@ void Command::readyReadStandardOutput() {
} }
} else } else
if ((i = s.indexOf("<DC-UPDATE-FINISH>")) != -1) { if ((i = s.indexOf("<DC-UPDATE-FINISH>")) != -1) {
m_worker->summary(); emit m_worker->summary();
// qApp->exit(0); // qApp->exit(0);
} else } else
if ((i = s.indexOf("<DC-UPDATE-SUCCESS>")) != -1) { if ((i = s.indexOf("<DC-UPDATE-SUCCESS>")) != -1) {
m_worker->summary(); // TODO
emit m_worker->summary();
} else } else
if ((i = s.indexOf("<DC-UPDATE-FAILURE>")) != -1) { if ((i = s.indexOf("<DC-UPDATE-FAILURE>")) != -1) {
m_worker->summary(); emit m_worker->summary();
//qApp->exit(-1); //qApp->exit(-1);
} else } else
if ((i = s.indexOf("<JS-PROGRESS>")) != -1) { if ((i = s.indexOf("<JS-PROGRESS>")) != -1) {

View File

@@ -45,10 +45,6 @@ void UpdateCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) {
//static constexpr const int PERCENT_UPDATE_DC{80}; //static constexpr const int PERCENT_UPDATE_DC{80};
//static constexpr const int PERCENT_SHOW_FINAL_STATUS{90}; //static constexpr const int PERCENT_SHOW_FINAL_STATUS{90};
qCritical() << __func__ << ":" << __LINE__ << m_command
<< "exitCode" << exitCode
<< "exitStatus" << exitStatus;
if (exitCode == 0 && exitStatus == QProcess::ExitStatus::NormalExit) { if (exitCode == 0 && exitStatus == QProcess::ExitStatus::NormalExit) {
if (m_command.contains("ATBUpdateCheck")) { if (m_command.contains("ATBUpdateCheck")) {
@@ -113,24 +109,33 @@ void UpdateCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) {
"sync customer repository with /etc"); "sync customer repository with /etc");
m_worker->clientForUpdate().sendCmdEvent(e); m_worker->clientForUpdate().sendCmdEvent(e);
} else } else
if (m_command.contains("ATBDownloadDCFirmware")) { if (m_command.contains("ATBUpdateDC")) {
ISMAS::EventData e(ISMAS::CONTINUE, ISMAS::EventData e(ISMAS::CONTINUE,
internal::PERCENT_UPDATE_DC, internal::PERCENT_UPDATE_DC,
0, 0,
"ATBDownloadDCFirmware", "ATBUpdateDC",
"downloaded new dc-firmware. about to reboot..."); "downloaded new dc-firmware. about to reboot...");
m_worker->clientForUpdate().sendCmdEvent(e); m_worker->clientForUpdate().sendCmdEvent(e);
} else } else
if (m_command.contains("ATBUpdateShowPSAInstalled")) { if (m_command.contains("ATBUpdateShow")) {
// TODO // TODO
} }
if (m_worker->workList().nextExec()) { if (m_worker->workList().nextExec()) {
m_worker->workList().exec(); m_worker->workList().exec();
} else {
// testing
qCritical() << __func__ << ":" << __LINE__ << "TEST: SEND UPDATE SUCCEEDED TO ISMAS";
m_worker->setLastFailedUpdateStep(Worker::UPDATE_STEP::NONE);
Worker::UpdateProcessRunning _(m_worker);
} }
} else { } else {
bool execShowStatus = true; bool execShowStatus = true;
m_worker->workList().exec(execShowStatus); m_worker->workList().exec(execShowStatus);
} }
} else {
Q_ASSERT_X(false,
QString("%1:%2").arg(__func__).arg(__LINE__).toUtf8().constData(),
"empty worker list");
} }
} }

View File

@@ -1,5 +1,6 @@
#include "process/update_dc_command.h" #include "process/update_dc_command.h"
#include "worker.h" #include "worker.h"
#include "utils_internal.h"
UpdateDCCommand::UpdateDCCommand(QString const &command, UpdateDCCommand::UpdateDCCommand(QString const &command,
Worker *worker, Worker *worker,
@@ -10,19 +11,55 @@ UpdateDCCommand::UpdateDCCommand(QString const &command,
} }
void UpdateDCCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) { void UpdateDCCommand::finished(int exitCode, QProcess::ExitStatus exitStatus) {
Worker *w = worker();
if (w) {
w->summaryTimer()->start();
}
return UpdateCommand::finished(exitCode, exitStatus); return UpdateCommand::finished(exitCode, exitStatus);
} }
void UpdateDCCommand::readyReadStandardOutput() { void UpdateDCCommand::readyReadStandardOutput() {
QProcess *p = (QProcess *)sender(); QProcess *p = (QProcess *)sender();
if (p) { if (p) {
QString s = p->readAllStandardOutput();
// TODO
Worker *w = worker(); Worker *w = worker();
if (w) { if (w) {
// static constexpr const char *UPDATE_DC_FIRMARE_SUCCESS"success"}; QString s = p->readAllStandardOutput();
emit w->showUpdateDCFirmware(UpdateCommand::UPDATE_DC_FIRMARE_SUCCESS); int i = -1;
if ((i = s.indexOf("<DC-VERSION>")) != -1) {
s = s.mid(i+12).trimmed();
if ((i = s.indexOf("\"")) != -1) {
s = s.mid(i+1);
if ((i = s.indexOf("\"")) != -1) {
s = s.mid(0, i).trimmed();
}
}
// emit w->showDcDownload(s);
} else
if ((i = s.indexOf("<DC-PROGRESS>")) != -1) {
bool ok;
int v = s.mid(i+13).trimmed().toInt(&ok);
if (ok) {
emit w->setDcDownloadProgress(v);
emit w->insertText(s.mid(0,i) + "\n");
}
} else
if ((i = s.indexOf("<DC-UPDATE-FINISH>")) != -1) {
emit w->showUpdateDCFirmware(internal::UPDATE_DC_FIRMARE_SUCCESS);
// QThread::sleep(3);
// emit w->summary();
// qApp->exit(0);
} else
if ((i = s.indexOf("<DC-UPDATE-SUCCESS>")) != -1) {
// TODO
emit w->summary();
} else
if ((i = s.indexOf("<DC-UPDATE-FAILURE>")) != -1) {
emit w->summary();
//qApp->exit(-1);
} else {
emit w->insertText(s);
}
m_commandResult += s;
} }
} }
} }

View File

@@ -9,7 +9,7 @@ public:
Worker *worker, Worker *worker,
int nextCommandIndex, int nextCommandIndex,
int start_timeout = 100000, int start_timeout = 100000,
int finish_timeout = 100000); int finish_timeout = -1);
public slots: public slots:
virtual void readyReadStandardOutput() override; virtual void readyReadStandardOutput() override;
virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override; virtual void finished(int exitCode, QProcess::ExitStatus exitStatus) override;

View File

@@ -31,6 +31,8 @@ public:
unsigned nextExecIndex() const; unsigned nextExecIndex() const;
bool nextExec() const; bool nextExec() const;
bool exec(bool last=false); bool exec(bool last=false);
unsigned size() { return m_workList.size(); }
}; };
#endif // WORK_LIST_H_INCLUDED #endif // WORK_LIST_H_INCLUDED

View File

@@ -19,6 +19,7 @@
#include <QScopedPointer> #include <QScopedPointer>
#include <QRegularExpression> #include <QRegularExpression>
#include <QJsonArray> #include <QJsonArray>
#include <QProgressBar>
#include <memory> #include <memory>
@@ -29,6 +30,7 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "utils.h" // deprecated #include "utils.h" // deprecated
#include "utils_internal.h" #include "utils_internal.h"
#include "log_line_entry.h"
#include "process/command.h" #include "process/command.h"
#include "process/update_command.h" #include "process/update_command.h"
#include "process/check_ismas_connectivity_command.h" #include "process/check_ismas_connectivity_command.h"
@@ -185,7 +187,7 @@ Worker::Worker(int customerNr,
, m_pluginVersionPrmCalcConfig(getPluginVersion("/opt/app/ATBAPP/plugins/libPRM_CalculatePricePlugin_ConfigUi.so")) , m_pluginVersionPrmCalcConfig(getPluginVersion("/opt/app/ATBAPP/plugins/libPRM_CalculatePricePlugin_ConfigUi.so"))
, m_pluginVersionTcpZvt(getPluginVersion("/opt/app/ATBAPP/plugins/libTCP_ZVT_CCPlugin.so")) , m_pluginVersionTcpZvt(getPluginVersion("/opt/app/ATBAPP/plugins/libTCP_ZVT_CCPlugin.so"))
, m_ismasUpdateRequests(ISMAS_UPDATE_REQUESTS) , m_ismasUpdateRequests(ISMAS_UPDATE_REQUESTS)
, m_waitForNewUpdates(this) , m_summaryTimer(this)
, m_filesToUpdate() , m_filesToUpdate()
, m_updateProcessRunning(true) , m_updateProcessRunning(true)
, m_mainWindow(nullptr) /* contains plugin */ , m_mainWindow(nullptr) /* contains plugin */
@@ -193,7 +195,28 @@ Worker::Worker(int customerNr,
, m_dcDownloadJsonFiles(new Command( , m_dcDownloadJsonFiles(new Command(
QString("/opt/app/tools/atbupdate/ATBDownloadDCJsonFiles --set-ppid %1").arg(QCoreApplication::applicationPid()))) QString("/opt/app/tools/atbupdate/ATBDownloadDCJsonFiles --set-ppid %1").arg(QCoreApplication::applicationPid())))
//, m_withoutIsmasDirectPort(true) /* useful for testing */ { //, m_withoutIsmasDirectPort(true) /* useful for testing */ {
, m_withoutIsmasDirectPort(false) /* useful for testing */ { , m_withoutIsmasDirectPort(false) /* useful for testing */
, m_updateLog("/opt/app/tools/atbupdate/update.log") // TODO: in ini-file eintragen
, m_updateLogBackup("/opt/app/tools/atbupdate/updateBackup.log") { // TODO: in ini-file eintragen
if (!m_updateLog.exists()) {
qCritical() << "ERROR" << m_updateLog.fileName() << "does not exist";
} else {
if (!m_updateLog.open(QIODevice::ReadWrite | QIODevice::Unbuffered)) {
qCritical() << "ERROR can not open" << m_updateLog.fileName();
} else {
m_updateLog.resize(0);
m_fileWatcher.addPath(QFileInfo(m_updateLog).absoluteFilePath());
connect(&m_fileWatcher, SIGNAL(fileChanged(QString const&)), this, SLOT(onFileChanged(QString const&)));
}
}
if (!m_updateLogBackup.open(QIODevice::ReadWrite | QIODevice::Unbuffered)) {
qCritical() << "ERROR can not open" << m_updateLogBackup.fileName();
} else {
m_updateLogBackup.resize(0);
m_updateLogBackup.close();
}
// *** check ISMAS connectivity *** // *** check ISMAS connectivity ***
// NOTE: if the customer repository does not exist, then it does not matter // NOTE: if the customer repository does not exist, then it does not matter
@@ -202,7 +225,7 @@ Worker::Worker(int customerNr,
int next = 1; int next = 1;
m_workList.push_back( m_workList.push_back(
std::make_unique<CheckIsmasConnectivityCommand>( std::make_unique<CheckIsmasConnectivityCommand>(
//QString("echo CheckIsmasConnectivityCommand") //QString("echo ATBUpdateCheck --ismas-connected")
QString("/opt/app/tools/atbupdate/ATBUpdateCheck --ismas-connected") QString("/opt/app/tools/atbupdate/ATBUpdateCheck --ismas-connected")
, this, ++next)); , this, ++next));
@@ -211,7 +234,7 @@ Worker::Worker(int customerNr,
// if the update has been activated via ISMAS. // if the update has been activated via ISMAS.
m_workList.push_back( m_workList.push_back(
std::make_unique<CheckUpdateActivationCommand>( std::make_unique<CheckUpdateActivationCommand>(
//QString("echo CheckUpdateActivationCommand") // QString("echo ATBUpdateCheck --update-requested")
QString("/opt/app/tools/atbupdate/ATBUpdateCheck --update-requested") QString("/opt/app/tools/atbupdate/ATBUpdateCheck --update-requested")
, this, ++next)); , this, ++next));
@@ -221,7 +244,7 @@ Worker::Worker(int customerNr,
// the corresponding branch, and check the integrity of the repository. // the corresponding branch, and check the integrity of the repository.
m_workList.push_back( m_workList.push_back(
std::make_unique<CheckAndFetchCustomerRepositoryCommand>( std::make_unique<CheckAndFetchCustomerRepositoryCommand>(
// QString("echo CheckAndFetchCustomerRepositoryCommand") // QString("echo ATBUpdateGit")
QString("/opt/app/tools/atbupdate/ATBUpdateGit") QString("/opt/app/tools/atbupdate/ATBUpdateGit")
, this, ++next)); , this, ++next));
@@ -229,7 +252,7 @@ Worker::Worker(int customerNr,
// NOTE: first run the opkg commands with no action -> dry-run // NOTE: first run the opkg commands with no action -> dry-run
m_workList.push_back( m_workList.push_back(
std::make_unique<ExecOpkgCommand>( std::make_unique<ExecOpkgCommand>(
// QString("echo ExecOpkgCommand noaction") // QString("echo ATBUpdateOpkg --noaction")
QString("/opt/app/tools/atbupdate/ATBUpdateOpkg --noaction") QString("/opt/app/tools/atbupdate/ATBUpdateOpkg --noaction")
, this, ++next, true)); , this, ++next, true));
@@ -237,16 +260,16 @@ Worker::Worker(int customerNr,
// NOTE: first run the opkg commands with action -> no dry-run // NOTE: first run the opkg commands with action -> no dry-run
m_workList.push_back( m_workList.push_back(
std::make_unique<ExecOpkgCommand>( std::make_unique<ExecOpkgCommand>(
//QString("echo ExecOpkgCommand run") QString("echo ExecOpkgCommand run")
QString("/opt/app/tools/atbupdate/ATBUpdateOpkg") // QString("/opt/app/tools/atbupdate/ATBUpdateOpkg")
, this, ++next, false)); , this, ++next, false));
// *** send json files down to device controller *** // send device-controller firmware down to device-controller-hardware
m_workList.push_back( m_workList.push_back(
std::make_unique<UpdateJsonCommand>( std::make_unique<UpdateDCCommand>(
QString("echo ATBDownloadDCJsonFiles") // QString("echo ATBUpdateDC")
//QString("/opt/app/tools/atbupdate/ATBDownloadDCJsonFiles --set-ppid %1").arg(QCoreApplication::applicationPid()) QString("/opt/app/tools/atbupdate/ATBUpdateDC")
, this, ++next, false)); , this, ++next));
// sync json files in repo etc-directory with /etc fs-directory // sync json files in repo etc-directory with /etc fs-directory
m_workList.push_back( m_workList.push_back(
@@ -254,17 +277,20 @@ Worker::Worker(int customerNr,
QString("echo ATBUpdateSync") QString("echo ATBUpdateSync")
, this, ++next)); , this, ++next));
// send device-controller firmware down to device-controller-hardware // *** send json files down to device controller ***
m_workList.push_back( m_workList.push_back(
std::make_unique<UpdateDCCommand>( std::make_unique<UpdateJsonCommand>(
QString("echo ATBDownloadDCFirmware") //QString("echo ATBUpdateJsonFiles")
// QString("/opt/app/tools/atbupdate/ATBDownloadDCFirmware --read-dc-version true") //QString("/opt/app/tools/atbupdate/ATBUpdateJsonFiles --set-ppid %1").arg(QCoreApplication::applicationPid())
, this, ++next));
// use customer repo
QString("/opt/app/tools/atbupdate/ATBUpdateJsonFiles").arg(QCoreApplication::applicationPid())
, this, ++next, false));
// show/send software-status // show/send software-status
m_workList.push_back( m_workList.push_back(
std::make_unique<ShowSoftwareStatusCommand>( std::make_unique<ShowSoftwareStatusCommand>(
QString("echo ATBUpdateShowPSAInstalled") QString("echo ATBUpdateShow")
, this, -1)); , this, -1));
// reboot machine // reboot machine
@@ -301,10 +327,91 @@ Worker::~Worker() {
} }
} }
#if 0
struct LogLineEntry {
char receiver; // 1 receiver can be: ISMAS
char reason[5]; // 6 SW_UP
char timestamp[19]; // 25 ISO-format: 1900-xx-xxT00:00:00
char eventId; // 26
char event[5]; // 31
/*
Note:
! After U0002 immer ein CMD_SENDVERSION
! Only U0002 and U0003 finish the Update process.
! U0001: Update finished but not activated
! U0002: Update finished and activated
! U0003: Update finished but FAILed.
*/
// #define _ISMAS_DONE "U0001" // 100%, Check: Resultcode: 0
// #define _ISMAS_SET_WAIT_OK "U0002" // empty WAIT-button (""), ResultCode: 0
// #define _ISMAS_NO_UPDATE_NECESSARY "M0100" // empty WAIT-button (""), ResultCode: 0
// #define _ISMAS_FAILURE "U0003" // FAIL
// #define _ISMAS_CONTINUE "U0010" // %-values: Update laeuft, Resultcodes entsprechend laufender Schritt
// #define _ISMAS_RESET_WAIT "ISMAS" // reset WAIT-button to "WAIT"
// #define _ISMAS_TEST_TRIGGER "U0099" // check the WAIT-button
char eventState; // 32
char percent; // 33 percent in progressbar of update-tool
char resultCode; // 34
char step[40]; // 74 step executed
char stepResult[40];// 114 result for step
char version[14]; // 128
};
#endif
void Worker::onFileChanged(QString const& fname) {
QFile f(fname);
//if (m_updateLog.fileName().contains(fname)) {
// if (f.exists() && m_updateLogBackup.exists()) {
if (!m_updateLogBackup.open(QIODevice::ReadWrite | QIODevice::Unbuffered)) {
qCritical() << "ERROR can not open" << m_updateLogBackup.fileName();
return;
}
if (f.open(QIODevice::ReadOnly)) {
QByteArray const &backup = m_updateLogBackup.readAll();
QByteArray const &data = f.readAll();
int const diff = data.size() - backup.size();
if (diff > 0) {
QByteArray const &newLines = data.mid(backup.size());
int const size = newLines.size();
if (size > 0) {
LogLineEntry logLine;
int pos = 0;
while (pos < size) {
QByteArray const &a = newLines.mid(pos, sizeof(logLine));
if (a.size() == sizeof(logLine)) {
memcpy(&logLine, a.data(), sizeof(logLine));
qCritical() << " reason:" << QString(QByteArray(logLine.reason, sizeof(logLine.reason)));
qCritical() << " timestamp:" << QString(QByteArray(logLine.timestamp, sizeof(logLine.timestamp)));
qCritical() << " event:" << QString(QByteArray(logLine.event, sizeof(logLine.event)));
qCritical() << " step:" << QString(QByteArray(logLine.step, sizeof(logLine.step)));
qCritical() << "stepResult:" << QString(QByteArray(logLine.stepResult, sizeof(logLine.stepResult)));
qCritical() << " percent:" << (int)logLine.percent;
displayProgressInMainWindow(logLine.percent);
}
pos += sizeof(logLine);
}
m_updateLogBackup.write(newLines);
}
}
f.close();
}
//}
m_updateLogBackup.close();
// TODO: daten an ISMAS senden
}
void Worker::displayProgressInMainWindow(int progress) { void Worker::displayProgressInMainWindow(int progress) {
if (m_mainWindow) { if (m_mainWindow) {
QApplication::postEvent(m_mainWindow, QProgressBar *progressBar = m_mainWindow->progressBar();
new ProgressEvent(this, progress)); if (progressBar) {
progressBar->setValue(progress);
}
//QApplication::postEvent(m_mainWindow,
// new ProgressEvent(this, progress));
} }
} }
@@ -1615,78 +1722,3 @@ bool Worker::jsUpdate() {
bool Worker::dcUpdate() { bool Worker::dcUpdate() {
return m_dcDownloadFirmware->start("/opt/app/tools/atbupdate"); return m_dcDownloadFirmware->start("/opt/app/tools/atbupdate");
} }
void Worker::summary() {
QString summary, first, second, line, tmp;
QVector<QPair<QString, QString>> vec = Utils::installedPackages();
vec.append(Utils::installedTariffFiles(this, m_customerRepository));
vec.append(Utils::installedJsonFiles(this, m_customerRepository));
int max_first = 0, max_second = 0;
for (int i = 0; i < vec.size(); ++i) {
max_first = std::max(max_first, vec[i].first.length());
max_second = std::max(max_second, vec[i].second.length());
}
max_first += 5;
summary = "UPDATE SUMMARY\n\n";
first = QString("%1").arg("start", max_first, QChar(' '));
tmp = QString("%1").arg(start().toString(Qt::ISODate));
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
first = QString("%1").arg("update tool version", max_first, QChar(' '));
tmp = QString("%1 - %2 %3").arg(APP_VERSION).arg(APP_BUILD_DATE).arg(APP_BUILD_TIME);
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
first = QString("%1").arg("machine number", max_first, QChar(' '));
tmp = QString("%1").arg(machineNr());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
first = QString("%1").arg("customer number", max_first, QChar(' '));
tmp = QString("%1").arg(customerNr());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
first = QString("%1").arg("zone number", max_first, QChar(' '));
tmp = QString("%1").arg(zoneNr());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
if (m_mainWindow) {
tmp = m_mainWindow->targetDcVersion();
if (!tmp.isEmpty()) {
first = QString("%1").arg("target device controller", max_first, QChar(' '));
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
}
first = QString("%1").arg("apism", max_first, QChar(' '));
tmp = QString("%1").arg(apismVersion());
second = QString("%1").arg(tmp, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
for (int i = 0; i < vec.size(); ++i) {
first = QString("%1").arg(vec[i].first, max_first, QChar(' '));
second = QString("%1").arg(vec[i].second, -max_second, QChar(' '));
line = first + ": " + second;
summary += line + "\n";
}
emit showSummary(summary);
emit enableExit();
}

View File

@@ -13,6 +13,7 @@
#include <QThread> #include <QThread>
#include <QByteArray> #include <QByteArray>
#include <QScopedPointer> #include <QScopedPointer>
#include <QFileSystemWatcher>
#include <optional> #include <optional>
#include <initializer_list> #include <initializer_list>
@@ -178,7 +179,7 @@ class Worker : public QThread{
QString const m_pluginVersionTcpZvt; QString const m_pluginVersionTcpZvt;
int m_ismasUpdateRequests; int m_ismasUpdateRequests;
QTimer m_waitForNewUpdates; QTimer m_summaryTimer;
QStringList m_filesToUpdate; QStringList m_filesToUpdate;
QStringList m_filesToDownload; QStringList m_filesToDownload;
@@ -230,6 +231,7 @@ class Worker : public QThread{
int sendUpdateSucceededAndActivated(); int sendUpdateSucceededAndActivated();
int sendFinalResult(); int sendFinalResult();
public:
struct UpdateProcessRunning { struct UpdateProcessRunning {
Worker *m_worker; Worker *m_worker;
@@ -394,6 +396,14 @@ protected:
virtual void run(); virtual void run();
public: public:
UPDATE_STEP lastFailedUpdateStep() const {
return m_lastFailedUpdateStep;
}
void setLastFailedUpdateStep(UPDATE_STEP step) {
m_lastFailedUpdateStep = step;
}
QDebug CONSOLE(QStringList const &lst = QStringList()) { QDebug CONSOLE(QStringList const &lst = QStringList()) {
m_debugMsg = lst; m_debugMsg = lst;
return QDebug(QtMsgType::QtInfoMsg); return QDebug(QtMsgType::QtInfoMsg);
@@ -453,6 +463,8 @@ public:
void setHW(hwinf *hw) { m_hw = hw; } void setHW(hwinf *hw) { m_hw = hw; }
hwinf *getHW() { return m_hw; } hwinf *getHW() { return m_hw; }
QString customerRepository() { return m_customerRepository; }
IsmasClient &getIsmasClient() { return m_ismasClient; } IsmasClient &getIsmasClient() { return m_ismasClient; }
IsmasClient const &getIsmasClient() const { return m_ismasClient; } IsmasClient const &getIsmasClient() const { return m_ismasClient; }
@@ -473,7 +485,6 @@ public:
bool jsUpdate(); bool jsUpdate();
bool dcUpdate(); bool dcUpdate();
void summary();
QDateTime start() { return m_start; } QDateTime start() { return m_start; }
QByteArray standardOutput() const { return m_standardOutput; } QByteArray standardOutput() const { return m_standardOutput; }
@@ -481,6 +492,8 @@ public:
WorkList const &workList() const { return m_workList; } WorkList const &workList() const { return m_workList; }
WorkList &workList() { return m_workList; } WorkList &workList() { return m_workList; }
QTimer *summaryTimer() { return &m_summaryTimer; }
signals: signals:
void appendText(QString, QString suffix = ""); void appendText(QString, QString suffix = "");
void insertText(QString); void insertText(QString);
@@ -507,6 +520,7 @@ signals:
void showDownloadDCJsonFilesStatus(QString); void showDownloadDCJsonFilesStatus(QString);
void showSyncCustRepoStatus(QString); void showSyncCustRepoStatus(QString);
void showUpdateDCFirmware(QString); void showUpdateDCFirmware(QString);
void summary();
void showSummary(QString); void showSummary(QString);
void setDcDownloadProgress(int); void setDcDownloadProgress(int);
@@ -518,6 +532,7 @@ private slots:
bool syncCustomerRepositoryAndFS(); bool syncCustomerRepositoryAndFS();
// bool sendIsmasLastVersionNotification(int progress); // bool sendIsmasLastVersionNotification(int progress);
bool saveLogFile(); bool saveLogFile();
void onFileChanged(QString const&);
public slots: public slots:
void readyReadStandardOutput(); void readyReadStandardOutput();
@@ -531,6 +546,9 @@ private:
QDateTime m_start; QDateTime m_start;
QByteArray m_standardOutput; QByteArray m_standardOutput;
QFileSystemWatcher m_fileWatcher;
QFile m_updateLog;
QFile m_updateLogBackup;
static const QMap<UPDATE_STEP, const char*> smap; static const QMap<UPDATE_STEP, const char*> smap;

View File

@@ -0,0 +1,69 @@
#ifndef LOG_LINE_ENTRY_H_INCLUDED
#define LOG_LINE_ENTRY_H_INCLUDED
#include <cstring>
#include <algorithm>
struct LogLineEntry {
char receiver; // 1 receiver can be: ISMAS
char reason[5]; // 6 SW_UP
char timestamp[19]; // 25 ISO-format: 1900-xx-xxT00:00:00
char eventId; // 26
char event[5]; // 31
/*
Note:
! After U0002 immer ein CMD_SENDVERSION
! Only U0002 and U0003 finish the Update process.
! U0001: Update finished but not activated
! U0002: Update finished and activated
! U0003: Update finished but FAILed.
*/
// #define _ISMAS_DONE "U0001" // 100%, Check: Resultcode: 0
// #define _ISMAS_SET_WAIT_OK "U0002" // empty WAIT-button (""), ResultCode: 0
// #define _ISMAS_NO_UPDATE_NECESSARY "M0100" // empty WAIT-button (""), ResultCode: 0
// #define _ISMAS_FAILURE "U0003" // FAIL
// #define _ISMAS_CONTINUE "U0010" // %-values: Update laeuft, Resultcodes entsprechend laufender Schritt
// #define _ISMAS_RESET_WAIT "ISMAS" // reset WAIT-button to "WAIT"
// #define _ISMAS_TEST_TRIGGER "U0099" // check the WAIT-button
char eventState; // 32
char percent; // 33 percent in progressbar of update-tool
char resultCode; // 34
char step[40]; // 74 step executed
char stepResult[40];// 114 result for step
char version[13]; // 127
char dummy; // 128
};
inline static LogLineEntry initLogLineEntry(
char const receiver,
char const timestamp[19],
char const event[5],
char const eventState,
char const percent,
char const resultCode,
char const step[40],
char const stepResult[40],
char const eventId = 0,
char const reason[5] = "SW_UP",
char const version[14] = "") {
LogLineEntry e;
memset(&e, 0, sizeof(e));
e.receiver = receiver;
std::memcpy(e.reason, reason, std::min(sizeof(e.reason), strlen(reason)));
std::memcpy(e.timestamp, timestamp, std::min(sizeof(e.timestamp), strlen(timestamp)));
e.eventId = eventId;
std::memcpy(e.event, event, std::min(sizeof(e.event), strlen(event)));
e.eventState = eventState;
e.percent = percent;
e.resultCode = resultCode;
std::memcpy(e.step, step, std::min(sizeof(e.step), strlen(step)));
std::memcpy(e.stepResult, stepResult, std::min(sizeof(e.stepResult), strlen(stepResult)));
std::memcpy(e.version, version, std::min(sizeof(e.version), strlen(version)));
e.dummy = '\0';
return e;
}
#endif // LOG_LINE_ENTRY_H_INCLUDED

View File

@@ -2,14 +2,22 @@
#define UTILS_INTERNAL_H_INCLUDED #define UTILS_INTERNAL_H_INCLUDED
#include <QString> #include <QString>
#include <QSettings>
#include <memory>
namespace internal { namespace internal {
static constexpr const char *UPDATE_NOT_NECESSARY{"not necessary"}; static constexpr const char *UPDATE_NOT_NECESSARY{"not necessary"};
static constexpr const char *UPDATE_NOT_REQUESTED{"not requested"}; static constexpr const char *UPDATE_NOT_REQUESTED{"not requested"};
static constexpr const char *UPDATE_INITIAL{"initial update"};
static constexpr const char *UPDATE_REQUESTED{"requested"}; static constexpr const char *UPDATE_REQUESTED{"requested"};
static constexpr const char *NO_CUSTOMER_REPOSITORY{"no customer repository"}; static constexpr const char *NO_CUSTOMER_REPOSITORY{"no customer repository"};
static constexpr const int NO_CUSTOMER_REPOSITORY_CODE{-8};
static constexpr const char *NO_ETC_CUSTOMER_REPOSITORY{"no etc/ in customer repository"};
static constexpr const int NO_ETC_CUSTOMER_REPOSITORY_CODE{-9};
static constexpr const char *NO_OPT_CUSTOMER_REPOSITORY{"no opt/ in customer repository"};
static constexpr const int NO_OPT_CUSTOMER_REPOSITORY_CODE{-10};
static constexpr const char *ISMAS_CONNECTED{"connected"}; static constexpr const char *ISMAS_CONNECTED{"connected"};
static constexpr const char *ISMAS_DISCONNECTED{"disconnected"}; static constexpr const char *ISMAS_DISCONNECTED{"disconnected"};
@@ -17,6 +25,12 @@ namespace internal {
static constexpr const char *ISMAS_NOT_CONNECTED{"not connected"}; static constexpr const char *ISMAS_NOT_CONNECTED{"not connected"};
static constexpr const char *ISMAS_CONNECTION_IN_PROGRESS{"connecting"}; static constexpr const char *ISMAS_CONNECTION_IN_PROGRESS{"connecting"};
static constexpr const char *BROKER_CONNECTED{"connected"};
static constexpr const char *BROKER_DISCONNECTED{"disconnected"};
static constexpr const char *BROKER_DISCONNECTING{"disconnecting"};
static constexpr const char *BROKER_NOT_CONNECTED{"not connected"};
static constexpr const char *BROKER_CONNECTION_IN_PROGRESS{"connecting"};
static constexpr const int GIT_CHECKOUT_ERROR_CODE{-2}; static constexpr const int GIT_CHECKOUT_ERROR_CODE{-2};
static constexpr const int GIT_PULL_ERROR_CODE{-4}; static constexpr const int GIT_PULL_ERROR_CODE{-4};
static constexpr const int GIT_NOT_NECESSARY_CODE{1}; static constexpr const int GIT_NOT_NECESSARY_CODE{1};
@@ -57,13 +71,19 @@ namespace internal {
static constexpr const int PERCENT_UPDATE_DC{80}; static constexpr const int PERCENT_UPDATE_DC{80};
static constexpr const int PERCENT_SHOW_FINAL_STATUS{90}; static constexpr const int PERCENT_SHOW_FINAL_STATUS{90};
static constexpr const char *DEFAULT_INI_DIR{"/etc/tools/atbupdate/"};
static constexpr const char *DEFAULT_INSTALL_DIR{"/opt/app/tools/atbupdate/"};
int read1stLineOfFile(QString fileName); int read1stLineOfFile(QString fileName);
QString customerRepoRoot(); QString customerRepoRoot();
QString customerRepoDir(); QString customerRepoDir();
QString customerRepoDcDir();
QString customerRepoDirName(); QString customerRepoDirName();
QString repositoryUrl(); QString repositoryUrl();
QString branchName(); QString branchName();
bool customerRepoExists(); bool customerRepoExists();
std::unique_ptr<QSettings> readSettings(QString const &optionalDirName = "");
std::unique_ptr<QString> dcCandidateToInstall(QString const &dcDirectory = "");
} }
#endif // UTILS_INTERNAL_H_INCLUDED #endif // UTILS_INTERNAL_H_INCLUDED

View File

@@ -1,8 +1,12 @@
#include "utils.h" #include "utils_internal.h"
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
#include <QTextStream> #include <QTextStream>
#include <QSettings>
#include <QDebug>
#include <QCryptographicHash>
#include <QFileInfoList>
namespace internal { namespace internal {
@@ -35,6 +39,11 @@ QString customerRepoDir() {
return !n.isEmpty() ? QDir::cleanPath(r + QDir::separator() + n) : ""; return !n.isEmpty() ? QDir::cleanPath(r + QDir::separator() + n) : "";
} }
QString customerRepoDcDir() {
QString const &r = customerRepoDir();
return QDir::cleanPath(r + QDir::separator() + "etc/dc/");
}
bool customerRepoExists() { bool customerRepoExists() {
QString const repoDir{customerRepoDir()}; QString const repoDir{customerRepoDir()};
return !repoDir.isEmpty() ? QDir(repoDir).exists() : false; return !repoDir.isEmpty() ? QDir(repoDir).exists() : false;
@@ -52,4 +61,107 @@ QString branchName() {
return ""; return "";
} }
std::unique_ptr<QSettings> readSettings(QString const &optionalDirName) {
std::unique_ptr<QSettings> settings{std::make_unique<QSettings>()};
//QString const fileName{settings->applicationName() + ".ini"};
QString const fileName{"ATBUpdateTool.ini"};
QDir d;
if (!optionalDirName.isEmpty()) {
d = QDir{optionalDirName};
if (d.exists()) { // try to find ini-file under optionalDirname
QFileInfo fi{d, optionalDirName};
if (fi.exists()) {
settings.reset(new QSettings(fi.absoluteFilePath(), QSettings::IniFormat));
return settings;
} else {
qCritical() << fi.absoluteFilePath() << "not found."
<< "Try" << internal::DEFAULT_INI_DIR;
}
} else {
qCritical() << optionalDirName << "not found."
<< "Try" << internal::DEFAULT_INSTALL_DIR;
}
}
d = internal::DEFAULT_INI_DIR;
if (d.exists()) { // try to find ini-file under /etc/tools/atbupdate
QFileInfo fi{d, fileName};
if (fi.exists()) {
settings.reset(new QSettings(fi.absoluteFilePath(), QSettings::IniFormat));
return settings;
} else {
qCritical() << fi.absoluteFilePath() << "not found."
<< "Try" << internal::DEFAULT_INSTALL_DIR;
}
} else {
qCritical() << internal::DEFAULT_INI_DIR << "not found."
<< "Try" << internal::DEFAULT_INSTALL_DIR;
}
d = QDir{internal::DEFAULT_INSTALL_DIR};
if (d.exists()) { // try to find ini-file under /opt/app/tools/atbupdate
QFileInfo fi{d, fileName};
if (fi.exists()) {
settings.reset(new QSettings(fi.absoluteFilePath(), QSettings::IniFormat));
return settings;
} else {
qCritical() << fi.absoluteFilePath() << "not found.";
}
} else {
qCritical() << internal::DEFAULT_INSTALL_DIR << "not found.";
}
return settings;
}
std::unique_ptr<QString> dcCandidateToInstall(QString const &dcDirectory) {
std::unique_ptr<QString> dcCandidate{nullptr};
qCritical() << __func__ << __LINE__ << dcDirectory;
QDir dcDir{dcDirectory.isEmpty() ? customerRepoDcDir() : dcDirectory};
if (dcDir.exists()) {
QFileInfoList fileInfoList =
dcDir.entryInfoList(QStringList("*.bin"),
QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
QFileInfo dc2cbin{dcDir.absoluteFilePath("dc2c.bin")};
if (dc2cbin.exists()) {
QCryptographicHash md5gen(QCryptographicHash::Md5);
QByteArray ba_dc2cbin{};
{
QFile f{dc2cbin.absoluteFilePath()};
if (f.open(QIODevice::ReadOnly)) {
md5gen.addData(f.readAll());
ba_dc2cbin = md5gen.result();
md5gen.reset();
}
}
if (ba_dc2cbin.size() > 0) {
QFileInfoList::const_iterator it;
for (it = fileInfoList.cbegin(); it != fileInfoList.cend(); ++it) {
if (it->absoluteFilePath() != dc2cbin.absoluteFilePath()) {
QFile f{it->absoluteFilePath()};
if (f.open(QIODevice::ReadOnly)) {
md5gen.addData(f.readAll());
if (ba_dc2cbin == md5gen.result()) {
dcCandidate.reset(new QString(f.fileName()));
break;
}
md5gen.reset();
}
}
}
}
}
}
return dcCandidate;
}
} // namespace internal } // namespace internal

File diff suppressed because it is too large Load Diff