Compare commits

...

91 Commits

Author SHA1 Message Date
da0fa54d28 gitPull():
Add important comment for the case that an remote host key change:
	'git pull' handles the issue itself, and continues to pull the repository
	using the ssh-key provided in the .keys/ directory.
2024-10-23 12:58:48 +02:00
1433c107b3 Remove right-justification in customer_id-name. Version: 1.5.3 2024-10-15 16:48:40 +02:00
8e0732cf95 Set version to 1.5.2. 2024-10-08 15:04:08 +02:00
8f6e1fdae7 clean up: remove .gz and .ipk files in /var/cache/opkg 2024-10-08 15:03:43 +02:00
0d00faf493 Remove hard coded (szeged) zone names 2024-07-23 09:28:54 +02:00
5beb235d92 Chop a trailing / of the repository url -> no clean path necessary 2024-07-17 14:50:32 +02:00
a4bb993217 Set version to 1.5.1 2024-07-17 14:06:18 +02:00
50357997c2 Do not use cleanPath() on an url-path 2024-07-17 14:04:53 +02:00
c02f0b08ed Set version to 1.5.0. 2024-06-28 13:01:24 +02:00
5da1eff41a Use repository-url="gitea@ptu-config.atb-comm.de:ATB/" 2024-06-28 12:58:13 +02:00
af89c9fbc1 Add SSH_GIT_COMMAND environment variable for pyu-config.atb-comm.de repository server. 2024-06-28 12:52:48 +02:00
fa7d1ba879 Allow empty lines in opkg_commands. 2024-06-28 12:50:30 +02:00
1dc7578645 Clean repository path from multiple slashes. 2024-06-28 12:49:53 +02:00
cd30cc91f0 Set version to 1.4.11. 2024-06-28 10:06:35 +02:00
6683b925aa Fix: remove hard-coded path to gitea repository (mimbach). 2024-06-28 10:03:10 +02:00
336d208906 Fix: never set the autoRequest-flag to false. 2024-06-26 13:27:39 +02:00
2da3c34d84 Set version to 1.4.10. 2024-06-26 13:26:55 +02:00
8f0a9112d6 Fix: do not set the autoRequest flag back to false. 2024-06-26 13:15:48 +02:00
25bf905a79 Use now new git-server: https://ptu-config.atb-comm.de/ATB 2024-06-14 13:36:34 +02:00
5d141b7234 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/ATBUpdateTool 2024-06-05 17:33:54 +02:00
ebb170123e Provide proto-binary 2024-06-05 10:10:21 +02:00
96bb70cfe9 Merge branch 'release_1.4.9' 2024-05-23 12:31:27 +02:00
8c1da92ff4 Make compile with yocto/bitbake 2024-05-23 12:29:07 +02:00
3e1a4ab09c Add comment for M0100 2024-05-17 12:32:53 +02:00
ee203e7672 doUpdate()/downloadJson(): send messages to ISMAS of the download
process of JSON files (DC2C_cash.json etc).
2024-05-17 12:29:02 +02:00
55c82eb509 Fix: send output to CONSOLE if directories are actually not equal. 2024-05-17 12:26:36 +02:00
f60cd9e4ef Again: improved ISMAS messages. 2024-05-17 12:26:03 +02:00
a9fb7a3630 Improve messages sent to ISMAS during update process. 2024-05-17 12:25:26 +02:00
db82f2af0d Fix: do not send a message to ISMAS about a check of the ISMAS
trigger (WAIT-button). For an automatic update this meant that
two messages have been visible in ISMAS which confused many users.
2024-05-17 12:22:38 +02:00
8b2e2d2086 For automatic updates send M0100, for user-triggered updates send U0002 = OK = Update aktivated. 2024-05-17 12:20:46 +02:00
5870f61395 Send UPDATE_SUCCEEDED (U0001 = 100%) only for user-triggered updates,
not for automatic ones.
2024-05-17 12:19:22 +02:00
aaa0f1e76c Minor: use correct string tor ISMAS message. 2024-05-17 12:18:11 +02:00
0d9a224977 Add M0100 message define. To be sent for automatic updates if not necessary. 2024-05-17 12:17:12 +02:00
d191020caa Configure new update-step values.
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS),
2024-05-17 08:47:10 +02:00
2b68242d04 Add new macro-values to improve output sent to ISMAS:
DOWNLOAD_CASH_FILE
DOWNLOAD_CASH_FILE_FAILURE
DOWNLOAD_CASH_FILE_SUCCESS
DOWNLOAD_DEVICE_FILE
DOWNLOAD_DEVICE_FILE_FAILURE
DOWNLOAD_DEVICE_FILE_SUCCESS
DOWNLOAD_JSON_FILE
DOWNLOAD_JSON_FILE_FAILURE
DOWNLOAD_JSON_FILE_SUCCESS

Adapt percent-counters to show progress of update process.
2024-05-17 08:43:37 +02:00
bd785e7df1 Minor: changes some debug text 2024-05-16 16:44:35 +02:00
f2534c7763 Fix: updateNewsToIsmas(): format TIMESTAMP with UTC-Offset suffix. 2024-05-16 10:36:58 +02:00
d2a6ae239d Set version to 1.4.9. 2024-05-15 15:06:54 +02:00
19273daa55 Do not install an own message-handler to prevent double-debug-output in
linux-journals.
2024-05-15 15:05:49 +02:00
ca67d1d159 Ignore RECORD-messages sent by APISM which do not have JSON format. 2024-05-15 15:04:51 +02:00
7c3e4ea497 Minor: remove some debug output. Error messages still intact. 2024-05-15 15:03:47 +02:00
f8897c2950 Implement Update::getInstalledJsonVersions(). 2024-05-15 15:02:53 +02:00
94a658ce8a Add some IMPORTANT comments about the format of JSON files to be downloaded. 2024-05-15 15:02:10 +02:00
9d9865e3c7 downloadJson(): continue update-process even when downloading of some JSON file fails. 2024-05-15 15:01:16 +02:00
a7d5a8f5cd Declaration of getInstalledJsonVersions() with default parameter. 2024-05-15 14:59:08 +02:00
cafd16a744 Read versions of JSON files installed on PSA (DC!).
If version is available, use as blob-value to be visible
in ISMAS.
2024-05-15 14:57:15 +02:00
5876c50a32 Make sure that SEND-LAST-VERSION is executed exactly once. 2024-05-15 14:56:41 +02:00
3b2200c0bf Make sure that SEND-LAST-VERSION is executed exactly once. 2024-05-15 14:55:55 +02:00
e8070a9e16 set port name 2024-05-14 16:39:09 +02:00
da10d6c2f6 make compile 2024-05-14 16:38:47 +02:00
c52b276722 first draft 2024-05-14 16:38:19 +02:00
e9cb421ac5 Add first draft 2024-05-14 16:37:45 +02:00
a3aef7594e Minor: add comment 2024-05-14 12:52:09 +02:00
afbcccf785 Minor: add comment about index shift: 4 -> 5 2024-05-14 12:51:32 +02:00
90e4e21391 System::getJsonFilesOnUsbStick(): return list of JSON files for configured
directory under mount path.
2024-05-14 12:49:28 +02:00
4536284f34 getUSBMountPath(): check for directory 'dirPathUnderMountPath' under mount path. 2024-05-14 12:48:19 +02:00
a3a4c09c7f checkForUSBStick(): look for etc/psa_config in mountpath-directory. 2024-05-14 12:46:38 +02:00
a5dd9af29a Add System::allowedJsonFiles to name default JSON file names. 2024-05-14 12:45:43 +02:00
5124e1cca6 Use return value of type std::optional<QString> for
checkForUSBStick() and getUSBMountPath().
Add getJsonFilesOnUsbStick().
2024-05-14 12:43:46 +02:00
fc75585de3 Parse psa-config-directory and psa-tariff-directory. 2024-05-14 12:40:32 +02:00
1964b08349 doUpdate(): use parameter 'usbStickDetected' to use the correct JSON
filenames.
2024-05-14 12:38:31 +02:00
c0d014644c Update (conf) JSON-Files using USB stick. When plugged in, look for
JSON-files in directory psa-config-directory and load them to the PSA.
Note: these files are overwritten during a usual ISMAS-update if not
checked in into the customer repository.
2024-05-14 12:35:18 +02:00
b24c50c572 Parse psa-config-directory and psa-tariff-directory settings. 2024-05-14 12:33:40 +02:00
bbdadc9063 Include psa_config_directory and psa_tariff_directory settings. 2024-05-14 12:32:26 +02:00
dc7f839d3f Include ATBUpdateTool.ini 2024-05-14 12:31:19 +02:00
0a33d078be Set version to 1.4.8 2024-05-08 16:20:54 +02:00
1d64769094 Fix: shift jsonNr by 1 in checkDownloadedJsonVersions(); print-templates start now with 6 instead of 5. 2024-05-08 16:17:28 +02:00
2e3af64c02 getFileVersion(): use only 16 byte of buffer filled by DC with version-info
of JSON-file.
2024-05-08 16:16:13 +02:00
f8472a3b87 call update.checkJsonVersions(filesToUpdate) after doUpdate(). 2024-05-08 16:10:20 +02:00
24addad11e Implement getFileversion(). 2024-05-08 16:09:18 +02:00
5a8298a078 Implemented checkJsonVersions(). 2024-05-08 16:08:53 +02:00
52af7894db Minor: remove useless assignments. 2024-05-08 16:08:01 +02:00
a6592ffd3e Check m_hw for nullprt. 2024-05-08 16:07:27 +02:00
696db7de39 Don't call exit(), but return nullptr. 2024-05-08 16:06:14 +02:00
b31588bfab checkJsonVersions(): provide default parameters 2024-05-08 16:04:53 +02:00
6651920f4a Merge branch 'release_1.4.6' 2024-05-06 11:29:29 +02:00
ef800366e1 Make compile with yocto/bitbake 2024-05-06 10:59:31 +02:00
1acec4d876 revert to original version of the file (tag: 1.4.7) 2024-05-06 10:28:43 +02:00
46c481b862 Add worker_thread.h/.cpp 2024-05-06 06:25:03 +02:00
8945ead5d6 set setting for opening serial device 2024-05-06 06:24:25 +02:00
bc064c38c6 use only one thread 2024-05-06 06:23:52 +02:00
f741fb96f9 start main sources 2024-05-05 17:26:34 +02:00
8d1c719626 form fir mainwindow 2024-05-05 17:25:07 +02:00
b5389a599e add main window 2024-05-05 17:24:28 +02:00
ea2f42beed Add gui-form and sneder/receiver-thread source. 2024-05-05 17:23:08 +02:00
22e751e197 Minor: add comment 2024-05-03 13:35:33 +02:00
05c7d11ef8 Only create m_update-object if it is configured to update hardware (JSONs and DC). 2024-05-03 13:32:39 +02:00
63dc70dda9 Check if it has to be possible to update hardware (JSONs, DC). If yes, then exit(). 2024-05-03 13:31:04 +02:00
e5ab9b98cd Set Version to 1.4.7 2024-05-03 13:14:57 +02:00
4477647acf Check m_hw before its use 2024-05-03 13:11:33 +02:00
d64b029a2d loadDCPlugin(): never call exit() inside a library. 2024-05-03 13:08:25 +02:00
37 changed files with 3108 additions and 404 deletions

View File

@@ -1,9 +1,12 @@
[REPOSITORY_URL] [REPOSITORY_URL]
repository-url="https://git.mimbach49.de/GerhardHoffmann" repository-url="gitea@ptu-config.atb-comm.de:ATB/"
[DIRECTORIES] [DIRECTORIES]
plugin-directory="/usr/lib/" plugin-directory="/usr/lib/"
working-directory="/opt/app/tools/atbupdate/" working-directory="/opt/app/tools/atbupdate/"
psa-config-directory="etc/psa_config/"
psa-tariff-directory="etc/psa_tariff/"
[PLUGINS] [PLUGINS]
plugin-name="libCAslave.so" plugin-name="libCAslave.so"

View File

@@ -1,5 +1,5 @@
QT += core QT += core gui
QT += serialport network QT += widgets serialport network
TARGET = ATBDownloadDCFirmware TARGET = ATBDownloadDCFirmware
@@ -16,6 +16,16 @@ GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}" EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
!contains(CONFIG, INCLUDEINTERFACES) {
INCLUDEINTERFACES=/opt/ptu5/opt/DCLibraries/include
}
INCLUDEPATH += \
plugins \
$${INCLUDEINTERFACES} \
$${_PRO_FILE_PWD_}/../UpdatePTUDevCtrl \
$${_PRO_FILE_PWD_}/../common/include
CONFIG += c++17 CONFIG += c++17
DEFINES+=APP_VERSION=\\\"$$VERSION\\\" DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
@@ -66,14 +76,32 @@ contains( CONFIG, DesktopLinux ) {
} }
SOURCES += \ SOURCES += \
main.cpp main.cpp \
mainwindow.cpp \
../common/src/message_handler.cpp \
../UpdatePTUDevCtrl/commandline_parser.cpp \
update.cpp \
dc_download.cpp \
../common/src/System.cpp
HEADERS += \
mainwindow.h \
../common/include/message_handler.h \
../UpdatePTUDevCtrl/commandline_parser.h \
update.h \
dc_download.h \
../common/include/System.h
# HEADERS +=
OTHER_FILES += \ OTHER_FILES += \
ATBDownloadDCFirmware.ini ATBDownloadDCFirmware.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

@@ -0,0 +1,444 @@
#include "dc_download.h"
#include <DeviceController/interfaces.h>
#include <QFile>
#include <QDebug>
#include <QDateTime>
#include <QThread>
DcDownload::DcDownload(hwinf *hw)
: m_hw(hw)
, m_fileToDownload(m_hw->dcDownloadFileName()) {
// connect(this, &QThread::finished,
// dynamic_cast<QObject const *>(m_hw), &QThread::deleteLater);
}
DcDownload::~DcDownload() {
}
/*
///////////////////////////////////////////////////////////////////////////////
//
// USING THE DC BOOTLOADER
//
///////////////////////////////////////////////////////////////////////////////
1 : bl_reboot() // send to application, want DC2 to reset (in order to
// start the bootloader)
//
// NOTE: this function is NOT reliable !!! Sometimes it
// simply does not work, in which case bl_startBL,
// bl_checkBL and bl_isUp do not work as well.
// Alas, there is no feedback if bl_reboot worked!
//
// NOTE: this function can be called only once per
// minute, because once called again, the controller
// performs some self-checks consuming some time.
//
// NOTE: after a successful bl_reboot(), the device is
// waiting about 4 seconds in the bootloader. To stay in
// the bootloader, we have to send the command
// bl_startBL(), which is kind of a misnomer, as it
// should be bl_doNotLeaveBL().
//
2 : bl_startBL(): // send within 4s after DC power-on, otherwise
// bootloader is left.
//
// NOTE: a running bootloader is a MUST for the download
// process of a device controller firmware as it does
// the actual writing of the memory (the bl_reboot()
// from above erases the available memory).
//
3 : bl_check(): // send command to verify if bl is up
//
// NOTE: this command is kind of a request that we want
// to check if the bootloader is up. The device
// (actually the bootloader) responds with its version.
//
4 : bl_isUp(): // returns true if bl is up and running
//
// NOTE: we know what the bootloader version actually is
// as the bootloader does not change. By comparing the
// string received in the previous step with this known
// version string we know if the bootloader is up.
//
// NOTE FOR ALL PREVIOUS STEPS: execute them in their
// own slots each to be sure to receive any possible
// responds from the device.
//
5 : bl_sendAddress(blockNumber)
// send start address, nr of 64-byte block, start with 0
// will be sent only for following block-numbers:
// 0, 1024, 2048, 3072 and 4096, so basically every
// 64kByte.
// for other addresses nothing happens
6 : bl_wasSendingAddOK()
// return val: 0: no response by now
// 1: error
// 10: OK
7 : bl_sendDataBlock()
// send 64 byte from bin file
8 : bl_sendLastBlock()
// send this command after all data are transferred
9 : bl_wasSendingDataOK()
// return val: 0: no response by now
// 1: error
// 10: OK
10 : bl_stopBL() // leave bl and start (the new) application
//
// NOTE: this function MUST work under all conditions.
// Alas, there is no direct result for this command, so
// the only way of knowing it was successful is to ask
// the device if the bootloader is still running.
// There is no problem to repeat this command until the
// bootloader is really not running anymore.
*/
void DcDownload::doDownload() {
#if 0
void DcDownload::run() {
// download thread running in ca-master sends the dc-file down to firmware
// TODO: send the json files as well
m_hw->dcDownloadRequestAck();
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): DOWNLOAD THREAD STARTED:";
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< " DcDownload::run(): Filename:" << m_hw->dcDownloadFileName();
QDateTime const start = QDateTime::currentDateTime();
#if 1
QFile fn(m_hw->dcDownloadFileName());
if (!fn.exists()) {
// output via CONSOLE() etc
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< " DcDownload::run(): Filename:" << m_hw->dcDownloadFileName() << "DOES NOT EXIST";;
} else {
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): DC-CONTROLLER SW-VERSION BEFORE"
<< m_hw->dc_getSWversion();
// load binary device controller file into memory
QByteArray ba = loadBinaryDCFile(m_hw->dcDownloadFileName());
if (ba.size() > 0) {
uint16_t const totalBlocks = (((ba.size())%64)==0) ? (ba.size()/64) : (ba.size()/64)+1;
m_hw->dcDownloadSetTotalBlockNumber(totalBlocks);
// fill last block of data to be sent with 0xFF
ba = ba.leftJustified(totalBlocks*64, (char)(0xFF));
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): TOTAL NUMBER OF BYTES TO SEND TO DC" << ba.size();
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): TOTAL NUMBER OF BLOCKS" << totalBlocks;
m_hw->dc_autoRequest(true); // turn auto-request setting on
m_hw->request_DC2_HWversion();
m_hw->request_DC2_SWversion();
QThread::sleep(1);
// m_hw->dc_autoRequest(false); // turn auto-request setting on
resetDeviceController();
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): RESET DEVICE-CONTROLLER";
if (startBootloader()) {
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): STARTED BOOT-LOADER";
m_hw->dc_autoRequest(false);// turn auto-request setting off for
// download of binary dc
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): TOTAL NUMBER OF FIRMWARE BLOCKS" << totalBlocks;
int currentBlock = 0; // download of binary dc
DownloadResult res = DownloadResult::OK;
while (res != DownloadResult::ERROR && currentBlock < totalBlocks) {
if ((res = sendNextAddress(currentBlock)) != DownloadResult::ERROR) {
if ((res = sendNextDataBlock(ba, currentBlock)) != DownloadResult::ERROR) {
m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): currentBlockNumber ..." << currentBlock;
currentBlock += 1;
}
}
}
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< QString("DcDownload::run(): last 64-byte block %1").arg(currentBlock);
int const rest = ba.size() % 64;
int const offset = ba.size() - rest;
char const *startAddress = ba.constData() + offset;
if (rest > 0) {
// SHOULD NEVER HAPPEN !!!
uint8_t local[66];
memset(local, 0xFF, sizeof(local));
memcpy(local, startAddress, rest);
qCritical() << "DcDownload::run(): ERROR SEND REMAINING" << rest << "BYTES";
m_hw->bl_sendDataBlock(64, local);
} else {
m_hw->bl_sendLastBlock();
m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
qCritical() << "DcDownload::run(): currentBlockNumber" << currentBlock;
// QThread::msleep(250);
}
qCritical() << "DcDownload::run(): last result" << (int)sendStatus(m_hw->bl_wasSendingDataOK());
stopBootloader(); // stop bootloader several times: if it
QThread::sleep(1); // is not stopped, then the PSA has to be
}
// restarted manually (!!!)
stopBootloader();
QThread::sleep(1);
}
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): STOPPED BOOT-LOADER";
stopBootloader(); // there is no harm in stopping the bootloader even
// if it was not started at all
m_hw->dc_autoRequest(true);
}
#else // test
// load binary device controller file into memory
QByteArray ba = loadBinaryDCFile(m_hw->dcDownloadFileName());
if (ba.size() > 0) {
uint16_t const totalBlocks = (((ba.size())%64)==0) ? (ba.size()/64) : (ba.size()/64)+1;
m_hw->dcDownloadSetTotalBlockNumber(totalBlocks);
// fill last block of data to be sent with 0xFF
ba = ba.leftJustified(totalBlocks*64, (char)(0xFF));
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): TOTAL NUMBER OF BYTES TO SEND TO DC" << ba.size();
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): TOTAL NUMBER OF BLOCKS" << totalBlocks;
m_hw->dc_autoRequest(true); // turn auto-request setting on
m_hw->request_DC2_HWversion();
m_hw->request_DC2_SWversion();
QThread::sleep(1);
resetDeviceController();
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): RESET DEVICE-CONTROLLER";
QThread::sleep(1);
if (startBootloader()) {
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): STARTED BOOT-LOADER";
m_hw->dc_autoRequest(false);// turn auto-request setting off for
// download of binary dc
for (uint16_t currentBlock = 0; currentBlock <= totalBlocks; ++currentBlock) {
m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
qCritical() << "DcDownload::run(): currentBlockNumber" << currentBlock;
QThread::msleep(250);
}
m_hw->dc_autoRequest(true); // turn auto-request setting on again
}
stopBootloader(); // there is no harm in stopping the bootloader even
// if it was not started at all
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "DcDownload::run(): STOPPED BOOT-LOADER";
}
#endif
m_hw->dcDownloadSetRunning(false);
m_hw->dcDownloadSetFinished(true);
QDateTime const end = QDateTime::currentDateTime();
quint64 secs = start.secsTo(end);
QString runtime;
if (secs % 60) {
runtime = QString("%1min %2s").arg(secs / 60).arg(secs % 60);
} else {
runtime = QString("%1min").arg((secs / 60) + 1);
}
qCritical() << end.time().toString(Qt::ISODateWithMs)
<< QString("DOWNLOAD THREAD FINISHED (RUNTIME %1)")
.arg(runtime);
// the object deletes itself ! This is the last line in run().
// Never touch the object after this statement
// m_hw->dcDcDownloadFinalize(this);
#endif
}
DcDownload::DownloadResult DcDownload::sendStatus(int ret) const {
switch (ret) { // return values of dc are:
case 0: // 0: no answer by now
return DownloadResult::NOP; // 1: error
case 10: // 10: success
return DownloadResult::OK;
default:;
}
return DownloadResult::ERROR;
}
DcDownload::DownloadResult
DcDownload::sendNextAddress(int bNum) const {
// sends address only if blockNumber is one of 0, 1024, 2048, 3072, 4096
int noAnswerCount = 0;
int errorCount = 0;
if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) {
while (noAnswerCount <= 250) {
m_hw->bl_sendAddress(bNum);
QThread::msleep(100);
DownloadResult const res = sendStatus(m_hw->bl_wasSendingAddOK());
if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) {
if (++errorCount >= 10) {
qCritical() << "addr-block" << bNum << "...FAILED";
return res;
}
} else { // res == DownloadResult::OK
// qInfo() << "addr-block" << bNum << "...OK";
// TODO: hier ins shared-mem schreiben
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
// blockNumber is not one of 0, 1024, 2048, 3072, 4096 -> do nothing
return DownloadResult::NOP;
}
DcDownload::DownloadResult
DcDownload::sendNextDataBlock(QByteArray const &binary, int bNum) const {
uint8_t local[66];
int const bAddr = bNum * 64;
int noAnswerCount = 0;
int errorCount = 0;
memcpy(local, binary.constData() + bAddr, 64);
local[64] = local[65] = 0x00;
while (noAnswerCount <= 250) {
m_hw->bl_sendDataBlock(64, local);
QThread::msleep(10);
DownloadResult const res = sendStatus(m_hw->bl_wasSendingDataOK());
if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) {
if (++errorCount >= 10) {
qCritical() << "data for block" << bNum << "...FAILED";
return res;
}
} else {
// qInfo() << "data for block" << bNum << "OK";
// TODO: hier ins shared mem schreiben
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
bool DcDownload::startBootloader() const {
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "starting bootloader...";
int nTry = 5;
while (--nTry >= 0) {
m_hw->bl_startBL();
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs) << "bl_startBL() ..." << nTry;
QThread::msleep(500);
m_hw->bl_checkBL();
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs) << "bl_checkBL() ..." << nTry;
QThread::msleep(500);
if (m_hw->bl_isUp()) {
qInfo() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs) << "bootloader... isUP" << nTry;
return true;
} else {
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "bootloader not up (" << nTry << ")";
}
}
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "starting bootloader FAILED";
return false;
}
bool DcDownload::stopBootloader() const {
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "stopping bootloader...";
int nTry = 5;
while (--nTry >= 0) {
m_hw->bl_stopBL();
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "bl_stopBL() ...";
QThread::msleep(500);
m_hw->bl_checkBL();
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs) << "bl_checkBL() ..." << nTry;
if (!m_hw->bl_isUp()) {
qInfo() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "stopping bootloader OK";
return true;
}
}
qCritical() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "stopping bootloader FAILED";
return false;
}
bool DcDownload::resetDeviceController() const {
qDebug() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "resetting device controller...";
m_hw->bl_rebootDC();
// wait maximally 3 seconds, before starting bootloader
QThread::sleep(1);
qInfo() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "resetting device controller...OK";
return true;
}
QByteArray DcDownload::loadBinaryDCFile(QString filename) const {
qInfo() << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
<< "loading dc binary" << filename << "...";
QFile file(filename); // closed in destructor call
if (!file.exists()) {
qCritical() << file.fileName() << "does not exist";
return QByteArray();
}
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "cannot open file" << file.fileName();
return QByteArray();
}
qInfo() << "loading dc binary" << filename << "...OK";
return file.readAll();
}

View File

@@ -0,0 +1,32 @@
#ifndef DC_DOWNLOAD_H_INCLUDED
#define DC_DOWNLOAD_H_INCLUDED
#include <QString>
#include <QByteArray>
class hwinf;
class DcDownload {
public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
DcDownload(hwinf *hw);
~DcDownload();
void doDownload();
private:
DownloadResult sendStatus(int ret) const;
DownloadResult sendNextAddress(int bNum) const;
DownloadResult sendNextDataBlock(QByteArray const &binary, int bNum) const;
bool startBootloader() const;
bool stopBootloader() const;
QByteArray loadBinaryDCFile(QString dcFileName) const;
bool resetDeviceController() const;
DownloadResult dcDownloadBinary(QByteArray const &b) const;
hwinf *m_hw;
QString m_fileToDownload;
};
#endif // DOWNLOAD_THREAD_H_INCLUDED

View File

@@ -1,8 +1,135 @@
#include <QtGlobal> #include <QtGlobal>
#include <QCoreApplication>
#include <QApplication>
#include <QByteArray>
#include <QProcess>
#include <QCommandLineParser>
#include <QStandardPaths>
#include <QSettings>
#include <QDir>
#include <QDebug>
#include <QThread>
#include "message_handler.h"
#include "commandline_parser.h"
#include "utils.h"
#include "update.h"
#include "mainwindow.h"
#include "System.h"
#include <DeviceController/interfaces.h>
#ifdef __linux__
#include <sys/sysinfo.h>
#endif
#ifdef PTU5
#define SERIAL_PORT "ttymxc2"
#else
#define SERIAL_PORT "ttyUSB0"
#endif
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;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
Q_UNUSED(argc); QByteArray const value = qgetenv("LC_ALL");
Q_UNUSED(argv); if (value != "C") {
qputenv("LC_ALL", "C");
}
// qputenv("XDG_RUNTIME_DIR", "/var/run/user/0");
openlog("ATB-UPDATE-DC-FIRMWARE", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
QApplication a(argc, argv);
QApplication::setApplicationName("ATBDownloadDCFirmware");
QApplication::setApplicationVersion(APP_VERSION);
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(LOG_NOTICE);
}
CommandLineParser parser;
parser.process(a);
parser.readSettings();
QString repositoryUrl = parser.repositoryUrl();
QString plugInDir = parser.plugInDir();
QString plugInName = parser.plugInName();
QString workingDir = parser.workingDir();
QString psaConfigDir = parser.psaConfigDir();
QString psaTariffDir = parser.psaTariffDir();
QString iniFileName = parser.iniFileName();
bool const dryRun = parser.dryRun();
bool const noUpdatePsaHardware = parser.noUpdatePsaHardware();
bool const showYoctoVersion = parser.yoctoVersion();
bool const showYoctoInstallStatus = parser.yoctoInstallStatus();
bool const showExtendedVersion = parser.extendedVersion();
bool const alwaysDownloadConfig = parser.alwaysDownloadConfig();
bool const alwaysDownloadDC = parser.alwaysDownloadDC();
QString const rtPath = QCoreApplication::applicationDirPath();
int const machineNr = read1stLineOfFile("/mnt/system_data/machine_nr");
int const customerNr = read1stLineOfFile("/mnt/system_data/cust_nr");
int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr");
QString const branchName = (zoneNr != 0)
? QString("zg1/zone%1").arg(zoneNr) : "master";
qInfo() << "pwd ......................" << rtPath;
qInfo() << "repositoryUrl ............" << repositoryUrl;
qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir;
qInfo() << "psaConfigDir ............." << psaConfigDir;
qInfo() << "psaTariffDir ............." << psaTariffDir;
qInfo() << "dryRun ..................." << dryRun;
qInfo() << "noUpdatePsaHardware ......" << noUpdatePsaHardware;
qInfo() << "alwaysDownloadConfig ....." << alwaysDownloadConfig;
qInfo() << "alwaysDownloadDC ........." << alwaysDownloadDC;
qInfo() << "showYoctoVersion ........." << showYoctoVersion;
qInfo() << "showYoctoInstallStatus ..." << showYoctoInstallStatus;
qInfo() << "showExtendedVersion ......" << showExtendedVersion;
qInfo() << "iniFileName .............." << iniFileName;
qInfo() << "extended-version ........." << APP_EXTENDED_VERSION;
qInfo() << "machineNr ................" << machineNr;
qInfo() << "customerNr ..............." << customerNr;
qInfo() << "zoneNr ..................." << zoneNr;
if (showExtendedVersion) {
printf(APP_EXTENDED_VERSION"\n");
return 0;
}
QString const &customerRepo = QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr));
QStringList filesToUpdate;
QThread::currentThread()->setObjectName("main thread");
qInfo() << "Main thread" << QThread::currentThreadId();
MainWindow mw;
mw.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
// mw.showFullScreen();
// qCritical() << "SHOW";
// mw.show();
return 0; return 0;
// return a.exec();
} }

View File

@@ -0,0 +1,352 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QMessageBox>
#include <QDebug>
#include <QScrollBar>
#include <QEvent>
#ifdef PTU5
#define SERIAL_PORT "ttymxc2"
#else
#define SERIAL_PORT "ttyUSB0"
#endif
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_serial(new QSerialPort(this))
, m_width(70) {
this->setStatusBar(new QStatusBar(this));
QFont f;
f.setStyleHint(QFont::Monospace);
f.setWeight(QFont::Bold);
f.setFamily("Misc Fixed");
f.setPixelSize(12);
this->statusBar()->setFont(f);
ui->setupUi(this);
openSerialPort();
//ui->updateProgress->setRange(0, 100);
//ui->updateProgress->reset();
#if 0
QStringList lst;
QString start = QDateTime::currentDateTime().toString(Qt::ISODate);
lst << QString("Start: ") + start.leftJustified(m_width-10);
lst << QString("").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("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("APISM version : %1").arg(m_worker->apismVersion()).leftJustified(m_width-3);
lst << QString("").leftJustified(m_width-3, '=');
ui->updateStatus->setText(lst.join('\n'));
ui->updateStatus->setEnabled(true);
// ui->updateStatus->installEventFilter(this);
m_startTimer = new QTimer(this);
connect(m_startTimer, SIGNAL(timeout()), m_worker, SLOT(start()));
m_startTimer->setSingleShot(true);
m_startTimer->start(1000);
m_exitTimer = new QTimer(this);
connect(m_exitTimer, SIGNAL(timeout()), ui->exit, SLOT(click()));
m_exitTimer->setSingleShot(true);
m_exitTimer->start(1800 * 1000);
connect(ui->exit, SIGNAL(clicked()),this,SLOT(onQuit()));
connect(m_worker, SIGNAL(disableExit()),this,SLOT(onDisableExit()));
connect(m_worker, SIGNAL(enableExit()),this,SLOT(onEnableExit()));
connect(m_worker, SIGNAL(stopStartTimer()),this,SLOT(onStopStartTimer()));
connect(m_worker, SIGNAL(restartExitTimer()),this,SLOT(onRestartExitTimer()));
connect(m_worker, SIGNAL(appendText(QString,QString)),this,SLOT(onAppendText(QString,QString)));
connect(m_worker, SIGNAL(showErrorMessage(QString,QString)),this, SLOT(onShowErrorMessage(QString,QString)));
connect(m_worker, SIGNAL(showStatusMessage(QString,QString)),this, SLOT(onShowStatusMessage(QString,QString)));
connect(m_worker, SIGNAL(showErrorMessage(QStringList)),this, SLOT(onShowErrorMessage(QStringList)));
connect(m_worker, SIGNAL(showStatusMessage(QString,QString)),this, SLOT(onShowStatusMessage(QString,QString)));
connect(m_worker, SIGNAL(replaceLast(QString,QString)),this,SLOT(onReplaceLast(QString,QString)));
connect(m_worker, SIGNAL(replaceLast(QStringList,QString)),this, SLOT(onReplaceLast(QStringList,QString)));
#endif
}
MainWindow::~MainWindow() {
//delete m_startTimer;
//delete m_exitTimer;
closeSerialPort();
delete ui;
}
bool MainWindow::openSerialPort() {
// const SettingsDialog::Settings p = m_settings->settings();
m_serial->setPortName(SERIAL_PORT);
m_serial->setBaudRate(QSerialPort::Baud115200);
m_serial->setDataBits(QSerialPort::DataBits::Data8);
m_serial->setParity(QSerialPort::Parity::NoParity);
m_serial->setStopBits(QSerialPort::StopBits::OneStop);
m_serial->setFlowControl(QSerialPort::FlowControl::NoFlowControl);
if (m_serial->open(QIODevice::ReadWrite)) {
//m_console->setEnabled(true);
//m_console->setLocalEchoEnabled(p.localEchoEnabled);
//m_ui->actionConnect->setEnabled(false);
//m_ui->actionDisconnect->setEnabled(true);
//m_ui->actionConfigure->setEnabled(false);
//showStatusMessage(tr("Connected to %1 : %2, %3, %4, %5, %6")
// .arg(p.name, p.stringBaudRate, p.stringDataBits,
// p.stringParity, p.stringStopBits, p.stringFlowControl));
return true;
} else {
//QMessageBox::critical(this, tr("Error"), m_serial->errorString());
//showStatusMessage(tr("Open error"));
}
return false;
}
bool MainWindow::closeSerialPort() {
if (m_serial->isOpen()) {
m_serial->close();
return true;
}
return false;
//m_console->setEnabled(false);
//m_ui->actionConnect->setEnabled(true);
//m_ui->actionDisconnect->setEnabled(false);
//m_ui->actionConfigure->setEnabled(true);
//showStatusMessage(tr("Disconnected"));
}
#if 0
void MainWindow::customEvent(QEvent *event) {
if (event->type() == ProgressEvent::type()) {
ProgressEvent *pevent = (ProgressEvent *)event;
int const progress = pevent->progressPercent();
QObject const *sender = pevent->sender();
if (sender == this) {
switch(progress) {
case 0: {
ui->updateProgress->reset();
} break;
case START_PROGRESS_LOOP: {
m_progressRunning = true;
ui->updateProgress->reset();
// m_progressValue = 10;
QApplication::postEvent(this, new ProgressEvent(this, 1));
} break;
case STOP_PROGRESS_LOOP: {
m_progressRunning = false;
// m_progressValue -= 10;
// m_worker->setProgress(m_progressValue/10);
} break;
default: {
if (m_progressRunning) {
// m_progressValue = progress;
ui->updateProgress->setValue(progress);
// ueberpruefen: hauptfenster schickt sich selber ein event
// QApplication::postEvent(this, new ProgressEvent(this, progress));
// QThread::msleep(500);
}}
}
} else
if (sender == m_worker) {
switch(progress) {
case 0: {
ui->updateProgress->reset();
} break;
case START_PROGRESS_LOOP: {
QApplication::postEvent(this, new ProgressEvent(this, START_PROGRESS_LOOP));
} break;
case STOP_PROGRESS_LOOP: {
QApplication::postEvent(this, new ProgressEvent(this, STOP_PROGRESS_LOOP));
} break;
default:{
ui->updateProgress->setValue(progress);
}}
} else {
qCritical() << "!!! UNKNOWN SENDER !!!";
}
}
QThread::yieldCurrentThread();
}
void MainWindow::onStopStartTimer() {
m_startTimer->stop();
}
void MainWindow::onDisableExit() {
ui->exit->setEnabled(false);
}
void MainWindow::onEnableExit() {
ui->exit->setEnabled(true);
}
void MainWindow::onRestartExitTimer() {
m_exitTimer->stop();
m_exitTimer->start(5 * 1000);
scrollDownTextEdit();
ui->updateStatus->setEnabled(false);
}
void MainWindow::onQuit() {
m_exitTimer->stop();
int errorCode = 0;
qCritical()
<< QString("ON QUIT: CURRENT STEP %1")
.arg(m_worker->getSmap()[m_worker->currentStep()]);
// TODO: replace SEND_LAST_VERSION with UPDATE_SUCCEEDED
if (m_worker->currentStep() != Worker::UPDATE_STEP::SEND_LAST_VERSION) {
errorCode = -1;
}
qCritical() << QString("ON QUIT: EXIT CODE %1").arg(errorCode);
qApp->exit(errorCode);
}
void MainWindow::scrollDownTextEdit() {
// Utils::printInfoMsg(QString("SCROLL-DOWN-TEXT_EDIT CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
ui->updateStatus->setEnabled(true);
QTextCursor tmpCursor = ui->updateStatus->textCursor();
tmpCursor.movePosition(QTextCursor::End);
ui->updateStatus->setTextCursor(tmpCursor);
ui->updateStatus->ensureCursorVisible();
}
void MainWindow::onAppendText(QString text, QString suffix) {
// Utils::printInfoMsg(QString("ON APPEND CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
QString editText = ui->updateStatus->toPlainText();
scrollDownTextEdit();
if (!suffix.isNull() && suffix.size() > 0) {
//qInfo() << "TEXT" << text << "SUFFIX" << suffix;
if (suffix == Worker::UPDATE_STEP_SUCCESS || suffix == Worker::UPDATE_STEP_FAIL) {
ui->updateStatus->insertPlainText(QString("\n").leftJustified(m_width-3, '=') + " ");
// editText += QString("\n").leftJustified(m_width-3, '=');
// editText += " ";
}
QString const &add = (QString("\n") + text).leftJustified(m_width - (2 + suffix.size())) + suffix;
ui->updateStatus->insertPlainText(add);
// editText += add;
} else {
QString const &add = text.leftJustified(m_width-9);
ui->updateStatus->insertPlainText(add);
//editText += add;
}
// debug
// QString editText = ui->updateStatus->toPlainText();
// Utils::printLineEditInfo(editText.split('\n', QString::SplitBehavior::SkipEmptyParts));
// ui->updateStatus->setText(editText.trimmed());
scrollDownTextEdit();
}
void MainWindow::onReplaceLast(QStringList newTextLines, QString suffix) {
// Utils::printInfoMsg(QString("ON REPLACE LAST (LIST) CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
int const s = newTextLines.size();
if (s > 0) {
QString editText = ui->updateStatus->toPlainText();
QStringList lines = editText.split('\n', QString::SplitBehavior::SkipEmptyParts);
QString newText;
if (lines.size() >= s) {
for (int i = 0; i < s; ++i) {
lines.removeLast();
}
if (lines.size() > 0) {
newText = lines.join('\n');
newText += '\n';
}
QStringList newLines;
for (int i = 0; i < s; ++i) {
if (i == 0 && !suffix.isNull() && suffix.size() > 0 && suffix != "\n") {
newLines += Utils::rstrip(newTextLines.at(i).leftJustified(m_width-10) + suffix);
} else {
newLines += Utils::rstrip(newTextLines.at(i).leftJustified(m_width-10));
}
}
lines += newLines;
newText += newLines.join(' ');
}
ui->updateStatus->setText(newText);
Utils::printLineEditInfo(lines);
scrollDownTextEdit();
}
}
void MainWindow::onReplaceLast(QString text, QString suffix) {
// Utils::printInfoMsg(QString("ON REPLACE LAST (TEXT) CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
QString editText = ui->updateStatus->toPlainText();
QStringList lines = editText.split('\n', QString::SplitBehavior::SkipEmptyParts);
if (lines.size() > 0) {
// removing the last line is really meant for refreshing the last line
// with a string very similar than the original one, typically only
// followed by a suffix.
if (lines.last().contains(text)) {
lines.removeLast();
}
if (!suffix.isNull() && suffix.size() > 0 && suffix != "\n") {
QString const add = text.leftJustified(m_width-10) + suffix;
if (!add.isEmpty()) {
lines += text.leftJustified(m_width-10) + suffix;
}
} else {
QString const add = text.leftJustified(m_width-10);
if (!add.isEmpty()) {
lines += text.leftJustified(m_width-10);
}
}
}
Utils::printLineEditInfo(lines);
ui->updateStatus->setText(lines.join('\n').trimmed());
scrollDownTextEdit();
}
void MainWindow::onShowMessage(QString title, QString text) {
this->statusBar()->clearMessage();
this->statusBar()->showMessage( // timeout: 10000
QString(title + " " + text).leftJustified(80, ' '), 10000);
}
void MainWindow::onShowErrorMessage(QString title, QString text) {
onShowMessage(title, text);
}
void MainWindow::onShowStatusMessage(QString title, QString text) {
onShowMessage(title, text);
}
void MainWindow::onShowErrorMessage(QStringList lst) {
if (lst.size() >= 2) {
onShowMessage(lst.at(0), lst.at(1));
}
if (lst.size() == 1) {
onShowMessage(lst.at(0), "");
}
}
void MainWindow::onShowStatusMessage(QStringList lst) {
if (lst.size() >= 2) {
onShowMessage(lst.at(0), lst.at(1));
}
if (lst.size() == 1) {
onShowMessage(lst.at(0), "");
}
}
#endif

View File

@@ -0,0 +1,58 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include <QStatusBar>
#include <QWidget>
#include <QSerialPort>
#include <QSerialPortInfo>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
//void onAppendText(QString, QString suffix = "");
//void onReplaceLast(QStringList, QString suffix = "");
//void onReplaceLast(QString, QString suffix = "");
//void onShowErrorMessage(QString, QString);
//void onShowStatusMessage(QString, QString);
//void onShowErrorMessage(QStringList);
//void onShowStatusMessage(QStringList);
//void onStopStartTimer();
//void onRestartExitTimer();
//void onEnableExit();
//void onDisableExit();
signals:
private slots:
// void onQuit();
private:
// void scrollDownTextEdit();
// void onShowMessage(QString, QString);
bool openSerialPort();
bool closeSerialPort();
Ui::MainWindow *ui;
QSerialPort *m_serial;
// Worker *m_worker;
int const m_width;
// QTimer *m_startTimer;
// QTimer *m_exitTimer;
// bool m_progressRunning;
//int m_progressValue;
// UpdateDcEvent::UpdateStep m_updateStep;
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>480</height>
</rect>
</property>
<property name="font">
<font>
<family>Source Code Pro</family>
</font>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>781</width>
<height>441</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="3" colspan="2">
<widget class="QTextEdit" name="updateStatus">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<family>Misc Fixed</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

View File

View File

View File

View File

@@ -0,0 +1,438 @@
#include "update.h"
#include <QCoreApplication>
#include <QFile>
#include <QTemporaryFile>
#include <QDebug>
#include <QTextStream>
#include <QRegularExpression>
#include <QRegExp>
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
#include "unistd.h"
#endif
#include <DeviceController/interfaces.h>
#include <QSharedMemory>
#include <QScopedPointer>
#include <QDir>
#include <QThread>
#include <QDateTime>
#include <QPluginLoader>
#include <QMap>
#define UPDATE_OPKG (1)
#define UPDATE_DC (0)
static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
{"57600" , 4}, {"115200" , 5}
};
QPluginLoader Update::pluginLoader;
hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
hwinf *hw = nullptr;
if (plugInDir.exists()) {
QString pluginLibName(fname);
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
QFileInfo info(pluginLibName);
if (info.exists()) {
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
pluginLoader.setFileName(pluginLibName);
// static QPluginLoader pluginLoader(pluginLibName);
if (!pluginLoader.load()) {
qCritical() << "in directory" << plugInDir.absolutePath();
qCritical() << "cannot load plugin" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString();
return nullptr;
}
qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString();
return nullptr;
}
QObject *plugin = pluginLoader.instance();
if (!plugin) {
qCritical() << "cannot start instance";
return nullptr;
}
if (! (hw = qobject_cast<hwinf *>(plugin))) {
qCritical() << "cannot cast plugin" << plugin << "to hwinf";
return nullptr;
}
} else {
qCritical() << pluginLibName << "does not exist";
return nullptr;
}
} else {
qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist";
return nullptr;
}
return hw;
}
bool Update::unloadDCPlugin() {
if (pluginLoader.unload()) {
qCritical() << "unloaded plugin" << pluginLoader.fileName();
// Note: will re-instantiate the library !
// QObject *rootObject = pluginLoader.instance();
// if (rootObject) {
// qCritical() << "reloaded plugin: root object again available";
// return false;
// }
// qCritical()unloaded plugin: root object gone";
return true;
}
return false;
}
class hwapi;
Update::Update(QString customerRepository,
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
bool dryRun,
QObject *parent,
char const *serialInterface,
char const *baudrate)
: QObject(parent)
, 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_dryRun(dryRun)
, m_sys_areDCdataValid(false) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin 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() {
unloadDCPlugin();
}
bool Update::doUpdate(QStringList const &filesToWorkOn, bool usbStickDetected) {
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);
}
bool res = false;
QList<QString>::const_iterator it;
for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) {
QString const &fToWorkOn = usbStickDetected ? QDir::cleanPath(it->trimmed())
: QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
int i = fToWorkOn.indexOf("DC2C_print", Qt::CaseInsensitive);
int const templateIdx = fToWorkOn.mid(i).midRef(10, 2).toInt();
if ((templateIdx < 1) || (templateIdx > 32)) {
qCritical() << "WRONG TEMPLATE INDEX" << templateIdx;
res = false;
} else {
if ((res = updatePrinterTemplate(templateIdx, fToWorkOn))) {
qCritical() <<
QString("DOWNLOADED PRINTER TEMPLATE %1 WITH INDEX=%2")
.arg(fToWorkOn)
.arg(templateIdx);
}
}
} else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateCashConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn);
}
} else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateConfig(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn);
}
} else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateDeviceConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn);
}
} else {
qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn;
res = false;
}
}
return res;
}
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);
}

148
DownloadDCFirmware/update.h Normal file
View File

@@ -0,0 +1,148 @@
#ifndef UPDATE_H_INCLUDED
#define UPDATE_H_INCLUDED
#include <QObject>
#include <QString>
#include <QFile>
#include <QDir>
#include <QByteArray>
#include <QProcess>
#include <QPluginLoader>
#include <initializer_list>
#include <DeviceController/interfaces.h>
#ifdef PTU5
#define SERIAL_PORT "ttymxc2"
#else
#define SERIAL_PORT "ttyUSB0"
#endif
class Update : public QObject {
Q_OBJECT
hwinf *m_hw = nullptr;
char const *m_serialInterface;
char const *m_baudrate;
QString m_customerRepository;
QString m_customerNrStr;
QString m_branchName;
QString m_pluginName;
QString m_workingDir;
bool m_maintenanceMode;
bool m_dryRun;
bool m_sys_areDCdataValid;
static QPluginLoader pluginLoader;
public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
enum class FileTypeJson {CONFIG=1, DEVICE=2, CASH=3, SERIAL=4, TIME=5, PRINTER=6};
static hwinf *loadDCPlugin(QDir const &plugInDir, QString const &fn);
static bool unloadDCPlugin();
static QStringList split(QString line, QChar sep = ',');
explicit Update(QString customerRepository,
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
bool dryRun = false,
QObject *parent = nullptr,
char const *serialInterface = SERIAL_PORT,
char const *baudrate = "115200");
virtual ~Update() override;
bool doUpdate(QStringList const &jsonFilesToDownload, bool usbStickDetected = false);
bool updatePrinterTemplate(int templateIdx, QString fname) const;
bool updateConfig(QString jsFileToSendToDC);
bool updateCashConf(QString jsFileToSendToDC);
bool updateDeviceConf(QString jsFileToSendToDC);
bool downloadJson(enum FileTypeJson type, int templateIdx,
QString jsFileToSendToDC) const;
QString getFileVersion(QString const& jsonFileName);
bool checkJsonVersions(QStringList const& jsonFileNames =
QStringList(
QList(
std::initializer_list<QString>{
QString("etc/psa_config/DC2C_conf.json"),
QString("etc/psa_config/DC2C_cash.json"),
QString("etc/psa_config/DC2C_device.json"),
QString("etc/psa_config/DC2C_print01.json"),
QString("etc/psa_config/DC2C_print02.json"),
QString("etc/psa_config/DC2C_print03.json"),
QString("etc/psa_config/DC2C_print04.json"),
QString("etc/psa_config/DC2C_print05.json"),
QString("etc/psa_config/DC2C_print06.json"),
QString("etc/psa_config/DC2C_print07.json"),
QString("etc/psa_config/DC2C_print08.json"),
QString("etc/psa_config/DC2C_print09.json"),
QString("etc/psa_config/DC2C_print10.json"),
QString("etc/psa_config/DC2C_print11.json"),
QString("etc/psa_config/DC2C_print12.json"),
QString("etc/psa_config/DC2C_print13.json"),
QString("etc/psa_config/DC2C_print14.json"),
QString("etc/psa_config/DC2C_print15.json"),
QString("etc/psa_config/DC2C_print16.json"),
QString("etc/psa_config/DC2C_print17.json"),
QString("etc/psa_config/DC2C_print18.json"),
QString("etc/psa_config/DC2C_print19.json"),
QString("etc/psa_config/DC2C_print20.json"),
QString("etc/psa_config/DC2C_print21.json"),
QString("etc/psa_config/DC2C_print22.json"),
QString("etc/psa_config/DC2C_print23.json"),
QString("etc/psa_config/DC2C_print24.json"),
QString("etc/psa_config/DC2C_print25.json"),
QString("etc/psa_config/DC2C_print26.json"),
QString("etc/psa_config/DC2C_print27.json"),
QString("etc/psa_config/DC2C_print28.json"),
QString("etc/psa_config/DC2C_print29.json"),
QString("etc/psa_config/DC2C_print30.json"),
QString("etc/psa_config/DC2C_print31.json"),
QString("etc/psa_config/DC2C_print32.json")})));
/*
bool checkDownloadedJsonVersions(QStringList const& jsonFileNames);
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 const branchName() const { return m_branchName; }
//QString repositoryPath() { return m_repositoryPath; }
//QString const repositoryPath() const { return m_repositoryPath; }
private:
static QString jsonType(enum FileTypeJson type);
bool openSerial(int br, QString baudrate, QString comPort) const;
void closeSerial() const;
bool isSerialOpen() const;
bool resetDeviceController() const;
QByteArray loadBinaryDCFile(QString filename) const;
bool downloadBinaryToDC(QString const &bFile) const;
bool updateBinary(QString const &fileToSendToDC);
QStringList getDcSoftAndHardWareVersion();
QString getFileVersion(QString const& jsonFile);
private slots:
void readyReadStandardOutput();
void readyReadStandardError();
void finished(int exitCode, QProcess::ExitStatus exitStatus);
void onReportDCDownloadStatus(QString const &status);
void onReportDCDownloadSuccess(QString const &msg);
void onReportDCDownloadFailure(QString const &errorMsg);
*/
};
#endif // UPDATE_H_INCLUDED

View File

@@ -0,0 +1,13 @@
#include "worker_thread.h"
WorkerThread::WorkerThread(QObject *parent)
: QThread(parent) {
}
WorkerThread::~WorkerThread() {
}
void WorkerThread::run() {
}

View File

@@ -0,0 +1,20 @@
#ifndef WORKER_THREAD_H_INCLUDED
#define WORKER_THREAD_H_INCLUDED
#include <QThread>
class WorkerThread : public QThread {
Q_OBJECT
public:
explicit WorkerThread(QObject *parent = nullptr);
~WorkerThread();
private:
void run() override;
bool m_quit = false;
};
#endif // WORKER_THREAD_H_INCLUDED

View File

@@ -24,7 +24,7 @@ INCLUDEPATH += \
plugins \ plugins \
$${INCLUDEINTERFACES} \ $${INCLUDEINTERFACES} \
$${_PRO_FILE_PWD_}/../UpdatePTUDevCtrl \ $${_PRO_FILE_PWD_}/../UpdatePTUDevCtrl \
$${_PRO_FILE_PWD_}/../../ATBUpdateTool/common/include $${_PRO_FILE_PWD_}/../common/include
CONFIG += c++17 CONFIG += c++17
@@ -81,16 +81,17 @@ SOURCES += \
../UpdatePTUDevCtrl/message_handler.cpp \ ../UpdatePTUDevCtrl/message_handler.cpp \
../UpdatePTUDevCtrl/commandline_parser.cpp \ ../UpdatePTUDevCtrl/commandline_parser.cpp \
update.cpp \ update.cpp \
../../ATBUpdateTool/common/src/System.cpp ../common/src/System.cpp
HEADERS += \ HEADERS += \
../UpdatePTUDevCtrl/message_handler.h \ ../UpdatePTUDevCtrl/message_handler.h \
../UpdatePTUDevCtrl/commandline_parser.h \ ../UpdatePTUDevCtrl/commandline_parser.h \
update.h \ update.h \
../../ATBUpdateTool/common/include/System.h ../common/include/System.h
OTHER_FILES += \ OTHER_FILES += \
ATBDownloadDCJsonFiles.ini ATBDownloadDCJsonFiles.ini \
../ATBUpdateTool.ini
########################################################################################## ##########################################################################################

View File

@@ -15,6 +15,7 @@
#include "commandline_parser.h" #include "commandline_parser.h"
#include "utils.h" #include "utils.h"
#include "update.h" #include "update.h"
#include "System.h"
#include <DeviceController/interfaces.h> #include <DeviceController/interfaces.h>
@@ -68,6 +69,8 @@ int main(int argc, char **argv) {
QString plugInDir = parser.plugInDir(); QString plugInDir = parser.plugInDir();
QString plugInName = parser.plugInName(); QString plugInName = parser.plugInName();
QString workingDir = parser.workingDir(); QString workingDir = parser.workingDir();
QString psaConfigDir = parser.psaConfigDir();
QString psaTariffDir = parser.psaTariffDir();
QString iniFileName = parser.iniFileName(); QString iniFileName = parser.iniFileName();
bool const dryRun = parser.dryRun(); bool const dryRun = parser.dryRun();
bool const noUpdatePsaHardware = parser.noUpdatePsaHardware(); bool const noUpdatePsaHardware = parser.noUpdatePsaHardware();
@@ -90,6 +93,8 @@ int main(int argc, char **argv) {
qInfo() << "plugInDir ................" << plugInDir; qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName; qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir; qInfo() << "workingDir ..............." << workingDir;
qInfo() << "psaConfigDir ............." << psaConfigDir;
qInfo() << "psaTariffDir ............." << psaTariffDir;
qInfo() << "dryRun ..................." << dryRun; qInfo() << "dryRun ..................." << dryRun;
qInfo() << "noUpdatePsaHardware ......" << noUpdatePsaHardware; qInfo() << "noUpdatePsaHardware ......" << noUpdatePsaHardware;
qInfo() << "alwaysDownloadConfig ....." << alwaysDownloadConfig; qInfo() << "alwaysDownloadConfig ....." << alwaysDownloadConfig;
@@ -108,28 +113,31 @@ int main(int argc, char **argv) {
return 0; return 0;
} }
QString const customerRepo = QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr)); QString const &customerRepo = QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr));
qCritical() << "Using customer repository" << customerRepo;
// always execute contents of opkg_commands-file
QStringList filesToUpdate; QStringList filesToUpdate;
QDir dir(QDir::cleanPath(customerRepo + QDir::separator() + "etc/psa_config")); // etc/psa_config: located under mount-path
std::optional<QString> mountPath = System::checkForUSBStick(psaConfigDir);
if (dir.exists()) { if (mountPath.has_value()) {
QStringList jsons = dir.entryList(QStringList() << "DC2C*.json", QDir::Files); filesToUpdate = System::getJsonFilesOnUsbStick(mountPath.value());
if (!jsons.isEmpty()) {
for (QStringList::size_type i=0; i<jsons.size(); ++i) {
filesToUpdate << QDir::cleanPath(QString("etc/psa_config/") + jsons.at(i));
}
}
} else { } else {
qCritical() << "DIRECTORY" << dir << "DOES NOT EXIST"; qCritical() << "Using customer repository" << customerRepo;
return -1;
QDir dir(QDir::cleanPath(customerRepo + QDir::separator() + "etc/psa_config"));
if (dir.exists()) {
QStringList jsons = dir.entryList(QStringList() << "DC2C*.json", QDir::Files);
if (!jsons.isEmpty()) {
for (QStringList::size_type i=0; i<jsons.size(); ++i) {
filesToUpdate << QDir::cleanPath(QString("etc/psa_config/") + jsons.at(i));
}
}
} else {
qCritical() << "DIRECTORY" << dir << "DOES NOT EXIST";
return -1;
}
} }
qCritical() << "JSON FILES TO UPDATE" << filesToUpdate; // qCritical() << "JSON FILES TO UPDATE" << filesToUpdate;
Update update(customerRepo, Update update(customerRepo,
QString::number(customerNr), QString::number(customerNr),
@@ -138,8 +146,13 @@ int main(int argc, char **argv) {
plugInName, plugInName,
workingDir); workingDir);
update.doUpdate(filesToUpdate); update.doUpdate(filesToUpdate, mountPath.has_value());
update.checkJsonVersions();
//update.checkJsonVersions(filesToUpdate);
if (mountPath.has_value()) {
System::umountUSBStick();
}
//return a.exec();
return 0; return 0;
} }

View File

@@ -46,7 +46,7 @@ hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
qCritical() << "in directory" << plugInDir.absolutePath(); qCritical() << "in directory" << plugInDir.absolutePath();
qCritical() << "cannot load plugin" << pluginLoader.fileName(); qCritical() << "cannot load plugin" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
exit(-1); return nullptr;
} }
qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath(); qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
@@ -54,25 +54,25 @@ hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
if (!pluginLoader.isLoaded()) { if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
exit(-2); return nullptr;
} }
QObject *plugin = pluginLoader.instance(); QObject *plugin = pluginLoader.instance();
if (!plugin) { if (!plugin) {
qCritical() << "cannot start instance"; qCritical() << "cannot start instance";
exit(-3); return nullptr;
} }
if (! (hw = qobject_cast<hwinf *>(plugin))) { if (! (hw = qobject_cast<hwinf *>(plugin))) {
qCritical() << "cannot cast plugin" << plugin << "to hwinf"; qCritical() << "cannot cast plugin" << plugin << "to hwinf";
exit(-4); return nullptr;
} }
} else { } else {
qCritical() << pluginLibName << "does not exist"; qCritical() << pluginLibName << "does not exist";
exit(-5); return nullptr;
} }
} else { } else {
qCritical() << "plugins directory" << plugInDir.absolutePath() qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist"; << "does not exist";
exit(-6); return nullptr;
} }
return hw; return hw;
} }
@@ -131,53 +131,31 @@ Update::Update(QString customerRepository,
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_sys_areDCDataValid ..." qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_sys_areDCDataValid ..."
<< m_sys_areDCdataValid; << m_sys_areDCdataValid;
#if 0
QObject const *obj = m_hw->getAPI();
Q_ASSERT(obj != nullptr);
QDebug critical = qCritical();
critical << "connect() to onReportDCDownloadStatus() ...";
if (!connect(obj,
SIGNAL(hwapi_reportDCDownloadStatus(QString const&)),
this,
SLOT(onReportDCDownloadStatus(QString const &)))) {
critical << "FAILED";
} else critical << "DONE";
critical = qCritical();
critical << "connect() to onReportDCDownloadSuccess() ...";
if (!connect(obj,
SIGNAL(hwapi_reportDCDownloadSuccess(QString const&)), this,
SLOT(onReportDCDownloadSuccess(QString const &)))) {
critical << "FAILED";
} else critical << "DONE";
critical = qCritical();
critical << "connect() to onReportDCDownloadFailure() ...";
if (!connect(obj,
SIGNAL(hwapi_reportDCDownloadFailure(QString const &)), this,
SLOT(onReportDCDownloadFailure(QString const &)))) {
critical << "FAILED";
} else critical << "DONE";
#endif
} }
} }
Update::~Update() { Update::~Update() {
// unloadDCPlugin(); unloadDCPlugin();
} }
bool Update::doUpdate(QStringList const &filesToWorkOn) { bool Update::doUpdate(QStringList const &filesToWorkOn, bool usbStickDetected) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return false;
}
int tries = 20; int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) { while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid // must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) { if (--tries < 0) {
qCritical() << "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED"; qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED";
return false; return false;
} }
qCritical() << "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")"; qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")";
m_hw->dc_autoRequest(true); m_hw->dc_autoRequest(true);
QThread::msleep(500); QThread::msleep(500);
} }
@@ -186,7 +164,8 @@ bool Update::doUpdate(QStringList const &filesToWorkOn) {
QList<QString>::const_iterator it; QList<QString>::const_iterator it;
for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) { for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) {
QString const &fToWorkOn = QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed()); QString const &fToWorkOn = usbStickDetected ? QDir::cleanPath(it->trimmed())
: QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive) if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true; res = true;
@@ -205,19 +184,16 @@ bool Update::doUpdate(QStringList const &filesToWorkOn) {
} }
} else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive) } else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
if ((res = updateCashConf(fToWorkOn))) { if ((res = updateCashConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn); qCritical() << QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn);
} }
} else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive) } else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true; if ((res = updateConfig(fToWorkOn))) {
if ((res= updateConfig(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn); qCritical() << QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn);
} }
} else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive) } else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
if ((res = updateDeviceConf(fToWorkOn))) { if ((res = updateDeviceConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn); qCritical() << QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn);
} }
@@ -230,13 +206,37 @@ bool Update::doUpdate(QStringList const &filesToWorkOn) {
return res; return res;
} }
bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) { 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) { for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
uint8_t jsonNr = 0; uint8_t jsonNr = 0;
QString const &fName = jsonFileNames[i]; 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")) { if (fName.endsWith("conf.json")) {
jsonNr = 1; jsonNr = 1;
} else } else
@@ -254,31 +254,46 @@ bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) {
bool ok = false; bool ok = false;
int n = captured.toInt(&ok); int n = captured.toInt(&ok);
if (ok) { if (ok) {
jsonNr = n + 4; // note: use 5 (instead of 4 -> index has been shifted)
jsonNr = n + 5;
} }
} }
} }
if (jsonNr != 0) { if (jsonNr != 0) {
#if 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); m_hw->sys_requestJsonVersions(jsonNr);
QThread::msleep(500); QThread::msleep(500);
char buf[64]; char buf[64];
memset(buf, 0x00, sizeof(buf)); memset(buf, 0x00, sizeof(buf));
m_hw->sys_getJsonVersions(jsonNr, buf); m_hw->sys_getJsonVersions(jsonNr, buf);
buf[sizeof(buf)-1] = '\0'; buf[16] = '\0'; // the DC only handles 16 bytes
QString const installedVersion(buf); static const QByteArray cb(16, (char)0xff);
QString const installedVersion(QString::fromStdString(buf));
QString const fileVersion = getFileVersion(jsonFileNames[i]); QString const fileVersion = getFileVersion(jsonFileNames[i]);
qCritical() << "installed version:" << installedVersion; QFileInfo fi(jsonFileNames[i]);
qCritical() << " file version:" << fileVersion;
qCritical() << endl;
qCritical() << " json request nr:" << jsonNr;
if (installedVersion == fileVersion) { 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;
} }
#endif
} else { } else {
qCritical() << "CANNOT FIND JSON-NR FOR" << fName; qCritical() << "CANNOT FIND JSON-NR FOR" << fName;
@@ -288,6 +303,39 @@ bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) {
return false; 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, bool Update::downloadJson(enum FileTypeJson type,
int templateIdx, int templateIdx,
QString jsFileToSendToDC) const { QString jsFileToSendToDC) const {
@@ -366,10 +414,6 @@ bool Update::downloadJson(enum FileTypeJson type,
} }
} }
m_hw->dc_autoRequest(false);
qDebug() << "SET AUTO-REQUEST=FALSE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
return ret; return ret;
} }

View File

@@ -9,6 +9,8 @@
#include <QProcess> #include <QProcess>
#include <QPluginLoader> #include <QPluginLoader>
#include <initializer_list>
#include <DeviceController/interfaces.h> #include <DeviceController/interfaces.h>
#ifdef PTU5 #ifdef PTU5
@@ -56,7 +58,7 @@ public:
virtual ~Update() override; virtual ~Update() override;
bool doUpdate(QStringList const &jsonFilesToDownload); bool doUpdate(QStringList const &jsonFilesToDownload, bool usbStickDetected = false);
bool updatePrinterTemplate(int templateIdx, QString fname) const; bool updatePrinterTemplate(int templateIdx, QString fname) const;
bool updateConfig(QString jsFileToSendToDC); bool updateConfig(QString jsFileToSendToDC);
@@ -67,7 +69,46 @@ public:
QString jsFileToSendToDC) const; QString jsFileToSendToDC) const;
bool checkDownloadedJsonVersions(QStringList const& jsonFileNames); QString getFileVersion(QString const& jsonFileName);
bool checkJsonVersions(QStringList const& jsonFileNames =
QStringList(
QList(
std::initializer_list<QString>{
QString("etc/psa_config/DC2C_conf.json"),
QString("etc/psa_config/DC2C_cash.json"),
QString("etc/psa_config/DC2C_device.json"),
QString("etc/psa_config/DC2C_print01.json"),
QString("etc/psa_config/DC2C_print02.json"),
QString("etc/psa_config/DC2C_print03.json"),
QString("etc/psa_config/DC2C_print04.json"),
QString("etc/psa_config/DC2C_print05.json"),
QString("etc/psa_config/DC2C_print06.json"),
QString("etc/psa_config/DC2C_print07.json"),
QString("etc/psa_config/DC2C_print08.json"),
QString("etc/psa_config/DC2C_print09.json"),
QString("etc/psa_config/DC2C_print10.json"),
QString("etc/psa_config/DC2C_print11.json"),
QString("etc/psa_config/DC2C_print12.json"),
QString("etc/psa_config/DC2C_print13.json"),
QString("etc/psa_config/DC2C_print14.json"),
QString("etc/psa_config/DC2C_print15.json"),
QString("etc/psa_config/DC2C_print16.json"),
QString("etc/psa_config/DC2C_print17.json"),
QString("etc/psa_config/DC2C_print18.json"),
QString("etc/psa_config/DC2C_print19.json"),
QString("etc/psa_config/DC2C_print20.json"),
QString("etc/psa_config/DC2C_print21.json"),
QString("etc/psa_config/DC2C_print22.json"),
QString("etc/psa_config/DC2C_print23.json"),
QString("etc/psa_config/DC2C_print24.json"),
QString("etc/psa_config/DC2C_print25.json"),
QString("etc/psa_config/DC2C_print26.json"),
QString("etc/psa_config/DC2C_print27.json"),
QString("etc/psa_config/DC2C_print28.json"),
QString("etc/psa_config/DC2C_print29.json"),
QString("etc/psa_config/DC2C_print30.json"),
QString("etc/psa_config/DC2C_print31.json"),
QString("etc/psa_config/DC2C_print32.json")})));
/* /*
bool checkDownloadedJsonVersions(QStringList const& jsonFileNames); bool checkDownloadedJsonVersions(QStringList const& jsonFileNames);

View File

@@ -119,7 +119,29 @@ DEFINES += QT_DEPRECATED_WARNINGS
# : Improve output of GUI/Console and messages sent to ISMAS. # : Improve output of GUI/Console and messages sent to ISMAS.
# : Fix: do not send the json-files to dc in any case. Bug introduced # : Fix: do not send the json-files to dc in any case. Bug introduced
# when pulling new branch, but branch already existed locally. # when pulling new branch, but branch already existed locally.
VERSION="1.4.6" # 1.4.6 : No exit()-call if loading CA-plugin fails.
# Check m_hw (pointer to CA-(Slave)Plugin) before its use.
# Only exit() if firmware is configured to be possibly updated, but
# loading the CA-plugin failed.
# 1.4.7 : Read Json-file versions of Json-files actually loaded into DC.
# 1.4.8 : Improve reading Json-file versions of Json-files actually loaded
# in DC. If available, show version info instead of blob-info of
# Json file.
# 1.4.9 : Improve ISMAS output: add messages for JSON downloads.
# Do not send CHECK_ISMAS_TRIGGER_SUCCESS to ISMAS for an automatic
# update.
# In case there is an automatic update (00:00-04:00) use M0100 instead
# of U0002.
# 1.4.10 : Fix: for the time being, never set the autoRequest-flag to false.
# 1.4.11 : Fix: remove hard-coded path to git-repos of gitea in mimbach. Read
# from ATBUpdateTool.ini the url for the gitrepositories.
# 1.5.0 : Use ptu-config.atb-comm.de (given in ini-file) as new server for
# customer repositories.
# Fix: allow empty lines in opkg_commands.
# 1.5.1 : Fix: do not use cleanPath() on a url-address.
# 1.5.2 : Remove .ipk and .gz files in /var/cache/opkg.
# 1.5.3 : Build customer_(id) name without right justification.
VERSION="1.5.3"
# 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

@@ -60,6 +60,16 @@ CommandLineParser::CommandLineParser()
QStringList() << "working-directory" << "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(
QCommandLineOption(
QStringList() << "psa-config-directory" << "psa-config-directory",
QCoreApplication::translate("main", "config directory of json-files sent to dc."),
QCoreApplication::translate("main", "directory")))
, m_psaTariffDirectoryOption(
QCommandLineOption(
QStringList() << "psa-tariff-directory" << "psa-tariff-directory",
QCoreApplication::translate("main", "tariff directory of tariff-json-files."),
QCoreApplication::translate("main", "directory")))
, m_dryRunOption( , m_dryRunOption(
QCommandLineOption( QCommandLineOption(
QStringList() << "d" << "dry-run", QStringList() << "d" << "dry-run",
@@ -111,6 +121,12 @@ void CommandLineParser::configure() {
m_workingDirectoryOption.setDefaultValue("/opt/app/tools/atbupdate/"); m_workingDirectoryOption.setDefaultValue("/opt/app/tools/atbupdate/");
m_parser.addOption(m_workingDirectoryOption); m_parser.addOption(m_workingDirectoryOption);
m_psaConfigDirectoryOption.setDefaultValue("etc/psa_config/");
m_parser.addOption(m_psaConfigDirectoryOption);
m_psaTariffDirectoryOption.setDefaultValue("etc/psa_tariff/");
m_parser.addOption(m_psaTariffDirectoryOption);
m_dryRunOption.setDefaultValue("false"); m_dryRunOption.setDefaultValue("false");
m_parser.addOption(m_dryRunOption); m_parser.addOption(m_dryRunOption);
@@ -151,6 +167,12 @@ void CommandLineParser::readSettings() {
if (key.contains("working-directory")) { if (key.contains("working-directory")) {
m_workingDir = v.toString(); m_workingDir = v.toString();
} else } else
if (key.contains("psa-config-directory")) {
m_psaConfigDir = v.toString();
} else
if (key.contains("psa-tariff-directory")) {
m_psaTariffDir = v.toString();
} else
if (key.contains("dry-run")) { if (key.contains("dry-run")) {
m_dryRun = (v.toBool() ? "true" : "false"); m_dryRun = (v.toBool() ? "true" : "false");
} else } else
@@ -207,6 +229,20 @@ QString CommandLineParser::plugInName() {
return m_plugInName; return m_plugInName;
} }
QString CommandLineParser::psaConfigDir() {
if (m_parser.isSet(m_psaConfigDirectoryOption)) {
m_psaConfigDir = m_parser.value(m_psaConfigDirectoryOption);
}
return m_psaConfigDir;
}
QString CommandLineParser::psaTariffDir() {
if (m_parser.isSet(m_psaTariffDirectoryOption)) {
m_psaTariffDir = m_parser.value(m_psaTariffDirectoryOption);
}
return m_psaTariffDir;
}
QString CommandLineParser::workingDir() { QString CommandLineParser::workingDir() {
if (m_parser.isSet(m_workingDirectoryOption)) { if (m_parser.isSet(m_workingDirectoryOption)) {
m_workingDir = m_parser.value(m_workingDirectoryOption); m_workingDir = m_parser.value(m_workingDirectoryOption);

View File

@@ -11,6 +11,8 @@ class CommandLineParser : public QCommandLineParser {
QString m_plugInDir; QString m_plugInDir;
QString m_plugInName; QString m_plugInName;
QString m_workingDir; QString m_workingDir;
QString m_psaConfigDir;
QString m_psaTariffDir;
QString m_dryRun; QString m_dryRun;
QString m_noUpdatePsaHardware; QString m_noUpdatePsaHardware;
QString m_showYoctoVersion; QString m_showYoctoVersion;
@@ -29,6 +31,8 @@ class CommandLineParser : public QCommandLineParser {
QCommandLineOption m_alwaysDownloadConfigOption; QCommandLineOption m_alwaysDownloadConfigOption;
QCommandLineOption m_alwaysDownloadDCOption; QCommandLineOption m_alwaysDownloadDCOption;
QCommandLineOption m_workingDirectoryOption; QCommandLineOption m_workingDirectoryOption;
QCommandLineOption m_psaConfigDirectoryOption;
QCommandLineOption m_psaTariffDirectoryOption;
QCommandLineOption m_dryRunOption; QCommandLineOption m_dryRunOption;
QCommandLineOption m_extendedVersionOption; QCommandLineOption m_extendedVersionOption;
QCommandLineOption m_yoctoVersionOption; QCommandLineOption m_yoctoVersionOption;
@@ -52,6 +56,8 @@ public:
QString plugInDir(); QString plugInDir();
QString plugInName(); QString plugInName();
QString workingDir(); QString workingDir();
QString psaConfigDir();
QString psaTariffDir();
bool dryRun(); bool dryRun();
bool noUpdatePsaHardware(); bool noUpdatePsaHardware();
bool yoctoVersion(); bool yoctoVersion();

View File

@@ -9,14 +9,15 @@
#include <QStringList> #include <QStringList>
GitClient::GitClient(QString const &customerNrStr, GitClient::GitClient(QString const &customerRepositoryPath,
QString const &customerNrStr,
QString const &customerRepository, QString const &customerRepository,
QString const &workingDirectory, QString const &workingDirectory,
QString const &branchName, QString const &branchName,
QObject *parent) QObject *parent)
: QObject(parent) : QObject(parent)
, m_worker(qobject_cast<Worker *>(parent)) , m_worker(qobject_cast<Worker *>(parent))
, m_repositoryPath(QString("https://git.mimbach49.de/GerhardHoffmann/%1.git").arg(customerNrStr)) , m_repositoryPath(customerRepositoryPath)
, m_customerNr(customerNrStr) , m_customerNr(customerNrStr)
, m_workingDirectory(workingDirectory) , m_workingDirectory(workingDirectory)
, m_branchName(branchName) , m_branchName(branchName)
@@ -392,6 +393,38 @@ std::optional<QString> GitClient::gitPull() {
if (QDir(m_customerRepository).exists()) { if (QDir(m_customerRepository).exists()) {
qInfo() << "BRANCH NAME" << m_branchName; qInfo() << "BRANCH NAME" << m_branchName;
#if 0
IMPORTANT COMMENT:
If remote host keys are changed, then
export GIT_SSH_COMMAND="ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig"
git pull
leads to the following warning/error message:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:vOD5jF2hglGktqLhK9ABxfEjwEgIK68/v9erdT05NDQ.
Please contact your system administrator.
Add correct host key in /home/root/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/root/.ssh/known_hosts:1
Password authentication is disabled to avoid man-in-the-middle attacks.
Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.
Agent forwarding is disabled to avoid man-in-the-middle attacks.
X11 forwarding is disabled to avoid man-in-the-middle attacks.
Already up to date.
This first part is from ssh itself, and could not be fetched easily, as this
process is gone when git itself starts.
Only the last line is the git message.
#endif
Command c("git pull"); Command c("git pull");
if (c.execute(m_customerRepository)) { if (c.execute(m_customerRepository)) {
QString const s = c.getCommandResult().trimmed(); QString const s = c.getCommandResult().trimmed();

View File

@@ -22,7 +22,8 @@ class GitClient : public QObject {
bool copyGitConfigFromMaster(); bool copyGitConfigFromMaster();
public: public:
explicit GitClient(QString const &customerNrStr, explicit GitClient(QString const &customerRepositoryUrl,
QString const &customerNrStr,
QString const &repositoryPath, QString const &repositoryPath,
QString const &workingDirectory = QCoreApplication::applicationDirPath(), QString const &workingDirectory = QCoreApplication::applicationDirPath(),
QString const &branchName = "master", QString const &branchName = "master",

View File

@@ -342,8 +342,11 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
return std::nullopt; return std::nullopt;
} }
} else { } else {
printDebugMessage(port, clientIP, clientPort, if (!response.contains("RECORD")) {
QString("PARSE ERROR ") + response + " " + parseError.errorString()); // maybe APISM does not send valid JSON: "RECORD SAVED" etc.
printDebugMessage(port, clientIP, clientPort,
QString("PARSE ERROR ") + response + " " + parseError.errorString());
}
::close(sockfd); ::close(sockfd);
return std::nullopt; return std::nullopt;
} }
@@ -360,7 +363,19 @@ QString IsmasClient::updateNewsToIsmas(char const *event,
char buf[1024]; char buf[1024];
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
QString const ts = QDateTime::currentDateTime().toString(Qt::ISODateWithMs); QDateTime const local(QDateTime::currentDateTime());
QDateTime utc(local);
utc.setTimeSpec(Qt::UTC);
int const diff = (int)local.secsTo(utc); // diff between UTC and local time
QTime t(0, 0, 0);
t = t.addSecs((uint)diff);
QString const st(QString("%1%2").arg(diff < 0 ? "-" : "+").arg(t.toString("hh:mm")));
QString const ts(local.toString(Qt::ISODateWithMs) + st);
snprintf(buf, sizeof(buf)-1, snprintf(buf, sizeof(buf)-1,
"{" "{"
"\"REASON\":\"SW_UP\"," "\"REASON\":\"SW_UP\","

View File

@@ -50,9 +50,11 @@
// argv[1]: file to send to dc // argv[1]: file to send to dc
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QByteArray const value = qgetenv("LC_ALL"); QByteArray const value = qgetenv("LC_ALL");
if (value != "C") { if (value.isEmpty() || value != "C") {
qputenv("LC_ALL", "C"); qputenv("LC_ALL", "C");
} }
// qputenv("XDG_RUNTIME_DIR", "/var/run/user/0"); // qputenv("XDG_RUNTIME_DIR", "/var/run/user/0");
openlog("ATB-UPDATE", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); openlog("ATB-UPDATE", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
@@ -62,7 +64,8 @@ int main(int argc, char *argv[]) {
QApplication::setApplicationVersion(APP_VERSION); QApplication::setApplicationVersion(APP_VERSION);
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(atbDebugOutput); atbInstallMessageHandler(nullptr);
//atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(LOG_NOTICE); setDebugLevel(LOG_NOTICE);
} }
@@ -71,6 +74,38 @@ int main(int argc, char *argv[]) {
parser.readSettings(); parser.readSettings();
QString repositoryUrl = parser.repositoryUrl(); QString repositoryUrl = parser.repositoryUrl();
if (repositoryUrl.endsWith('/')) {
repositoryUrl.chop(1);
}
QString gitSSHCommand("");
if (repositoryUrl.contains("ptu-config.atb-comm.de")) {
QByteArray const v = qgetenv("GIT_SSH_COMMAND");
if (v.isEmpty()) {
QString sshKeyFile("/opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig");
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()))) {
qCritical() << "ERROR: GIT_SSH_COMMAND not put into env. Exiting...";
return -1;
}
} else {
qCritical() << "ERROR ssh-key-file" << sshKeyFile << "does not exists. Exiting...";
return -1;
}
} else {
gitSSHCommand = QString(v.toStdString().c_str());
qCritical() << "WARNING GIT_SSH_COMMAND already set in enviroment:"
<< gitSSHCommand;
if (gitSSHCommand != "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig") {
qCritical() << "ERROR" << gitSSHCommand << "wrong. Exiting...";
return -1;
}
}
}
QString plugInDir = parser.plugInDir(); QString plugInDir = parser.plugInDir();
QString plugInName = parser.plugInName(); QString plugInName = parser.plugInName();
QString workingDir = parser.workingDir(); QString workingDir = parser.workingDir();
@@ -93,6 +128,9 @@ int main(int argc, char *argv[]) {
qInfo() << "pwd ......................" << rtPath; qInfo() << "pwd ......................" << rtPath;
qInfo() << "repositoryUrl ............" << repositoryUrl; qInfo() << "repositoryUrl ............" << repositoryUrl;
if (!gitSSHCommand.isEmpty()) {
qInfo() << "GIT_SSH_COMMAND .........." << gitSSHCommand;
}
qInfo() << "plugInDir ................" << plugInDir; qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName; qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir; qInfo() << "workingDir ..............." << workingDir;
@@ -130,7 +168,9 @@ int main(int argc, char *argv[]) {
if (!QDir(plugInDir).exists()) { if (!QDir(plugInDir).exists()) {
qCritical() << plugInDir qCritical() << plugInDir
<< "does not exists, but has to contain dc-library"; << "does not exists, but has to contain dc-library";
exit(-1); if (noUpdatePsaHardware == false) {
exit(-1);
}
} }
// before loading the library, delete all possible shared memory segments // before loading the library, delete all possible shared memory segments

View File

@@ -57,21 +57,21 @@ bool Command::execute(QString workingDirectory, QStringList args) {
connect(&(*p), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError())); connect(&(*p), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
if (!args.isEmpty()) { if (!args.isEmpty()) {
qDebug() << "START COMMAND" << m_command << "WITH ARGS" << args //qDebug() << "START COMMAND" << m_command << "WITH ARGS" << args
<< "IN" << p->workingDirectory(); // << "IN" << p->workingDirectory();
p->start(m_command, args); p->start(m_command, args);
} else { } else {
qDebug() << "START COMMAND" << m_command //qDebug() << "START COMMAND" << m_command
<< "IN" << p->workingDirectory(); // << "IN" << p->workingDirectory();
p->start(m_command); p->start(m_command);
} }
qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch(); qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch();
if (p->waitForStarted(m_waitForStartTimeout)) { if (p->waitForStarted(m_waitForStartTimeout)) {
qDebug() << "PROCESS" << m_command << "STARTED IN" << p->workingDirectory(); // qDebug() << "PROCESS" << m_command << "STARTED IN" << p->workingDirectory();
if (p->state() == QProcess::ProcessState::Running) { if (p->state() == QProcess::ProcessState::Running) {
qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory(); // qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory();
// wait forever for git/opkg-commands to finish // wait forever for git/opkg-commands to finish
int wait = m_waitForFinishTimeout; int wait = m_waitForFinishTimeout;
if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) || if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) ||
@@ -80,7 +80,7 @@ bool Command::execute(QString workingDirectory, QStringList args) {
} }
bool const no_timeout = p->waitForFinished(wait); bool const no_timeout = p->waitForFinished(wait);
if (no_timeout) { if (no_timeout) {
qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory(); // qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory();
if (p->exitStatus() == QProcess::NormalExit) { if (p->exitStatus() == QProcess::NormalExit) {
if ((m_exitCode = p->exitCode()) == 0) { if ((m_exitCode = p->exitCode()) == 0) {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch(); qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();

View File

@@ -52,7 +52,6 @@ hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
qCritical() << "in directory" << plugInDir.absolutePath(); qCritical() << "in directory" << plugInDir.absolutePath();
qCritical() << "cannot load plugin" << pluginLoader.fileName(); qCritical() << "cannot load plugin" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
exit(-1);
} }
qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath(); qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
@@ -60,25 +59,20 @@ hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
if (!pluginLoader.isLoaded()) { if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString(); qCritical() << pluginLoader.errorString();
exit(-2);
} }
QObject *plugin = pluginLoader.instance(); QObject *plugin = pluginLoader.instance();
if (!plugin) { if (!plugin) {
qCritical() << "cannot start instance"; qCritical() << "cannot start instance";
exit(-3);
} }
if (! (hw = qobject_cast<hwinf *>(plugin))) { if (! (hw = qobject_cast<hwinf *>(plugin))) {
qCritical() << "cannot cast plugin" << plugin << "to hwinf"; qCritical() << "cannot cast plugin" << plugin << "to hwinf";
exit(-4);
} }
} else { } else {
qCritical() << pluginLibName << "does not exist"; qCritical() << pluginLibName << "does not exist";
exit(-5);
} }
} else { } else {
qCritical() << "plugins directory" << plugInDir.absolutePath() qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist"; << "does not exist";
exit(-6);
} }
return hw; return hw;
} }
@@ -124,7 +118,7 @@ Update::Update(Worker *worker,
, m_sys_areDCdataValid(false) { , m_sys_areDCdataValid(false) {
if (!m_hw) { if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin loaded ???"; qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin not loaded";
} else { } else {
int tries = 20; int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) { while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
@@ -191,33 +185,37 @@ void Update::onReportDCDownloadFailure(QString const &errorMsg) {
// br is a index into a table, used for historical reasons. // br is a index into a table, used for historical reasons.
bool Update::openSerial(int br, QString baudrate, QString comPort) const { bool Update::openSerial(int br, QString baudrate, QString comPort) const {
qDebug() << "opening serial" << br << baudrate << comPort << "..."; if (m_hw) {
if (m_hw->dc_openSerial(br, baudrate, comPort, 1) == true) { // 1 for connect qDebug() << "opening serial" << br << baudrate << comPort << "...";
Utils::printInfoMsg( 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) QString("OPENING SERIAL %1").arg(br)
+ " " + baudrate + " " + comPort + "...OK"); + " " + baudrate + " " + comPort + "...FAILED");
// 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; return false;
} }
void Update::closeSerial() const { void Update::closeSerial() const {
qInfo() << "CLOSED SERIAL" << m_baudrate << m_serialInterface; qInfo() << "CLOSED SERIAL" << m_baudrate << m_serialInterface;
m_hw->dc_closeSerial(); if (m_hw) {
m_hw->dc_closeSerial();
}
} }
bool Update::isSerialOpen() const { bool Update::isSerialOpen() const {
return m_hw->dc_isPortOpen(); return m_hw ? m_hw->dc_isPortOpen() : false;
} }
/* /*
@@ -396,121 +394,125 @@ bool Update::downloadJson(enum FileTypeJson type,
int templateIdx, int templateIdx,
QString jsFileToSendToDC) const { QString jsFileToSendToDC) const {
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag if (m_hw) {
qDebug() << "SET AUTO-REQUEST=TRUE"; m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
QThread::sleep(1); // make sure the auto-request flag is acknowledged qDebug() << "SET AUTO-REQUEST=TRUE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
QStringList lst; QStringList lst;
bool ready = false; bool ready = false;
int nTry = 25; int nTry = 25;
while ((ready = m_hw->sys_ready4sending()) == false) { while ((ready = m_hw->sys_ready4sending()) == false) {
QThread::msleep(200); QThread::msleep(200);
if (--nTry <= 0) { if (--nTry <= 0) {
QString msg("SYS NOT READY FOR SENDING AFTER 5 SECONDS"); QString msg("SYS NOT READY FOR SENDING AFTER 5 SECONDS");
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
}
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(':');
*/
if (m_worker) {
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
}
ret = true;
} else {
msg = QString("ERROR SEND JSON-FILE %1 TO DC").arg(file.fileName());
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst)
<< Worker::UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
}
}
} else {
msg = QString("SIZE OF %1 TOO BIG (%2 BYTES)").arg(jsFileToSendToDC).arg(fi.size());
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst)
<< Worker::UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
}
}
} else {
msg = QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING";
Utils::printCriticalErrorMsg(msg); Utils::printCriticalErrorMsg(msg);
lst << msg; lst << msg;
if (m_worker) { if (m_worker) {
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst) m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE));
<< Worker::UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
} }
} break;
} else {
msg = QString(jsFileToSendToDC) + " DOES NOT EXIST";
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst)
<< Worker::UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
} }
} }
lst.clear();
if (ready) {
QString msg;
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
// type == kindOfFile
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(':');
*/
if (m_worker) {
lst.clear();
if (templateIdx >= 1 && templateIdx <= 32) {
lst << QString("LOADED %1 (%2) TO DC").arg(fi.fileName()).arg(templateIdx);
} else {
lst << QString("LOADED %1 (%2) TO DC").arg(fi.fileName()).arg((uint8_t)type);
}
m_worker->ISMAS(lst) << (m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE));
}
} else {
msg = QString("ERROR SEND JSON-FILE %1 TO DC").arg(file.fileName());
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE);
}
}
} else {
msg = QString("SIZE OF %1 TOO BIG (%2 BYTES)").arg(jsFileToSendToDC).arg(fi.size());
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE);
}
}
} else {
msg = QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING";
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE);
}
}
} else {
msg = QString(jsFileToSendToDC) + " DOES NOT EXIST";
Utils::printCriticalErrorMsg(msg);
lst << msg;
if (m_worker) {
m_worker->GUI(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE);
}
}
}
// m_hw->dc_autoRequest(false);
// qDebug() << "SET AUTO-REQUEST=FALSE";
// QThread::sleep(1); // make sure the auto-request flag is acknowledged
} }
m_hw->dc_autoRequest(false); return true;
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 { bool Update::updatePrinterTemplate(int templateIdx, QString jsFile) const {
@@ -518,14 +520,18 @@ bool Update::updatePrinterTemplate(int templateIdx, QString jsFile) const {
} }
bool Update::updateConfig(QString jsFile) { bool Update::updateConfig(QString jsFile) {
// IMPORTANT: the JSON-file has a 'title'-line: the value MUST be 'DC2C_config'
return downloadJson(FileTypeJson::CONFIG, 0, jsFile); return downloadJson(FileTypeJson::CONFIG, 0, jsFile);
} }
bool Update::updateCashConf(QString jsFile) { bool Update::updateCashConf(QString jsFile) {
// IMPORTANT: the JSON-file has a 'title'-line: the value MUST be 'DC2C_cash '
// Note the twp spaces after DC2C_cash !!
return downloadJson(FileTypeJson::CASH, 0, jsFile); return downloadJson(FileTypeJson::CASH, 0, jsFile);
} }
bool Update::updateDeviceConf(QString jsFile) { bool Update::updateDeviceConf(QString jsFile) {
// IMPORTANT: the JSON-file has a 'title'-line: the value MUST be 'DC2C_device'
return downloadJson(FileTypeJson::DEVICE, 0, jsFile); return downloadJson(FileTypeJson::DEVICE, 0, jsFile);
} }
@@ -564,24 +570,26 @@ void Update::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
} }
QStringList Update::getDcSoftAndHardWareVersion() { QStringList Update::getDcSoftAndHardWareVersion() {
m_hw->dc_autoRequest(true); if (m_hw) {
QThread::sleep(1); // make sure the timer-slots are active m_hw->dc_autoRequest(true);
QThread::sleep(1); // make sure the timer-slots are active
for (int i=0; i < 3; ++i) { // send explicit reuests to get for (int i=0; i < 3; ++i) { // send explicit reuests to get
// current SW/HW-versions // current SW/HW-versions
m_hw->request_DC2_SWversion(); m_hw->request_DC2_SWversion();
m_hw->request_DC2_HWversion(); m_hw->request_DC2_HWversion();
QThread::sleep(1); QThread::sleep(1);
} }
QString const &hwVersion = m_hw->dc_getHWversion().toLower().trimmed(); QString const &hwVersion = m_hw->dc_getHWversion().toLower().trimmed();
QString const &swVersion = m_hw->dc_getSWversion().toLower().trimmed(); QString const &swVersion = m_hw->dc_getSWversion().toLower().trimmed();
m_hw->dc_autoRequest(false); //m_hw->dc_autoRequest(false);
QThread::sleep(1); // make sure the timer-slots are inactive //QThread::sleep(1); // make sure the timer-slots are inactive
if (!hwVersion.isEmpty() && !swVersion.isEmpty()) { if (!hwVersion.isEmpty() && !swVersion.isEmpty()) {
return QStringList() << hwVersion << swVersion; return QStringList() << hwVersion << swVersion;
}
} }
return QStringList() << "DC HW-version not available" return QStringList() << "DC HW-version not available"
@@ -590,23 +598,31 @@ QStringList Update::getDcSoftAndHardWareVersion() {
QString Update::getFileVersion(QString const& jsonFileName) { QString Update::getFileVersion(QString const& jsonFileName) {
// "version":"15.10.2023 14:55 02.00.06", // "version":"15.10.2023 14:55 02.00.06",
static const QRegularExpression re("^.*(\\\"version\\\":)(.*)$"); static const QRegularExpression re("^.*(\\\"[Vv]ersion\\\":)([\\s\\\"]{0,})([^,\\\"]{0,}).*$");
QString fileVersion; QString fileVersion("");
QFile inputFile(jsonFileName); QFile inputFile(QDir::cleanPath(m_customerRepository + QDir::separator() + jsonFileName));
if (inputFile.open(QIODevice::ReadOnly)) {
QTextStream in(&inputFile);
while (!in.atEnd()) {
QString line = in.readLine();
QRegularExpressionMatch match; if (inputFile.exists()) {
int idx = line.indexOf(re, 0, &match); if (inputFile.open(QIODevice::ReadOnly)) {
if (idx != -1) { QTextStream in(&inputFile);
fileVersion = match.captured(match.lastCapturedIndex()); while (!in.atEnd()) {
break; QString line = in.readLine();
}
} QRegularExpressionMatch match;
inputFile.close(); 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; return fileVersion;
@@ -617,60 +633,192 @@ bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) {
for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) { for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
uint8_t jsonNr = 0; uint8_t jsonNr = 0;
QFileInfo fInfo(jsonFileNames[i]);
if (fInfo.fileName().endsWith("conf.json")) { 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; jsonNr = 1;
} else } else
if (fInfo.fileName().endsWith("device.json")) { if (fName.endsWith("device.json")) {
jsonNr = 2; jsonNr = 2;
} else } else
if (fInfo.fileName().endsWith("cash.json")) { if (fName.endsWith("cash.json")) {
jsonNr = 3; jsonNr = 3;
} else { } else {
QRegularExpressionMatch match; QRegularExpressionMatch match;
static const QRegularExpression re("^(.*print)([0-3][0-9])\\.json\\s*$"); static const QRegularExpression re("^(.*print)([0-3][0-9])\\.json\\s*$");
int idx = fInfo.fileName().indexOf(re, 0, &match); int idx = fName.indexOf(re, 0, &match);
if (idx != -1) { if (idx != -1) {
QString captured = match.captured(match.lastCapturedIndex()); QString captured = match.captured(match.lastCapturedIndex());
bool ok = false; bool ok = false;
int n = captured.toInt(&ok); int n = captured.toInt(&ok);
if (ok) { if (ok) {
jsonNr = n + 4; // note: the '5' is correct
jsonNr = n + 5;
} }
} }
} }
if (jsonNr != 0) { if (jsonNr != 0) {
#if 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); m_hw->sys_requestJsonVersions(jsonNr);
QThread::msleep(500); QThread::msleep(500);
char buf[64]; char buf[64];
memset(buf, 0x00, sizeof(buf)); memset(buf, 0x00, sizeof(buf));
m_hw->sys_getJsonVersions(jsonNr, buf); m_hw->sys_getJsonVersions(jsonNr, buf);
buf[sizeof(buf)-1] = '\0'; buf[16] = '\0'; // the DC only handles 16 bytes
QString const installedVersion(buf); static const QByteArray cb(16, (char)0xff);
QString const installedVersion(QString::fromStdString(buf));
QString const fileVersion = getFileVersion(jsonFileNames[i]); QString const fileVersion = getFileVersion(jsonFileNames[i]);
qCritical() << "installed version:" << installedVersion; QFileInfo fi(jsonFileNames[i]);
qCritical() << " file version:" << fileVersion;
qCritical() << endl;
qCritical() << " json request nr:" << jsonNr;
if (installedVersion == fileVersion) { 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;
} }
#endif
} else { } else {
qCritical() << "CANNOT FIND JSON-NR FOR" << jsonFileNames[i]; qCritical() << "CANNOT FIND JSON-NR FOR" << fName;
} }
} }
return false; return false;
} }
QMap<QString, QString>
Update::getInstalledJsonVersions(QStringList const& jsonFileNames) {
QMap<QString, QString> map;
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return map;
}
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 map;
}
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]);
if (cb == QByteArray(buf)) {
map.insert(fi.fileName(), "inst.vers.not.avail");
} else {
map.insert(fi.fileName(), installedVersion);
}
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 map;
}
bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) { bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
if (!m_hw) {
Utils::printInfoMsg("CA-PLUGIN NOT LOADED");
return false;
}
int tries = 20; int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) { while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid // must deliver 'true', only then are all data from hwapi valid
@@ -803,45 +951,58 @@ bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
res = false; res = false;
} else { } else {
if ((res = updatePrinterTemplate(templateIdx, fToWorkOn))) { if ((res = updatePrinterTemplate(templateIdx, fToWorkOn))) {
Utils::printInfoMsg( if (m_worker) {
QString("DOWNLOADED PRINTER TEMPLATE %1 WITH INDEX=%2") QStringList lst(QString("DL:%1 (%2)").arg(QFileInfo(fToWorkOn).fileName()).arg(templateIdx));
.arg(fToWorkOn) m_worker->ISMAS(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS);
.arg(templateIdx));
++displayIndex; ++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")") emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(), + QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE); Worker::UPDATE_STEP_DONE);
}
} }
} }
} else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive) } else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true; res = true;
if ((res = updateCashConf(fToWorkOn))) { if ((res = updateCashConf(fToWorkOn))) {
Utils::printInfoMsg(QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn)); if (m_worker) {
++displayIndex; QStringList lst(QString("DL:%1").arg(QFileInfo(fToWorkOn).fileName()));
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")") m_worker->ISMAS(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS);
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE); ++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
} }
} else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive) } else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true; res = true;
if ((res= updateConfig(fToWorkOn))) { if ((res= updateConfig(fToWorkOn))) {
Utils::printInfoMsg(QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn)); if (m_worker) {
++displayIndex; QStringList lst(QString("DL:%1").arg(QFileInfo(fToWorkOn).fileName()));
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")") m_worker->ISMAS(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS);
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE); ++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
} }
} else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive) } else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) { && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true; res = true;
if ((res = updateDeviceConf(fToWorkOn))) { if ((res = updateDeviceConf(fToWorkOn))) {
Utils::printInfoMsg(QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn)); if (m_worker) {
++displayIndex; QStringList lst(QString("DL:%1").arg(QFileInfo(fToWorkOn).fileName()));
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")") m_worker->ISMAS(lst) << (m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS);
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE); ++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
} }
} else { } else {
qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn; qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn;

View File

@@ -8,6 +8,7 @@
#include <QByteArray> #include <QByteArray>
#include <QProcess> #include <QProcess>
#include <QPluginLoader> #include <QPluginLoader>
#include <QMap>
#include <DeviceController/interfaces.h> #include <DeviceController/interfaces.h>
@@ -60,6 +61,47 @@ public:
bool doUpdate(int &displayIndex, QStringList const &linesToWorkOn); bool doUpdate(int &displayIndex, QStringList const &linesToWorkOn);
bool checkDownloadedJsonVersions(QStringList const& jsonFileNames); bool checkDownloadedJsonVersions(QStringList const& jsonFileNames);
QMap<QString, QString>
getInstalledJsonVersions(QStringList const& jsonFileNames =
QStringList(
QList(
std::initializer_list<QString>{
QString("etc/psa_config/DC2C_conf.json"),
QString("etc/psa_config/DC2C_cash.json"),
QString("etc/psa_config/DC2C_device.json"),
QString("etc/psa_config/DC2C_print01.json"),
QString("etc/psa_config/DC2C_print02.json"),
QString("etc/psa_config/DC2C_print03.json"),
QString("etc/psa_config/DC2C_print04.json"),
QString("etc/psa_config/DC2C_print05.json"),
QString("etc/psa_config/DC2C_print06.json"),
QString("etc/psa_config/DC2C_print07.json"),
QString("etc/psa_config/DC2C_print08.json"),
QString("etc/psa_config/DC2C_print09.json"),
QString("etc/psa_config/DC2C_print10.json"),
QString("etc/psa_config/DC2C_print11.json"),
QString("etc/psa_config/DC2C_print12.json"),
QString("etc/psa_config/DC2C_print13.json"),
QString("etc/psa_config/DC2C_print14.json"),
QString("etc/psa_config/DC2C_print15.json"),
QString("etc/psa_config/DC2C_print16.json"),
QString("etc/psa_config/DC2C_print17.json"),
QString("etc/psa_config/DC2C_print18.json"),
QString("etc/psa_config/DC2C_print19.json"),
QString("etc/psa_config/DC2C_print20.json"),
QString("etc/psa_config/DC2C_print21.json"),
QString("etc/psa_config/DC2C_print22.json"),
QString("etc/psa_config/DC2C_print23.json"),
QString("etc/psa_config/DC2C_print24.json"),
QString("etc/psa_config/DC2C_print25.json"),
QString("etc/psa_config/DC2C_print26.json"),
QString("etc/psa_config/DC2C_print27.json"),
QString("etc/psa_config/DC2C_print28.json"),
QString("etc/psa_config/DC2C_print29.json"),
QString("etc/psa_config/DC2C_print30.json"),
QString("etc/psa_config/DC2C_print31.json"),
QString("etc/psa_config/DC2C_print32.json")})));
hwinf *hw() { return m_hw; } hwinf *hw() { return m_hw; }
hwinf const *hw() const { return m_hw; } hwinf const *hw() const { return m_hw; }

View File

@@ -110,19 +110,19 @@ QString Utils::getTariffInfo(QString fileName) {
} }
QString Utils::zoneName(quint8 i) { QString Utils::zoneName(quint8 i) {
static constexpr char const *zName[] = { //static constexpr char const *zName[] = {
"", // "",
"purple", // "purple",
"blue", // "blue",
"yellow", // "yellow",
"green", // "green",
"yellow (mars)", // "yellow (mars)",
"green (mars)" // "green (mars)"
}; //};
if (i < (sizeof(zName)/sizeof(char const *))) { //if (i < (sizeof(zName)/sizeof(char const *))) {
return zName[i]; // return zName[i];
} //}
return "N/A"; return "---";
} }
void Utils::printCriticalErrorMsg(QString const &errorMsg, bool upper, bool lower) { void Utils::printCriticalErrorMsg(QString const &errorMsg, bool upper, bool lower) {
@@ -293,7 +293,7 @@ bool Utils::sameFilesInDirs(QDir const &dir1, QDir const &dir2,
} }
if (fileNameLst1 != fileNameLst2) { if (fileNameLst1 != fileNameLst2) {
printCriticalErrorMsg(dirPath1 + " AND " + dirPath2 printCriticalErrorMsg(dirPath1 + " AND " + dirPath2
+ " DIFFER: [" + fileNameLst1.join(',') + "],[" + " HAVE DIFFERENT FILES: [" + fileNameLst1.join(',') + "],["
+ fileNameLst2.join(',') + "]"); + fileNameLst2.join(',') + "]");
return false; return false;
} else { } else {
@@ -323,7 +323,7 @@ bool Utils::sameFilesInDirs(QDir const &dir1, QDir const &dir2,
if (gitBlobLst1 != gitBlobLst2) { if (gitBlobLst1 != gitBlobLst2) {
printCriticalErrorMsg(dirPath1 + " AND " + dirPath2 printCriticalErrorMsg(dirPath1 + " AND " + dirPath2
+ " DIFFER: [" + gitBlobLst1.join(',') + "],[" + " HAVE DIFFERENT BLOBS: [" + gitBlobLst1.join(',') + "],["
+ gitBlobLst2.join(',') + "]"); + gitBlobLst2.join(',') + "]");
return false; return false;
} else { } else {

View File

@@ -32,6 +32,8 @@ QString const Worker::UPDATE_STEP_WRONG ( "[WRONG]");
QString const Worker::UPDATE_STEP_FAIL ( " [FAIL]"); QString const Worker::UPDATE_STEP_FAIL ( " [FAIL]");
QString const Worker::UPDATE_STEP_SUCCESS(" [SUCCESS]"); QString const Worker::UPDATE_STEP_SUCCESS(" [SUCCESS]");
bool Worker::sendLastVersionOnce = false;
using UPDATE_STEP = Worker::UPDATE_STEP; using UPDATE_STEP = Worker::UPDATE_STEP;
const QMap<UPDATE_STEP, const char*> Worker::smap ( const QMap<UPDATE_STEP, const char*> Worker::smap (
std::initializer_list<std::pair<UPDATE_STEP, const char*>>{ std::initializer_list<std::pair<UPDATE_STEP, const char*>>{
@@ -87,6 +89,15 @@ const QMap<UPDATE_STEP, const char*> Worker::smap (
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE), INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS), INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE), INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER), INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_SUCCESS), INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_SUCCESS),
INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_FAILURE), INSERT_ELEMENT(UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_FAILURE),
@@ -130,7 +141,7 @@ Worker::Worker(int customerNr,
char const *serialInterface, char const *serialInterface,
char const *baudrate) char const *baudrate)
: m_customerNr(customerNr) : m_customerNr(customerNr)
, m_customerNrStr(QString("customer_") + QString::number(m_customerNr).rightJustified(3, '0')) , m_customerNrStr(QString("customer_") + QString::number(m_customerNr))
, m_machineNr(machineNr) , m_machineNr(machineNr)
, m_zoneNr(zoneNr) , m_zoneNr(zoneNr)
, m_pluginDir(pluginDir) , m_pluginDir(pluginDir)
@@ -146,7 +157,7 @@ Worker::Worker(int customerNr,
, m_parent(parent) , m_parent(parent)
, m_serialInterface(serialInterface) , m_serialInterface(serialInterface)
, m_baudrate(baudrate) , m_baudrate(baudrate)
, m_gc(m_customerNrStr, m_customerRepository, m_workingDirectory, m_branchName, this) , m_gc(m_customerRepositoryPath, m_customerNrStr, m_customerRepository, m_workingDirectory, m_branchName, this)
, m_versionInfo(QStringList()) , m_versionInfo(QStringList())
, m_osVersion(getOsVersion()) , m_osVersion(getOsVersion())
, m_atbqtVersion(getATBQTVersion()) , m_atbqtVersion(getATBQTVersion())
@@ -170,13 +181,16 @@ Worker::Worker(int customerNr,
// TODO: turn object into singleton // TODO: turn object into singleton
instance = this; instance = this;
m_lastFailedUpdateStep = UPDATE_STEP::NONE; m_lastFailedUpdateStep = UPDATE_STEP::NONE;
m_update = new Update(this,
QDir::cleanPath(m_workingDirectory + QDir::separator() + m_customerNrStr), if (m_noUpdatePsaHardware == false) {
m_customerNrStr, m_update = new Update(this,
m_branchName, QDir::cleanPath(m_workingDirectory + QDir::separator() + m_customerNrStr),
m_pluginDir, m_customerNrStr,
m_pluginName, m_branchName,
m_workingDirectory); m_pluginDir,
m_pluginName,
m_workingDirectory);
}
this->setObjectName("worker-object"); this->setObjectName("worker-object");
QDir::setCurrent(m_workingDirectory); QDir::setCurrent(m_workingDirectory);
@@ -311,7 +325,7 @@ void Worker::privateUpdate() {
QStringList lst = m_ismasTriggerStatusMessage; QStringList lst = m_ismasTriggerStatusMessage;
// trigger message to ISMAS and CONSOLE // trigger message to ISMAS and CONSOLE
ISMAS(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS)); CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS);
// overwrite m_lastFailedUpdateStep // overwrite m_lastFailedUpdateStep
m_lastFailedUpdateStep = UPDATE_STEP::NONE; m_lastFailedUpdateStep = UPDATE_STEP::NONE;
return; return;
@@ -497,9 +511,8 @@ void Worker::privateUpdate() {
if ((continueUpdate = downloadFilesToPSAHardware()) == false) { if ((continueUpdate = downloadFilesToPSAHardware()) == false) {
return; return;
} }
lst = QStringList(QString(smap[UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS])); lst = QStringList(QString("DONE"));
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE)); ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS));
setProgress(_DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS);
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// //
@@ -851,7 +864,24 @@ bool Worker::computeFilesToDownload() {
return (m_filesToDownload.size() > 0); return (m_filesToDownload.size() > 0);
} }
bool Worker::cleanUpOpkgCache() {
bool removedFiles = true;
QDir dir("/var/cache/opkg");
if (dir.exists()) {
dir.setNameFilters(QStringList() << ".gz" << ".ipk");
dir.setFilter(QDir::Files);
foreach(QString dirFile, dir.entryList()) {
removedFiles &= dir.remove(dirFile);
}
}
return removedFiles;
}
bool Worker::execOpkgCommands() { bool Worker::execOpkgCommands() {
if (!cleanUpOpkgCache()) {
CONSOLE() << "INFO: some cached opkg files not removed";
}
for (int i = 0; i < m_filesToUpdate.size(); ++i) { for (int i = 0; i < m_filesToUpdate.size(); ++i) {
QString const fName = m_filesToUpdate.at(i); QString const fName = m_filesToUpdate.at(i);
if (fName.contains("opkg_commands", Qt::CaseInsensitive)) { if (fName.contains("opkg_commands", Qt::CaseInsensitive)) {
@@ -866,10 +896,13 @@ bool Worker::execOpkgCommands() {
QStringList opkgErrorLst; QStringList opkgErrorLst;
while (!in.atEnd()) { while (!in.atEnd()) {
QString line = in.readLine(); QString line = in.readLine();
static const QRegularExpression comment("^\\s*#.*$"); // TODO: "^\\s*[#]{0,}$" : empty line or comment line starting with #
if (line.indexOf(comment, 0) == -1) { static const QRegularExpression comment("^\\s*[#].*$");
// found opkg command static const QRegularExpression emptyLine("^\\s*$");
if (line.indexOf(emptyLine, 0) == -1 &&
line.indexOf(comment, 0) == -1) {
QString opkgCommand = line.trimmed(); QString opkgCommand = line.trimmed();
qCritical() << "Found opkg-command" << opkgCommand;
if (!executeOpkgCommand(opkgCommand)) { if (!executeOpkgCommand(opkgCommand)) {
opkgErrorLst << opkgCommand; opkgErrorLst << opkgCommand;
} else { } else {
@@ -948,13 +981,16 @@ bool Worker::execOpkgCommands() {
bool Worker::downloadFilesToPSAHardware() { bool Worker::downloadFilesToPSAHardware() {
m_displayIndex = 0; m_displayIndex = 0;
QStringList lst(QString("START"));
GUI(m_filesToDownload) << (CONSOLE(m_filesToDownload) << UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE); ISMAS(lst) << (GUI(m_filesToDownload) << (CONSOLE(m_filesToDownload) << UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE));
setProgress(_DOWNLOAD_FILES_TO_PSA_HARDWARE);
if (m_noUpdatePsaHardware == false) { if (m_noUpdatePsaHardware == false) {
if (computeFilesToDownload() > 0) { if (computeFilesToDownload() > 0) {
QStringList lst = m_filesToDownload; lst.clear();
for (int i = 0; i < m_filesToDownload.size(); ++i) {
lst << QFileInfo(m_filesToDownload.at(i)).fileName();
}
ISMAS(lst) << (CONSOLE(lst) << UPDATE_STEP::FILES_TO_DOWNLOAD); ISMAS(lst) << (CONSOLE(lst) << UPDATE_STEP::FILES_TO_DOWNLOAD);
if (m_update && m_update->doUpdate(m_displayIndex, m_filesToDownload)) { if (m_update && m_update->doUpdate(m_displayIndex, m_filesToDownload)) {
@@ -967,7 +1003,7 @@ bool Worker::downloadFilesToPSAHardware() {
return true; return true;
} }
CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE); ISMAS(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE));
setProgress(_DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE); setProgress(_DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE);
return false; return false;
@@ -978,14 +1014,20 @@ bool Worker::downloadFilesToPSAHardware() {
} }
bool Worker::syncCustomerRepositoryAndFS() { bool Worker::syncCustomerRepositoryAndFS() {
ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY)); QString msg("START");
QStringList lst(msg);
ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY));
lst.clear();
if (QDir(m_customerRepository).exists()) { if (QDir(m_customerRepository).exists()) {
if (QDir::setCurrent(m_customerRepository)) { if (QDir::setCurrent(m_customerRepository)) {
Command md("bash"); Command md("bash");
if (!md.execute(m_customerRepository, if (!md.execute(m_customerRepository,
QStringList() << "-c" << "mkdir -p /etc/psa_config /etc/dc /etc/psa_tariff")) { QStringList() << "-c" << "mkdir -p /etc/psa_config /etc/dc /etc/psa_tariff")) {
qCritical() << "COULD NOT EXECUTE '" << md.command() << "' exitCode=(" << md.exitCode() << ")"; msg = QString("COULD NOT EXECUTE '%1', exitCode=%2").arg(md.command()).arg(md.exitCode());
qCritical() << msg;
QStringList lst2(msg);
ISMAS(lst2) << (CONSOLE(lst2) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY);
} }
QString const params("-v " QString const params("-v "
"--recursive " "--recursive "
@@ -1044,12 +1086,22 @@ bool Worker::syncCustomerRepositoryAndFS() {
error = true; error = true;
} }
} }
if (!error) {
lst.clear();
lst << QString("SUCCESS %1").arg(cmd);
ISMAS(lst) << (CONSOLE(lst) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY);
} else {
msg = QString("FAILURE %1").arg(cmd);
lst << msg;
QStringList lst2(msg);
ISMAS(lst2) << (CONSOLE(lst2) << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY);
}
} }
if (!error) { if (!error) {
// now check tariff-files in etc and /etc/psa_tariff // now check tariff-files in etc and /etc/psa_tariff
QDir dir1(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_tariff")); QDir dir1(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_tariff"));
QDir dir2("/etc/psa_tariff"); QDir dir2("/etc/psa_tariff");
if (Utils::sameFilesInDirs(dir1, dir2)) { if (Utils::sameFilesInDirs(dir1, dir2) == false) {
CONSOLE() << QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_tariff") CONSOLE() << QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/psa_tariff")
<< "AND /etc/psa_tariff ARE DIFFERENT: CHANGED CUSTOMER-NUMBER?"; << "AND /etc/psa_tariff ARE DIFFERENT: CHANGED CUSTOMER-NUMBER?";
} }
@@ -1057,9 +1109,13 @@ bool Worker::syncCustomerRepositoryAndFS() {
setProgress(_SYNC_CUSTOMER_REPOSITORY_SUCCESS); setProgress(_SYNC_CUSTOMER_REPOSITORY_SUCCESS);
return true; return true;
} }
} else {
lst << QString("CAN NOT CD TO CUST-REPO %1").arg(m_customerRepository);
} }
} else {
lst << QString("CUST-REPO %1 DOES NOT EXIST").arg(m_customerRepository);
} }
ISMAS() << (GUI() << (CONSOLE() << (m_lastFailedUpdateStep = UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_FAILURE))); ISMAS(lst) << (GUI(lst) << (CONSOLE(lst) << (m_lastFailedUpdateStep = UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_FAILURE)));
setProgress(_SYNC_CUSTOMER_REPOSITORY_FAILURE); setProgress(_SYNC_CUSTOMER_REPOSITORY_FAILURE);
return false; return false;
} }
@@ -1339,20 +1395,36 @@ PSAInstalled Worker::getPSAInstalled() {
psaInstalled.pluginVersion.prmCalculatePriceConfigUi = m_pluginVersionPrmCalcConfig; psaInstalled.pluginVersion.prmCalculatePriceConfigUi = m_pluginVersionPrmCalcConfig;
psaInstalled.pluginVersion.tcpZVT = m_pluginVersionTcpZvt; psaInstalled.pluginVersion.tcpZVT = m_pluginVersionTcpZvt;
// key: conf-json-filename; value: installed version on DC
QMap<QString, QString> map;
if (m_update) {
map = m_update->getInstalledJsonVersions();
}
psaInstalled.cash.name = "DC2C_cash.json"; psaInstalled.cash.name = "DC2C_cash.json";
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.cash.name); absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.cash.name);
psaInstalled.cash.blob = m_gc.gitBlob(absPathName); psaInstalled.cash.blob = m_gc.gitBlob(absPathName);
psaInstalled.cash.size = getFileSize(absPathName); psaInstalled.cash.size = getFileSize(absPathName);
if (map.contains("DC2C_cash.json")) {
psaInstalled.cash.blob = map.value("DC2C_cash.json", "inst.vers.not.avail");
}
psaInstalled.conf.name = "DC2C_conf.json"; psaInstalled.conf.name = "DC2C_conf.json";
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.conf.name); absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.conf.name);
psaInstalled.conf.blob = m_gc.gitBlob(absPathName); psaInstalled.conf.blob = m_gc.gitBlob(absPathName);
psaInstalled.conf.size = getFileSize(absPathName); psaInstalled.conf.size = getFileSize(absPathName);
if (map.contains("DC2C_conf.json")) {
psaInstalled.conf.blob = map.value("DC2C_conf.json", "inst.vers.not.avail");
}
psaInstalled.device.name = "DC2C_device.json"; psaInstalled.device.name = "DC2C_device.json";
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.device.name); absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.device.name);
psaInstalled.device.blob = m_gc.gitBlob(absPathName); psaInstalled.device.blob = m_gc.gitBlob(absPathName);
psaInstalled.device.size = getFileSize(absPathName); psaInstalled.device.size = getFileSize(absPathName);
if (map.contains("DC2C_device.json")) {
psaInstalled.device.blob = map.value("DC2C_device.json", "inst.vers.not.avail");
}
for (int i=0; i < 32; ++i) { for (int i=0; i < 32; ++i) {
QString const &n = QString("%1").arg(i+1).rightJustified(2, '0'); QString const &n = QString("%1").arg(i+1).rightJustified(2, '0');
@@ -1360,6 +1432,9 @@ PSAInstalled Worker::getPSAInstalled() {
absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.print[i].name); absPathName = QDir::cleanPath(printSysDir + QDir::separator() + psaInstalled.print[i].name);
psaInstalled.print[i].blob = m_gc.gitBlob(absPathName); psaInstalled.print[i].blob = m_gc.gitBlob(absPathName);
psaInstalled.print[i].size = getFileSize(absPathName); psaInstalled.print[i].size = getFileSize(absPathName);
if (map.contains(psaInstalled.print[i].name)) {
psaInstalled.print[i].blob = map.value(psaInstalled.print[i].name, "inst.vers.not.avail");
}
} }
return psaInstalled; return psaInstalled;

View File

@@ -35,12 +35,13 @@
! U0003: Update finished but FAILed. ! U0003: Update finished but FAILed.
*/ */
#define _ISMAS_DONE "U0001" // 100%, Check: Resultcode: 0 #define _ISMAS_DONE "U0001" // 100%, Check: Resultcode: 0
#define _ISMAS_SET_WAIT_OK "U0002" // empty WAIT-button (""), ResultCode: 0 #define _ISMAS_SET_WAIT_OK "U0002" // empty WAIT-button (""), ResultCode: 0
#define _ISMAS_FAILURE "U0003" // FAIL #define _ISMAS_NO_UPDATE_NECESSARY "M0100" // empty WAIT-button (""), ResultCode: 0
#define _ISMAS_CONTINUE "U0010" // %-values: Update laeuft, Resultcodes entsprechend laufender Schritt #define _ISMAS_FAILURE "U0003" // FAIL
#define _ISMAS_RESET_WAIT "ISMAS" // reset WAIT-button to "WAIT" #define _ISMAS_CONTINUE "U0010" // %-values: Update laeuft, Resultcodes entsprechend laufender Schritt
#define _ISMAS_TEST_TRIGGER "U0099" // check the WAIT-button #define _ISMAS_RESET_WAIT "ISMAS" // reset WAIT-button to "WAIT"
#define _ISMAS_TEST_TRIGGER "U0099" // check the WAIT-button
#define _STARTED (1) #define _STARTED (1)
#define _CHECK_ISMAS_TRIGGER (2) #define _CHECK_ISMAS_TRIGGER (2)
@@ -79,7 +80,6 @@
#define _SYNC_CUSTOMER_REPOSITORY_SUCCESS (35) #define _SYNC_CUSTOMER_REPOSITORY_SUCCESS (35)
#define _FILES_TO_UPDATE (36) #define _FILES_TO_UPDATE (36)
#define _CHECK_FOR_REPOSITORY_CHANGES_FAILURE (37) #define _CHECK_FOR_REPOSITORY_CHANGES_FAILURE (37)
#define _FILES_TO_DOWNLOAD (38)
#define _EXEC_OPKG_COMMANDS (39) #define _EXEC_OPKG_COMMANDS (39)
#define _EXEC_OPKG_COMMAND_1 (40) #define _EXEC_OPKG_COMMAND_1 (40)
#define _EXEC_OPKG_COMMAND_2 (41) #define _EXEC_OPKG_COMMAND_2 (41)
@@ -93,13 +93,23 @@
#define _EXEC_OPKG_COMMAND_LAST (49) #define _EXEC_OPKG_COMMAND_LAST (49)
#define _EXEC_OPKG_COMMAND_FAILURE (50) #define _EXEC_OPKG_COMMAND_FAILURE (50)
#define _EXEC_OPKG_COMMAND_SUCCESS (51) #define _EXEC_OPKG_COMMAND_SUCCESS (51)
#define _DOWNLOAD_FILES_TO_PSA_HARDWARE (60) #define _DOWNLOAD_FILES_TO_PSA_HARDWARE (59)
#define _DOWNLOAD_CONFIG_FILE (61) #define _FILES_TO_DOWNLOAD (60)
#define _DOWNLOAD_CONFIG_FILE_SUCCESS (62) #define _DOWNLOAD_CASH_FILE (61)
#define _DOWNLOAD_CONFIG_FILE_FAILURE (63) #define _DOWNLOAD_CASH_FILE_FAILURE (62)
#define _DOWNLOAD_DEVICE_CONTROLLER (64) #define _DOWNLOAD_CASH_FILE_SUCCESS (63)
#define _DOWNLOAD_DEVICE_CONTROLLER_SUCCESS (85) #define _DOWNLOAD_CONFIG_FILE (64)
#define _DOWNLOAD_DEVICE_CONTROLLER_FAILURE (86) #define _DOWNLOAD_CONFIG_FILE_FAILURE (65)
#define _DOWNLOAD_CONFIG_FILE_SUCCESS (66)
#define _DOWNLOAD_DEVICE_FILE (67)
#define _DOWNLOAD_DEVICE_FILE_FAILURE (68)
#define _DOWNLOAD_DEVICE_FILE_SUCCESS (69)
#define _DOWNLOAD_JSON_FILE (70)
#define _DOWNLOAD_JSON_FILE_FAILURE (71)
#define _DOWNLOAD_JSON_FILE_SUCCESS (72)
#define _DOWNLOAD_DEVICE_CONTROLLER (84)
#define _DOWNLOAD_DEVICE_CONTROLLER_FAILURE (85)
#define _DOWNLOAD_DEVICE_CONTROLLER_SUCCESS (86)
#define _DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE (87) #define _DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE (87)
#define _DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS (88) #define _DOWNLOAD_FILES_TO_PSA_HARDWARE_SUCCESS (88)
#define _SAVE_LOGS (92) #define _SAVE_LOGS (92)
@@ -183,6 +193,7 @@ class Worker : public QThread{
QString m_apismVersion; QString m_apismVersion;
bool executeOpkgCommand(QString opkgCommand); bool executeOpkgCommand(QString opkgCommand);
bool cleanUpOpkgCache();
QString getOsVersion() const; QString getOsVersion() const;
QString getATBQTVersion() const; QString getATBQTVersion() const;
QString getATBUpdateToolVersion() const; QString getATBUpdateToolVersion() const;
@@ -326,6 +337,15 @@ public:
DOWNLOAD_CONFIG_FILE = _DOWNLOAD_CONFIG_FILE, DOWNLOAD_CONFIG_FILE = _DOWNLOAD_CONFIG_FILE,
DOWNLOAD_CONFIG_FILE_SUCCESS = _DOWNLOAD_CONFIG_FILE_SUCCESS, DOWNLOAD_CONFIG_FILE_SUCCESS = _DOWNLOAD_CONFIG_FILE_SUCCESS,
DOWNLOAD_CONFIG_FILE_FAILURE = _DOWNLOAD_CONFIG_FILE_FAILURE, DOWNLOAD_CONFIG_FILE_FAILURE = _DOWNLOAD_CONFIG_FILE_FAILURE,
DOWNLOAD_CASH_FILE = _DOWNLOAD_CASH_FILE,
DOWNLOAD_CASH_FILE_FAILURE = _DOWNLOAD_CASH_FILE_FAILURE,
DOWNLOAD_CASH_FILE_SUCCESS = _DOWNLOAD_CASH_FILE_SUCCESS,
DOWNLOAD_DEVICE_FILE = _DOWNLOAD_DEVICE_FILE,
DOWNLOAD_DEVICE_FILE_FAILURE = _DOWNLOAD_DEVICE_FILE_FAILURE,
DOWNLOAD_DEVICE_FILE_SUCCESS = _DOWNLOAD_DEVICE_FILE_SUCCESS,
DOWNLOAD_JSON_FILE = _DOWNLOAD_JSON_FILE,
DOWNLOAD_JSON_FILE_FAILURE = _DOWNLOAD_JSON_FILE_FAILURE,
DOWNLOAD_JSON_FILE_SUCCESS = _DOWNLOAD_JSON_FILE_SUCCESS,
DOWNLOAD_DEVICE_CONTROLLER = _DOWNLOAD_DEVICE_CONTROLLER, DOWNLOAD_DEVICE_CONTROLLER = _DOWNLOAD_DEVICE_CONTROLLER,
DOWNLOAD_DEVICE_CONTROLLER_SUCCESS = _DOWNLOAD_DEVICE_CONTROLLER_SUCCESS, DOWNLOAD_DEVICE_CONTROLLER_SUCCESS = _DOWNLOAD_DEVICE_CONTROLLER_SUCCESS,
DOWNLOAD_DEVICE_CONTROLLER_FAILURE = _DOWNLOAD_DEVICE_CONTROLLER_FAILURE, DOWNLOAD_DEVICE_CONTROLLER_FAILURE = _DOWNLOAD_DEVICE_CONTROLLER_FAILURE,
@@ -462,6 +482,7 @@ private slots:
private: private:
PSAInstalled getPSAInstalled(); PSAInstalled getPSAInstalled();
static bool sendLastVersionOnce;
void privateUpdate(); void privateUpdate();
bool computeFilesToDownload(); bool computeFilesToDownload();
bool execOpkgCommands(); bool execOpkgCommands();
@@ -654,6 +675,24 @@ private:
break; break;
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE: case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE:
break; break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE: {
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE: {
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS: {
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE: {
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE: {
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER: case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER:
lst << instance->m_debugMsg; lst << instance->m_debugMsg;
Utils::printUpdateStatusMsg(debug, lst); Utils::printUpdateStatusMsg(debug, lst);
@@ -1087,12 +1126,34 @@ private:
case UPDATE_STEP::FILES_TO_UPDATE: case UPDATE_STEP::FILES_TO_UPDATE:
ismasClient.setProgressInPercent(_FILES_TO_UPDATE); ismasClient.setProgressInPercent(_FILES_TO_UPDATE);
break; break;
case UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE: case UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE: {
ismasClient.setProgressInPercent(_DOWNLOAD_FILES_TO_PSA_HARDWARE); ismasClient.setProgressInPercent(_DOWNLOAD_FILES_TO_PSA_HARDWARE);
break; QString const &ismasUpdateNews =
case UPDATE_STEP::FILES_TO_DOWNLOAD: QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::FILES_TO_DOWNLOAD: {
ismasClient.setProgressInPercent(_FILES_TO_DOWNLOAD); ismasClient.setProgressInPercent(_FILES_TO_DOWNLOAD);
break; QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_JSON_FILE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::EXEC_OPKG_COMMANDS: case UPDATE_STEP::EXEC_OPKG_COMMANDS:
ismasClient.setProgressInPercent(_EXEC_OPKG_COMMANDS); ismasClient.setProgressInPercent(_EXEC_OPKG_COMMANDS);
break; break;
@@ -1228,15 +1289,180 @@ private:
ismasClient.sendRequestReceiveResponse( ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews); IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break; } break;
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE: case UPDATE_STEP::DOWNLOAD_CONFIG_FILE: {
ismasClient.setProgressInPercent(_DOWNLOAD_CONFIG_FILE); //ismasClient.setProgressInPercent(_DOWNLOAD_CONFIG_FILE);
break; ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS: QString const &ismasUpdateNews =
ismasClient.setProgressInPercent(_DOWNLOAD_CONFIG_FILE_SUCCESS); QString("#M=APISM#C=CMD_EVENT#J=") +
break; ismasClient.updateNewsToIsmas(
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE: _ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_CONFIG_FILE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS: {
//ismasClient.setProgressInPercent(_DOWNLOAD_CONFIG_FILE_SUCCESS);
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_CONFIG_FILE_SUCCESS],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE: {
ismasClient.setProgressInPercent(_DOWNLOAD_CONFIG_FILE_FAILURE); ismasClient.setProgressInPercent(_DOWNLOAD_CONFIG_FILE_FAILURE);
break; QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::JSON_FILES_DOWNLOAD_ERROR,
smap[UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE: {
//ismasClient.setProgressInPercent(_DOWNLOAD_CASH_FILE);
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_CASH_FILE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE: {
ismasClient.setProgressInPercent(_DOWNLOAD_CASH_FILE_FAILURE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::JSON_FILES_DOWNLOAD_ERROR,
smap[UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS: {
//ismasClient.setProgressInPercent(_DOWNLOAD_CASH_FILE_SUCCESS);
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE: {
//ismasClient.setProgressInPercent(_DOWNLOAD_DEVICE_FILE);
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_DEVICE_FILE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE: {
ismasClient.setProgressInPercent(_DOWNLOAD_DEVICE_FILE_FAILURE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::JSON_FILES_DOWNLOAD_ERROR,
smap[UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS: {
//ismasClient.setProgressInPercent(_DOWNLOAD_DEVICE_FILE_SUCCESS);
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE: {
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_JSON_FILE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE: {
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE_FAILURE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::JSON_FILES_DOWNLOAD_ERROR,
smap[UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS: {
ismasClient.setProgressInPercent(_DOWNLOAD_JSON_FILE);
QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER: case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER:
ismasClient.setProgressInPercent(_DOWNLOAD_DEVICE_CONTROLLER); ismasClient.setProgressInPercent(_DOWNLOAD_DEVICE_CONTROLLER);
break; break;
@@ -1274,9 +1500,20 @@ private:
case UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE: case UPDATE_STEP::DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE:
ismasClient.setProgressInPercent(_DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE); ismasClient.setProgressInPercent(_DOWNLOAD_FILES_TO_PSA_HARDWARE_FAILURE);
break; break;
case UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY: case UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY: {
ismasClient.setProgressInPercent(_SYNC_CUSTOMER_REPOSITORY); ismasClient.setProgressInPercent(_SYNC_CUSTOMER_REPOSITORY);
break; QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas(
_ISMAS_CONTINUE,
ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY],
instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
} break;
case UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS: { case UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS: {
ismasClient.setProgressInPercent(_SYNC_CUSTOMER_REPOSITORY_SUCCESS); ismasClient.setProgressInPercent(_SYNC_CUSTOMER_REPOSITORY_SUCCESS);
QString const &ismasUpdateNews = QString const &ismasUpdateNews =
@@ -1285,7 +1522,7 @@ private:
_ISMAS_CONTINUE, _ISMAS_CONTINUE,
ismasClient.getProgressInPercent(), ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS, IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY], smap[UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS],
instance->m_ismasMsg.join(' ').toStdString().c_str(), instance->m_ismasMsg.join(' ').toStdString().c_str(),
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A"); instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
ismasClient.sendRequestReceiveResponse( ismasClient.sendRequestReceiveResponse(
@@ -1315,31 +1552,36 @@ private:
ismasClient.setProgressInPercent(_SAVE_LOGS_FAILURE); ismasClient.setProgressInPercent(_SAVE_LOGS_FAILURE);
break; break;
case UPDATE_STEP::SEND_LAST_VERSION: { case UPDATE_STEP::SEND_LAST_VERSION: {
ismasClient.setProgressInPercent(_SEND_LAST_VERSION + _SEND_LAST_VERSION_CORRECTION); if (Worker::sendLastVersionOnce == false) {
ismasClient.sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, ismasClient.setProgressInPercent(_SEND_LAST_VERSION + _SEND_LAST_VERSION_CORRECTION);
QString("#M=APISM#C=CMD_SENDVERSION#J=") + ismasClient.sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT,
ismasClient.updateOfPSASendVersion(instance->getPSAInstalled())); QString("#M=APISM#C=CMD_SENDVERSION#J=") +
ismasClient.updateOfPSASendVersion(instance->getPSAInstalled()));
Worker::sendLastVersionOnce = true;
}
} break; } break;
case UPDATE_STEP::UPDATE_SUCCEEDED: { case UPDATE_STEP::UPDATE_SUCCEEDED: {
ismasClient.setProgressInPercent(_UPDATE_SUCCEEDED + _UPDATE_SUCCEEDED_CORRECTION); ismasClient.setProgressInPercent(_UPDATE_SUCCEEDED + _UPDATE_SUCCEEDED_CORRECTION);
QString const &ismasUpdateNews = if (instance->m_automaticUpdate == false) {
QString("#M=APISM#C=CMD_EVENT#J=") + QString const &ismasUpdateNews =
ismasClient.updateNewsToIsmas( QString("#M=APISM#C=CMD_EVENT#J=") +
_ISMAS_DONE, // WAIT-button set to 100% ismasClient.updateNewsToIsmas(
ismasClient.getProgressInPercent(), _ISMAS_DONE, // WAIT-button set to 100%
IsmasClient::RESULT_CODE::SUCCESS, ismasClient.getProgressInPercent(),
smap[UPDATE_STEP::UPDATE_FINALIZE], IsmasClient::RESULT_CODE::SUCCESS,
instance->m_ismasMsg.join(' ').toStdString().c_str(), smap[UPDATE_STEP::UPDATE_FINALIZE],
instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A"); instance->m_ismasMsg.join(' ').toStdString().c_str(),
ismasClient.sendRequestReceiveResponse( instance->m_versionInfo.size() >= 1 ? instance->m_versionInfo.at(0).toUtf8().constData() : "N/A");
IsmasClient::APISM::DB_PORT, ismasUpdateNews); ismasClient.sendRequestReceiveResponse(
IsmasClient::APISM::DB_PORT, ismasUpdateNews);
}
} break; } break;
case UPDATE_STEP::UPDATE_ACTIVATED: { case UPDATE_STEP::UPDATE_ACTIVATED: {
ismasClient.setProgressInPercent(_UPDATE_ACTIVATED + _UPDATE_ACTIVATED_CORRECTION); ismasClient.setProgressInPercent(_UPDATE_ACTIVATED + _UPDATE_ACTIVATED_CORRECTION);
QString const &ismasUpdateNews = QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") + QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas( ismasClient.updateNewsToIsmas(
_ISMAS_SET_WAIT_OK, // U0002 (instance->m_automaticUpdate ? _ISMAS_NO_UPDATE_NECESSARY : _ISMAS_SET_WAIT_OK), // U0002 or M0100
ismasClient.getProgressInPercent(), ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::SUCCESS, IsmasClient::RESULT_CODE::SUCCESS,
smap[UPDATE_STEP::UPDATE_FINALIZE], smap[UPDATE_STEP::UPDATE_FINALIZE],
@@ -1353,7 +1595,7 @@ private:
QString const &ismasUpdateNews = QString const &ismasUpdateNews =
QString("#M=APISM#C=CMD_EVENT#J=") + QString("#M=APISM#C=CMD_EVENT#J=") +
ismasClient.updateNewsToIsmas( ismasClient.updateNewsToIsmas(
_ISMAS_SET_WAIT_OK, // U0002 (instance->m_automaticUpdate ? _ISMAS_NO_UPDATE_NECESSARY : _ISMAS_SET_WAIT_OK), // U0002 or M0100
ismasClient.getProgressInPercent(), ismasClient.getProgressInPercent(),
IsmasClient::RESULT_CODE::NO_UPDATE_NECESSARY, IsmasClient::RESULT_CODE::NO_UPDATE_NECESSARY,
smap[UPDATE_STEP::UPDATE_FINALIZE], smap[UPDATE_STEP::UPDATE_FINALIZE],
@@ -1548,6 +1790,24 @@ private:
break; break;
case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE: case UPDATE_STEP::DOWNLOAD_CONFIG_FILE_FAILURE:
break; break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE: {
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE_FAILURE: {
} break;
case UPDATE_STEP::DOWNLOAD_CASH_FILE_SUCCESS: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE_FAILURE: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_FILE_SUCCESS: {
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE: {
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE_FAILURE: {
} break;
case UPDATE_STEP::DOWNLOAD_JSON_FILE_SUCCESS: {
} break;
case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER: case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER:
break; break;
case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_SUCCESS: case UPDATE_STEP::DOWNLOAD_DEVICE_CONTROLLER_SUCCESS:

View File

@@ -3,6 +3,10 @@
#include <QObject> #include <QObject>
#include <QStringList>
#include <optional>
#include <initializer_list>
class System : public QObject class System : public QObject
{ {
@@ -13,16 +17,17 @@ private:
static QString errorMsg; static QString errorMsg;
public: public:
static const QStringList allowedJsonFiles;
static bool checkForSDCard(); static bool checkForSDCard();
static bool umountSDCard(); static bool umountSDCard();
static bool checkForUSBStick(); static std::optional<QString> checkForUSBStick(QString const &dirPathUnderMountPath = ".");
static QString getUSBMountPath(); static QString getUSBMountPath(QString const &dirPathUnderMountPath = ".");
static QString getUSBDeviceName();
//static QString getUSBDeviceName();
static bool umountUSBStick(); static bool umountUSBStick();
static bool test_mount(const QString& dev, const QString &mountpoint); static bool test_mount(const QString& dev, const QString &mountpoint);
@@ -48,7 +53,7 @@ public:
static QString getPTU4SerialNumber(); static QString getPTU4SerialNumber();
static QString getPTU4MACAddress(); static QString getPTU4MACAddress();
static QStringList getJsonFilesOnUsbStick(QString const &mountPath);
}; };

View File

@@ -0,0 +1,23 @@
#ifndef MESSAGE_HANDLER_H_INCLUDED
#define MESSAGE_HANDLER_H_INCLUDED
#include <QtGlobal>
#ifdef __linux__
#include <syslog.h>
#endif
int getDebugLevel();
void setDebugLevel(int newDebugLevel);
bool messageHandlerInstalled();
QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler);
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
// typedef void (*QtMessageHandler)(QtMsgType, const char *);
void atbDebugOutput(QtMsgType type, const char *msg);
#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);
void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
#endif
#endif // MESSAGE_HANDLER_H_INCLUDED

View File

@@ -7,10 +7,52 @@
#include <QRegExp> #include <QRegExp>
#include <QStringList> #include <QStringList>
#include <QDebug> #include <QDebug>
#include <QDirIterator>
//#include "version.h" //#include "version.h"
const QStringList System::allowedJsonFiles =
std::initializer_list<QString>{
QString("DC2C_conf.json"),
QString("DC2C_cash.json"),
QString("DC2C_device.json"),
QString("DC2C_print01.json"),
QString("DC2C_print02.json"),
QString("DC2C_print03.json"),
QString("DC2C_print04.json"),
QString("DC2C_print05.json"),
QString("DC2C_print06.json"),
QString("DC2C_print07.json"),
QString("DC2C_print08.json"),
QString("DC2C_print09.json"),
QString("DC2C_print10.json"),
QString("DC2C_print11.json"),
QString("DC2C_print12.json"),
QString("DC2C_print13.json"),
QString("DC2C_print14.json"),
QString("DC2C_print15.json"),
QString("DC2C_print16.json"),
QString("DC2C_print17.json"),
QString("DC2C_print18.json"),
QString("DC2C_print19.json"),
QString("DC2C_print20.json"),
QString("DC2C_print21.json"),
QString("DC2C_print22.json"),
QString("DC2C_print23.json"),
QString("DC2C_print24.json"),
QString("DC2C_print25.json"),
QString("DC2C_print26.json"),
QString("DC2C_print27.json"),
QString("DC2C_print28.json"),
QString("DC2C_print29.json"),
QString("DC2C_print30.json"),
QString("DC2C_print31.json"),
QString("DC2C_print32.json")
};
QString System::errorMsg = ""; QString System::errorMsg = "";
System::System(QObject *parent) : System::System(QObject *parent) :
@@ -209,8 +251,7 @@ bool System::test_dir(const QString& dir)
bool System::checkForUSBStick() std::optional<QString> System::checkForUSBStick(QString const &dirPathUnderMountPath) {
{
#if defined (ARCH_DesktopLinux) #if defined (ARCH_DesktopLinux)
// DEBUG / TEST: // DEBUG / TEST:
if (QFileInfo(getUSBMountPath()).isDir()) if (QFileInfo(getUSBMountPath()).isDir())
@@ -219,11 +260,9 @@ bool System::checkForUSBStick()
return false; return false;
#endif #endif
if (getUSBMountPath().isEmpty()) { QString const &mountPath = getUSBMountPath(dirPathUnderMountPath);
return false; // qCritical() << "MOUNT-PATH" << mountPath;
} return mountPath.isEmpty() ? std::nullopt : std::optional<QString>(mountPath);
return true;
} }
@@ -235,8 +274,7 @@ bool System::checkForUSBStick()
* Note, do not return an empty string ("") here because a calling method (which could not be * Note, do not return an empty string ("") here because a calling method (which could not be
* identified till now) is relying on this! * identified till now) is relying on this!
*/ */
QString System::getUSBMountPath() QString System::getUSBMountPath(QString const &dirPathUnderMountPath) {
{
#if defined (ARCH_DesktopLinux) #if defined (ARCH_DesktopLinux)
// DEBUG / TEST: // DEBUG / TEST:
@@ -277,8 +315,13 @@ QString System::getUSBMountPath()
mountLine = line.split(' '); mountLine = line.split(' ');
if (mountLine.size() > 3) { if (mountLine.size() > 3) {
qDebug() << "System::getUSBMountPath(): " << mountLine.at(0) << " is mounted on " << mountLine.at(2); qCritical() << "System::getUSBMountPath(): " << mountLine.at(0) << " is mounted on " << mountLine.at(2);
return mountLine.at(2); QDir d(QDir::cleanPath(mountLine.at(2) + QDir::separator() + dirPathUnderMountPath));
if (d.exists()) {
return mountLine.at(2);
} else {
qCritical() << "directory" << d.absolutePath() << "does not exist";
}
} }
} }
} }
@@ -289,6 +332,27 @@ QString System::getUSBMountPath()
return ""; return "";
} }
QStringList System::getJsonFilesOnUsbStick(QString const &mountPath) {
QStringList jsonFiles;
// /media/sda2/etc/psa_config
QString const &dirPath = QDir::cleanPath(mountPath + QDir::separator() + "etc" + QDir::separator() + "psa_config");
QDir d(dirPath);
if (d.exists()) {
QDirIterator it(dirPath, QStringList() << "*.json", QDir::Files, QDirIterator::NoIteratorFlags);
while (it.hasNext()) {
QString const &jsonFile = it.next();
QFileInfo fi(jsonFile);
if (System::allowedJsonFiles.contains(fi.fileName())) {
jsonFiles << jsonFile;
} else {
qCritical() << "Warning:" << fi.fileName() << "unknown";
}
}
}
return jsonFiles;
}
/******************************************************************************** /********************************************************************************
* static function to check if a mounted sd-card is writable. * static function to check if a mounted sd-card is writable.

97
common/src/message_handler.cpp Executable file
View File

@@ -0,0 +1,97 @@
#include "message_handler.h"
#include <QDateTime>
#include <cstring>
#include <QString>
#include <QFileInfo>
#include <QMessageLogContext>
static char const *DBG_NAME[] = { "DBG ", "WARN ", "CRIT ", "FATAL", "INFO " };
static bool installedMsgHandler = false;
static int debugLevel = LOG_NOTICE;
int getDebugLevel() { return debugLevel; }
void setDebugLevel(int newDebugLevel) {
debugLevel = newDebugLevel;
}
bool messageHandlerInstalled() {
return installedMsgHandler;
}
QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) {
installedMsgHandler = (handler != 0);
static QtMessageHandler prevHandler = nullptr;
if (handler) {
prevHandler = qInstallMessageHandler(handler);
return prevHandler;
} else {
return qInstallMessageHandler(prevHandler);
}
}
///
/// \brief Print message according to given debug level.
///
/// \note Install this function using qInstallMsgHandler().
///
/// int main(int argc, char **argv) {
/// installMsgHandler(atbDebugOutput);
/// QApplication app(argc, argv);
/// ...
/// return app.exec();
/// }
///
#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
Q_UNUSED(context);
QString const localMsg = QString(DBG_NAME[type]) + msg.toLocal8Bit();
switch (debugLevel) {
case LOG_DEBUG: { // debug-level message
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
} break;
case LOG_INFO: { // informational message
if (type != QtDebugMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
case LOG_NOTICE: { // normal, but significant, condition
if (type != QtDebugMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
case LOG_WARNING: { // warning conditions
if (type != QtInfoMsg && type != QtDebugMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
case LOG_ERR: { // error conditions
if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
case LOG_CRIT: { // critical conditions
if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
case LOG_ALERT: { // action must be taken immediately
if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
case LOG_EMERG: { // system is unusable
if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
}
} break;
default: {
//fprintf(stderr, "%s No ErrorLevel defined! %s\n",
// datetime.toStdString().c_str(), msg.toStdString().c_str());
}
}
}
#endif