Move UpdatePTUDevCtrl files into subdir UpdatePTUDevCtrl
This commit is contained in:
		
							
								
								
									
										36
									
								
								UpdatePTUDevCtrl/DC2C_print01.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								UpdatePTUDevCtrl/DC2C_print01.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
{
 | 
			
		||||
"title":"DC2C_pri01",
 | 
			
		||||
"project":"DBM Szeged park_coins",
 | 
			
		||||
"issued":"13.04.2023 01.01",
 | 
			
		||||
"styl":"size 01",
 | 
			
		||||
"text":"PARKOLÓJEGY",
 | 
			
		||||
"styl":"size 11",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Nyugta",
 | 
			
		||||
"styl":"size 00",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"mögé jól láthatóan", 
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"elhelyezni!",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"A PARKOLÓ NEM ŐRZÖTT!",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"styl":"size 10",
 | 
			
		||||
"text":"Rendszám: ",
 | 
			
		||||
"styl":"size 00",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"vari":"Dynamic01",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Parkolási idõ vége:",
 | 
			
		||||
"vari":"Dynamic02",
 | 
			
		||||
"vari":"Dynamic03",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Parkolás helye:",
 | 
			
		||||
"vari":"location",
 | 
			
		||||
"text":"Összeg: ",
 | 
			
		||||
"vari":"Dynamic04",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								UpdatePTUDevCtrl/DC2C_print02.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								UpdatePTUDevCtrl/DC2C_print02.json
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
{
 | 
			
		||||
"title":"DC2C_pri02",
 | 
			
		||||
"project":"DBM Szeged park_coins",
 | 
			
		||||
"issued":"13.04.2023 01.01",
 | 
			
		||||
"text":"Kiadás időpontja:",
 | 
			
		||||
"vari":"date us",	
 | 
			
		||||
"vari":"time long",	
 | 
			
		||||
"text":"Automata száma: ",
 | 
			
		||||
"vari":"manu",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Park.jegy sorsz.: ",
 | 
			
		||||
"vari":"TickCtr",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Szegedi Közlekedési Kft",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"6720 Szeged ",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Zrínyi utca 4-8",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Adósz: 11092612-2-06", 
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"A jegy ára az ÁFA-t", 
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"     tartalmazza!",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Üf. szolg nyitvatartás:",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								UpdatePTUDevCtrl/DC2C_print03.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								UpdatePTUDevCtrl/DC2C_print03.json
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
"title":"DC2C_pri03",
 | 
			
		||||
"project":"DBM Szeged park_coins",
 | 
			
		||||
"issued":"13.04.2023 01.01",
 | 
			
		||||
"text":"H - P: 7:45 - 17:00",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Tel: (80) 820-500",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Parkoljon egy érintéssel. ",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"Használja bankkártyáját ",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"text":"  automatáinknál is!",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"feed":"nl",
 | 
			
		||||
"feed":"eject",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										267
									
								
								UpdatePTUDevCtrl/OnDemandUpdatePTU.pro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								UpdatePTUDevCtrl/OnDemandUpdatePTU.pro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,267 @@
 | 
			
		||||
QT += core gui
 | 
			
		||||
QT += widgets serialport network
 | 
			
		||||
 | 
			
		||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 | 
			
		||||
 | 
			
		||||
TARGET = ATBUpdateTool
 | 
			
		||||
 | 
			
		||||
# The following define makes your compiler emit warnings if you use
 | 
			
		||||
# any Qt feature that has been marked deprecated (the exact warnings
 | 
			
		||||
# depend on your compiler). Please consult the documentation of the
 | 
			
		||||
# deprecated API in order to know how to port your code away from it.
 | 
			
		||||
DEFINES += QT_DEPRECATED_WARNINGS
 | 
			
		||||
 | 
			
		||||
# You can also make your code fail to compile if it uses deprecated APIs.
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
# 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.
 | 
			
		||||
# 1.3.15:   Bug fixes found during testing.
 | 
			
		||||
#           Do not 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).
 | 
			
		||||
# 1.3.16:   Bug fixes found during testing.
 | 
			
		||||
# 1.3.17:   Add ATBUpdateTool.ini and custom command line parser. Settings
 | 
			
		||||
#           given in ATBUpdateTool.ini can be overwritten on the command-line.
 | 
			
		||||
# 1.3.18:   Bug fixes found during testing.
 | 
			
		||||
# 1.3.19:   Bug fixes found during testing.
 | 
			
		||||
# 1.3.20:   Bug fixes found during testing.
 | 
			
		||||
# 1.3.21:   Bug fixes found during testing:
 | 
			
		||||
#           Fix directory of ATBUpdateTool.ini to be the working directory of
 | 
			
		||||
#           the application rather than just ".".
 | 
			
		||||
#           Check existance of etc-directory inside customer repository.
 | 
			
		||||
#           Check for valid ISMAS trigger (button) 15x (=90s).
 | 
			
		||||
#           NOTE: if the customer repository is cloned (or repaired and cloned
 | 
			
		||||
#           again), and if the settings always-download-config=true and
 | 
			
		||||
#           always-download-dc=true in the ATBUpdateTool.ini file, the download
 | 
			
		||||
#           the printer-json files and the device controller file, even without
 | 
			
		||||
#           an activated ISMAS trigger (button). The tariff-files are rsynced to
 | 
			
		||||
#           the local filesystem for such clone.
 | 
			
		||||
#           Set new filename for device controller: dc2c.bin.
 | 
			
		||||
# 1.3.22:   Bug fixes found during testing:
 | 
			
		||||
#           Fix the path-names of the json-files and the device-controller.
 | 
			
		||||
#           Set automatic download of json-file in ATBUpdateTool.ini file for
 | 
			
		||||
#           a fresh clone of the repository.
 | 
			
		||||
# 1.3.23:   Added a 'break' to prevent a possible endless loop when checking if
 | 
			
		||||
#           the device is alive.
 | 
			
		||||
#
 | 
			
		||||
# NOTE:     The versioning info has to be shifted up by one version, i.e. what
 | 
			
		||||
#           happened for 1.3.23 was actually done in 1.3.24.
 | 
			
		||||
# 1.3.24
 | 
			
		||||
#
 | 
			
		||||
# 1.3._24_: Special version for szeged using a old dc-controller (4.42):
 | 
			
		||||
#           Changes:
 | 
			
		||||
#               (1) the ini-File now uses the libCAmaster.so.
 | 
			
		||||
# 1.3._25_: Again special version for szeged, using interface.h, version 4.4.
 | 
			
		||||
# 1.4.0   : Start with version at 1.4.0 (mainly to see a difference with Szeged)
 | 
			
		||||
#           Set hash-value in EVENT-objects. Set location (project), version
 | 
			
		||||
#           and info in send-last-version.
 | 
			
		||||
#           If the customer repository does not exist, then do not check the
 | 
			
		||||
#           ISMAS trigger, but proceed with the update procedure. Otherwise,
 | 
			
		||||
#           check the ISMAS update-trigger as first step.
 | 
			
		||||
#           If the current time is between 0.00 - 4.00 o'clock, then a wrong
 | 
			
		||||
#           trigger-value will result in an UPDATE_STEP_NOT_NECESSARY.
 | 
			
		||||
#           Move final processing to subclass UpdateProcessRunning.
 | 
			
		||||
#           Disable EXIT-button for the whole update-process, except for the
 | 
			
		||||
#           checking of the ISMAS-trigger-button (aka WAIT-button).
 | 
			
		||||
# 1.4.1   : Sync files in the customer repository (under ./etc) as the very
 | 
			
		||||
#           first step
 | 
			
		||||
VERSION="1.4.1"
 | 
			
		||||
# 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.
 | 
			
		||||
#   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:  Versionen der Json-Files lassen sich auslesen.
 | 
			
		||||
#       Problem: Einstellungen in den Json-Files lassen sich auch mittels
 | 
			
		||||
#       Funktionen in der CD-Library ueberschreiben. Damit ist dann wieder nicht
 | 
			
		||||
#       mehr so klar, was jetzt eigentlich aktiv ist.
 | 
			
		||||
#   8:  m_alwaysDownloadConfig und m_alwaysDownloadDC: vorbereitet: man koennte
 | 
			
		||||
#       es so arrangieren, dass der DC plus die Json-files im Repository immer
 | 
			
		||||
#       runtergeladen werden, obwohl sich im Repository gar nicts veraendert
 | 
			
		||||
#       hat. Eeventuell nuetzlich beim initialen Setuo eines PSA.
 | 
			
		||||
#   9:  Das Kunden-Repository sollte immer gezogen werden, unabhaengig von der
 | 
			
		||||
#       Stellung des WAIT-Button. Grund: es koennte sein, dass andernfalls ein
 | 
			
		||||
#       PSA weit hiter anderen steht, und dann ploetzlich einmal alle vorher-
 | 
			
		||||
#       gehenden Aenderungen anzieht, die gar nicht fuer ihn gemeint waren.
 | 
			
		||||
#  11:  Das Edit-Fenster teilen um die Anzeige zu verbessern.
 | 
			
		||||
#  12:  Bei einem Update muss immer ersichtlich sein, warum es ueberhaupt
 | 
			
		||||
#       angestossen wurde. Steht kein "WAIT" im ISMAS-Trigger, dann kann man
 | 
			
		||||
#       davon ausgehen, dass es sich um ein automatisches Update handelt.
 | 
			
		||||
#       In jedem Fall wird bei einem automatischen Update, bei dem der WAIT-
 | 
			
		||||
#       Button nicht gesetzt war, ein "OK" gesendet, falls sonst nichts weiter
 | 
			
		||||
#       zu tun ist. Beachte aber: wir haben auch noch den Fall, dass eine SD-
 | 
			
		||||
#       Karte gesteckt wird. In diesem Fall wird ein komplettes Update gefahren,
 | 
			
		||||
#       und zwar explizit auch ohne WAIT-Button.
 | 
			
		||||
#       Am Ende eines Updates steht im ISMAS entweder ein "OK" oder ein "FAIL".
 | 
			
		||||
# 13:   SendLastVersion: fuer jedes erfolgreich installierte Paket eine
 | 
			
		||||
#       Send-Last-Version-Nachricht an ISMAS. Dadurch entsteht im ISMAS eine
 | 
			
		||||
#       History (Christian darueber informieren).
 | 
			
		||||
# 14:   Installiert werden nur Dateien, die neu sind oder geaendert wurden.
 | 
			
		||||
#       Nicht etwas Dateien, die geloescht wurden: sicherstellen, dass man hier
 | 
			
		||||
#       immer direkt im repository arbeitet, nicht auf dem Filesystem.
 | 
			
		||||
#       Ferner: der DeviceController heisst dc2c.bin, auch fuer die Jsons
 | 
			
		||||
#       sind Dtandard-Namen vergeben. Alternativ: alle vorhandenen Jsons
 | 
			
		||||
#       werden runtergeladen: Thomas ist eh fuer deren Inhalte verantworlich.
 | 
			
		||||
#       WICHTIG: immer ueberpruefen, ob die Dateien im Customer-Repository
 | 
			
		||||
#       wirklich die richtigen Dateien sind.
 | 
			
		||||
# 15:   Der WAIT-Button laesst sich auf WAIT zuruecksetzen (etwa wenn git
 | 
			
		||||
#       selber Probleme hatte).
 | 
			
		||||
# 16:   Der Download-Thread sollte sowohl die auto-Variable auf false setzen
 | 
			
		||||
#       als auch den cycle-Timer stoppen, damit sichergestellt ist, dass der
 | 
			
		||||
#       Download des DC nicht gestoert wird.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
# 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 -O
 | 
			
		||||
 | 
			
		||||
contains( CONFIG, PTU5 ) {
 | 
			
		||||
    greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
 | 
			
		||||
    CONFIG += link_pkgconfig
 | 
			
		||||
    lessThan(QT_MAJOR_VERSION, 5):   PKGCONFIG += qextserialport
 | 
			
		||||
    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
 | 
			
		||||
    PTU5BASEPATH = /opt/devel/ptu5
 | 
			
		||||
    ARCH = PTU5
 | 
			
		||||
    DEFINES+=PTU5
 | 
			
		||||
 | 
			
		||||
    # add qmqtt lib
 | 
			
		||||
    #LIBS += -lQt5Qmqtt
 | 
			
		||||
}
 | 
			
		||||
contains( CONFIG, DesktopLinux ) {
 | 
			
		||||
    greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
 | 
			
		||||
    lessThan(QT_MAJOR_VERSION, 5):    CONFIG += extserialport
 | 
			
		||||
    # QMAKE_CC = ccache $$QMAKE_CC
 | 
			
		||||
    # QMAKE_CXX = ccache $$QMAKE_CXX
 | 
			
		||||
    QMAKE_CXXFLAGS += -std=c++17
 | 
			
		||||
    # QMAKE_CXXFLAGS += -Wno-deprecated-copy
 | 
			
		||||
    linux-clang {  QMAKE_CXXFLAGS += -Qunused-arguments   }
 | 
			
		||||
    ARCH = DesktopLinux
 | 
			
		||||
    DEFINES+=DesktopLinux
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SOURCES += \
 | 
			
		||||
        main.cpp \
 | 
			
		||||
        progress_event.cpp \
 | 
			
		||||
        update_dc_event.cpp \
 | 
			
		||||
        mainwindow.cpp \
 | 
			
		||||
        utils.cpp \
 | 
			
		||||
        update.cpp \
 | 
			
		||||
        git/git_client.cpp \
 | 
			
		||||
        ismas/ismas_client.cpp \
 | 
			
		||||
        process/command.cpp \
 | 
			
		||||
        message_handler.cpp \
 | 
			
		||||
        worker.cpp \
 | 
			
		||||
        commandline_parser.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS += \
 | 
			
		||||
        update.h \
 | 
			
		||||
        progress_event.h \
 | 
			
		||||
        update_dc_event.h \
 | 
			
		||||
        utils.h \
 | 
			
		||||
        mainwindow.h \
 | 
			
		||||
        git/git_client.h \
 | 
			
		||||
        apism/ismas_data.h \
 | 
			
		||||
        ismas/ismas_client.h \
 | 
			
		||||
        process/command.h \
 | 
			
		||||
        message_handler.h \
 | 
			
		||||
        worker.h \
 | 
			
		||||
        interfaces.h \
 | 
			
		||||
        commandline_parser.h \
 | 
			
		||||
        plugins/interfaces.h
 | 
			
		||||
 | 
			
		||||
OTHER_FILES += \
 | 
			
		||||
    ATBUpdateTool.ini
 | 
			
		||||
 | 
			
		||||
FORMS += \
 | 
			
		||||
    mainwindow.ui
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################################
 | 
			
		||||
# for running program on target through QtCreator
 | 
			
		||||
contains( CONFIG, PTU5 ) {
 | 
			
		||||
   qnx: target.path = /tmp/$${TARGET}/bin
 | 
			
		||||
   else: unix:!android: target.path = /opt/app/tools/atbupdate/
 | 
			
		||||
   !isEmpty(target.path): INSTALLS += target
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										477
									
								
								UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro.user
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										477
									
								
								UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro.user
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,477 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE QtCreatorProject>
 | 
			
		||||
<!-- Written by QtCreator 7.0.1, 2023-04-05T10:01:18. -->
 | 
			
		||||
<qtcreator>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>EnvironmentId</variable>
 | 
			
		||||
  <value type="QByteArray">{f1e3048b-d6d5-4c03-ba3e-d60a08550dca}</value>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.ActiveTarget</variable>
 | 
			
		||||
  <value type="qlonglong">0</value>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.EditorSettings</variable>
 | 
			
		||||
  <valuemap type="QVariantMap">
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
 | 
			
		||||
    <value type="QString" key="language">Cpp</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="value">
 | 
			
		||||
     <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
 | 
			
		||||
    <value type="QString" key="language">QmlJS</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="value">
 | 
			
		||||
     <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
 | 
			
		||||
   <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.IndentSize">4</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.MarginColumn">80</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.PaddingMode">1</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.TabSize">8</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.UseIndenter">false</value>
 | 
			
		||||
   <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
 | 
			
		||||
   <value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
 | 
			
		||||
   <value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
 | 
			
		||||
  </valuemap>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.PluginSettings</variable>
 | 
			
		||||
  <valuemap type="QVariantMap">
 | 
			
		||||
   <valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
 | 
			
		||||
    <value type="bool" key="AutoTest.Framework.Boost">true</value>
 | 
			
		||||
    <value type="bool" key="AutoTest.Framework.CTest">false</value>
 | 
			
		||||
    <value type="bool" key="AutoTest.Framework.Catch">true</value>
 | 
			
		||||
    <value type="bool" key="AutoTest.Framework.GTest">true</value>
 | 
			
		||||
    <value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
 | 
			
		||||
    <value type="bool" key="AutoTest.Framework.QtTest">true</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
 | 
			
		||||
   <value type="int" key="AutoTest.RunAfterBuild">0</value>
 | 
			
		||||
   <value type="bool" key="AutoTest.UseGlobal">true</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ClangTools">
 | 
			
		||||
    <value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
 | 
			
		||||
    <value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
 | 
			
		||||
    <value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
 | 
			
		||||
    <value type="int" key="ClangTools.ParallelJobs">3</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
 | 
			
		||||
    <valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
 | 
			
		||||
    <valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
 | 
			
		||||
    <value type="bool" key="ClangTools.UseGlobalSettings">true</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
  </valuemap>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.Target.0</variable>
 | 
			
		||||
  <valuemap type="QVariantMap">
 | 
			
		||||
   <value type="QString" key="DeviceType">Desktop</value>
 | 
			
		||||
   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.12.5 GCC 64bit</value>
 | 
			
		||||
   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.12.5 GCC 64bit</value>
 | 
			
		||||
   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5125.gcc_64_kit</value>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
 | 
			
		||||
    <value type="int" key="EnableQmlDebugging">0</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Debug</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Debug</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
 | 
			
		||||
      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
 | 
			
		||||
    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Release</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Release</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
 | 
			
		||||
      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
 | 
			
		||||
    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
 | 
			
		||||
    <value type="int" key="QtQuickCompiler">0</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
 | 
			
		||||
    <value type="int" key="EnableQmlDebugging">0</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Profile</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Profile</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
 | 
			
		||||
      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
 | 
			
		||||
    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
 | 
			
		||||
    <value type="int" key="QtQuickCompiler">0</value>
 | 
			
		||||
    <value type="int" key="SeparateDebugInfo">0</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
 | 
			
		||||
    <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="CustomOutputParsers"/>
 | 
			
		||||
    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/opt/ptu5/opt/UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/opt/ptu5/opt/UpdatePTUDevCtrl/UpdatePTUDevCtrl.pro</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
 | 
			
		||||
    <value type="QString" key="RunConfiguration.WorkingDirectory.default">/opt/ptu5/opt/build-UpdatePTUDevCtrl-Desktop_Qt_5_12_5_GCC_64bit-Debug</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
 | 
			
		||||
  </valuemap>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.Target.1</variable>
 | 
			
		||||
  <valuemap type="QVariantMap">
 | 
			
		||||
   <value type="QString" key="DeviceType">GenericLinuxOsType</value>
 | 
			
		||||
   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">i.MX6-ATB-PTU5</value>
 | 
			
		||||
   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">i.MX6-ATB-PTU5</value>
 | 
			
		||||
   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{cce48fb5-7479-4381-9a7f-7b1adfbd1ea1}</value>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
 | 
			
		||||
    <value type="int" key="EnableQmlDebugging">0</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-UpdatePTUDevCtrl-i_MX6_ATB_PTU5-Debug</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-UpdatePTUDevCtrl-i_MX6_ATB_PTU5-Debug</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
 | 
			
		||||
      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
 | 
			
		||||
    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-UpdatePTUDevCtrl-i_MX6_ATB_PTU5-Release</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-UpdatePTUDevCtrl-i_MX6_ATB_PTU5-Release</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
 | 
			
		||||
      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
 | 
			
		||||
    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
 | 
			
		||||
    <value type="int" key="QtQuickCompiler">0</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
 | 
			
		||||
    <value type="int" key="EnableQmlDebugging">0</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-UpdatePTUDevCtrl-i_MX6_ATB_PTU5-Profile</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-UpdatePTUDevCtrl-i_MX6_ATB_PTU5-Profile</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
 | 
			
		||||
      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
 | 
			
		||||
      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
 | 
			
		||||
    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
 | 
			
		||||
    <value type="int" key="QtQuickCompiler">0</value>
 | 
			
		||||
    <value type="int" key="SeparateDebugInfo">0</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.CheckForFreeDiskSpaceStep</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
 | 
			
		||||
      <value type="QString" key="RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck">/</value>
 | 
			
		||||
      <value type="qlonglong" key="RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace">5242880</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.KillAppStep</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
 | 
			
		||||
      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
 | 
			
		||||
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.RsyncDeployStep</value>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
 | 
			
		||||
      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
 | 
			
		||||
      <value type="QString" key="RemoteLinux.RsyncDeployStep.Flags">-av</value>
 | 
			
		||||
     </valuemap>
 | 
			
		||||
     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
 | 
			
		||||
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
 | 
			
		||||
    </valuemap>
 | 
			
		||||
    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
 | 
			
		||||
    <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
 | 
			
		||||
    <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">DeployToGenericLinux</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
 | 
			
		||||
    <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="CustomOutputParsers"/>
 | 
			
		||||
    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
 | 
			
		||||
    <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
 | 
			
		||||
    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="CustomOutputParsers"/>
 | 
			
		||||
    <value type="int" key="PE.EnvironmentAspect.Base">1</value>
 | 
			
		||||
    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.CustomRunConfig</value>
 | 
			
		||||
    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
 | 
			
		||||
    <value type="int" key="RemoteLinux.EnvironmentAspect.Version">1</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
 | 
			
		||||
    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
 | 
			
		||||
    <value type="QString" key="RunConfiguration.X11Forwarding">:0</value>
 | 
			
		||||
   </valuemap>
 | 
			
		||||
   <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
 | 
			
		||||
  </valuemap>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.TargetCount</variable>
 | 
			
		||||
  <value type="qlonglong">2</value>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
 | 
			
		||||
  <value type="int">22</value>
 | 
			
		||||
 </data>
 | 
			
		||||
 <data>
 | 
			
		||||
  <variable>Version</variable>
 | 
			
		||||
  <value type="int">22</value>
 | 
			
		||||
 </data>
 | 
			
		||||
</qtcreator>
 | 
			
		||||
							
								
								
									
										126
									
								
								UpdatePTUDevCtrl/allgemein.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								UpdatePTUDevCtrl/allgemein.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,126 @@
 | 
			
		||||
0:
 | 
			
		||||
    Zunaechst wir immer nachgesehen, ob das Repository bereits geklont wurde.
 | 
			
		||||
    Wenn nein, dann wird geklont. Im Master-Branch befinden sich Dateinen, die
 | 
			
		||||
    in allen anderen Branches gemeinsam genutzt werden. Das sollte wohl auf
 | 
			
		||||
    jeden Fall fuer den DeviceController gelten.
 | 
			
		||||
1:
 | 
			
		||||
    Anfrage bei ISMAS ob neue Daten da sind. Hier faengt die ganze Sache an.
 | 
			
		||||
    Da man nicht weiss, on ISMAS ueberhaupt antworten wird braucht es einen
 | 
			
		||||
    Timer. Man kann die Sache dann auch gleich mehrfach versuchen.
 | 
			
		||||
 | 
			
		||||
    Die Anfrage geht also per Signal an den Apism-Client. Im Signal wird der
 | 
			
		||||
    Zustand mitgegeben:
 | 
			
		||||
 | 
			
		||||
        ISMAS_UPDATE_REQUEST_PENDING
 | 
			
		||||
 | 
			
		||||
    und im Slot dann entsprechend uebernommen. Der Timer sollte nicht im Worker
 | 
			
		||||
    stehen, sondern im Apism-Client. Der Worker sollte damit nicht belastet
 | 
			
		||||
    sein. Der wird dann vom Apism-Client entsprechend benachrichtigt.
 | 
			
		||||
 | 
			
		||||
        ISMAS_UPDATE_REQUEST_FAILURE
 | 
			
		||||
            ISMAS_UPDATE_REQUEST_TIMEOUT
 | 
			
		||||
        ISMAS_UPDATE_REQUEST_SUCCESS
 | 
			
		||||
 | 
			
		||||
    Im 1./2.Fall wird dann ein Fehlerhandling durchgefuehrt. Insbesondere
 | 
			
		||||
    wird Apism ueber den DB-Kanal darueber informiert (U0003). Am Ende wie
 | 
			
		||||
    dann wie immer SendCmdVersion und beenden der Applikation.
 | 
			
		||||
 | 
			
		||||
    Im Erfolgsfall muss in der Antwort der Branch enthalten sein, fuer den das
 | 
			
		||||
    Update durchgefuhrt werden soll. Das ist auch bereits so (Location).
 | 
			
		||||
 | 
			
		||||
    Ein Sonderfall waere der -m-Modus, da hier niemand auf der ISMAS-Seite
 | 
			
		||||
    aktiv eingreift. Hier braucht es dann einen Ubergabeparameter an 
 | 
			
		||||
    ATBUpdateTool: --branch-name
 | 
			
		||||
 | 
			
		||||
    Normalfall ist aber die Aktivierung via ISMAS. Dann muss der in der Antwort
 | 
			
		||||
    enthaltene Branch zunaechst ausgecheckt werden.
 | 
			
		||||
2: 
 | 
			
		||||
    Dazu wird ein entsprechendes Signal an den GitClient gesandet.
 | 
			
		||||
        
 | 
			
		||||
        GIT_CHECKOUT_BRANCH_REQUEST
 | 
			
		||||
 | 
			
		||||
    Der GitClient sieht jetzt erstmal nach, ob es diesen Branch ueberhaupt
 | 
			
		||||
    gibt.
 | 
			
		||||
 | 
			
		||||
        Falls nein:    
 | 
			
		||||
 | 
			
		||||
        GIT_CHECKOUT_BRANCH_REQUEST_FAILURE
 | 
			
		||||
            BRANCH_NOT_EXIST
 | 
			
		||||
 
 | 
			
		||||
        Falls ja:
 | 
			
		||||
            der GitClient versucht nun den Branch auszuchecken. 
 | 
			
		||||
            Geht das gut?
 | 
			
		||||
            Falls nein:
 | 
			
		||||
 | 
			
		||||
                GIT_CHECKOUT_BRANCH_REQUEST_FAILURE
 | 
			
		||||
                    BRANCH_CHECKOUT_ERROR
 | 
			
		||||
 | 
			
		||||
            Falls ja:
 | 
			
		||||
                GIT_CHECKOUT_BRANCH_REQUEST_SUCCESS
 | 
			
		||||
                    -> eventl. koennte man den Namen des Branches mitgeben
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Signal an den Worker. Im entsprechenden Slot wird jetzt der eigentliche
 | 
			
		||||
        UpdateProzess angeworfen.
 | 
			
		||||
 3:
 | 
			
		||||
    Mittels git fetch werden jetzt die Aenderungen ermittelt.
 | 
			
		||||
 | 
			
		||||
        GIT_FETCH_UPDATES_REQUEST
 | 
			
		||||
        
 | 
			
		||||
        GIT_FETCH_UPDATES_REQUEST_FAILURE
 | 
			
		||||
            -> Worker informieren damit Fehlerbehandlung aktiviert wird
 | 
			
		||||
        GIT_FETCH_UPDATES_REQUEST_SUCCESS
 | 
			
		||||
 | 
			
		||||
        GIT_DIFF_UPDATES
 | 
			
		||||
 | 
			
		||||
        Die Liste der geaenderten Dateien geht an den Worker. Der kann jetzt
 | 
			
		||||
        noch Test machen, ob das Sinn macht. Evtl. eine Statusmeldung ausgeben
 | 
			
		||||
        drueber was gleich passieren wird.
 | 
			
		||||
4:
 | 
			
		||||
    Mittels git merge/pull werden nun die Dateien tatsaechlich im Branch 
 | 
			
		||||
    aktualisiert.
 | 
			
		||||
 | 
			
		||||
        GIT_PULL_UPDATES_REQUEST
 | 
			
		||||
        GIT_PULL_UPDATES_REQUEST_FAILURE
 | 
			
		||||
            -> Worker informieren damit Fehlerbehandlung aktiviert wird
 | 
			
		||||
        GIT_PULL_UPDATES_REQUEST_SUCCESS
 | 
			
		||||
            -> Worker informieren
 | 
			
		||||
 | 
			
		||||
    Sind die Daten vorhanden, dann werden sie mittels rsync ins Dateisystem
 | 
			
		||||
    kopiert.
 | 
			
		||||
 | 
			
		||||
        RSYNC_UPDATES 
 | 
			
		||||
        RSYNC_UPDATES_FAILURE
 | 
			
		||||
        RSYNC_UPDATES_SUCCESS
 | 
			
		||||
 | 
			
		||||
    Fuer jede kopierte Datei geht eine Nachricht raus ans ISMAS.
 | 
			
		||||
5:
 | 
			
		||||
    Sind die Daten dann kopiert, so werden sie auf den DC kopiert (falls
 | 
			
		||||
    notwendig): hier gehen dann wieder Nachrichten an ISMAS raus:
 | 
			
		||||
 | 
			
		||||
        DC_UPDATE 
 | 
			
		||||
        DC_UPDATE_FAILURE
 | 
			
		||||
        DC_UPDATE_SUCCESS
 | 
			
		||||
 | 
			
		||||
        JSON_UPDATE
 | 
			
		||||
        JSON_UPDATE_FAILURE
 | 
			
		||||
        JSON_UPDATE_SUCCESS
 | 
			
		||||
        
 | 
			
		||||
        Hier fuer jedes Json-File.
 | 
			
		||||
 | 
			
		||||
    Schliesslich noch eine Zusammenfasung an ISMAS:
 | 
			
		||||
 | 
			
		||||
        ISMAS_UPDATE_INFO_CONFIRM
 | 
			
		||||
        ISMAS_UPDATE_INFO_CONFIRM_FAILURE
 | 
			
		||||
            -> Worker informieren damit Fehlerbehandlung aktiviert wird
 | 
			
		||||
        ISMAS_UPDATE_INFO_CONFIRM_SUCCESS
 | 
			
		||||
 | 
			
		||||
    und schliesslich der abschliessende Status an ISMAS zurueckgemeldet:
 | 
			
		||||
 | 
			
		||||
        ISMAS_CURRENT_PSA_STATUS_CONFIRM
 | 
			
		||||
        ISMAS_CURRENT_PSA_STATUS_CONFIRM_FAILURE
 | 
			
		||||
        ISMAS_CURRENT_PSA_STATUS_CONFIRM_SUCCESS
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										137
									
								
								UpdatePTUDevCtrl/apism/ismas_data.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								UpdatePTUDevCtrl/apism/ismas_data.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
			
		||||
#ifndef ISMASDATA_H
 | 
			
		||||
#define ISMASDATA_H
 | 
			
		||||
 | 
			
		||||
#include <QJsonObject>
 | 
			
		||||
#include <QJsonArray>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ISMAS {
 | 
			
		||||
 | 
			
		||||
    struct TransferData : public QJsonObject {
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            QJsonValue tariffId;
 | 
			
		||||
            QJsonValue group;
 | 
			
		||||
            QJsonValue zone;
 | 
			
		||||
        } device;
 | 
			
		||||
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            QJsonValue state;
 | 
			
		||||
            QJsonValue uid;
 | 
			
		||||
            QJsonValue seq_tick_number;
 | 
			
		||||
            QJsonValue timestamp;
 | 
			
		||||
            QJsonValue userText;
 | 
			
		||||
            QJsonValue userTextType;
 | 
			
		||||
        } transaction;
 | 
			
		||||
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            // TODO: check what is really used at the moment
 | 
			
		||||
            QJsonValue id;          // unique article id
 | 
			
		||||
            QJsonValue name;        // name
 | 
			
		||||
            QJsonValue price;       // price in cent
 | 
			
		||||
            QJsonValue currency;    //
 | 
			
		||||
            QJsonValue startTime;   // start time
 | 
			
		||||
            QJsonValue endTime;     // end time
 | 
			
		||||
            QJsonValue userText;    // additional info
 | 
			
		||||
            QJsonValue parkingTime;
 | 
			
		||||
            QJsonValue printText;
 | 
			
		||||
            // QJsonValue discount;
 | 
			
		||||
        } item;
 | 
			
		||||
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            struct : public QJsonObject {
 | 
			
		||||
                QJsonValue coins;     // total amount of coins value
 | 
			
		||||
                // QJsonValue notes;     // total amount of notes value
 | 
			
		||||
                QJsonValue overpaid;  // in cent
 | 
			
		||||
                QJsonValue currency;
 | 
			
		||||
                QJsonValue change;
 | 
			
		||||
            } cash;
 | 
			
		||||
 | 
			
		||||
            struct : public QJsonObject {
 | 
			
		||||
                QJsonValue cardNumber;
 | 
			
		||||
                QJsonValue value;           // buchungsbetrag
 | 
			
		||||
                QJsonValue cardType;
 | 
			
		||||
                QJsonValue currency;
 | 
			
		||||
                QJsonValue tid;
 | 
			
		||||
                QJsonValue tresult;
 | 
			
		||||
            } card;
 | 
			
		||||
 | 
			
		||||
            struct : public QJsonObject {
 | 
			
		||||
                QJsonValue cardNumber;
 | 
			
		||||
                QJsonValue cardType;
 | 
			
		||||
                QJsonValue value;
 | 
			
		||||
                QJsonValue valueOld;
 | 
			
		||||
                QJsonValue valueNew;
 | 
			
		||||
                QJsonValue time;
 | 
			
		||||
                QJsonValue timeOld;
 | 
			
		||||
                QJsonValue timeNew;
 | 
			
		||||
            } prePaidCard;
 | 
			
		||||
        } payment;
 | 
			
		||||
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            QJsonValue delivery;    // PRINT, OnlineTicket
 | 
			
		||||
            QJsonValue result;      // SUCCESS, ERROR
 | 
			
		||||
            QJsonValue errorCode;   // 0=OK, 1=...
 | 
			
		||||
            QJsonValue errorMsg;
 | 
			
		||||
        } result;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    struct AccountData : public QJsonObject {
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            QJsonValue UID;
 | 
			
		||||
            QJsonValue ChangeNumber;
 | 
			
		||||
            QJsonValue Process;         // Vorgang
 | 
			
		||||
            QJsonValue startDateTime;
 | 
			
		||||
            QJsonValue endDateTime;
 | 
			
		||||
            QJsonValue startHash;
 | 
			
		||||
            QJsonValue endHash;
 | 
			
		||||
 | 
			
		||||
            struct : public QJsonObject {
 | 
			
		||||
                QJsonValue value;          // coin value
 | 
			
		||||
                QJsonValue numberOfCoins;  // number of coins
 | 
			
		||||
                QJsonValue currency;
 | 
			
		||||
            } coin;
 | 
			
		||||
 | 
			
		||||
        } coinBox;                  // Münzkasse
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    struct EventData : public QJsonObject {
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            QJsonValue eventID;
 | 
			
		||||
            QJsonValue deviceName;
 | 
			
		||||
            QJsonValue reason;
 | 
			
		||||
            QJsonValue event;
 | 
			
		||||
            QJsonValue eventState;
 | 
			
		||||
            QJsonValue timeStamp;
 | 
			
		||||
            QJsonValue parameter;
 | 
			
		||||
            QJsonValue secondLevelInfo;
 | 
			
		||||
        } machineEvent;                  //
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct StateData : public QJsonObject {
 | 
			
		||||
        QJsonValue Timestamp;
 | 
			
		||||
        QJsonArray HW_States;
 | 
			
		||||
        struct : public QJsonObject {
 | 
			
		||||
            QJsonValue name;
 | 
			
		||||
            QJsonValue value;
 | 
			
		||||
            QJsonValue unit;
 | 
			
		||||
        } machineState;                  //
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    enum class REQUEST : quint8 {
 | 
			
		||||
        NO_REQUEST,
 | 
			
		||||
        START,
 | 
			
		||||
        STOP,
 | 
			
		||||
        PING,
 | 
			
		||||
        SELF,
 | 
			
		||||
        ISMAS_PARAMETER
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // ISMASDATA_H
 | 
			
		||||
							
								
								
									
										266
									
								
								UpdatePTUDevCtrl/commandline_parser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								UpdatePTUDevCtrl/commandline_parser.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,266 @@
 | 
			
		||||
#include "commandline_parser.h"
 | 
			
		||||
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
 | 
			
		||||
CommandLineParser::CommandLineParser()
 | 
			
		||||
  : m_repositoryUrl("https://git.mimbach49.de/GerhardHoffmann")
 | 
			
		||||
  , m_plugInDir("/usr/lib/")
 | 
			
		||||
  , m_plugInName("libCAslave.so")
 | 
			
		||||
  , m_workingDir("/opt/app/tools/atbupdate/")
 | 
			
		||||
  , m_dryRun("false")
 | 
			
		||||
  , m_noUpdatePsaHardware("false")
 | 
			
		||||
  , m_showYoctoVersion("false")
 | 
			
		||||
  , m_showYoctoInstallStatus("false")
 | 
			
		||||
  , m_showExtendedVersion("false")
 | 
			
		||||
  , m_iniFileName("ATBUpdateTool.ini")
 | 
			
		||||
  , m_alwaysDownloadConfig("false")
 | 
			
		||||
  , m_alwaysDownloadDC("false")
 | 
			
		||||
  , m_repositoryUrlOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "repository-url" << "repository-url",
 | 
			
		||||
            QCoreApplication::translate("main", "Where to find a customer repository."),
 | 
			
		||||
            QCoreApplication::translate("main", "directory")))
 | 
			
		||||
  , m_iniFileDirectoryOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "ini-directory" << "ini-directory",
 | 
			
		||||
            QCoreApplication::translate("main", "Where to find an ini-file."),
 | 
			
		||||
            QCoreApplication::translate("main", "directory")))
 | 
			
		||||
  , m_iniFileNameOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "ini-filename" << "ini-filename",
 | 
			
		||||
            QCoreApplication::translate("main", "Name of ini-file."),
 | 
			
		||||
            QCoreApplication::translate("main", "file")))
 | 
			
		||||
  , m_pluginDirectoryOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "plugin-directory" << "plugin-directory",
 | 
			
		||||
            QCoreApplication::translate("main", "Where to find dc-plugin."),
 | 
			
		||||
            QCoreApplication::translate("main", "directory")))
 | 
			
		||||
  , m_pluginNameOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "plugin-name" << "plugin-name",
 | 
			
		||||
            QCoreApplication::translate("main", "Name of dc-plugin."),
 | 
			
		||||
            QCoreApplication::translate("main", "directory")))
 | 
			
		||||
  , m_noDownloadOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            "no-psa-hardware-update",
 | 
			
		||||
            QCoreApplication::translate("main", "Do not update the PSA firmware (json, device-controller).")))
 | 
			
		||||
  , m_alwaysDownloadConfigOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            "always-download-config",
 | 
			
		||||
            QCoreApplication::translate("main", "Always download the (json-)configs to DC).")))
 | 
			
		||||
  , m_alwaysDownloadDCOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            "always-download-dc",
 | 
			
		||||
            QCoreApplication::translate("main", "Always download the dc-bin-file to DC).")))
 | 
			
		||||
  , m_workingDirectoryOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "working-directory" << "working-directory",
 | 
			
		||||
            QCoreApplication::translate("main", "working directory of update-script."),
 | 
			
		||||
            QCoreApplication::translate("main", "directory")))
 | 
			
		||||
  , m_dryRunOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "d" << "dry-run",
 | 
			
		||||
            QCoreApplication::translate("main", "Start ATBUpdateTool in dry-run-mode. No actual actions.")))
 | 
			
		||||
  , m_extendedVersionOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "V" << "extended-version",
 | 
			
		||||
            QCoreApplication::translate("main", "Show extended version (including last git commit).")))
 | 
			
		||||
  , m_yoctoVersionOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "y" << "yocto-version",
 | 
			
		||||
            QCoreApplication::translate("main", "Show yocto version of ATBUpdateTool.")))
 | 
			
		||||
  , m_yoctoInstallStatusOption(
 | 
			
		||||
        QCommandLineOption(
 | 
			
		||||
            QStringList() << "Y" << "yocto-install",
 | 
			
		||||
            QCoreApplication::translate("main", "Show yocto install status of ATBUpdateTool."))) {
 | 
			
		||||
    configure();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CommandLineParser::configure() {
 | 
			
		||||
    m_parser.setApplicationDescription("Download tool for downloading device controller firmware, printer json-files and executing opkg-commands.");
 | 
			
		||||
    m_parser.addHelpOption();
 | 
			
		||||
    m_parser.addVersionOption();
 | 
			
		||||
 | 
			
		||||
    m_repositoryUrlOption.setDefaultValue("https://git.mimbach49.de/GerhardHoffmann");
 | 
			
		||||
    m_parser.addOption(m_repositoryUrlOption);
 | 
			
		||||
 | 
			
		||||
    m_iniFileDirectoryOption.setDefaultValue(QCoreApplication::applicationDirPath());
 | 
			
		||||
    m_parser.addOption(m_iniFileDirectoryOption);
 | 
			
		||||
 | 
			
		||||
    m_iniFileNameOption.setDefaultValue("ATBUpdateTool.ini");
 | 
			
		||||
    m_parser.addOption(m_iniFileNameOption);
 | 
			
		||||
 | 
			
		||||
    m_pluginDirectoryOption.setDefaultValue("/usr/lib/");
 | 
			
		||||
    m_parser.addOption(m_pluginDirectoryOption);
 | 
			
		||||
 | 
			
		||||
    m_pluginNameOption.setDefaultValue("libCAslave.so");
 | 
			
		||||
    m_parser.addOption(m_pluginNameOption);
 | 
			
		||||
 | 
			
		||||
    m_alwaysDownloadConfigOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_alwaysDownloadConfigOption);
 | 
			
		||||
 | 
			
		||||
    m_alwaysDownloadDCOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_alwaysDownloadDCOption);
 | 
			
		||||
 | 
			
		||||
    m_noDownloadOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_noDownloadOption);
 | 
			
		||||
 | 
			
		||||
    m_workingDirectoryOption.setDefaultValue("/opt/app/tools/atbupdate/");
 | 
			
		||||
    m_parser.addOption(m_workingDirectoryOption);
 | 
			
		||||
 | 
			
		||||
    m_dryRunOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_dryRunOption);
 | 
			
		||||
 | 
			
		||||
    m_extendedVersionOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_extendedVersionOption);
 | 
			
		||||
 | 
			
		||||
    m_yoctoVersionOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_yoctoVersionOption);
 | 
			
		||||
 | 
			
		||||
    m_yoctoInstallStatusOption.setDefaultValue("false");
 | 
			
		||||
    m_parser.addOption(m_yoctoInstallStatusOption);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CommandLineParser::readSettings() {
 | 
			
		||||
    QString const iniFileDir = m_parser.value(m_iniFileDirectoryOption);
 | 
			
		||||
    QString const iniFileName = m_parser.value(m_iniFileNameOption);
 | 
			
		||||
    m_iniFileName = QDir::cleanPath(iniFileDir + QDir::separator() + iniFileName);
 | 
			
		||||
 | 
			
		||||
    qCritical() << __PRETTY_FUNCTION__ << " iniFileDir" << iniFileDir;
 | 
			
		||||
    qCritical() << __PRETTY_FUNCTION__ << "iniFileName" << m_iniFileName;
 | 
			
		||||
 | 
			
		||||
    if (!m_iniFileName.isEmpty()) {
 | 
			
		||||
        if (QFile(m_iniFileName).exists()) {
 | 
			
		||||
            QSettings settings(m_iniFileName, QSettings::IniFormat);
 | 
			
		||||
            QStringList keys = settings.allKeys();
 | 
			
		||||
            for (QString const &key: keys) {
 | 
			
		||||
                QVariant v = settings.value(key);
 | 
			
		||||
 | 
			
		||||
                qCritical() << __PRETTY_FUNCTION__
 | 
			
		||||
                            << key << " -> " << v.toString();
 | 
			
		||||
 | 
			
		||||
                if (key.contains("repository-url")) {
 | 
			
		||||
                    m_repositoryUrl = v.toString();
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("plugin-directory")) {
 | 
			
		||||
                    m_plugInDir = v.toString();
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("working-directory")) {
 | 
			
		||||
                    m_workingDir = v.toString();
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("dry-run")) {
 | 
			
		||||
                    m_dryRun = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("extended-version")) {
 | 
			
		||||
                    m_showExtendedVersion = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("no-psa-hardware-update")) {
 | 
			
		||||
                    m_noUpdatePsaHardware = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("always-download-config")) {
 | 
			
		||||
                    m_alwaysDownloadConfig = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("always-download-dc")) {
 | 
			
		||||
                    m_alwaysDownloadDC = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("yocto-install")) {
 | 
			
		||||
                    m_showYoctoInstallStatus = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("yocto-version")) {
 | 
			
		||||
                    m_showYoctoVersion = (v.toBool() ? "true" : "false");
 | 
			
		||||
                } else
 | 
			
		||||
                if (key.contains("plugin-name")) {
 | 
			
		||||
                    m_plugInName = v.toString();
 | 
			
		||||
                } else {
 | 
			
		||||
                    qCritical() << __PRETTY_FUNCTION__
 | 
			
		||||
                                << key << " -> (UNKNOWN) " << v.toString();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            qCritical() << __PRETTY_FUNCTION__ << "iniFileName" << m_iniFileName
 | 
			
		||||
                        << "DOES NOT EXIST";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString CommandLineParser::repositoryUrl() {
 | 
			
		||||
    if (m_parser.isSet(m_repositoryUrlOption)) {
 | 
			
		||||
        m_repositoryUrl = m_parser.value(m_repositoryUrlOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_repositoryUrl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString CommandLineParser::plugInDir() {
 | 
			
		||||
    if (m_parser.isSet(m_pluginDirectoryOption)) {
 | 
			
		||||
        m_plugInDir = m_parser.value(m_pluginDirectoryOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_plugInDir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString CommandLineParser::plugInName() {
 | 
			
		||||
    if (m_parser.isSet(m_pluginNameOption)) {
 | 
			
		||||
        m_plugInName = m_parser.value(m_pluginNameOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_plugInName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString CommandLineParser::workingDir() {
 | 
			
		||||
    if (m_parser.isSet(m_workingDirectoryOption)) {
 | 
			
		||||
        m_workingDir = m_parser.value(m_workingDirectoryOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_workingDir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::dryRun() {
 | 
			
		||||
    if (m_parser.isSet(m_dryRunOption)) {
 | 
			
		||||
        m_dryRun = m_parser.value(m_dryRunOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_dryRun == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::noUpdatePsaHardware() {
 | 
			
		||||
    if (m_parser.isSet(m_noDownloadOption)) {
 | 
			
		||||
        m_noUpdatePsaHardware = m_parser.value(m_noDownloadOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_noUpdatePsaHardware == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::yoctoVersion() {
 | 
			
		||||
    if (m_parser.isSet(m_yoctoVersionOption)) {
 | 
			
		||||
        m_showYoctoVersion = m_parser.value(m_yoctoVersionOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_showYoctoVersion == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::yoctoInstallStatus() {
 | 
			
		||||
    if (m_parser.isSet(m_yoctoInstallStatusOption)) {
 | 
			
		||||
        m_showYoctoInstallStatus = m_parser.value(m_yoctoInstallStatusOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_showYoctoInstallStatus == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::extendedVersion() {
 | 
			
		||||
    if (m_parser.isSet(m_extendedVersionOption)) {
 | 
			
		||||
        m_showExtendedVersion = m_parser.value(m_extendedVersionOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_showExtendedVersion == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::alwaysDownloadConfig() {
 | 
			
		||||
    if (m_parser.isSet(m_alwaysDownloadConfigOption)) {
 | 
			
		||||
        m_alwaysDownloadConfig = m_parser.value(m_alwaysDownloadConfigOption);
 | 
			
		||||
        qCritical() << "m_alwaysDownloadConfigOption IS SET" << m_alwaysDownloadConfig;
 | 
			
		||||
    }
 | 
			
		||||
    qCritical() << "m_alwaysDownloadConfig" << m_alwaysDownloadConfig;
 | 
			
		||||
    return m_alwaysDownloadConfig == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommandLineParser::alwaysDownloadDC() {
 | 
			
		||||
    if (m_parser.isSet(m_alwaysDownloadDCOption)) {
 | 
			
		||||
        m_alwaysDownloadDC = m_parser.value(m_alwaysDownloadDCOption);
 | 
			
		||||
    }
 | 
			
		||||
    return m_alwaysDownloadDC == "false" ? false : true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								UpdatePTUDevCtrl/commandline_parser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								UpdatePTUDevCtrl/commandline_parser.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
#ifndef COMMAND_LINE_PARSER_H_INCLUDED
 | 
			
		||||
#define COMMAND_LINE_PARSER_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QCommandLineParser>
 | 
			
		||||
#include <QCommandLineOption>
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
class CommandLineParser : public QCommandLineParser {
 | 
			
		||||
    QString m_repositoryUrl;
 | 
			
		||||
    QString m_plugInDir;
 | 
			
		||||
    QString m_plugInName;
 | 
			
		||||
    QString m_workingDir;
 | 
			
		||||
    QString m_dryRun;
 | 
			
		||||
    QString m_noUpdatePsaHardware;
 | 
			
		||||
    QString m_showYoctoVersion;
 | 
			
		||||
    QString m_showYoctoInstallStatus;
 | 
			
		||||
    QString m_showExtendedVersion;
 | 
			
		||||
    QString m_iniFileName;
 | 
			
		||||
    QString m_alwaysDownloadConfig;
 | 
			
		||||
    QString m_alwaysDownloadDC;
 | 
			
		||||
 | 
			
		||||
    QCommandLineOption m_repositoryUrlOption;
 | 
			
		||||
    QCommandLineOption m_iniFileDirectoryOption;
 | 
			
		||||
    QCommandLineOption m_iniFileNameOption;
 | 
			
		||||
    QCommandLineOption m_pluginDirectoryOption;
 | 
			
		||||
    QCommandLineOption m_pluginNameOption;
 | 
			
		||||
    QCommandLineOption m_noDownloadOption;
 | 
			
		||||
    QCommandLineOption m_alwaysDownloadConfigOption;
 | 
			
		||||
    QCommandLineOption m_alwaysDownloadDCOption;
 | 
			
		||||
    QCommandLineOption m_workingDirectoryOption;
 | 
			
		||||
    QCommandLineOption m_dryRunOption;
 | 
			
		||||
    QCommandLineOption m_extendedVersionOption;
 | 
			
		||||
    QCommandLineOption m_yoctoVersionOption;
 | 
			
		||||
    QCommandLineOption m_yoctoInstallStatusOption;
 | 
			
		||||
 | 
			
		||||
    QCommandLineParser m_parser;
 | 
			
		||||
 | 
			
		||||
    void configure();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    explicit CommandLineParser();
 | 
			
		||||
    ~CommandLineParser() = default;
 | 
			
		||||
 | 
			
		||||
    QCommandLineParser &parser() { return m_parser; }
 | 
			
		||||
    QCommandLineParser const &parser() const { return m_parser; }
 | 
			
		||||
    void process(const QCoreApplication &app) { m_parser.process(app); }
 | 
			
		||||
    QString const &iniFileName() const { return m_iniFileName; }
 | 
			
		||||
    void readSettings();
 | 
			
		||||
    QString repositoryUrl();
 | 
			
		||||
    QString plugInDir();
 | 
			
		||||
    QString plugInName();
 | 
			
		||||
    QString workingDir();
 | 
			
		||||
    bool dryRun();
 | 
			
		||||
    bool noUpdatePsaHardware();
 | 
			
		||||
    bool yoctoVersion();
 | 
			
		||||
    bool yoctoInstallStatus();
 | 
			
		||||
    bool extendedVersion();
 | 
			
		||||
    bool alwaysDownloadConfig();
 | 
			
		||||
    bool alwaysDownloadDC();
 | 
			
		||||
};
 | 
			
		||||
#endif // COMMAND_LINE_PARSER_H_INCLUDED
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/dc2c4.bin
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/dc2c4.bin
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										230
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool.drawio
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool.drawio
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,230 @@
 | 
			
		||||
<mxfile host="www.draw.io" modified="2023-11-07T10:37:35.350Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0" etag="ldmgaDoAxcOIqmOptaKH" version="22.0.8" type="device">
 | 
			
		||||
  <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
 | 
			
		||||
    <mxGraphModel dx="1042" dy="633" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
 | 
			
		||||
      <root>
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-2" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-3" target="WIyWlLk6GJQsqaUBKTNV-6" edge="1">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-3" value="START" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
 | 
			
		||||
          <mxGeometry x="350" y="10" width="120" height="40" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-6">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="220" y="180" as="targetPoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-6" value="<div><br></div><div>Existent customer repository</div><div>?</div>" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
 | 
			
		||||
          <mxGeometry x="170" y="60" width="100" height="90" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <object label="" id="KwNStDcgQ-FNAQaH3l0E-18">
 | 
			
		||||
          <mxCell style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-7" target="KwNStDcgQ-FNAQaH3l0E-9">
 | 
			
		||||
            <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
          </mxCell>
 | 
			
		||||
        </object>
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-7" value="Clone customer repository" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
 | 
			
		||||
          <mxGeometry x="310" y="130" width="120" height="40" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="WIyWlLk6GJQsqaUBKTNV-10" value="<div><br></div><div>Repository corrupted</div><div>?</div>" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
 | 
			
		||||
          <mxGeometry x="170" y="180" width="100" height="80" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.15;entryY=0.55;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-9" target="KwNStDcgQ-FNAQaH3l0E-110">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="600" y="150" as="targetPoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-9" value="<div><br></div><div>Repository corrupted</div><div>?</div>" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="480" y="150" width="90" height="80" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-11" value="FAIL" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="585" y="10" width="100" height="40" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <UserObject label="Yes" placeholders="1" name="Variable" id="KwNStDcgQ-FNAQaH3l0E-20">
 | 
			
		||||
          <mxCell style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
            <mxGeometry x="560" y="160" width="80" height="20" as="geometry" />
 | 
			
		||||
          </mxCell>
 | 
			
		||||
        </UserObject>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-23" value="<div>No</div><div><br></div>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="430" y="280" width="60" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-25" value="Delete corrupted repository" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="310" y="200" width="120" height="40" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-26" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-25">
 | 
			
		||||
          <mxGeometry width="80" relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="270" y="220" as="sourcePoint" />
 | 
			
		||||
            <mxPoint x="310" y="220" as="targetPoint" />
 | 
			
		||||
            <Array as="points" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-27" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-25" target="WIyWlLk6GJQsqaUBKTNV-7">
 | 
			
		||||
          <mxGeometry width="80" relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="540" y="240" as="sourcePoint" />
 | 
			
		||||
            <mxPoint x="620" y="240" as="targetPoint" />
 | 
			
		||||
            <Array as="points" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-93" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-28" target="KwNStDcgQ-FNAQaH3l0E-92">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-28" value="<div><br></div><div>ISMAS trigger</div><div><b>WAIT</b><br></div><div>?<b><br></b></div>" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="300" y="380" width="140" height="90" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-29" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-9" target="KwNStDcgQ-FNAQaH3l0E-78">
 | 
			
		||||
          <mxGeometry width="80" relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="540" y="240" as="sourcePoint" />
 | 
			
		||||
            <mxPoint x="420" y="300" as="targetPoint" />
 | 
			
		||||
            <Array as="points">
 | 
			
		||||
              <mxPoint x="525" y="300" />
 | 
			
		||||
            </Array>
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-34" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-37">
 | 
			
		||||
          <mxGeometry width="80" relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="220" y="260" as="sourcePoint" />
 | 
			
		||||
            <mxPoint x="320" y="300" as="targetPoint" />
 | 
			
		||||
            <Array as="points">
 | 
			
		||||
              <mxPoint x="220" y="300" />
 | 
			
		||||
            </Array>
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-37" value="<div>No</div><div><br></div>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="250" y="280" width="120" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-42" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-28" target="KwNStDcgQ-FNAQaH3l0E-72">
 | 
			
		||||
          <mxGeometry width="80" relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="260" y="430" as="sourcePoint" />
 | 
			
		||||
            <mxPoint x="99" y="560" as="targetPoint" />
 | 
			
		||||
            <Array as="points">
 | 
			
		||||
              <mxPoint x="40" y="425" />
 | 
			
		||||
              <mxPoint x="40" y="570" />
 | 
			
		||||
            </Array>
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-43" value="<div>Yes</div><div><br></div>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="240" y="405" width="60" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-65" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-45">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="120" y="585" as="sourcePoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-46">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="120" y="670" as="sourcePoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-44">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="120" y="510" as="sourcePoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.994;exitY=0.491;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-75" target="KwNStDcgQ-FNAQaH3l0E-107">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="760" y="445" as="targetPoint" />
 | 
			
		||||
            <mxPoint x="730" y="580" as="sourcePoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-78" target="KwNStDcgQ-FNAQaH3l0E-28">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-78" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="360" y="290" width="20" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-6" target="WIyWlLk6GJQsqaUBKTNV-7">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-83" value="<div>No</div><div><br></div>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="290" y="90" width="60" height="30" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-84" value="<div><br></div><div><br></div><div>Yes</div><div><br></div><div><br></div>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="170" y="140" width="60" height="30" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-86" value="opkg_commands always counts as a file to update" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="240" y="610" width="120" height="100" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-87" value="in case someone has changed the zone (which means changed the branch)" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="90" y="610" width="140" height="100" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-88" value="Update Json-configuration files) and the device controller firmware." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="370" y="610" width="180" height="100" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-89" value="Sync tariff-files and ini-files with local filesystem." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="560" y="610" width="160" height="100" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-90" value="Make sure the customer repository is in place and useable." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="20" y="110" width="140" height="95" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-91" value="<b>NEVER</b> do any real update-steps without an active ISMAS trigger." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="20" y="320" width="140" height="80" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-92" value="<div><br></div><div>Initial/repaired</div><div>clone</div><div>?<br></div>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="585" y="375" width="100" height="100" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-96" value="SUCCESS" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="710" y="10" width="100" height="40" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-132" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-97" target="KwNStDcgQ-FNAQaH3l0E-11">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-97" value="<div>Send Last Version</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="580" y="100" width="110" height="30" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-99" value="No" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="450" y="400" width="60" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-103" value="No" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="580" y="330" width="60" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-104" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.15;entryY=0.4;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-92" target="KwNStDcgQ-FNAQaH3l0E-107">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry">
 | 
			
		||||
            <mxPoint x="700" y="425" as="targetPoint" />
 | 
			
		||||
          </mxGeometry>
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-106" value="" style="group" vertex="1" connectable="0" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="50" y="540" width="770" height="57" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-72" value="<div><br></div><div>&nbsp;&nbsp; Checkout branch</div><div><br></div>" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
 | 
			
		||||
          <mxGeometry width="130" height="57" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-73" value="<div>Update files</div><div>(Json, DeviceController)<br></div>" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
 | 
			
		||||
          <mxGeometry x="350" width="194" height="57" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-74" value="<div>Compute files <br></div><div>to update<br></div>" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
 | 
			
		||||
          <mxGeometry x="110" width="140" height="57" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-75" value="<div>(R)Sync with local</div><div>filesystem<br></div>" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
 | 
			
		||||
          <mxGeometry x="520" width="170" height="57" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-105" value="<div>Exec</div><div>opkg-commands</div>" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
 | 
			
		||||
          <mxGeometry x="230" width="140" height="57" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-107" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="750" y="415" width="20" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-109" value="<div>Yes</div><div><br></div>" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="690" y="415" width="60" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-120" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-110" target="KwNStDcgQ-FNAQaH3l0E-97">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-110" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="625" y="180" width="20" height="20" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-129" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.95;entryY=0.95;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-92" target="KwNStDcgQ-FNAQaH3l0E-110">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-135" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-130" target="KwNStDcgQ-FNAQaH3l0E-96">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-130" value="<div>Send Last Version</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
 | 
			
		||||
          <mxGeometry x="705" y="100" width="110" height="30" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
        <mxCell id="KwNStDcgQ-FNAQaH3l0E-131" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-107" target="KwNStDcgQ-FNAQaH3l0E-130">
 | 
			
		||||
          <mxGeometry relative="1" as="geometry" />
 | 
			
		||||
        </mxCell>
 | 
			
		||||
      </root>
 | 
			
		||||
    </mxGraphModel>
 | 
			
		||||
  </diagram>
 | 
			
		||||
</mxfile>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool.drawio-3.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool.drawio-3.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool.drawio-4.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool.drawio-4.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool4.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/ATBUpdateTool4.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/update_ptu.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/doc/update_ptu.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										172
									
								
								UpdatePTUDevCtrl/doc/update_ptu.tex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								UpdatePTUDevCtrl/doc/update_ptu.tex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
			
		||||
\documentclass[12pt]{article}
 | 
			
		||||
\usepackage{euler}
 | 
			
		||||
\usepackage[english]{babel}
 | 
			
		||||
\usepackage{lipsum}
 | 
			
		||||
\usepackage{multirow}
 | 
			
		||||
\usepackage[colorlinks=true, urlcolor=blue, linkcolor=red]{hyperref}
 | 
			
		||||
\newcounter{Chapcounter}
 | 
			
		||||
\newcommand\showmycounter{\addtocounter{Chapcounter}{1}\themycounter}
 | 
			
		||||
\newcommand{\chapter}[1] 
 | 
			
		||||
{{\centering          
 | 
			
		||||
  \addtocounter{Chapcounter}{1} \Large \underline{\textbf{ \color{blue} Chapter \theChapcounter: ~#1}} }   
 | 
			
		||||
  \addcontentsline{toc}{section}{ \color{blue} Chapter:~\theChapcounter~~ #1}    
 | 
			
		||||
}
 | 
			
		||||
\hypersetup{colorlinks=true}
 | 
			
		||||
\hypersetup{linkcolor=black}
 | 
			
		||||
 | 
			
		||||
\title{Update PTU}
 | 
			
		||||
\author{Gerhard Hoffmann}
 | 
			
		||||
\date{\today}
 | 
			
		||||
 | 
			
		||||
\begin{document}
 | 
			
		||||
\maketitle
 | 
			
		||||
% \chapter{Introduction}
 | 
			
		||||
\section{Motivation}
 | 
			
		||||
 | 
			
		||||
The two main components of a PSA are
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
    \item PTU software.
 | 
			
		||||
    \item Device controller (DC) firmware.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
 | 
			
		||||
While the DC firmware is basically the same for each PSA (even for different
 | 
			
		||||
customers), the PTU software is highly dependent on customer requirements.\par
 | 
			
		||||
Hence, each customer is assigned an own git-repository, which will be loaded
 | 
			
		||||
("cloned") on the PSA when configuring the machine for the first time.\par
 | 
			
		||||
Two special tools, the {\bf UpdateController} (a \href{https://doc.qt.io/qt-5/}{Qt}
 | 
			
		||||
binary [{\bf \nameref{UpdateTool}}]) and the {\bf UpdateScript}
 | 
			
		||||
(a \href{https://www.gnu.org/software/bash/manual/bash.html}{bash}
 | 
			
		||||
script [{\bf \nameref{UpdateScript}}]), work together to finish a PSA installation.\par 
 | 
			
		||||
    
 | 
			
		||||
\section{PSA: Initial configuration}
 | 
			
		||||
 | 
			
		||||
For the initial configuration, a PSA loads a customer-specific git-repository,
 | 
			
		||||
which structure is detailed below [{\bf \nameref{repostructure}}].\par
 | 
			
		||||
The "git clone" for the repository is done by the UpdateScript [{\bf \nameref{UpdateScript}}].
 | 
			
		||||
It updates the file
 | 
			
		||||
\begin{center}
 | 
			
		||||
    \fbox{
 | 
			
		||||
        /opt/app/tools/atbupdate/update\_log.csv
 | 
			
		||||
    }
 | 
			
		||||
\end{center}
 | 
			
		||||
which will be interpreted by the UpdateController [{\bf \nameref{UpdateTool}}].
 | 
			
		||||
The structure of [{\bf \nameref{updatelogcsv}}] is detailed below.\par
 | 
			
		||||
Each line of update\_log.csv represents a command for the UpdateController,
 | 
			
		||||
which will either download certain files to the DC or execute some
 | 
			
		||||
\href{https://openwrt.org/docs/guide-user/additional-software/opkg}{opkg}
 | 
			
		||||
commands [{\bf \nameref{opkg}}].
 | 
			
		||||
        
 | 
			
		||||
\section{PSA: Update}
 | 
			
		||||
   
 | 
			
		||||
The update of a PSA is basically managed by \href{https://git-scm.com/}{git}, a
 | 
			
		||||
free and open source distributed version control system. Like many other Version
 | 
			
		||||
Control Systems, git has a way to fire off custom scripts when certain important
 | 
			
		||||
actions occur, so-called \href{https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks}{hooks}.
 | 
			
		||||
The hooks used for a PSA update are called {\bf post-checkout} and {\bf post-merge}.\par
 | 
			
		||||
The post-checkout hook is called when checking out some branch of the customer-repository
 | 
			
		||||
(for instance when cloning the customer repository for the first time). In contrast,
 | 
			
		||||
the post-merge hook is called when a \href{https://www.git-scm.com/docs/git-pull}{git pull}
 | 
			
		||||
operation has been issued (more precisely, a \href {https://www.git-scm.com/docs/git-fetch}{git-fetch}
 | 
			
		||||
followed by a \href{https://www.git-scm.com/docs/git-merge}{git-merge}).\par
 | 
			
		||||
Both hooks update the file [{\bf \nameref{updatelogcsv}}], which is interpreted
 | 
			
		||||
by the UpdateController in a second step.
 | 
			
		||||
    
 | 
			
		||||
% \chapter{Update-Tool "up\_dev\_ctrl"}
 | 
			
		||||
    \section{up\_dev\_ctrl}
 | 
			
		||||
    \label{UpdateTool}
 | 
			
		||||
 | 
			
		||||
        The update-tool is a Qt binary ("up\_dev\_ctrl") and called by the
 | 
			
		||||
        system-controller application. It is installed under
 | 
			
		||||
        \begin{center}
 | 
			
		||||
            \fbox{
 | 
			
		||||
                /opt/app/tools/atbupdate/up\_dev\_ctrl
 | 
			
		||||
            }
 | 
			
		||||
        \end{center}
 | 
			
		||||
 | 
			
		||||
        and has two responsibilities:
 | 
			
		||||
        \begin{itemize}
 | 
			
		||||
            \item Call update-script "update\_psa".
 | 
			
		||||
            \item Update the device controller firmware.
 | 
			
		||||
        \end{itemize}
 | 
			
		||||
    \subsection{Calling the update-script "update\_psa"}
 | 
			
		||||
        The update-script "update\_psa" is about executing all git-commands
 | 
			
		||||
        necessary to clone and pull a customer repository.
 | 
			
		||||
 | 
			
		||||
    \newpage
 | 
			
		||||
 | 
			
		||||
% \chapter{Update-Script "update\_psa"}
 | 
			
		||||
    \section{update\_psa}
 | 
			
		||||
    \label{UpdateScript}
 | 
			
		||||
 | 
			
		||||
    Inside of such a
 | 
			
		||||
        repository, there are at least the following directories:
 | 
			
		||||
        \begin{itemize}
 | 
			
		||||
           \item {\bf etc} 
 | 
			
		||||
           \item {\bf etc/dc}\newline 
 | 
			
		||||
                Contains the device controller firmware as binary file.
 | 
			
		||||
           \item {\bf etc/psa\_config}\newline
 | 
			
		||||
                Contains the printer template files (JSON).
 | 
			
		||||
           \item {\bf etc/psa\_tariff}\newline
 | 
			
		||||
                Contains the tariff files (JSON).
 | 
			
		||||
           \item {\bf etc/psa\_update}\newline
 | 
			
		||||
                Contains a single file for opkg-commands.
 | 
			
		||||
        \end{itemize}
 | 
			
		||||
    \newpage
 | 
			
		||||
 | 
			
		||||
%\chapter{Annex}
 | 
			
		||||
    \section{Structure of a customer git-repository}
 | 
			
		||||
    \label{repostructure}
 | 
			
		||||
    \subsection{The post-checkout hook}
 | 
			
		||||
TODO: checkout\_history
 | 
			
		||||
    \subsection{The post-merge hook}
 | 
			
		||||
They are both located under the {\bf .githooks}-directory
 | 
			
		||||
    
 | 
			
		||||
\section{update\_log.csv}
 | 
			
		||||
\label{updatelogcsv}
 | 
			
		||||
    \begin{table}[h!]
 | 
			
		||||
        \begin{center}
 | 
			
		||||
        \caption{Initial state of update\_log.csv}
 | 
			
		||||
        \label{tab:initial_state}
 | 
			
		||||
        \begin{tabular}{llll}
 | 
			
		||||
            \textbf{Request} & \textbf{Name} & \textbf{Date} & \textbf{Status}\\
 | 
			
		||||
            \hline
 | 
			
		||||
            \multicolumn{4}{c}{}\\
 | 
			
		||||
            DOWNLOAD & /etc/dc/dc2c4.21.bin                & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print01.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print02.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print03.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print04.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print29.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print32.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            EXECUTE  & opkg update                         & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
        \end{tabular}
 | 
			
		||||
        \end{center}
 | 
			
		||||
    \end{table}    
 | 
			
		||||
 | 
			
		||||
    \begin{table}[h!]
 | 
			
		||||
        \begin{center}
 | 
			
		||||
        \caption{State of update\_log.csv after updating}
 | 
			
		||||
        \label{tab:initial_state}
 | 
			
		||||
        \begin{tabular}{llll}
 | 
			
		||||
            \textbf{Request} & \textbf{Name} & \textbf{Date} & \textbf{Status}\\
 | 
			
		||||
            \hline
 | 
			
		||||
            \multicolumn{4}{c}{}\\
 | 
			
		||||
            DONE & /etc/dc/dc2c4.21.bin                & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print01.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print02.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print03.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print04.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print29.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print32.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & opkg update                         & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
        \end{tabular}
 | 
			
		||||
        \end{center}
 | 
			
		||||
    \end{table}    
 | 
			
		||||
 | 
			
		||||
    \newpage
 | 
			
		||||
    
 | 
			
		||||
    \section{The package manager "opkg"}
 | 
			
		||||
    \label{opkg}
 | 
			
		||||
 | 
			
		||||
    \section{Known problems}
 | 
			
		||||
\end{document}
 | 
			
		||||
							
								
								
									
										434
									
								
								UpdatePTUDevCtrl/git/git_client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								UpdatePTUDevCtrl/git/git_client.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,434 @@
 | 
			
		||||
#include "git_client.h"
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GitClient::GitClient(QString const &customerNrStr,
 | 
			
		||||
                     QString const &customerRepository,
 | 
			
		||||
                     QString const &workingDirectory,
 | 
			
		||||
                     QString const &branchName,
 | 
			
		||||
                     QObject *parent)
 | 
			
		||||
  : QObject(parent)
 | 
			
		||||
  , m_worker(qobject_cast<Worker *>(parent))
 | 
			
		||||
  , m_repositoryPath(QString("https://git.mimbach49.de/GerhardHoffmann/%1.git").arg(customerNrStr))
 | 
			
		||||
  , m_customerNr(customerNrStr)
 | 
			
		||||
  , m_workingDirectory(workingDirectory)
 | 
			
		||||
  , m_branchName(branchName)
 | 
			
		||||
  , m_customerRepository(customerRepository) {
 | 
			
		||||
    if (!m_worker) {
 | 
			
		||||
        qCritical() << "ERROR CASTING PARENT TO WORKER FAILED";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitCloneCustomerRepository() {
 | 
			
		||||
    /*  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 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
 | 
			
		||||
            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("ERROR CLONE RESULT IS EMPTY");
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::copyGitConfigFromMaster() { // only allowed when called in
 | 
			
		||||
                                            // master branch (???)
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const cp = QString("cp .gitconfig .git/config");
 | 
			
		||||
        Command c("bash");
 | 
			
		||||
        if (c.execute(m_customerRepository, QStringList() << "-c" << cp)) {
 | 
			
		||||
            qInfo() << "cp .gitconfig .git/config OK";
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        qCritical() << "ERROR cp .gitconfig .git/config";
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList GitClient::gitBranchNames() {
 | 
			
		||||
    // git config --global pager.branch false
 | 
			
		||||
    QStringList bNames;
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString gitCommand("git branch -a");
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute(m_customerRepository)) {
 | 
			
		||||
            QString const result = c.getCommandResult();
 | 
			
		||||
            return result.split('\n');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return bNames;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitCheckoutBranch() {
 | 
			
		||||
    // TODO: nachsehen, ob der Branch ueberhaupt existiert
 | 
			
		||||
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        int zoneNr = Utils::read1stLineOfFile("/mnt/system_data/zone_nr");
 | 
			
		||||
        m_branchName = (zoneNr != 0)
 | 
			
		||||
            ? QString("zg1/zone%1").arg(zoneNr) : "master";
 | 
			
		||||
 | 
			
		||||
        QString gitCommand("git checkout ");
 | 
			
		||||
        gitCommand += m_branchName;
 | 
			
		||||
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        return c.execute(m_customerRepository); // execute command in customerRepo
 | 
			
		||||
    }
 | 
			
		||||
    Utils::printCriticalErrorMsg(QString("ERROR ") + m_customerRepository + " DOES NOT EXIST");
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitCloneAndCheckoutBranch() {
 | 
			
		||||
    qInfo() << "CLONE" << m_repositoryPath << "AND CHECKOUT" << m_branchName;
 | 
			
		||||
    if (gitCloneCustomerRepository()) {
 | 
			
		||||
        //if (copyGitConfigFromMaster()) {
 | 
			
		||||
            if (gitCheckoutBranch()) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else {
 | 
			
		||||
                // TODO
 | 
			
		||||
            }
 | 
			
		||||
        //}
 | 
			
		||||
    }
 | 
			
		||||
    Utils::printCriticalErrorMsg(QString("CLONE ") + m_repositoryPath + " AND CHECKOUT FAILED");
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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: 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=");
 | 
			
		||||
            int const m = s.indexOf("m=");
 | 
			
		||||
            int const d = s.indexOf("d=");
 | 
			
		||||
 | 
			
		||||
            QString msg = IsmasClient::getReasonForLastSendVersion();
 | 
			
		||||
            QString commit{""}, date{""};
 | 
			
		||||
 | 
			
		||||
            if (c != -1) {
 | 
			
		||||
                int start = c + 2;
 | 
			
		||||
                if (m >= start) {
 | 
			
		||||
                    int length = m - start;
 | 
			
		||||
                    commit = s.mid(start, length).trimmed();
 | 
			
		||||
 | 
			
		||||
                    start = m + 2;
 | 
			
		||||
                    if (d >= start) {
 | 
			
		||||
                        length = d - start;
 | 
			
		||||
                        msg += " (";
 | 
			
		||||
                        msg = s.mid(start, length).trimmed();
 | 
			
		||||
                        msg += ")";
 | 
			
		||||
 | 
			
		||||
                        start = d + 2;
 | 
			
		||||
                        date = s.mid(start);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!commit.isEmpty() && !msg.isEmpty() && !date.isEmpty()) {
 | 
			
		||||
                    lst << commit << msg << date;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << "CUSTOMER_REPOSITORY" << m_customerRepository
 | 
			
		||||
                    << "DOES NOT EXIST";
 | 
			
		||||
    }
 | 
			
		||||
    return lst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Zu beachten: wird eine datei neu hinzugefuegt (git add/commit) dann aber gleich
 | 
			
		||||
 wieder geloscht, so wird sie im diff nicht angezeigt.
 | 
			
		||||
 */
 | 
			
		||||
std::optional<QStringList> GitClient::gitDiff(QString const &commits) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        // 409f198..6c22726
 | 
			
		||||
        QString gitCommand("git diff --compact-summary ");
 | 
			
		||||
        gitCommand += commits;
 | 
			
		||||
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute(m_customerRepository)) { // execute command in local customerRepo
 | 
			
		||||
            QString s = c.getCommandResult().trimmed();
 | 
			
		||||
            Utils::printInfoMsg("GIT DIFF RESULT " + s);
 | 
			
		||||
 | 
			
		||||
            QStringList lines = Update::split(s, '\n');
 | 
			
		||||
            QStringList fileNames;
 | 
			
		||||
            // each line has the format "etc/psa_config/DC2C_print01.json | 1 +
 | 
			
		||||
            // or the format            "etc/psa_config/DC2C_print01.json (new) | 1 +
 | 
			
		||||
            // the filenames are relativ to the repository
 | 
			
		||||
            for (int i = 0; i < lines.size(); ++i) {
 | 
			
		||||
                QString const &line = lines.at(i);
 | 
			
		||||
                int newIndex = line.indexOf("(new");    // for new files
 | 
			
		||||
                int goneIndex = line.indexOf("(gone");  // for removed files
 | 
			
		||||
                int modeIndex = line.indexOf("(mode");
 | 
			
		||||
                int pipeIndex = line.indexOf('|');
 | 
			
		||||
                if (newIndex != -1) {
 | 
			
		||||
                    QString file = line.left(newIndex).trimmed();
 | 
			
		||||
                    qInfo() << "FILE (NEW)" << file;
 | 
			
		||||
                    fileNames << file;
 | 
			
		||||
                } else
 | 
			
		||||
                if (modeIndex != -1) {
 | 
			
		||||
                    QString const file = line.left(modeIndex).trimmed();
 | 
			
		||||
                    qInfo() << "FILE (MODE)" << file;
 | 
			
		||||
                    fileNames << file;
 | 
			
		||||
                } else
 | 
			
		||||
                if (goneIndex != -1) {
 | 
			
		||||
                    QString const file = line.left(goneIndex).trimmed();
 | 
			
		||||
                    qCritical() << "FILE (GONE)" << file;
 | 
			
		||||
                } else
 | 
			
		||||
                if (pipeIndex != -1) {
 | 
			
		||||
                    QString const file = line.left(pipeIndex).trimmed();
 | 
			
		||||
                    qInfo() << "FILE (PIPE)" << file;
 | 
			
		||||
                    fileNames << file;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!fileNames.isEmpty()) {
 | 
			
		||||
                return fileNames;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    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::gitPull() {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        qInfo() << "BRANCH NAME" << m_branchName;
 | 
			
		||||
 | 
			
		||||
        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()) {
 | 
			
		||||
                    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 {
 | 
			
		||||
                                    QStringList lst("no regex-match for commits");
 | 
			
		||||
                                    worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        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 {
 | 
			
		||||
                    QStringList lst(QString("WRONG FORMAT FOR RESULT OF 'GIT PULL' ") + s);
 | 
			
		||||
                    worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                QStringList lst("EMPTY RESULT FOR 'GIT PULL'");
 | 
			
		||||
                worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        QStringList lst(QString("REPOSITORY ") + m_customerRepository + " DOES NOT EXIST");
 | 
			
		||||
        worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QStringList> GitClient::gitMerge() {
 | 
			
		||||
    Command c("git merge");
 | 
			
		||||
    if (c.execute(m_workingDirectory)) {
 | 
			
		||||
        QString s = c.getCommandResult();
 | 
			
		||||
        QStringList lst = Update::split(s, '\n');
 | 
			
		||||
        return lst;
 | 
			
		||||
    }
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString GitClient::gitLastCommit(QString fileName) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const filePath
 | 
			
		||||
            = QDir::cleanPath(m_customerRepository + QDir::separator() + fileName);
 | 
			
		||||
        if (QFile(filePath).exists()) {
 | 
			
		||||
            QString const gitCommand = QString("git log %1 | head -n 1").arg(fileName);
 | 
			
		||||
            Command c("bash");
 | 
			
		||||
            if (c.execute(m_customerRepository, QStringList() << "-c" << gitCommand)) {
 | 
			
		||||
                QString const r = c.getCommandResult();
 | 
			
		||||
                int const idx = r.indexOf("commit ");
 | 
			
		||||
                if (idx != -1) {
 | 
			
		||||
                    return r.mid(idx + 8).trimmed();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fileName has to an absolute path
 | 
			
		||||
QString GitClient::gitBlob(QString fileName) {
 | 
			
		||||
    QFileInfo fi(fileName);
 | 
			
		||||
    if (fi.exists()) {
 | 
			
		||||
        QString const gitCommand = QString("git hash-object %1").arg(fileName);
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute("/tmp")) {
 | 
			
		||||
            return c.getCommandResult().trimmed();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "N/A";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString GitClient::gitCommitForBlob(QString blob) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const gitCommand
 | 
			
		||||
            = QString("git whatchanged --all --find-object=%1 | head -n 1").arg(blob);
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute(m_customerRepository)) {
 | 
			
		||||
            return c.getCommandResult();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitIsFileTracked(QString fName) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const gitCommand
 | 
			
		||||
            = QString("git ls-files --error-unmatch %1").arg(fName);
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        return c.execute(m_customerRepository);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//get_commit_for_blob () {
 | 
			
		||||
//    # search for the blob in all commits for the file(name) $1
 | 
			
		||||
//    echo $(git log --all --pretty=format:%H -- $2   |
 | 
			
		||||
//           xargs -I{} bash -c "git ls-tree {} -- $2 |
 | 
			
		||||
//           grep -q $1 && echo -n {} && head -n 1")
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										62
									
								
								UpdatePTUDevCtrl/git/git_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								UpdatePTUDevCtrl/git/git_client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
#ifndef GIT_CLIENT_H_INCLUDED
 | 
			
		||||
#define GIT_CLIENT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
#include "process/command.h"
 | 
			
		||||
#include "ismas/ismas_client.h"
 | 
			
		||||
 | 
			
		||||
class Worker;
 | 
			
		||||
class GitClient : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    Worker *m_worker;
 | 
			
		||||
    QString const m_repositoryPath;
 | 
			
		||||
    QString const m_customerNr;
 | 
			
		||||
    QString const m_workingDirectory;
 | 
			
		||||
    QString m_branchName;
 | 
			
		||||
    QString const m_customerRepository;
 | 
			
		||||
 | 
			
		||||
    bool copyGitConfigFromMaster();
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit GitClient(QString const &customerNrStr,
 | 
			
		||||
                       QString const &repositoryPath,
 | 
			
		||||
                       QString const &workingDirectory = QCoreApplication::applicationDirPath(),
 | 
			
		||||
                       QString const &branchName = "master",
 | 
			
		||||
                       QObject *parent = 0);
 | 
			
		||||
 | 
			
		||||
    bool gitCloneCustomerRepository();
 | 
			
		||||
    bool gitCheckoutBranch();
 | 
			
		||||
    QStringList gitBranchNames();
 | 
			
		||||
 | 
			
		||||
    QString const workingDirectory() const { return m_workingDirectory; }
 | 
			
		||||
    QString workingDirectory() { return m_workingDirectory; }
 | 
			
		||||
 | 
			
		||||
    QString const branchName() const { return m_branchName; }
 | 
			
		||||
    QString branchName() { return m_branchName; }
 | 
			
		||||
 | 
			
		||||
    QString repositoryPath() { return m_repositoryPath; }
 | 
			
		||||
    QString const repositoryPath() const { return m_repositoryPath; }
 | 
			
		||||
 | 
			
		||||
    bool gitCloneAndCheckoutBranch();
 | 
			
		||||
 | 
			
		||||
    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(QString branchName);
 | 
			
		||||
    static QString gitBlob(QString fileName);
 | 
			
		||||
    QString gitCommitForBlob(QString blob);
 | 
			
		||||
    bool gitIsFileTracked(QString file2name);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // GIT_CLIENT_H_INCLUDED
 | 
			
		||||
							
								
								
									
										2492
									
								
								UpdatePTUDevCtrl/interfaces.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2492
									
								
								UpdatePTUDevCtrl/interfaces.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1088
									
								
								UpdatePTUDevCtrl/ismas/ismas_client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1088
									
								
								UpdatePTUDevCtrl/ismas/ismas_client.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										272
									
								
								UpdatePTUDevCtrl/ismas/ismas_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								UpdatePTUDevCtrl/ismas/ismas_client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,272 @@
 | 
			
		||||
#ifndef ISMAS_CLIENT_H_INCLUDED
 | 
			
		||||
#define ISMAS_CLIENT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
struct PSAInstalled {
 | 
			
		||||
    struct VersionInfo {
 | 
			
		||||
        QString created;
 | 
			
		||||
        QString reason;
 | 
			
		||||
        QString lastCommit;
 | 
			
		||||
    } versionInfo;
 | 
			
		||||
 | 
			
		||||
    struct Tariff {
 | 
			
		||||
        // VersionInfo versionInfo;
 | 
			
		||||
        QString name;
 | 
			
		||||
        QString version;
 | 
			
		||||
        QString project;
 | 
			
		||||
        int zone;
 | 
			
		||||
        int size;
 | 
			
		||||
        QString blob;
 | 
			
		||||
        QString lastCommit;
 | 
			
		||||
        QString info;
 | 
			
		||||
        QString loadTime;
 | 
			
		||||
    } tariff;
 | 
			
		||||
 | 
			
		||||
    struct HardWare {
 | 
			
		||||
        QString linuxVersion;
 | 
			
		||||
        QString cpuSerial;
 | 
			
		||||
    } hw;
 | 
			
		||||
 | 
			
		||||
    struct Opkg {
 | 
			
		||||
        // VersionInfo versionInfo;
 | 
			
		||||
        int size;
 | 
			
		||||
        QString blob;
 | 
			
		||||
        QString lastCommit;
 | 
			
		||||
        QString loadTime;
 | 
			
		||||
    } opkg;
 | 
			
		||||
 | 
			
		||||
    struct DC {
 | 
			
		||||
        // VersionInfo versionInfo;
 | 
			
		||||
        QString versionHW;
 | 
			
		||||
        QString versionSW;
 | 
			
		||||
        QString gitBlob;
 | 
			
		||||
        QString gitLastCommit;
 | 
			
		||||
        int size;
 | 
			
		||||
    } dc;
 | 
			
		||||
 | 
			
		||||
    struct SoftWare {
 | 
			
		||||
        QString apismVersion;
 | 
			
		||||
        QString atbQTVersion;
 | 
			
		||||
        QString atbUpdateToolVersion;
 | 
			
		||||
    } sw;
 | 
			
		||||
 | 
			
		||||
    struct PluginVersion {
 | 
			
		||||
        QString deviceController;
 | 
			
		||||
        QString ingenicoISelfCC;
 | 
			
		||||
        QString mobilisisCalculatePrice;
 | 
			
		||||
        QString mobilisisCalculatePriceConfigUi;
 | 
			
		||||
        QString prmCalculatePrice;
 | 
			
		||||
        QString prmCalculatePriceConfigUi;
 | 
			
		||||
        QString tcpZVT;
 | 
			
		||||
    } pluginVersion;
 | 
			
		||||
 | 
			
		||||
    struct DC2C {
 | 
			
		||||
        // VersionInfo versionInfo;
 | 
			
		||||
        QString name;
 | 
			
		||||
        QString blob;
 | 
			
		||||
        int size;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    DC2C cash;
 | 
			
		||||
    DC2C conf;
 | 
			
		||||
    DC2C device;
 | 
			
		||||
 | 
			
		||||
    DC2C print[32];
 | 
			
		||||
 | 
			
		||||
    explicit PSAInstalled() {
 | 
			
		||||
        tariff.name = "N/A";
 | 
			
		||||
        tariff.version = "N/A";
 | 
			
		||||
        tariff.project = "N/A";
 | 
			
		||||
        tariff.zone = -1;
 | 
			
		||||
        tariff.size = -1;
 | 
			
		||||
        tariff.blob = "N/A";
 | 
			
		||||
        tariff.info = "N/A";
 | 
			
		||||
        tariff.loadTime = "N/A";
 | 
			
		||||
 | 
			
		||||
        hw.linuxVersion = "N/A";
 | 
			
		||||
        hw.cpuSerial = "N/A";
 | 
			
		||||
 | 
			
		||||
        opkg.size = -1;
 | 
			
		||||
        opkg.blob = "N/A";
 | 
			
		||||
        opkg.lastCommit = "N/A";
 | 
			
		||||
        opkg.loadTime = "N/A";
 | 
			
		||||
 | 
			
		||||
        dc.versionHW = "N/A";
 | 
			
		||||
        dc.versionSW = "N/A";
 | 
			
		||||
        dc.gitBlob = "N/A";
 | 
			
		||||
        dc.gitLastCommit = "N/A";
 | 
			
		||||
        dc.size = -1;
 | 
			
		||||
 | 
			
		||||
        sw.apismVersion = "N/A";
 | 
			
		||||
        sw.atbQTVersion = "N/A";
 | 
			
		||||
        sw.atbUpdateToolVersion = "N/A";
 | 
			
		||||
 | 
			
		||||
        pluginVersion.deviceController = "N/A";
 | 
			
		||||
        pluginVersion.ingenicoISelfCC = "N/A";
 | 
			
		||||
        pluginVersion.mobilisisCalculatePrice = "N/A";
 | 
			
		||||
        pluginVersion.mobilisisCalculatePriceConfigUi = "N/A";
 | 
			
		||||
        pluginVersion.prmCalculatePrice = "N/A";
 | 
			
		||||
        pluginVersion.prmCalculatePriceConfigUi = "N/A";
 | 
			
		||||
        pluginVersion.tcpZVT = "N/A";
 | 
			
		||||
 | 
			
		||||
        cash.name = "N/A";
 | 
			
		||||
        cash.blob = "N/A";
 | 
			
		||||
        cash.size = -1;
 | 
			
		||||
 | 
			
		||||
        conf.name = "N/A";
 | 
			
		||||
        conf.blob = "N/A";
 | 
			
		||||
        conf.size = -1;
 | 
			
		||||
 | 
			
		||||
        device.size = -1;
 | 
			
		||||
        device.blob = "N/A";
 | 
			
		||||
        device.size = -1;
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i < 32; ++i) {
 | 
			
		||||
            print[i].size = -1;
 | 
			
		||||
            print[i].blob = "N/A";
 | 
			
		||||
            print[i].size = -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IsmasClient : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    int m_progressInPercent;
 | 
			
		||||
public:
 | 
			
		||||
    explicit IsmasClient() : m_progressInPercent(1) {}
 | 
			
		||||
 | 
			
		||||
    enum APISM {
 | 
			
		||||
        DB_PORT = 7777,
 | 
			
		||||
        DIRECT_PORT = 7778
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    enum RESULT_CODE {
 | 
			
		||||
        SUCCESS=0,
 | 
			
		||||
        NO_UPDATE_NECESSARY=1,
 | 
			
		||||
        BACKUP_FAILED=2,
 | 
			
		||||
        WRONG_PACKAGE=3,
 | 
			
		||||
        INSTALL_ERROR=4};
 | 
			
		||||
 | 
			
		||||
    enum REASON {
 | 
			
		||||
        TIME_TRIGGERED = 0,
 | 
			
		||||
        SERVICE,
 | 
			
		||||
        DEV_TEST,
 | 
			
		||||
        ENTRIES
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static char const *reason[REASON::ENTRIES];
 | 
			
		||||
 | 
			
		||||
    static std::optional<QString>
 | 
			
		||||
        sendRequestReceiveResponse(int port, QString const &request);
 | 
			
		||||
 | 
			
		||||
    static QString getReasonForLastSendVersion();
 | 
			
		||||
 | 
			
		||||
    int getProgressInPercent() const {return m_progressInPercent; }
 | 
			
		||||
    void setProgressInPercent(int procent) { m_progressInPercent = procent; }
 | 
			
		||||
 | 
			
		||||
    QString updateNewsToIsmas(char const *event,
 | 
			
		||||
                              int percent,
 | 
			
		||||
                              int resultCode,
 | 
			
		||||
                              char const *step,
 | 
			
		||||
                              char const *step_result,
 | 
			
		||||
                              char const *version);
 | 
			
		||||
 | 
			
		||||
    QString updateOfPSAStarted(QString const &version = QString());   // start of update process
 | 
			
		||||
    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(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());
 | 
			
		||||
    QString gitFetch(QString const &info, QString const &version = QString());
 | 
			
		||||
    QString execOpkgCommand(QString const &info, QString const &version = QString());
 | 
			
		||||
    QString rsyncFile(QString const &info, QString const &version = QString());
 | 
			
		||||
    QString errorGitFetch(int resultCode, QString const &info, QString const &version = QString());
 | 
			
		||||
    QString updateOfPSAActivated(QString const &version = QString());
 | 
			
		||||
                                    // and update accepted
 | 
			
		||||
    QString updateOfPSASucceeded(QString const &version = QString()); // update process succeeded
 | 
			
		||||
    QString updateOfPSAContinues(QString currentStage, QString currentStageInfo, QString const &version = QString());
 | 
			
		||||
    QString updateOfPSAFailed(int resultCode, QString step, QString reason, QString const &version = QString());
 | 
			
		||||
    QString sanityCheckFailed(int resultCode, QString reason, QString const &version = QString());
 | 
			
		||||
    QString jsonParseFailed(int resultCode, QString reason, QString const &version = QString());
 | 
			
		||||
    std::optional<QString> finalResult(int resultCode, QString reason, QString const &version = QString());
 | 
			
		||||
 | 
			
		||||
    // legacy
 | 
			
		||||
    QString updateOfPSASendVersion(PSAInstalled const &psa);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    enum class UPDATE_COMPONENT {
 | 
			
		||||
        TARIFF,
 | 
			
		||||
        SOFTWARE_ATBQT,
 | 
			
		||||
        SOFTWARE_APISM,
 | 
			
		||||
        SOFTWARE_ATB_UPDATE_TOOL,
 | 
			
		||||
        CONFIG_PTU5_CPU_SERIAL,
 | 
			
		||||
        CONFIG_DEVICE_CONTROLLER,
 | 
			
		||||
        CONFIG_PRINTER,
 | 
			
		||||
        CONFIG_BNA,
 | 
			
		||||
        PLUGIN_ATB_DEVICE_CONTROLLER,
 | 
			
		||||
        PLUGIN_INGENICO_CC,
 | 
			
		||||
        PLUGIN_MOBILISIS_CALC_PRICE,
 | 
			
		||||
        PLUGIN_MOBILISIS_CALC_PRICE_UI,
 | 
			
		||||
        PLUGIN_PRM_CALC_PRICE,
 | 
			
		||||
        PLUGIN_PRM_CALC_PRICE_UI,
 | 
			
		||||
        PLUGIN_TCP_ZVT_CC,
 | 
			
		||||
        OPKG_COMMANDS,
 | 
			
		||||
        HARDWARE_DEVICES,
 | 
			
		||||
        OS,
 | 
			
		||||
        DC2C_CASH_JSON,
 | 
			
		||||
        DC2C_CONF_JSON,
 | 
			
		||||
        DC2C_DEVICE_JSON,
 | 
			
		||||
        DC2C_PRINT01_JSON,
 | 
			
		||||
        DC2C_PRINT02_JSON,
 | 
			
		||||
        DC2C_PRINT03_JSON,
 | 
			
		||||
        DC2C_PRINT04_JSON,
 | 
			
		||||
        DC2C_PRINT05_JSON,
 | 
			
		||||
        DC2C_PRINT06_JSON,
 | 
			
		||||
        DC2C_PRINT07_JSON,
 | 
			
		||||
        DC2C_PRINT08_JSON,
 | 
			
		||||
        DC2C_PRINT09_JSON,
 | 
			
		||||
        DC2C_PRINT10_JSON,
 | 
			
		||||
        DC2C_PRINT11_JSON,
 | 
			
		||||
        DC2C_PRINT12_JSON,
 | 
			
		||||
        DC2C_PRINT13_JSON,
 | 
			
		||||
        DC2C_PRINT14_JSON,
 | 
			
		||||
        DC2C_PRINT15_JSON,
 | 
			
		||||
        DC2C_PRINT16_JSON,
 | 
			
		||||
        DC2C_PRINT17_JSON,
 | 
			
		||||
        DC2C_PRINT18_JSON,
 | 
			
		||||
        DC2C_PRINT19_JSON,
 | 
			
		||||
        DC2C_PRINT20_JSON,
 | 
			
		||||
        DC2C_PRINT21_JSON,
 | 
			
		||||
        DC2C_PRINT22_JSON,
 | 
			
		||||
        DC2C_PRINT23_JSON,
 | 
			
		||||
        DC2C_PRINT24_JSON,
 | 
			
		||||
        DC2C_PRINT25_JSON,
 | 
			
		||||
        DC2C_PRINT26_JSON,
 | 
			
		||||
        DC2C_PRINT27_JSON,
 | 
			
		||||
        DC2C_PRINT28_JSON,
 | 
			
		||||
        DC2C_PRINT29_JSON,
 | 
			
		||||
        DC2C_PRINT30_JSON,
 | 
			
		||||
        DC2C_PRINT31_JSON,
 | 
			
		||||
        DC2C_PRINT32_JSON,
 | 
			
		||||
    };
 | 
			
		||||
    QString sendLastVersion(UPDATE_COMPONENT comp, PSAInstalled const &psa);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    static void printDebugMessage(int port, QString const &clientIP, int clientPort,
 | 
			
		||||
                                  QString const &message);
 | 
			
		||||
    static void printInfoMessage(int port, QString const &clientIP, int clientPort,
 | 
			
		||||
                                 QString const &message);
 | 
			
		||||
    static void printErrorMessage(int port, QString const &clientIP, int clientPort,
 | 
			
		||||
                                  QString const &message);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // ISMAS_CLIENT_H_INCLUDED
 | 
			
		||||
							
								
								
									
										163
									
								
								UpdatePTUDevCtrl/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								UpdatePTUDevCtrl/main.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#include <stdlib.h> // system()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
#include "commandline_parser.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <QSharedMemory>
 | 
			
		||||
#include <QRunnable>
 | 
			
		||||
#include <QThreadPool>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
#include <QCommandLineParser>
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
#include <QMainWindow>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "git/git_client.h"
 | 
			
		||||
#include "ismas/ismas_client.h"
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QtWidgets>
 | 
			
		||||
#include <QScopedPointer>
 | 
			
		||||
 | 
			
		||||
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
#else
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// argv[1]: file to send to dc
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QByteArray const value = qgetenv("LC_ALL");
 | 
			
		||||
    if (value != "C") {
 | 
			
		||||
        qputenv("LC_ALL", "C");
 | 
			
		||||
    }
 | 
			
		||||
    // qputenv("XDG_RUNTIME_DIR", "/var/run/user/0");
 | 
			
		||||
 | 
			
		||||
    openlog("ATB-UPDATE", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
 | 
			
		||||
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
    QApplication::setApplicationName("ATBUpdateTool");
 | 
			
		||||
    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 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 = Utils::read1stLineOfFile("/mnt/system_data/machine_nr");
 | 
			
		||||
    int const customerNr = Utils::read1stLineOfFile("/mnt/system_data/cust_nr");
 | 
			
		||||
    int const zoneNr = Utils::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() << "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;
 | 
			
		||||
    }
 | 
			
		||||
    if (showYoctoVersion) {
 | 
			
		||||
        printf("%s\n", Worker::getATBUpdateToolYoctoVersion().toStdString().c_str());
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (showYoctoInstallStatus) {
 | 
			
		||||
        printf("%s\n", Worker::getATBUpdateToolYoctoInstallationStatus().toStdString().c_str());
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    QThread::currentThread()->setObjectName("main thread");
 | 
			
		||||
    qInfo() << "Main thread" << QThread::currentThreadId();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (!QDir(plugInDir).exists()) {
 | 
			
		||||
        qCritical() << plugInDir
 | 
			
		||||
                    << "does not exists, but has to contain dc-library";
 | 
			
		||||
        exit(-1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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,
 | 
			
		||||
                  repositoryUrl,
 | 
			
		||||
                  branchName,
 | 
			
		||||
                  plugInDir,
 | 
			
		||||
                  plugInName,
 | 
			
		||||
                  workingDir,
 | 
			
		||||
                  noUpdatePsaHardware,
 | 
			
		||||
                  alwaysDownloadConfig,
 | 
			
		||||
                  alwaysDownloadDC,
 | 
			
		||||
                  dryRun);
 | 
			
		||||
 | 
			
		||||
    MainWindow mw(&worker);
 | 
			
		||||
    worker.setMainWindow(&mw);
 | 
			
		||||
 | 
			
		||||
    mw.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
 | 
			
		||||
    mw.showFullScreen();
 | 
			
		||||
 | 
			
		||||
    return a.exec();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								UpdatePTUDevCtrl/main.cpp.bck
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								UpdatePTUDevCtrl/main.cpp.bck
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
static void updateBinary(std::unique_ptr<hwinf> hw,     // update d2dc*.bin
 | 
			
		||||
                         char const *fileToSendToDC,
 | 
			
		||||
                         char const *baudrate,
 | 
			
		||||
                         char const *serialInterface) {
 | 
			
		||||
    for (int i=0; i < 1;++i) {
 | 
			
		||||
        hw->dc_updateDC(fileToSendToDC, baudrate, serialInterface);
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(3000));
 | 
			
		||||
    }
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void updatePrinterConf(std::unique_ptr<hwinf> hw, // update printer-file
 | 
			
		||||
                              char const *fileToSendToDC,
 | 
			
		||||
                              char const *baudrate,
 | 
			
		||||
                              char const *serialInterface) {
 | 
			
		||||
    for (int i=0; i < 1;++i) {
 | 
			
		||||
        hw->dc_updateDC(fileToSendToDC, baudrate, serialInterface);
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(3000));
 | 
			
		||||
    }
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
 | 
			
		||||
        atbInstallMessageHandler(atbDebugOutput);
 | 
			
		||||
        setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
        //setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (argc > 2) {
 | 
			
		||||
        qCritical() << "Usage: " << argv[0] << "<file to send to dc>";
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<hwinf> hw(new hwapi());
 | 
			
		||||
    QFileInfo fileInfo(argv[1]);
 | 
			
		||||
    QString fname(fileInfo.fileName());
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    if (fname.startsWith("dc") && fname.endsWith(".bin")) {
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
        std::thread t(updateBinary, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttymxc2");
 | 
			
		||||
#else
 | 
			
		||||
        std::thread t(updateBinary, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttyUSB0");
 | 
			
		||||
#endif
 | 
			
		||||
        ret = a.exec();
 | 
			
		||||
        t.join();
 | 
			
		||||
    } else
 | 
			
		||||
    if (fname.startsWith("DC") && fname.endsWith(".json")) {
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
        std::thread t(updatePrinterConf, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttymxc2");
 | 
			
		||||
#else
 | 
			
		||||
        std::thread t(updatePrinterConf, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttyUSB0");
 | 
			
		||||
#endif
 | 
			
		||||
        ret = a.exec();
 | 
			
		||||
        t.join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								UpdatePTUDevCtrl/main.cpp.bck2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								UpdatePTUDevCtrl/main.cpp.bck2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "interfaces.h"
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <QSharedMemory>
 | 
			
		||||
#include <QRunnable>
 | 
			
		||||
#include <QThreadPool>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
#else
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// argv[1]: file to send to dc
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
 | 
			
		||||
        atbInstallMessageHandler(atbDebugOutput);
 | 
			
		||||
        setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
        //setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QByteArray const value = qgetenv("XDG_RUNTIME_DIR");
 | 
			
		||||
    if (value.size() == 0) {
 | 
			
		||||
        qputenv("XDG_RUNTIME_DIR", "/run/user/0");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString const update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
 | 
			
		||||
    QString const workingDir = (argc == 2) ? argv[1] : ".";
 | 
			
		||||
 | 
			
		||||
    Worker worker(update_ctrl_file, workingDir);
 | 
			
		||||
 | 
			
		||||
    qCritical() << "starting main event loop";
 | 
			
		||||
    int ret = a.exec();
 | 
			
		||||
    qCritical() << "stopping main event loop" << ret;
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								UpdatePTUDevCtrl/main.cpp.bck3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								UpdatePTUDevCtrl/main.cpp.bck3
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <QSharedMemory>
 | 
			
		||||
#include <QRunnable>
 | 
			
		||||
#include <QThreadPool>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
#else
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void doWork(QString update_ctrl_file, QString workingDir) {
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 | 
			
		||||
    Update update(update_ctrl_file, workingDir);
 | 
			
		||||
    update.doUpdate();
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// argv[1]: file to send to dc
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
 | 
			
		||||
        atbInstallMessageHandler(atbDebugOutput);
 | 
			
		||||
        setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
        //setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QByteArray const value = qgetenv("XDG_RUNTIME_DIR");
 | 
			
		||||
    if (value.size() == 0) {
 | 
			
		||||
        qputenv("XDG_RUNTIME_DIR", "/run/user/0");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // QString const update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
 | 
			
		||||
    // QString const workingDir = (argc == 2) ? argv[1] : ".";
 | 
			
		||||
 | 
			
		||||
    // std::thread t(doWork, update_ctrl_file, workingDir);
 | 
			
		||||
 | 
			
		||||
    int ret = a.exec();
 | 
			
		||||
    // t.join();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										308
									
								
								UpdatePTUDevCtrl/mainwindow.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								UpdatePTUDevCtrl/mainwindow.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,308 @@
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
#include "ui_mainwindow.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "progress_event.h"
 | 
			
		||||
#include "update_dc_event.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QScrollBar>
 | 
			
		||||
#include <QEvent>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MainWindow::MainWindow(Worker *worker, QWidget *parent)
 | 
			
		||||
    : QMainWindow(parent)
 | 
			
		||||
    , ui(new Ui::MainWindow)
 | 
			
		||||
    , m_worker(worker)
 | 
			
		||||
    , m_width(70)
 | 
			
		||||
    , m_progressRunning(false)
 | 
			
		||||
    , m_updateStep(UpdateDcEvent::UpdateStep::NONE) {
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    ui->updateProgress->setRange(0, 100);
 | 
			
		||||
    ui->updateProgress->reset();
 | 
			
		||||
 | 
			
		||||
    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)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MainWindow::~MainWindow() {
 | 
			
		||||
    delete m_startTimer;
 | 
			
		||||
    delete m_exitTimer;
 | 
			
		||||
    delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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), "");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								UpdatePTUDevCtrl/mainwindow.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								UpdatePTUDevCtrl/mainwindow.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
#ifndef MAINWINDOW_H
 | 
			
		||||
#define MAINWINDOW_H
 | 
			
		||||
 | 
			
		||||
#include <QMainWindow>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QStatusBar>
 | 
			
		||||
 | 
			
		||||
QT_BEGIN_NAMESPACE
 | 
			
		||||
namespace Ui { class MainWindow; }
 | 
			
		||||
QT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "update_dc_event.h"
 | 
			
		||||
 | 
			
		||||
#define EMERGENCY_LEAVE_BL 0
 | 
			
		||||
 | 
			
		||||
class hwinf;
 | 
			
		||||
class MainWindow : public QMainWindow {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void customEvent(QEvent *event) override;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    MainWindow(Worker *worker, QWidget *parent = nullptr);
 | 
			
		||||
    ~MainWindow();
 | 
			
		||||
 | 
			
		||||
    static const int START_PROGRESS_LOOP = -1;
 | 
			
		||||
    static const int STOP_PROGRESS_LOOP = -2;
 | 
			
		||||
    static const int BL_START_COUNT = 5;
 | 
			
		||||
    static const int BL_CHECK_COUNT = 5;
 | 
			
		||||
    static const int BL_IS_UP_COUNT = 5;
 | 
			
		||||
    static const int BL_STOP_COUNT = 5;
 | 
			
		||||
 | 
			
		||||
    UpdateDcEvent::UpdateStep updateStep() const { return m_updateStep; }
 | 
			
		||||
    void setUpdateStep(UpdateDcEvent::UpdateStep updateStep) { m_updateStep = updateStep; }
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
#if EMERGENCY_LEAVE_BL==1
 | 
			
		||||
    void emergencyLeaveBL();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
 | 
			
		||||
#if EMERGENCY_LEAVE_BL==1
 | 
			
		||||
    void leaveBL();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void onQuit();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void scrollDownTextEdit();
 | 
			
		||||
    void onShowMessage(QString, QString);
 | 
			
		||||
 | 
			
		||||
    Ui::MainWindow *ui;
 | 
			
		||||
    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
 | 
			
		||||
							
								
								
									
										75
									
								
								UpdatePTUDevCtrl/mainwindow.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								UpdatePTUDevCtrl/mainwindow.ui
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
<?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="3" column="2">
 | 
			
		||||
      <widget class="QPushButton" name="exit">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Exit</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item row="3" column="1">
 | 
			
		||||
      <widget class="QProgressBar" name="updateProgress">
 | 
			
		||||
       <property name="value">
 | 
			
		||||
        <number>1</number>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item row="0" column="0" rowspan="3" colspan="3">
 | 
			
		||||
      <widget class="QTextEdit" name="updateStatus">
 | 
			
		||||
       <property name="enabled">
 | 
			
		||||
        <bool>true</bool>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="font">
 | 
			
		||||
        <font>
 | 
			
		||||
         <family>Misc Fixed</family>
 | 
			
		||||
         <pointsize>11</pointsize>
 | 
			
		||||
         <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>
 | 
			
		||||
							
								
								
									
										97
									
								
								UpdatePTUDevCtrl/message_handler.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										97
									
								
								UpdatePTUDevCtrl/message_handler.cpp
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QMessageLogContext>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static char const *DBG_NAME[] = { "DBG  ", "WARN ", "CRIT ", "FATAL", "INFO " };
 | 
			
		||||
static bool installedMsgHandler = false;
 | 
			
		||||
static int debugLevel = LOG_NOTICE;
 | 
			
		||||
 | 
			
		||||
int getDebugLevel() { return debugLevel; }
 | 
			
		||||
void setDebugLevel(int newDebugLevel) {
 | 
			
		||||
    debugLevel = newDebugLevel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool messageHandlerInstalled() {
 | 
			
		||||
    return installedMsgHandler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) {
 | 
			
		||||
    installedMsgHandler = (handler != 0);
 | 
			
		||||
    static QtMessageHandler prevHandler = nullptr;
 | 
			
		||||
    if (handler) {
 | 
			
		||||
        prevHandler = qInstallMessageHandler(handler);
 | 
			
		||||
        return prevHandler;
 | 
			
		||||
    } else {
 | 
			
		||||
        return qInstallMessageHandler(prevHandler);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
/// \brief Print message according to given debug level.
 | 
			
		||||
///
 | 
			
		||||
/// \note Install this function using qInstallMsgHandler().
 | 
			
		||||
///
 | 
			
		||||
///  int main(int argc, char **argv) {
 | 
			
		||||
///     installMsgHandler(atbDebugOutput);
 | 
			
		||||
///     QApplication app(argc, argv);
 | 
			
		||||
///     ...
 | 
			
		||||
///     return app.exec();
 | 
			
		||||
///  }
 | 
			
		||||
///
 | 
			
		||||
#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
 | 
			
		||||
void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
 | 
			
		||||
    Q_UNUSED(context);
 | 
			
		||||
    QString const localMsg = QString(DBG_NAME[type]) + msg.toLocal8Bit();
 | 
			
		||||
 | 
			
		||||
    switch (debugLevel) {
 | 
			
		||||
        case LOG_DEBUG: { // debug-level message
 | 
			
		||||
            syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_INFO: { // informational message
 | 
			
		||||
            if (type != QtDebugMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_NOTICE: { // normal, but significant, condition
 | 
			
		||||
            if (type != QtDebugMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_WARNING: { // warning conditions
 | 
			
		||||
            if (type != QtInfoMsg && type != QtDebugMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_ERR: { // error conditions
 | 
			
		||||
            if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_CRIT: { // critical conditions
 | 
			
		||||
            if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_ALERT: { // action must be taken immediately
 | 
			
		||||
            if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case LOG_EMERG: { // system is unusable
 | 
			
		||||
            if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
 | 
			
		||||
                syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        default: {
 | 
			
		||||
            //fprintf(stderr, "%s No ErrorLevel defined! %s\n",
 | 
			
		||||
            //    datetime.toStdString().c_str(), msg.toStdString().c_str());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								UpdatePTUDevCtrl/message_handler.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										23
									
								
								UpdatePTUDevCtrl/message_handler.h
									
									
									
									
									
										Executable 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
 | 
			
		||||
							
								
								
									
										2492
									
								
								UpdatePTUDevCtrl/plugins/interfaces.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2492
									
								
								UpdatePTUDevCtrl/plugins/interfaces.h
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/plugins/libCAmaster.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/plugins/libCAmaster.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/plugins/libCAslave.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								UpdatePTUDevCtrl/plugins/libCAslave.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										124
									
								
								UpdatePTUDevCtrl/process/command.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								UpdatePTUDevCtrl/process/command.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
#include "command.h"
 | 
			
		||||
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
 | 
			
		||||
Command::Command(QString const &command, int start_timeout, int finish_timeout)
 | 
			
		||||
    : m_command(command.trimmed())
 | 
			
		||||
    , m_commandResult("")
 | 
			
		||||
    , m_waitForStartTimeout(start_timeout)
 | 
			
		||||
    , m_waitForFinishTimeout(finish_timeout)
 | 
			
		||||
    , m_exitCode(-1) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Command::getCommandResult() const {
 | 
			
		||||
    return m_commandResult;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Command::readyReadStandardOutput() {
 | 
			
		||||
    QProcess *p = (QProcess *)sender();
 | 
			
		||||
    m_commandResult += p->readAllStandardOutput();
 | 
			
		||||
    // qCritical() << m_commandResult;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Command::readyReadStandardError() {
 | 
			
		||||
    QProcess *p = (QProcess *)sender();
 | 
			
		||||
    QByteArray buf = p->readAllStandardError();
 | 
			
		||||
    qCritical() << buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Command::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
 | 
			
		||||
    QProcess *p = (QProcess *)sender();
 | 
			
		||||
    // read all remaining data sent to the process, just in case
 | 
			
		||||
    QString d = p->readAllStandardOutput();
 | 
			
		||||
    if (!d.isEmpty()) {
 | 
			
		||||
        m_commandResult += d;
 | 
			
		||||
    }
 | 
			
		||||
    disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardOutput()));
 | 
			
		||||
    disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardError()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Command::execute(QString workingDirectory, QStringList args) {
 | 
			
		||||
 | 
			
		||||
    if (!QDir::setCurrent(workingDirectory)) {
 | 
			
		||||
        qCritical() << "SET WORKING_DIRECTORY" << workingDirectory
 | 
			
		||||
                    << "FAILED FOR" << m_command;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QScopedPointer<QProcess> p(new QProcess(this));
 | 
			
		||||
    p->setWorkingDirectory(workingDirectory);
 | 
			
		||||
    p->setProcessChannelMode(QProcess::MergedChannels);
 | 
			
		||||
 | 
			
		||||
    connect(&(*p), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
 | 
			
		||||
    connect(&(*p), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
 | 
			
		||||
 | 
			
		||||
    if (!args.isEmpty()) {
 | 
			
		||||
        qDebug() << "START COMMAND" << m_command << "WITH ARGS" << args
 | 
			
		||||
                 << "IN" << p->workingDirectory();
 | 
			
		||||
        p->start(m_command, args);
 | 
			
		||||
    } else {
 | 
			
		||||
        qDebug() << "START COMMAND" << m_command
 | 
			
		||||
                 << "IN" << p->workingDirectory();
 | 
			
		||||
        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();
 | 
			
		||||
            // 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 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								UpdatePTUDevCtrl/process/command.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								UpdatePTUDevCtrl/process/command.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#ifndef COMMAND_H_INCLUDED
 | 
			
		||||
#define COMMAND_H_INCLUDED
 | 
			
		||||
#endif // COMMAND_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Command : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    QString m_command;
 | 
			
		||||
    QString m_commandResult;
 | 
			
		||||
    int m_waitForStartTimeout;
 | 
			
		||||
    int m_waitForFinishTimeout;
 | 
			
		||||
    int m_exitCode;
 | 
			
		||||
public:
 | 
			
		||||
    explicit Command(QString const &command,
 | 
			
		||||
                     int start_timeout = 100000,
 | 
			
		||||
                     int finish_timeout = 100000);
 | 
			
		||||
 | 
			
		||||
    QString getCommandResult() const;
 | 
			
		||||
    QString command() const { return m_command; }
 | 
			
		||||
 | 
			
		||||
    bool execute(QString workingDirectory, QStringList args = QStringList());
 | 
			
		||||
    int exitCode() const { return m_exitCode; }
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void readyReadStandardOutput();
 | 
			
		||||
    void readyReadStandardError();
 | 
			
		||||
    void finished(int exitCode, QProcess::ExitStatus exitStatus);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										20
									
								
								UpdatePTUDevCtrl/progress_event.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								UpdatePTUDevCtrl/progress_event.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
#include "progress_event.h"
 | 
			
		||||
 | 
			
		||||
QEvent::Type ProgressEvent::customEventType = QEvent::None;
 | 
			
		||||
 | 
			
		||||
ProgressEvent::ProgressEvent(QObject const *sender, int progressPercent)
 | 
			
		||||
    : QEvent(ProgressEvent::type())
 | 
			
		||||
    , m_sender(sender)
 | 
			
		||||
    , m_progressPercent(progressPercent) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ProgressEvent::~ProgressEvent() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QEvent::Type ProgressEvent::type() {
 | 
			
		||||
    if (customEventType == QEvent::None) {
 | 
			
		||||
        int generatedType = QEvent::registerEventType();
 | 
			
		||||
        customEventType = static_cast<QEvent::Type>(generatedType);
 | 
			
		||||
    }
 | 
			
		||||
    return customEventType;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								UpdatePTUDevCtrl/progress_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								UpdatePTUDevCtrl/progress_event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
#ifndef PROGRESS_EVENT_H_INCLUDED
 | 
			
		||||
#define PROGRESS_EVENT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QEvent>
 | 
			
		||||
 | 
			
		||||
class ProgressEvent : public QEvent {
 | 
			
		||||
 | 
			
		||||
    QObject const *m_sender;
 | 
			
		||||
    int m_progressPercent;
 | 
			
		||||
public:
 | 
			
		||||
    explicit ProgressEvent(QObject const *sender, int progressPercent);
 | 
			
		||||
    virtual ~ProgressEvent();
 | 
			
		||||
    static QEvent::Type type();
 | 
			
		||||
 | 
			
		||||
    QObject const *sender() { return m_sender; }
 | 
			
		||||
    QObject const *sender() const { return m_sender; }
 | 
			
		||||
 | 
			
		||||
    void setProgress(int progressPercent) { m_progressPercent = progressPercent; }
 | 
			
		||||
    int progressPercent() { return m_progressPercent; }
 | 
			
		||||
    int progressPercent() const { return m_progressPercent; }
 | 
			
		||||
private:
 | 
			
		||||
    static QEvent::Type customEventType;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PROGRESS_EVENT_H_INCLUDED
 | 
			
		||||
							
								
								
									
										709
									
								
								UpdatePTUDevCtrl/update.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										709
									
								
								UpdatePTUDevCtrl/update.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,709 @@
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "update_dc_event.h"
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QTemporaryFile>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
#include <QRegExp>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
 | 
			
		||||
#include "unistd.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "plugins/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();
 | 
			
		||||
                exit(-1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
 | 
			
		||||
            qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
 | 
			
		||||
 | 
			
		||||
            if (!pluginLoader.isLoaded()) {
 | 
			
		||||
                qCritical() << pluginLoader.errorString();
 | 
			
		||||
                exit(-2);
 | 
			
		||||
            }
 | 
			
		||||
            QObject *plugin = pluginLoader.instance();
 | 
			
		||||
            if (!plugin) {
 | 
			
		||||
                qCritical() << "cannot start instance";
 | 
			
		||||
                exit(-3);
 | 
			
		||||
            }
 | 
			
		||||
            if (! (hw = qobject_cast<hwinf *>(plugin))) {
 | 
			
		||||
                qCritical() << "cannot cast plugin" << plugin << "to hwinf";
 | 
			
		||||
                exit(-4);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            qCritical() << pluginLibName << "does not exist";
 | 
			
		||||
            exit(-5);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << "plugins directory" << plugInDir.absolutePath()
 | 
			
		||||
                    << "does not exist";
 | 
			
		||||
        exit(-6);
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::Update(Worker *worker,
 | 
			
		||||
               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_worker(worker)
 | 
			
		||||
    , 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) {
 | 
			
		||||
 | 
			
		||||
    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() << __PRETTY_FUNCTION__ << "m_sys_areDCDataValid ..." << m_sys_areDCdataValid;
 | 
			
		||||
 | 
			
		||||
    //qInfo() << "UPDATE: m_serialInterface    ..." << m_serialInterface;
 | 
			
		||||
    //qInfo() << "UPDATE: m_baudrate           ..." << m_baudrate;
 | 
			
		||||
    //qInfo() << "UPDATE: m_customerRepository ..." << m_customerRepository;
 | 
			
		||||
    //qInfo() << "UPDATE: m_customerNr ..........." << m_customerNrStr;
 | 
			
		||||
    //qInfo() << "UPDATE: m_branchName ..........." << m_branchName;
 | 
			
		||||
    //qInfo() << "UPDATE: m_pluginName ..........." << m_pluginName;
 | 
			
		||||
    //qInfo() << "UPDATE: m_workingDirectory ....." << m_workingDir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::~Update() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// br is a index into a table, used for historical reasons.
 | 
			
		||||
bool Update::openSerial(int br, QString baudrate, QString comPort) const {
 | 
			
		||||
    qDebug() << "opening serial" << br << baudrate << comPort << "...";
 | 
			
		||||
    if (m_hw->dc_openSerial(br, baudrate, comPort, 1) == true) { // 1 for connect
 | 
			
		||||
        Utils::printInfoMsg(
 | 
			
		||||
            QString("OPENING SERIAL %1").arg(br)
 | 
			
		||||
                  + " " + baudrate + " " + comPort + "...OK");
 | 
			
		||||
 | 
			
		||||
        // m_hw->dc_autoRequest(true);
 | 
			
		||||
        m_hw->dc_autoRequest(false);
 | 
			
		||||
        QThread::sleep(1);
 | 
			
		||||
 | 
			
		||||
        Utils::printInfoMsg(QString("IS PORT OPEN %1").arg(m_hw->dc_isPortOpen()));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Utils::printCriticalErrorMsg(
 | 
			
		||||
        QString("OPENING SERIAL %1").arg(br)
 | 
			
		||||
              + " " + baudrate + " " + comPort + "...FAILED");
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Update::closeSerial() const {
 | 
			
		||||
    qInfo() << "CLOSED SERIAL" << m_baudrate << m_serialInterface;
 | 
			
		||||
    m_hw->dc_closeSerial();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::isSerialOpen() const {
 | 
			
		||||
    return m_hw->dc_isPortOpen();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
 ///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 //
 | 
			
		||||
 //                        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.
 | 
			
		||||
 */
 | 
			
		||||
bool Update::updateBinary(QString const &fileToSendToDC) {
 | 
			
		||||
    qInfo() << "UPDATING DEVICE CONTROLLER FIRMWARE BINARY" << fileToSendToDC;
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    QFile fn(fileToSendToDC);
 | 
			
		||||
    if (!fn.exists()) {
 | 
			
		||||
        // output via CONSOLE() etc
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool bl_isUp = false;
 | 
			
		||||
    if (m_hw->bl_completeStart()) {
 | 
			
		||||
        int cnt = 5;
 | 
			
		||||
        while (--cnt > 0) {
 | 
			
		||||
            if (m_hw->bl_isUp()) {
 | 
			
		||||
                bl_isUp = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!bl_isUp) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!m_hw->bl_storeFirmware(fileToSendToDC)) {
 | 
			
		||||
        m_hw->bl_stopBL();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint16_t const nrOfFirmwareBlocks = m_hw->bl_getNrOfFirmwareBlocks();
 | 
			
		||||
 | 
			
		||||
    for (uint16_t blockNr = 0; blockNr <= nrOfFirmwareBlocks; ++blockNr) {
 | 
			
		||||
        m_hw->bl_blockAutoLoad(blockNr);
 | 
			
		||||
 | 
			
		||||
        int sleepTime = 0;
 | 
			
		||||
        while (1) {
 | 
			
		||||
            if (sleepTime > 1500) {
 | 
			
		||||
                m_hw->bl_stopBL();
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int8_t const r = m_hw->bl_blockAutoResponse();
 | 
			
		||||
 | 
			
		||||
            // after every "bl_blockAutoLoad()" call this until response
 | 
			
		||||
            // retval  0: wait   1: OK, blk was sent    2: OK, transfer complete
 | 
			
		||||
            //         3: error despite repeating, cancel. probably bin file corrupted
 | 
			
		||||
            //      Max duration: 3x no response from BL = 900ms
 | 
			
		||||
 | 
			
		||||
            switch(r) {
 | 
			
		||||
            case 1:
 | 
			
		||||
            /* fall through */
 | 
			
		||||
            case 2:
 | 
			
		||||
                sleepTime = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case 0: {
 | 
			
		||||
                QThread::msleep(100);
 | 
			
		||||
                sleepTime += 100;
 | 
			
		||||
            } break;
 | 
			
		||||
            case 3:
 | 
			
		||||
                m_hw->bl_stopBL();
 | 
			
		||||
                return false;
 | 
			
		||||
            default:
 | 
			
		||||
                m_hw->bl_stopBL();
 | 
			
		||||
                return false; // unknown error code
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_hw->bl_stopBL();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Update::jsonType(enum FileTypeJson type) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case FileTypeJson::CASH: return "CASH";
 | 
			
		||||
    case FileTypeJson::CONFIG: return "CONFIG";
 | 
			
		||||
    case FileTypeJson::PRINTER: return "PRINTER";
 | 
			
		||||
    case FileTypeJson::SERIAL: return "SERIAL";
 | 
			
		||||
    case FileTypeJson::DEVICE: return "DEVICE";
 | 
			
		||||
    case FileTypeJson::TIME: return "TIME";
 | 
			
		||||
    }
 | 
			
		||||
    return "N/A";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::downloadJson(enum FileTypeJson type,
 | 
			
		||||
                          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
 | 
			
		||||
 | 
			
		||||
    bool ready = false;
 | 
			
		||||
    int nTry = 25;
 | 
			
		||||
    while ((ready = m_hw->sys_ready4sending()) == false) {
 | 
			
		||||
        QThread::msleep(200);
 | 
			
		||||
        if (--nTry <= 0) {
 | 
			
		||||
            Utils::printCriticalErrorMsg("SYS NOT READY FOR SENDING AFTER 5 SECONDS");
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool ret = false;
 | 
			
		||||
    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() <= 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 {
 | 
			
		||||
                    Utils::printCriticalErrorMsg(
 | 
			
		||||
                        QString("SIZE OF %1 TOO BIG (%2 BYTES)")
 | 
			
		||||
                            .arg(jsFileToSendToDC).arg(fi.size()));
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                Utils::printCriticalErrorMsg(
 | 
			
		||||
                    QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING");
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            Utils::printCriticalErrorMsg(
 | 
			
		||||
                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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList Update::split(QString line, QChar sep) {
 | 
			
		||||
    QStringList lst;
 | 
			
		||||
    QString next;
 | 
			
		||||
    int start = 0, end;
 | 
			
		||||
 | 
			
		||||
    while ((end = line.indexOf(sep, start)) != -1) {
 | 
			
		||||
        next = line.mid(start, end - start).trimmed();
 | 
			
		||||
        lst << next;
 | 
			
		||||
        start = end + 1;
 | 
			
		||||
    }
 | 
			
		||||
    next = line.mid(start, end - start).trimmed();
 | 
			
		||||
    lst << next;
 | 
			
		||||
 | 
			
		||||
    return lst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Update::readyReadStandardOutput() {
 | 
			
		||||
    QProcess *p = (QProcess *)sender();
 | 
			
		||||
    QByteArray buf = p->readAllStandardOutput();
 | 
			
		||||
    qCritical() << buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Update::readyReadStandardError() {
 | 
			
		||||
    QProcess *p = (QProcess *)sender();
 | 
			
		||||
    QByteArray buf = p->readAllStandardError();
 | 
			
		||||
    qCritical() << buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Update::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
 | 
			
		||||
    QProcess *p = (QProcess *)sender();
 | 
			
		||||
    disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardOutput()));
 | 
			
		||||
    disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardError()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList Update::getDcSoftAndHardWareVersion() {
 | 
			
		||||
    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
 | 
			
		||||
                                // current SW/HW-versions
 | 
			
		||||
        m_hw->request_DC2_SWversion();
 | 
			
		||||
        m_hw->request_DC2_HWversion();
 | 
			
		||||
        QThread::sleep(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString const &hwVersion = m_hw->dc_getHWversion().toLower().trimmed();
 | 
			
		||||
    QString const &swVersion = m_hw->dc_getSWversion().toLower().trimmed();
 | 
			
		||||
 | 
			
		||||
    m_hw->dc_autoRequest(false);
 | 
			
		||||
    QThread::sleep(1); // make sure the timer-slots are inactive
 | 
			
		||||
 | 
			
		||||
    if (!hwVersion.isEmpty() && !swVersion.isEmpty()) {
 | 
			
		||||
        return QStringList() << hwVersion << swVersion;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return QStringList() << "DC HW-version not available"
 | 
			
		||||
                         << "DC SW-version not available";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Update::getFileVersion(QString const& jsonFileName) {
 | 
			
		||||
    // "version":"15.10.2023 14:55 02.00.06",
 | 
			
		||||
    static const QRegularExpression re("^.*(\\\"version\\\":)(.*)$");
 | 
			
		||||
 | 
			
		||||
    QString fileVersion;
 | 
			
		||||
    QFile inputFile(jsonFileName);
 | 
			
		||||
    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) {
 | 
			
		||||
              fileVersion = match.captured(match.lastCapturedIndex());
 | 
			
		||||
              break;
 | 
			
		||||
          }
 | 
			
		||||
       }
 | 
			
		||||
       inputFile.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return fileVersion;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::checkDownloadedJsonVersions(QStringList const& jsonFileNames) {
 | 
			
		||||
 | 
			
		||||
    for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
 | 
			
		||||
 | 
			
		||||
        uint8_t jsonNr = 0;
 | 
			
		||||
        QFileInfo fInfo(jsonFileNames[i]);
 | 
			
		||||
 | 
			
		||||
        if (fInfo.fileName().endsWith("conf.json")) {
 | 
			
		||||
            jsonNr = 1;
 | 
			
		||||
        } else
 | 
			
		||||
        if (fInfo.fileName().endsWith("device.json")) {
 | 
			
		||||
            jsonNr = 2;
 | 
			
		||||
        } else
 | 
			
		||||
        if (fInfo.fileName().endsWith("cash.json")) {
 | 
			
		||||
            jsonNr = 3;
 | 
			
		||||
        } else {
 | 
			
		||||
            QRegularExpressionMatch match;
 | 
			
		||||
            static const QRegularExpression re("^(.*print)([0-3][0-9])\\.json\\s*$");
 | 
			
		||||
            int idx = fInfo.fileName().indexOf(re, 0, &match);
 | 
			
		||||
            if (idx != -1) {
 | 
			
		||||
                QString captured = match.captured(match.lastCapturedIndex());
 | 
			
		||||
                bool ok = false;
 | 
			
		||||
                int n = captured.toInt(&ok);
 | 
			
		||||
                if (ok) {
 | 
			
		||||
                    jsonNr = n + 4;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (jsonNr != 0) {
 | 
			
		||||
#if 0
 | 
			
		||||
            m_hw->sys_requestJsonVersions(jsonNr);
 | 
			
		||||
            QThread::msleep(500);
 | 
			
		||||
 | 
			
		||||
            char buf[64];
 | 
			
		||||
            memset(buf, 0x00, sizeof(buf));
 | 
			
		||||
            m_hw->sys_getJsonVersions(jsonNr, buf);
 | 
			
		||||
            buf[sizeof(buf)-1] = '\0';
 | 
			
		||||
 | 
			
		||||
            QString const installedVersion(buf);
 | 
			
		||||
            QString const fileVersion = getFileVersion(jsonFileNames[i]);
 | 
			
		||||
 | 
			
		||||
            qCritical() << "installed version:" << installedVersion;
 | 
			
		||||
            qCritical() << "     file version:" << fileVersion;
 | 
			
		||||
 | 
			
		||||
            if (installedVersion == fileVersion) {
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            qCritical() << "CANNOT FIND JSON-NR FOR" << jsonFileNames[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
 | 
			
		||||
    if (m_sys_areDCdataValid == false) {
 | 
			
		||||
        qCritical() << "ERROR!!! DC DATA NOT VALID -> CA-MASTER-PLUGIN NOT CONNECTED";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool res = false;
 | 
			
		||||
    QList<QString>::const_iterator it;
 | 
			
		||||
    for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) {
 | 
			
		||||
        m_worker->startProgressLoop();
 | 
			
		||||
 | 
			
		||||
        QString const &fToWorkOn = QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
 | 
			
		||||
 | 
			
		||||
        if (fToWorkOn.contains("dc2c.bin")) {
 | 
			
		||||
            bool updateBinaryRes = true;
 | 
			
		||||
 | 
			
		||||
            // CONSOLE()
 | 
			
		||||
 | 
			
		||||
            // 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
 | 
			
		||||
 | 
			
		||||
            // if ((updateBinaryRes = updateBinary(fToWorkOn)) == true) {
 | 
			
		||||
            //
 | 
			
		||||
                // qCritical() << "downloaded binary" << fToWorkOn;
 | 
			
		||||
 | 
			
		||||
            //    ++displayIndex;
 | 
			
		||||
            //    emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(2, ' ') + QString(")")
 | 
			
		||||
            //        + QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
 | 
			
		||||
            //        Worker::UPDATE_STEP_DONE);
 | 
			
		||||
            //}
 | 
			
		||||
 | 
			
		||||
            m_hw->dc_autoRequest(true); // turn auto-request setting on
 | 
			
		||||
 | 
			
		||||
            // qInfo() << "SET AUTO-REQUEST=TRUE";
 | 
			
		||||
 | 
			
		||||
            QStringList const &versions = Update::getDcSoftAndHardWareVersion();
 | 
			
		||||
            if (versions.size() >= 2) {
 | 
			
		||||
                if (updateBinaryRes == true) {
 | 
			
		||||
                    qInfo() << "dc-hardware-version (UPDATED)" << versions[0];
 | 
			
		||||
                    qInfo() << "dc-firmware-version (UPDATED)" << versions[1];
 | 
			
		||||
                } else {
 | 
			
		||||
                    qInfo() << "dc-hardware-version (NOT UPDATED)" << versions[0];
 | 
			
		||||
                    qInfo() << "dc-firmware-version (NOT UPDATED)" << versions[1];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            res = updateBinaryRes;
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            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))) {
 | 
			
		||||
                        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(3, ' ') + QString(")")
 | 
			
		||||
                              + QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
 | 
			
		||||
                                Worker::UPDATE_STEP_DONE);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
 | 
			
		||||
                    && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
 | 
			
		||||
                res = true;
 | 
			
		||||
                if ((res = updateCashConf(fToWorkOn))) {
 | 
			
		||||
                    Utils::printInfoMsg(QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn));
 | 
			
		||||
                    ++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)
 | 
			
		||||
                    && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
 | 
			
		||||
                res = true;
 | 
			
		||||
                if ((res= updateConfig(fToWorkOn))) {
 | 
			
		||||
                    Utils::printInfoMsg(QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn));
 | 
			
		||||
                    ++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)
 | 
			
		||||
                    && fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
 | 
			
		||||
                res = true;
 | 
			
		||||
                if ((res = updateDeviceConf(fToWorkOn))) {
 | 
			
		||||
                    Utils::printInfoMsg(QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn));
 | 
			
		||||
                    ++displayIndex;
 | 
			
		||||
                    emit m_worker->appendText(QString("\n(") + QString("%1").arg(displayIndex).rightJustified(3, ' ') + QString(")")
 | 
			
		||||
                          + QString(" Update ") + QFileInfo(fToWorkOn).fileName(),
 | 
			
		||||
                            Worker::UPDATE_STEP_DONE);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn;
 | 
			
		||||
                res = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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";
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										99
									
								
								UpdatePTUDevCtrl/update.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								UpdatePTUDevCtrl/update.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
#ifndef UPDATE_H_INCLUDED
 | 
			
		||||
#define UPDATE_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
#include <QPluginLoader>
 | 
			
		||||
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
#else
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class Worker;
 | 
			
		||||
class Update : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    hwinf *m_hw = nullptr;
 | 
			
		||||
    Worker *m_worker = 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(Worker *worker,
 | 
			
		||||
                    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(int &displayIndex, QStringList const &linesToWorkOn);
 | 
			
		||||
    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 updatePrinterTemplate(int templateIdx, QString fname) const;
 | 
			
		||||
    bool updateBinary(QString const &fileToSendToDC);
 | 
			
		||||
    bool updateConfig(QString jsFileToSendToDC);
 | 
			
		||||
    bool updateCashConf(QString jsFileToSendToDC);
 | 
			
		||||
    bool updateDeviceConf(QString jsFileToSendToDC);
 | 
			
		||||
    bool downloadJson(enum FileTypeJson type, int templateIdx,
 | 
			
		||||
                      QString jsFileToSendToDC) const;
 | 
			
		||||
    QStringList getDcSoftAndHardWareVersion();
 | 
			
		||||
    QString getFileVersion(QString const& jsonFile);
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void readyReadStandardOutput();
 | 
			
		||||
    void readyReadStandardError();
 | 
			
		||||
    void finished(int exitCode, QProcess::ExitStatus exitStatus);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
#endif // UPDATE_H_INCLUDED
 | 
			
		||||
							
								
								
									
										25
									
								
								UpdatePTUDevCtrl/update_dc_event.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								UpdatePTUDevCtrl/update_dc_event.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
#include "update_dc_event.h"
 | 
			
		||||
 | 
			
		||||
QEvent::Type UpdateDcEvent::customEventType = QEvent::None;
 | 
			
		||||
 | 
			
		||||
UpdateDcEvent::UpdateDcEvent(QObject const *sender,
 | 
			
		||||
                             UpdateStep updateStep,
 | 
			
		||||
                             int count,
 | 
			
		||||
                             QDateTime const &sendDateTime)
 | 
			
		||||
    : QEvent(UpdateDcEvent::type())
 | 
			
		||||
    , m_sender(sender)
 | 
			
		||||
    , m_updateStep(updateStep)
 | 
			
		||||
    , m_count(count)
 | 
			
		||||
    , m_sendDateTime(sendDateTime) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UpdateDcEvent::~UpdateDcEvent() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QEvent::Type UpdateDcEvent::type() {
 | 
			
		||||
    if (customEventType == QEvent::None) {
 | 
			
		||||
        int generatedType = QEvent::registerEventType();
 | 
			
		||||
        customEventType = static_cast<QEvent::Type>(generatedType);
 | 
			
		||||
    }
 | 
			
		||||
    return customEventType;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								UpdatePTUDevCtrl/update_dc_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								UpdatePTUDevCtrl/update_dc_event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
#ifndef UPDATE_DC_EVENT_H_INCLUDED
 | 
			
		||||
#define UPDATE_DC_EVENT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QEvent>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
 | 
			
		||||
class UpdateDcEvent : public QEvent {
 | 
			
		||||
public:
 | 
			
		||||
    enum UpdateStep { NONE, DC_REBOOT, BL_START, BL_CHECK, BL_CHECK_AFTER_STOP, BL_IS_UP, BL_IS_DOWN, BL_STOP};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QObject const *m_sender;
 | 
			
		||||
    UpdateStep m_updateStep;
 | 
			
		||||
    int m_count;
 | 
			
		||||
    QDateTime m_sendDateTime;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit UpdateDcEvent(QObject const *sender, UpdateStep updateStep,
 | 
			
		||||
                           int count,
 | 
			
		||||
                           QDateTime const &sendDateTime = QDateTime::currentDateTime());
 | 
			
		||||
    virtual ~UpdateDcEvent();
 | 
			
		||||
    static QEvent::Type type();
 | 
			
		||||
 | 
			
		||||
    QObject const *sender() { return m_sender; }
 | 
			
		||||
    QObject const *sender() const { return m_sender; }
 | 
			
		||||
 | 
			
		||||
    void setUpdateStep(UpdateStep updateStep) { m_updateStep = updateStep; }
 | 
			
		||||
    UpdateStep updateStep() { return m_updateStep; }
 | 
			
		||||
    UpdateStep updateStep() const { return m_updateStep; }
 | 
			
		||||
    int count() const { return m_count; }
 | 
			
		||||
    void setCount(int count) { m_count = count; }
 | 
			
		||||
    QDateTime &sendDateTime() { return m_sendDateTime; }
 | 
			
		||||
    QDateTime const &sendDateTime() const { return m_sendDateTime; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static QEvent::Type customEventType;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // PROGRESS_EVENT_H_INCLUDED
 | 
			
		||||
							
								
								
									
										380
									
								
								UpdatePTUDevCtrl/utils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								UpdatePTUDevCtrl/utils.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,380 @@
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "git/git_client.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
 | 
			
		||||
#include "unistd.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QDirIterator>
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
 | 
			
		||||
int Utils::read1stLineOfFile(QString fileName) {
 | 
			
		||||
    QFile f(fileName);
 | 
			
		||||
    if (f.exists()) {
 | 
			
		||||
        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
			
		||||
            QTextStream in(&f);
 | 
			
		||||
            in.setCodec("UTF-8");
 | 
			
		||||
            while(!in.atEnd()) {
 | 
			
		||||
                return in.readLine().toInt();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::getLocation(QString fileName) {
 | 
			
		||||
    QString location("N/A");
 | 
			
		||||
    QFile f(fileName);
 | 
			
		||||
    if (f.exists()) {
 | 
			
		||||
        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
			
		||||
            QTextStream in(&f);
 | 
			
		||||
            in.setCodec("UTF-8");
 | 
			
		||||
            while(!in.atEnd()) {
 | 
			
		||||
                QString const &line = in.readLine();
 | 
			
		||||
                if (line.indexOf("Project", Qt::CaseInsensitive) != -1) {
 | 
			
		||||
                    int const c = line.indexOf(":");
 | 
			
		||||
                    if (c != -1) {
 | 
			
		||||
                        location = line.mid(c+1);
 | 
			
		||||
                        if (!location.isEmpty()) {
 | 
			
		||||
                            return location.replace(QChar('"'), QString("")).trimmed();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return location;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::getTariffVersion(QString fileName) {
 | 
			
		||||
    QString version("N/A");
 | 
			
		||||
    QFile f(fileName);
 | 
			
		||||
    if (f.exists()) {
 | 
			
		||||
        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
			
		||||
            QTextStream in(&f);
 | 
			
		||||
            in.setCodec("UTF-8");
 | 
			
		||||
            while(!in.atEnd()) {
 | 
			
		||||
                QString const &line = in.readLine();
 | 
			
		||||
                if (line.indexOf("Version", Qt::CaseInsensitive) != -1) {
 | 
			
		||||
                    int const c = line.indexOf(":");
 | 
			
		||||
                    if (c != -1) {
 | 
			
		||||
                        version = line.mid(c+1);
 | 
			
		||||
                        if (!version.isEmpty()) {
 | 
			
		||||
                            return version.replace(QChar('"'), QString("")).trimmed();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::getTariffInfo(QString fileName) {
 | 
			
		||||
    QString info("N/A");
 | 
			
		||||
    QFile f(fileName);
 | 
			
		||||
    if (f.exists()) {
 | 
			
		||||
        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
			
		||||
            QTextStream in(&f);
 | 
			
		||||
            in.setCodec("UTF-8");
 | 
			
		||||
            while(!in.atEnd()) {
 | 
			
		||||
                QString const &line = in.readLine();
 | 
			
		||||
                if (line.indexOf("Info", Qt::CaseInsensitive) != -1) {
 | 
			
		||||
                    int const c = line.indexOf(":");
 | 
			
		||||
                    if (c != -1) {
 | 
			
		||||
                        info = line.mid(c+1);
 | 
			
		||||
                        if (!info.isEmpty()) {
 | 
			
		||||
                            return info.replace(QChar('"'), QString("")).trimmed();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return info;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::zoneName(quint8 i) {
 | 
			
		||||
    static constexpr char const *zName[] = {
 | 
			
		||||
        "",
 | 
			
		||||
        "purple",
 | 
			
		||||
        "blue",
 | 
			
		||||
        "yellow",
 | 
			
		||||
        "green",
 | 
			
		||||
        "yellow (mars)",
 | 
			
		||||
        "green (mars)"
 | 
			
		||||
    };
 | 
			
		||||
    if (i < (sizeof(zName)/sizeof(char const *))) {
 | 
			
		||||
        return zName[i];
 | 
			
		||||
    }
 | 
			
		||||
    return "N/A";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Utils::printCriticalErrorMsg(QString const &errorMsg, bool upper, bool lower) {
 | 
			
		||||
    if (upper) qCritical() << QString(80, 'E');
 | 
			
		||||
 | 
			
		||||
    qCritical() << errorMsg;
 | 
			
		||||
 | 
			
		||||
    if (lower) qCritical() << QString(80, 'E');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    if (getDebugLevel() == LOG_DEBUG) {
 | 
			
		||||
        for (int i=0; i<lines.size(); ++i) {
 | 
			
		||||
            qInfo() << lines.at(i);
 | 
			
		||||
        } qInfo() << ""; qInfo() << "";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::getTariffLoadTime(QString fileName) {
 | 
			
		||||
    QFileInfo fInfo(fileName);
 | 
			
		||||
    if (fInfo.exists()) {
 | 
			
		||||
        QDateTime lastModifiedTime = fInfo.lastModified();
 | 
			
		||||
        if (lastModifiedTime.isValid()) {
 | 
			
		||||
            return lastModifiedTime.toString(Qt::ISODateWithMs);
 | 
			
		||||
        } else {
 | 
			
		||||
            printCriticalErrorMsg(fileName + " HAS INVALID MODIFIED-TIME");
 | 
			
		||||
            QDateTime birthTime = fInfo.birthTime();
 | 
			
		||||
            if (birthTime.isValid()) {
 | 
			
		||||
                return birthTime.toString(Qt::ISODateWithMs);
 | 
			
		||||
            } else {
 | 
			
		||||
                printCriticalErrorMsg(fileName + " HAS INVALID BIRTH-TIME");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        printCriticalErrorMsg(fileName + " DOES NOT EXIST");
 | 
			
		||||
    }
 | 
			
		||||
    return "N/A";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::rstrip(QString const &str) {
 | 
			
		||||
    int n = str.size() - 1;
 | 
			
		||||
    for (; n >= 0; --n) {
 | 
			
		||||
        if (!str.at(n).isSpace()) {
 | 
			
		||||
            return str.left(n + 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Utils::sameFilesInDirs(QDir const &dir1, QDir const &dir2,
 | 
			
		||||
                            QStringList const &nameFilters) {
 | 
			
		||||
    if (!dir1.exists()) {
 | 
			
		||||
        printCriticalErrorMsg(dir1.dirName() + " DOES NOT EXIST");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (!dir2.exists()) {
 | 
			
		||||
        printCriticalErrorMsg(dir2.dirName() + " DOES NOT EXIST");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (dir1.absolutePath() == dir2.absolutePath()) {
 | 
			
		||||
        printCriticalErrorMsg(dir1.dirName() + " AND "+ dir2.dirName() + " HAVE SAME PATH");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // files, sorted by name
 | 
			
		||||
    QFileInfoList const &lst1 = dir1.entryInfoList(nameFilters, QDir::Files, QDir::Name);
 | 
			
		||||
    QFileInfoList const &lst2 = dir2.entryInfoList(nameFilters, QDir::Files, QDir::Name);
 | 
			
		||||
 | 
			
		||||
    QStringList fileNameLst1{};
 | 
			
		||||
    QStringList fileNameLst2{};
 | 
			
		||||
    QListIterator<QFileInfo> i1(lst1);
 | 
			
		||||
    while (i1.hasNext()) {
 | 
			
		||||
        fileNameLst1 << i1.next().fileName();
 | 
			
		||||
    }
 | 
			
		||||
    QListIterator<QFileInfo> i2(lst2);
 | 
			
		||||
    while (i2.hasNext()) {
 | 
			
		||||
        fileNameLst2 << i2.next().fileName();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fileNameLst1.isEmpty()) {
 | 
			
		||||
        qCritical() << "DIR1" << dir1.dirName() << " DOES NOT CONTAIN EXPECTED FILES";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (fileNameLst2.isEmpty())  {
 | 
			
		||||
        qCritical() << "DIR1" << dir2.dirName() << " DOES NOT CONTAIN EXPECTED FILES";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (fileNameLst1 != fileNameLst2) {
 | 
			
		||||
        printCriticalErrorMsg(dir1.dirName() + " AND " + dir2.dirName()
 | 
			
		||||
                            + " DIFFER: [" + fileNameLst1.join(',') + "],["
 | 
			
		||||
                            + fileNameLst2.join(',') + "]");
 | 
			
		||||
        return false;
 | 
			
		||||
    } else {
 | 
			
		||||
        printInfoMsg(dir1.dirName() + " AND " + dir2.dirName()
 | 
			
		||||
                    + " ARE EQUAL: [" + fileNameLst1.join(',') + "]");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QStringList gitBlobLst1{};
 | 
			
		||||
    QStringList gitBlobLst2{};
 | 
			
		||||
    QListIterator<QFileInfo> i3(lst1);
 | 
			
		||||
    while (i3.hasNext()) {
 | 
			
		||||
        gitBlobLst1 << GitClient::gitBlob(i3.next().fileName());
 | 
			
		||||
    }
 | 
			
		||||
    QListIterator<QFileInfo> i4(lst2);
 | 
			
		||||
    while (i4.hasNext()) {
 | 
			
		||||
        gitBlobLst2 << GitClient::gitBlob(i4.next().fileName());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (gitBlobLst1.isEmpty()) {
 | 
			
		||||
        qCritical() << "DIR1" << dir1.dirName() << " DOES NOT CONTAIN EXPECTED FILES";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (gitBlobLst2.isEmpty())  {
 | 
			
		||||
        qCritical() << "DIR1" << dir2.dirName() << " DOES NOT CONTAIN EXPECTED FILES";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (gitBlobLst1 != gitBlobLst2) {
 | 
			
		||||
        printCriticalErrorMsg(dir1.dirName() + " AND " + dir2.dirName()
 | 
			
		||||
                            + " DIFFER: [" + gitBlobLst1.join(',') + "],["
 | 
			
		||||
                            + gitBlobLst2.join(',') + "]");
 | 
			
		||||
        return false;
 | 
			
		||||
    } else {
 | 
			
		||||
        printInfoMsg(dir1.dirName() + " AND " + dir2.dirName()
 | 
			
		||||
                    + " CONTAIN SAME GIT-BLOBS FOR FILES: [" + fileNameLst1.join(',') + "]");
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QString Utils::getParentName() { // get name of parent process
 | 
			
		||||
    QString ppid = QString("/proc/%1/status").arg(getppid());
 | 
			
		||||
    std::ifstream f(ppid.toStdString().c_str());
 | 
			
		||||
    if (f.is_open()) {
 | 
			
		||||
        std::string next;
 | 
			
		||||
        while (std::getline(f, next)) {
 | 
			
		||||
            QString line = QString(next.c_str()).simplified();
 | 
			
		||||
            if (line.startsWith("Name")) {
 | 
			
		||||
                int const idx = line.indexOf(QChar(':'));
 | 
			
		||||
                if (idx != -1) {
 | 
			
		||||
                    return line.mid(idx+1).trimmed();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Utils::isATBQTRunning() {
 | 
			
		||||
    QDirIterator it("/proc",
 | 
			
		||||
                    QStringList() << "status",
 | 
			
		||||
                    QDir::Files,
 | 
			
		||||
                    QDirIterator::Subdirectories);
 | 
			
		||||
    while (it.hasNext()) {
 | 
			
		||||
        QString const &nextStatusFile = it.next();
 | 
			
		||||
        static const QRegularExpression re("^/proc/[0-9]{1,}/status");
 | 
			
		||||
        QRegularExpressionMatch match = re.match(nextStatusFile);
 | 
			
		||||
        if (match.hasMatch()) {
 | 
			
		||||
            std::ifstream f(nextStatusFile.toStdString().c_str());
 | 
			
		||||
            if (f.is_open()) {
 | 
			
		||||
                std::string next;
 | 
			
		||||
                while (std::getline(f, next)) {
 | 
			
		||||
                    QString line = QString(next.c_str()).simplified();
 | 
			
		||||
                    if (line.startsWith("Name")) {
 | 
			
		||||
                        int const idx = line.indexOf(QChar(':'));
 | 
			
		||||
                        if (idx != -1) {
 | 
			
		||||
                            QString const binary = line.mid(idx+1).trimmed();
 | 
			
		||||
                            if (binary == "ATBQT") {
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								UpdatePTUDevCtrl/utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								UpdatePTUDevCtrl/utils.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#ifndef UTILS_H_INCLUDED
 | 
			
		||||
#define UTILS_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
namespace Utils {
 | 
			
		||||
    int read1stLineOfFile(QString fileName);
 | 
			
		||||
    QString getLocation(QString fileName);
 | 
			
		||||
    QString getTariffVersion(QString fileName);
 | 
			
		||||
    QString getTariffInfo(QString fileName);
 | 
			
		||||
    QString zoneName(quint8 i);
 | 
			
		||||
    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);
 | 
			
		||||
    bool sameFilesInDirs(QDir const &dir1, QDir const &dir2,
 | 
			
		||||
                         QStringList const &nameFilters = {"*.json"});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    QString getParentName();
 | 
			
		||||
    bool isATBQTRunning();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // UTILS_H_INCLUDED
 | 
			
		||||
							
								
								
									
										1257
									
								
								UpdatePTUDevCtrl/worker.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1257
									
								
								UpdatePTUDevCtrl/worker.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1446
									
								
								UpdatePTUDevCtrl/worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1446
									
								
								UpdatePTUDevCtrl/worker.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								UpdatePTUDevCtrl/worker_thread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								UpdatePTUDevCtrl/worker_thread.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
 | 
			
		||||
WorkerThread::WorkerThread(QString const &name,
 | 
			
		||||
                           QObject *parent) : QThread(parent) {
 | 
			
		||||
    this->setObjectName(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WorkerThread::~WorkerThread() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//void WorkerThread::run() {
 | 
			
		||||
//
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										17
									
								
								UpdatePTUDevCtrl/worker_thread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								UpdatePTUDevCtrl/worker_thread.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#ifndef WORKER_THREAD_H_INCLUDED
 | 
			
		||||
#define WORKER_THREAD_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
class WorkerThread : public QThread {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    WorkerThread(QString const &name, QObject *parent = nullptr);
 | 
			
		||||
    virtual ~WorkerThread();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    // virtual void run();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // WORKER_THREAD_H_INCLUDED
 | 
			
		||||
		Reference in New Issue
	
	Block a user