Compare commits

..

122 Commits

Author SHA1 Message Date
990d257b09 Make sure the dc-data are vaild: set again the auto-request flag inside the CA-plugin.w 2023-11-07 09:33:42 +01:00
dfbad69ab1 Add some comments. Set version to 1.3.15. Removed worker_thread.h/.cpp. 2023-11-07 09:24:32 +01:00
5f0c86ba19 Minor: removed obsolete test-code. 2023-11-07 09:23:43 +01:00
3588b25e65 Removed any references to CA-plugin from MainWindow. 2023-11-07 09:18:04 +01:00
1f8b88b2b6 Update-object now proper memeber of worker-thread.w 2023-11-07 09:14:49 +01:00
0050ea35d0 Update to new interfaces.h 2023-11-07 09:13:15 +01:00
7e4c138d1b Fixed getDCVersion() as part of turning worker-object into its own
thread.
2023-11-07 09:12:17 +01:00
685568d4f6 Call execOpkgCommands(0 and downloadTpPSAHardware() helpers. 2023-11-07 09:11:42 +01:00
14b4c035da Add computeFilesToUpdate() and downloadFilesToPSA() helper functions. 2023-11-07 09:10:45 +01:00
90de2f415e Add new members to worker-class. 2023-11-07 09:10:01 +01:00
3cc71cb69b Minor: remove obsolete code. 2023-11-07 09:09:26 +01:00
fef7533d00 Minor: replace APPLY_... with DOWNLOAD... enum-variables. 2023-11-07 09:08:33 +01:00
e93058cc6b Turn worker-object into a thread. Don't do a moveToThread() anymore. 2023-11-07 09:07:08 +01:00
e65387aa60 Turned worker-object into a thread 2023-11-07 09:04:05 +01:00
904fa0374b Minor: removed empty line 2023-11-07 09:00:25 +01:00
4bf1bbe81f Removed references to update and ca-plugin.w 2023-11-06 16:23:43 +01:00
3ccdcbae51 Removed generation of upodate-object. This will be donw inside
worker(-thread), and only when it is really needed, i.e. when there
are json-files to be updated (or a deveice-controller).
2023-11-06 16:20:27 +01:00
8c50e6cf59 Added command-line option no-psa-hardware-update (future use for
multipass).
2023-11-06 16:19:36 +01:00
7e69846169 Minor: removed obsolete code (commented out). 2023-11-06 16:15:31 +01:00
34c55c576c Use new masterlib. NOTE: furture versions have to use the slave lib. 2023-11-03 13:50:22 +01:00
7c2c4d4b80 Use new interface file. 2023-11-03 13:49:56 +01:00
f9f698fd15 Save for the weekend: set version to 1.3.15. 2023-11-03 13:49:28 +01:00
b4457d8815 Fix debugging output. 2023-11-03 13:46:23 +01:00
3621777827 Do not disable the exit button. 2023-11-03 13:45:54 +01:00
003bd0bf77 Check if repository is corrupted: do not check for etc/ or
opt/-directories, as they may be not existent inside of the repository.
2023-11-03 13:44:15 +01:00
721c5dd7a5 MAke sure removeDuplicates() is called for list containing file to be
updated.
2023-10-31 09:16:24 +01:00
a24eb9fd8c Minor: removed unused, obsolete code (commented out). 2023-10-31 09:14:02 +01:00
24351b8342 Minor: add runtime information in debug output. 2023-10-31 09:12:43 +01:00
4b3a39b0e6 Set version to 1.3.14.
Add compile flag -C (so it is possible to use /*fall through*/ without
having the proprocessor to remove this comment.
2023-10-30 15:35:38 +01:00
a44b780d93 Minor: Add header for using RAII in sending SEND-LAST-VERSION to ISAMS. 2023-10-30 15:29:23 +01:00
19dfae9b56 Use output functions ISMAS(), GUI() and CONSOLE(), which point to friend
operators<< in Worker-class.
2023-10-30 15:28:25 +01:00
bef0d4fe12 Refactor the update process: streamline code. When WAIT button is not
active, the a clone or a fix of a defunct repository is possible, but
not more.
If WAIT button is active, the at least the opkg_commnds are executed. If
there are chenged files, they are handkled as wll.
2023-10-30 15:25:49 +01:00
72a2fc781c Minor: reove obsolete m_returnCode. 2023-10-30 15:24:33 +01:00
fc264689b1 Use and implement getAPISMYoctoVersion() and
getAPISMYoctoInstallationSTatus().
2023-10-30 15:22:59 +01:00
fc587456d5 Filling the QMap Worker:smap with data. 2023-10-30 15:21:26 +01:00
a2b933ab71 Minor: Added UPDATE_STEP_WRONG. 2023-10-30 15:20:15 +01:00
7d0fdf4d6d Small fixes:
1: fixed wrong parameters of a connect().
2: Minor: improved onQuit().
2023-10-30 15:17:59 +01:00
c2ce44c79b Adding three friend operator<< functions to output status information of
the update process: the first on outputs to CONSOLE(), the second one
outputs to ISMAS() and the last one to GUI(), i.e. the text edit of the
main window.
2023-10-30 15:15:30 +01:00
16a9556863 bool customerEnvironment();
bool filesToUpdate();
bool updateFiles();
bool syncCustomerRepositoryAndFS();
bool saveLogFile(): remove progress parameter.
2023-10-30 15:14:19 +01:00
48896f97ec Adding UPDATE_STEP_WRONG: helper variable to be used in text edit of
main window.
2023-10-30 15:13:04 +01:00
4486317cb2 dd declaration for getAPISMYoctoVersion() and
getAPISMYoctoInstallationStatus(): the first one returning the
yocto-version
of APIS, the second returning the installation status of APIS as display
in 'opkg info'.
2023-10-30 15:11:06 +01:00
6b9b88ea19 Adding member variables to check if customer repository was a fresh
clone, or if it was already existent.
2023-10-30 15:09:33 +01:00
99a99d95a1 Adding UPDATE_STEP enum plus associated interger defines.
Adding QMap: Worker::smap, which contains names of UPDATE_STEP-members.
2023-10-30 15:07:28 +01:00
d4ddbbee21 Add class UpdateProcessRunning: use for sending SEND-LAST-VERSION as
part of its destruktor: RAII-pattern.
2023-10-30 15:05:30 +01:00
34e5189945 comment out some debug output -> too much output. 2023-10-30 15:03:35 +01:00
c44c805238 Use some special output methods using ISMAS(), GUI() nad CONSOLE(). 2023-10-30 15:00:57 +01:00
196f1a730e gitPull(): don't use regex anumore, but just plain
string-matching/searching.
Regex seems to be quite error-prone.
2023-10-30 14:59:58 +01:00
7dc04c4422 Add helper function worker(), returning the worker-object. 2023-10-30 14:56:19 +01:00
5efac2619b sicherung der aenderungen 2023-10-23 16:16:11 +02:00
9b0f741b9b to be continued on monday 2023-10-22 19:44:45 +02:00
81c5f8ee7e Save for the weekend. 2023-10-20 13:55:18 +02:00
29e6a25e72 Add comment for version 1.3.13 2023-10-19 13:45:52 +02:00
5abc057bda Minor: add possible debug messages. 2023-10-19 13:44:51 +02:00
8aeb7ecfea Don't check opkg_commands-file in the system-filesystem to remove
confusing error-messages.
2023-10-19 13:43:53 +02:00
4bb8e241b6 Update process: check sanity of customer repository: are etc/ and
opt/directories contained? If not, remove the repository and clone it
again. This is done without checking the ISMAS-WAIT-button.
2023-10-19 13:41:44 +02:00
4469a23f9c Implemented helpers:
bool isRepositoryCorrupted();
    bool repairCorruptedRepository();

    int sendCloneAndCheckoutSuccess();
    int sendCloneAndCheckoutFailure();
    int sendIsmasTriggerFailure();
2023-10-19 13:39:48 +02:00
d1f795e2db Added helpers:
bool isRepositoryCorrupted();
    bool repairCorruptedRepository();

    int sendCloneAndCheckoutSuccess();
    int sendCloneAndCheckoutFailure();
    int sendIsmasTriggerFailure();

and static variables

    static constexpr const int CLONE_AND_CHECKOUT_SUCCESS = 0;
    static constexpr const int CLONE_AND_CHECKOUT_FAILURE = -3;
    static constexpr const int ISMAS_TRIGGER_FAILURE = -5;
2023-10-19 13:38:16 +02:00
6865056f4b Replace regex in gitCloneCustomerRepository() with straight-forward
steing-handling: regex sometimes returned error.
2023-10-19 13:35:07 +02:00
37bd5c90d3 Add printUpdateStatus() helper for QString 2023-10-19 13:34:07 +02:00
fcba120dfa Minor: commented out unnecessary debug/info output 2023-10-18 16:21:44 +02:00
1d4f50fb9f Add printing-utils that also take string-lists 2023-10-18 16:20:49 +02:00
a78040a037 Minor: add error-debug-message in ase customer-nr is wrong 2023-10-18 16:19:37 +02:00
9b175d7789 Set version to 1.3.12 2023-10-18 11:45:54 +02:00
2d7f145a25 Replaced using gitFetch() with gitPull() 2023-10-18 11:40:04 +02:00
4589c4ca76 Removed gitFetchAndDiff() and original version of gitPull(). 2023-10-18 11:38:26 +02:00
a32258a59e Replaced "git fetch" with "git pull". 2023-10-18 11:37:46 +02:00
22f25e5251 Replaced 'git clone' with 'git clone --filter=blob:none' to speed
up cloning of customer-repository.
2023-10-18 11:36:13 +02:00
258d883a51 Replaced gitFetch() with gitPull() 2023-10-18 11:35:23 +02:00
504e242d42 Implemented getATBUpdateToolYoctoVersion() and getATBUpdateToolYoctoInstallationStatus() 2023-10-18 11:31:15 +02:00
731cdcbe09 Added getATBUpdateToolYoctoVersion() and getATBUpdateToolYoctoInstallationStatus() 2023-10-18 11:30:12 +02:00
b4e2d4c54a Minor: Move reading of machine_nr, customer_nr and zone_nr upwards. 2023-10-18 11:28:06 +02:00
42961dea40 Add command-parameters yoctoVersionOption (yocto-version of
ATBUpdateTool as reported by opkg), and yoctoInstallStatusOption (info
if ATBUpdateTool is installed as reported by opkg).
2023-10-18 11:26:30 +02:00
fd2f601f67 Add printAupdateStatusMsg(). 2023-10-18 11:21:32 +02:00
b45af505cd Minor: change output format. 2023-10-18 11:21:08 +02:00
2dfe80b654 Add printUpdateStatusMsg() 2023-10-18 11:20:31 +02:00
4b9dcc5e99 Set version to 1.3.11: integrate extended version (VERSION + last git
commit) in send-last-version-message.
2023-10-12 12:13:49 +02:00
53639b55c9 Integrate call parameter -V (= --extended-version) to show extended
version (including last git commit)
2023-10-12 12:12:16 +02:00
3a83efbd3f Integrate extended version of ATBUpdateTool into send-last-version command to ISMAS. 2023-10-12 12:11:48 +02:00
c9d6a8d245 Integrate extended version of ATBUpdateTool into send-last-version 2023-10-12 12:10:24 +02:00
91db59b9f3 Integrate version of ATBUpdateTool in send-last-version. 2023-10-12 12:09:19 +02:00
1d81e6b650 Minor: removed unused code. 2023-10-12 12:08:19 +02:00
6d57b45d1a Use getATBQTVersion() for dynamic value of atbapp. 2023-10-12 12:07:38 +02:00
4e7ce2cd70 set version to 1.3.10: remove timeout on opkg-commands. tested download of DC2C_cash.conf file. 2023-10-10 16:05:16 +02:00
47fac31223 remove timeout for process runtime for opkg-commands 2023-10-10 16:03:52 +02:00
0d353cfbcf Check if opkg_command failed, and if this is the case, stop the
update-process without showing a wrong UPDATE-SUCCESS.
2023-10-10 16:01:45 +02:00
bdcb073bf8 set version to 1.3.9 2023-10-10 14:26:20 +02:00
226553a8ab Set version to 1.3.9 after fix of gitShowReason(). 2023-10-09 15:57:11 +02:00
d4ee56559b Use getShowReason() with branchName. Use getOsVersion(0 and
getApismVersion().
2023-10-09 15:54:58 +02:00
355b28ba40 Use current branch name in gitShowReason(), not just master 2023-10-09 15:53:35 +02:00
edeff35d7e Activate download of json-configuration files. 2023-10-06 13:02:23 +02:00
09d5de1b0b rsync: check if source directories in customer repositories exist. 2023-10-06 13:00:25 +02:00
145fdab26e Minor: fixed output format (in text edit) 2023-10-06 13:00:00 +02:00
89d1ec5b21 Deactivate download of device controller. Will be added in coming
version.
2023-10-06 12:58:38 +02:00
f38c975dc6 Remove check for which parent has started atbupdatetool: it is always
systemd now.
2023-10-06 12:57:38 +02:00
fba007aa35 Activate download of json-configuration files. 2023-10-06 12:56:03 +02:00
8b6adb3ea7 Scrolldown text edit at end of whole update process to show
UPDATE_SUCCESS message.
2023-10-06 12:51:30 +02:00
30603317c6 Minor: Add debug messages or change debug message format. 2023-10-06 10:47:08 +02:00
7083f3b4f8 Minor: add debug message. 2023-10-06 10:44:55 +02:00
7ff866525e Fix: allow for json-files EC2C_conf/cash/device.json as well. 2023-10-06 10:43:55 +02:00
2164037123 Do not use opkg_commnands-file as located in the filesystem under
/etc/psa_update anymore.
2023-10-06 10:42:35 +02:00
2e7d33c4c8 Set version to 1.3.7: wait forever for git-commands to finish in QProcess. 2023-10-05 10:54:19 +02:00
2a2751f6f3 Add creation of BUILD_DATE and BUILD_TIME 2023-10-04 14:34:54 +02:00
2764ef4371 Output of current tool version at program startup 2023-10-04 14:33:52 +02:00
9783f343e1 Set version to 1.3.6: exec opkg-commands even for unchanged opkg-commnds-file 2023-10-04 13:23:06 +02:00
8c6f0dfcc7 Minor: use Q_UNUSED() for unused parameters 2023-10-04 13:21:49 +02:00
d688ad3d5c Minor: comments 2023-10-04 10:34:56 +02:00
7b3f652b0e Deactivated doUpdate 2023-10-04 10:20:52 +02:00
4cc42b2a65 Set version to 1.3.6. Removed DCPlugin related stuff. 2023-09-28 12:11:47 +02:00
d783fd7fb6 Minor: print info instead of critical message when git fetch is empty 2023-09-28 12:09:57 +02:00
e0a0ff54e1 Added comment for U00-ISMAS values. Deactivated finalResult() 2023-09-28 12:08:42 +02:00
863d052a21 Removed debug info in appendText()/replcaeLst(). 2023-09-28 12:06:28 +02:00
61b3d29e31 Disable text-edit (showing update-status) ehen update procedure
finished.
2023-09-28 12:05:07 +02:00
cac4f7249e Minor: Add progress parameters. 2023-09-28 12:01:55 +02:00
3223c430be Do not rsync opkg_commnds to local file systems: this sync is not needed. 2023-09-28 12:00:24 +02:00
c09682ea33 Always execute commands contained in opkg_commands, even if no
change in opkg_commands. WAIT button in ISMAS must still be activated.
2023-09-28 11:57:17 +02:00
fef1d43d5f Adapated information of update-progress-status. 2023-09-28 11:56:20 +02:00
705424727b Removed call to final-result: ISMAS will not show U0002 twice. 2023-09-28 11:53:59 +02:00
b96f0896e3 Add explicit message when update-process is starting. 2023-09-28 11:53:10 +02:00
a3967c76ac Use showFullScreen() instead of using a flag 2023-09-28 11:47:09 +02:00
1197598a3d Set version to 1.3.5 2023-09-21 16:52:42 +02:00
ec13e97226 Update interfaces.h to HWapi/4.6 2023-09-21 15:55:31 +02:00
a8dd9d7e24 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/UpdatePTUDevCtrl 2023-09-21 15:50:19 +02:00
17 changed files with 2515 additions and 1503 deletions

View File

@@ -15,47 +15,111 @@ DEFINES += QT_DEPRECATED_WARNINGS
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
VERSION=1.3.4
# 1.3.6 : Do not update device-controller/json files, but have the library
# (in a later step) do that.
# Fixed sending messages to ISMAS.
# Always execute contents of opkg_commands-file (even if there are no
# changes).
# 1.3.7 : Wait forever for git-commands to finish in QProcess executing such
# a command.
# 1.3.8 : Remove accessing opkg_commands under file-system-path /etc/psa_update.
# Activate download of json-configuration files.
# 1.3.9 : Fix sendLastVersion: use configured branch and not master branch in
# git show origin/master -s --format="c=%h m=%s d=%cI" ==>
# git show origin/zg1/zone1 -s --format="c=%h m=%s d=%cI"
# Use dynamic values for os-release and apism-version when sending
# last version info.
# 1.3.10: Fix premature killing opkg-commands: detected timeout of 100s was
# too small when updating apism.
# Fix display of UPDATE_SUCCESS when opkg_command fails. Detected when
# updating apsim failed.
# 1.3.11: Integrate version of ATBUpdateTool in SendLastVersion-ISMAS-message.
# 1.3.12: Add command parameters for output of yocto-infos about ATBUpdateTool.
# Use 'git pull' instead of 'git fetch'.
# Use 'git clone --filter=blob:none' instead of 'git clone' to speed
# up cloning of customer repository.
# 1.3.13: Fix: if the customer repository is corrupted, remove it and re-clone
# the repository (without checking the ISMAS-trigger (WAIT-)button.
# 1.3.14: Add additional check for sanity of customer repository using
# "git fsck".
# Stream-lined code of update process: massive refactoring.
# Added functionality: If WAIT button is not active, then an existing
# customer repository will be repaired, or a not existing repository
# will be cloned. The process stops then.
# However, if the WAIT button is active, the at least the commands in
# opkg_commands will be executed. Changed files in the customer
# repository will be worked on: tariff-files will be synced with the
# local filesystem, json-files will be downloaded to firmware.
# The device-controller firmware will be handled in a later version.
VERSION="1.3.15"
# Bug fixes found during testing.
# Don't disable Exit-button during update-process.
# Removed worker-thread with an own event-loop: only the GUI thread
# has an event loop. Tested JSON-downloads several times successfully
# (using the slave lib where the CA helper tool was active as master).
# Turned previous worker-object into its own thread, but without any
# own event-loop (so it cannot block anything inside the CA-plugin).
# PLANNED TODOS:
# 1: Das Repository wird repariert bwz. neu geklont. Unabhaengig vom WAIT.
# 2: Wenn der WAIT-Button aktiv ist, dann wird ein Repository repariert (neu
# geklont), aber zusaetzlich werden alle verfuegbaren Dateien als neu
# angesehen und die entsprechenden Aktionen durchgefuehrt: tariff-files
# spiegeln, json-files laden und dc laden. Also VORSICHT: das repository
# muss in diesem fall wirklich in ordnung sein.
# 3: Wurde keine Datei geaendert, kein initiales Clone und der WAIT-button
# nicht aktiv, so (passiert natuerlich nichts) kann man davon ausgehen,
# dass es sich um ein automatisches Update handelt. Dann koennte man im
# ISMAS eine entsprechende Meldung anzeigen als Teil von SEND-LAST-VERSION.
# Wenn der WAIT-button aktiv ist, dann werden zumindest die opkg-commands
# ausgefuehrt.
# 4: rsync: immer alle Dateien soiegeln (bis auf opkg-commands)
# 5: Falls das Tool mal abstuerzt, dann einen Signal-Handler (fuer TERM)
# installieren, sodass zumnidest SEND-LAST-VERSION mit rausgeht.
# 6: rsync: explizites Binary, nicht das in busybox enthaltene.
# 7: Ein ini-File oder sowas.
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
}
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
INCLUDEPATH += plugins
CONFIG += c++17 console
CONFIG += c++17
# CONFIG -= app_bundle
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
# keep comments, as /* fall through */
QMAKE_CXXFLAGS += -C
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# custom target for 'git subtree'
# subtree.target = subtree
# subtree.commands = git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# subtree.depends =
# QMAKE_EXTRA_UNIX_TARGETS += subtree
# ! exists(DCPlugin) {
# $$system("git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
# } else {
# $$system("git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
# }
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -std=c++17 # for GCC >= 4.7
QMAKE_CXXFLAGS += -Wno-deprecated-copy
QMAKE_CXXFLAGS += -O2 -std=c++17 # for GCC >= 4.7
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
ARCH = PTU5
DEFINES+=PTU5
}
contains( CONFIG, PTU5_YOCTO ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
QMAKE_CXXFLAGS += -std=c++17 # for GCC >= 4.7
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
PTU5BASEPATH = /opt/devel/ptu5
ARCH = PTU5
DEFINES+=PTU5
@@ -69,7 +133,7 @@ contains( CONFIG, DesktopLinux ) {
# QMAKE_CC = ccache $$QMAKE_CC
# QMAKE_CXX = ccache $$QMAKE_CXX
QMAKE_CXXFLAGS += -std=c++17
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux
DEFINES+=DesktopLinux
@@ -86,8 +150,7 @@ SOURCES += \
ismas/ismas_client.cpp \
process/command.cpp \
message_handler.cpp \
worker.cpp \
worker_thread.cpp
worker.cpp
HEADERS += \
update.h \
@@ -101,24 +164,11 @@ HEADERS += \
process/command.h \
message_handler.h \
worker.h \
worker_thread.h \
plugins/interfaces.h
FORMS += \
mainwindow.ui
OTHER_FILES += \
/opt/app/tools/atbupdate/update_log.csv \
main.cpp.bck \
main.cpp.bck2 \
main.cpp.bck3
# https://blog.developer.atlassian.com/the-power-of-git-subtree/?_ga=2-71978451-1385799339-1568044055-1068396449-1567112770
# git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# include(./DCPlugin/DCPlugin.pri)
##########################################################################################
# for running program on target through QtCreator

View File

@@ -26,29 +26,93 @@ GitClient::GitClient(QString const &customerNrStr,
}
bool GitClient::gitCloneCustomerRepository() {
QString gitCommand("git clone ");
/* Blobless clone
==============
When using the --filter=blob:none option, the initial git clone will
download all reachable commits and trees, and only download the blobs
for commits when you do a git checkout. This includes the first checkout
inside the git clone operation.
The important thing to notice is that we have a copy of every blob at
HEAD but the blobs in the history are not present. If your repository
has a deep history full of large blobs, then this option can
significantly reduce your git clone times. The commit and tree data is
still present, so any subsequent git checkout only needs to download
the missing blobs. The Git client knows how to batch these requests to
ask the server only for the missing blobs.
Further, when running git fetch in a blobless clone, the server only
sends the new commits and trees. The new blobs are downloaded only
after a git checkout. Note that git pull runs git fetch and then git
merge, so it will download the necessary blobs during the git merge
command.
When using a blobless clone, you will trigger a blob download whenever
you need the contents of a file, but you will not need one if you only
need the OID (object-id) of a file. This means that git log can detect
which commits changed a given path without needing to download extra
data.
This means that blobless clones can perform commands like git
merge-base, git log, or even git log -- <path> with the same performance
as a full clone.
Commands like git diff or git blame <path> require the contents of the
paths to compute diffs, so these will trigger blob downloads the first
time they are run. However, the good news is that after that you will
have those blobs in your repository and do not need to download them a
second time. Most developers only need to run git blame on a small
number of files, so this tradeoff of a slightly slower git blame command
is worth the faster clone and fetch times.
Note: git v2.18 does not support treeless clones: --filter=tree:0.
*/
// Note: for some reason it is necessary to pass "--progress ---v",
// otherwise QProcess returns an error of 128 = 0x80 for the command.
QString gitCommand("git clone --progress -vvv --filter=blob:none ");
gitCommand += m_repositoryPath;
Command c(gitCommand);
qInfo() << "IN CURRENT WD" << m_workingDirectory
<< "CLONE" << m_repositoryPath << "...";
<< "CLONE VIA COMMAND" << gitCommand;
if (c.execute(m_workingDirectory)) { // execute the command in wd
QString const result = c.getCommandResult();
if (!result.isEmpty()) {
// Cloning into 'customer_281'...\n
static QRegularExpression re("(^\\s*Cloning\\s+into\\s+[']\\s*)(.*)(\\s*['].*$)");
QRegularExpressionMatch match = re.match(result);
if (match.hasMatch()) {
if (re.captureCount() == 3) { // start with full match (0), then the other 3 matches
if (match.captured(2).trimmed() == m_customerNr) {
qInfo() << "CLONING" << m_repositoryPath << "OK";
return true;
int customer = -1;
int cloning = result.indexOf("Cloning", 0, Qt::CaseInsensitive);
if (cloning != -1) {
customer = result.indexOf("customer_", cloning, Qt::CaseInsensitive);
if (customer != -1) {
QString customerNr = result.mid(customer);
static constexpr char const ch = '\'';
int i = customerNr.indexOf(QChar(ch));
if (i != -1) {
if ((customerNr = customerNr.mid(0, i)) == m_customerNr) {
qInfo() << "CLONING" << m_repositoryPath << "OK";
return true;
}
Utils::printCriticalErrorMsg(
QString("ERROR CLONE RESULT HAS WRONG CUSTOMER-NR. (%1 != %2) CLONE_RESULT=%3")
.arg(customerNr)
.arg(m_customerNr)
.arg(result));
return false;
}
}
}
Utils::printCriticalErrorMsg(
QString("ERROR CLONE RESULT HAS WRONG FORMAT. CLONING=%1 CUSTOMER=%2 CLONE_RESULT=%3")
.arg(cloning)
.arg(customer)
.arg(result));
return false;
}
Utils::printCriticalErrorMsg(QString("ERROR CLONE RESULT HAS WRONG FORMAT. CLONE_RESULT=") + result);
Utils::printCriticalErrorMsg("ERROR CLONE RESULT IS EMPTY");
}
return false;
}
@@ -114,16 +178,14 @@ bool GitClient::gitCloneAndCheckoutBranch() {
return false;
}
QStringList GitClient::gitShowReason() {
QStringList GitClient::gitShowReason(QString branchName) {
QStringList lst;
if (QDir(m_customerRepository).exists()) {
// %h: commit (short form)
// %s: commit message
// %cI: commit date, strict ISO 8601 format
// Note: use master branch. By convention, there is a ChangeLog file
// in the root of the repository, which has to be always the last file
// to be checked in when the customer repository somehow changed.
Command c("git show origin/master -s --format=\"c=%h m=%s d=%cI\"");
// Note: branch with branchName has to exist: format zg1/zone1
Command c(QString("git show origin/%1 -s --format=\"c=%h m=%s d=%cI\"").arg(branchName));
if (c.execute(m_customerRepository)) {
QString const s = c.getCommandResult().trimmed();
int const c = s.indexOf("c=");
@@ -217,92 +279,88 @@ std::optional<QStringList> GitClient::gitDiff(QString const &commits) {
return std::nullopt;
}
bool GitClient::gitFsck() {
bool r = false;
if (QDir(m_customerRepository).exists()) {
Command c("git fsck");
if ((r = c.execute(m_customerRepository)) == false) {
QString const &s = c.getCommandResult().trimmed();
Utils::printCriticalErrorMsg(QString("GIT FSCK FAILED: %1").arg(s));
}
}
return r;
}
/*
Hat sich nichts geaendert, so werden auch keine Commits <>..<> angezeigt
*/
std::optional<QString> GitClient::gitFetch() {
std::optional<QString> GitClient::gitPull() {
if (QDir(m_customerRepository).exists()) {
qInfo() << "BRANCH NAME" << m_branchName;
Command c("git fetch");
Command c("git pull");
if (c.execute(m_customerRepository)) {
QString const s = c.getCommandResult().trimmed();
if (!s.isEmpty()) {
QStringList lines = Update::split(s, '\n');
worker()->CONSOLE(lines) << Worker::UPDATE_STEP::UPDATE_REPOSITORY;
if (!lines.empty()) {
int zoneNr = Utils::read1stLineOfFile("/mnt/system_data/zone_nr");
m_branchName = (zoneNr != 0) ? QString("zg1/zone%1").arg(zoneNr) : "master";
// lines can look like this:
// From https://git.mimbach49.de/GerhardHoffmann/customer_281
// 41ec581..5d25ac3 master -> origin/master
// ff10f57..43530a1 zg1/zone1 -> origin/zg1/zone1
// 6ed893f..5d9882c zg1/zone2 -> origin/zg1/zone2
// 4384d17..77045d8 zg1/zone3 -> origin/zg1/zone3
// 89d2812..36a0d74 zg1/zone5 -> origin/zg1/zone5
bool found = false;
for (int i=0; i < lines.size(); ++i) {
if (lines.at(i).contains(m_branchName)) {
found = true;
// 409f198..6c22726 zg1/zone1 -> origin/zg1/zone1
static QRegularExpression re("(^\\s*)([0-9A-Fa-f]+..[0-9A-Fa-f]+)(.*$)");
QRegularExpressionMatch match = re.match(lines.at(i));
if (match.hasMatch()) {
if (re.captureCount() == 3) { // start with full match (0), then the other 3 matches
return match.captured(2);
static const QRegularExpression alreadyUpToDate("^\\s*Already\\s+up\\s+to\\s+date.*$");
if (std::none_of(lines.cbegin(), lines.cend(),
[](QString const &s) { return s.contains(alreadyUpToDate); })) {
int zoneNr = Utils::read1stLineOfFile("/mnt/system_data/zone_nr");
m_branchName = (zoneNr != 0) ? QString("zg1/zone%1").arg(zoneNr) : "master";
// lines can look like this:
// From https://git.mimbach49.de/GerhardHoffmann/customer_281
// 41ec581..5d25ac3 master -> origin/master
// ff10f57..43530a1 zg1/zone1 -> origin/zg1/zone1
// 6ed893f..5d9882c zg1/zone2 -> origin/zg1/zone2
// 4384d17..77045d8 zg1/zone3 -> origin/zg1/zone3
// 89d2812..36a0d74 zg1/zone5 -> origin/zg1/zone5
bool found = false;
for (int i=0; i < lines.size(); ++i) {
if (lines.at(i).contains(m_branchName)) {
found = true;
// 409f198..6c22726 zg1/zone1 -> origin/zg1/zone1
static QRegularExpression re("(^\\s*)([0-9A-Fa-f]+..[0-9A-Fa-f]+)(.*$)");
QRegularExpressionMatch match = re.match(lines.at(i));
if (match.hasMatch()) {
if (re.captureCount() == 3) { // start with full match (0), then the other 3 matches
QString const matchCaptured = match.captured(2);
worker()->CONSOLE(QStringList(matchCaptured)) << Worker::UPDATE_STEP::UPDATE_REPOSITORY;
return matchCaptured;
} else {
QStringList lst(QString("(wrong capture count (%1)").arg(re.captureCount()));
worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
}
} else {
emit m_worker->showErrorMessage("git fetch",
QString("(wrong cap-count (%1)").arg(re.captureCount()));
QStringList lst("no regex-match for commits");
worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
}
} else {
emit m_worker->showErrorMessage("git fetch",
"no regex-match for commits");
Utils::printCriticalErrorMsg("NO REGEX MATCH FOR COMMITS");
}
}
}
if (!found) {
emit m_worker->showErrorMessage("git fetch",
QString("unkown branch name ") + m_branchName);
Utils::printCriticalErrorMsg("UNKNOWN BRANCH NAME " + m_branchName);
if (!found) {
QStringList lst(QString("unknown branch name ") + m_branchName);
worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
}
} else {
return "Already up to date";
}
} else {
emit m_worker->showErrorMessage("git fetch",
QString("wrong format for result of 'git fetch' ") + s);
Utils::printCriticalErrorMsg(QString("WRONG FORMAT FOR RESULT OF 'GIT FETCH' ") + s);
QStringList lst(QString("WRONG FORMAT FOR RESULT OF 'GIT PULL' ") + s);
worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
}
} else {
emit m_worker->showErrorMessage("git fetch", "empty result for 'git fetch'");
Utils::printCriticalErrorMsg("EMPTY RESULT FOR 'GIT FETCH'");
QStringList lst("EMPTY RESULT FOR 'GIT PULL'");
worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
}
}
} else {
emit m_worker->showErrorMessage("git fetch", QString("repository ") + m_customerRepository + " does not exist");
Utils::printCriticalErrorMsg(QString("REPOSITORY ") + m_customerRepository + " DOES NOT EXIST");
QStringList lst(QString("REPOSITORY ") + m_customerRepository + " DOES NOT EXIST");
worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
}
return std::nullopt;
}
bool GitClient::gitFetchAndDiff() {
if (gitFetch()) {
QString gitCommand("git diff --compact-summary HEAD..FETCH_HEAD");
Command c(gitCommand);
return c.execute(m_workingDirectory);
}
return false;
}
bool GitClient::gitPull() {
if (QDir(m_customerRepository).exists()) {
Command c("git pull");
if (c.execute(m_customerRepository)) {
qInfo() << "PULLED INTO" << m_customerRepository;
return true;
}
Utils::printCriticalErrorMsg(QString("PULL INTO " + m_customerRepository + " FAILED"));
}
return false;
}
std::optional<QStringList> GitClient::gitMerge() {
Command c("git merge");
if (c.execute(m_workingDirectory)) {

View File

@@ -43,14 +43,17 @@ class GitClient : public QObject {
bool gitCloneAndCheckoutBranch();
std::optional<QString> gitFetch();
bool gitFetchAndDiff();
bool gitPull();
Worker *worker() { return m_worker; }
Worker const *worker() const { return m_worker; }
std::optional<QString> gitPull();
std::optional<QStringList> gitDiff(QString const &commit);
std::optional<QStringList> gitMerge();
bool gitFsck();
QString gitLastCommit(QString fileName);
QStringList gitShowReason();
QStringList gitShowReason(QString branchName);
static QString gitBlob(QString fileName);
QString gitCommitForBlob(QString blob);
bool gitIsFileTracked(QString file2name);

View File

@@ -23,6 +23,15 @@
#include <QJsonObject>
#if 0
########################
# Spec vom 27.10.2023:
# U0010 -> %-Werte
# U0001 -> 100%
# U0003 -> "FAIL"
# U0002 -> "" (OK -> WAIT state reset)
# ISMAS -> "WAIT"
########################
#
# $1: EVENT: U0001 update finished: 100%
# U0002 reset TRG
# U0003 error
@@ -47,6 +56,12 @@ void IsmasClient::printDebugMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
#if 0
Q_UNUSED(port);
Q_UNUSED(clientIP);
Q_UNUSED(clientPort);
Q_UNUSED(message);
#else
qDebug().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
@@ -55,12 +70,19 @@ void IsmasClient::printDebugMessage(int port,
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
#endif
}
void IsmasClient::printInfoMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
#if 0
Q_UNUSED(port);
Q_UNUSED(clientIP);
Q_UNUSED(clientPort);
Q_UNUSED(message);
#else
qInfo().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
@@ -69,6 +91,7 @@ void IsmasClient::printInfoMessage(int port,
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
#endif
}
void IsmasClient::printErrorMessage(int port,
@@ -292,7 +315,7 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
}
}
printInfoMessage(port, clientIP, clientPort, QString("MESSAGE RECEIVED ") + buf);
// printInfoMessage(port, clientIP, clientPort, QString("MESSAGE RECEIVED ") + buf);
QString response(buf);
if (int idx = response.indexOf("{\"error\":\"ISMAS is offline\"}")) {
@@ -367,16 +390,18 @@ QString IsmasClient::errorBackendNotConnected(QString const &info,
version.toStdString().c_str());
}
QString IsmasClient::errorGitClone(int percent, QString const &info, QString const &version) {
QString IsmasClient::errorGitClone(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0003",
percent,
m_progressInPercent,
RESULT_CODE::INSTALL_ERROR,
"CLONE CUSTOMER REPOSITORY FAILED",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::backendConnected(QString const &info, QString const &version) {
QString IsmasClient::backendConnected(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
@@ -385,7 +410,8 @@ QString IsmasClient::backendConnected(QString const &info, QString const &versio
version.toStdString().c_str());
}
QString IsmasClient::execOpkgCommand(QString const &info, QString const &version) {
QString IsmasClient::execOpkgCommand(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
@@ -622,6 +648,9 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
"},"
"\"ATBQT\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"ATB-UPDATE-TOOL\" : {"
"\"VERSION\" : \"%s\""
"}"
"},"
"\"PLUGINS\" : {"
@@ -749,6 +778,7 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
psa.sw.apismVersion.toStdString().c_str(),
psa.sw.atbQTVersion.toStdString().c_str(),
psa.sw.atbUpdateToolVersion.toStdString().c_str(),
psa.pluginVersion.deviceController.toStdString().c_str(),
psa.pluginVersion.ingenicoISelfCC.toStdString().c_str(),
@@ -857,7 +887,14 @@ QString IsmasClient::jsonParseFailed(int resultCode, QString reason, QString con
version.toStdString().c_str());
}
std::optional<QString> IsmasClient::finalResult(int resultCode, QString reason, QString const &version) {
std::optional<QString> IsmasClient::finalResult(int resultCode,
QString reason,
QString const &version) {
Q_UNUSED(resultCode);
Q_UNUSED(reason);
Q_UNUSED(version);
/*
m_progressInPercent = 100;
if (resultCode == RESULT_CODE::SUCCESS) {
return updateNewsToIsmas("U0002",
@@ -875,6 +912,7 @@ std::optional<QString> IsmasClient::finalResult(int resultCode, QString reason,
reason.toStdString().c_str(),
version.toStdString().c_str());
}
*/
return std::nullopt;
}

View File

@@ -48,6 +48,7 @@ struct PSAInstalled {
struct SoftWare {
QString apismVersion;
QString atbQTVersion;
QString atbUpdateToolVersion;
} sw;
struct PluginVersion {
@@ -98,6 +99,7 @@ struct PSAInstalled {
sw.apismVersion = "N/A";
sw.atbQTVersion = "N/A";
sw.atbUpdateToolVersion = "N/A";
pluginVersion.deviceController = "N/A";
pluginVersion.ingenicoISelfCC = "N/A";
@@ -175,7 +177,7 @@ public:
QString cloneAndCheckoutCustomerRepository(QString const &info, QString const &version = QString()); // clone and checkout customer repository
QString checkoutBranch(QString const &info, QString const &version = QString()); // checkout branch
QString errorBackendNotConnected(QString const &info, QString const &version = QString()); // checkout branch
QString errorGitClone(int percent, QString const &info, QString const &version = QString());
QString errorGitClone(QString const &info, QString const &version = QString());
QString backendConnected(QString const &info, QString const &version = QString());
QString updateTriggerSet(QString const &info, QString const &version = QString());
QString errorUpdateTrigger(QString const &info, QString const &version = QString());

124
main.cpp
View File

@@ -64,24 +64,6 @@ int main(int argc, char *argv[]) {
setDebugLevel(LOG_NOTICE);
}
//#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
//#ifdef _POSIX_THREAD_PROCESS_SHARED
// errno = 0;
// int res = 0;
// if ((res = sysconf(_SC_THREAD_PROCESS_SHARED)) < 0) {
// if (errno != 0) {
// qCritical() << "_POSIX_THREAD_PROCESS_SHARED NOT SUPPORTED"
// << strerror(errno);
// exit(-1);
// }
// } else {
// if (res == _POSIX_THREAD_PROCESS_SHARED) {
// Utils::printInfoMsg("_POSIX_THREAD_PROCESS_SHARED SUPPORTED");
// }
// }
//#endif
//#endif
QCommandLineParser parser;
parser.setApplicationDescription("Download tool for downloading device controller firmware, printer json-files and executing opkg-commands.");
parser.addHelpOption();
@@ -101,6 +83,10 @@ int main(int argc, char *argv[]) {
pluginNameOption.setDefaultValue(pluginNameDefault);
parser.addOption(pluginNameOption);
QCommandLineOption noDownloadOption("no-psa-hardware-update",
QCoreApplication::translate("main", "Do not update the PSA firmware (json, device-controller)."));
parser.addOption(noDownloadOption);
QCommandLineOption workingDirectoryOption(QStringList() << "working-directory" << "working-directory",
QCoreApplication::translate("main", "working directory of update-script."),
QCoreApplication::translate("main", "directory"));
@@ -112,37 +98,30 @@ int main(int argc, char *argv[]) {
QCoreApplication::translate("main", "Start ATBUpdateTool in dry-run-mode. No actual actions."));
parser.addOption(dryRunOption);
QCommandLineOption extendedVersionOption(QStringList() << "V" << "extended-version",
QCoreApplication::translate("main", "Show extended version (including last git commit)."));
parser.addOption(extendedVersionOption);
QCommandLineOption yoctoVersionOption(QStringList() << "y" << "yocto-version",
QCoreApplication::translate("main", "Show yocto version of ATBUpdateTool."));
parser.addOption(yoctoVersionOption);
QCommandLineOption yoctoInstallStatusOption(QStringList() << "Y" << "yocto-install",
QCoreApplication::translate("main", "Show yocto install status of ATBUpdateTool."));
parser.addOption(yoctoInstallStatusOption);
// Process the actual command line arguments given by the user
parser.process(a);
QString plugInDir = parser.value(pluginDirectoryOption);
QString plugInName = parser.value(pluginNameOption);
QString workingDir = parser.value(workingDirectoryOption);
bool dryRun = parser.isSet(dryRunOption);
bool const dryRun = parser.isSet(dryRunOption);
bool const noUpdatePsaHardware = parser.isSet(noDownloadOption);
bool const showYoctoVersion = parser.isSet(yoctoVersionOption);
bool const showYoctoInstallStatus = parser.isSet(yoctoInstallStatusOption);
bool const showExtendedVersion = parser.isSet(extendedVersionOption);
QString const rtPath = QCoreApplication::applicationDirPath();
if (!QDir(plugInDir).exists()) {
qCritical() << plugInDir
<< "does not exists, but has to contain dc-library";
exit(-1);
}
qInfo() << "pwd ..............." << rtPath;
qInfo() << "plugInDir ........." << plugInDir;
qInfo() << "plugInName ........" << plugInName;
qInfo() << "workingDir ........" << workingDir;
qInfo() << "dryRun ............" << dryRun;
// before loading the library, delete all possible shared memory segments
#if defined Q_OS_LINUX || defined Q_OS_UNIX
// system("rm -rf /tmp/qipc*");
#else
#error "Only tested under UNIX/LINUX"
#endif
hwinf *hw = Update::loadDCPlugin(QDir(plugInDir), plugInName);
hw->dc_autoRequest(true);
// hw->dc_openSerial(5, "115200", "ttymxc2", 1);
int machineNr = Utils::read1stLineOfFile("/etc/machine_nr");
int customerNr = Utils::read1stLineOfFile("/etc/cust_nr");
int zoneNr = Utils::read1stLineOfFile("/etc/zone_nr");
@@ -152,36 +131,59 @@ int main(int argc, char *argv[]) {
QThread::currentThread()->setObjectName("main thread");
qInfo() << "Main thread" << QThread::currentThreadId();
if (showExtendedVersion) {
printf(APP_EXTENDED_VERSION"\n");
return 0;
}
if (showYoctoVersion) {
printf("%s\n", Worker::getATBUpdateToolYoctoVersion().toStdString().c_str());
return 0;
}
if (showYoctoInstallStatus) {
printf("%s\n", Worker::getATBUpdateToolYoctoInstallationStatus().toStdString().c_str());
return 0;
}
if (!QDir(plugInDir).exists()) {
qCritical() << plugInDir
<< "does not exists, but has to contain dc-library";
exit(-1);
}
qInfo() << "pwd ......................" << rtPath;
qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir;
qInfo() << "dryRun ..................." << dryRun;
qInfo() << "noUpdatePsaHardware ......" << noUpdatePsaHardware;
qInfo() << "extended-version ........." << APP_EXTENDED_VERSION;
//qInfo() << "yocto-version ............" << Worker::getATBUpdateToolYoctoVersion();
//qInfo() << "yocto-install-status ....." << Worker::getATBUpdateToolYoctoInstallationStatus();
// before loading the library, delete all possible shared memory segments
#if defined Q_OS_LINUX || defined Q_OS_UNIX
// system("rm -rf /tmp/qipc*");
#else
#error "Only tested under UNIX/LINUX"
#endif
Worker worker(customerNr,
machineNr,
zoneNr,
branchName,
plugInDir,
plugInName,
workingDir,
noUpdatePsaHardware,
dryRun);
QString const customerNrStr(
QString("customer_") + QString::number(customerNr).rightJustified(3, '0'));
QScopedPointer<Update> update(
new Update(hw,
&worker,
QDir::cleanPath(workingDir + QDir::separator() + customerNrStr),
customerNrStr,
branchName,
plugInName,
workingDir,
dryRun,
nullptr,
SERIAL_PORT,
"115200"));
MainWindow mw(hw, &worker, update.get());
MainWindow mw(&worker);
worker.setMainWindow(&mw);
mw.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
mw.setWindowState(Qt::WindowFullScreen);
mw.show();
mw.showFullScreen();
return a.exec();
}

View File

@@ -10,104 +10,17 @@
#include <QMessageBox>
#include <QDebug>
#include <QScrollBar>
#include <QEvent>
#if EMERGENCY_LEAVE_BL==1
static int step = 0;
void MainWindow::emergencyLeaveBL() {
//
qCritical() << __func__ << step;
switch(step) {
case 0:
if (m_hw->dc_openSerial(5, "115200", "ttymxc2", 1)) {
qCritical() << __func__ << "open ok";
step++;
QThread::msleep(2000);
m_hw->dc_autoRequest(false);
emit leaveBL();
}
break;
case 1:
m_hw->bl_rebootDC();
QThread::msleep(1000);
qCritical() << __func__ << "reboot ok" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
step++;
emit leaveBL();
break;
case 2:
case 3:
case 4:
case 5:
case 6:
m_hw->bl_startBL();
QThread::msleep(1000);
qCritical() << __func__ << "start" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
step++;
emit leaveBL();
break;
case 7:
case 9:
case 11:
case 13:
case 15:
m_hw->bl_checkBL();
qCritical() << __func__ << "check" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
QThread::msleep(1500);
++step;
emit leaveBL();
break;
case 8:
case 10:
case 12:
case 14:
case 16:
qCritical() << __func__ << "is Up..." << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
if (m_hw->bl_isUp()) {
qCritical() << __func__ << "is Up...OK" << step << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
QThread::msleep(5000);
step = 16;
} else {
qCritical() << __func__ << "is Up...NO" << step << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
}
++step;
emit leaveBL();
break;
case 17:
case 18:
case 19:
qCritical() << __func__ << "stop" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
m_hw->bl_stopBL();
QThread::msleep(1000);
//m_hw->dc_closeSerial();
++step;
emit leaveBL();
break;
}
}
#endif
MainWindow::MainWindow(hwinf *hw, Worker *worker, Update *update, QWidget *parent)
MainWindow::MainWindow(Worker *worker, QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_hw(hw)
, m_worker(worker)
, m_width(70)
, m_progressRunning(false)
, m_progressValue(0)
, m_update(update)
, m_updateStep(UpdateDcEvent::UpdateStep::NONE) {
#if EMERGENCY_LEAVE_BL==1
QTimer *t = new QTimer(this);
connect(t, SIGNAL(timeout()), this, SLOT(emergencyLeaveBL()));
connect(this, SIGNAL(leaveBL()), this, SLOT(emergencyLeaveBL()), Qt::QueuedConnection);
t->setSingleShot(true);
t->start(1000);
return;
#endif
this->setStatusBar(new QStatusBar(this));
QFont f;
f.setStyleHint(QFont::Monospace);
@@ -125,10 +38,11 @@ MainWindow::MainWindow(hwinf *hw, Worker *worker, Update *update, QWidget *paren
QString start = QDateTime::currentDateTime().toString(Qt::ISODate);
lst << QString("Start: ") + start.leftJustified(m_width-10);
lst << QString("").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("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'));
@@ -136,7 +50,7 @@ MainWindow::MainWindow(hwinf *hw, Worker *worker, Update *update, QWidget *paren
// ui->updateStatus->installEventFilter(this);
m_startTimer = new QTimer(this);
connect(m_startTimer, SIGNAL(timeout()), m_worker, SLOT(update()));
connect(m_startTimer, SIGNAL(timeout()), m_worker, SLOT(start()));
m_startTimer->setSingleShot(true);
m_startTimer->start(1000);
@@ -153,6 +67,8 @@ MainWindow::MainWindow(hwinf *hw, Worker *worker, Update *update, QWidget *paren
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)));
}
@@ -176,22 +92,22 @@ void MainWindow::customEvent(QEvent *event) {
case START_PROGRESS_LOOP: {
m_progressRunning = true;
ui->updateProgress->reset();
m_progressValue = 10;
QApplication::postEvent(this, new ProgressEvent(this, m_progressValue));
// 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);
// m_progressValue -= 10;
// m_worker->setProgress(m_progressValue/10);
} break;
default: {
if (m_progressRunning) {
m_progressValue = progress;
ui->updateProgress->setValue(progress/10);
QApplication::postEvent(this, new ProgressEvent(this, progress+10));
QThread::msleep(500);
}
}
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) {
@@ -211,86 +127,6 @@ void MainWindow::customEvent(QEvent *event) {
} else {
qCritical() << "!!! UNKNOWN SENDER !!!";
}
} else
if (event->type() == UpdateDcEvent::type()) {
UpdateDcEvent *pevent = (UpdateDcEvent *)event;
UpdateDcEvent::UpdateStep const updateStep = pevent->updateStep();
QObject const *sender = pevent->sender();
if (sender == m_worker) {
QDateTime const &recv = QDateTime::currentDateTime();
QDateTime const &send = pevent->sendDateTime();
qint64 const delay = recv.toMSecsSinceEpoch() - send.toMSecsSinceEpoch();
switch(updateStep) {
case UpdateDcEvent::UpdateStep::NONE:
break;
case UpdateDcEvent::UpdateStep::DC_REBOOT: {
m_hw->bl_rebootDC();
QString msg = QDateTime::currentDateTime().toString(Qt::ISODateWithMs)
+ QString(": reset device controller (delay=%1ms").arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_updateStep = UpdateDcEvent::UpdateStep::DC_REBOOT;
} break;
case UpdateDcEvent::UpdateStep::BL_START: {
QString const &msg = recv.toString(Qt::ISODateWithMs)
+ QString(": start bootloader (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_hw->bl_startBL();
if (pevent->count() == BL_START_COUNT) {
m_updateStep = UpdateDcEvent::UpdateStep::BL_START;
}
} break;
case UpdateDcEvent::UpdateStep::BL_CHECK: {
if (m_updateStep != UpdateDcEvent::UpdateStep::BL_IS_UP) {
QString const &msg = recv.toString(Qt::ISODateWithMs)
+ QString(": request bootloader version (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_hw->bl_checkBL();
//m_updateStep = UpdateDcEvent::UpdateStep::BL_CHECK;
}
} break;
case UpdateDcEvent::UpdateStep::BL_IS_UP: {
QString msg = recv.toString(Qt::ISODateWithMs)
+ QString(": check running bootloader (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
if (m_updateStep != UpdateDcEvent::UpdateStep::BL_IS_UP) {
if (m_hw->bl_isUp()) {
msg = recv.toString(Qt::ISODateWithMs)
+ QString(": bootloader running (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_updateStep = UpdateDcEvent::UpdateStep::BL_IS_UP;
} else {
msg = recv.toString(Qt::ISODateWithMs)
+ QString(": bootloader stop requested (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
if (m_updateStep == UpdateDcEvent::UpdateStep::BL_STOP) {
msg = QDateTime::currentDateTime().toString(Qt::ISODateWithMs)
+ QString(": bootloader down (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_updateStep = UpdateDcEvent::UpdateStep::BL_IS_DOWN;
}
}
}
} break;
case UpdateDcEvent::UpdateStep::BL_STOP: {
QString const &msg = QDateTime::currentDateTime().toString(Qt::ISODateWithMs)
+ QString(": stop bootloader (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
//if (m_bootLoaderIsUp) {
m_hw->bl_stopBL();
m_updateStep = UpdateDcEvent::UpdateStep::BL_STOP;
//}
} break;
default: ;
}
}
}
QThread::yieldCurrentThread();
@@ -308,29 +144,33 @@ void MainWindow::onEnableExit() {
ui->exit->setEnabled(true);
}
//bool MainWindow::eventFilter(QObject *obj, QEvent *ev) {
// if (obj == ui->updateStatus) {
// qCritical() << "REc. event for text edit" << ev->type();
// }
// return QMainWindow::eventFilter(obj, ev);
//}
void MainWindow::onRestartExitTimer() {
m_exitTimer->stop();
m_exitTimer->start(60 * 1000);
// ui->updateStatus->blockSignals(true);
scrollDownTextEdit();
ui->updateStatus->setEnabled(false);
}
void MainWindow::onQuit() {
m_exitTimer->stop();
qCritical() << QString("ON QUIT: EXIT CODE %1").arg(m_worker->returnCode());
qApp->exit(m_worker->returnCode());
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));
// Utils::printInfoMsg(QString("SCROLL-DOWN-TEXT_EDIT CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
ui->updateStatus->setEnabled(true);
@@ -341,10 +181,12 @@ void MainWindow::scrollDownTextEdit() {
}
void MainWindow::onAppendText(QString text, QString suffix) {
Utils::printInfoMsg(QString("ON APPEND CALLED AT ")
+ QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
// 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) {
@@ -366,12 +208,12 @@ void MainWindow::onAppendText(QString text, QString suffix) {
// Utils::printLineEditInfo(editText.split('\n', QString::SplitBehavior::SkipEmptyParts));
// ui->updateStatus->setText(editText.trimmed());
scrollDownTextEdit();
// scrollDownTextEdit();
}
void MainWindow::onReplaceLast(QStringList newTextLines, QString suffix) {
Utils::printInfoMsg(QString("ON REPLACE LAST (LIST) CALLED AT ")
+ QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
// Utils::printInfoMsg(QString("ON REPLACE LAST (LIST) CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
int const s = newTextLines.size();
if (s > 0) {
@@ -405,8 +247,8 @@ void MainWindow::onReplaceLast(QStringList newTextLines, QString suffix) {
}
void MainWindow::onReplaceLast(QString text, QString suffix) {
Utils::printInfoMsg(QString("ON REPLACE LAST (TEXT) CALLED AT ")
+ QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
// 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);
@@ -443,3 +285,21 @@ void MainWindow::onShowErrorMessage(QString title, QString 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), "");
}
}

View File

@@ -21,10 +21,9 @@ class MainWindow : public QMainWindow {
protected:
void customEvent(QEvent *event) override;
// bool eventFilter(QObject *obj, QEvent *ev) override;
public:
MainWindow(hwinf *hw, Worker *worker, Update *update, QWidget *parent = nullptr);
MainWindow(Worker *worker, QWidget *parent = nullptr);
~MainWindow();
static const int START_PROGRESS_LOOP = -1;
@@ -34,11 +33,6 @@ public:
static const int BL_IS_UP_COUNT = 5;
static const int BL_STOP_COUNT = 5;
int progressValue() const { return m_progressValue; }
hwinf *getPlugin() { return m_hw; }
hwinf const *getPlugin() const { return m_hw; }
Update *getUpdate() { return m_update; }
Update const *getUpdate() const { return m_update; }
UpdateDcEvent::UpdateStep updateStep() const { return m_updateStep; }
void setUpdateStep(UpdateDcEvent::UpdateStep updateStep) { m_updateStep = updateStep; }
@@ -48,6 +42,8 @@ public slots:
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();
@@ -70,14 +66,12 @@ private:
void onShowMessage(QString, QString);
Ui::MainWindow *ui;
hwinf *m_hw;
Worker *m_worker;
int const m_width;
QTimer *m_startTimer;
QTimer *m_exitTimer;
bool m_progressRunning;
int m_progressValue;
Update *m_update;
//int m_progressValue;
UpdateDcEvent::UpdateStep m_updateStep;
};
#endif // MAINWINDOW_H

271
plugins/interfaces.h Normal file → Executable file
View File

@@ -193,7 +193,7 @@ struct T_moduleCondition
uint8_t coinChecker; // EMP, OMP or mei-cashflow
uint8_t coinEscrow;
uint8_t mifareReader;
uint8_t mifareReader; // 0: unknown 1=OK 200=no response 201=wrong response 202: Reader reports HW-error
uint8_t creditTerm;
uint8_t coinReject;
@@ -344,7 +344,41 @@ struct T_devices
};
struct T_chg_Tub
{
uint8_t tubeLevel[8]; // [0]=nr coins of lowest value
uint8_t tubeFull[8]; // 1=full 0 else
uint16_t tubeValues[8]; // in cent [0]=lowest value 5c or 10cent
uint16_t tubeFilled[8]; // nr of every coin inserted
uint16_t tubeDispens[8]; // nr of every coin dispensed
// 64 byte
};
struct T_changer
{
// Fixdata from Coin Changer
uint8_t setup; // always 1
uint8_t state; // step of state machine
// 0..12 like EMP, 13...30 for coin dispense
uint8_t level; // mdb-level, always 3
uint16_t countryCode;
uint8_t scale;
uint8_t decimals;
uint8_t coinSetup[16]; // [0]=lowest coin, multiply with scale
uint16_t intendedAcceptance; //bitwise 0,1 1=accept coin, came from master
uint8_t tokenChannel;
uint8_t pollingRunning; // 1: emp is polled 0:not
uint8_t paymentRunning; // 1: coins are accepted
uint16_t denomination[16];
uint16_t availableTubes; //bitwise 0,1 1=av. bit0 = lowest coin value
};
struct T_bna
{
};
class hwinf
{
@@ -818,7 +852,7 @@ public:
// --------------------------------------------- MIFARE -----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
// obsolete
virtual uint8_t mif_returnReaderStateAndCardType(uint8_t *buf, uint8_t maxBufferSize) const =0;
// retval 0=OK 1=error host buffer too small
/* data description, new fast version:
@@ -840,13 +874,16 @@ public:
virtual bool mif_readerIsOK(void) const =0;
virtual bool mif_cardAttached(void) const =0;
// not working! use mif_cardIsAttached() instead
virtual uint8_t mif_readResult(void) const =0;
// result: 0: unknown or still in progress
// 1: card read successful
// 2: reading error
// not working!
virtual QString mif_cardUID(void) const =0;
// not working
virtual uint8_t mif_getCardDataDec(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize) const =0;
@@ -1289,7 +1326,7 @@ public:
// 1= wrong length 2=wrong start sign 5= wrong crc
// 6= slave: master cmd was wrong 7: slave: could not write/read data
// 8=timeout, got no response from slave
// 0,8 work, 1..6 not yet tested. 8 comes immed. and stays 8 until reconnect
// use for important and extended commands (print several templates, print ticket...)
virtual void log_startSupervision(void) const =0;
@@ -1299,6 +1336,7 @@ public:
// 0: started, in progress
// 1: done and OK
// 2: done and error
// not working properly, always 0
virtual bool log_getVaultData(uint8_t *data) const =0;
// get vault record in linear 8bit buffer with 384 byte
@@ -1343,6 +1381,213 @@ public:
// new functions from 8.9.23
virtual QString mif_getReaderType(void) const =0;
// return "SL025" if correct reader is connected
virtual void mif_getCardSize(uint8_t *cardSize, uint8_t *idLeng) const =0;
// cardSize=1k or 4kByte
// idLeng =4Byte or 7 byte
virtual char mif_getAtbCardData(uint8_t *buf, uint8_t maxBuffSiz) const =0;
// return complete buffer binary, just for test purpose
virtual bool mif_isValidAtbCard(void) const =0;
virtual uint32_t mif_getAtbCardCuNu(void) const =0;
virtual uint8_t mif_getAtbCardTyp(void) const =0;
// return 1=upper door card 1=lower door 3=printer-test 4=coin-test
// 0: not a valid atb2020 card
virtual QString mif_getAtbCardPerso(void) const =0;
// e.g. "PNsax001" used for personal number, name shortcode, card number
// free to use, can be set in AtbMcw23.exe tool
virtual void mif_getAtbCardExpire(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute) const =0;
// ------------------------------------------------------------------------------------
// Device-Controller-Bootloader convenient version 21.09.2023
// ------------------------------------------------------------------------------------
// use this to jump to BL:
//void hwapi::bl_rebootDC(void) const
// use this to start BL:
// void hwapi::bl_startBL(void) const
// call this in order to get response from BL:
//void hwapi::bl_checkBL(void) const
// evaluate BL response:
//bool hwapi::bl_isUp(void) const
// 29.9.23: new: "completeStart" function, replaces bl_rebootDC(), bl_startBL() and bl_checkBL()
// result can be verified with bl_isUp() as before
virtual bool bl_completeStart(void) const =0;
// must be used in DC's normal operation
// select binfile-name in GUI
// send binfile-name to BL-processor:
virtual bool bl_storeFirmware(QString fileName) const =0;
// load binary file 3x and compare
// return true if loaded correctly
// return false: error, could not load correctly
// request the number of blocks for this file
virtual uint16_t bl_getNrOfFirmwareBlocks(void) const =0;
// size of the loaded bin file in 64byte blocks
// call after bl_storeFirmware()
// call the next two function's repetitive with "blockNumber"=0,1,2,3....."bl_getNrOfFirmwareBlocks()"
virtual bool bl_blockAutoLoad(uint16_t blockNumber) const =0;
// call in loop from block number 0 up to <= "dcBL_getNrOfBlocks()"
//the last block "bl_getNrOfFirmwareBlocks()" is sent as conclusion command (important!)
// but after every call WAIT (!) for response "bl_blockAutoResponse()" !!!!
// data will be sent to DC, if neccesary addr will be sent additionally
// if neccesary sending will automatically repeat up to 3times
// retval: false if blockNumber>4095, true else
// check out this response after every block-sending, wait until >0!!!
virtual int8_t bl_blockAutoResponse(void) const =0;
// after every "bl_blockAutoLoad()" call this until response
// retval 0: wait 1: OK, blk was sent 2: OK, transfer complete
// 3: error despite repeating, cancel. probably bin file corrupted
// Max duration: 3x no response from BL = 900ms
// finally call:
// void hwapi::bl_stopBL(void) const
// -------------- end of bootloader ---------------------------------------------------
// new from 28.9.23 and earliest from DC version 4.45
// get all versions of the DC-Jsons
virtual void sys_requestJsonVersions(uint8_t jsonNr) const =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
virtual void sys_getJsonVersions(uint8_t jsonNr, char *versionString) const =0;
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
// length of buffer is always 16 byte
// ------------------------------------------------------------------------------------
// Coin Changer
// ------------------------------------------------------------------------------------
// find above (same as for coin checker (EMP)):
// mdb_switchPower(true); // power on/off
// cash_startPayment(amount_cent); // start polling, enable coins, changer turns to green
// getInsertedAmount()
// getLastInsertedCoin()
// getAllInsertedCoins(uint16_t *types, uint16_t *values)
// all inserted coins of this past transaction are stored, max 64
// cash_stopPayment(); // and wait for further command (changer blinks yellow)
// cash_cancelPayment(); // and return complete paid amount
// after ticket/goods issue:
// vend_success()
// conclude payment process, keep all coins. Printing was successful
// return change (payment above start-amount), so it works only if
// Payment was started with real vending price (pre selection).
// if payment was started with maximum price (for direct coin insertion)
// then use "changer_returnCoins()", not vend_success()
// vend_failed()
// conclude payment process and return complete paid amount
// also valid for changer:
// emp_sendSettings(uint16_t coinAcceptance, uint8_t tokenChannel, uint16_t *coinDenomination ) const =0;
// coinAcceptance: bit0=coin1 (lowest donomination) bit15=coin16 bitH=accept bit L = deny coin (no validation)
// tokenChannel 0...31: if this signal comes from emp then a token was inserted
// coinDenomination = array of 16 coin values (e.g. 5, 10, 20...)
virtual void changer_returnCoins(uint32_t amountInCent) const =0;
virtual void changer_requestChangeResult(void) const =0;
virtual uint8_t changer_getChangeResult(uint32_t *returnedAmount) const =0;
// get result of coin dispensing
// receivedData[0]: 0: not yet started 1:amount returned
// 2:only partial return 3: no return possible
// receivedData[2,3,4,5]: returned amount
virtual void changer_getAllParameters(struct T_changer *mw) const =0;
// requested automatically with 23, same like EMP
virtual void changer_requestTubelevel(void) const =0;
virtual void changer_getTubelevel(struct T_chg_Tub *tubLevel) const =0;
// don't use tubeDispens[], it's not yet correct!
// ------------------------------------------------------------------------------------
// bank note acceptor
// ------------------------------------------------------------------------------------
// already defiened functions applying for BNA as well:
// mdb_switchPower(true); // power on/off
// bank notes are integrated in the normal transaction process, so use the usual functions to run a vending cycle:
// cash_startPayment(amount_cent); // start polling, enable bills, reader shows green
// getInsertedAmount()
// cash_stopPayment();
// cash_cancelPayment();
// vend_success()
// vend_failed()
virtual void bna_sendSettings(uint16_t notesToAccept, uint16_t parameters,
uint16_t *billDenomination,
uint32_t acceptanceLimit) const =0;
// notesToAccept: bit0=bill1 (lowest donomination) bitH=accept bit L = deny
// parameters: e.g. use escrow function for some notes
// billDenomination = array of 16 bill values (e.g. 5, 10, 20...)
// these can be set alternatively by Json-File DC2C_cash.json
// acceptanceLimit: device will stop acceptance once this amount is reached and
// optionally keep last bill in escrow until vend_success()
// is called (put bill to stacker) or vend_failed() is called (return bill)
virtual void bna_setCurrentAcceptance(uint16_t notesToAccept) const =0;
// can be used to block notes dynamically, example: from now only 5€ bills are allowed (if only 3€ are to be paid)
// only valid till next start-payment. Cannot add notes which are not activated in Json
virtual void bna_requestParameters(void) const =0;
// send command to DC in order to get static invariable device parameters like currency
// device must be powered and polled to get these
virtual bool bna_getAllParameters(struct T_bna *bna) const =0;
// get all constant data from reader (e.g. currency)
// and actual Host-Settings (sent with bna_sendSettings() or json)
// retval = true if data are valid
virtual void bna_requestCurrentNotes(void) const =0;
// send command to DC in order to get transaction data
virtual uint8_t bna_getCurrentNotes(uint16_t latestBill, uint16_t *currentNotes) const =0;
// returns number of collected bank notes since start-command (current transaction)
// latestBill: last accepted bank note, value in cent
// currentNotes an array with up to 16 (further) notes collected
virtual void bna_requestStackerLevel(void) const =0;
virtual uint16_t bna_getStackerLevel(uint32_t *amountInStacker, uint16_t *countOfBills) const =0;
// return val: nr of bills in stacker
// countOfBills: array of up to 16 sums, countOfBills[0]=nr of 5€-bills in stacker
// countOfBills[1] for 10€ and so on
signals:
virtual void hwapi_templatePrintFinished_OK(void) const=0;
virtual void hwapi_templatePrintFinished_Err(void) const=0;
@@ -1360,8 +1605,6 @@ signals:
virtual void hwapi_payCancelled(void) const=0;
virtual void hwapi_coinProcessJustStopped(void) const=0;
// new from 2023.06.12
virtual void hwapi_doorServiceDoorOpened(void) const=0;
virtual void hwapi_doorVaultDoorOpened(void) const=0;
virtual void hwapi_doorCoinBoxRemoved(void) const=0;
@@ -1413,9 +1656,23 @@ signals:
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.1"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.2"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.3"
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.4"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.4"
// 8.9.2023 two new functions (end of file) for mifare test
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.5"
// 18.9.2023 major improvements for DC data exchange
// verification of door and cash box signals
// intensive verification of Json-Programming Master-Slave (PTU to DC), 100% ok
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.6"
// 20.9.2023: speeding up door and cash box signals
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.7"
// 26.09.2023: added improved DC-bootloader files
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/4.8"
// 28.09.2023: added version request of DC-Json-Files
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.0"
// 10.10.2023: added coin changer
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.1"
// 20.10.2023: added bill validator
Q_DECLARE_INTERFACE(hwinf, HWINF_iid)

Binary file not shown.

View File

@@ -4,6 +4,7 @@
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
#include <QDateTime>
Command::Command(QString const &command, int start_timeout, int finish_timeout)
: m_command(command.trimmed())
@@ -65,39 +66,58 @@ bool Command::execute(QString workingDirectory, QStringList args) {
p->start(m_command);
}
qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch();
if (p->waitForStarted(m_waitForStartTimeout)) {
qDebug() << "PROCESS" << m_command << "STARTED IN" << p->workingDirectory();
if (p->state() == QProcess::ProcessState::Running) {
qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory();
if (p->waitForFinished(m_waitForFinishTimeout)) {
// wait forever for git/opkg-commands to finish
int wait = m_waitForFinishTimeout;
if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) ||
m_command.trimmed().startsWith("opkg", Qt::CaseInsensitive)) {
wait = -1;
}
bool const no_timeout = p->waitForFinished(wait);
if (no_timeout) {
qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory();
if (p->exitStatus() == QProcess::NormalExit) {
if ((m_exitCode = p->exitCode()) == 0) {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qDebug() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
return true;
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "CRASHED with code"
<< p->exitCode()
<< QString("(after %1ms)").arg(end-start)
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command
<< "DID NOT FINISH"
<< "IN" << p->workingDirectory();
<< "DID NOT FINISH WITH" << wait
<< "MS IN" << p->workingDirectory()
<< QString("(runtime %1ms)").arg(end-start);
}
} else {
qCritical() << "WRONG PROCESS STATE" << p->state()
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"
<< QString("(runtime %1ms)").arg(end-start)
<< "IN" << p->workingDirectory();
}
return false;

View File

@@ -29,11 +29,7 @@
#include <QMap>
#define UPDATE_OPKG (1)
#define UPDATE_DC (1)
#define UPDATE_PRINTER_TEMPLATES (1)
#define UPDATE_CASH_TEMPLATE (1)
#define UPDATE_CONF_TEMPLATE (1)
#define UPDATE_DEVICE_TEMPLATE (1)
#define UPDATE_DC (0)
static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
@@ -98,11 +94,11 @@ bool Update::unloadDCPlugin() {
return false;
}
Update::Update(hwinf *hw,
Worker *worker,
Update::Update(Worker *worker,
QString customerRepository,
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
bool dryRun,
@@ -110,7 +106,7 @@ Update::Update(hwinf *hw,
char const *serialInterface,
char const *baudrate)
: QObject(parent)
, m_hw(hw)
, m_hw(loadDCPlugin(QDir(plugInDir), pluginName))
, m_worker(worker)
, m_serialInterface(serialInterface)
, m_baudrate(baudrate)
@@ -610,9 +606,12 @@ bool Update::downloadJson(enum FileTypeJson type,
int templateIdx,
QString jsFileToSendToDC) const {
qDebug() << "updating json-file:" << jsFileToSendToDC << "...";
qDebug() << " template-index:" << templateIdx;
qDebug() << " json-type:" << jsonType(type);
Utils::printInfoMsg(
QString("UPDATING JSON-FILE=%1, TEMPLATE-INDEX=%2, JSON-TYPE=%3")
.arg(jsFileToSendToDC)
.arg(templateIdx)
.arg(jsonType(type)));
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
qDebug() << "SET AUTO-REQUEST=TRUE";
@@ -623,7 +622,7 @@ bool Update::downloadJson(enum FileTypeJson type,
while ((ready = m_hw->sys_ready4sending()) == false) {
QThread::msleep(200);
if (--nTry <= 0) {
qCritical() << "SYS NOT READY FOR SENDING AFTER 5 SECONDS";
Utils::printCriticalErrorMsg("SYS NOT READY FOR SENDING AFTER 5 SECONDS");
break;
}
}
@@ -636,22 +635,27 @@ bool Update::downloadJson(enum FileTypeJson type,
if (file.open(QIODevice::ReadOnly)) {
if (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())) {
QThread::sleep(1);
qDebug() << "SENT" << jsFileToSendToDC;
ret = true;
}
} else {
qCritical() << "SIZE OF" << jsFileToSendToDC
<< "TOO BIG (" << fi.size() << "BYTES)";
Utils::printCriticalErrorMsg(
QString("SIZE OF %1 TOO BIG (%2 BYTES)")
.arg(jsFileToSendToDC).arg(fi.size()));
}
} else {
qCritical() << "CANNOT OPEN" << jsFileToSendToDC << "FOR READING";
Utils::printCriticalErrorMsg(
QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING");
}
} else {
qCritical() << jsFileToSendToDC << "DOES NOT EXIST";
Utils::printCriticalErrorMsg(
QString(jsFileToSendToDC) + " DOES NOT EXIST");
}
}
@@ -738,64 +742,23 @@ QStringList Update::getDcSoftAndHardWareVersion() {
}
bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
bool serialOpened = false;
QString const &parentName = Utils::getParentName();
Utils::printInfoMsg(
QString("PARENT OF ATB-UPDATE-TOOL (ppid=%1) ").arg(getppid()) + parentName);
if (parentName == "ATBQT" || parentName == "systemd") {
// the tool was not called during 'service' ot during an automatic
// update procedure. and it was called explicitly with libCAmaster.so
if (m_pluginName.contains("master", Qt::CaseInsensitive)) {
Utils::printCriticalErrorMsg(parentName
+ " IS MASTER, BUT ATB-UPDATE-TOOL CALLED WITH libCAmaster.so");
int tries = 20;
while (!m_hw->sys_areDCdataValid()) { // 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";
return false;
}
Utils::printInfoMsg(
QString("ATB-UPDATE-TOOL STARTED AS SLAVE OF ") + parentName);
} else
if (Utils::isATBQTRunning()) { // manual testing
if (m_pluginName.contains("master", Qt::CaseInsensitive)) {
Utils::printCriticalErrorMsg(
"ATBQT IS MASTER, BUT ATB-UPDATE-TOOL CALLED WITH libCAmaster.so");
return false;
}
Utils::printInfoMsg(
"ATB-UPDATE-TOOL STARTED AS SLAVE-SIBLING OF ATBQT-MASTER");
} else {
if (m_pluginName.contains("slave", Qt::CaseInsensitive)) {
Utils::printCriticalErrorMsg(
"ATB-UPDATE-TOOL CALLED WITH libCAslave.so ALTHOUGH MASTER");
return false;
}
Utils::printInfoMsg("ATB-UPDATE-TOOL STARTED AS MASTER");
if ((serialOpened = openSerial(baudrateMap.value(m_baudrate),
m_baudrate,
m_serialInterface)) == false) {
Utils::printCriticalErrorMsg(
QString("CANNOT OPEN ")
+ m_serialInterface
+ "( BAUDRATE=" + m_baudrate + ")");
return false;
}
m_hw->dc_autoRequest(false);
Utils::printInfoMsg(
QString("SERIAL OPEN ") + m_serialInterface
+ " (BAUDRATE=" + m_baudrate + ")");
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
bool res = false;
QList<QString>::const_iterator it;
for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) {
m_worker->startProgressLoop();
QString fToWorkOn = (*it).trimmed();
fToWorkOn = QDir::cleanPath(m_customerRepository + QDir::separator() + fToWorkOn);
QString const &fToWorkOn = QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
#if UPDATE_DC == 1
static const QRegularExpression version("^.*dc2c[.][0-9]{1,2}[.][0-9]{1,2}[.]bin.*$");
if (fToWorkOn.contains(version)) {
Utils::printInfoMsg("DO-UPDATE FILE-TO-WORK-ON " + fToWorkOn);
@@ -810,7 +773,6 @@ bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
bool updateBinaryRes = true;
qInfo() << "DOWNLOADING" << finfo.completeBaseName() << "TO DC";
#if UPDATE_DC == 1
m_hw->dc_autoRequest(false);// default: turn auto-request setting off
QThread::sleep(1); // wait to be sure that there are no more
// commands sent to dc-hardware
@@ -837,13 +799,12 @@ bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
qInfo() << "dc-firmware-version (NOT UPDATED)" << versions[1];
}
}
#endif
res = updateBinaryRes;
}
} else if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
#endif
if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
#if UPDATE_PRINTER_TEMPLATES == 1
int i = fToWorkOn.indexOf("DC2C_print", Qt::CaseInsensitive);
int const templateIdx = fToWorkOn.mid(i).midRef(10, 2).toInt();
if ((templateIdx < 1) || (templateIdx > 32)) {
@@ -851,68 +812,60 @@ bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
res = false;
} else {
if ((res = updatePrinterTemplate(templateIdx, fToWorkOn))) {
qInfo() << "downloaded printer template"<< fToWorkOn;
Utils::printInfoMsg(
QString("DOWNLOADED PRINTER TEMPLATE %1 WITH INDEX=%2")
.arg(fToWorkOn)
.arg(templateIdx));
++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(2, ' ') + QString(")")
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
}
#endif
} else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
#if UPDATE_CASH_TEMPLATE == 1
if ((res = updateCashConf(fToWorkOn))) {
qInfo() << "downloaded cash template"<< fToWorkOn;
Utils::printInfoMsg(QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn));
++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(2, ' ') + QString(")")
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
#endif
} else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
#if UPDATE_CONF_TEMPLATE == 1
if ((res= updateConfig(fToWorkOn))) {
qInfo() << "downloaded config template"<< fToWorkOn;
Utils::printInfoMsg(QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn));
++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(2, ' ') + QString(")")
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
#endif
} else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
#if UPDATE_DEVICE_TEMPLATE == 1
if ((res = updateDeviceConf(fToWorkOn))) {
qInfo() << "downloaded device template"<< fToWorkOn;
Utils::printInfoMsg(QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn));
++displayIndex;
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(2, ' ') + QString(")")
emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
+ QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
Worker::UPDATE_STEP_DONE);
}
#endif
} else {
qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn;
res = false;
}
m_worker->stopProgressLoop();
m_worker->setProgress(100);
// m_worker->stopProgressLoop();
// m_worker->setProgress(100);
if (res == false) {
break;
}
} // for (it = openLines.cbegin(); it != openLines.end(); ++it) {
//m_hw->dc_autoRequest(true); // ALWAYS turn autoRequest ON
//qDebug() << "SET AUTO-REQUEST=TRUE";
if (serialOpened) {
m_hw->dc_closeSerial();
}
m_hw->dc_autoRequest(true); // ALWAYS turn autoRequest ON
qDebug() << "SET AUTO-REQUEST=TRUE";
return res;
}

View File

@@ -21,8 +21,8 @@ class Worker;
class Update : public QObject {
Q_OBJECT
hwinf *m_hw;
Worker *m_worker;
hwinf *m_hw = nullptr;
Worker *m_worker = nullptr;
char const *m_serialInterface;
char const *m_baudrate;
QString m_customerRepository;
@@ -44,11 +44,11 @@ public:
static QStringList split(QString line, QChar sep = ',');
explicit Update(hwinf *hw,
Worker *worker,
explicit Update(Worker *worker,
QString customerRepository,
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
bool dryRun = false,
@@ -58,6 +58,9 @@ public:
virtual ~Update() override;
bool doUpdate(int &displayIndex, QStringList const &linesToWorkOn);
hwinf *hw() { return m_hw; }
hwinf const *hw() const { return m_hw; }
//QString customerId() { return m_customerId; }
//QString const customerId() const { return m_customerId; }

View File

@@ -46,17 +46,90 @@ QString Utils::zoneName(quint8 i) {
return "N/A";
}
void Utils::printCriticalErrorMsg(QString const &errorMsg) {
qCritical() << QString(80, '!');
void Utils::printCriticalErrorMsg(QString const &errorMsg, bool upper, bool lower) {
if (upper) qCritical() << QString(80, 'E');
qCritical() << errorMsg;
qCritical() << QString(80, '!');
if (lower) qCritical() << QString(80, 'E');
}
void Utils::printInfoMsg(QString const &infoMsg) {
qCritical() << QString(80, '=');
qCritical() << infoMsg;
qCritical() << QString(80, '=');
void Utils::printCriticalErrorMsg(QStringList const &errorMsg) {
qCritical() << QString(80, 'E');
for (int i = 0; i < errorMsg.size(); ++i) {
qCritical() << errorMsg.at(i);
}
qCritical() << QString(80, 'E');
}
void Utils::printUpdateStatusMsg(QDebug debug, QStringList const &updateMsg) {
//if (updateMsg.size() > 1) {
// qCritical() << QString(80, 'U');
//}
Q_UNUSED(debug);
for (int i = 0; i < updateMsg.size(); ++i) {
qInfo() << updateMsg.at(i);
}
//if (updateMsg.size() > 1) {
// qCritical() << QString(80, 'U');
//}
}
void Utils::printUpdateStatusMsg(QStringList const &updateMsg) {
//if (updateMsg.size() > 1) {
// qCritical() << QString(80, 'U');
//}
for (int i = 0; i < updateMsg.size(); ++i) {
qCritical() << updateMsg.at(i);
}
//if (updateMsg.size() > 1) {
// qCritical() << QString(80, 'U');
//}
}
void Utils::printUpdateStatusMsg(QString const &updateMsg, bool upper, bool lower) {
if (upper) qCritical() << QString(80, 'U');
qCritical() << updateMsg;
if (lower) qCritical() << QString(80, 'U');
}
void Utils::printUpdateStatusMsg(QDebug debug, QString const &updateMsg,
bool upper, bool lower) {
if (upper) debug << QString(80, 'U');
qInfo() << updateMsg;
if (lower) debug << QString(80, 'U');
}
void Utils::printInfoMsg(QString const &infoMsg, bool upper, bool lower) {
if (upper) qCritical() << QString(80, 'I');
qCritical() << infoMsg;
if (lower) qCritical() << QString(80, 'I');
}
void Utils::printInfoMsg(QStringList const &infoMsg) {
//if (infoMsg.size() > 1) {
// qCritical() << QString(80, 'I');
//}
for (int i = 0; i < infoMsg.size(); ++i) {
qCritical() << infoMsg.at(i);
}
//if (infoMsg.size() > 1) {
// qCritical() << QString(80, 'I');
//}
}
void Utils::printLineEditInfo(QStringList const &lines) {

11
utils.h
View File

@@ -8,12 +8,19 @@
#include <QFileInfo>
#include <QDateTime>
#include <QDir>
#include <QDebug>
namespace Utils {
int read1stLineOfFile(QString fileName);
QString zoneName(quint8 i);
void printCriticalErrorMsg(QString const &errorMsg);
void printInfoMsg(QString const &infoMsg);
void printCriticalErrorMsg(QString const &errorMsg, bool upper=false, bool lower=false);
void printCriticalErrorMsg(QStringList const &errorMsg);
void printInfoMsg(QString const &infoMsg, bool upper=false, bool lower=false);
void printInfoMsg(QStringList const &infoMsg);
void printUpdateStatusMsg(QDebug debug, QStringList const &updateMsg);
void printUpdateStatusMsg(QStringList const &updateMsg);
void printUpdateStatusMsg(QString const &updateMsg, bool upper=false, bool lower=false);
void printUpdateStatusMsg(QDebug debug, QString const &updateMsg, bool upper=false, bool lower=false);
void printLineEditInfo(QStringList const &lines);
QString getTariffLoadTime(QString fileName);
QString rstrip(QString const &str);

1523
worker.cpp

File diff suppressed because it is too large Load Diff

1143
worker.h

File diff suppressed because it is too large Load Diff