Compare commits

..

9 Commits

Author SHA1 Message Date
7bfb7f5a3b save for christmas 2024-12-20 13:01:34 +01:00
2ec7b61682 Remove any reference to device controller as downloading jsons/dc-firmware
will be done by ATBDownloadDCJsonFiles and ATBDownloadDCFirmware binaries.
2024-12-06 12:30:54 +01:00
75b0b83174 Update::updateBinary():
begin with starting "/opt/app/tools/atbupdate/ATBDownloadDCFirmware".
2024-12-06 11:51:06 +01:00
79e2405738 Minor: remove unused code. 2024-12-06 11:50:25 +01:00
0ebf8b095a getCommandResult():
reset result if necessary (for instance for showing current result
	in GUI.
2024-12-06 11:48:21 +01:00
11524b8389 read dc-verion directly from binary file 2024-11-28 12:53:44 +01:00
6663866743 Mior: remove debugs 2024-11-28 12:52:50 +01:00
12aa9a734a init some vars to defaults 2024-11-28 12:52:14 +01:00
9b6f5db8fe start with downloading dc: parsing command arguments. started to implement the acrual download 2024-11-27 15:54:42 +01:00
23 changed files with 529 additions and 1144 deletions

View File

@@ -1,6 +1,7 @@
QT += core serialport QT += core gui
QT += widgets serialport network
TARGET = ATBUpdateDC TARGET = ATBDownloadDCFirmware
VERSION="0.1.0" VERSION="0.1.0"
win32 { win32 {
@@ -76,21 +77,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 \
../common/src/System.cpp \ dc_download.cpp \
../common/src/utils_internal.cpp \ ../common/src/System.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 \
../common/include/System.h \ dc_download.h \
../common/include/utils_internal.h \ ../common/include/System.h
../common/include/command.h
OTHER_FILES += \ OTHER_FILES += \
@@ -98,6 +99,9 @@ OTHER_FILES += \
../ATBUpdateTool.ini ../ATBUpdateTool.ini
FORMS += \
mainwindow.ui
########################################################################################## ##########################################################################################
# for running program on target through QtCreator # for running program on target through QtCreator
contains( CONFIG, PTU5 ) { contains( CONFIG, PTU5 ) {

View File

@@ -1,21 +1,22 @@
#include <QtGlobal> #include <QtGlobal>
#include <QCoreApplication> #include <QCoreApplication>
#include <QApplication>
#include <QByteArray> #include <QByteArray>
#include <QProcess> #include <QProcess>
#include <QCommandLineParser>
#include <QStandardPaths> #include <QStandardPaths>
#include <QSettings> #include <QSettings>
#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>
@@ -53,18 +54,15 @@ int main(int argc, char **argv) {
openlog("DC", LOG_PERROR | LOG_CONS, LOG_USER); openlog("DC", LOG_PERROR | LOG_CONS, LOG_USER);
QCoreApplication a(argc, argv); QApplication a(argc, argv);
QCoreApplication::setOrganizationName("ATB Automatentechnik Baumann GmBH"); QApplication::setApplicationName("ATBDownloadDCFirmware");
QCoreApplication::setApplicationName("ATBUpdateDC"); QApplication::setApplicationVersion(APP_VERSION);
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);
} }
/*
CommandLineParser parser; CommandLineParser parser;
parser.process(a); parser.process(a);
parser.readSettings(); parser.readSettings();
@@ -126,66 +124,60 @@ int main(int argc, char **argv) {
printf(APP_EXTENDED_VERSION"\n"); printf(APP_EXTENDED_VERSION"\n");
return 0; return 0;
} }
*/
bool debug = false; QString const &customerRepo
bool noaction = true; = QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr));
QString libDir;
QString libca;
QString workingDir;
std::unique_ptr<QSettings> settings = internal::readSettings();
if (settings) {
settings->beginGroup("DIRECTORIES");
workingDir = settings->value("workingdir", "/tmp").toString();
libDir = settings->value("plugin-directory", "/usr/lib/").toString();
settings->endGroup();
settings->beginGroup("FLAGS");
debug = settings->value("debug", false).toBool();
settings->endGroup();
settings->beginGroup("PLUGINS");
libca = libDir + settings->value("plugin-name", "libCAslave.so").toString();
settings->endGroup();
}
// etc/dc: located under mount-path
std::optional<QString> mountPath = System::checkForUSBStick(psaDcDir);
QFileInfo fi; QFileInfo fi;
if (mountPath.has_value()) {
fi.setFile(mountPath.value(), System::getDCFileOnUsbStick(mountPath.value()));
} else
if ((mountPath = System::checkForSDCard(psaDcDir)).has_value()) {
fi.setFile(mountPath.value(), System::getDCFileOnSDCard(mountPath.value()));
} else {
qInfo() << "using customer repository" << customerRepo;
// ------------------- single command line argument is DC-firmware binary file ----------------- QDir dir(QDir::cleanPath(customerRepo + QDir::separator() + "etc/dc"));
QStringList args = a.arguments(); if (dir.exists()) {
if (args.size() != 2) { fi.setFile(dir, dir.absoluteFilePath("dc2c.bin"));
qCritical() << "ERROR: missing parameter <dc-firmware>"; } else {
exit(1); qCritical() << "DIRECTORY" << dir << "DOES NOT EXIST";
return -1;
}
} }
qCritical() << "------------------------------------------------------"; qInfo() << "downloading dc-firmware .." << fi.absoluteFilePath();
qCritical() << "main: argument dc-firmware: " << args.at(1); qInfo() << "dc-firmware size (bytes) ." << fi.size();
qCritical() << "------------------------------------------------------"; if (readDCVersion) {
qInfo() << "dc-version ..............." << Update::dcVersion(fi.absoluteFilePath());
fi.setFile(args.at(1));
if (!fi.isFile()) {
qCritical() << "ERROR: parameter " << fi.absoluteFilePath() << " is not a file";
exit(1);
} }
if (!fi.isReadable()) { QThread::currentThread()->setObjectName("main thread");
qCritical() << "ERROR: parameter " << fi.absoluteFilePath() << " is not readable"; // qInfo() << "Main thread" << QThread::currentThreadId();
exit(1);
}
qCritical() << "------------------------------------------------------"; Update update(customerRepo,
qCritical() << "uploading dc-firmware" << fi.absoluteFilePath(); QString::number(customerNr),
qCritical() << "dc-firmware size (bytes)" << fi.size(); branchName,
qCritical() << "dc-version" << Update::dcVersion(fi.absoluteFilePath()); plugInDir,
qCritical() << "------------------------------------------------------"; plugInName,
workingDir,
psaDcDir);
Update u(fi.absoluteFilePath(), libca, debug, noaction); update.doUpdate(fi.absoluteFilePath());
u.run();
// 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,7 +1,10 @@
#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

@@ -1,5 +1,5 @@
#include "update.h" #include "update.h"
#include "command.h" #include "process/command.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QFile> #include <QFile>
@@ -24,14 +24,10 @@
#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}
@@ -39,19 +35,25 @@ static const QMap<QString, int> baudrateMap = {
QPluginLoader Update::pluginLoader; QPluginLoader Update::pluginLoader;
hwinf *Update::loadDCPlugin(QString const &libCA /* absolute file path */) { hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
hwinf *hw = nullptr; hwinf *hw = nullptr;
QFileInfo libCAInfo(libCA); if (plugInDir.exists()) {
if (libCAInfo.exists()) { QString pluginLibName(fname);
pluginLoader.setFileName(libCA); pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
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 file name:" << pluginLoader.fileName(); qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
if (!pluginLoader.isLoaded()) { if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
@@ -67,10 +69,14 @@ hwinf *Update::loadDCPlugin(QString const &libCA /* absolute file path */) {
return nullptr; return nullptr;
} }
} else { } else {
qCritical() << libCAInfo.absoluteFilePath() << "does not exist"; qCritical() << pluginLibName << "does not exist";
return nullptr;
}
} else {
qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist";
return nullptr; return nullptr;
} }
return hw; return hw;
} }
@@ -101,12 +107,40 @@ QString Update::dcVersion(QString const &dcBinFile) {
} }
class hwapi; class hwapi;
Update::Update(QString const &dcFileName, QString const &libCA, bool debug, bool noaction) Update::Update(QString customerRepository,
: m_dcFileName(dcFileName) QString customerNrStr,
, m_hw(loadDCPlugin(libCA)) QString branchName,
, m_sys_areDCdataValid(false) QString plugInDir,
, m_debug(debug) QString pluginName,
, m_noaction(noaction) { QString workingDir,
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() {
@@ -132,15 +166,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);
DownloadResult res = DownloadResult::OK; QThread::msleep(100);
if (!m_debug) {
m_hw->bl_sendAddress(bNum);
QThread::msleep(10); //from 100ms to 20ms // TODO
//################################################################################### // 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) {
@@ -155,7 +189,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;
} }
@@ -175,25 +209,25 @@ Update::sendNextDataBlock(QByteArray const &binary, int bNum) const {
QString s = nextTimePoint(); QString s = nextTimePoint();
s += " sending block "; s += " sending block ";
s += QString("%1/%2 ...done <DC-PROGRESS>").arg(bNum).arg(m_totalBlocks); s += QString("%1/%2 ...done <PROGRESS>").arg(bNum).arg(m_totalBlocks);
s += QString::number(ceil(((bNum * 100.0) / (double)m_totalBlocks))); s += QString::number(ceil(((bNum * 100.0) / (double)m_totalBlocks)));
qInfo() << s.toUtf8().constData(); qInfo() << s.toUtf8().constData();
QThread::msleep(20); //reduce from 200 to 50 ms QThread::msleep(200);
//############################################################################ 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);
DownloadResult res = DownloadResult::OK; // TODO
// DownloadResult const res = sendStatus(m_hw->bl_wasSendingDataOK());
if (!m_debug) { DownloadResult const res = DownloadResult::OK;
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) {
@@ -215,13 +249,15 @@ Update::sendNextDataBlock(QByteArray const &binary, int bNum) const {
} }
bool Update::startBootloader() const { bool Update::startBootloader() const {
qDebug() << "starting bootloader..."; QThread::msleep(1000);
qInfo() << nextTimePoint().toUtf8().constData() << "starting bootloader ...done";
return true;
if (!m_debug) { #if 0
int nTry = 10; int nTry = 5;
while (--nTry >= 0) { while (--nTry >= 0) {
m_hw->bl_startBL(); m_hw->bl_startBL();
QThread::msleep(1000); QThread::msleep(5000);
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";
@@ -229,27 +265,24 @@ 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;
} else { #endif
QThread::msleep(1000);
qInfo() << "starting bootloader...OK";
}
return true;
} }
bool Update::stopBootloader() const { bool Update::stopBootloader() const {
qDebug() << "stopping bootloader..."; QThread::msleep(1000);
qInfo() << nextTimePoint().toUtf8().constData() << "stopping bootloader ...done";
return true;
if (!m_debug) { #if 0
qDebug() << "stopping bootloader...";
int nTry = 5; int nTry = 5;
while (--nTry >= 0) { while (--nTry >= 0) {
m_hw->bl_stopBL(); m_hw->bl_stopBL();
QThread::msleep(1000); QThread::msleep(500);
if (!m_hw->bl_isUp()) { if (!m_hw->bl_isUp()) {
qInfo() << "stopping bootloader...OK"; qInfo() << "stopping bootloader...OK";
return true; return true;
@@ -257,21 +290,12 @@ 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 {
qInfo() << nextTimePoint().toUtf8().constData() << "resetting device controller"; // TODO
// 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);
@@ -289,12 +313,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()
@@ -384,24 +408,19 @@ 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.
*/ */
int Update::run() { bool Update::doUpdate(QString const &dcFileName) {
if (!m_hw) { qInfo() << "<DC-VERSION>" << Update::dcVersion(dcFileName);
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin loaded ???";
return -(int)Result::PLUGIN_LOAD_ERROR;
}
m_start = QDateTime::currentDateTime(); m_dcFileName = dcFileName;
if (m_debug) { //QString const &fToWorkOn = usbStickDetected ? QDir::cleanPath(it->trimmed())
qInfo() << "start dc-update for" << m_dcFileName << "at" << m_start.toString(Qt::ISODate); //: QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
qInfo() << "<DC-VERSION>" << Update::dcVersion(m_dcFileName);
}
m_hw->dc_autoRequest(false); //if (!m_hw) {
// qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
qInfo() << "DC auto request OFF"; // << "ERROR!!! m_hw == nullptr";
// return false;
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) {
@@ -414,14 +433,15 @@ int Update::run() {
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;
} }
@@ -450,26 +470,243 @@ int Update::run() {
} }
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>";
stopBootloader(); return true;
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,21 +17,26 @@
#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;
bool m_sys_areDCdataValid{}; char const *m_serialInterface;
bool m_debug{false}; char const *m_baudrate;
bool m_noaction; QString m_customerRepository;
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;
@@ -43,16 +48,27 @@ class Update : public QObject {
public: public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP}; enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
enum class Result {SUCCESS=0, PLUGIN_LOAD_ERROR}; enum class FileTypeJson {CONFIG=1, DEVICE=2, CASH=3, SERIAL=4, TIME=5, PRINTER=6};
static hwinf *loadDCPlugin(QString const &libCA = "/usr/lib/libCAslave.so"); static hwinf *loadDCPlugin(QDir const &plugInDir, QString const &fn);
static bool unloadDCPlugin(); static bool unloadDCPlugin();
static QStringList split(QString line, QChar sep = ','); static QStringList split(QString line, QChar sep = ',');
explicit Update(QString const &dcBinFile, QString const &libCA, bool debug, bool noaction); explicit Update(QString customerRepository,
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;
int run(); bool doUpdate(QString const &dcFileName);
static QString dcVersion(QString const &dcBinFile); static QString dcVersion(QString const &dcBinFile);
private: private:

View File

@@ -147,11 +147,7 @@ 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.
# 1.5.7 : Add support for dynamic portrait / landscape. VERSION="1.5.6"
# 1.5.8 : Use EVENT_ID=<pid of update-tool> for CMD_EVENT.
# 1.5.9 : Removed restart of Apism if ISMAS unreachable.
# 1,6,9 : Add separate tool ATBUpdateDC for manual updating DC-FW
VERSION="1.6.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

View File

@@ -6,9 +6,7 @@
#include <QFile> #include <QFile>
CommandLineParser::CommandLineParser() CommandLineParser::CommandLineParser()
: m_repositoryUrl("gitea@ptu-config.atb-comm.de:ATB/") : m_repositoryUrl("https://git.mimbach49.de/GerhardHoffmann")
, m_sshKeyFile("/opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig")
, m_sshOptionStrictHostKeyChecking("false")
, m_plugInDir("/usr/lib/") , m_plugInDir("/usr/lib/")
, m_plugInName("libCAslave.so") , m_plugInName("libCAslave.so")
, m_workingDir("/opt/app/tools/atbupdate/") , m_workingDir("/opt/app/tools/atbupdate/")
@@ -22,36 +20,27 @@ CommandLineParser::CommandLineParser()
, m_alwaysDownloadDC("false") , m_alwaysDownloadDC("false")
, m_repositoryUrlOption( , m_repositoryUrlOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "repository-url", QStringList() << "repository-url" << "repository-url",
QCoreApplication::translate("main", "Where to find a customer repository."), QCoreApplication::translate("main", "Where to find a customer repository."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_sshKeyFileOption(
QCommandLineOption(
QStringList() << "sshKeyFile",
QCoreApplication::translate("main", "Used ssh key."),
QCoreApplication::translate("main", "file")))
, m_sshOptionStrictHostKeyCheckingOption(
QCommandLineOption(
QStringList() << "sshStrictHostKeyChecking",
QCoreApplication::translate("main", "Enable ssh strict host key checking")))
, m_iniFileDirectoryOption( , m_iniFileDirectoryOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "ini-directory", QStringList() << "ini-directory" << "ini-directory",
QCoreApplication::translate("main", "Where to find an ini-file."), QCoreApplication::translate("main", "Where to find an ini-file."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_iniFileNameOption( , m_iniFileNameOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "ini-filename", QStringList() << "ini-filename" << "ini-filename",
QCoreApplication::translate("main", "Name of ini-file."), QCoreApplication::translate("main", "Name of ini-file."),
QCoreApplication::translate("main", "file"))) QCoreApplication::translate("main", "file")))
, m_pluginDirectoryOption( , m_pluginDirectoryOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "plugin-directory", QStringList() << "plugin-directory" << "plugin-directory",
QCoreApplication::translate("main", "Where to find dc-plugin."), QCoreApplication::translate("main", "Where to find dc-plugin."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_pluginNameOption( , m_pluginNameOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "plugin-name", QStringList() << "plugin-name" << "plugin-name",
QCoreApplication::translate("main", "Name of dc-plugin."), QCoreApplication::translate("main", "Name of dc-plugin."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_noDownloadOption( , m_noDownloadOption(
@@ -68,17 +57,17 @@ CommandLineParser::CommandLineParser()
QCoreApplication::translate("main", "Always download the dc-bin-file to DC)."))) QCoreApplication::translate("main", "Always download the dc-bin-file to DC).")))
, m_workingDirectoryOption( , m_workingDirectoryOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "working-directory", QStringList() << "working-directory" << "working-directory",
QCoreApplication::translate("main", "working directory of update-script."), QCoreApplication::translate("main", "working directory of update-script."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_psaConfigDirectoryOption( , m_psaConfigDirectoryOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "psa-config-directory", QStringList() << "psa-config-directory" << "psa-config-directory",
QCoreApplication::translate("main", "config directory of json-files sent to dc."), QCoreApplication::translate("main", "config directory of json-files sent to dc."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_psaTariffDirectoryOption( , m_psaTariffDirectoryOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "psa-tariff-directory", QStringList() << "psa-tariff-directory" << "psa-tariff-directory",
QCoreApplication::translate("main", "tariff directory of tariff-json-files."), QCoreApplication::translate("main", "tariff directory of tariff-json-files."),
QCoreApplication::translate("main", "directory"))) QCoreApplication::translate("main", "directory")))
, m_dryRunOption( , m_dryRunOption(
@@ -105,8 +94,8 @@ CommandLineParser::CommandLineParser()
, m_readDCVersionOption( , m_readDCVersionOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "D" << "read-dc-version", QStringList() << "D" << "read-dc-version",
QCoreApplication::translate("main", "Show version of device controller."))) QCoreApplication::translate("main", "Show version of device controller."),
{ QCoreApplication::translate("main", "Show version of device controller."))) {
configure(); configure();
} }
@@ -115,15 +104,9 @@ void CommandLineParser::configure() {
m_parser.addHelpOption(); m_parser.addHelpOption();
m_parser.addVersionOption(); m_parser.addVersionOption();
m_repositoryUrlOption.setDefaultValue("gitea@ptu-config.atb-comm.de:ATB/"); m_repositoryUrlOption.setDefaultValue("https://git.mimbach49.de/GerhardHoffmann");
m_parser.addOption(m_repositoryUrlOption); m_parser.addOption(m_repositoryUrlOption);
m_sshKeyFileOption.setDefaultValue("/opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig");
m_parser.addOption(m_sshKeyFileOption);
m_sshOptionStrictHostKeyCheckingOption.setDefaultValue("");
m_parser.addOption(m_sshOptionStrictHostKeyCheckingOption);
m_iniFileDirectoryOption.setDefaultValue(QCoreApplication::applicationDirPath()); m_iniFileDirectoryOption.setDefaultValue(QCoreApplication::applicationDirPath());
m_parser.addOption(m_iniFileDirectoryOption); m_parser.addOption(m_iniFileDirectoryOption);
@@ -194,12 +177,6 @@ void CommandLineParser::readSettings() {
if (key.contains("repository-url")) { if (key.contains("repository-url")) {
m_repositoryUrl = v.toString(); m_repositoryUrl = v.toString();
} else } else
if (key.contains("sshKeyFile")) {
m_sshKeyFile = v.toString();
} else
if (key.contains("sshOptionStrictHostKeyChecking")) {
m_sshOptionStrictHostKeyChecking = (v.toBool() ? "true" : "false");
} else
if (key.contains("plugin-directory")) { if (key.contains("plugin-directory")) {
m_plugInDir = v.toString(); m_plugInDir = v.toString();
} else } else
@@ -260,21 +237,6 @@ QString CommandLineParser::repositoryUrl() {
return m_repositoryUrl; return m_repositoryUrl;
} }
QString CommandLineParser::sshKeyFile() {
if (m_parser.isSet(m_sshKeyFileOption)) {
m_sshKeyFile = m_parser.value(m_sshKeyFileOption);
}
return m_sshKeyFile;
}
bool CommandLineParser::sshOptionStrictHostKeyChecking()
{
if (m_parser.isSet(m_sshOptionStrictHostKeyCheckingOption)) {
m_sshOptionStrictHostKeyChecking = m_parser.value(m_sshOptionStrictHostKeyCheckingOption);
}
return m_sshOptionStrictHostKeyChecking == "false" ? false : true;
}
QString CommandLineParser::plugInDir() { QString CommandLineParser::plugInDir() {
if (m_parser.isSet(m_pluginDirectoryOption)) { if (m_parser.isSet(m_pluginDirectoryOption)) {
m_plugInDir = m_parser.value(m_pluginDirectoryOption); m_plugInDir = m_parser.value(m_pluginDirectoryOption);

View File

@@ -8,8 +8,6 @@
class CommandLineParser : public QCommandLineParser { class CommandLineParser : public QCommandLineParser {
QString m_repositoryUrl; QString m_repositoryUrl;
QString m_sshKeyFile;
QString m_sshOptionStrictHostKeyChecking;
QString m_plugInDir; QString m_plugInDir;
QString m_plugInName; QString m_plugInName;
QString m_workingDir; QString m_workingDir;
@@ -27,8 +25,6 @@ class CommandLineParser : public QCommandLineParser {
QString m_dcDir{"etc/dc/"}; QString m_dcDir{"etc/dc/"};
QCommandLineOption m_repositoryUrlOption; QCommandLineOption m_repositoryUrlOption;
QCommandLineOption m_sshKeyFileOption;
QCommandLineOption m_sshOptionStrictHostKeyCheckingOption;
QCommandLineOption m_iniFileDirectoryOption; QCommandLineOption m_iniFileDirectoryOption;
QCommandLineOption m_iniFileNameOption; QCommandLineOption m_iniFileNameOption;
QCommandLineOption m_pluginDirectoryOption; QCommandLineOption m_pluginDirectoryOption;
@@ -61,8 +57,6 @@ public:
QString const &iniFileName() const { return m_iniFileName; } QString const &iniFileName() const { return m_iniFileName; }
void readSettings(); void readSettings();
QString repositoryUrl(); QString repositoryUrl();
QString sshKeyFile();
bool sshOptionStrictHostKeyChecking();
QString plugInDir(); QString plugInDir();
QString plugInName(); QString plugInName();
QString workingDir(); QString workingDir();

View File

@@ -400,12 +400,6 @@ std::optional<QString> GitClient::gitPull() {
If remote host keys are changed, then If remote host keys are changed, then
export GIT_SSH_COMMAND="ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig" export GIT_SSH_COMMAND="ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig"
... or ignore host key checking:
export GIT_SSH_COMMAND="ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig -o StrictHostKeyChecking=no"
... or use separate known_hosts file:
export GIT_SSH_COMMAND="ssh -i /mypath/.keys/id_ed25519 -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/opt/app/tools/atbupdate/.keys/known_hosts"
git pull git pull
leads to the following warning/error message: leads to the following warning/error message:

View File

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

View File

@@ -72,31 +72,22 @@ int main(int argc, char *argv[]) {
CommandLineParser parser; CommandLineParser parser;
parser.process(a); parser.process(a);
if (parser.isSet(parser.addHelpOption())) {
parser.showHelp(0);
return 0;
}
parser.readSettings(); parser.readSettings();
QString repositoryUrl = parser.repositoryUrl(); QString repositoryUrl = parser.repositoryUrl();
QString sshKeyFile = parser.sshKeyFile();
bool strictHostKeyChecking = parser.sshOptionStrictHostKeyChecking();
if (repositoryUrl.endsWith('/')) { if (repositoryUrl.endsWith('/')) {
repositoryUrl.chop(1); repositoryUrl.chop(1);
} }
// default for gitSSHCommand QString gitSSHCommand("");
QString gitSSHCommand = "ssh -i " + sshKeyFile;
strictHostKeyChecking ? gitSSHCommand.append(" -o StrictHostKeyChecking=yes")
: gitSSHCommand.append(" -o StrictHostKeyChecking=no");
if (repositoryUrl.contains("ptu-config.atb-comm.de")) {
QByteArray const v = qgetenv("GIT_SSH_COMMAND"); QByteArray const v = qgetenv("GIT_SSH_COMMAND");
if (v.isEmpty()) { if (v.isEmpty()) {
QString sshKeyFile("/opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig");
if (QFileInfo(sshKeyFile).exists()) { if (QFileInfo(sshKeyFile).exists()) {
gitSSHCommand = "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig";
if (!qputenv("GIT_SSH_COMMAND", QByteArray(gitSSHCommand.toStdString().c_str()))) { if (!qputenv("GIT_SSH_COMMAND", QByteArray(gitSSHCommand.toStdString().c_str()))) {
qCritical() << "ERROR: GIT_SSH_COMMAND not put into env. Exiting..."; qCritical() << "ERROR: GIT_SSH_COMMAND not put into env. Exiting...";
return -1; return -1;
@@ -109,6 +100,11 @@ int main(int argc, char *argv[]) {
gitSSHCommand = QString(v.toStdString().c_str()); gitSSHCommand = QString(v.toStdString().c_str());
qCritical() << "WARNING GIT_SSH_COMMAND already set in enviroment:" qCritical() << "WARNING GIT_SSH_COMMAND already set in enviroment:"
<< gitSSHCommand; << gitSSHCommand;
if (gitSSHCommand != "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig") {
qCritical() << "ERROR" << gitSSHCommand << "wrong. Exiting...";
return -1;
}
}
} }
QString plugInDir = parser.plugInDir(); QString plugInDir = parser.plugInDir();
@@ -165,6 +161,7 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} }
QThread::currentThread()->setObjectName("main thread"); QThread::currentThread()->setObjectName("main thread");
qInfo() << "Main thread" << QThread::currentThreadId(); qInfo() << "Main thread" << QThread::currentThreadId();

View File

@@ -14,9 +14,6 @@
#include <QColor> #include <QColor>
#include <QColorDialog> #include <QColorDialog>
#include <QScreen>
MainWindow::MainWindow(Worker *worker, QWidget *parent) MainWindow::MainWindow(Worker *worker, QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@@ -27,7 +24,6 @@ MainWindow::MainWindow(Worker *worker, QWidget *parent)
, m_updateStep(UpdateDcEvent::UpdateStep::NONE) { , m_updateStep(UpdateDcEvent::UpdateStep::NONE) {
ui->setupUi(this); ui->setupUi(this);
checkOrientation();
this->setStatusBar(new QStatusBar(this)); this->setStatusBar(new QStatusBar(this));
QFont f; QFont f;
@@ -131,56 +127,6 @@ MainWindow::~MainWindow() {
delete ui; delete ui;
} }
// ----------------------------- Ui::LAYOUT setting -------------------------------------
void MainWindow::checkOrientation()
{
QScreen *screen = QGuiApplication::primaryScreen();
Qt::ScreenOrientation orientation = screen->orientation();
switch (orientation) {
case Qt::PrimaryOrientation:
this->setLandscapeLayout();
break;
case Qt::LandscapeOrientation:
this->setLandscapeLayout();
break;
case Qt::PortraitOrientation:
this->setPortraitLayout();
break;
case Qt::InvertedLandscapeOrientation:
this->setLandscapeLayout();
break;
case Qt::InvertedPortraitOrientation:
this->setPortraitLayout();
break;
}
this->currentOrientation = orientation;
}
void MainWindow::setPortraitLayout()
{
// Adjust layout for portrait mode (480x800)
this->setFixedSize(480, 800);
ui->centralwidget->setFixedSize(480, 800);
}
void MainWindow::setLandscapeLayout()
{
// Adjust layout for landscape mode (800x480)
this->setFixedSize(800, 480);
ui->centralwidget->setFixedSize(800, 480);
}
void MainWindow::customEvent(QEvent *event) { void MainWindow::customEvent(QEvent *event) {
if (event->type() == ProgressEvent::type()) { if (event->type() == ProgressEvent::type()) {
ProgressEvent *pevent = (ProgressEvent *)event; ProgressEvent *pevent = (ProgressEvent *)event;

View File

@@ -72,12 +72,6 @@ private:
void onShowMessage(QString, QString); void onShowMessage(QString, QString);
Ui::MainWindow *ui; Ui::MainWindow *ui;
void checkOrientation();
void setPortraitLayout();
void setLandscapeLayout();
Qt::ScreenOrientation currentOrientation;
Worker *m_worker; Worker *m_worker;
int const m_width; int const m_width;
QTimer *m_startTimer; QTimer *m_startTimer;

View File

@@ -10,12 +10,6 @@
<height>480</height> <height>480</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>480</width>
<height>480</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<family>Misc Fixed</family> <family>Misc Fixed</family>

View File

@@ -105,7 +105,6 @@ Update::Update(Worker *worker,
char const *serialInterface, char const *serialInterface,
char const *baudrate) char const *baudrate)
: QObject(parent) : QObject(parent)
, m_hw(loadDCPlugin(QDir(plugInDir), pluginName))
, m_worker(worker) , m_worker(worker)
, m_serialInterface(serialInterface) , m_serialInterface(serialInterface)
, m_baudrate(baudrate) , m_baudrate(baudrate)
@@ -116,24 +115,6 @@ Update::Update(Worker *worker,
, m_workingDir(workingDir) , m_workingDir(workingDir)
, m_dryRun(dryRun) , m_dryRun(dryRun)
, m_sys_areDCdataValid(false) { , m_sys_areDCdataValid(false) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin not loaded";
} else {
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() << "ERROR!!! DC DATA NOT VALID -> CA-MASTER-PLUGIN NOT CONNECTED";
break;
}
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_sys_areDCDataValid ..."
<< m_sys_areDCdataValid;
}
} }
Update::~Update() { Update::~Update() {
@@ -151,43 +132,6 @@ void Update::onReportDCDownloadFailure(QString const &errorMsg) {
qCritical() << "msg" << errorMsg; qCritical() << "msg" << errorMsg;
} }
// br is a index into a table, used for historical reasons.
bool Update::openSerial(int br, QString baudrate, QString comPort) const {
if (m_hw) {
qDebug() << "opening serial" << br << baudrate << comPort << "...";
if (m_hw->dc_openSerial(br, baudrate, comPort, 1) == true) { // 1 for connect
Utils::printInfoMsg(
QString("OPENING SERIAL %1").arg(br)
+ " " + baudrate + " " + comPort + "...OK");
// m_hw->dc_autoRequest(true);
// m_hw->dc_autoRequest(false);
// QThread::sleep(1);
Utils::printInfoMsg(QString("IS PORT OPEN %1").arg(m_hw->dc_isPortOpen()));
return true;
}
Utils::printCriticalErrorMsg(
QString("OPENING SERIAL %1").arg(br)
+ " " + baudrate + " " + comPort + "...FAILED");
}
return false;
}
void Update::closeSerial() const {
qInfo() << "CLOSED SERIAL" << m_baudrate << m_serialInterface;
if (m_hw) {
m_hw->dc_closeSerial();
}
}
bool Update::isSerialOpen() const {
return m_hw ? m_hw->dc_isPortOpen() : false;
}
/* /*
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -282,95 +226,13 @@ bool Update::updateBinary(QString const &fileToSendToDC) {
qInfo() << "updating dc-binary" << fileToSendToDC << "..."; qInfo() << "updating dc-binary" << fileToSendToDC << "...";
return false; return false;
#if 0
QFile fn(fileToSendToDC);
if (!fn.exists()) {
// output via CONSOLE() etc
return false;
}
bool bl_isUp = false;
if (m_hw->bl_completeStart()) {
int cnt = 5;
while (--cnt > 0) {
if (m_hw->bl_isUp()) {
bl_isUp = true;
break;
}
}
}
if (!bl_isUp) {
return false;
}
if (!m_hw->bl_storeFirmware(fileToSendToDC)) {
m_hw->bl_stopBL();
return false;
}
uint16_t const nrOfFirmwareBlocks = m_hw->bl_getNrOfFirmwareBlocks();
for (uint16_t blockNr = 0; blockNr <= nrOfFirmwareBlocks; ++blockNr) {
m_hw->bl_blockAutoLoad(blockNr);
int sleepTime = 0;
while (1) {
if (sleepTime > 1500) {
m_hw->bl_stopBL();
return false;
}
int8_t const r = m_hw->bl_blockAutoResponse();
// after every "bl_blockAutoLoad()" call this until response
// retval 0: wait 1: OK, blk was sent 2: OK, transfer complete
// 3: error despite repeating, cancel. probably bin file corrupted
// Max duration: 3x no response from BL = 900ms
switch(r) {
case 1:
/* fall through */
case 2:
sleepTime = 0;
break;
case 0: {
QThread::msleep(100);
sleepTime += 100;
} break;
case 3:
m_hw->bl_stopBL();
return false;
default:
m_hw->bl_stopBL();
return false; // unknown error code
}
}
m_hw->bl_stopBL();
}
return true;
#endif
}
QString Update::jsonType(enum FileTypeJson type) {
switch (type) {
case FileTypeJson::CASH: return "CASH";
case FileTypeJson::CONFIG: return "CONFIG";
case FileTypeJson::PRINTER: return "PRINTER";
case FileTypeJson::SERIAL: return "SERIAL";
case FileTypeJson::DEVICE: return "DEVICE";
case FileTypeJson::TIME: return "TIME";
}
return "N/A";
} }
bool Update::downloadJson(enum FileTypeJson type, bool Update::downloadJson(enum FileTypeJson type,
int templateIdx, int templateIdx,
QString jsFileToSendToDC) const { QString jsFileToSendToDC) const {
#if 0
if (m_hw) { if (m_hw) {
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
qDebug() << "SET AUTO-REQUEST=TRUE"; qDebug() << "SET AUTO-REQUEST=TRUE";
@@ -489,6 +351,7 @@ bool Update::downloadJson(enum FileTypeJson type,
// QThread::sleep(1); // make sure the auto-request flag is acknowledged // QThread::sleep(1); // make sure the auto-request flag is acknowledged
} }
#endif
return true; return true;
} }
@@ -547,6 +410,7 @@ void Update::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
} }
QStringList Update::getDcSoftAndHardWareVersion() { QStringList Update::getDcSoftAndHardWareVersion() {
#if 0
if (m_hw) { if (m_hw) {
m_hw->dc_autoRequest(true); m_hw->dc_autoRequest(true);
QThread::sleep(1); // make sure the timer-slots are active QThread::sleep(1); // make sure the timer-slots are active
@@ -569,15 +433,17 @@ QStringList Update::getDcSoftAndHardWareVersion() {
} }
} }
#endif
return QStringList() << "DC HW-version not available" return QStringList() << "DC HW-version not available"
<< "DC SW-version not available"; << "DC SW-version not available";
} }
QString Update::getFileVersion(QString const& jsonFileName) { QString Update::getFileVersion(QString const& jsonFileName) {
QString fileVersion("");
#if 0
// "version":"15.10.2023 14:55 02.00.06", // "version":"15.10.2023 14:55 02.00.06",
static const QRegularExpression re("^.*(\\\"[Vv]ersion\\\":)([\\s\\\"]{0,})([^,\\\"]{0,}).*$"); static const QRegularExpression re("^.*(\\\"[Vv]ersion\\\":)([\\s\\\"]{0,})([^,\\\"]{0,}).*$");
QString fileVersion("");
QFile inputFile(QDir::cleanPath(m_customerRepository + QDir::separator() + jsonFileName)); QFile inputFile(QDir::cleanPath(m_customerRepository + QDir::separator() + jsonFileName));
if (inputFile.exists()) { if (inputFile.exists()) {
@@ -602,10 +468,12 @@ QString Update::getFileVersion(QString const& jsonFileName) {
// qCritical() << "ERROR" << inputFile.fileName() << "does not exist"; // qCritical() << "ERROR" << inputFile.fileName() << "does not exist";
} }
#endif
return fileVersion; return fileVersion;
} }
bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) { bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) {
#if 0
for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) { for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
@@ -680,6 +548,7 @@ bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) {
} }
} }
#endif
return false; return false;
} }
@@ -687,6 +556,7 @@ QMap<QString, QString>
Update::getInstalledJsonVersions(QStringList const& jsonFileNames) { Update::getInstalledJsonVersions(QStringList const& jsonFileNames) {
QMap<QString, QString> map; QMap<QString, QString> map;
#if 0
if (!m_hw) { if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):" qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr"; << "ERROR!!! m_hw == nullptr";
@@ -786,11 +656,13 @@ Update::getInstalledJsonVersions(QStringList const& jsonFileNames) {
} }
} }
#endif
return map; return map;
} }
bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) { bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
#if 0
if (!m_hw) { if (!m_hw) {
Utils::printInfoMsg("CA-PLUGIN NOT LOADED"); Utils::printInfoMsg("CA-PLUGIN NOT LOADED");
return false; return false;
@@ -997,4 +869,7 @@ bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
qDebug() << "SET AUTO-REQUEST=TRUE"; qDebug() << "SET AUTO-REQUEST=TRUE";
return res; return res;
#endif
return false;
} }

View File

@@ -22,7 +22,6 @@ class Worker;
class Update : public QObject { class Update : public QObject {
Q_OBJECT Q_OBJECT
hwinf *m_hw = nullptr;
Worker *m_worker = nullptr; Worker *m_worker = nullptr;
char const *m_serialInterface; char const *m_serialInterface;
char const *m_baudrate; char const *m_baudrate;
@@ -102,12 +101,6 @@ public:
QString("etc/psa_config/DC2C_print31.json"), QString("etc/psa_config/DC2C_print31.json"),
QString("etc/psa_config/DC2C_print32.json")}))); QString("etc/psa_config/DC2C_print32.json")})));
hwinf *hw() { return m_hw; }
hwinf const *hw() const { return m_hw; }
//QString customerId() { return m_customerId; }
//QString const customerId() const { return m_customerId; }
QString branchName() { return m_branchName; } QString branchName() { return m_branchName; }
QString const branchName() const { return m_branchName; } QString const branchName() const { return m_branchName; }

View File

@@ -178,9 +178,6 @@ QString Utils::zoneName(quint8 i) {
//if (i < (sizeof(zName)/sizeof(char const *))) { //if (i < (sizeof(zName)/sizeof(char const *))) {
// return zName[i]; // return zName[i];
//} //}
Q_UNUSED(i)
return "---"; return "---";
} }

View File

@@ -290,6 +290,8 @@ void Worker::privateUpdate() {
return; return;
} }
return;
QString func(__PRETTY_FUNCTION__); QString func(__PRETTY_FUNCTION__);
GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::STARTED)); GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::STARTED));
@@ -590,6 +592,16 @@ bool Worker::updateTriggerSet() {
CONSOLE(lst) << UPDATE_STEP::DEBUG; CONSOLE(lst) << UPDATE_STEP::DEBUG;
} }
if ((repeat % 8) == 0) {
CONSOLE(QStringList(func) << "RESTART APISM") << UPDATE_STEP::DEBUG;
Command c("systemctl restart apism");
if (c.execute("/tmp")) {
QThread::sleep(20); // give APISM some time to reconnect
QStringList lst = (m_ismasTriggerStatusMessage = (QStringList(func) << "RESTART APISM DONE"));
CONSOLE(lst) << UPDATE_STEP::DEBUG;
}
}
if (std::optional<QString> result if (std::optional<QString> result
= IsmasClient::sendRequestReceiveResponse( = IsmasClient::sendRequestReceiveResponse(
IsmasClient::APISM::DIRECT_PORT, "#M=APISM#C=REQ_ISMASPARAMETER#J={}")) { IsmasClient::APISM::DIRECT_PORT, "#M=APISM#C=REQ_ISMASPARAMETER#J={}")) {

View File

@@ -1,49 +0,0 @@
#ifndef COMMAND_H_INCLUDED
#define COMMAND_H_INCLUDED
#include <QObject>
#include <QCoreApplication>
#include <QString>
#include <QStringList>
#include <QProcess>
#include <QScopedPointer>
class Command : public QObject {
Q_OBJECT
QString m_command;
QString m_commandResult;
int m_waitForStartTimeout;
int m_waitForFinishTimeout;
bool m_verbose;
int m_exitCode;
QString m_workingDirectory;
QScopedPointer<QProcess> m_p;
QStringList m_args;
public:
Command(QString command,
QStringList args,
QString workingDirectory,
bool verbose = true,
int start_timeout = 100000,
int finish_timeout = 100000);
void resetCommandResult() { m_commandResult.clear(); }
QString getCommandResult(bool reset = false);
QString const &command() const { return m_command; }
QString const &commandResult() const { return m_commandResult; }
QStringList const &args() const { return m_args; }
bool exec();
int exitCode() const { return m_exitCode; }
private slots:
virtual void readyReadStandardOutput();
virtual void readyReadStandardError();
};
#endif // COMMAND_H_INCLUDED

View File

@@ -1,92 +0,0 @@
#ifndef UTILS_INTERNAL_H_INCLUDED
#define UTILS_INTERNAL_H_INCLUDED
#include <QString>
#include <QSettings>
#include <memory>
namespace internal {
static constexpr const char *UPDATE_NOT_NECESSARY{"not necessary"};
static constexpr const char *UPDATE_NOT_REQUESTED{"not requested"};
static constexpr const char *UPDATE_INITIAL{"initial update"};
static constexpr const char *UPDATE_REQUESTED{"requested"};
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_DISCONNECTED{"disconnected"};
static constexpr const char *ISMAS_DISCONNECTING{"disconnecting"};
static constexpr const char *ISMAS_NOT_CONNECTED{"not connected"};
static constexpr const char *ISMAS_CONNECTION_IN_PROGRESS{"connecting"};
static constexpr const char *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_PULL_ERROR_CODE{-4};
static constexpr const int GIT_NOT_NECESSARY_CODE{1};
static constexpr const int GIT_UPDATED_CODE{2};
static constexpr const int GIT_CLONED_CODE{3};
static constexpr const char *GIT_CUSTOMER_REPO_CHECKOUT_ERROR{"checkout error"};
static constexpr const char *GIT_CUSTOMER_REPO_PULL_ERROR{"pull error"};
static constexpr const char *GIT_CUSTOMER_REPO_UP_TO_DATE{"up to date"};
static constexpr const char *GIT_CUSTOMER_REPO_NO_UPDATE_NECESSARY{"no repository update necessary"};
static constexpr const char *GIT_CUSTOMER_REPO_NOT_NECESSARY{"not necessary"};
static constexpr const char *GIT_CUSTOMER_REPO_UPDATED{"repository updated"};
static constexpr const char *GIT_CUSTOMER_REPO_CLONED{"repository cloned"};
static constexpr const char *GIT_UPDATED{"updated"};
static constexpr const char *EXEC_OPKG_COMMANDS_SUCCESS{"success"};
static constexpr const char *EXEC_OPKG_COMMANDS_FAIL{"FAIL"};
static constexpr const char *EXEC_OPKG_COMMANDS_NOACTION_SUCCESS{"success"};
static constexpr const char *EXEC_OPKG_COMMANDS_NOACTION_FAIL{"FAIL"};
static constexpr const char *UPDATE_DC_JSON_FILES_SUCCESS{"success"};
static constexpr const char *SYNC_CUSTOMER_REPO_FILES_SUCCESS{"success"};
static constexpr const char *UPDATE_DC_FIRMARE_SUCCESS{"success"};
static constexpr const char *OPKG_MARKER{"<OPKG>"};
static constexpr const char *SYNC_MARKER{"<SYNC>"};
static constexpr const char *DC_MARKER{"<DC>"};
static constexpr const char *GIT_MARKER{"<GIT>"};
static constexpr const char *ISMAS_MARKER{"<ISMAS>"};
static constexpr const int PERCENT_CHECK_ISMAS_CONNECIVITY{10};
static constexpr const int PERCENT_CHECK_UPDATE_REQUEST{20};
static constexpr const int PERCENT_CHECK_CUSTOMER_REPOSITORY{30};
static constexpr const int PERCENT_INSTALL_SW_PACKETS_NOACTION{40};
static constexpr const int PERCENT_INSTALL_SW_PACKETS{50};
static constexpr const int PERCENT_INSTALL_DC_CONFIGURATION{60};
static constexpr const int PERCENT_SYNCHRONIZE_REPO_AND_FILESYS{70};
static constexpr const int PERCENT_UPDATE_DC{80};
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);
QString customerRepoRoot();
QString customerRepoDir();
QString customerRepoDcDir();
QString customerRepoDirName();
QString repositoryUrl();
QString branchName();
bool customerRepoExists();
std::unique_ptr<QSettings> readSettings(QString const &optionalDirName = "");
std::unique_ptr<QString> dcCandidateToInstall(QString const &dcDirectory);
}
#endif // UTILS_INTERNAL_H_INCLUDED

View File

@@ -1,128 +0,0 @@
#include "command.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
#include <QDateTime>
Command::Command(QString command, QStringList args, QString workingDirectory,
bool verbose, int start_timeout, int finish_timeout)
: m_command(command.trimmed())
, m_commandResult("")
, m_waitForStartTimeout(start_timeout)
, m_waitForFinishTimeout(finish_timeout)
, m_verbose(verbose)
, m_exitCode(-1)
, m_workingDirectory(workingDirectory)
, m_args(args) {
m_p.reset(new QProcess(this));
if (m_p) {
m_p->setWorkingDirectory(workingDirectory);
m_p->setProcessChannelMode(QProcess::MergedChannels);
connect(m_p.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
connect(m_p.get(), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
}
}
void Command::readyReadStandardOutput() {
QProcess *p = (QProcess *)sender();
if (p) {
QString s = p->readAllStandardOutput();
if (m_verbose) {
// qCritical().noquote() << s;
m_commandResult += s;
}
}
}
void Command::readyReadStandardError() {
QProcess *p = (QProcess *)sender();
if (p) {
QString s = p->readAllStandardError();
// qCritical().noquote() << s;
m_commandResult += s;
}
}
QString Command::getCommandResult(bool reset) {
if (reset == false) {
return m_commandResult;
}
QString commandResult = m_commandResult;
m_commandResult.clear();
return commandResult;
}
bool Command::exec() {
if (!m_args.isEmpty()) {
m_p->start(m_command, m_args);
} else {
m_p->start(m_command);
}
qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch();
bool started = false;
if ((started = m_p->waitForStarted(m_waitForStartTimeout)) == true) {
// qCritical() << "PROCESS" << m_command << "STARTED IN" << m_p->workingDirectory();
if (m_p->state() == QProcess::ProcessState::Running) {
// qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory();
// wait forever for git/opkg-commands to finish
int wait = m_waitForFinishTimeout;
if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) ||
m_command.trimmed().startsWith("opkg", Qt::CaseInsensitive)) {
wait = -1;
}
bool const no_timeout = m_p->waitForFinished(wait);
if (no_timeout) {
// qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory();
if (m_p->exitStatus() == QProcess::NormalExit) {
if ((m_exitCode = m_p->exitCode()) == 0) {
qCritical().noquote() << m_p->readAllStandardOutput();
//qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
//qDebug() << "EXECUTED" << m_command
// << QString("(runtime %1ms)").arg(end-start)
// << "with code" << m_exitCode
// << "IN" << m_p->workingDirectory();
return true;
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << m_p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "CRASHED with code"
<< m_p->exitCode()
<< QString("(after %1ms)").arg(end-start)
<< "IN" << m_p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command
<< "DID NOT FINISH WITH" << wait
<< "MS IN" << m_p->workingDirectory()
<< QString("(runtime %1ms)").arg(end-start);
}
} else {
qCritical() << "WRONG PROCESS STATE" << m_p->state()
<< "IN" << m_p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"
<< QString("(runtime %1ms)").arg(end-start)
<< "IN" << m_p->workingDirectory() << m_waitForStartTimeout;
}
return false;
}

View File

@@ -1,167 +0,0 @@
#include "utils_internal.h"
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QSettings>
#include <QDebug>
#include <QCryptographicHash>
#include <QFileInfoList>
namespace internal {
int read1stLineOfFile(QString fileName) {
QFile f(fileName);
if (f.exists()) {
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&f);
in.setCodec("UTF-8");
while(!in.atEnd()) {
return in.readLine().toInt();
}
}
}
return -1;
}
QString customerRepoRoot() {
return "/opt/app/tools/atbupdate/";
}
QString customerRepoDirName() {
int const customerNr = read1stLineOfFile("/mnt/system_data/cust_nr");
return (customerNr != -1) ? QString("customer_%1").arg(customerNr) : "";
}
QString customerRepoDir() {
QString const &n = customerRepoDirName();
QString const &r = customerRepoRoot();
return !n.isEmpty() ? QDir::cleanPath(r + QDir::separator() + n) : "";
}
QString customerRepoDcDir() {
QString const &r = customerRepoDir();
return QDir::cleanPath(r + QDir::separator() + "etc/dc/");
}
bool customerRepoExists() {
QString const repoDir{customerRepoDir()};
return !repoDir.isEmpty() ? QDir(repoDir).exists() : false;
}
QString repositoryUrl() {
return "gitea@ptu-config.atb-comm.de:ATB/";
}
QString branchName() {
int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr");
if (zoneNr != -1) {
return QString("zg1/zone%1").arg(zoneNr);
}
return "";
}
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

View File

@@ -1,184 +0,0 @@
#!/bin/bash
# set -x
#
#############################################################################
# Check if the ATBUpdateTool(.service) did not send U0001 (sucess),
# U0002 (activated) or U0003 (error) to ISMAS, including the case that the
# tool did not crash or was not killed under other circumstances.
#
# This script will be called in the associated atbupdatetool.service (see
# /lib/systemd/system/atbupdatetool.service).
#
###############################################################################
readonly OUT_FILE=/tmp/out.txt
readonly SCRIPT_NAME=$(basename $0)
if [ -z "$START_DATE" ]
then
START_DATE=$(date +"%Y-%m-%d00:00:00")
fi
if [ -z "$STOP_DATE" ]
then
STOP_DATE=$(date +"%Y-%m-%d%H:%M:%S")
fi
echo "EXIT_CODE=$EXIT_CODE"
echo "SERVICE_RESULT=$SERVICE_RESULT"
echo "EXIT_STATUS=$EXIT_STATUS"
echo "START_DATE=$START_DATE"
echo "STOP_DATE=$STOP_DATE"
last_cmd_event () {
# output json; look for start of CMD_EVENT; look for }}; extract everything between; finally re-add }}.
# could also look for ">>>", but this might change in the future.
local json=$(\
journalctl -u atbupdatetool --since="$START_DATE" --until="$STOP_DATE" --output=json-pretty |\
grep "#M=APISM#C=CMD_EVENT#J=" |\
awk '{split($0, a, "#M=APISM#C=CMD_EVENT#J="); print a[2]}' |\
awk '{split($0, a, /\}[\s]*\}/); print a[1]}' |\
tr -d '\\' |\
tail -1)
json+="}}"
echo "$json"
}
last_percent_value () {
echo $(cat $OUT_FILE | sed -n "s/\(^.*\)\(\"PERCENT\"\\s*:\)\(\\s*[0-9]\+\)\(.*$\)/\3/p" | xargs | awk '{print $NF}')
}
last_step () {
echo $(cat $OUT_FILE | sed -n "s/\(^.*\)\(\"PERCENT\"\\s*:\)\(\\s*[0-9]\+\)\(.*$\)/\1\2\3\4/p" | tail -1 | awk '{split($0, a, ","); print a[8]}' | awk '{split($0, b, " : "); print b[2]}' | tr -d '"\\')
}
last_step_result () {
echo $(cat $OUT_FILE | sed -n "s/\(^.*\)\(\"PERCENT\"\\s*:\)\(\\s*[0-9]\+\)\(.*$\)/\1\2\3\4/p" | tail -1 | awk '{split($0, a, ","); print a[9]}' | awk '{split($0, b, " : "); print b[2]}' | tr -d '"\\')
}
pid_atbupdatetool () {
echo $(cat $OUT_FILE | sed -n "s/\(^.*\)\(ATBUpdateTool\[\)\(\\s*[0-9]\+\)\(\].*$\)/\3/p" | uniq)
}
last_event () {
echo $(cat $OUT_FILE | sed -n "s/\(^.*\)\(\"PERCENT\"\\s*:\)\(\\s*[0-9]\+\)\(.*$\)/\1\2\3\4/p" | tail -1 | awk '{split($0, a, ","); print a[4]}' | awk '{split($0, b, ":"); print b[2]}' | tr -d ' ' | tr -d '"\\')
}
sendU0003 () {
LAST_CMD_EVENT=$(last_cmd_event)
echo "LAST=$LAST_CMD_EVENT"
local json_detected=0
local temp
local x
if [[ ! -z "$LAST_CMD_EVENT" ]]
then
temp=$(mktemp -p /tmp)
echo "$LAST_CMD_EVENT" > "$temp"
x=$(jq .EVENT $temp)
if [ $? -eq 0 ]; then
json_detected=1
fi
fi
if [ $json_detected -eq 1 ]
then
# local pid=$(jq .EVENT_ID $temp)
# if json has been detected, use "jq".
x=$(jq .PARAMETER.PERCENT $temp | tr -d '"')
[[ -z "$x" ]] && PERCENT=0 || PERCENT=$x
x=$(jq .PARAMETER.STEP $temp | tr -d '"')
[[ -z "$x" ]] && STEP="unknown" || STEP="$x"
x=$(jq .PARAMETER.STEP_RESULT $temp | tr -d '"')
[[ -z "$x" ]] && STEP_RESULT="unknown" || STEP_RESULT="$x"
x=$(pid_atbupdatetool)
[[ -z "$x" ]] && PID=99999 || PID=$x
x=$(last_event)
[[ -z "$x" ]] && EVENT="unknown" || EVENT="$x"
else
# cannot parse valid json. try original journal text file.
x=$(last_percent_value)
[[ -z "$x" ]] && PERCENT=0 || PERCENT=$x
x=$(last_step)
[[ -z "$x" ]] && STEP="unknown" || STEP="$x"
x=$(last_step_result)
[[ -z "$x" ]] && STEP_RESULT="unknown" || STEP_RESULT="$x"
x=$(pid_atbupdatetool)
[[ -z "$x" ]] && PID=99999 || PID=$x
x=$(last_event)
[[ -z "$x" ]] && EVENT="unknown" || EVENT="$x"
fi
echo "PERCENT=$PERCENT"
echo "STEP=$STEP"
echo "STEP_RESULT=$STEP_RESULT"
echo "PID=$PID"
echo "EVENT=$EVENT"
# build json to be sent to ISMAS with "U0003"
CURRENT_DATE=$(date +"%Y-%m-%d %H:%M:%S.000%z")
U0003Msg="{\
\"REASON\":\"SW_UP\",\
\"TIMESTAMP\":\"$CURRENT_DATE\",\
\"EVENT_ID\":\"$PID\",\
\"EVENT\":\"U0003\",\
\"EVENTSTATE\":1,\
\"PARAMETER\": {\
\"PERCENT\" : $PERCENT,\
\"RESULTCODE\" : 99,\
\"STEP\" : \"$1 -> monitored last step: $STEP\",\
\"STEP_RESULT\" : \"$1 -> monitored last step result: $STEP_RESULT\",\
\"VERSION\" : \"\"\
}\
}"
echo -e "U0003Msg=$U0003Msg"
(echo "#M=APISM#C=CMD_EVENT#J=$U0003Msg"; sleep 5) | nc localhost 7777
}
# save journal for the last run of atbupdatetool in $OUT_FILE
echo $(journalctl -u atbupdatetool --since="$START_DATE" --until=$STOP_DATE) > $OUT_FILE
if [[ "$EXIT_CODE" = "exited" && "$SERVICE_RESULT" = "success" && "$EXIT_STATUS" = "0" ]]
then
# almost normal run; at least there was no crash.
if cat $OUT_FILE | grep -o "U0003" | wc -l; then
echo "$SCRIPT_NAME: Failure code U0003 already sent to ISMAS"
exit 0
fi
if cat $OUT_FILE | grep -o "U0002" | wc -l; then
echo "$SCRIPT_NAME: Success code U0002 already sent to ISMAS"
exit 0
else
sendU0003 "$SCRIPT_NAME: Success code U0002 not sent to ISMAS"
fi
if cat $OUT_FILE | grep -o "U0001" | wc -l; then
echo "$SCRIPT_NAME: Success code U0001 already sent to ISMAS"
exit 0
else
sendU0003 "$SCRIPT_NAME: Success code U0001 not sent to ISMAS"
fi
else
# something unexpected has happened.
sendU0003 "$SCRIPT_NAME: EXIT_CODE=$EXIT_CODE;SERVICE_RESULT=$SERVICE_RESULT;EXIT_STATUS=$EXIT_STATUS"
fi