394 Commits

Author SHA1 Message Date
4b3a39b0e6 Set version to 1.3.14.
Add compile flag -C (so it is possible to use /*fall through*/ without
having the proprocessor to remove this comment.
2023-10-30 15:35:38 +01:00
a44b780d93 Minor: Add header for using RAII in sending SEND-LAST-VERSION to ISAMS. 2023-10-30 15:29:23 +01:00
19dfae9b56 Use output functions ISMAS(), GUI() and CONSOLE(), which point to friend
operators<< in Worker-class.
2023-10-30 15:28:25 +01:00
bef0d4fe12 Refactor the update process: streamline code. When WAIT button is not
active, the a clone or a fix of a defunct repository is possible, but
not more.
If WAIT button is active, the at least the opkg_commnds are executed. If
there are chenged files, they are handkled as wll.
2023-10-30 15:25:49 +01:00
72a2fc781c Minor: reove obsolete m_returnCode. 2023-10-30 15:24:33 +01:00
fc264689b1 Use and implement getAPISMYoctoVersion() and
getAPISMYoctoInstallationSTatus().
2023-10-30 15:22:59 +01:00
fc587456d5 Filling the QMap Worker:smap with data. 2023-10-30 15:21:26 +01:00
a2b933ab71 Minor: Added UPDATE_STEP_WRONG. 2023-10-30 15:20:15 +01:00
7d0fdf4d6d Small fixes:
1: fixed wrong parameters of a connect().
2: Minor: improved onQuit().
2023-10-30 15:17:59 +01:00
c2ce44c79b Adding three friend operator<< functions to output status information of
the update process: the first on outputs to CONSOLE(), the second one
outputs to ISMAS() and the last one to GUI(), i.e. the text edit of the
main window.
2023-10-30 15:15:30 +01:00
16a9556863 bool customerEnvironment();
bool filesToUpdate();
bool updateFiles();
bool syncCustomerRepositoryAndFS();
bool saveLogFile(): remove progress parameter.
2023-10-30 15:14:19 +01:00
48896f97ec Adding UPDATE_STEP_WRONG: helper variable to be used in text edit of
main window.
2023-10-30 15:13:04 +01:00
4486317cb2 dd declaration for getAPISMYoctoVersion() and
getAPISMYoctoInstallationStatus(): the first one returning the
yocto-version
of APIS, the second returning the installation status of APIS as display
in 'opkg info'.
2023-10-30 15:11:06 +01:00
6b9b88ea19 Adding member variables to check if customer repository was a fresh
clone, or if it was already existent.
2023-10-30 15:09:33 +01:00
99a99d95a1 Adding UPDATE_STEP enum plus associated interger defines.
Adding QMap: Worker::smap, which contains names of UPDATE_STEP-members.
2023-10-30 15:07:28 +01:00
d4ddbbee21 Add class UpdateProcessRunning: use for sending SEND-LAST-VERSION as
part of its destruktor: RAII-pattern.
2023-10-30 15:05:30 +01:00
34e5189945 comment out some debug output -> too much output. 2023-10-30 15:03:35 +01:00
c44c805238 Use some special output methods using ISMAS(), GUI() nad CONSOLE(). 2023-10-30 15:00:57 +01:00
196f1a730e gitPull(): don't use regex anumore, but just plain
string-matching/searching.
Regex seems to be quite error-prone.
2023-10-30 14:59:58 +01:00
7dc04c4422 Add helper function worker(), returning the worker-object. 2023-10-30 14:56:19 +01:00
5efac2619b sicherung der aenderungen 2023-10-23 16:16:11 +02:00
9b0f741b9b to be continued on monday 2023-10-22 19:44:45 +02:00
81c5f8ee7e Save for the weekend. 2023-10-20 13:55:18 +02:00
29e6a25e72 Add comment for version 1.3.13 2023-10-19 13:45:52 +02:00
5abc057bda Minor: add possible debug messages. 2023-10-19 13:44:51 +02:00
8aeb7ecfea Don't check opkg_commands-file in the system-filesystem to remove
confusing error-messages.
2023-10-19 13:43:53 +02:00
4bb8e241b6 Update process: check sanity of customer repository: are etc/ and
opt/directories contained? If not, remove the repository and clone it
again. This is done without checking the ISMAS-WAIT-button.
2023-10-19 13:41:44 +02:00
4469a23f9c Implemented helpers:
bool isRepositoryCorrupted();
    bool repairCorruptedRepository();

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

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

and static variables

    static constexpr const int CLONE_AND_CHECKOUT_SUCCESS = 0;
    static constexpr const int CLONE_AND_CHECKOUT_FAILURE = -3;
    static constexpr const int ISMAS_TRIGGER_FAILURE = -5;
2023-10-19 13:38:16 +02:00
6865056f4b Replace regex in gitCloneCustomerRepository() with straight-forward
steing-handling: regex sometimes returned error.
2023-10-19 13:35:07 +02:00
37bd5c90d3 Add printUpdateStatus() helper for QString 2023-10-19 13:34:07 +02:00
fcba120dfa Minor: commented out unnecessary debug/info output 2023-10-18 16:21:44 +02:00
1d4f50fb9f Add printing-utils that also take string-lists 2023-10-18 16:20:49 +02:00
a78040a037 Minor: add error-debug-message in ase customer-nr is wrong 2023-10-18 16:19:37 +02:00
9b175d7789 Set version to 1.3.12 2023-10-18 11:45:54 +02:00
2d7f145a25 Replaced using gitFetch() with gitPull() 2023-10-18 11:40:04 +02:00
4589c4ca76 Removed gitFetchAndDiff() and original version of gitPull(). 2023-10-18 11:38:26 +02:00
a32258a59e Replaced "git fetch" with "git pull". 2023-10-18 11:37:46 +02:00
22f25e5251 Replaced 'git clone' with 'git clone --filter=blob:none' to speed
up cloning of customer-repository.
2023-10-18 11:36:13 +02:00
258d883a51 Replaced gitFetch() with gitPull() 2023-10-18 11:35:23 +02:00
504e242d42 Implemented getATBUpdateToolYoctoVersion() and getATBUpdateToolYoctoInstallationStatus() 2023-10-18 11:31:15 +02:00
731cdcbe09 Added getATBUpdateToolYoctoVersion() and getATBUpdateToolYoctoInstallationStatus() 2023-10-18 11:30:12 +02:00
b4e2d4c54a Minor: Move reading of machine_nr, customer_nr and zone_nr upwards. 2023-10-18 11:28:06 +02:00
42961dea40 Add command-parameters yoctoVersionOption (yocto-version of
ATBUpdateTool as reported by opkg), and yoctoInstallStatusOption (info
if ATBUpdateTool is installed as reported by opkg).
2023-10-18 11:26:30 +02:00
fd2f601f67 Add printAupdateStatusMsg(). 2023-10-18 11:21:32 +02:00
b45af505cd Minor: change output format. 2023-10-18 11:21:08 +02:00
2dfe80b654 Add printUpdateStatusMsg() 2023-10-18 11:20:31 +02:00
4b9dcc5e99 Set version to 1.3.11: integrate extended version (VERSION + last git
commit) in send-last-version-message.
2023-10-12 12:13:49 +02:00
53639b55c9 Integrate call parameter -V (= --extended-version) to show extended
version (including last git commit)
2023-10-12 12:12:16 +02:00
3a83efbd3f Integrate extended version of ATBUpdateTool into send-last-version command to ISMAS. 2023-10-12 12:11:48 +02:00
c9d6a8d245 Integrate extended version of ATBUpdateTool into send-last-version 2023-10-12 12:10:24 +02:00
91db59b9f3 Integrate version of ATBUpdateTool in send-last-version. 2023-10-12 12:09:19 +02:00
1d81e6b650 Minor: removed unused code. 2023-10-12 12:08:19 +02:00
6d57b45d1a Use getATBQTVersion() for dynamic value of atbapp. 2023-10-12 12:07:38 +02:00
4e7ce2cd70 set version to 1.3.10: remove timeout on opkg-commands. tested download of DC2C_cash.conf file. 2023-10-10 16:05:16 +02:00
47fac31223 remove timeout for process runtime for opkg-commands 2023-10-10 16:03:52 +02:00
0d353cfbcf Check if opkg_command failed, and if this is the case, stop the
update-process without showing a wrong UPDATE-SUCCESS.
2023-10-10 16:01:45 +02:00
bdcb073bf8 set version to 1.3.9 2023-10-10 14:26:20 +02:00
226553a8ab Set version to 1.3.9 after fix of gitShowReason(). 2023-10-09 15:57:11 +02:00
d4ee56559b Use getShowReason() with branchName. Use getOsVersion(0 and
getApismVersion().
2023-10-09 15:54:58 +02:00
355b28ba40 Use current branch name in gitShowReason(), not just master 2023-10-09 15:53:35 +02:00
edeff35d7e Activate download of json-configuration files. 2023-10-06 13:02:23 +02:00
09d5de1b0b rsync: check if source directories in customer repositories exist. 2023-10-06 13:00:25 +02:00
145fdab26e Minor: fixed output format (in text edit) 2023-10-06 13:00:00 +02:00
89d1ec5b21 Deactivate download of device controller. Will be added in coming
version.
2023-10-06 12:58:38 +02:00
f38c975dc6 Remove check for which parent has started atbupdatetool: it is always
systemd now.
2023-10-06 12:57:38 +02:00
fba007aa35 Activate download of json-configuration files. 2023-10-06 12:56:03 +02:00
8b6adb3ea7 Scrolldown text edit at end of whole update process to show
UPDATE_SUCCESS message.
2023-10-06 12:51:30 +02:00
30603317c6 Minor: Add debug messages or change debug message format. 2023-10-06 10:47:08 +02:00
7083f3b4f8 Minor: add debug message. 2023-10-06 10:44:55 +02:00
7ff866525e Fix: allow for json-files EC2C_conf/cash/device.json as well. 2023-10-06 10:43:55 +02:00
2164037123 Do not use opkg_commnands-file as located in the filesystem under
/etc/psa_update anymore.
2023-10-06 10:42:35 +02:00
2e7d33c4c8 Set version to 1.3.7: wait forever for git-commands to finish in QProcess. 2023-10-05 10:54:19 +02:00
2a2751f6f3 Add creation of BUILD_DATE and BUILD_TIME 2023-10-04 14:34:54 +02:00
2764ef4371 Output of current tool version at program startup 2023-10-04 14:33:52 +02:00
9783f343e1 Set version to 1.3.6: exec opkg-commands even for unchanged opkg-commnds-file 2023-10-04 13:23:06 +02:00
8c6f0dfcc7 Minor: use Q_UNUSED() for unused parameters 2023-10-04 13:21:49 +02:00
d688ad3d5c Minor: comments 2023-10-04 10:34:56 +02:00
7b3f652b0e Deactivated doUpdate 2023-10-04 10:20:52 +02:00
4cc42b2a65 Set version to 1.3.6. Removed DCPlugin related stuff. 2023-09-28 12:11:47 +02:00
d783fd7fb6 Minor: print info instead of critical message when git fetch is empty 2023-09-28 12:09:57 +02:00
e0a0ff54e1 Added comment for U00-ISMAS values. Deactivated finalResult() 2023-09-28 12:08:42 +02:00
863d052a21 Removed debug info in appendText()/replcaeLst(). 2023-09-28 12:06:28 +02:00
61b3d29e31 Disable text-edit (showing update-status) ehen update procedure
finished.
2023-09-28 12:05:07 +02:00
cac4f7249e Minor: Add progress parameters. 2023-09-28 12:01:55 +02:00
3223c430be Do not rsync opkg_commnds to local file systems: this sync is not needed. 2023-09-28 12:00:24 +02:00
c09682ea33 Always execute commands contained in opkg_commands, even if no
change in opkg_commands. WAIT button in ISMAS must still be activated.
2023-09-28 11:57:17 +02:00
fef1d43d5f Adapated information of update-progress-status. 2023-09-28 11:56:20 +02:00
705424727b Removed call to final-result: ISMAS will not show U0002 twice. 2023-09-28 11:53:59 +02:00
b96f0896e3 Add explicit message when update-process is starting. 2023-09-28 11:53:10 +02:00
a3967c76ac Use showFullScreen() instead of using a flag 2023-09-28 11:47:09 +02:00
1197598a3d Set version to 1.3.5 2023-09-21 16:52:42 +02:00
ec13e97226 Update interfaces.h to HWapi/4.6 2023-09-21 15:55:31 +02:00
a8dd9d7e24 Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/UpdatePTUDevCtrl 2023-09-21 15:50:19 +02:00
82751eb1d4 Set version to 1.3.4. 2023-09-11 10:14:41 +02:00
17a4a69df2 Added some debug output for parent-process-name 2023-09-11 10:14:04 +02:00
a03261d04a Fixed getParentName() to work analogously to isATBQTRunning(). 2023-09-11 10:12:20 +02:00
7832ef5d8c Set version to 1.3.3. 2023-09-10 17:22:49 +02:00
9c213d0a97 Added some better debug output in the slots concerned with the text edit
of the main window ("update status").
Use insertPlainText() when adding to the text edit to simplify code.
2023-09-10 16:55:32 +02:00
18378afdc5 Did some testing with event filters on the main window. not used. 2023-09-10 16:54:54 +02:00
6dd8a8c6b3 did some testing with event filter. not used. 2023-09-10 16:54:29 +02:00
adfb358e12 Add some output to see if start of the update tool is configured correctly. 2023-09-10 16:51:36 +02:00
ff418b11a1 Use plauginLoader as a dedicated static object. 2023-09-10 16:51:07 +02:00
38e79f0354 Use pluginLoader as a dedicated static object. 2023-09-10 16:50:19 +02:00
103b3f3f9c isATBQTRunning():
Use std::fstream to read /proc/<pid>/status, as the lines
end on '\r', not on '\n'.
2023-09-10 16:46:59 +02:00
ff6a6e0e45 Use libCAslave.so as default library to use for downloading the device-controller-firmware. 2023-09-10 16:45:40 +02:00
afbce3b4ea Add new dc-lib 2023-09-09 15:10:53 +02:00
823e59a582 Set version to 1.3.2 2023-09-09 15:09:59 +02:00
01cfbddfb1 Add update_dc_event 2023-09-09 15:08:03 +02:00
838efd3945 Show status message in the status bar of the GUI. 2023-09-09 15:06:58 +02:00
9a65cb4456 Add some debug message when adding content to the text edit of the GUI. 2023-09-09 15:06:21 +02:00
df0951d671 Add the steps to prepare the bootloader for device-controller-firmware download
using cutom-events of type update-dc-event.
2023-09-09 15:04:41 +02:00
60cc752819 Add connect for showning a status message in status bar. 2023-09-09 15:03:52 +02:00
57b4716e2a Add emergency test function: if device stays in bootloader then use it to
make the device to leave the bootloader.
2023-09-09 15:02:45 +02:00
15f28e9ffd Add m_update-object and prepare for doing the bootloader setup for downloading
the device controller firmware.
2023-09-09 15:01:03 +02:00
a07893ddab doUpdate() and updateDC(): communicate with main window to enter bootloader
(i.e. to prepare device for download of device controller firmware), but do not
perform an actual download at the moment.
2023-09-09 14:59:05 +02:00
d0eb1d12d8 Add some debug output to updateBinary(). 2023-09-09 14:57:49 +02:00
cd59a39569 Add some more debug output to updateBinary(). 2023-09-09 14:57:04 +02:00
67c8b2f472 Extended comment: USING THE BOOTLOADER. 2023-09-09 14:55:48 +02:00
5158878ce2 Extend comment for: USING THE BOOTLOADER.
Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,
2023-09-09 14:54:48 +02:00
b6971c1db5 resetDeviceController(): deprecated. 2023-09-09 14:54:12 +02:00
9df46a1c49 Add some debug output to openSerial(). 2023-09-09 14:53:36 +02:00
6765b12f0c startBootloader(): deprecated. 2023-09-09 14:52:40 +02:00
3e925756cf Add getDcSoftAndHardWareVersion() utility. 2023-09-09 14:43:46 +02:00
b2798b349e Fixed reg-exp for name of device controller firmare version. 2023-09-09 14:41:53 +02:00
64dce44fe1 Move update-object into main window.
Activate using ISMAS WAIT button.
2023-09-09 14:40:43 +02:00
7e96b65c1b Move m_update-object to main window.
Add signal for showing status messages at status bar of ATBUpdateTool gui.
2023-09-09 14:38:53 +02:00
276d65a9d8 Add utility isATBQTRunning(). 2023-09-09 14:33:13 +02:00
ba71728979 Move the dc-plugin (and the update-object) into the gui-thread instead of the
worker thread, so the worker-thread cannot block itself when inside a slot
and therefore not able to react to qt-signals.
2023-09-09 14:30:53 +02:00
e82742a609 Add helper class update_dc_event to dend customer messages from the worker-thread
to the gui-thread. The gui-thread will then perform bl_rebootDC, bl_startBL,
bl_checkBL(), bl_isUp() and bl_stopBL().
2023-09-09 14:27:50 +02:00
6773a7243a Save name of device-controller-plugin (either libCAmaster or libCAslave)
in the Update-object.
2023-09-06 09:12:25 +02:00
22c8997f1e Set autoRequest to false and pass a pointer to the device-controller-plugin
to the main window instead to the worker (thread).
2023-09-06 09:10:14 +02:00
9531a08b4a Add a pointer to the device-controller-plugin. The main window will always be
owned by the GUI thread, and the GUI thread is loading the plugin. Hence the
worker-thread does not block itself when inside a QT slot.
2023-09-06 09:07:45 +02:00
c065b57f0c Remove direct member m_hw, a pointer to the device-controller-plugin.
The worker shall not load the plugin, otherwise it would block itself inside
an QT slot.
2023-09-06 09:04:43 +02:00
cef05b7511 Set version to 1.3.1: extended reason in send-last-version 2023-09-04 11:48:15 +02:00
bb35e985ad Using IsmasClient::getReasonForLastSendVersion() 2023-09-04 11:46:37 +02:00
981a2ea13a Added method getReasonForSendLastVersion() 2023-09-04 11:45:30 +02:00
b14b296011 Added utility getParentName() (name of parent process) 2023-09-04 11:42:12 +02:00
1ef9853876 Set version of UpdateTool to 1.3.0.
1.3.0: main change: add fetching info for current apiism-version and send
if to ISMAS.
2023-08-30 11:47:56 +02:00
01d8312aa8 Removed rauc/opkg-members. Added m_apismVersion member. 2023-08-30 11:46:55 +02:00
507586f9dc Added fetching apism-version. Fixed calls to final_result(). 2023-08-30 11:46:00 +02:00
12ffa71455 Removed rauc/opkg-versions. Added fetching of apism-version. 2023-08-30 11:44:20 +02:00
a84f495d43 Removed output of rauc/opkg-versions, and added output of apism-version. 2023-08-30 11:42:05 +02:00
7e4b5006eb Fixed return string of final result(). 2023-08-30 11:41:23 +02:00
0a28f0d82c Add message for current APISM version 2023-08-30 11:39:37 +02:00
5427844977 For each customer repository change the file ChangeLog in branch master
as last step. The git commit for this file will be used as output, so this file
has always be the last to be checked in.
2023-08-30 11:36:28 +02:00
a45e552d90 set version to 1.2.0 2023-08-25 08:46:29 +02:00
be28570d23 Minor change for output in status bar. 2023-08-23 16:27:47 +02:00
1509e8619c Send message to ISMAS when rsyncing a traiff-file 2023-08-23 16:26:55 +02:00
a8df026a80 Added rsyncFile() method. 2023-08-23 16:26:11 +02:00
a803907449 Refined information shown in status bar. 2023-08-22 13:49:42 +02:00
afd31f1b27 Fill in opkg related info. 2023-08-22 13:49:09 +02:00
f8fef38009 Add last-commit for traiff and add info for opkg_commands. 2023-08-22 13:47:57 +02:00
cbe1fd387d After "rsync", compare etc/psa_tariff and /etc/psa_tariff, if they contain the
same traiff-files (as they should).
2023-08-22 12:31:15 +02:00
1620b73d01 Added sameFilesInDirs(): check for two different directories if the contain the
same files (comparison by name and by git-blob).
2023-08-22 12:29:52 +02:00
4ebdcf56a0 Clear message before showing a new one. 2023-08-22 12:21:17 +02:00
99b9419150 Made gitBlob() static and execute in /tmp as this command can be executed
for every file not only the files contained in a git repository.
2023-08-22 12:19:25 +02:00
4307fb96a6 Add status bar instead of using an message box for displaying error messages. 2023-08-22 09:27:59 +02:00
c35390b6d6 removed commented code plannned for future use -> did not work 2023-08-22 09:27:20 +02:00
fff6bd2b49 Make room for status bar 2023-08-22 09:25:02 +02:00
631ade1954 Show the executed opkg-commands in the text edit. 2023-08-18 11:53:32 +02:00
337bdd1bb0 Add some debug output when restarting APISM. APISM is give a delay of 20s when restarting. 2023-08-18 11:52:34 +02:00
978cc16304 added signal onReplaceLast for QStringList 2023-08-18 11:51:27 +02:00
bea8242d6f Add some changes to the message box (to be chenged anyways later). 2023-08-18 11:50:14 +02:00
56daa84a14 Streamlined the connects (without any whitespace) to silence clang. 2023-08-18 11:49:34 +02:00
17ddfd0ddd Added slot onReplaceLast() to handle adding a QStringList to the text edit. 2023-08-18 11:48:29 +02:00
2ac8c4cfc6 Added scrollDownTextEdit() -> text edit is supposed to scroll down autmatically
in case too much info has to be displayed.
2023-08-18 11:46:57 +02:00
0559ff64e2 Extended some debug output 2023-08-18 11:42:47 +02:00
385a7b7b00 Added utility rstrip() to remove whitespace at the right end of a string. 2023-08-18 11:41:16 +02:00
503b7c64f9 Added some comments to prepare for future change. 2023-08-18 11:39:00 +02:00
beec9c2f9d Added properties to text edit:
Qt::ScrollBarAsNeeded, Qt::ScrollBarAsNeeded, QAbstractScrollArea::AdjustToContents.
2023-08-18 11:37:24 +02:00
5263b7de0f Removed some DEBUG-output. 2023-08-16 12:42:10 +02:00
9b4d0494c8 Streamlined handling of UPDATE_STATUS. 2023-08-16 12:41:42 +02:00
0f2ee0349f Improved debug output. 2023-08-16 10:39:46 +02:00
e700a40875 Initialize psaInstalled.versionInfo to be sent to ISMAS in sendLastVersion(). 2023-08-16 10:38:36 +02:00
1eba5338e4 Removed obsolete sendCmdSendVersionToIsmas(). 2023-08-16 10:37:59 +02:00
f20be9ddcf Removed obsolete sendCmdSendVersionToIsmas(). 2023-08-16 10:37:31 +02:00
7631c05e22 Insert last commit-id, message and date of last commit into sendLastVersion-message to ISMAS. 2023-08-16 10:34:55 +02:00
ad93e536f0 Added gitShowReason(): get lastCommit, message and date of last commit to insert inti
sendLastVersion-message to ISMAS.
2023-08-16 10:33:08 +02:00
259da8200e Fixed known defaults for starting ATBUpdateTool. 2023-08-14 15:08:00 +02:00
8d528f0f55 SO_SNDTIMEO and SO_RCVTIMEO socket options have turned out not to be reliable.
Use select() for detecting timeout on socket (read and write).
2023-08-14 14:35:54 +02:00
66d0214720 Always look for {"error": "ISMAS is offline"} first.
Allow for empty update-trgger (try again)
rsync: mkdir -p the necessary directories.
2023-08-14 14:33:12 +02:00
86064979b4 Add memeber-variable for exitCode of executed process. 2023-08-14 14:28:23 +02:00
86c996d7ac Set final version to 1.1.1w 2023-08-11 12:24:51 +02:00
effe41bac9 Use finalResult() to sent a final message to ISMAS about the result of the update process. 2023-08-11 12:20:09 +02:00
4968942cc2 Added finalResult() -> send final message to ISMAS in any case. 2023-08-11 12:19:10 +02:00
769626581f Use head -n 1 in gitLastCommit(). 2023-08-11 11:12:59 +02:00
0e97ce7dc2 Take the pipe symbol into account in output of git getch command. 2023-08-11 11:12:09 +02:00
34334676fc Use print-utis from utils.h. 2023-08-11 11:11:14 +02:00
853787cd4b Added lastCommit to tariff-struct. Added jsonParseFailed(). 2023-08-11 11:09:51 +02:00
a932ed5471 Hide button on error message box. 2023-08-11 11:07:16 +02:00
c338884fc7 Use print-util in utils.h. 2023-08-11 11:06:38 +02:00
ed6df98653 Set progress bar timer to 500ms.
Yield thread to give worker thread its share of CPU time.
2023-08-11 11:05:33 +02:00
9eb458c4c5 Start Application after 1 second delay. 2023-08-11 11:05:02 +02:00
202e83268b Added utilities
void printCriticalErrorMsg(QString const &errorMsg);
    void printInfoMsg(QString const &infoMsg);
    void printLineEditInfo(QStringList const &lines);
    QString getTariffLoadTime(QString fileName);
2023-08-11 11:03:21 +02:00
8f26bfee0f Get last commit date and loadtime of tariff-file. 2023-08-11 11:02:15 +02:00
1af136e39d Set delay when trying to fetch value of update-trigger. 2023-08-11 11:01:26 +02:00
a550d55004 Get triggerValue directly from JSON. 2023-08-11 11:00:52 +02:00
a37a22d3f9 Show message boxes when running UpdateTool manually. 2023-08-11 11:00:02 +02:00
a8941f4ef4 Set progress values. 2023-08-11 10:59:26 +02:00
746565dbe0 Add messages sent to ISMAS. 2023-08-11 10:58:29 +02:00
79906df12e Add some qt debug aoutput. 2023-08-11 10:56:36 +02:00
edf1d105e7 Deactivate backendConnected(). 2023-08-11 10:55:53 +02:00
6c4b02cb56 Use print-utils to print some debug messages. 2023-08-11 10:52:31 +02:00
04d5061d79 Added some constants. 2023-08-11 10:49:34 +02:00
042e6dfa38 Try to establish a connection to backend 50x. 2023-08-09 16:17:28 +02:00
e523d3cc2c Added/chenged some debug output. 2023-08-09 16:16:36 +02:00
927197d0d1 Removed restart of APISM. 2023-08-09 16:14:59 +02:00
72cb738af5 Removed handling of pipe symbol (if available in git output). 2023-08-09 16:12:56 +02:00
0fb38013f7 Work with device controller file directly, not via link.
Add startProgress/stopProgress().
2023-08-09 15:09:44 +02:00
5f1376cf1e Removed buttons reserved for future use.
Start application automatically, not via Start-Button.
2023-08-09 15:08:22 +02:00
5db7b4224e Made start/stopProgress() public. 2023-08-09 15:06:20 +02:00
7c7adc94e6 Removed Start-button, because it is not needed.
Removed buttons reserved for future use.
2023-08-09 15:05:04 +02:00
89c2d3a8ae Added some debug output. 2023-08-09 15:03:14 +02:00
c2b52aa91d Only check for keyword RECORD to be more general. 2023-08-09 15:01:43 +02:00
329c770aa0 Use a message box with color red and a timer to click on ok after 5 secs. 2023-08-07 14:01:51 +02:00
cdb045b72b Fixed onAppendText() and onReplaceLast():
Watch out for special suffixes.
2023-08-07 13:59:44 +02:00
6d43cf4c9f Send custom events to the progress bar according to the state of the update process.
Changed the handling of messages for the text edit.
2023-08-07 13:56:51 +02:00
4caa0c0d83 Removed obsolete out-commented lines. 2023-08-07 13:55:52 +02:00
4d2d38e45c Default parameter for onReplaceLast() 2023-08-07 13:53:48 +02:00
9a55ce18e4 Chawnged font to Misc Fixed 2023-08-07 13:53:04 +02:00
223c7a8f8d Added errorGitClone(). 2023-08-07 13:51:47 +02:00
ce72d3d14d For the error EWOULDBLOCK try again 10 times until quitting. 2023-08-07 13:50:59 +02:00
8b66c47e49 Added errorGitClone() 2023-08-07 13:50:14 +02:00
4ff3b0efdf Advance the progress bar in the foreground when a long running task
in the background (e.g. git clone).
2023-08-06 20:44:26 +02:00
1fd2269753 onAppendText() only appends text.
onReplaceLast() replaces the last line in the text edit window.
2023-08-06 14:14:47 +02:00
a8994423f4 Change font size for full screen window. 2023-08-06 14:11:41 +02:00
4594c913e0 Using syslog for debugging. 2023-08-06 07:34:17 +02:00
cf9033e898 Send custom event from worker(-thread) to MainWindow in order to update
progress bar.
2023-08-05 18:50:50 +02:00
b09ccfd4f5 Add custom ProgressEvent class for future use. 2023-08-04 14:10:47 +02:00
6b4c486549 Add m_ismasClient.updateOfPSASucceeded() for a successful run. 2023-08-04 13:53:55 +02:00
9c44656104 Add parameter -vv fot the rsync command to see more debugoutput. 2023-08-04 13:52:57 +02:00
d57914957d Add text-edit entry if git pull is successful. 2023-08-04 13:50:19 +02:00
c4f12ce75a Added terminal-debug-output. 2023-08-04 13:49:32 +02:00
4ad370ea46 Extended displayed messages in text-edit. 2023-08-04 13:48:40 +02:00
44ad3caf2b Stop exit timer in onQuit.
Activate error message boxes.
2023-08-04 13:45:56 +02:00
427a272f8f Connect exit-button with clicked(). 2023-08-04 13:45:19 +02:00
96fb50e68d Moved init. of text-edit upwards.
Hide reserved buttons.
2023-08-04 13:44:16 +02:00
19274546c9 set main window fullscreen 2023-08-04 13:39:17 +02:00
d2d730589b changed return type of returnCode() ti 'int' 2023-08-04 13:38:33 +02:00
f88b0edb2a Fix for the case when several branches are edited: 'git fetch' will
display several lines then, not only one.
2023-08-04 13:35:42 +02:00
c62299aa72 Read from /mnt/system_data/ instead of /etc. 2023-08-04 13:33:25 +02:00
c054668eac Ask for the reurn code of the process, not only for process exit status. 2023-08-04 13:31:12 +02:00
82352713f1 Added 6 more buttons for future use and for the fullscreen layout. 2023-08-04 13:30:18 +02:00
48073ab1f0 update to next version 2023-08-03 10:14:23 +02:00
c6e98f50c2 call onQuit() directly whem timer runs out 2023-08-03 10:14:09 +02:00
ef88fdc9a4 Fix: config for deployment 2023-08-03 09:50:26 +02:00
8889aaca2a Fix: path for deployment 2023-08-03 09:44:08 +02:00
9b08420ac1 Use exit() instead of quit() to be able to add a returnCode in case of failure. 2023-08-03 09:06:50 +02:00
0ee92f0181 disbale exit-button as long as update process is running 2023-08-02 17:51:35 +02:00
a995cae000 set exit timer to 10 secs 2023-08-02 16:54:47 +02:00
0b7d504a7a Fixed missing git pull command.
Fixed missing update for text-edit when only clone the customer repository.
2023-08-02 16:53:19 +02:00
6a4a852fd6 Updated for new device controller lib (CAmaster) 2023-08-02 15:52:01 +02:00
81a9304438 Worker is the work-horse of the update process.
Using ismas-client it sends requests to APISM and gets results in a synchronous fashion.
Add previous emits to git client and apism client have been removed.
2023-08-02 15:50:04 +02:00
332d689b8c Add worker-object to be able to update for the worker. 2023-08-02 15:47:19 +02:00
b508c0517d Reset.
Add helper functions read1stLineOfFile() and zoneNr().
2023-08-02 15:45:20 +02:00
d2c0fdf820 Minor change: remove header 2023-08-02 15:44:45 +02:00
7293afd203 Minor change: include header 2023-08-02 15:44:16 +02:00
2fd1053bf9 Removed maintenance mode 2023-08-02 15:40:44 +02:00
e0a68a35f4 raised output-buffer length to 1024*8 2023-08-02 15:39:52 +02:00
4e277b4ca6 Added text edit 2023-08-02 15:39:08 +02:00
b3f4a4086b Populate text-edit with run-time info from update-process. 2023-08-02 15:29:10 +02:00
eb7d77692b Removed obsolete apism/tcp-client files. 2023-08-02 15:20:07 +02:00
ce1b1859df Removed apism-client and tcp-client. All done inside of ismas client now. 2023-08-02 15:18:39 +02:00
371cc1a187 Removed communication with ISMAS from git client. 2023-08-02 15:17:10 +02:00
a94606ca89 Added sendRequestReceiveResponse(): static member for communication with
APISM, on ports 7777 and 7778.
Each request is immediately handled in a synchronous fashion.
Added several helper functions to format messages to be sent to APISM/ISMAS.
2023-08-02 15:13:05 +02:00
5c9c9dc917 add mainwindow and utils 2023-07-31 16:56:16 +02:00
ab8acfc7d1 use gui-interface for ATBUpdateTool 2023-07-31 16:55:36 +02:00
1ddd0074b3 Set c++17 for PTU5-YOCTO 2023-07-20 09:06:07 +02:00
2b934f6baf Added signals
void sendCmdSendVersionToIsmas(QString);
    void sendCmdEventToIsmas(QString);
and associated slots:
    void onSendCmdSendVersionToIsmas(QString);
    void onSendCmdEventToIsmas(QString);
Implemented slots.
2023-07-19 16:53:45 +02:00
1bdae56342 Added debug messages.
Fixed gitBlob(): do not check for existing customer repository.
2023-07-19 16:50:54 +02:00
6caaae6d50 Add struct PSAInstalled.
Changed interface of updateOfPSASendVersion into
    QString updateOfPSASendVersion(PSAInstalled const &psa);

Re-implemented updateOfPSASendVersion().
2023-07-19 16:48:42 +02:00
4dc0c71d3f Add -g flag even for release build 2023-07-19 16:46:29 +02:00
a54f4f94c9 Minor change: remove not needed customerNrStr-variable 2023-07-19 16:45:43 +02:00
b8d6c909eb Minor change: reset output buffer-length to 1024 2023-07-19 16:44:26 +02:00
e35fb9dc19 Commented out debug-messages 2023-07-19 16:43:24 +02:00
0e0363f131 Additinal UPDATE_STATE constants.
Added struct UpdateStatus for printing debug messages.
Added member variables used for sending SENDCMD to ISMAS.A
Added helper functions
    getATBQTVersion(),
    getCPUSerial(),
    getRaucVersion(),
    getOpkgVersion(),
    getPluginVersion(),
    getDCVersion(),
    getFileSize().

Removed automatic restart of Apism.
Added emergency timer to end application after 10 mintes.
onHandleChangedFilenames():
    handling of opkg_commands
    handling of json/dc -> deactivated for the moment.
Re-implemented onSendCmdSendVersionToIsmas(): use only one parameter of type PSAInstalled.
Implemented operators<<() to print debug messages.
2023-07-19 16:42:18 +02:00
088d7c8aa0 Additinal UPDATE_STATE constants.
Added struct UpdateStatus for printing debug messages.
Added member variables used for sending SENDCMD to ISMAS.A
Added helper functions
    getATBQTVersion(),
    getCPUSerial(),
    getRaucVersion(),
    getOpkgVersion(),
    getPluginVersion(),
    getDCVersion(),
    getFileSize().
2023-07-19 16:35:48 +02:00
60084450e6 Removed 't (testMode)' and 'e (executeScript)' options. Adapted call to Worker-ctor. 2023-07-17 16:54:18 +02:00
9775792916 Minor change: extended debug-output. 2023-07-17 16:52:27 +02:00
93d6277386 Simplified interface. 2023-07-17 16:51:40 +02:00
37c5c7c4f6 Simplified interface.
When doing a clone of the repository, do not execute any other commands.
2023-07-17 16:49:44 +02:00
5eb33f3e31 Minor change: renamed function sendUpdateInfToIsmas() to
emulateUpdatesAvailable() for clarity.
2023-07-17 16:48:04 +02:00
43f5f3ecae Removed usage of any files. Removed any dependencies on git-hooks.
Removed handling of opkg-related things: they are done now inside the worker itself.
2023-07-17 16:45:11 +02:00
c503750e90 Simplified interface of ctor.
onHandleChangedFiles(): split handling of opkg_commands-file and
downloading of DC/JSON-Files.
rsync to file-system only once these operations were successful.
2023-07-17 16:43:05 +02:00
7054c18113 Extended UPDATE_STATUS enum.
Simplified interface.
Read machine_nr, cust_nr, zone_nr from file.
2023-07-17 16:38:53 +02:00
077eb803a1 plan fuer das update 2023-07-16 18:31:15 +02:00
f963b61ebc Added helper functions. Update will be used heavily by the Worker-class in a later stage. 2023-07-14 13:34:48 +02:00
9ed51d60e4 Added helper functions. 2023-07-14 13:33:46 +02:00
f5198efab3 Added worker/worker-thread-pair.
Worker uses event-loop of worker-thread.
Worker itself is used as work-horse for the update-process.
2023-07-14 13:32:00 +02:00
d6446f90fe Removed C++-thread-handling, replaced it with Qt-versions. Using explicit Worker
instance instead.
2023-07-14 13:29:52 +02:00
58bceb5d27 Started ISMASClient providing the data to be sent to ISMAS.
It does not send to ISMAS itself.
2023-07-14 13:28:41 +02:00
92084bed99 Added call to waitForConnected() when doing a connectToHost().
Replaced some qCritical() with qDebug()-calls.
2023-07-14 13:27:14 +02:00
cd1c92a7db Copied from ATBQT app.
Added slots requestAvailableIsmasUpdates(), sendCmdSendVersionToIsmas() and
sendUpdateInfoToIsmas().
2023-07-14 13:24:14 +02:00
9ca758ecd3 Added ISMAS_PARAMETER for ISMAS::REQUEST 2023-07-14 13:21:02 +02:00
3c54d8de6d Made GitClient a Qt-object. Impreoved several utility functions handling git commands.
Added slot onIsmasUpdatesAvailable().
Added helpers getLastCommit(), gitBlob(), gitCommitForBlob(), gitIsFileTracked().
2023-07-14 13:17:45 +02:00
d91d4261d9 Add another utility function and added signal/slot ismasUpdatesAvailable/onIsmasUpdatesAvailable(). 2023-07-14 13:13:03 +02:00
00f5216a9f Added utility functions. 2023-07-14 13:12:37 +02:00
aeae9002fe Made GitClient a Qt-Object. 2023-07-14 13:10:55 +02:00
9df425f5f8 Use Qt to format debug-info. Note that the full info is visible only in debug-mode. 2023-07-14 12:58:23 +02:00
5149a67d4b Provide the possibility to pass parameters to a command using a string-list.
Has to be improved later.
2023-07-14 12:56:33 +02:00
1309c27f7c Added ismas_client.h/.cpp. Added c++17-flag. 2023-07-11 16:59:49 +02:00
26db620465 use of worker/worker-thread so we can work without using buttons (as the cannot be triggered by an automatic update process) 2023-07-11 16:58:49 +02:00
bd213b8f8c start 2023-07-11 11:24:23 +02:00
31b7bd1314 Made split() a static member function. 2023-07-10 16:00:34 +02:00
0bdbd39632 Added directories for apism/command/process. 2023-07-10 15:59:28 +02:00
b979fb5b2a command-class as abstraction for executing git-commands. 2023-07-10 15:57:59 +02:00
cbefccd2d3 Add first commands for using AUBUpdateTool as git-client 2023-07-10 15:57:17 +02:00
0ebe274e9a Add files copied from ATBQT application 2023-07-10 15:56:20 +02:00
c4d09eb2ea Add -e (execute-script-only) and -d (dry-run) options 2023-07-06 16:54:01 +02:00
3039fcc553 remove superfluous \n 2023-07-06 16:52:32 +02:00
a67e587769 Activate download of printer templates 2023-07-06 15:14:52 +02:00
d89520d58e Activate updating device-controller-firmware. 2023-07-06 14:32:57 +02:00
06a9eba177 Turn auto-request ON in any case. 2023-07-06 14:32:20 +02:00
a41dc5403f Open serial port only if not already opened. 2023-07-06 14:31:32 +02:00
85b2c1f08e Write update_log.csv.copy in different format. 2023-07-06 14:30:48 +02:00
ba8dd7d083 updateDC(): stop boot loader even when not ven able to start it. 2023-07-06 14:28:46 +02:00
fa04e32266 When sending dc-data, fill the last block with 0xFF to stream-line the source code. 2023-07-06 14:27:44 +02:00
7d6b433373 Removed obsolete code. 2023-07-06 14:26:58 +02:00
faae8b8d9a Add aux. function isSerialOpen(). 2023-07-06 14:25:36 +02:00
a0d0de19c5 Use QThread::sleep() instead of std-C++-code. 2023-07-06 14:24:19 +02:00
17eaa7858f Add handling of test-mode. 2023-07-06 14:23:04 +02:00
f2556412d8 Comment some lines. 2023-07-06 14:21:29 +02:00
26557542f1 Added test-mode. Added aux. function isSerialOpen(). 2023-07-06 14:13:33 +02:00
6bb46e165c Add handling of VERSION. Add test-mode. 2023-07-06 14:12:41 +02:00
027529161d Add VERSION to be used inside application 2023-07-06 14:11:28 +02:00
61c847102d Open/empty update_log.csv/.csv.copy at start. Added some debug-output 2023-06-29 12:42:16 +02:00
3034f49c96 Minor change: add comment 2023-06-29 12:40:47 +02:00
528b74549a Aopen serial port only when necessary, i.e. when downloading device controller
or json-files.
2023-06-27 17:32:13 +02:00
c7acc2a99b Add comment for the procedure of downloading device controller. 2023-06-27 17:31:38 +02:00
61afdfc325 resetDeviceController(): use bl_rebootDC(). 2023-06-27 17:30:56 +02:00
c34944af8b Add slots for catching output of underlying update_psa_script.
iSetting timeout to 200000 when in maintenance-mode.
2023-06-27 17:29:10 +02:00
58684cf3c4 Add new slots readyReadStandardOutput/Error and finished to get messages
from included update_psa-script.
2023-06-27 17:25:23 +02:00
08122cf703 Update interfaces.h 2023-06-22 18:17:46 +02:00
fdd32cea92 Remove interfaces.h for update interfaces.h 2023-06-22 18:16:41 +02:00
7c17090a2b Remove deployment rules (conflict on yocto) 2023-06-22 17:54:11 +02:00
3de46ea099 Add Config PTU5_YOCTO 2023-06-22 17:46:09 +02:00
f46ac4075a activate only handling of opkg-commands 2023-06-22 15:43:21 +02:00
0668ab65be Added helper-function downloadJson() to implement downloadinf print/conf/cash/device.json. Added some compile time flags used for testing. 2023-06-22 15:36:36 +02:00
f66ae498ce Adding methods for downloading DC2C_cash/conf/device.json 2023-06-22 15:20:21 +02:00
e420f95eb0 Fix: do not print an empty buffer ending with \n 2023-06-22 15:19:17 +02:00
809440ba95 Added comment 2023-06-22 15:18:20 +02:00
c6ea94e249 Added some commnts. 2023-06-21 16:25:53 +02:00
4cee0e37da executeUpdateScript: set timeout to 200 secs. Open serial port only once for the whole loop handling the lines in update_log.csv. Sending of device controller in Debug-setting worked. Execution of opkg-commnds worked. Sending of JSON files needs further testing: sys_readyForSending failes sometimes after 5 seconds. 2023-06-21 16:25:21 +02:00
9c343f3eeb Added planned methods updateConf() and updateCashConf(). Changed interface of updateDC() and updatePrinterTemplate() 2023-06-21 16:19:45 +02:00
e79d6c6fef Added maintenance-mode parameter. Activated handling of opkg-commands. 2023-06-20 16:14:13 +02:00
88013e82f0 Added maintenance-mode parameter 2023-06-20 16:13:11 +02:00
079a6910dd Added flag for maintenance-mode 2023-06-20 16:08:42 +02:00
bbf97dc58d network-setting not necessary. Make console-setting explicit. 2023-06-20 16:08:02 +02:00
810b603d70 Added updateDC() and updatePrinterTemplate(). Prepared for live testing. 2023-06-19 16:01:29 +02:00
8281303a55 Added updateDC() and updatePrinterTemplate() 2023-06-19 16:00:22 +02:00
a4afeeb396 Added Qt-commandline parser 2023-06-19 15:59:17 +02:00
bc3a801b8d Renamed ATBUpdateDC to ATBUpdateTool 2023-06-19 15:58:15 +02:00
f52dec9124 Just for saving 2023-06-16 16:54:21 +02:00
07942153c3 Add newest dc-library 2023-06-16 16:53:02 +02:00
bac848f6be update interface.h to fit newest version of dc-controller-software 2023-06-16 16:52:22 +02:00
ccc1bf2a99 Add functionality from hwapi to download device controller to dc-hardware 2023-06-16 16:51:30 +02:00
c8487a7541 fixed handling of debug levels 2023-06-16 16:49:20 +02:00
dc90705f24 re-implement to use dc-plugin as shsred onject 2023-06-16 16:48:58 +02:00
c4c503080e Do not use DCPlugin subtree anymore 2023-06-16 16:47:56 +02:00
e2d9c5aa90 Comit helper-classes for now 2023-06-16 16:47:13 +02:00
60f845aa8d generated from tex file 2023-06-16 16:45:03 +02:00
fa0c31d9e4 save for the weekend 2023-06-02 14:17:48 +02:00
57b82094c8 removed handling of tariff, as this is not downloaded to dc 2023-05-30 16:49:48 +02:00
af337874a6 removed handling of tariff, as this is not downloaded to dc 2023-05-30 16:47:00 +02:00
f016e9777e Added default parameter to split() 2023-05-30 16:44:55 +02:00
85bec3364f deleted obsolete file 2023-05-26 13:04:43 +02:00
35d40e3b3c Add handling of update-script 2023-05-26 13:03:38 +02:00
71a6b82d58 Add env-var XDG_RUNTIME_DIR 2023-05-26 13:02:45 +02:00
de75ef32d9 start docu for update_ptu 2023-05-26 13:01:44 +02:00
3bac92c711 Add subtree add command to make sure DCPlugin is included 2023-05-25 10:21:42 +02:00
2b5fca73a2 removed c++-headers. 2023-05-22 16:06:52 +02:00
6d4c247de7 Using update.h/.cpp and thread pool 2023-05-22 16:04:50 +02:00
892fae92ad Using Utils-class and QRunnable.w 2023-05-19 15:33:40 +02:00
3938051c32 Add Utils-class to provide most of the previous functionality. 2023-05-19 15:32:52 +02:00
18e4811d57 Added some debug output.
Send only one DC_print-template.
Tested again downloading dc-firmware and printer-templates.
2023-05-18 14:26:23 +02:00
8d325c20eb Merge commit '6099d07650acb28df1a5c9659479351daa7c2d27' 2023-05-17 16:08:57 +02:00
6099d07650 Squashed 'DCPlugin/' changes from d992ee3..e32142c
e32142c Implement cash input interface
f611e07 Implement printing ticket
6478eda TS: pr_printTemplate(): send 'longFDcmd_set()'
1663d09 Merge with TS 21.04.23
080c00e Set serialPort name from config
bbce2b0 Test printing ticket
8ff17a2 DeviceControllerInterface: erroCode is a string
c657428 Project: including DCPlugin.pri globally
f0f0493 hwapi: remove unused dependency to QWidget
9bf99c5 Fix: make plugin compile
8ff8faf Fix: warning
09a8049 Merge branch 'master' into pu/integration
21fb07b Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/DCPlugin
01f8c1e First compiling version for high level vending interface
3029b8d Rename TARGET name
2143801 Configure project for PTU5-YOCTO
6f6d3b7 Add atb/qt gitignore
4cfb8f1 Add auto version generation script

git-subtree-dir: DCPlugin
git-subtree-split: e32142cd6277cf647d27a9c0a2e9e4d7c6ca4269
2023-05-17 16:08:57 +02:00
0c14002f7f remove update printer template 2023-05-03 09:00:02 +02:00
6765bb13e5 Fixed printing od ticket: dc_printTemplate(). First send dynamic data, then use prn_sendDynamicPrnValues() 2023-05-03 08:59:17 +02:00
ceedf72b34 iAdd some test data. 2023-04-19 14:22:28 +02:00
8a216c43c0 Squashed 'DCPlugin/' changes from 01140c5..d992ee3
d992ee3 Added dc_getStatus() to send info to ISMAS
b7d8fab Added dc_getStatus() to send info to ISMAS
7129805 Added dc_getStatus() to send info to ISMAS

git-subtree-dir: DCPlugin
git-subtree-split: d992ee3fad831f8bc159b87e687390a233b41afb
2023-04-18 15:07:55 +02:00
9620d58373 Merge commit '8a216c43c05db28340cf5e4272bf2e66c6a868e9' 2023-04-18 15:07:55 +02:00
2c6fa31cff Squashed 'DCPlugin/' changes from 1eb2ac3..01140c5
01140c5 Using std::min from algorithm-header
c99d073 Added additional variables into shared memory. Cleaned source.
81c610c Included additional variables into shared memory
6ae7c06 Changed to const-pointer

git-subtree-dir: DCPlugin
git-subtree-split: 01140c523b600912e83302c988059c1cfd0a5488
2023-04-18 14:44:24 +02:00
073482d1a9 Merge commit '2c6fa31cff30e193dc542183b8a5aec022100d79' 2023-04-18 14:44:24 +02:00
ee902898c4 Squashed 'DCPlugin/' changes from f3adba2..1eb2ac3
1eb2ac3 Use const-pointer

git-subtree-dir: DCPlugin
git-subtree-split: 1eb2ac3a1df01a7af3244f6fe495a8b143d946bf
2023-04-18 13:56:04 +02:00
4c21c439a2 Merge commit 'ee902898c4bed3a7ecdc4954094e535cf1af1e67' 2023-04-18 13:56:04 +02:00
acde999b9d Squashed 'DCPlugin/' changes from 652ad9b..f3adba2
f3adba2 Change parameter type from uint8_t to bool

git-subtree-dir: DCPlugin
git-subtree-split: f3adba2f0ff7a574039c23b44cee9872d0f25d34
2023-04-18 13:53:23 +02:00
928e7de9ac Merge commit 'acde999b9db601dcb93e86639da5127cfc10ac79'. 2023-04-18 13:53:23 +02:00
8b301a91dc Squashed 'DCPlugin/' changes from 3e3e1ef..652ad9b
652ad9b Included changes of TS for version 3.5.
c85b090 Added ulong2uchar (version 3.5).
87a6ed0 Include changes of Thomas for version 3.5.
99c88c7 Included changes of Thomas for version 3.5. prn_getPrintResult(),
712ea0f Included changes of Thomas for version 3.5 of library: datif_templatePrintFinished_OK(), datif_templatePrintFinished_Err(), datif_gotNewCoin().
86311de Add use of shared memory. Add changes for version 3.4. of library.
cb44127 Added check4freeFDshortCmd.
a95e174 Included some changes of Thomas.
c724b5b Shift several device controller related variables to shared memory.
ef79321 Massive change: using shared memory containing most device controller realted variables.
a7aa75a Massive change: using shared memory containing devcie controller variables.
dc00c69 Added check4freeFDlongCmd.
eeb3519 Adding shared memory containing all variables necessary to check device controller related variables.
30338e2 Changed struct T_moduleCondition. Changed struct T_dynamicCondition. Added struct T_extTime. Added log_chkIfVaultRecordAvailable(). Added sys_getDeviceConditions(). set version to 3.4.
58fdea4 Added m_sharedMem. Added cash_getAmountInVault. Added cash_getNrCoinsInVault. Added sys_getDynMachineConditions() with new interface. Added sys_getDeviceConditions() with new interface. Added log_chkIfVaultRecordAvailable().
df760f1 Added shared_mem_buffer.h/.cpp.

git-subtree-dir: DCPlugin
git-subtree-split: 652ad9b43d24bddbc3c2636c4ff4b5d74e081e46
2023-04-18 13:43:37 +02:00
981d9706e2 Merge commit '8b301a91dc0d4ae7a4ddd5f470016b4cd68b85c4'. 2023-04-18 13:43:37 +02:00
ff5e3f15a4 Squashed 'DCPlugin/' changes from e5a8cfd..3e3e1ef
3e3e1ef Make sure the printer functions can be called without explicitly openeing the serial device.

git-subtree-dir: DCPlugin
git-subtree-split: 3e3e1efe7d77c71f0101f35c8b38419e877f5636
2023-04-14 09:06:56 +02:00
04dfc407c0 Merge commit 'ff5e3f15a47f165005e691a88cbe1fa44a84fe0d'
Use a defualt parameter for printer functions to decide if serial device has to be
opened or not.
2023-04-14 09:06:56 +02:00
39f5e2af10 Use PTU5 define. 2023-04-14 09:06:45 +02:00
67 changed files with 16695 additions and 9690 deletions

36
DC2C_print01.json Normal file
View 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
DC2C_print02.json Executable file
View 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
DC2C_print03.json Executable file
View 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",
}

42
DCPlugin/.gitignore vendored
View File

@@ -1 +1,41 @@
*.user # C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
*.pro.user
*.pro.user.*
moc_*.cpp
qrc_*.cpp
Makefile
Makefile.*
*-build-*
#
*.autosave
ui_*.h
version.h
version.txt
packages/*
*.pro.orig
Output/setup.exe
.directory
*~
resources/icons/*.png
resources/icons/*.jpg
resources/icons/*.gif
resources/style/*.qss
text/*.html
!text/*_template.html
text/*.xml

View File

@@ -10,7 +10,8 @@ HEADERS += $${PWD}/include/com.h \
$${PWD}/include/prot.h \ $${PWD}/include/prot.h \
$${PWD}/include/sendWRcmd.h \ $${PWD}/include/sendWRcmd.h \
$${PWD}/include/storeINdata.h \ $${PWD}/include/storeINdata.h \
$${PWD}/include/tslib.h $${PWD}/include/tslib.h \
$${PWD}/include/shared_mem_buffer.h
SOURCES += $${PWD}/src/com.cpp \ SOURCES += $${PWD}/src/com.cpp \
$${PWD}/src/controlBus.cpp \ $${PWD}/src/controlBus.cpp \
@@ -20,4 +21,5 @@ SOURCES += $${PWD}/src/com.cpp \
$${PWD}/src/prot.cpp \ $${PWD}/src/prot.cpp \
$${PWD}/src/sendWRcmd.cpp \ $${PWD}/src/sendWRcmd.cpp \
$${PWD}/src/storeINdata.cpp \ $${PWD}/src/storeINdata.cpp \
$${PWD}/src/tslib.cpp $${PWD}/src/tslib.cpp \
$${PWD}/src/shared_mem_buffer.cpp

View File

@@ -14,6 +14,8 @@ QMAKE_CXXFLAGS += -Wno-deprecated-copy
# default # default
ARCH = PTU5 ARCH = PTU5
include(DCPlugin.pri)
contains( CONFIG, DesktopLinux ) { contains( CONFIG, DesktopLinux ) {
QMAKE_CC = ccache $$QMAKE_CC QMAKE_CC = ccache $$QMAKE_CC
QMAKE_CXX = ccache $$QMAKE_CXX QMAKE_CXX = ccache $$QMAKE_CXX
@@ -21,7 +23,6 @@ contains( CONFIG, DesktopLinux ) {
# QMAKE_CXXFLAGS += -Wno-deprecated-ctor # QMAKE_CXXFLAGS += -Wno-deprecated-ctor
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments } linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux ARCH = DesktopLinux
include(DCPlugin.pri)
} }
contains( CONFIG, PTU5 ) { contains( CONFIG, PTU5 ) {
@@ -31,22 +32,23 @@ contains( CONFIG, PTU5 ) {
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments } linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
CONFIG += link_pkgconfig CONFIG += link_pkgconfig
ARCH = PTU5 ARCH = PTU5
# NOTE: include contents of DCPlugin.pri. Also used by ATBQT.
# Add new files in DCPlugin.pri.
include(DCPlugin.pri)
} }
contains( CONFIG, PTU5_YOCTO ) { contains( CONFIG, PTU5_YOCTO ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
PTU5BASEPATH = /opt/devel/ptu5
ARCH = PTU5 ARCH = PTU5
# add qmqtt lib # add qmqtt lib
#LIBS += -lQt5Qmqtt #LIBS += -lQt5Qmqtt
} }
TARGET = CashAgentLib TARGET = ATBDeviceControllerPlugin
DESTDIR = ../plugins #DESTDIR = ../plugins
INTERFACE = DeviceController
INTERFACE_DEFINITION = $${PWD}/include/ATBAPP/DeviceControllerInterface.h
DEFINES += DEVICECONTROLLERPLUGIN_LIBRARY
# The following define makes your compiler emit warnings if you use # The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings # any Qt feature that has been marked deprecated (the exact warnings
@@ -66,3 +68,27 @@ DEFINES += QT_DEPRECATED_WARNINGS
#else: unix:!android: target.path = /opt/$${TARGET}/bin #else: unix:!android: target.path = /opt/$${TARGET}/bin
#!isEmpty(target.path): INSTALLS += target #!isEmpty(target.path): INSTALLS += target
# ATBAPP interface
HEADERS += \
src/ATBAPP/ATBAPPplugin.h \
src/ATBAPP/DeviceControllerInterface.h \
src/ATBAPP/ATBHealthEvent.h \
src/ATBAPP/ATBDeviceControllerPlugin.h
SOURCES += \
src/ATBAPP/ATBHealthEvent.cpp \
src/ATBAPP/ATBDeviceControllerPlugin.cpp
DISTFILES += \
generate-version.sh
# Define how to create version.h
VERSION_H = $$PWD/include/version.h
version.output = $$PWD/include/version.h
version.commands = $$PWD/generate-version.sh $${ARCH} $${TARGET} $${INTERFACE} $${INTERFACE_DEFINITION} $${VERSION_H}
version.depends = FORCE
version.input = VERSION_H
version.variable_out = HEADERS
QMAKE_EXTRA_COMPILERS += version
QMAKE_CLEAN += $${PWD}/include/version.h

155
DCPlugin/generate-version.sh Executable file
View File

@@ -0,0 +1,155 @@
#!/bin/bash
VERSION_STRING=""
#GIT='/cygdrive/c/Program Files \(x86\)/Git/bin/git'
GIT=git
parse_git_branch () {
$GIT branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* \(.*\)/\1/"
}
ARCH=$1
TARGET=$2
INTERFACE=$3
INTERFACE_DEFINITION=$4
VERSION_H=$5
SCRIPT=$(readlink -f $0)
SCRIPTPATH=`dirname $SCRIPT`
OUTPUTDIR=$(pwd)
echo " current dir is : " $(pwd)
echo $SCRIPT
echo $SCRIPTPATH
echo "changing dir to script path: " $SCRIPTPATH
cd $SCRIPTPATH
# set version string ##################################################################
if [ -z $VERSION_STRING ] ; then
VERSION_STRING=$(date +%Y%m%d_%H%M)
fi
GIT_DESCRIBE=$($GIT describe)
GIT_BRANCH=$(parse_git_branch)
# extract path from branchname:
IFS='_' read -ra TMP_ARRAY <<< "${GIT_BRANCH}"
BRANCH_PATH=${TMP_ARRAY[0]}
# detect if we have a development version:
if [ ${#TMP_ARRAY[1]} -gt 0 ] ; then
DEV_SUFFIX="_dev"
else
DEV_SUFFIX=""
fi
# detect if git status is dirty
GIT_DESCRIBE_DIRTY=$($GIT describe --dirty)
if [ "${GIT_DESCRIBE_DIRTY:(-6)}" == "-dirty" ] ; then
DIRTY_SUFFIX="_dirty"
else
DIRTY_SUFFIX=""
fi
if [ -n "$DIRTY_SUFFIX" ] || [ -n "$DEV_SUFFIX" ] ; then
DEVDIRTY=true
else
DEVDIRTY=false
fi
# extract interface definition
#
#Q_DECLARE_INTERFACE(CCInterface,
# "eu.atb.ptu.plugin.CCInterface/2.9.0")
# -> extract whole string within quotation marks
INTERFACE_VERSION=$(grep 'eu.atb.ptu.plugin.' ${INTERFACE_DEFINITION})
# get string within quotes:
INTERFACE_VERSION=`echo ${INTERFACE_VERSION} | awk -F \" '{print $2}'`
#
# write version.h
echo " TARGET is: $TARGET"
echo " ARCH is: $ARCH"
echo " "
echo " PluginName: $TARGET"
echo " Interface: $INTERFACE"
echo " InterfaceVersion: $INTERFACE_VERSION"
echo " "
echo " new version is: $VERSION_STRING"
echo " git describe is: $GIT_DESCRIBE"
echo " git branch is: $GIT_BRANCH"
echo " branch-path is: $BRANCH_PATH"
echo " "
echo " dev suffix: $DEV_SUFFIX"
echo " dirty suffix: $DIRTY_SUFFIX"
PLUGIN_VERSION=${VERSION_STRING}
#ATB_QT_GIT_DESCRIBE=${GIT_DESCRIBE}_${GIT_BRANCH}
PLUGIN_GIT_DESCRIBE=${GIT_DESCRIBE}_${BRANCH_PATH}${DEV_SUFFIX}${DIRTY_SUFFIX}
#TARGET=IngenicoZVT_CCPlugin
# build version.h #####################################################################
echo " building new version info (version.h) ..."
echo "#ifndef VERSION_H" > ${VERSION_H}
echo "#define VERSION_H" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "#define INTERFACE_VERSION \"${INTERFACE_VERSION}\"" >> ${VERSION_H}
echo "#define PLUGIN_VERSION \"${PLUGIN_VERSION}\"" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "#define PLUGIN_GIT_DESCRIBE \"${PLUGIN_GIT_DESCRIBE}\"" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "" >> ${VERSION_H}
cat <<EOT >> ${VERSION_H}
const std::string pluginInfoString = R"(
{
"Interface": "${INTERFACE}",
"InterfaceVersion": "${INTERFACE_VERSION}",
"PluginName": "${TARGET}",
"Version": "${PLUGIN_VERSION}",
"git-describe": "${PLUGIN_GIT_DESCRIBE}",
}
)";
EOT
echo "" >> ${VERSION_H}
echo "" >> ${VERSION_H}
if [ ${DEVDIRTY} == "true" ] ; then
echo "#define DEVDIRTY" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "" >> ${VERSION_H}
fi
echo "#define SYSTEM_ARCH \"${ARCH}\"" >> ${VERSION_H}
echo "#define ARCH_${ARCH}" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "" >> ${VERSION_H}
echo "#endif //VERSION_H" >> ${VERSION_H}

View File

@@ -170,7 +170,7 @@ uint8_t epi_getResultOfLastRequest();
// retval: 0: in progress 1: OK 2: error // retval: 0: in progress 1: OK 2: error
void gpi_storeRecPayLoad(uint8_t RdDlen, uint8_t *receivedData); void gpi_storeRecPayLoad(uint8_t RdDlen, uint8_t const *receivedData);
// stored by Datif // stored by Datif
uint16_t epi_getLastPayLoad(uint16_t plBufSiz, uint8_t *payLoad); uint16_t epi_getLastPayLoad(uint16_t plBufSiz, uint8_t *payLoad);

View File

@@ -324,12 +324,18 @@ public:
// Sende Schreibbefehle die bereits vorher asynchron gespeichert wurden // Sende Schreibbefehle die bereits vorher asynchron gespeichert wurden
void send_requests(uint16_t nextWrCmd); void send_requests(uint16_t nextWrCmd);
void sendHighLevel(uint16_t nxtHLCmd); void sendHighLevel(uint16_t nxtHLCmd);
bool areDataValid(void);
signals: signals:
void ResponseRecieved(); void ResponseRecieved();
//the requested data are stored in peripheral image //the requested data are stored in peripheral image
// can be loaded with epi // can be loaded with epi
void datif_templatePrintFinished_OK();
void datif_templatePrintFinished_Err();
void datif_gotNewCoin();
}; };
#endif // CI_H #endif // CI_H

35
DCPlugin/include/hwChk.h Executable file
View File

@@ -0,0 +1,35 @@
#ifndef hwchk_H
#define hwchk_H
#include <stdint.h>
#include <QTabWidget>
#include <QObject>
#include "interfaces.h"
//#include "datIf.h"
#include <QDebug>
#include <QSharedMemory>
#include "hwapi.h"
//class QSharedMemory;
class hwChk : public QObject,
public hwinf
{
Q_OBJECT
// Q_PLUGIN_METADATA(IID "Atb.Psa2020.software.HWapi/1.0" ) //FILE "HWapi.json")
// Q_INTERFACES(hwinf)
//private:
// QSharedMemory *m_sharedMem;
public:
explicit hwChk(QWidget *parent = nullptr);
virtual ~hwChk();
public:
hwinf *HWaccess;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -2,12 +2,9 @@
#define INTERFACE_H #define INTERFACE_H
#include <QtPlugin> #include <QtPlugin>
#include <QStringList>
struct T_emp {
struct T_emp
{
// Fixdata from EMP: // Fixdata from EMP:
uint8_t shaft; // = changer level uint8_t shaft; // = changer level
uint16_t countryCode; uint16_t countryCode;
@@ -34,11 +31,9 @@ struct T_emp
uint8_t pollingRunning; uint8_t pollingRunning;
uint8_t paymentRunning; uint8_t paymentRunning;
}; };
struct Trtc_DateTime struct Trtc_DateTime {
{
uint8_t rtc_hour; uint8_t rtc_hour;
uint8_t rtc_min; uint8_t rtc_min;
uint8_t rtc_sec; uint8_t rtc_sec;
@@ -48,8 +43,7 @@ struct Trtc_DateTime
uint8_t rtc_dayOfWeek; uint8_t rtc_dayOfWeek;
}; };
struct Tprn_hw_state struct Tprn_hw_state {
{
// hardware (IO's) // hardware (IO's)
bool powerRdBk; // prn pwr is on bool powerRdBk; // prn pwr is on
bool rsSwOk; // serial switch (printer or modem) is set to printer bool rsSwOk; // serial switch (printer or modem) is set to printer
@@ -66,8 +60,7 @@ struct Tprn_hw_state
bool badResponse; bool badResponse;
}; };
struct Tprn_currentSettings struct Tprn_currentSettings {
{
uint8_t currFont; uint8_t currFont;
uint8_t currSize; uint8_t currSize;
uint8_t currHeigth; uint8_t currHeigth;
@@ -80,8 +73,7 @@ struct Tprn_hw_state
bool nowAligned; bool nowAligned;
}; };
struct T_dynDat struct T_dynDat {
{
uint8_t licensePlate[8]; uint8_t licensePlate[8];
uint8_t vendingPrice[8]; uint8_t vendingPrice[8];
uint8_t parkingEnd[8]; uint8_t parkingEnd[8];
@@ -92,184 +84,223 @@ struct Tprn_hw_state
uint8_t dynDat7[8]; uint8_t dynDat7[8];
}; };
struct T_vaultRecord {
struct T_vaultRecord
{
// Kassenbeleg (Abrechnungsdatensatz = Kassenwechsel-Datensatz) // Kassenbeleg (Abrechnungsdatensatz = Kassenwechsel-Datensatz)
char startbuffer[4]; // Psa> // never move or change this 1st entry char startbuffer[4]; // Psa> // never move or change this 1st entry
uint16_t AccountingNumber; uint16_t AccountingNumber;
uint16_t CUNU; uint16_t CUNU;
uint16_t MANU; uint16_t MANU;
uint16_t resint1; uint16_t resint1;
//uint16_t resint2; //uint16_t resint2;
char label1buffer[4]; // tim> char label1buffer[4]; // tim>
uint8_t year; uint8_t year;
uint8_t month; uint8_t month;
uint8_t dom; uint8_t dom;
uint8_t hour; uint8_t hour;
uint8_t min; uint8_t min;
uint8_t sec; uint8_t sec;
uint8_t DoW; uint8_t DoW;
uint8_t reschar3; uint8_t reschar3;
char label2buffer[4]; // abs> char label2buffer[4]; // abs>
uint32_t AbsIncome1; uint32_t AbsIncome1;
uint32_t AbsReserve; uint32_t AbsReserve;
uint32_t AbsNrOfCuts; uint32_t AbsNrOfCuts;
//16 //16
char label3buffer[4]; // mw > char label3buffer[4]; // mw >
// Verkauf, Tür zu: // Verkauf, Tür zu:
uint32_t VKcoinsInserted[16]; // nur für Wechsler, soviel wurde eingeworfen uint32_t VKcoinsInserted[16]; // nur für Wechsler, soviel wurde eingeworfen
uint32_t VKcoinsReturned[6]; // nur für Wechsler, Anzahl Münzen pro Typ, soviel wurde zurückgegeben uint32_t VKcoinsReturned[6]; // nur für Wechsler, Anzahl Münzen pro Typ, soviel wurde zurückgegeben
//88 //88
// Service, Tür offen:
// Service, Tür offen: uint16_t ServCoinsInserted[16]; // nur für Wechsler, soviel wurde eingeworfen
uint16_t ServCoinsInserted[16]; // nur für Wechsler, soviel wurde eingeworfen uint16_t ServCoinsReturned[6]; // nur für Wechsler, Anzahl Münzen pro Typ, soviel wurde zurückgegeben
uint16_t ServCoinsReturned[6]; // nur für Wechsler, Anzahl Münzen pro Typ, soviel wurde zurückgegeben uint16_t resint3;
uint16_t resint3; uint16_t resint4;
uint16_t resint4; uint16_t currentTubeContent[6]; // nur für Wechsler, aktueller Füllstand
uint16_t currentTubeContent[6]; // nur für Wechsler, aktueller Füllstand uint16_t resint5;
uint16_t resint5; uint16_t resint6;
uint16_t resint6;
// 56 // 56
char label4buffer[4]; // box>
char label4buffer[4]; // box> uint16_t coinsInVault[16];
uint16_t coinsInVault[16]; uint16_t billsInStacker[8];
uint16_t billsInStacker[8];
// 48 // 48
char label5buffer[4]; // val>
char label5buffer[4]; // val> // actually constant unless exchange rate is changed
// actually constant unless exchange rate is changed uint16_t coinDenomination[16]; // 5..50000 (z.B. 2? sind in Ungarn 760Ft)
uint16_t coinDenomination[16]; // 5..50000 (z.B. 2? sind in Ungarn 760Ft) uint16_t billDenom[8];
uint16_t billDenom[8]; uint16_t tubeDenom[6];
uint16_t tubeDenom[6]; uint16_t exchangeRate;
uint16_t exchangeRate; uint16_t resint9;
uint16_t resint9;
// 64 // 64
char endofblock[4]; // end>
char endofblock[4]; // end>
// 316 byte Block im Speicher // 316 byte Block im Speicher
};
struct T_moduleCondition {
// store conditon of all system components, hold in RAM
// 0 means unknown, not yet tested/used
// 1 means OK
// 50..99 = HINT / Notification
// 100..150 = WARNING
// 200..250 = ERROR
uint8_t ram;
uint8_t intEe;
uint8_t extEe;
uint8_t rtc; // 1: time/date OK 100: time not plausible 200: hardware error
uint8_t boardHw;
uint8_t printer;
uint8_t modem;
uint8_t signal; // 1...99
uint8_t regist; // 100:not 1:reg 2:ping OK 3:gotTime
uint8_t mdbBus;
uint8_t coinChecker; // EMP, OMP or mei-cashflow
uint8_t coinEscrow;
uint8_t mifareReader;
uint8_t creditTerm;
uint8_t coinReject;
uint8_t coinSafe;
uint8_t billSafe;
uint8_t voltage; // 1:11..14V
uint8_t temper;
uint8_t poweronTest;
uint8_t doorState; // 1: alles zu 200: t?r offen + bit1(S) +bit2(CB) + bit3(CB)
uint8_t doorWasOpened; // 1: all doors are closed 200: any door was just opened
uint8_t changer; // can only be tested by usage
uint8_t coinBlocker; // can only be tested by usage
uint8_t billReader; // can only be tested by usage
uint8_t ResetReason;
uint8_t allModulesChecked;
}; };
struct T_moduleCondition struct T_dynamicCondition {
{ char allDoorsDebounced; // 99: undefined, 0=all closed, bit1=upper door open 2=midlle door open 3=lower door open
// store conditon of all system components, hold in RAM char openedAuthorized;
// 0 means unknown, not yet tested/used uint8_t CBinDebounced;
// 1 means OK char upperDoor; // 99: undefined 0:closed 1:open
// 50..99 = HINT / Notification char middleDoor; // 99: undefined 0:closed 1:open
// 100..150 = WARNING char lowerDoor; // 99: undefined 0:closed 1:open
// 200..250 = ERROR char reserve; // not used, always 0
char billBox;
uint8_t structStart; // always first!!! char modeAbrech;
uint8_t ram; // v char onAlarm; // 0:alarm aus 1:alarm 2:alarm mit Sirene 3: Sirenentest
uint8_t intEe; // v char nowCardTest;
uint8_t extEe; // v char nowPayment;
char lastMifCardType;
uint8_t rtc; // 1: time/date OK 100: time not plausible 200: hardware error uint8_t lastSDoorState;
uint8_t boardHw; // v uint8_t lastVDoorState;
uint8_t printer; // v uint8_t lastCBstate; // 99: undefined 0:not there 1:insered
uint8_t modem; // v char paymentInProgress;
char res1;
uint8_t signal; // 1...99 uint16_t U_Batt;
uint8_t regist; // 100:not 1:reg 2:ping OK 3:gotTime uint16_t Temperatur;
uint8_t mdbBus; uint16_t nrCoinsInBox;
uint8_t coinChecker; // EMP, OMP or mei-cashflow uint32_t amountInBox;
uint32_t totalTransVolume;
uint8_t coinEscrow; // v uint32_t totalNrOfVends;
uint8_t mifareReader; // v char jsonValid_config;
uint8_t creditTerm; // not available char jsonValid_device;
uint8_t coinReject; // v char jsonValid_cash;
char jsonValid_print;
uint8_t coinSafe; // v char jsonValid_serial;
uint8_t billSafe; // v char jsonValid_time;
uint8_t voltage; // v // 1:11..14V char lastFileType;
uint8_t temper; // v // 44
uint8_t MifCardHolder[8];
uint8_t poweronTest; uint8_t resultOfLastTemplPrint;
uint8_t doorState; // 1: alles zu 200: t?r offen + bit1(S) +bit2(CB) + bit3(CB) // 0: unknown or printing in progress
uint8_t doorWasOpened; // 1: all doors are closed 200: any door was just opened // 1: OK, doc was printed 2: error, doc was not printed
uint8_t changer; // can only be tested by usage uint8_t lastPrinterStatus;
// 0: printer OK
uint8_t coinBlocker; // can only be tested by usage // bit0: near paper end bit1: no paper
uint8_t billReader; // can only be tested by usage // bit2: temperature error bit3: error head open
uint8_t ResetReason; // bit4: paper jam in cutter
uint8_t allModulesChecked; // bit6: no response bit7: serial rec. error
// bit5: printer not ready
uint8_t alarmState; uint8_t startupTestIsRunning;
uint8_t res11; //54
uint8_t res12;
uint8_t res13;
}; };
struct T_dynamicCondition struct T_extTime {
uint8_t Hours;
uint8_t Min;
uint8_t Sec;
uint8_t Year;
uint8_t Month;
uint8_t Day;
uint8_t DOW;
uint8_t res1;
uint16_t MinOfDay;
uint16_t res2;
uint32_t SecOfDay;
uint8_t isLeapYear;
uint8_t nxtLeapYear;
uint8_t lastLeapYear;
uint8_t hoursOfThisWeek;
uint16_t minutesOfThisWeek;
uint16_t hoursOfThisMonth;
uint16_t daysOfThisYear;
uint16_t GetHoursOfYear;
uint16_t res3;
uint32_t GetMinutesOfYear;
uint8_t getWakeIntvSec;
uint8_t res4;
uint16_t res5;
uint32_t MinutesOfMillenium;
};
typedef uint8_t UCHAR;
typedef uint16_t UINT;
struct T_devices
{ {
// dynamic conditions, change rapidly and frequently // set by master, used(1) or notused (0) or type 2....20
// these are values for the Heartbeat
// T?rschalter entprellt: UCHAR kindOfPrinter; // 0:off 1:Gebe
char upperDoor; // 0:fehlt 1:drin UCHAR kindOfCoinChecker; // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW)
char middleDoor; UCHAR kindOfMifareReader; // by now only stronglink SL025 =1
char lowerDoor; UCHAR suppressSleepMode; // 0:sleep allowed 1: no sleep
char coinBox;
char billBox; UCHAR kindOfModem; // 0:off 1:Sunlink
char modeAbrech; UCHAR kindOfCreditcard; // 0:off 1:Feig NFC
char onAlarm; UCHAR CoinEscrow;
char nowCardTest; UCHAR CoinRejectUnit;
char nowPayment; UCHAR CoinShutter;
char lastMifCardType; UCHAR BillAcceptor;
char openedAuthorized; UCHAR usevaultLock;
char allDoorsDebounced; UCHAR autoAlarm; // 1: switch on siren for 1min in doors opened unauthorized
uint8_t lastSDoorState; UCHAR autoOpen; // 1: open door covers after valid ATBcard
uint8_t lastVDoorState; UCHAR printAccReceipt; // 0/1
uint8_t CBinDebounced; UCHAR printDoorReceipt;
uint8_t lastCBstate; UCHAR printTokenTicket;
char paymentInProgress; UINT VaultFullWarnLevel;
char res1; UINT VaultFullErrorLevel;
char res2;
char res3;
uint16_t U_Batt;
uint16_t Temperatur;
uint16_t cash_storedaccNumbers[8]; // List all stored accounting numbers in ext. eeprom
uint16_t nrCoinsInBox;
uint16_t resui1;
uint32_t amountInBox;
uint32_t amountJustPaid;
uint16_t lastInsCoinType; // wahrscheinlich uchar
uint16_t resui2;
uint32_t totalTransVolume;
uint32_t totalNrOfVends;
}; };
class hwinf class hwinf {
{
public: public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP}; enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
enum class FileTypeJson {CONFIG=1, DEVICE, CASH, SERIAL, TIME, PRINTER}; enum class FileTypeJson {CONFIG=1, DEVICE, CASH, SERIAL, TIME, PRINTER};
virtual ~hwinf() {} virtual ~hwinf() {}
virtual QStringList dc_getStatus() const = 0;
// $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// Use serial interface and protocol stack in Cashagent-Library // Use serial interface and protocol stack in Cashagent-Library
@@ -310,12 +341,12 @@ public:
QVector<int> templateIdx, QVector<int> templateIdx,
QVector<QString> fnames, QVector<QString> fnames,
QString br, QString br,
QString serial) const = 0; QString serial = QString()) const = 0;
virtual bool dc_printTemplate(enum FileTypeJson type, virtual bool dc_printTemplate(enum FileTypeJson type,
QVector<int> templateIdx, QVector<int> templateIdx,
QString br, QString br,
QString serial) const = 0; QString serial = QString()) const = 0;
virtual void dc_autoRequest(bool on) const =0; virtual void dc_autoRequest(bool on) const =0;
// on = true: select that all READ-Requests are sent automatically // on = true: select that all READ-Requests are sent automatically
@@ -1371,6 +1402,8 @@ public:
*/ */
virtual bool rtc_getExtendedTime(struct T_extTime *exTime) const=0;
virtual bool sys_runCompleteTest(void) const=0; virtual bool sys_runCompleteTest(void) const=0;
// warning: lasts 20s in one pace // warning: lasts 20s in one pace
// return true if sending, false if cmd-stack is full // return true if sending, false if cmd-stack is full
@@ -1395,15 +1428,18 @@ public:
// nr = 1..32 // nr = 1..32
// return true if sending, false if cmd-stack is full // return true if sending, false if cmd-stack is full
virtual void log_getHoldAccountNumbers(uint32_t *accNr ) const=0; virtual void log_getHoldAccountNumbers(uint8_t *nrOfVals, uint16_t *accNr ) const=0;
// returns all acc nrs of the backuped vault records // returns all acc nrs of the backuped vault records
// use: uint32_t backupedAccNumbers[8] // use: uint16_t backupedAccNumbers[8]
virtual bool log_selectVaultRecord(uint16_t accountNr ) const=0; virtual bool log_selectVaultRecord(uint16_t accountNr ) const=0;
// return true if sending, false if cmd-stack is full // return true if sending, false if cmd-stack is full
// and trigger transfer
//request, isAvailable virtual bool log_chkIfVaultRecordAvailable(void) const=0;
virtual void log_getVaultRecord(struct T_vaultRecord *retVR) const=0; // return true if completly received
virtual bool log_getVaultRecord(struct T_vaultRecord *retVR) const=0;
// which was selected by: log_selectVaultRecord() // which was selected by: log_selectVaultRecord()
// to be forwarded to Ismas // to be forwarded to Ismas
@@ -1413,7 +1449,8 @@ virtual void log_getVaultRecord(struct T_vaultRecord *retVR) const=0;
virtual bool prn_printTestTicket(void) const=0; virtual bool prn_printTestTicket(void) const=0;
// return true if sending to DC OK, false if cmd-stack is full // return true if sending to DC OK, false if cmd-stack is full
virtual bool cash_startPayment(uint16_t amount) const=0; virtual bool cash_startPayment(uint32_t amount) const=0;
// 17.4.23TS: extended to 32bit
virtual uint32_t getInsertedAmount(void) const=0; virtual uint32_t getInsertedAmount(void) const=0;
@@ -1437,18 +1474,23 @@ virtual void log_getVaultRecord(struct T_vaultRecord *retVR) const=0;
// conclude payment process and return all inserted coins // conclude payment process and return all inserted coins
virtual uint8_t mif_getCardType(QString *cardholder) const=0;
virtual uint8_t mif_getCardType(QString cardholder) const=0;
// return 1,2,3,4 = upper, lower access card, printer test, coin test // return 1,2,3,4 = upper, lower access card, printer test, coin test
// cardholder: 7byte Name-String // cardholder: 7byte Name-String
virtual uint64_t sys_getWakeSource(void) const =0; virtual uint64_t sys_getWakeSource(void) const =0;
// retval: 6 bytes, bit coded, 1=event keeps DC awake // retval: 6 bytes, bit coded, 1=event keeps DC awake
//virtual void sys_getDeviceConditions(struct T_moduleCondition *devCond) const=0; virtual uint8_t sys_getWakeReason(void) const=0;
// Master was woken by following reason:
// 1: MDB Event
// 2: Coin Event
// ( 3: Master Event) - will not set the wake line
// ( 4: 32s pulse) - will not set the wake line
// 5: Door Event
// ( 6: Diag Event) - will not set the wake line
// 7: 30min-Pulse for HB
virtual void sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const=0; virtual void sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const=0;
/* /*
@@ -1485,8 +1527,7 @@ virtual void log_getVaultRecord(struct T_vaultRecord *retVR) const=0;
*/ */
virtual void sys_getDeviceConditions(struct T_moduleCondition *devCond) const=0;
//virtual void sys_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) const=0;
virtual void sys_getDynMachineConditions(uint8_t *leng, uint8_t *data) const=0; virtual void sys_getDynMachineConditions(uint8_t *leng, uint8_t *data) const=0;
/* /*
@@ -1552,6 +1593,85 @@ virtual void log_getVaultRecord(struct T_vaultRecord *retVR) const=0;
*/ */
virtual void sys_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) const=0;
// content of Cashbox
virtual uint32_t cash_getAmountInVault(void) const=0;
virtual uint16_t cash_getNrCoinsInVault(void) const=0;
virtual uint8_t prn_getPrintResult() const=0;
// in case of print-error get detailed error:
virtual uint8_t prn_getCurrentPrinterState() const=0;
// 0: printer OK
// bit0: near paper end bit1: no paper
// bit2: temperature error bit3: error head open
// bit4: paper jam in cutter
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
virtual void sys_sendDeviceParameter(struct T_devices *deviceSettings) const=0;
virtual void sys_restoreDeviceParameter(struct T_devices *deviceSettings) const=0;
/* ---------------------------------------------------------------------------------------------
// ------------ supervise all hardware components
// ------------ assess the machine state
1. check if DC startup test is through, retrigger if not
2. get results and find errors
3. in case of error check if component is used (e.g. billreader is seldom used)
4: check doors
5. return value: 0: no response from DC
1: no Test results and Test not running. need retrigger!
2: state not clear by now, test ongoing, wait
3: Service or battery door is open, goto INTRUSION MODE
from here: after valid ID-card goto SERVICE MODE
4: vault door is open, goto INTRUSION MODE
from here: after valid ID-card and vault door closed goto TEST MODE
in TEST MODE: complete system check decides if vending mode allowed
5: All doors are closed but errors found,
goto OOO MODE (out-of-order)
from here: run system test until problem is fixed
6: All doors are closed, no error, maybe warnings,
goto VENDING MODE (normal operation)
(priority sinks from 0 to 6)
--------------------------------------------------------------------------------------------- */
virtual uint8_t sys_componentAssessment(void) const=0;
// this function decides if vending mode is possible, independant from door
// return >0 in case of error
// is inncluded in sys_superviseSystem
virtual uint8_t sys_superviseSystem(void) const=0;
// this function proofs if vending is possible depending of doors state
virtual uint8_t sys_getSystemErrors(void) const=0;
// retrigger System-Check with:
// bool hwapi::sys_runCompleteTest(void) const
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
signals:
virtual void hwapi_templatePrintFinished_OK(void) const=0;
virtual void hwapi_templatePrintFinished_Err(void) const=0;
virtual void hwapi_gotNewCoin(void) const=0;
virtual void hwapi_vendStopByMax(void) const=0;
virtual void hwapi_vendStopByPushbutton(void) const=0;
}; };
@@ -1569,10 +1689,15 @@ virtual void log_getVaultRecord(struct T_vaultRecord *retVR) const=0;
// 29.03.2023: V3.1 some extensions for PSA1256_ptu5, // 29.03.2023: V3.1 some extensions for PSA1256_ptu5,
// V3.2 Bootloader improvement // V3.2 Bootloader improvement
// 12.04.2023: V3.3 new features extended: loading and using Json-files, cash-collection, cash-data-logging // 12.04.2023: V3.3 new features extended: loading and using Json-files, cash-collection, cash-data-logging
// 14.04.2023: V3.4 new features extended: sys_getDynMachineConditions, sys_getDeviceConditions and
// rtc_getExtendedTime return struct in addition. New function to select and get VaultRecord
//
//#define HWINF_iid "Atb.Psa2020.software.HWapi/3.1" //#define HWINF_iid "Atb.Psa2020.software.HWapi/3.1"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.1" //#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.1"
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.3" //#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.3"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.4"
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.5"

View File

@@ -218,7 +218,10 @@ bool sendFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8
bool sendFDcmd_get(uint8_t *nextWrCmd, uint8_t *nextRdCmd, uint8_t *blockNum, uint8_t *dat1, uint8_t *dat2, uint8_t *dat3, uint8_t *dat4); bool sendFDcmd_get(uint8_t *nextWrCmd, uint8_t *nextRdCmd, uint8_t *blockNum, uint8_t *dat1, uint8_t *dat2, uint8_t *dat3, uint8_t *dat4);
uint8_t check4FDshortCmd(void); uint8_t check4FDshortCmd(void);
// returns number of waiting command // returns number of waiting command, maxFDCMD_STACKDEPTH
uint8_t check4freeFDshortCmd(void);
// returns number of free places in short-command stack
#define FDLONG_STACKDEPTH 16 #define FDLONG_STACKDEPTH 16
void longFDcmd_clrStack(void); void longFDcmd_clrStack(void);
@@ -230,6 +233,17 @@ bool longFDcmd_get(uint8_t *nextWrCmd, uint8_t *nextRdCmd, uint8_t *blockNum, ui
uint8_t check4FDlongCmd(void); uint8_t check4FDlongCmd(void);
// returns number of waiting command // returns number of waiting command
uint8_t check4freeFDlongCmd(void);
// returns number of free places in long-command stack
uint8_t epi_store64BdevParameter(uint8_t length, uint8_t *buf);
// HWapi writes data to be stored
uint8_t epi_restore64BdevParameter(uint8_t *length, uint8_t *buf);
#endif #endif

View File

@@ -0,0 +1,296 @@
#ifndef SHARED_MEM_BUFFER_INCLUDED_H
#define SHARED_MEM_BUFFER_INCLUDED_H
#include <cinttypes>
#include <atomic>
#include <QSharedMemory>
struct SharedMemBuffer {
struct rs {
char comportName[16]; // z.B. "COM48"
char baudStr[16]; // z.B. "19200"
int baudNr; // 0...5 oder -1
uint8_t connect; // 0,1
bool portIsOpen;
} rs;
char AutoEmissionOn; // 1: zyklisch Anfragen zum Slave senden
struct datif {
uint16_t sendingPeriod;
bool sendingPer_changed;
} datif;
#if 0
// controlBus.cpp
char txt4comStateLine[32];
char txt4HsStateLine[32];
char txt4masterStateLine[32];
char txt4resultStateLine[32];
char txt4dataLine[32];
char txt4datifReceive[32];
char txt4diagWindow[32];
char sndTxt4diagWindow[32];
bool Sdata_serialTestResult[32];
uint8_t Sdata_pProtResultOk[32];
uint16_t Sdata_receivedDataLength[32];
uint8_t Sdata_receivedDataBlock[64];
// datif.cpp
uint8_t dif_dataStep;
uint8_t dif_scanStep;
uint8_t RDBLKNR;
uint8_t datif_OutCmdpara1;
uint8_t datif_OutCmdpara2;
uint8_t datif_OutCmdpara3;
uint8_t datif_OutCmdpara4;
uint16_t datif_OutCmdpara5;
uint32_t datif_OutCmdpara6;
uint8_t cycl_running;
// dcBL.cpp
uint8_t dcBL_LastBLcmd; // stored the last sent cmd in order to analys response
uint8_t dcBL_AtbBinFile[300000];
uint32_t dcBL_fileSize;
uint16_t dcBL_nrOfBlocks;
uint16_t dcBL_fileCrc;
uint8_t dcBL_myBuf[300000]; // same content like "dcBL_AtbBinFile" but bytewise
char BlResp[50][32];
uint8_t dcBL_step;
uint8_t dcBL_state;
uint16_t dcBL_BlkCtr;
uint16_t dcBL_cyclCtr;
uint16_t repeatCtr;
uint8_t Sdata_rawData[150];
uint8_t Sdata_LengthRawData;
// hwapi.cpp
uint16_t hwapi_shutterTime;
char ticketTemplate[1024];
// sendWRcmd.cpp
uint16_t nextAsynchsendCmd0[16];
uint8_t nrOfCmdsInQueue;
uint16_t nextAsynchsendCmd4[8];
uint8_t nextCmd4para1[8];
uint8_t nextCmd4para2[8];
uint8_t nextCmd4para3[8];
uint8_t nextCmd4para4[8];
uint8_t nrOfCmds4InQueue;
uint16_t nextAsynchsendCmd8[4];
uint8_t nextCmd8para1[4];
uint8_t nextCmd8para2[4];
uint16_t nextCmd8para3[4];
uint32_t nextCmd8para4[4];
uint8_t nrOfCmds8InQueue;
uint8_t sendAsynchDataBuf[160]; // no stack, only ONE buffer
uint8_t sendAsyDatLen;
uint8_t Sdata_mdbSendBuffer[64];
uint8_t Sdata_mdbSendLen;
uint8_t prnDataParameters[4];
uint8_t prnDataBufferUser;
char Sdata_PRN_TEXT[20][64];
uint8_t pPrnDataBuff; // points to next PRINTER_BLOCK
uint8_t nextFDwrCmd[16];
uint8_t nextFDrdCmd[16];
uint8_t nextFDblkNr[16];
uint8_t nextFDpara1[16];
uint8_t nextFDpara2[16];
uint8_t nextFDpara3[16];
uint8_t nextFDpara4[16];
uint8_t p_nextFDcmdsInQueue;
uint8_t longFDwrCmd[16];
uint8_t longFDrdCmd[16];
uint8_t longFDblkNr[16];
uint8_t longFDlength[16];
uint8_t longFDpara[16][64];
uint8_t p_longFDcmdsInQueue;
// storeInData.cpp
bool indat_savePrnPwr;
bool indat_saveMifPwr;
bool indat_MdbIsOn;
#endif
uint8_t ndbs;
uint8_t pari;
uint8_t nsb;
uint8_t br;
#define MAXNROF_GENSTR 16
char genStrings[MAXNROF_GENSTR][64];
#define MAXNROF_AI 4
uint16_t AI_val[MAXNROF_AI];
struct DigitalInputs {
uint8_t doorSwitch;
uint8_t vaultSwitch;
uint8_t lockSwitch;
uint8_t opto;
uint8_t aux;
bool wakeFromPtu;
bool wakeFromMdb;
bool wakeFromModem;
bool PrnReady;
bool CoinAttach;
bool CoinEscrowOpen;
bool mifCardTap;
bool contactPwrOn;
bool mifarePwrOn;
bool rdbk_mdbTxd;
bool AuxPwrOn;
bool gsmPwrOn;
bool creditPwrOn;
bool printerPwrOn;
bool mdbPwrOn;
bool rejMot_home;
uint8_t npe_sensor;
} din;
struct DigitalOutputs {
uint8_t mbdRxTst;
uint8_t motorBits;
uint8_t serialSwitch; // serial drv on/off, Serial mux1, Serial mux2
uint8_t ledsAndFan;
uint8_t laermUndRelay;
uint8_t ptuWake;
uint8_t auxPower;
uint8_t coinShutter;
uint8_t coinEscrow;
uint8_t printerPower;
} dout;
struct Sdata {
#define NROFMIFSTATEBYTES 40
#define PRN_STATE_ARRAY_SIZE 20
#define PRN_STATE_FONT_SIZE 20
uint8_t MIF_STATE[NROFMIFSTATEBYTES];
uint8_t MIF_DATA[12][64];
uint8_t PRN_STATE[PRN_STATE_ARRAY_SIZE];
uint8_t PRN_FONTS[PRN_STATE_FONT_SIZE];
bool mdb_busRdy;
bool mdb_V12on;
bool mdb_V5on;
uint8_t mdbNrOfRecData;
uint8_t RecBuff[40];
uint8_t empNrOfsettings;
uint8_t emp_settingsBuff[66];
uint8_t NrOfDeviceSetting;
uint8_t DeviceSettingBuff[66];
uint8_t NrOfMachineIDSetting;
uint8_t NrOfMachineIDBuff[66];
uint64_t slaveUID;
uint8_t UIDstr[8];
#define MAXNROF_MEASURE 4
uint32_t measurement[MAXNROF_MEASURE];
bool serialTestResult;
uint8_t pProtResultOk;
uint16_t receivedDataLength;
uint8_t receivedDataBlock[64];
} Sdata;
uint8_t mif_cardType;
uint8_t mif_cardHolder[8];
#define MEMDEPTH_GOTCOINS (16)
struct T_coin {
uint8_t valid;
uint8_t signal;
uint8_t error;
uint8_t pad;
uint16_t value;
} gotCoin[MEMDEPTH_GOTCOINS];
uint8_t ctr_gotCoin;
struct store {
uint32_t insertedAmount;
uint16_t lastCoinType[64];
uint16_t lastCoinValue[64];
uint64_t wakeSrc;
uint8_t rbDevParamLen;
uint8_t rbDevParams[66];
uint8_t deviceCondLen;
uint8_t deviceCond[66];
uint8_t machCondLen;
uint8_t machCond[66];
uint8_t DcBackupNrOfAccNr;
uint16_t DcBackupAccNr[16]; // z.Z. nur 8
uint8_t gotNrBlocksOfVaultRec;
uint8_t vaultrecord[360];
uint32_t amount;
uint16_t nrOfCoins;
bool dcDataValid;
uint8_t wakeReason;
} store;
struct T_globTime {
// Reihenfolge nicht vertauschen!!!!!
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t Year;
uint8_t Month;
uint8_t DayOfMonth;
uint8_t DayOfWeek; // 1=monday...7
uint8_t reserve1;
uint16_t MinutesOfToday;
uint16_t reserve2;
uint32_t SecondsOfToday;
uint8_t IsLeapyear;
uint8_t nextLeap;
uint8_t lastLeap;
uint8_t hoursOfWeek;
uint16_t minOfWeek;
uint16_t hoursOfMonth;
uint16_t minOfMonth;
uint16_t dayOfYear;
uint16_t hoursOfYear;
uint16_t reserve3;
uint32_t minOfYear;
uint8_t squareOutMode;
uint8_t free1;
uint16_t reserve4;
uint32_t minOfMillenium;
// bis hierher 44byts
uint32_t free2;
uint32_t free3;
uint32_t free4;
} getGlobalTime;
static QSharedMemory *getShm(std::size_t s = 0);
static SharedMemBuffer *getData() {
return (SharedMemBuffer *)getShm()->data();
}
static SharedMemBuffer const *getDataConst() {
return (SharedMemBuffer const *)getShm()->data();
}
#if 0
static std::atomic<bool> __sharedMemLocked;
static bool sharedMemLocked() {
return __sharedMemLocked;
}
static void setSharedMemLocked() {
__sharedMemLocked = true;
}
static void setSharedMemUnlocked() {
__sharedMemLocked = false;
}
#endif
};
#endif // SHARED_MEM_BUFFER_INCLUDED_H

View File

@@ -3,12 +3,12 @@
#define STOREINDATA_H #define STOREINDATA_H
#include <stdint.h> #include <stdint.h>
#include "tslib.h" //#include "tslib.h"
#include <QString> #include <QString>
#define MAXNROF_AO 3 #define MAXNROF_AO 3
#define MAXNROF_GENSTR 16 //#define MAXNROF_GENSTR 16
#define MAXNROF_CONTR_PORTS 11 #define MAXNROF_CONTR_PORTS 11
#define MAXNROF_DIports 2 #define MAXNROF_DIports 2
#define MAXNROF_DOports 2 #define MAXNROF_DOports 2
@@ -32,9 +32,6 @@ bool indat_isMifareOn();
void indat_storeMDBisOn(bool isOn); void indat_storeMDBisOn(bool isOn);
bool indat_isMdbOn(); bool indat_isMdbOn();
void gpi_storeSlaveSerParams(uint8_t slaveBaudRate, uint8_t NrDataBits, void gpi_storeSlaveSerParams(uint8_t slaveBaudRate, uint8_t NrDataBits,
uint8_t parity, uint8_t NrStopBits); uint8_t parity, uint8_t NrStopBits);
@@ -43,23 +40,16 @@ void epi_getSlaveSerParams(uint8_t *slaveBaudRate, uint8_t *NrDataBits,
QString epi_getSlaveParamSTR(); QString epi_getSlaveParamSTR();
void gpi_storeGenerals(uint8_t genNr, QString text); void gpi_storeGenerals(uint8_t genNr, QString text);
// 0=HW 1=SW 2=State // 0=HW 1=SW 2=State
QString epi_loadGenerals(uint8_t genNr); QString epi_loadGenerals(uint8_t genNr);
// genNr=0=HW 1=SW 2=State // genNr=0=HW 1=SW 2=State
void gpi_storeUID(uint8_t *buf8byteUid); void gpi_storeUID(uint8_t const *buf8byteUid);
// buffer size: 8 byte // buffer size: 8 byte
void epi_getUIDdec(uint8_t *buf8byteUid); void epi_getUIDdec(uint8_t *buf8byteUid);
// buffer size: 8 byte // buffer size: 8 byte
QString epi_getUIDstr(); QString epi_getUIDstr();
@@ -89,7 +79,7 @@ void epi_getSpecialYearTimeDate(uint16_t *DayOfYear, uint16_t *HoursOfYear, uint
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
#define MAXNROF_AI 4 // #define MAXNROF_AI 4
void gpi_storeAIs(uint8_t aiNr, uint16_t val); // rs -> Sdata void gpi_storeAIs(uint8_t aiNr, uint16_t val); // rs -> Sdata
@@ -138,185 +128,119 @@ void gpi_storeDI_optos(uint8_t indatOpto);
uint8_t epi_getDI_optos(void); uint8_t epi_getDI_optos(void);
// bit0: opto in 1 1: opto in 2 // bit0: opto in 1 1: opto in 2
void gpi_storeDI_auxIn(uint8_t indatAuxIn); uint8_t gpi_storeDI_auxIn(uint8_t indatAuxIn); // Aux0...5
// Aux0...5 uint8_t epi_getDI_auxIn(void); // bit0: auxin 1 ... 5: auxin 6
uint8_t epi_getDI_auxIn(void);
// bit0: auxin 1 ... 5: auxin 6
void gpi_storeDI_ptuWake(uint8_t indat);
bool gpi_storeDI_ptuWake(bool w);
bool epi_getDI_ptuWake(void); bool epi_getDI_ptuWake(void);
void gpi_storeDI_mbdWake(uint8_t indat); bool gpi_storeDI_mbdWake(bool w);
bool epi_getDI_mdbWake(void); bool epi_getDI_mdbWake(void);
void gpi_storeDI_prnReady(uint8_t indat); bool gpi_storeDI_prnReady(bool ready);
bool epi_getDI_prnReady(void); bool epi_getDI_prnReady(void);
void gpi_storeDI_CoinAttach(uint8_t indat); bool gpi_storeDI_CoinAttach(bool attach);
bool epi_getDI_CoinAttach(void); bool epi_getDI_CoinAttach(void);
void gpi_storeDI_CoinEscrow(uint8_t indat); bool gpi_storeDI_CoinEscrow(bool ce);
bool epi_getDI_CoinEscrow(void); bool epi_getDI_CoinEscrow(void);
void gpi_storeDI_mifareCardTapped(uint8_t indat); bool gpi_storeDI_mifareCardTapped(bool tapped);
bool epi_getDI_mifareCardTapped(void); bool epi_getDI_mifareCardTapped(void);
void gpi_storeDI_modemWake(uint8_t indat); bool gpi_storeDI_modemWake(bool w);
bool epi_getDI_modemWake(void); bool epi_getDI_modemWake(void);
bool gpi_storeDI_contactPowerIsOn(bool on);
void gpi_storeDI_contactPowerIsOn(bool di_contact_PwrOn);
bool epi_getDI_contactPwr(void); bool epi_getDI_contactPwr(void);
void gpi_storeDI_MifarePowerIsOn(bool di_mifare_PwrOn); bool gpi_storeDI_MifarePowerIsOn(bool on);
bool epi_getDI_mifarePwr(void); bool epi_getDI_mifarePwr(void);
void gpi_storeDI_readbackMdbTxD(bool di_rdbkMdbTxd); bool gpi_storeDI_readbackMdbTxD(bool rdbkMdbTxd);
bool epi_getDI_mdbTxd(void); bool epi_getDI_mdbTxd(void);
void gpi_storeDI_AuxPowerIsOn(bool di_Aux_PwrOn); bool gpi_storeDI_AuxPowerIsOn(bool on);
bool epi_getDI_auxPwr(void); bool epi_getDI_auxPwr(void);
void gpi_storeDI_GsmPowerIsOn(bool di_gsm_PwrOn); bool gpi_storeDI_GsmPowerIsOn(bool on);
bool epi_getDI_gsmPwr(void); bool epi_getDI_gsmPwr(void);
void gpi_storeDI_CreditPowerIsOn(bool di_credit_PwrOn); bool gpi_storeDI_CreditPowerIsOn(bool on);
bool epi_getDI_creditPwr(void); bool epi_getDI_creditPwr(void);
void gpi_storeDI_PrinterPowerIsOn(bool di_printer_PwrOn); bool gpi_storeDI_PrinterPowerIsOn(bool on);
bool epi_getDI_printerPwr(void); bool epi_getDI_printerPwr(void);
void gpi_storeDI_MdbPowerIsOn(bool di_mdb_PwrOn); bool gpi_storeDI_MdbPowerIsOn(bool on);
bool epi_getDI_mdbPwr(void); bool epi_getDI_mdbPwr(void);
bool gpi_storeDI_rejMot_home(bool reject);
void gpi_storeDI_rejMot_home(bool di);
bool epi_getDI_rejectMotor_homepos(void); bool epi_getDI_rejectMotor_homepos(void);
void gpi_storeDI_paperLow(uint8_t di); uint8_t gpi_storeDI_paperLow(uint8_t di);
uint8_t epi_getDI_npe_sensor(void); uint8_t epi_getDI_npe_sensor(void);
// 0: Sensor sees paper 1: no paper 99: off // 0: Sensor sees paper 1: no paper 99: off
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// readback digital outputs // readback digital outputs
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
void gpi_storeDO_mdbRxTst(uint8_t do_mbdRxTst); uint8_t gpi_storeDO_mdbRxTst(uint8_t do_mbdRxTst);
bool epi_getDO_mdbRxTestOut(void); bool epi_getDO_mdbRxTestOut(void);
uint8_t gpi_storeDO_motorOutputs(uint8_t Pwr);
void gpi_storeDO_motorOutputs(uint8_t Pwr);
uint8_t epi_getDO_motorOuts(void); uint8_t epi_getDO_motorOuts(void);
// bit0: upper lock forward bit 1 backward // bit0: upper lock forward bit 1 backward
// bit2: lower lock forward bit 3 backward // bit2: lower lock forward bit 3 backward
uint8_t gpi_storeDO_serialSwitch(uint8_t state);
void gpi_storeDO_serialSwitch(uint8_t state);
// serial drv on/off, Serial mux1, Serial mux2 // serial drv on/off, Serial mux1, Serial mux2
uint8_t epi_getDO_serialSwitch(void); uint8_t epi_getDO_serialSwitch(void);
// serial drv on/off, Serial mux1, Serial mux2 // serial drv on/off, Serial mux1, Serial mux2
bool epi_getDO_serialDriverIsOn(void); bool epi_getDO_serialDriverIsOn(void);
bool epi_getDO_serialMux1isSetToPrinter(void); bool epi_getDO_serialMux1isSetToPrinter(void);
// mux1 off: serial is switched to printer // mux1 off: serial is switched to printer
bool epi_getDO_serialMux1isSetToModem(void); bool epi_getDO_serialMux1isSetToModem(void);
// mux1 on: serial is switched to modem // mux1 on: serial is switched to modem
bool epi_getDO_serialMux2isSetToCredit(void); bool epi_getDO_serialMux2isSetToCredit(void);
// mux2 off: serial is switched to credit card terminal // mux2 off: serial is switched to credit card terminal
bool epi_getDO_serialMux2isSetToMifare(void); bool epi_getDO_serialMux2isSetToMifare(void);
// mux2 on: serial is switched to mifare reader // mux2 on: serial is switched to mifare reader
uint8_t gpi_storeDO_ledsAndFan(uint8_t ledState);
void gpi_storeDO_ledsAndFan(uint8_t ledState);
bool epi_getDO_led_coin(void); bool epi_getDO_led_coin(void);
bool epi_getDO_led_front(void); bool epi_getDO_led_front(void);
bool epi_getDO_led_ticket(void); bool epi_getDO_led_ticket(void);
bool epi_getDO_led_pin(void); bool epi_getDO_led_pin(void);
bool epi_getDO_led_start(void); bool epi_getDO_led_start(void);
bool epi_getDO_led_inside(void); bool epi_getDO_led_inside(void);
bool epi_getDO_fan(void); bool epi_getDO_fan(void);
void gpi_storeDO_sirenAndRelay(uint8_t sirenRelay); uint8_t gpi_storeDO_sirenAndRelay(uint8_t sirenRelay);
bool epi_getDO_sirene(void); bool epi_getDO_sirene(void);
bool epi_getDO_relay(void); bool epi_getDO_relay(void);
void gpi_storeDO_ptuWake(uint8_t state); uint8_t gpi_storeDO_ptuWake(uint8_t state);
bool epi_getDO_ptuWake(void); bool epi_getDO_ptuWake(void);
void gpi_storeDO_auxPower(uint8_t pwr); uint8_t gpi_storeDO_auxPower(uint8_t pwr);
bool epi_getDO_auxPower(void); bool epi_getDO_auxPower(void);
uint8_t gpi_storeDO_coinShutter(uint8_t state);
void gpi_storeDO_coinShutter(uint8_t state);
bool epi_getDO_coinShutterOpen(void); bool epi_getDO_coinShutterOpen(void);
bool epi_getDO_coinShutterTest(void); bool epi_getDO_coinShutterTest(void);
uint8_t gpi_storeDO_coinEscrow(uint8_t state);
void gpi_storeDO_coinEscrow(uint8_t state);
uint8_t epi_getDO_coinEscrow(void); uint8_t epi_getDO_coinEscrow(void);
// retval: 1:return flap is open 2:take flap is open 0:closed // retval: 1:return flap is open 2:take flap is open 0:closed
uint8_t gpi_storeDO_printerPwrOn(uint8_t state);
void gpi_storeDO_printerPwrOn(uint8_t state);
uint8_t epi_getDO_printerPwr(void); uint8_t epi_getDO_printerPwr(void);
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
// counterchecks, make sure that DC-outputs are correct // counterchecks, make sure that DC-outputs are correct
@@ -363,21 +287,14 @@ bool epi_cntchk_Mot2Fon(void);
uint8_t gpi_storeMdbRecData(uint8_t length, uint8_t *buf); uint8_t gpi_storeMdbRecData(uint8_t length, uint8_t *buf);
// datif store received mdb data // datif store received mdb data
uint8_t epi_getMdbResponse(void); uint8_t epi_getMdbResponse(void);
// 0=no response 1=ACK 2=NAK 3=ACK with data // 0=no response 1=ACK 2=NAK 3=ACK with data
uint8_t epi_getMdbRecLength(void); uint8_t epi_getMdbRecLength(void);
// 0...31 // 0...31
uint8_t epi_restoreMdbRecData(uint8_t *buf); uint8_t epi_restoreMdbRecData(uint8_t *buf);
// hwapi reads received mdb data from PI // hwapi reads received mdb data from PI
uint8_t gpi_storeMifReaderStateAndCardType(uint8_t const *buf);
uint8_t gpi_storeMifReaderStateAndCardType(uint8_t *buf);
/* data description: /* data description:
byte 0: current read state: 0=power off 1=reader-fault 2=ready byte 0: current read state: 0=power off 1=reader-fault 2=ready
@@ -401,41 +318,24 @@ byte 32: result, always 0
uint8_t epi_restoreMifState(uint8_t *buf, uint8_t maxBufferSize); uint8_t epi_restoreMifState(uint8_t *buf, uint8_t maxBufferSize);
// retval 0=OK 1=error host buffer too small // retval 0=OK 1=error host buffer too small
bool gpi_storeMifCardData(uint8_t blkNr, uint8_t const *receivedData);
void gpi_storeMifCardData(uint8_t blkNr, uint8_t *receivedData);
// blkNr=0...11 receivedData[64] // blkNr=0...11 receivedData[64]
uint8_t epi_restoreMifData(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize); uint8_t epi_restoreMifData(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize);
// blkNr=0...11 return buf[64] // blkNr=0...11 return buf[64]
// retval: 1=error 0=OK // retval: 1=error 0=OK
#define pi_prnStateArraySize 20
#define pi_prnFontArraySize 20
void epi_restorePrinterState(uint8_t *buf); void epi_restorePrinterState(uint8_t *buf);
void gpi_storePrinterState(uint8_t const *buf);
void gpi_storePrinterState(uint8_t *buf);
void epi_restorePrinterFonts(uint8_t *buf); void epi_restorePrinterFonts(uint8_t *buf);
void gpi_storePrinterFonts(uint8_t const *buf);
void gpi_storePrinterFonts(uint8_t *buf); bool gpi_storeMdbState(bool busReady, bool V12on, bool V5on);
void gpi_storeMdbState(uint8_t busReady, uint8_t V12on, uint8_t V5on );
bool epi_restoreMdbBusReady(void); bool epi_restoreMdbBusReady(void);
bool epi_restoreMdbV12Ready(void); bool epi_restoreMdbV12Ready(void);
bool epi_restoreMdbV5Ready(void); bool epi_restoreMdbV5Ready(void);
void gpi_storeMdbResponse(uint8_t leng, uint8_t const *data);
void gpi_storeMdbResponse(uint8_t leng, uint8_t *data);
void epi_restoreMdbResponse(uint8_t *leng, uint8_t *data); void epi_restoreMdbResponse(uint8_t *leng, uint8_t *data);
// last received mdb answer (from mdb device) // last received mdb answer (from mdb device)
// only needed if a special command was sent directly // only needed if a special command was sent directly
@@ -444,12 +344,9 @@ void epi_restoreMdbResponse(uint8_t *leng, uint8_t *data);
// DB2: nr of received (payload) data bytes (apart from ACK, can be 0....34) // DB2: nr of received (payload) data bytes (apart from ACK, can be 0....34)
// DB3...DB38: rec.data (payload) // DB3...DB38: rec.data (payload)
void gpi_storeEmpSettings(uint8_t leng, uint8_t const *data);
void gpi_storeEmpSettings(uint8_t leng, uint8_t *data);
void epi_restoreEmpSettings(uint8_t *leng, uint8_t *data); void epi_restoreEmpSettings(uint8_t *leng, uint8_t *data);
/* /*
void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t *data); void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t *data);
@@ -463,65 +360,64 @@ void epi_restoreEmpCoinSignal(uint8_t *leng, uint8_t *data);
void epi_clearEmpCoinSignal(); void epi_clearEmpCoinSignal();
*/ */
#define MEMDEPTH_GOTCOINS 16
void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t *data); void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t const *data);
uint8_t epi_isNewCoinLeft(void); uint8_t epi_isNewCoinLeft(void);
// retval: 0...16 coins left in FIFO // retval: 0...16 coins left in FIFO
void epi_restoreEmpCoinSignal(uint8_t *valid, uint8_t *signal, uint8_t *error, uint16_t *value); void epi_restoreEmpCoinSignal(uint8_t *valid, uint8_t *signal, uint8_t *error, uint16_t *value);
void gpi_storeRbDeviceSettings(uint8_t leng, uint8_t const *data);
void gpi_storeRbDeviceSettings(uint8_t leng, uint8_t *data);
void epi_restoreRbDeviceSettings(uint8_t *leng, uint8_t *data); void epi_restoreRbDeviceSettings(uint8_t *leng, uint8_t *data);
void gpi_storeMachineIDsettings(uint8_t leng, uint8_t const *data);
void gpi_storeMachineIDsettings(uint8_t leng, uint8_t *data);
void epi_restoreMachineIDsettings(uint8_t *leng, uint8_t *data); void epi_restoreMachineIDsettings(uint8_t *leng, uint8_t *data);
void epi_clearCurrentPayment(void); void epi_clearCurrentPayment(void);
void gpi_storeCurrentPayment(uint32_t insertedAmount, uint16_t lastCoinType, uint16_t lastCoinValue); void gpi_storeCurrentPayment(uint32_t insertedAmount, uint16_t lastCoinType, uint16_t lastCoinValue);
uint32_t epi_CurrentPaymentGetAmount(void); uint32_t epi_CurrentPaymentGetAmount(void);
uint16_t epi_CurrentPaymentGetLastCoin(void); uint16_t epi_CurrentPaymentGetLastCoin(void);
bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values); bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values);
// alle bei diesem Verkauf eingeworfenen Münzen sind gespeichert falls die jmd. braucht // alle bei diesem Verkauf eingeworfenen Münzen sind gespeichert falls die jmd. braucht
void gpi_storeWakeSources(uint8_t const *receivedData);
void gpi_storeWakeSources(uint8_t *receivedData);
uint64_t epi_getWakeSources(void); uint64_t epi_getWakeSources(void);
uint8_t epi_getWakeReason(void);
void gpi_storeExtendedTime(uint8_t leng, uint8_t const *data);
void gpi_storeExtendedTime(uint8_t leng, uint8_t *data);
void epi_restoreExtendedTime(uint8_t *leng, uint8_t *data); void epi_restoreExtendedTime(uint8_t *leng, uint8_t *data);
void gpi_storeDeviceConditions(uint8_t leng, uint8_t const *data);
void gpi_storeDeviceConditions(uint8_t leng, uint8_t *data);
void epi_restoreDeviceConditions(uint8_t *leng, uint8_t *data); void epi_restoreDeviceConditions(uint8_t *leng, uint8_t *data);
void gpi_storeDynMachineConditions(uint8_t leng, uint8_t const *data);
void gpi_storeDynMachineConditions(uint8_t leng, uint8_t *data);
void epi_restoreDynMachineConditions(uint8_t *leng, uint8_t *data); void epi_restoreDynMachineConditions(uint8_t *leng, uint8_t *data);
void gpi_storeDCbackupAccNr(uint8_t leng, uint8_t const *data);
void epi_restoreDCbackupAccNr(uint8_t *leng, uint16_t *accNrs);
// return accNrs[0..7]
void epi_iniVRstorage(void);
void gpi_storeVaultRecord(uint8_t blkNr, uint8_t const *data);
bool epi_checkIfVaultRecordAvailable(void);
bool epi_restoreVaultRecord(uint16_t *length, uint8_t *buf);
// true if completly received
void gpi_storeCBlevel(uint32_t amount, uint16_t nrOfCoins);
uint32_t epi_getCashBoxContent(void);
uint16_t epi_getNrOfCoinsInCashBox(void);
void gpi_storeNewMifareCard(uint8_t typ, uint8_t const *holder);
uint8_t epi_mifGetCardType(uint8_t const *holder);
//holder[8] = name of card holder
// retval Type of MifareCard, 1=upper door, 2=lower door 3=test printer 4=test coins
void gpi_storeDcDataValid(bool isVal);
bool gpi_areDcDataValid();

View File

@@ -13,6 +13,9 @@ uint32_t uchar2ulong(uint8_t Highbyte, uint8_t MHbyte, uint8_t MLbyte, uint8_t L
uint8_t uint2uchar(uint16_t uival, bool getHighB); uint8_t uint2uchar(uint16_t uival, bool getHighB);
uint8_t ulong2uchar(uint32_t ulval, uint8_t getBytNr);
// getBytNr: 0=LSB 3=MSB
void delay(uint16_t MilliSec); void delay(uint16_t MilliSec);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
#ifndef ATBAPPPLUGIN_H
#define ATBAPPPLUGIN_H
/***********************************************************
* a simple class with only one method for plugin info
*/
#include <QObject>
#include <QString>
class ATBAPPplugin
{
public:
virtual const QString & getPluginInfo() = 0;
};
Q_DECLARE_INTERFACE(ATBAPPplugin,
"eu.atb.ptu.plugin.ATBAPPplugin/0.9")
#endif // ATBAPPPLUGIN_H

View File

@@ -0,0 +1,293 @@
#include "src/ATBAPP/ATBDeviceControllerPlugin.h"
#include "src/ATBAPP/ATBHealthEvent.h"
#include <QTimer>
#include <QTextCodec>
ATBDeviceControllerPlugin::ATBDeviceControllerPlugin(QObject *parent) : QObject(parent),
pluginState(PLUGIN_STATE::NOT_INITIALIZED)
{
this->pluginInfo = QString::fromUtf8(pluginInfoString.c_str());
this->hw = new hwapi();
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_templatePrintFinished_OK()), this, SLOT(onPrintFinishedOK()));
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_templatePrintFinished_Err()), this, SLOT(onPrintFinishedERR()));
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_gotNewCoin()), this, SLOT(onCashGotCoin()));
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_vendStopByMax()), this, SLOT(onCashVendStopByMax()));
}
ATBDeviceControllerPlugin::~ATBDeviceControllerPlugin() {}
PLUGIN_STATE ATBDeviceControllerPlugin::initDCPlugin(QObject *healthEventReceiver, const QSettings & settings)
{
this->healthEventReceiver = healthEventReceiver;
// read variables from setting
QString serialPort = settings.value("DEVICE_CONTROLLER/serialPort", "ttymxc2").toString();
QByteArray printerEncoding = settings.value("DEVICE_CONTROLLER/printerEnconding", "ISO 8859-2").toString().toLatin1();
// open serial port
hw->dc_openSerial(5, "115200", serialPort, 1);
// text encoding for printer
this->codec = QTextCodec::codecForName(printerEncoding);
this->pluginState = PLUGIN_STATE::INITIALIZED;
return pluginState;
}
// TASKS: Cash handling -------------------------------------------------------
void ATBDeviceControllerPlugin::requestStartCashInput(const QString & amount)
{
qCritical() << "Start Cash vending with amount = " << amount;
uint32_t amountInt = static_cast<uint32_t>(amount.toUInt());
hw->cash_startPayment(amountInt);
}
void ATBDeviceControllerPlugin::requestStopCashInput()
{
hw->cash_stopPayment();
}
void ATBDeviceControllerPlugin::cashCollect()
{
hw->vend_success();
}
void ATBDeviceControllerPlugin::cashAbort()
{
hw->vend_failed();
}
// TASKS: printing ------------------------------------------------------------
void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant> & printingData)
{
struct T_dynDat *dynTicketData = new T_dynDat;
memset(dynTicketData, 0, sizeof(*dynTicketData));
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket( " << endl
<< " licenseplate = " << printingData["licenseplate"] << endl
<< " amount = " << printingData["amount"] << endl
<< " parkingEnd = " << printingData["parkingEnd"] << endl
<< " currentTime = " << printingData["currentTime"] << endl
<< " currentDate = " << printingData["currentDate"] << endl;
// set dynamic printer data:
memcpy((char*)dynTicketData->licensePlate, codec->fromUnicode(printingData["licenseplate"].toString()).data(), 8);
memcpy((char*)dynTicketData->vendingPrice, codec->fromUnicode(printingData["amount"].toString()).data(), 8);
QDateTime parkingEndQDateTime = QDateTime::fromString(printingData["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(printingData["currentTime"].toString(), Qt::ISODate);
memcpy((char*)dynTicketData->parkingEnd, codec->fromUnicode(parkingEndQDateTime.toString("hh:mm")).data(), 8);
memcpy((char*)dynTicketData->currentTime, codec->fromUnicode(currentDateTime.toString("hh:mm")).data(), 8);
memcpy((char*)dynTicketData->currentDate, codec->fromUnicode(currentDateTime.toString("dd.MM.yy")).data(), 8);
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket()";
if (!this->hw->dc_isPortOpen()) {
qCritical() << " ... serial port is not open!";
this->onPrintFinishedERR();
return;
}
// TODO: wird hier nur 'licensePlate' gedruckt?
if (!this->hw->prn_sendDynamicPrnValues(dynTicketData->licensePlate)) {
this->errorCode = "hwapi::prn_sendDynamicPrnValues";
this->errorDescription = "hwapi method 'hwapi::prn_sendDynamicPrnValues' result is false";
qCritical() << "ERROR:";
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket( " << endl
<< " licenseplate = " << printingData["licenseplate"] << endl
<< " amount = " << printingData["amount"] << endl
<< " parkingEnd = " << printingData["parkingEnd"] << endl
<< " currentTime = " << printingData["currentTime"] << endl
<< " currentDate = " << printingData["currentDate"] << endl;
this->onPrintFinishedERR();
return;
}
QTimer::singleShot(1000, this, SLOT(onPrinterDataPrepared()));
}
void ATBDeviceControllerPlugin::onPrinterDataPrepared()
{
this->currentTemplate = 1;
this->onPrinterPrintNextTemplate();
}
void ATBDeviceControllerPlugin::onPrinterPrintNextTemplate()
{
qCritical() << " ... print template " << this->currentTemplate;
if (!this->hw->prn_printTemplate(this->currentTemplate)) {
this->errorCode = "hwapi::prn_printTemplate";
this->errorDescription = QString("hwapi method 'hwapi::onPrinterPrintNextTemplate(%1)' result is false").arg(this->currentTemplate);
this->onPrintFinishedERR();
return;
}
if (this->currentTemplate >= 3) {
// all templates are printed
this->currentTemplate = 0;
// FAKE SIGNAL:
QTimer::singleShot(1000, this, SLOT(onPrintFinishedOK()));
}
else {
// print next template
this->currentTemplate++;
QTimer::singleShot(3000, this, SLOT(onPrinterPrintNextTemplate()));
}
}
/************************************************************************************************
* private slots, interface to low level hwapi
*
*/
void ATBDeviceControllerPlugin::onPrintFinishedOK()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onPrintFinishedOK()";
emit this->printTicketFinished(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
"",
"");
}
void ATBDeviceControllerPlugin::onPrintFinishedERR()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onPrintFinishedERR()";
this->errorCode = "PRINTER"; // TODO: get more detailed error code from low level API
this->errorDescription = "Printer error"; // TODO: get more detailed error description from low level API
emit this->printTicketFinished(nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND,
this->errorCode,
this->errorDescription);
}
/************************************************************************************************
* cash payment
*/
void ATBDeviceControllerPlugin::onCashGotCoin()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onGotCoin()";
uint32_t amountInt = this->hw->getInsertedAmount();
QString amountString = QString::number(amountInt);
emit this->cashInputEvent(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
nsDeviceControllerInterface::CASH_STATE::CACHE_INPUT,
amountString,
"",
"");
}
void ATBDeviceControllerPlugin::onCashVendStopByMax()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onCashVendStopByMax()";
uint32_t amountInt = this->hw->getInsertedAmount();
QString amountString = QString::number(amountInt);
emit this->cashInputFinished(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
amountString,
"",
"");
}
/************************************************************************************************
* Mandatory plugin methods
*
*/
PLUGIN_STATE ATBDeviceControllerPlugin::getState()
{
return this->pluginState;
}
QString & ATBDeviceControllerPlugin::getLastError()
{
return this->errorCode;
}
const QString & ATBDeviceControllerPlugin::getLastErrorDescription()
{
return this->errorDescription;
}
const QString & ATBDeviceControllerPlugin::getPluginInfo()
{
return this->pluginInfo;
}
const QString ATBDeviceControllerPlugin::getString(nsDeviceControllerInterface::RESULT_STATE resultState)
{
QString str;
switch (resultState) {
case nsDeviceControllerInterface::RESULT_STATE::SUCCESS:
str = QString("RESULT_STATE::SUCCESS");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND:
str = QString("RESULT_STATE::ERROR_BACKEND");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_TIMEOUT:
str = QString("RESULT_STATE::ERROR_TIMEOUT");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_PROCESS:
str = QString("RESULT_STATE::ERROR_PROCESS");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_RETRY:
str = QString("RESULT_STATE::ERROR_RETRY");
break;
case nsDeviceControllerInterface::RESULT_STATE::INFO:
str = QString("RESULT_STATE::INFO");
break;
}
return str;
}
/************************************************************************************************
* ... end
*/
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2( ATBDeviceControllerPlugin, ATBDeviceControllerPlugin )
#endif

View File

@@ -0,0 +1,125 @@
#ifndef ATBDEVICECONTROLLERPLUGIN_H
#define ATBDEVICECONTROLLERPLUGIN_H
#include <QObject>
#include "src/ATBAPP/DeviceControllerInterface.h"
#include "src/ATBAPP/ATBAPPplugin.h"
#include "version.h"
#include "hwapi.h"
#include <unistd.h>
#include <thread>
#include <memory>
#include <QSharedMemory>
class QTextCodec;
using namespace nsDeviceControllerInterface;
class QSettings;
class ATBDeviceControllerPlugin : public QObject,
public DeviceControllerInterface
{
Q_OBJECT
Q_INTERFACES(ATBAPPplugin)
Q_INTERFACES(DeviceControllerInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA( IID "ATBDeviceControllerPlugin" )
#endif
public:
explicit ATBDeviceControllerPlugin(QObject *parent = nullptr);
~ATBDeviceControllerPlugin();
// ----------------------------------------------------------------------------
// interface:
PLUGIN_STATE initDCPlugin(QObject *healthEventReceiver, const QSettings & settings);
// TASKS: Cash handling -------------------------------------------------------
void requestStartCashInput(const QString & amount);
void requestStopCashInput();
void cashCollect();
void cashAbort();
// TASKS: printing ------------------------------------------------------------
void requestPrintTicket(const QHash<QString, QVariant> & printingData);
// mandantory ATBAPP plugin methods: ------------------------------------------
nsDeviceControllerInterface::PLUGIN_STATE getState();
QString & getLastError();
const QString & getLastErrorDescription();
const QString & getPluginInfo();
// helpers e.g. for debug / log
const QString getString(nsDeviceControllerInterface::RESULT_STATE resultState);
signals:
void printTicketFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & errorCode,
const QString & errorDescription);
void cashInputEvent(nsDeviceControllerInterface::RESULT_STATE resultState,
nsDeviceControllerInterface::CASH_STATE cashState,
const QString & newCashValue,
const QString & errorCode,
const QString & errorDescription);
void cashInputFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & newCashValue,
const QString & errorCode,
const QString & errorDescription);
void requestServiceMode();
void Error(
const QString & errorCode,
const QString & errorDescription);
private:
QString errorCode;
QString errorDescription;
QString pluginInfo;
int currentTemplate;
bool useDebug;
PLUGIN_STATE pluginState;
QObject* healthEventReceiver;
hwinf* hw;
QTextCodec *codec;
private slots:
// printer
void onPrinterDataPrepared();
void onPrinterPrintNextTemplate();
void onPrintFinishedOK();
void onPrintFinishedERR();
// cash payment
void onCashGotCoin();
void onCashVendStopByMax();
};
#endif // ATBDEVICECONTROLLERPLUGIN_H

View File

@@ -0,0 +1,25 @@
#include "src/ATBAPP/ATBHealthEvent.h"
ATBHealthEvent::ATBHealthEvent(ATB_HEALTH_MODE mode, const QString & errorNumber, const QString & errorDescription) :
QEvent(ATB_HEALTH_EVENT),
healthMode(mode),
errorNumber(errorNumber),
errorDescription(errorDescription)
{
}
QString ATBHealthEvent::getErrorNumber()
{
return this->errorNumber;
}
QString ATBHealthEvent::getErrorDescription()
{
return this->errorDescription;
}
ATB_HEALTH_MODE ATBHealthEvent::getMode()
{
return this->healthMode;
}

View File

@@ -0,0 +1,44 @@
#ifndef ATBHEALTHEVENT_H
#define ATBHEALTHEVENT_H
#include <QEvent>
#include <QString>
enum class ATB_HEALTH_MODE : quint8;
const QEvent::Type ATB_HEALTH_EVENT = static_cast<QEvent::Type>(QEvent::User + 1);
class ATBHealthEvent : public QEvent
{
public:
ATBHealthEvent(ATB_HEALTH_MODE mode, const QString & errorNumber, const QString & errorDescription);
QString getErrorNumber();
QString getErrorDescription();
ATB_HEALTH_MODE getMode();
signals:
public slots:
private:
ATB_HEALTH_MODE healthMode;
QString errorNumber;
QString errorDescription;
};
enum class ATB_HEALTH_MODE : quint8 {
WARNING,
ERROR,
WARNING_CORRECTION,
ERROR_CORRECTION,
DEBUG,
STATE,
UNSPECIFIED
};
#endif // ATBHEALTHEVENT_H

View File

@@ -0,0 +1,142 @@
#ifndef DEVICECONTROLLERINTERFACE_H
#define DEVICECONTROLLERINTERFACE_H
#include <QtPlugin>
#include <QSettings>
#include <QString>
#include "ATBAPPplugin.h"
namespace nsDeviceControllerInterface {
enum class PLUGIN_STATE : quint8;
enum class RESULT_STATE : quint8;
enum class CASH_STATE : quint8;
}
class DeviceControllerInterface : public ATBAPPplugin
{
Q_INTERFACES(ATBAPPplugin)
public:
virtual ~DeviceControllerInterface() {}
virtual nsDeviceControllerInterface::PLUGIN_STATE initDCPlugin(QObject *healthEventReceiver,
const QSettings & settings) = 0;
// TASKS: Cash handling -------------------------------------------------------
/**
* enables coin input
* amount = "0": pay-up
* amount > "0": pay-down
*/
virtual void requestStartCashInput(const QString & amount) = 0;
/**
* called e.g. on Button "NEXT" in pay-up (direct coin input)
*/
virtual void requestStopCashInput() = 0;
/**
* called e.g. on Button "NEXT" in pay-up (direct coin input)
*/
virtual void cashCollect() = 0;
virtual void cashAbort() = 0;
// TASKS: printing ------------------------------------------------------------
virtual void requestPrintTicket(const QHash<QString, QVariant> & printingData) = 0;
// mandantory ATBAPP plugin methods:
virtual nsDeviceControllerInterface::PLUGIN_STATE getState() = 0;
virtual const QString & getLastError() = 0;
virtual const QString & getLastErrorDescription() = 0;
// return a plugin description in JSON or XML
// -> ATBAPPplugin::getPluginInfo()
// helpers e.g. for debug / log
virtual const QString getString(nsDeviceControllerInterface::RESULT_STATE resultState) = 0;
signals:
virtual void printTicketFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & errorCode,
const QString & errorDescription) = 0;
/**
* emitted on e.g. a coin input
*/
virtual void cashInputEvent(nsDeviceControllerInterface::RESULT_STATE resultState,
nsDeviceControllerInterface::CASH_STATE cashState,
const QString & newCashValue,
/* additional variables? */
const QString & errorCode,
const QString & errorDescription) = 0;
/**
* emitted if cashInput has been stopped, e.g. in result to task requestStopCashInput():
* -> shutter is blocked
* -> no cash input is possible
* -> coins are in cache
*/
virtual void cashInputFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & newCashValue,
/* additional variables? */
const QString & errorCode,
const QString & errorDescription) = 0;
/**
* emitted e.g. if service door is opened
*/
virtual void requestServiceMode() = 0;
/**
* emitted on error
* depending on errorCode:
* -> interrupt selling process
* -> machine can go to state OOO
* -> send error event to ISMAS
* -> ...
*/
virtual void Error(
/* additional variables? */
const QString & errorCode,
const QString & errorDescription) = 0;
};
Q_DECLARE_INTERFACE(DeviceControllerInterface,
"eu.atb.ptu.plugin.DeviceControllerInterface/1.0")
namespace nsDeviceControllerInterface {
enum class PLUGIN_STATE : quint8 {
NOT_INITIALIZED = 0,
INITIALIZED = 1
};
enum class RESULT_STATE : quint8 {
SUCCESS = 1, // operation was successfull
ERROR_BACKEND, // error from backend (e.g. backend replies with error)
ERROR_TIMEOUT, // the operation timed out
ERROR_PROCESS, // internal plugin error, should not occur (this is a bug in implementation)
ERROR_RETRY, // retry operation
INFO // informational (e.g. display a message, log something etc.)
};
enum class CASH_STATE : quint8 {
CACHE_EMPTY, // Cache still empty, default state
CACHE_INPUT, // Coins are in Cache
OVERPAYED,
/* t.b.d. */
};
}
#endif // DEVICECONTROLLERINTERFACE_H

View File

@@ -1,141 +1,110 @@
#include <stdint.h> #include <stdint.h>
#include <algorithm>
#include <QString> #include <QString>
#include <QDebug> #include <QDebug>
#include "tslib.h" #include "tslib.h"
//#include "controlBus.h" #include "shared_mem_buffer.h"
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// control serial interface gui <--> serial // control serial interface gui <--> serial
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
void epi_setSerial(int BaudNr,
QString BaudStr,
QString ComName,
uint8_t connect) {
memset(&SharedMemBuffer::getData()->rs.comportName[0], 0x00,
sizeof(SharedMemBuffer::getData()->rs.comportName));
strncpy(SharedMemBuffer::getData()->rs.comportName,
ComName.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->rs.comportName)-1);
static QString rs_comportName; // z.B. "COM48" memset(&SharedMemBuffer::getData()->rs.baudStr[0], 0x00,
static QString rs_baudStr; // z.B. "19200" sizeof(SharedMemBuffer::getData()->rs.baudStr));
static int rs_baudNr; //0...5 oder -1 strncpy(SharedMemBuffer::getData()->rs.baudStr,
static uint8_t rs_connect; // 0,1 BaudStr.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->rs.baudStr)-1);
void epi_setSerial(int BaudNr, QString BaudStr, QString ComName, uint8_t connect) SharedMemBuffer::getData()->rs.baudNr = BaudNr;
{ SharedMemBuffer::getData()->rs.connect = connect;
// qDebug() << "ENTER" << BaudNr << BaudStr << ComName << connect;
rs_comportName = ComName;
rs_baudStr = BaudStr;
rs_baudNr = BaudNr; // 0=1200 1=9600 2=19200 3=38400 4=57600 5=115200 oder -1
rs_connect = connect; // 0/1
// qDebug() << "LEAVE" << rs_baudNr << rs_baudStr << rs_comportName << rs_connect;
} }
void epi_closeSerial(void) void epi_closeSerial(void) {
{ SharedMemBuffer::getData()->rs.connect = 0;
rs_connect=0;
// qDebug() << "ENTER/LEAVE rc_connect=0";
} }
void gpi_serialChanged(void) {
void gpi_serialChanged(void)
{
// serial confirms that port was closed or opened // serial confirms that port was closed or opened
rs_connect=2; // Flanke, nur 1x öffnen/schließen // rs_connect=2; // Flanke, nur 1x öffnen/schließen
//qDebug() << "ENTER/LEAVE rc_connect=2"; SharedMemBuffer::getData()->rs.connect = 2;
} }
uint8_t gpi_getSerialConn(void) uint8_t gpi_getSerialConn(void) {
{ return SharedMemBuffer::getDataConst()->rs.connect;
return rs_connect;
} }
int gpi_getBaudNr(void) {
int gpi_getBaudNr(void) return SharedMemBuffer::getDataConst()->rs.baudNr;
{
return rs_baudNr;
} }
QString gpi_getComPortName(void) QString gpi_getComPortName(void) {
{ return SharedMemBuffer::getDataConst()->rs.comportName;
return rs_comportName;
} }
static bool rs_portIsOpen; void gpi_serialIsOpen(bool offen) {
SharedMemBuffer::getData()->rs.portIsOpen = offen;
void gpi_serialIsOpen(bool offen)
{
//qDebug() << "ENTER/LEAVE offen=" << offen;
rs_portIsOpen=offen;
} }
bool epi_isSerialPortOpen() bool epi_isSerialPortOpen() {
{
// true: port is open false: port is closed // true: port is open false: port is closed
//qDebug() << "ENTER/LEAVE offen=" << rs_portIsOpen; return SharedMemBuffer::getDataConst()->rs.portIsOpen;
return rs_portIsOpen;
} }
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// Control transfer gui <--> serial // Control transfer gui <--> serial
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
void epi_startEmmision(char start) {
static char AutoEmissionOn; // 1: zyklisch Anfragen zum Slave senden SharedMemBuffer::getData()->AutoEmissionOn = start;
void epi_startEmmision(char start)
{
AutoEmissionOn=start;
} }
bool gpi_isEmmisionOn(void) bool gpi_isEmmisionOn(void) {
{ return SharedMemBuffer::getDataConst()->AutoEmissionOn;
return AutoEmissionOn;
} }
//----------------------------------------------------- uint16_t gpi_getPeriodicSendTimeVal() {
SharedMemBuffer::getData()->datif.sendingPer_changed = 0;
static uint16_t datif_sendingPeriod; if ((SharedMemBuffer::getDataConst()->datif.sendingPeriod < 3) ||
static bool datif_sendingPer_changed; (SharedMemBuffer::getDataConst()->datif.sendingPeriod > 10000)) {
uint16_t gpi_getPeriodicSendTimeVal()
{
datif_sendingPer_changed=0;
if (datif_sendingPeriod<3 || datif_sendingPeriod>10000)
return 130; // ms, default return 130; // ms, default
else }
return datif_sendingPeriod; return SharedMemBuffer::getDataConst()->datif.sendingPeriod;
} }
void epi_setPeriodicSendTimeVal(uint16_t val) void epi_setPeriodicSendTimeVal(uint16_t val) {
{ if (val>=3 && val<10000) {
if (val>=3 && val<10000) SharedMemBuffer::getData()->datif.sendingPer_changed = 1;
{ SharedMemBuffer::getData()->datif.sendingPeriod = val;
datif_sendingPer_changed=1;
datif_sendingPeriod=val;
} }
} }
bool gpi_PeriodicSendTimeHasChanged() bool gpi_PeriodicSendTimeHasChanged() {
{ return SharedMemBuffer::getDataConst()->datif.sendingPer_changed;
return datif_sendingPer_changed;
} }
//-----------------------------------------------------
//-----------------------------------------------------
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// Status Display gui <--> serial // Status Display gui <--> serial
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// linke Spalte, über Connect Button // linke Spalte, über Connect Button
static QString txt4comStateLine; static QString txt4comStateLine;
QString epi_getTxt4comStateLine(void) QString epi_getTxt4comStateLine(void) {
{
// GUI: get Text for serial Comport-State Line // GUI: get Text for serial Comport-State Line
return txt4comStateLine; return txt4comStateLine;
} }
void gpi_setTxt4comStateLine(QString txtline) // gpi void gpi_setTxt4comStateLine(QString txtline) {
{
// serial: write Text to be displayed in serial Comport-State line (like "connected") // serial: write Text to be displayed in serial Comport-State line (like "connected")
txt4comStateLine.clear(); txt4comStateLine.clear();
if (txtline=="") if (txtline=="")
@@ -144,26 +113,20 @@ void gpi_setTxt4comStateLine(QString txtline) // gpi
txt4comStateLine=txtline; txt4comStateLine=txtline;
} }
void epi_clrTxt4comStateLine() void epi_clrTxt4comStateLine() {
{
txt4comStateLine.clear(); txt4comStateLine.clear();
} }
//---------------------------------------------------------------------------------------------
// rechte Spalte, oberste Statuszeile // rechte Spalte, oberste Statuszeile
// I) "Handshakes" (serial Control) flow.cpp // I) "Handshakes" (serial Control) flow.cpp
// geht überhaupt was raus? kommt überhaupt was zurück? // geht überhaupt was raus? kommt überhaupt was zurück?
static QString txt4HsStateLine; static QString txt4HsStateLine;
QString epi_getTxt4HsStateLine(void) QString epi_getTxt4HsStateLine(void) {
{
return txt4HsStateLine; return txt4HsStateLine;
} }
void gpi_setTxt4HsStateLine(QString txtline) void gpi_setTxt4HsStateLine(QString txtline) {
{
txt4HsStateLine.clear(); txt4HsStateLine.clear();
if (txtline=="") if (txtline=="")
txt4HsStateLine.clear(); txt4HsStateLine.clear();
@@ -171,26 +134,19 @@ void gpi_setTxt4HsStateLine(QString txtline)
txt4HsStateLine=txtline; txt4HsStateLine=txtline;
} }
void epi_clrTxt4HsStateLine() void epi_clrTxt4HsStateLine() {
{
txt4HsStateLine.clear(); txt4HsStateLine.clear();
} }
//---------------------------------------------------------------------------------------------
// II) Master receive state (empfangenes Telgramm OK? crc? length? ) // II) Master receive state (empfangenes Telgramm OK? crc? length? )
// Statuszeile Auswertung der SlaveResponse (serial Frame, CRC usw) (prot.cpp) // Statuszeile Auswertung der SlaveResponse (serial Frame, CRC usw) (prot.cpp)
static QString txt4masterStateLine; static QString txt4masterStateLine;
QString epi_getTxt4masterStateLine(void) QString epi_getTxt4masterStateLine(void) {
{
return txt4masterStateLine; return txt4masterStateLine;
} }
void gpi_setTxt4masterStateLine(QString txtline) void gpi_setTxt4masterStateLine(QString txtline) {
{
txt4masterStateLine.clear(); txt4masterStateLine.clear();
if (txtline=="") if (txtline=="")
txt4masterStateLine.clear(); txt4masterStateLine.clear();
@@ -198,13 +154,10 @@ void gpi_setTxt4masterStateLine(QString txtline)
txt4masterStateLine=txtline; txt4masterStateLine=txtline;
} }
void epi_clrTxt4masterStateLine() void epi_clrTxt4masterStateLine() {
{
txt4masterStateLine.clear(); txt4masterStateLine.clear();
} }
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
// III Slave receive (from Master) OK? if then show results, if not then show errors // III Slave receive (from Master) OK? if then show results, if not then show errors
@@ -214,13 +167,11 @@ void epi_clrTxt4masterStateLine()
static QString txt4resultStateLine; static QString txt4resultStateLine;
QString epi_getTxt4resultStateLine(void) QString epi_getTxt4resultStateLine(void) {
{
return txt4resultStateLine; return txt4resultStateLine;
} }
void gpi_setTxt4resultStateLine(QString txtline) void gpi_setTxt4resultStateLine(QString txtline) {
{
txt4resultStateLine.clear(); txt4resultStateLine.clear();
if (txtline=="") if (txtline=="")
txt4resultStateLine.clear(); txt4resultStateLine.clear();
@@ -228,26 +179,22 @@ void gpi_setTxt4resultStateLine(QString txtline)
txt4resultStateLine=txtline; txt4resultStateLine=txtline;
} }
void epi_clrTxt4resultStateLine() void epi_clrTxt4resultStateLine() {
{
txt4resultStateLine.clear(); txt4resultStateLine.clear();
} }
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
// IV Statuszeile Empfangsdaten // IV Statuszeile Empfangsdaten
static QString txt4dataLine; static QString txt4dataLine;
QString epi_getTxt4dataStateLine(void) QString epi_getTxt4dataStateLine(void) {
{
// GUI: get Text for serial Comport-State Line // GUI: get Text for serial Comport-State Line
return txt4dataLine; return txt4dataLine;
} }
void gpi_setTxt4dataStateLine(QString txtline) void gpi_setTxt4dataStateLine(QString txtline) {
{
// serial: write Text to be displayed in serial Comport-State line (like "connected") // serial: write Text to be displayed in serial Comport-State line (like "connected")
txt4dataLine.clear(); txt4dataLine.clear();
if (txtline=="") if (txtline=="")
@@ -256,8 +203,7 @@ void gpi_setTxt4dataStateLine(QString txtline)
txt4dataLine=txtline; txt4dataLine=txtline;
} }
void epi_clrTxt4dataStateLine() void epi_clrTxt4dataStateLine() {
{
txt4dataLine.clear(); txt4dataLine.clear();
} }
@@ -267,16 +213,11 @@ void epi_clrTxt4dataStateLine()
static QString txt4datifReceive; static QString txt4datifReceive;
QString epi_getTxt4datifLine(void) QString epi_getTxt4datifLine(void) {
{
return txt4datifReceive; return txt4datifReceive;
} }
void gpi_setTxt4datifLine(QString txtline) void gpi_setTxt4datifLine(QString txtline) {
{
txt4datifReceive.clear(); txt4datifReceive.clear();
if (txtline=="") if (txtline=="")
txt4datifReceive.clear(); txt4datifReceive.clear();
@@ -284,8 +225,7 @@ void gpi_setTxt4datifLine(QString txtline)
txt4datifReceive=txtline; txt4datifReceive=txtline;
} }
void epi_clrTxt4datifLine() void epi_clrTxt4datifLine() {
{
txt4datifReceive.clear(); txt4datifReceive.clear();
} }
@@ -294,14 +234,11 @@ void epi_clrTxt4datifLine()
static QString txt4diagWindow; static QString txt4diagWindow;
QString epi_getTxt4RsDiagWin(void) QString epi_getTxt4RsDiagWin(void) {
{
return txt4diagWindow; return txt4diagWindow;
} }
void gpi_setTxt4RsDiagWin(QString txtline) void gpi_setTxt4RsDiagWin(QString txtline) {
{
txt4diagWindow.clear(); txt4diagWindow.clear();
if (txtline=="") if (txtline=="")
txt4diagWindow.clear(); txt4diagWindow.clear();
@@ -309,8 +246,7 @@ void gpi_setTxt4RsDiagWin(QString txtline)
txt4diagWindow=txtline; txt4diagWindow=txtline;
} }
void epi_clrTxt4RsDiagWin() void epi_clrTxt4RsDiagWin() {
{
txt4diagWindow.clear(); txt4diagWindow.clear();
} }
@@ -318,14 +254,11 @@ void epi_clrTxt4RsDiagWin()
static QString sndTxt4diagWindow; static QString sndTxt4diagWindow;
QString epi_get2ndTxt4RsDiagWin(void) QString epi_get2ndTxt4RsDiagWin(void) {
{
return sndTxt4diagWindow; return sndTxt4diagWindow;
} }
void gpi_set2ndTxt4RsDiagWin(QString txtline) void gpi_set2ndTxt4RsDiagWin(QString txtline) {
{
sndTxt4diagWindow.clear(); sndTxt4diagWindow.clear();
if (txtline=="") if (txtline=="")
sndTxt4diagWindow.clear(); sndTxt4diagWindow.clear();
@@ -333,90 +266,61 @@ void gpi_set2ndTxt4RsDiagWin(QString txtline)
sndTxt4diagWindow=txtline; sndTxt4diagWindow=txtline;
} }
void epi_clr2ndTxt4RsDiagWin() void epi_clr2ndTxt4RsDiagWin() {
{
sndTxt4diagWindow.clear(); sndTxt4diagWindow.clear();
} }
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// Memory for Slave responses, common data // Memory for Slave responses, common data
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
void gpi_storeResult_serialTestOK(bool wasOk) {
SharedMemBuffer::getData()->Sdata.serialTestResult = wasOk;
static bool Sdata_serialTestResult;
void gpi_storeResult_serialTestOK(bool wasOk)
{
Sdata_serialTestResult=wasOk;
} }
bool epi_getResult_serialTestOK() bool epi_getResult_serialTestOK() {
{
// retval: true: test was successful, got right response // retval: true: test was successful, got right response
return Sdata_serialTestResult; return SharedMemBuffer::getDataConst()->Sdata.serialTestResult;
} }
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
// Store received data for hwapi // Store received data for hwapi
// /////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////
void gpi_startNewRequest() {
SharedMemBuffer::getData()->Sdata.pProtResultOk = 0;
static uint8_t Sdata_pProtResultOk;
void gpi_startNewRequest()
{
Sdata_pProtResultOk=0;
} }
void gpi_storeResultOfLastRequest(bool answisok) void gpi_storeResultOfLastRequest(bool answisok) {
{ SharedMemBuffer::getData()->Sdata.pProtResultOk = answisok ? 1 : 2;
if (answisok)
Sdata_pProtResultOk=1;
else
Sdata_pProtResultOk=2;
} }
uint8_t epi_getResultOfLastRequest() uint8_t epi_getResultOfLastRequest() {
{
// retval: 0: in progress 1: OK 2: error // retval: 0: in progress 1: OK 2: error
return Sdata_pProtResultOk; return SharedMemBuffer::getDataConst()->Sdata.pProtResultOk;
} }
void gpi_storeRecPayLoad(uint8_t RdDlen, uint8_t const *receivedData) {
SharedMemBuffer::getData()->Sdata.receivedDataLength
= std::min(RdDlen, (uint8_t)(64));
static uint16_t Sdata_receivedDataLength; memset((char *)(&SharedMemBuffer::getData()->Sdata.receivedDataBlock[0]),
static uint8_t Sdata_receivedDataBlock[64]; 0x00, sizeof(SharedMemBuffer::getData()->Sdata.receivedDataBlock));
strncpy((char *)(&SharedMemBuffer::getData()->Sdata.receivedDataBlock[0]),
void gpi_storeRecPayLoad(uint8_t RdDlen, uint8_t *receivedData) (char const *)receivedData,
{ sizeof(SharedMemBuffer::getData()->Sdata.receivedDataBlock)-1);
Sdata_receivedDataLength=uint16_t(RdDlen);
if (Sdata_receivedDataLength>64)
Sdata_receivedDataLength=64;
tslib_strclr(Sdata_receivedDataBlock,0,64);
tslib_strcpy(receivedData, Sdata_receivedDataBlock, Sdata_receivedDataLength);
} }
uint16_t epi_getLastPayLoad(uint16_t plBufSiz, uint8_t *payLoad) uint16_t epi_getLastPayLoad(uint16_t plBufSiz, uint8_t *payLoad) {
{
// get data back in *pl, max 64 byte // get data back in *pl, max 64 byte
// retval = nr of bytes received. If host buffer too small then // retval = nr of bytes received. If host buffer too small then
// only plBufSíz bytes are copied to pl // only plBufSíz bytes are copied to pl
// plBufSíz=size of host buffer // plBufSíz=size of host buffer
uint16_t ml=plBufSiz; uint16_t ml = std::min(plBufSiz, (uint16_t)(64));
if (ml>64) ml=64; if (SharedMemBuffer::getDataConst()->Sdata.receivedDataLength < ml) {
if (Sdata_receivedDataLength<ml) ml = SharedMemBuffer::getDataConst()->Sdata.receivedDataLength;
ml=Sdata_receivedDataLength; }
tslib_strcpy(Sdata_receivedDataBlock, payLoad, ml); strncpy((char *)payLoad,
return Sdata_receivedDataLength; (char const *)(&SharedMemBuffer::getData()->Sdata.receivedDataBlock[0]),
ml);
return SharedMemBuffer::getDataConst()->Sdata.receivedDataLength;
} }

View File

@@ -17,6 +17,8 @@ static uint16_t datif_OutCmdpara5;
static uint32_t datif_OutCmdpara6; static uint32_t datif_OutCmdpara6;
static uint8_t cycl_running; static uint8_t cycl_running;
//static bool datif_DCdataValid;
T_datif::T_datif(QWidget *parent) : QMainWindow(parent) T_datif::T_datif(QWidget *parent) : QMainWindow(parent)
{ {
@@ -46,6 +48,8 @@ T_datif::T_datif(QWidget *parent) : QMainWindow(parent)
dif_scanStep=0; dif_scanStep=0;
selectedSlaveAddr=FIX_SLAVE_ADDR; selectedSlaveAddr=FIX_SLAVE_ADDR;
cycl_running=0; cycl_running=0;
//datif_DCdataValid=0;
gpi_storeDcDataValid(0);
} }
void T_datif::resetChain(void) void T_datif::resetChain(void)
@@ -863,6 +867,11 @@ char T_datif::loadRecDataFromFrame()
//int portNr; //int portNr;
bool ret; bool ret;
uint8_t uctmp; // maxai uint8_t uctmp; // maxai
char ctmp;
static uint8_t lastResult;
uint8_t prnResult;
static uint32_t lastInsertedAmount;
uint32_t newInsertedAmount;
ret=myDCIF->getReceivedInData(&SlaveAdr, &readSource, &readAddress, &RdDleng, receivedData); ret=myDCIF->getReceivedInData(&SlaveAdr, &readSource, &readAddress, &RdDleng, receivedData);
// retval: data valid, only one time true, true if CommandState OK and readState OK // retval: data valid, only one time true, true if CommandState OK and readState OK
@@ -902,7 +911,8 @@ char T_datif::loadRecDataFromFrame()
for (int ii=0; ii<RdDleng; ii++) for (int ii=0; ii<RdDleng; ii++)
{ {
localStr.append(receivedData[ii]); ctmp=receivedData[ii];
localStr.append(ctmp);
} }
//qDebug() << "got HW version: " << localStr; //qDebug() << "got HW version: " << localStr;
@@ -936,7 +946,7 @@ char T_datif::loadRecDataFromFrame()
case CMD2DC_RdBkDCstate: //101 case CMD2DC_RdBkDCstate: //101
//qDebug() << "got DC state " << localStr; //qDebug() << "got DC state " << localStr;
localStr[8]=0; //localStr[8]=0;
gpi_storeGenerals(2, localStr); gpi_storeGenerals(2, localStr);
// 0=HW 1=SW 2=State // 0=HW 1=SW 2=State
break; break;
@@ -1112,7 +1122,9 @@ char T_datif::loadRecDataFromFrame()
case CMD2DC_RdBk_MifState: //109 case CMD2DC_RdBk_MifState: //109
// get reader status and card type // get reader status and card type
gpi_storeMifReaderStateAndCardType(receivedData); //gpi_storeMifReaderStateAndCardType(receivedData);
gpi_storeNewMifareCard(receivedData[0], &receivedData[1]);
break; break;
case CMD2DC_RdBk_MifData: //24 case CMD2DC_RdBk_MifData: //24
@@ -1216,7 +1228,7 @@ char T_datif::loadRecDataFromFrame()
// ab hier neu: XXX // ab hier neu: 12.4.23
case CMD2DC_RDBK_DEV_PARA: //14 case CMD2DC_RDBK_DEV_PARA: //14
/* /*
@@ -1350,10 +1362,16 @@ char T_datif::loadRecDataFromFrame()
case 112: // get inserted amount in cent in sum case 112: // get inserted amount in cent in sum
// byte 0..3: amount just paid 4,5:last coin type 6,7: last coin value // byte 0..3: amount just paid 4,5:last coin type 6,7: last coin value
ultmp=uchar2ulong(receivedData[3],receivedData[2],receivedData[1],receivedData[0]); newInsertedAmount=uchar2ulong(receivedData[3],receivedData[2],receivedData[1],receivedData[0]);
uitmp=uchar2uint(receivedData[5],receivedData[4]); uitmp=uchar2uint(receivedData[5],receivedData[4]);
uit2=uchar2uint(receivedData[7],receivedData[6]); uit2=uchar2uint(receivedData[7],receivedData[6]);
gpi_storeCurrentPayment(ultmp, uitmp, uit2); gpi_storeCurrentPayment(newInsertedAmount, uitmp, uit2);
if (newInsertedAmount != lastInsertedAmount)
{
emit datif_gotNewCoin();
lastInsertedAmount=newInsertedAmount;
}
break; break;
case 113: // get wake source, 8byte case 113: // get wake source, 8byte
@@ -1464,18 +1482,40 @@ char T_datif::loadRecDataFromFrame()
*/ */
if (RdDleng>40)
//datif_DCdataValid=1; // das hier sind die wichtigsten Daten, deshalb hierrein!
gpi_storeDcDataValid(1);
gpi_storeDynMachineConditions(RdDleng, receivedData); gpi_storeDynMachineConditions(RdDleng, receivedData);
prnResult=receivedData[52];
if (prnResult != lastResult)
{
// new result
if (prnResult==1)
{
emit datif_templatePrintFinished_OK();
} else
if (prnResult==2)
{
emit datif_templatePrintFinished_Err();
}
lastResult=prnResult;
}
break; break;
case 32: // Get current cash level (in vault) case 32: // Get current cash level (in vault)
// bytes 0..3: amount bytes 4,5=Nr.ofCoins in vault // bytes 0..3: amount bytes 4,5=Nr.ofCoins in vault
ultmp=uchar2ulong(receivedData[3],receivedData[2],receivedData[1],receivedData[0]);
uitmp=uchar2uint(receivedData[5],receivedData[4]);
gpi_storeCBlevel(ultmp, uitmp);
break; break;
case 33: // Get all backuped acc. Numbers case 33: // Get all backuped acc. Numbers
// 8 UINTs with acc-nr // 8 UINTs with acc-nr
gpi_storeDCbackupAccNr(RdDleng, receivedData);
break; break;
case 38: // Get stored account record backup case 38: // Get stored account record backup
@@ -1541,7 +1581,8 @@ struct T_vaultRecord
UCHAR endofblock[4]; // end> UCHAR endofblock[4]; // end>
// 316 byte Block im Speicher // 316 byte Block im Speicher
*/ */
// readAddress, &RdDleng, receivedData
gpi_storeVaultRecord(readAddress, receivedData ); // always 64byte
break; break;
} }
@@ -1644,11 +1685,15 @@ bool T_datif::verifyLineTestresponse(uint8_t RdDlen, uint8_t *receivedData)
if (RdDlen < 16) if (RdDlen < 16)
return false; return false;
QString myStr; QString myStr;
char ctmp;
myStr.clear(); myStr.clear();
myStr.append("< Slave Response"); myStr.append("< Slave Response");
for (int nn=0; nn<16; nn++) for (int nn=0; nn<16; nn++)
if (myStr[nn] !=receivedData[nn]) {
ctmp=receivedData[nn];
if (myStr[nn] != ctmp)
{ {
//qDebug() << " datif cmd 10: got wrong string "; //qDebug() << " datif cmd 10: got wrong string ";
//qDebug() << myStr; //qDebug() << myStr;
@@ -1656,6 +1701,7 @@ bool T_datif::verifyLineTestresponse(uint8_t RdDlen, uint8_t *receivedData)
//qDebug() << nn; //qDebug() << nn;
return false; return false;
} }
}
return true; return true;
} }

25
DCPlugin/src/hwChk.cpp Executable file
View File

@@ -0,0 +1,25 @@
#include <stdint.h>
#include "hwChk.h"
hwChk::hwChk(QWidget *parent) : QObject(parent)
{
// myDCIF = new T_prot();
// h: T_prot *myDCIF;
//myDatif = new T_datif();
HWaccess = new hwinf();
struct T_moduleCondition dcModCond;
sys_getDeviceConditions(dcModCond);
}
hwChk::~hwChk()
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -563,11 +563,17 @@ bool sendFDcmd_get(uint8_t *nextWrCmd, uint8_t *nextRdCmd, uint8_t *blockNum, ui
uint8_t check4FDshortCmd(void) uint8_t check4FDshortCmd(void)
{ {
// returns number of waiting command // returns number of waiting command, max FDCMD_STACKDEPTH
return p_nextFDcmdsInQueue; return p_nextFDcmdsInQueue;
} }
uint8_t check4freeFDshortCmd(void)
{
// returns number of free places in short-command stack
return FDCMD_STACKDEPTH - p_nextFDcmdsInQueue;
}
// long command, 64 data bytes // long command, 64 data bytes
static uint8_t longFDwrCmd[FDLONG_STACKDEPTH]; static uint8_t longFDwrCmd[FDLONG_STACKDEPTH];
@@ -602,7 +608,7 @@ bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8
uint8_t nn; uint8_t nn;
if (p_longFDcmdsInQueue>=FDLONG_STACKDEPTH) if (p_longFDcmdsInQueue>=FDLONG_STACKDEPTH)
{ {
qCritical() << "cannot save cmd because stack is full"; qDebug() << "cannot save cmd because stack is full";
return false; // not possible return false; // not possible
} }
longFDwrCmd[p_longFDcmdsInQueue]=nextWrCmd; longFDwrCmd[p_longFDcmdsInQueue]=nextWrCmd;
@@ -613,7 +619,6 @@ bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8
longFDpara[p_longFDcmdsInQueue][nn]=data[nn]; longFDpara[p_longFDcmdsInQueue][nn]=data[nn];
p_longFDcmdsInQueue++; p_longFDcmdsInQueue++;
return true; // ok, will be sent return true; // ok, will be sent
} }
@@ -659,5 +664,41 @@ uint8_t check4FDlongCmd(void)
return p_longFDcmdsInQueue; return p_longFDcmdsInQueue;
} }
uint8_t check4freeFDlongCmd(void)
{
// returns number of free places in command stack
return FDLONG_STACKDEPTH - p_longFDcmdsInQueue;
}
static uint8_t Sdata_DeviceParameter[64];
static uint8_t Sdata_DevParaLen;
uint8_t epi_store64BdevParameter(uint8_t length, uint8_t *buf)
{
// HWapi writes data to be stored
uint8_t nn;
for (nn=0; nn<length; nn++)
Sdata_DeviceParameter[nn]=buf[nn];
for (nn=length; nn<64; nn++)
Sdata_DeviceParameter[nn]=0;
Sdata_DevParaLen=length;
return 0;
}
uint8_t epi_restore64BdevParameter(uint8_t *length, uint8_t *buf)
{
for (uint8_t nn=0; nn<Sdata_DevParaLen; nn++)
buf[nn]=Sdata_DeviceParameter[nn];
*length=Sdata_DevParaLen;
return 0;
}

View File

@@ -0,0 +1,39 @@
#include "shared_mem_buffer.h"
#include <QDebug>
#include <atomic>
#ifdef QT_POSIX_IPC
// The POSIX backend can be explicitly selected using the -feature-ipc_posix
// option to the Qt configure script. If it is enabled, the QT_POSIX_IPC
// macro will be defined. -> we use SystemV shared memory
#error "QT_POSIX_IPC defined"
#else
#include <sys/ipc.h> // ftok
#endif
// std::atomic_bool SharedMemBuffer::__sharedMemLocked{false};
QSharedMemory *SharedMemBuffer::getShm(std::size_t size) {
static QSharedMemory shMem;
if (size > 0) {
static const long nativeKey = ftok("/etc/os-release", 'H');
static const QString fkey = std::to_string(nativeKey).c_str();
shMem.setKey(fkey);
if (!shMem.isAttached()) {
if (shMem.create(size)) {
return &shMem;
} else {
if (shMem.error() == QSharedMemory::AlreadyExists) {
if (shMem.attach()) {
return &shMem;
}
}
}
qCritical() << shMem.nativeKey() << shMem.key() << shMem.data()
<< shMem.error() << shMem.errorString();
return nullptr;
}
}
return &shMem;
}

File diff suppressed because it is too large Load Diff

View File

@@ -76,6 +76,23 @@ uint8_t uint2uchar(uint16_t uival, bool getHighB)
} }
uint8_t ulong2uchar(uint32_t ulval, uint8_t getBytNr)
{
// getBytNr: 0=LSB 3=MSB
uint32_t ultmp=ulval;
if (getBytNr==0)
return uint8_t(ultmp);
ultmp>>=8;
if (getBytNr==1)
return uint8_t(ultmp);
ultmp>>=8;
if (getBytNr==2)
return uint8_t(ultmp);
ultmp>>=8;
return uint8_t(ultmp);
}
void delay(uint16_t MilliSec) void delay(uint16_t MilliSec)
{ {
QThread::msleep(uint32_t(MilliSec)); QThread::msleep(uint32_t(MilliSec));

173
OnDemandUpdatePTU.pro Normal file
View File

@@ -0,0 +1,173 @@
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.
VERSION="1.3.14"
# 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.
# PLANNED TODOS:
# 1: Das Repository wird repariert bwz. neu geklont. Unabhaengig vom WAIT.
# 2: Wenn der WAIT-Button aktiv ist, dann wird ein Repository repariert (neu
# geklont), aber zusaetzlich werden alle verfuegbaren Dateien als neu
# angesehen und die entsprechenden Aktionen durchgefuehrt: tariff-files
# spiegeln, json-files laden und dc laden. Also VORSICHT: das repository
# muss in diesem fall wirklich in ordnung sein.
# 3: Wurde keine Datei geaendert, kein initiales Clone und der WAIT-button
# nicht aktiv, so (passiert natuerlich nichts) kann man davon ausgehen,
# dass es sich um ein automatisches Update handelt. Dann koennte man im
# ISMAS eine entsprechende Meldung anzeigen als Teil von SEND-LAST-VERSION.
# Wenn der WAIT-button aktiv ist, dann werden zumindest die opkg-commands
# ausgefuehrt.
# 4: rsync: immer alle Dateien soiegeln (bis auf opkg-commands)
# 5: Falls das Tool mal abstuerzt, dann einen Signal-Handler (fuer TERM)
# installieren, sodass zumnidest SEND-LASt-VERSION mit rausgeht.
# 6: rsync: explizites Binary, nicht das in busybox enthaltene.
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
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 \
worker_thread.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 \
worker_thread.h \
plugins/interfaces.h
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
}

View File

@@ -1,56 +0,0 @@
# QT -= gui
QT += core
QT += widgets serialport
QT += network
TARGET = up_dev_ctrl
CONFIG += c++11
# CONFIG -= app_bundle
# DEFINES+=LinuxDesktop
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -std=c++11 # for GCC >= 4.7
QMAKE_CXXFLAGS += -Wno-deprecated-copy
ARCH = PTU5
DEFINES+=PTU5
}
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++11
QMAKE_CXXFLAGS += -Wno-deprecated-copy
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux
DEFINES+=DesktopLinux
}
SOURCES += \
main.cpp \
message_handler.cpp
HEADERS += \
message_handler.h \
DCPlugin/include/interfaces.h
# https://blog.developer.atlassian.com/the-power-of-git-subtree/?_ga=2-71978451-1385799339-1568044055-1068396449-1567112770
# git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
include(./DCPlugin/DCPlugin.pri)
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

126
allgemein.txt Normal file
View 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
apism/ismas_data.h Normal file
View 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

BIN
dc2c4.bin Executable file

Binary file not shown.

BIN
doc/update_ptu.pdf Normal file

Binary file not shown.

172
doc/update_ptu.tex Normal file
View 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
git/git_client.cpp Normal file
View 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
git/git_client.h Normal file
View 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

942
ismas/ismas_client.cpp Normal file
View File

@@ -0,0 +1,942 @@
#include "ismas/ismas_client.h"
#include "utils.h"
#include <cstring>
#include <cstdio>
#include <errno.h>
#include <arpa/inet.h> // inet_addr()
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#include <strings.h> // bzero()
#include <sys/socket.h>
#include <unistd.h> // read(), write(), close()
#include <fcntl.h>
#include <QThread>
#include <QJsonDocument>
#include <QJsonObject>
#if 0
########################
# Spec vom 27.10.2023:
# U0010 -> %-Werte
# U0001 -> 100%
# U0003 -> "FAIL"
# U0002 -> "" (OK -> WAIT state reset)
# ISMAS -> "WAIT"
########################
#
# $1: EVENT: U0001 update finished: 100%
# U0002 reset TRG
# U0003 error
# U0010 for update process
# $2: PERCENT : "only for ISMAS: 0-100%",
# $3: RESULTCODE : "only for ISMAS",
# 0: Success
# 1: no Update nessesary
# 2: Backup failed
# 3: Package error/ Wrong package
# 4: Install Error
# $4: STEP : "running step (only for us): update_psa...",
# $5: STEP_RESULT : "error and result text",
# $6: VERSION : "opkg and conf info; what will be updated"
#
#endif
#include <QDateTime>
#include <QDebug>
void IsmasClient::printDebugMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
#if 0
Q_UNUSED(port);
Q_UNUSED(clientIP);
Q_UNUSED(clientPort);
Q_UNUSED(message);
#else
qDebug().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
<< "hostname ........" << "127.0.0.1" << "\n"
<< "port ............" << port << "\n"
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
#endif
}
void IsmasClient::printInfoMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
#if 0
Q_UNUSED(port);
Q_UNUSED(clientIP);
Q_UNUSED(clientPort);
Q_UNUSED(message);
#else
qInfo().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
<< "hostname ........" << "127.0.0.1" << "\n"
<< "port ............" << port << "\n"
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
#endif
}
void IsmasClient::printErrorMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
qCritical().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
<< "hostname ........" << "127.0.0.1" << "\n"
<< "port ............" << port << "\n"
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
}
std::optional<QString>
IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
qInfo() << "REQUEST" << request;
int sockfd;
int r;
errno = 0;
// socket create and verification
if ((sockfd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) {
qCritical().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
<< "SOCKET CREATION FAILED (" << strerror(errno) << ")";
return std::nullopt;
}
struct sockaddr_in servAddr;
bzero(&servAddr, sizeof(servAddr));
// assign IP, PORT
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servAddr.sin_port = htons(port);
// connect the client socket to server socket
if ((r = ::connect(sockfd, (struct sockaddr *)(&servAddr), sizeof(servAddr))) != 0) {
qCritical().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
<< "CONNECTION WITH SERVER FAILED (" << strerror(r) << ")";
::close(sockfd);
return std::nullopt;
}
struct sockaddr_in clientAddr;
bzero(&clientAddr, sizeof(clientAddr));
socklen_t sockLen = sizeof(clientAddr);
char clientIP[16];
bzero(&clientIP, sizeof(clientIP));
getsockname(sockfd, (struct sockaddr *)(&clientAddr), &sockLen);
inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, sizeof(clientIP));
unsigned int clientPort = ntohs(clientAddr.sin_port);
printDebugMessage(port, clientIP, clientPort, QString("CONNECTED TO SERVER"));
struct timeval tv;
tv.tv_sec = 10; /* 10 secs timeout for read and write */
struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
int maxfdp1;
fd_set rset;
fd_set wset;
setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
// no reliable, but does not harm, as we use select() as well
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
int flag = 1;
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
static char buf[1024*8];
bzero(buf, sizeof(buf));
int const bytesToWrite = strlen(request.toStdString().c_str());
strncpy(buf, request.toStdString().c_str(), sizeof(buf)-1);
int loop = 0;
int bytesWritten = 0;
while (bytesWritten < bytesToWrite) {
errno = 0;
FD_ZERO(&wset);
FD_SET(sockfd, &wset);
maxfdp1 = sockfd + 1;
tv.tv_sec = 60; /* 60 secs timeout for read and write -> APISM cuts the connection after 30s */
tv.tv_usec = 0;
int const w = select(maxfdp1, NULL, &wset, NULL, &tv);
if (w < 0) { // error
if (errno == EINTR) {
printErrorMessage(port, clientIP, clientPort,
QString("INTERRUPTED BY SIGNAL (1) (") + strerror(errno) + ")");
continue;
} else {
printErrorMessage(port, clientIP, clientPort,
QString("SELECT-ERROR (WRITE) %1(").arg(loop) + strerror(errno) + ")");
::close(sockfd);
return std::nullopt;
}
} else
if (w == 0) { // timeout
printErrorMessage(port, clientIP, clientPort,
QString("SELECT-TIMEOUT (WRITE) %1(").arg(loop) + strerror(errno) + ")");
if (++loop < 10) {
QThread::msleep(500);
continue;
}
::close(sockfd);
return std::nullopt;
} else
if (w > 0) {
int n = ::sendto(sockfd, buf+bytesWritten, bytesToWrite-bytesWritten, 0, NULL, 0);
if (n >= 0) {
bytesWritten += n;
} else {
if (errno == EWOULDBLOCK) {
if (++loop < 10) {
QThread::msleep(500);
continue;
}
printErrorMessage(port, clientIP, clientPort,
QString("WRITE TIMEOUT %1(").arg(loop) + strerror(errno) + ")");
::close(sockfd);
return std::nullopt;
} else
if (errno == EINTR) {
printErrorMessage(port, clientIP, clientPort,
QString("WRITE INTERRUPTED BY SIGNAL (1) (") + strerror(errno) + ")");
continue;
}
}
}
}
// DO NOT USE SHUTDOWN! APISM CAN NOT COPE WITH IT
// errno = 0;
// if (shutdown(sockfd, SHUT_WR) < 0) {
// printErrorMessage(port, clientIP, clientPort,
// QString("CANNOT CLOSE WRITING END (") + strerror(errno) + ")");
// }
printInfoMessage(port, clientIP, clientPort, QString("MESSAGE SENT <<<") + buf + ">>>");
loop = 0;
bzero(buf, sizeof(buf));
int bytesToRead = sizeof(buf)-1;
int bytesRead = 0;
while (bytesRead < bytesToRead) {
errno = 0;
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
maxfdp1 = sockfd + 1;
tv.tv_sec = 60; /* 60 secs timeout for read and write */
tv.tv_usec = 0;
QString const selectStart = QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
int const r = select(maxfdp1, &rset, NULL, NULL, &tv);
if (r < 0) { // error
if (errno == EINTR) {
printErrorMessage(port, clientIP, clientPort,
QString("INTERRUPTED BY SIGNAL (2) (") + strerror(errno) + ")");
continue;
} else {
printErrorMessage(port, clientIP, clientPort,
QString("SELECT-ERROR (READ) %1(").arg(loop) + strerror(errno) + ")");
::close(sockfd);
return std::nullopt;
}
} else
if (r == 0) { // timeout
printErrorMessage(port, clientIP, clientPort,
QString("SELECT-TIMEOUT (READ) %1(").arg(loop) + strerror(errno) + ")");
if (++loop < 10) {
QThread::msleep(500);
continue;
}
::close(sockfd);
return std::nullopt;
} else
if (r > 0) {
if (FD_ISSET(sockfd, &rset)) {
int n = ::recvfrom(sockfd, buf+bytesRead, bytesToRead-bytesRead,
0, NULL, NULL);
if (n > 0) { //
bytesRead += n;
} else
if (n == 0) {
// The return value will be 0 when the peer has performed an orderly shutdown.
printErrorMessage(port, clientIP, clientPort,
QString("PEER CLOSED CONNECTION (") + strerror(errno) + ") START AT" +
selectStart + " NOW " + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
::close(sockfd);
return std::nullopt;
} else
if (n < 0) {
if (errno == EWOULDBLOCK) { // check just in case
if (++loop < 10) {
QThread::msleep(500);
continue;
}
printErrorMessage(port, clientIP, clientPort,
QString("READ TIMEOUT %1(").arg(loop) + strerror(errno) + ")");
::close(sockfd);
return std::nullopt;
}
if (errno == EINTR) {
printErrorMessage(port, clientIP, clientPort,
QString("INTERRUPTED BY SIGNAL (2) (") + strerror(errno) + ")");
continue;
}
}
}
}
// printInfoMessage(port, clientIP, clientPort, QString("MESSAGE RECEIVED ") + buf);
QString response(buf);
if (int idx = response.indexOf("{\"error\":\"ISMAS is offline\"}")) {
response = response.mid(0, idx);
} else
if (response.contains("RECORD")) { // RECORD SAVED or RECORD WRITE ABORTED
printInfoMessage(port, clientIP, clientPort, QString("IGNORED '") + response + "' RESPONSE");
::close(sockfd);
return std::nullopt;
}
QJsonParseError parseError;
QJsonDocument document(QJsonDocument::fromJson(response.toUtf8(), &parseError));
if (parseError.error == QJsonParseError::NoError) {
if (document.isObject()) { // done: received valid APISM response
printInfoMessage(port, clientIP, clientPort,
QString("VALID APISM RESPONSE .. \n") + response);
::close(sockfd);
return response;
} else {
printInfoMessage(port, clientIP, clientPort,
QString("CORRUPTED RESPONSE ") + response);
::close(sockfd);
return std::nullopt;
}
} else {
printDebugMessage(port, clientIP, clientPort,
QString("PARSE ERROR ") + response + " " + parseError.errorString());
::close(sockfd);
return std::nullopt;
}
}
return std::nullopt;
}
QString IsmasClient::updateNewsToIsmas(char const *event,
int percent,
int resultCode,
char const *step,
char const *step_result,
char const *version) {
char buf[1024];
memset(buf, 0, sizeof(buf));
QString const ts = QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
snprintf(buf, sizeof(buf)-1,
"{"
"\"REASON\":\"SW_UP\","
"\"TIMESTAMP\":\"%s\","
"\"EVENT_ID\":\"0\","
"\"EVENT\":\"%s\","
"\"EVENTSTATE\":1,"
"\"PARAMETER\": {"
"\"PERCENT\" : %d,"
"\"RESULTCODE\" : %d,"
"\"STEP\" : \"%s\","
"\"STEP_RESULT\" : \"%s\","
"\"VERSION\" : \"%s\""
"}"
"}", ts.toStdString().c_str(), event, percent, resultCode,
step, step_result, version);
return buf;
}
QString IsmasClient::errorBackendNotConnected(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
RESULT_CODE::INSTALL_ERROR,
"CHECK BACKEND CONNECTIVITY",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::errorGitClone(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
RESULT_CODE::INSTALL_ERROR,
"CLONE CUSTOMER REPOSITORY FAILED",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::backendConnected(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"CHECK BACKEND CONNECTIVITY",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::execOpkgCommand(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"EXECUTE OPKG COMMAND",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::rsyncFile(QString const &info, QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"RSYNC FILE",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::updateTriggerSet(QString const &info, QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"CHECK UPDATE TRIGGER",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::errorUpdateTrigger(QString const &info, QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
RESULT_CODE::INSTALL_ERROR,
"CHECK UPDATE TRIGGER",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
//static int const constexpr SIZE = 4096*8;
static char buf[4096*2];
memset(buf, 0, sizeof(buf));
// local data="#M=APISM#C=CMD_SENDVERSION#J=
snprintf(buf, sizeof(buf)-1,
"{"
"\"VERSION_INFO\" : {"
"\"REASON\":\"%s\","
"\"CREATED\":\"%s\","
"\"HASH\":\"%s\""
"},"
"\"TARIFF\" : {"
"\"VERSION\" : \"%s\","
"\"PROJECT\" : \"%s\","
"\"ZONE\" : %d,"
"\"INFO\" : \"%s\","
"\"BLOB\" : \"%s\","
"\"LAST-COMMIT\" : \"%s\","
"\"SIZE\" : %d,"
"\"LOADED\" : \"%s\""
"},"
"\"OPKG_COMMANDS\" : {"
"\"BLOB\" : \"%s\","
"\"LAST-COMMIT\" : \"%s\","
"\"SIZE\" : %d,"
"\"LOADED\" : \"%s\""
"},"
"\"JSON\" : {"
"\"DC2C_CASH\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_CONF\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_DEVICE\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_01\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_02\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_03\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_04\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_05\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_06\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_07\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_08\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_09\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_10\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_11\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_12\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_13\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_14\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_15\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_16\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_17\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_18\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_19\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_20\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_21\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_22\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_23\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_24\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_25\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_26\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_27\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_28\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_29\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_30\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_31\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"},"
"\"DC2C_PRINT_32\" : {"
"\"BLOB\" : \"%s\","
"\"SIZE\" : %d"
"}"
"},"
"\"HARDWARE\" : {"
"\"DEVICES\" : [\"PTU5\", \"DC\", \"PRINTER\", \"BNA\"]"
"},"
"\"OS\" : {"
"\"Linux\": \"%s\""
"},"
"\"CONFIG\" : {"
"\"PTU5\" : {"
"\"CPU_SERIAL\" : \"%s\""
"},"
"\"DC\" : {"
"\"HW-VERSION\" : \"%s\","
"\"SW-VERSION\" : \"%s\","
"\"SIZE\" : %d,"
"\"GITBLOB\" : \"%s\","
"\"GITLASTCOMMIT\" : \"%s\""
"},"
"\"PRINTER\" : {"
"},"
"\"BNA\" : {"
"}"
"},"
"\"SOFTWARE\": {"
"\"APISM\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"ATBQT\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"ATB-UPDATE-TOOL\" : {"
"\"VERSION\" : \"%s\""
"}"
"},"
"\"PLUGINS\" : {"
"\"libATBDeviceControllerPlugin.so\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"libIngenicoISelf_CCPlugin.so\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"libMOBILISIS_CalculatePricePlugin.so\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"libMOBILISIS_CalculatePricePlugin_ConfigUi.so\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"libPRM_CalculatePricePlugin.so\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"libPRM_CalculatePricePlugin_ConfigUi.so\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"libTCP_ZVT_CCPlugin.so\" : {"
"\"VERSION\" : \"%s\""
"}"
"}"
"}",
psa.versionInfo.reason.toStdString().c_str(),
psa.versionInfo.created.toStdString().c_str(),
psa.versionInfo.lastCommit.toStdString().c_str(),
psa.tariff.version.toStdString().c_str(),
psa.tariff.project.toStdString().c_str(),
psa.tariff.zone,
psa.tariff.info.toStdString().c_str(),
psa.tariff.blob.toStdString().c_str(),
psa.tariff.lastCommit.toStdString().c_str(),
psa.tariff.size,
psa.tariff.loadTime.toStdString().c_str(),
psa.opkg.blob.toStdString().c_str(),
psa.opkg.lastCommit.toStdString().c_str(),
psa.opkg.size,
psa.opkg.loadTime.toStdString().c_str(),
psa.cash.blob.toStdString().c_str(),
psa.cash.size,
psa.conf.blob.toStdString().c_str(),
psa.conf.size,
psa.device.blob.toStdString().c_str(),
psa.device.size,
psa.print[0].blob.toStdString().c_str(),
psa.print[0].size,
psa.print[1].blob.toStdString().c_str(),
psa.print[1].size,
psa.print[2].blob.toStdString().c_str(),
psa.print[2].size,
psa.print[3].blob.toStdString().c_str(),
psa.print[3].size,
psa.print[4].blob.toStdString().c_str(),
psa.print[4].size,
psa.print[5].blob.toStdString().c_str(),
psa.print[5].size,
psa.print[6].blob.toStdString().c_str(),
psa.print[6].size,
psa.print[7].blob.toStdString().c_str(),
psa.print[7].size,
psa.print[8].blob.toStdString().c_str(),
psa.print[8].size,
psa.print[9].blob.toStdString().c_str(),
psa.print[9].size,
psa.print[10].blob.toStdString().c_str(),
psa.print[10].size,
psa.print[11].blob.toStdString().c_str(),
psa.print[11].size,
psa.print[12].blob.toStdString().c_str(),
psa.print[12].size,
psa.print[13].blob.toStdString().c_str(),
psa.print[13].size,
psa.print[14].blob.toStdString().c_str(),
psa.print[14].size,
psa.print[15].blob.toStdString().c_str(),
psa.print[15].size,
psa.print[16].blob.toStdString().c_str(),
psa.print[16].size,
psa.print[17].blob.toStdString().c_str(),
psa.print[17].size,
psa.print[18].blob.toStdString().c_str(),
psa.print[18].size,
psa.print[19].blob.toStdString().c_str(),
psa.print[19].size,
psa.print[20].blob.toStdString().c_str(),
psa.print[20].size,
psa.print[21].blob.toStdString().c_str(),
psa.print[21].size,
psa.print[22].blob.toStdString().c_str(),
psa.print[22].size,
psa.print[23].blob.toStdString().c_str(),
psa.print[23].size,
psa.print[24].blob.toStdString().c_str(),
psa.print[24].size,
psa.print[25].blob.toStdString().c_str(),
psa.print[25].size,
psa.print[26].blob.toStdString().c_str(),
psa.print[26].size,
psa.print[27].blob.toStdString().c_str(),
psa.print[27].size,
psa.print[28].blob.toStdString().c_str(),
psa.print[28].size,
psa.print[29].blob.toStdString().c_str(),
psa.print[29].size,
psa.print[30].blob.toStdString().c_str(),
psa.print[30].size,
psa.print[31].blob.toStdString().c_str(),
psa.print[31].size,
psa.hw.linuxVersion.toStdString().c_str(),
psa.hw.cpuSerial.toStdString().c_str(),
psa.dc.versionHW.toStdString().c_str(),
psa.dc.versionSW.toStdString().c_str(),
psa.dc.size,
psa.dc.gitBlob.toStdString().c_str(),
psa.dc.gitLastCommit.toStdString().c_str(),
psa.sw.apismVersion.toStdString().c_str(),
psa.sw.atbQTVersion.toStdString().c_str(),
psa.sw.atbUpdateToolVersion.toStdString().c_str(),
psa.pluginVersion.deviceController.toStdString().c_str(),
psa.pluginVersion.ingenicoISelfCC.toStdString().c_str(),
psa.pluginVersion.mobilisisCalculatePrice.toStdString().c_str(),
psa.pluginVersion.mobilisisCalculatePriceConfigUi.toStdString().c_str(),
psa.pluginVersion.prmCalculatePrice.toStdString().c_str(),
psa.pluginVersion.prmCalculatePriceConfigUi.toStdString().c_str(),
psa.pluginVersion.tcpZVT.toStdString().c_str());
qInfo() << buf;
return buf;
}
QString IsmasClient::updateOfPSAContinues(QString currentStage,
QString currentStageInfo,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
currentStage.toStdString().c_str(),
currentStageInfo.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::updateOfPSAStarted(QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"START",
"detected WAIT state: start update process",
version.toStdString().c_str());
}
QString IsmasClient::checkoutBranch(QString const &info, QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"BRANCH-CHECKOUT",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::cloneAndCheckoutCustomerRepository(QString const &info, QString const &version) { // clone and checkout customer repository
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"CLONE-CHECKOUT",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::gitFetch(QString const &info, QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"GIT-FETCH",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::errorGitFetch(int resultCode, QString const &info, QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
resultCode,
"GIT-FETCH-FAILED",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::updateOfPSAActivated(QString const &version) { // sent even after success
m_progressInPercent = 0;
return updateNewsToIsmas("U0002",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"UPDATE ACTIVATED",
"reset WAIT state",
version.toStdString().c_str());
}
QString IsmasClient::updateOfPSASucceeded(QString const &version) {
m_progressInPercent = 100;
return updateNewsToIsmas("U0001",
m_progressInPercent,
RESULT_CODE::SUCCESS,
"UPDATE SUCCESS",
"update process succeeded",
version.toStdString().c_str());
}
QString IsmasClient::sanityCheckFailed(int resultCode, QString reason, QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
resultCode,
"SANITY-CHECK-FAILED",
reason.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::jsonParseFailed(int resultCode, QString reason, QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
resultCode,
"JSON-PARSE-ERROR",
reason.toStdString().c_str(),
version.toStdString().c_str());
}
std::optional<QString> IsmasClient::finalResult(int resultCode,
QString reason,
QString const &version) {
Q_UNUSED(resultCode);
Q_UNUSED(reason);
Q_UNUSED(version);
/*
m_progressInPercent = 100;
if (resultCode == RESULT_CODE::SUCCESS) {
return updateNewsToIsmas("U0002",
m_progressInPercent,
resultCode,
"FINAL-UPDATE-RESULT",
reason.toStdString().c_str(),
version.toStdString().c_str());
}
if (resultCode == RESULT_CODE::INSTALL_ERROR) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
resultCode,
"FINAL-UPDATE-RESULT",
reason.toStdString().c_str(),
version.toStdString().c_str());
}
*/
return std::nullopt;
}
QString IsmasClient::updateOfPSAFailed(int resultCode, QString step,
QString reason, QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
resultCode,
step.toStdString().c_str(),
reason.toStdString().c_str(),
version.toStdString().c_str());
}
char const *IsmasClient::reason[REASON::ENTRIES] = {
"TIME-TRIGGERED", "SERVICE", "DEV-TEST"
};
QString IsmasClient::getReasonForLastSendVersion() {
QString const &parentName = Utils::getParentName();
if (parentName == "ATBQT") {
return reason[REASON::SERVICE];
}
if (parentName == "systemd") {
return reason[REASON::TIME_TRIGGERED];
}
return reason[REASON::DEV_TEST];
}

208
ismas/ismas_client.h Normal file
View File

@@ -0,0 +1,208 @@
#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 {
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 {
int size;
QString blob;
QString lastCommit;
QString loadTime;
} opkg;
struct DC {
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 {
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());
QString updateOfPSASendVersion(PSAInstalled const &psa);
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

247
main.cpp
View File

@@ -4,14 +4,40 @@
#include <QTimer> #include <QTimer>
#include <QFileInfo> #include <QFileInfo>
#include "message_handler.h" #ifdef __linux__
#include "interfaces.h" #include <stdlib.h> // system()
#endif
#include "DCPlugin/include/hwapi.h" #include "message_handler.h"
#include "plugins/interfaces.h"
#include <unistd.h> #include <unistd.h>
#include <thread>
#include <memory> #include <memory>
#include <QSharedMemory>
#include <QRunnable>
#include <QThreadPool>
#include <QDir>
#include <QProcess>
#include <QCommandLineParser>
#include <QStandardPaths>
#include <QMainWindow>
#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 #ifdef PTU5
#define SERIAL_PORT "ttymxc2" #define SERIAL_PORT "ttymxc2"
@@ -19,70 +45,175 @@
#define SERIAL_PORT "ttyUSB0" #define SERIAL_PORT "ttyUSB0"
#endif #endif
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
QVector<int> nrOfTemplate,
QVector<QString> fileToSendToDC,
QString br, QString serial) {
for (int i=0; i < 1;++i) {
hw->dc_updatePrinterTemplate(hwapi::FileTypeJson::PRINTER,
nrOfTemplate, fileToSendToDC,
br, serial);
hw->dc_printTemplate(hwapi::FileTypeJson::PRINTER,
nrOfTemplate, br, serial);
}
QCoreApplication::quit();
}
// argv[1]: file to send to dc // argv[1]: file to send to dc
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QByteArray const value = qgetenv("LC_ALL");
if (value != "C") {
qputenv("LC_ALL", "C");
}
// qputenv("XDG_RUNTIME_DIR", "/run/user/0");
openlog("ATB-UPDATE", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
QApplication a(argc, argv); QApplication a(argc, argv);
QApplication::setApplicationName("ATBUpdateTool");
QApplication::setApplicationVersion(APP_VERSION);
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(atbDebugOutput); atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(QtMsgType::QtDebugMsg); setDebugLevel(LOG_NOTICE);
//setDebugLevel(QtMsgType::QtDebugMsg);
} }
if (argc > 2) { //#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
qCritical() << "Usage: " << argv[0] << "<file to send to dc>"; //#ifdef _POSIX_THREAD_PROCESS_SHARED
return -1; // errno = 0;
// int res = 0;
// if ((res = sysconf(_SC_THREAD_PROCESS_SHARED)) < 0) {
// if (errno != 0) {
// qCritical() << "_POSIX_THREAD_PROCESS_SHARED NOT SUPPORTED"
// << strerror(errno);
// exit(-1);
// }
// } else {
// if (res == _POSIX_THREAD_PROCESS_SHARED) {
// Utils::printInfoMsg("_POSIX_THREAD_PROCESS_SHARED SUPPORTED");
// }
// }
//#endif
//#endif
QCommandLineParser parser;
parser.setApplicationDescription("Download tool for downloading device controller firmware, printer json-files and executing opkg-commands.");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption pluginDirectoryOption(QStringList() << "plugin-directory" << "plugin-directory",
QCoreApplication::translate("main", "Where to find dc-plugin."),
QCoreApplication::translate("main", "directory"));
QString const pluginDefault = "/usr/lib";
pluginDirectoryOption.setDefaultValue(pluginDefault);
parser.addOption(pluginDirectoryOption);
QCommandLineOption pluginNameOption(QStringList() << "plugin-name" << "plugin-name",
QCoreApplication::translate("main", "Name of dc-plugin."),
QCoreApplication::translate("main", "directory"));
QString const pluginNameDefault = "libCAslave.so";
pluginNameOption.setDefaultValue(pluginNameDefault);
parser.addOption(pluginNameOption);
QCommandLineOption workingDirectoryOption(QStringList() << "working-directory" << "working-directory",
QCoreApplication::translate("main", "working directory of update-script."),
QCoreApplication::translate("main", "directory"));
QString const workingDirectoryDefault = "/opt/app/tools/atbupdate";
workingDirectoryOption.setDefaultValue(workingDirectoryDefault);
parser.addOption(workingDirectoryOption);
QCommandLineOption dryRunOption(QStringList() << "d" << "dry-run",
QCoreApplication::translate("main", "Start ATBUpdateTool in dry-run-mode. No actual actions."));
parser.addOption(dryRunOption);
QCommandLineOption extendedVersionOption(QStringList() << "V" << "extended-version",
QCoreApplication::translate("main", "Show extended version (including last git commit)."));
parser.addOption(extendedVersionOption);
QCommandLineOption yoctoVersionOption(QStringList() << "y" << "yocto-version",
QCoreApplication::translate("main", "Show yocto version of ATBUpdateTool."));
parser.addOption(yoctoVersionOption);
QCommandLineOption yoctoInstallStatusOption(QStringList() << "Y" << "yocto-install",
QCoreApplication::translate("main", "Show yocto install status of ATBUpdateTool."));
parser.addOption(yoctoInstallStatusOption);
// Process the actual command line arguments given by the user
parser.process(a);
QString plugInDir = parser.value(pluginDirectoryOption);
QString plugInName = parser.value(pluginNameOption);
QString workingDir = parser.value(workingDirectoryOption);
bool const dryRun = parser.isSet(dryRunOption);
bool const showYoctoVersion = parser.isSet(yoctoVersionOption);
bool const showYoctoInstallStatus = parser.isSet(yoctoInstallStatusOption);
bool const showExtendedVersion = parser.isSet(extendedVersionOption);
QString const rtPath = QCoreApplication::applicationDirPath();
int machineNr = Utils::read1stLineOfFile("/etc/machine_nr");
int customerNr = Utils::read1stLineOfFile("/etc/cust_nr");
int zoneNr = Utils::read1stLineOfFile("/etc/zone_nr");
QString const branchName = (zoneNr != 0)
? QString("zg1/zone%1").arg(zoneNr) : "master";
QThread::currentThread()->setObjectName("main thread");
qInfo() << "Main thread" << QThread::currentThreadId();
if (showExtendedVersion) {
printf(APP_EXTENDED_VERSION"\n");
return 0;
} }
std::unique_ptr<hwinf> hw(new hwapi()); if (showYoctoVersion) {
QFileInfo fileInfo(argv[1]); printf("%s\n", Worker::getATBUpdateToolYoctoVersion().toStdString().c_str());
QString fname(fileInfo.fileName()); return 0;
int ret = 0;
if (fname.startsWith("dc") && fname.endsWith(".bin")) {
std::thread t(updateBinary, std::move(hw),
fname.toStdString().c_str(), "115200", SERIAL_PORT);
ret = a.exec();
t.join();
} else {
QVector<QString> fnames{"DC2C_print01.json",
"DC2C_print02.json",
"DC2C_print03.json"};
QVector<int> templateIdx{1,2,3};
//if (fname.startsWith("DC2C_print") && fname.endsWith(".json")) {
//int const nrOfTemplate = fname.midRef(10, 2).toInt();
std::thread t(updatePrinterConf, std::move(hw), templateIdx, fnames,
"115200", SERIAL_PORT);
ret = a.exec();
t.join();
//}
} }
return ret; if (showYoctoInstallStatus) {
printf("%s\n", Worker::getATBUpdateToolYoctoInstallationStatus().toStdString().c_str());
return 0;
}
if (!QDir(plugInDir).exists()) {
qCritical() << plugInDir
<< "does not exists, but has to contain dc-library";
exit(-1);
}
qInfo() << "pwd ......................" << rtPath;
qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir;
qInfo() << "dryRun ..................." << dryRun;
qInfo() << "extended-version ........." << APP_EXTENDED_VERSION;
//qInfo() << "yocto-version ............" << Worker::getATBUpdateToolYoctoVersion();
//qInfo() << "yocto-install-status ....." << Worker::getATBUpdateToolYoctoInstallationStatus();
// before loading the library, delete all possible shared memory segments
#if defined Q_OS_LINUX || defined Q_OS_UNIX
// system("rm -rf /tmp/qipc*");
#else
#error "Only tested under UNIX/LINUX"
#endif
hwinf *hw = Update::loadDCPlugin(QDir(plugInDir), plugInName);
hw->dc_autoRequest(true);
// hw->dc_openSerial(5, "115200", "ttymxc2", 1);
Worker worker(customerNr,
machineNr,
zoneNr,
branchName,
plugInName,
workingDir,
dryRun);
QString const customerNrStr(
QString("customer_") + QString::number(customerNr).rightJustified(3, '0'));
QScopedPointer<Update> update(
new Update(hw,
&worker,
QDir::cleanPath(workingDir + QDir::separator() + customerNrStr),
customerNrStr,
branchName,
plugInName,
workingDir,
dryRun,
nullptr,
SERIAL_PORT,
"115200"));
MainWindow mw(hw, &worker, update.get());
worker.setMainWindow(&mw);
mw.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
mw.showFullScreen();
return a.exec();
} }

81
main.cpp.bck Normal file
View 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
main.cpp.bck2 Normal file
View 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
main.cpp.bck3 Normal file
View 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;
}

480
mainwindow.cpp Normal file
View File

@@ -0,0 +1,480 @@
#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>
#if EMERGENCY_LEAVE_BL==1
static int step = 0;
void MainWindow::emergencyLeaveBL() {
//
qCritical() << __func__ << step;
switch(step) {
case 0:
if (m_hw->dc_openSerial(5, "115200", "ttymxc2", 1)) {
qCritical() << __func__ << "open ok";
step++;
QThread::msleep(2000);
m_hw->dc_autoRequest(false);
emit leaveBL();
}
break;
case 1:
m_hw->bl_rebootDC();
QThread::msleep(1000);
qCritical() << __func__ << "reboot ok" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
step++;
emit leaveBL();
break;
case 2:
case 3:
case 4:
case 5:
case 6:
m_hw->bl_startBL();
QThread::msleep(1000);
qCritical() << __func__ << "start" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
step++;
emit leaveBL();
break;
case 7:
case 9:
case 11:
case 13:
case 15:
m_hw->bl_checkBL();
qCritical() << __func__ << "check" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
QThread::msleep(1500);
++step;
emit leaveBL();
break;
case 8:
case 10:
case 12:
case 14:
case 16:
qCritical() << __func__ << "is Up..." << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
if (m_hw->bl_isUp()) {
qCritical() << __func__ << "is Up...OK" << step << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
QThread::msleep(5000);
step = 16;
} else {
qCritical() << __func__ << "is Up...NO" << step << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
}
++step;
emit leaveBL();
break;
case 17:
case 18:
case 19:
qCritical() << __func__ << "stop" << QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
m_hw->bl_stopBL();
QThread::msleep(1000);
//m_hw->dc_closeSerial();
++step;
emit leaveBL();
break;
}
}
#endif
MainWindow::MainWindow(hwinf *hw, Worker *worker, Update *update, QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_hw(hw)
, m_worker(worker)
, m_width(70)
, m_progressRunning(false)
// , m_progressValue(0)
, m_update(update)
, m_updateStep(UpdateDcEvent::UpdateStep::NONE) {
#if EMERGENCY_LEAVE_BL==1
QTimer *t = new QTimer(this);
connect(t, SIGNAL(timeout()), this, SLOT(emergencyLeaveBL()));
connect(this, SIGNAL(leaveBL()), this, SLOT(emergencyLeaveBL()), Qt::QueuedConnection);
t->setSingleShot(true);
t->start(1000);
return;
#endif
this->setStatusBar(new QStatusBar(this));
QFont f;
f.setStyleHint(QFont::Monospace);
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(update()));
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 !!!";
}
} else
if (event->type() == UpdateDcEvent::type()) {
UpdateDcEvent *pevent = (UpdateDcEvent *)event;
UpdateDcEvent::UpdateStep const updateStep = pevent->updateStep();
QObject const *sender = pevent->sender();
if (sender == m_worker) {
QDateTime const &recv = QDateTime::currentDateTime();
QDateTime const &send = pevent->sendDateTime();
qint64 const delay = recv.toMSecsSinceEpoch() - send.toMSecsSinceEpoch();
switch(updateStep) {
case UpdateDcEvent::UpdateStep::NONE:
break;
case UpdateDcEvent::UpdateStep::DC_REBOOT: {
m_hw->bl_rebootDC();
QString msg = QDateTime::currentDateTime().toString(Qt::ISODateWithMs)
+ QString(": reset device controller (delay=%1ms").arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_updateStep = UpdateDcEvent::UpdateStep::DC_REBOOT;
} break;
case UpdateDcEvent::UpdateStep::BL_START: {
QString const &msg = recv.toString(Qt::ISODateWithMs)
+ QString(": start bootloader (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_hw->bl_startBL();
if (pevent->count() == BL_START_COUNT) {
m_updateStep = UpdateDcEvent::UpdateStep::BL_START;
}
} break;
case UpdateDcEvent::UpdateStep::BL_CHECK: {
if (m_updateStep != UpdateDcEvent::UpdateStep::BL_IS_UP) {
QString const &msg = recv.toString(Qt::ISODateWithMs)
+ QString(": request bootloader version (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_hw->bl_checkBL();
//m_updateStep = UpdateDcEvent::UpdateStep::BL_CHECK;
}
} break;
case UpdateDcEvent::UpdateStep::BL_IS_UP: {
QString msg = recv.toString(Qt::ISODateWithMs)
+ QString(": check running bootloader (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
if (m_updateStep != UpdateDcEvent::UpdateStep::BL_IS_UP) {
if (m_hw->bl_isUp()) {
msg = recv.toString(Qt::ISODateWithMs)
+ QString(": bootloader running (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_updateStep = UpdateDcEvent::UpdateStep::BL_IS_UP;
} else {
msg = recv.toString(Qt::ISODateWithMs)
+ QString(": bootloader stop requested (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
if (m_updateStep == UpdateDcEvent::UpdateStep::BL_STOP) {
msg = QDateTime::currentDateTime().toString(Qt::ISODateWithMs)
+ QString(": bootloader down (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
m_updateStep = UpdateDcEvent::UpdateStep::BL_IS_DOWN;
}
}
}
} break;
case UpdateDcEvent::UpdateStep::BL_STOP: {
QString const &msg = QDateTime::currentDateTime().toString(Qt::ISODateWithMs)
+ QString(": stop bootloader (%1, delay=%2ms)").arg(pevent->count()).arg(delay);
emit m_worker->showStatusMessage("dc update", msg);
Utils::printInfoMsg(msg.toUpper());
//if (m_bootLoaderIsUp) {
m_hw->bl_stopBL();
m_updateStep = UpdateDcEvent::UpdateStep::BL_STOP;
//}
} break;
default: ;
}
}
}
QThread::yieldCurrentThread();
}
void MainWindow::onStopStartTimer() {
m_startTimer->stop();
}
void MainWindow::onDisableExit() {
ui->exit->setEnabled(false);
}
void MainWindow::onEnableExit() {
ui->exit->setEnabled(true);
}
//bool MainWindow::eventFilter(QObject *obj, QEvent *ev) {
// if (obj == ui->updateStatus) {
// qCritical() << "REc. event for text edit" << ev->type();
// }
// return QMainWindow::eventFilter(obj, ev);
//}
void MainWindow::onRestartExitTimer() {
m_exitTimer->stop();
m_exitTimer->start(60 * 1000);
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) {
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), "");
}
}

85
mainwindow.h Normal file
View File

@@ -0,0 +1,85 @@
#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;
// bool eventFilter(QObject *obj, QEvent *ev) override;
public:
MainWindow(hwinf *hw, Worker *worker, Update *update, 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;
// int progressValue() const { return m_progressValue; }
hwinf *getPlugin() { return m_hw; }
hwinf const *getPlugin() const { return m_hw; }
Update *getUpdate() { return m_update; }
Update const *getUpdate() const { return m_update; }
UpdateDcEvent::UpdateStep updateStep() const { return m_updateStep; }
void setUpdateStep(UpdateDcEvent::UpdateStep updateStep) { m_updateStep = updateStep; }
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;
hwinf *m_hw;
Worker *m_worker;
int const m_width;
QTimer *m_startTimer;
QTimer *m_exitTimer;
bool m_progressRunning;
//int m_progressValue;
Update *m_update;
UpdateDcEvent::UpdateStep m_updateStep;
};
#endif // MAINWINDOW_H

75
mainwindow.ui Normal file
View 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>

View File

@@ -2,15 +2,17 @@
#include <QDateTime> #include <QDateTime>
#include <cstring> #include <cstring>
#include <QString>
#define OUTPUT_LEN (20) #include <QFileInfo>
#include <QMessageLogContext>
static char const *DBG_NAME[] = { "DBG ", "WARN ", "CRIT ", "FATAL", "INFO " };
static bool installedMsgHandler = false; static bool installedMsgHandler = false;
static QtMsgType debugLevel = QtInfoMsg; static int debugLevel = LOG_NOTICE;
QtMsgType getDebugLevel() { return debugLevel; } int getDebugLevel() { return debugLevel; }
void setDebugLevel(QtMsgType newDebugLevel) { void setDebugLevel(int newDebugLevel) {
debugLevel = newDebugLevel; debugLevel = newDebugLevel;
} }
@@ -41,108 +43,53 @@ QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) {
/// return app.exec(); /// return app.exec();
/// } /// }
/// ///
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
void atbDebugOutput(QtMsgType type, const char *msg) {
switch (type) {
case QtDebugMsg: {
if (debugLevel <= QtDebugMsg) {
fprintf(stderr, "%*.*s Debug: %s\n", OUTPUT_LEN, OUTPUT_LEN,
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
}
} break;
case QtInfoMsg: {
if (debugLevel <= QtInfoMsg) {
fprintf(stderr, "%*.*s Info: %s\n", OUTPUT_LEN, OUTPUT_LEN,
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
}
} break;
case QtWarningMsg: {
if (debugLevel <= QtWarningMsg) {
fprintf(stderr, "%*.*s Warning: %s\n", OUTPUT_LEN, OUTPUT_LEN,
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
}
} break;
case QtCriticalMsg: {
if (debugLevel <= QtCriticalMsg) {
fprintf(stderr, "%*.*s Critical: %s\n", OUTPUT_LEN, OUTPUT_LEN,
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
}
} break;
case QtFatalMsg: {
if (debugLevel <= QtFatalMsg) {
fprintf(stderr, "%*.*s Fatal: %s\n", OUTPUT_LEN, OUTPUT_LEN,
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
}
// abort();
} break;
default: {
fprintf(stderr, "%*.*s No ErrorLevel defined! %s\n", OUTPUT_LEN, OUTPUT_LEN,
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
}
}
}
#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
static constexpr const char *format = "dd.MM.yyyy hh:mm:ss"; Q_UNUSED(context);
QByteArray localMsg = msg.toLocal8Bit(); QString const localMsg = QString(DBG_NAME[type]) + msg.toLocal8Bit();
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : ""; switch (debugLevel) {
const char *p = std::strstr(function, "::"); case LOG_DEBUG: { // debug-level message
if (p) { syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
function = p + 2; } break;
} case LOG_INFO: { // informational message
char const* output = std::strrchr(file, '/'); if (type != QtDebugMsg) {
if (output) { syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
file = output + 1;
}
qint64 const currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
int const fractional_part = currentMSecsSinceEpoch % 1000;
QDateTime const datetime = QDateTime::fromMSecsSinceEpoch(currentMSecsSinceEpoch);
switch (type) {
case QtDebugMsg: {
if (debugLevel <= QtDebugMsg) {
// fprintf(stderr, "%*.*s CTX %s (%s:%u) ->\n", OUTPUT_LEN, OUTPUT_LEN,
// "", function, file, context.line);
//fprintf(stderr, "%*.*s.%03d DEBG %s\n", OUTPUT_LEN, OUTPUT_LEN,
// datetime.toString(format).toStdString().c_str(), fractional_part,
// localMsg.constData());
fprintf(stderr, "%*.*s.%03d DEBUG %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN,
datetime.toString(format).toStdString().c_str(), fractional_part,
localMsg.constData(), file, context.line);
} }
} break; } break;
case QtInfoMsg: { case LOG_NOTICE: { // normal, but significant, condition
if (debugLevel <= QtInfoMsg) { if (type != QtDebugMsg) {
fprintf(stderr, "%*.*s.%03d INFO %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN, syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
datetime.toString(format).toStdString().c_str(), fractional_part,
localMsg.constData(), file, context.line);
} }
} break; } break;
case QtWarningMsg: { case LOG_WARNING: { // warning conditions
if (debugLevel <= QtWarningMsg) { if (type != QtInfoMsg && type != QtDebugMsg) {
fprintf(stderr, "%*.*s.%03d WARN %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN, syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
datetime.toString(format).toStdString().c_str(), fractional_part,
localMsg.constData(), file, context.line);
} }
} break; } break;
case QtCriticalMsg: { case LOG_ERR: { // error conditions
if (debugLevel <= QtCriticalMsg) { if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
fprintf(stderr, "%*.*s.%03d CRIT %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN, syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
datetime.toString(format).toStdString().c_str(), fractional_part,
localMsg.constData(), file, context.line);
} }
} break; } break;
case QtFatalMsg: { case LOG_CRIT: { // critical conditions
if (debugLevel <= QtFatalMsg) { if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) {
fprintf(stderr, "%*.*s.%03d FATAL %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN, syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str());
datetime.toString(format).toStdString().c_str(), fractional_part, }
localMsg.constData(), file, context.line); } 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; } break;
default: { default: {
fprintf(stderr, "%*.*s.%03d No ErrorLevel defined! %s\n", OUTPUT_LEN, OUTPUT_LEN, //fprintf(stderr, "%s No ErrorLevel defined! %s\n",
datetime.toString(format).toStdString().c_str(), fractional_part, // datetime.toStdString().c_str(), msg.toStdString().c_str());
msg.toStdString().c_str());
} }
} }
} }

View File

@@ -2,9 +2,12 @@
#define MESSAGE_HANDLER_H_INCLUDED #define MESSAGE_HANDLER_H_INCLUDED
#include <QtGlobal> #include <QtGlobal>
#ifdef __linux__
#include <syslog.h>
#endif
QtMsgType getDebugLevel(); int getDebugLevel();
void setDebugLevel(QtMsgType newDebugLevel); void setDebugLevel(int newDebugLevel);
bool messageHandlerInstalled(); bool messageHandlerInstalled();
QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler); QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler);

File diff suppressed because it is too large Load Diff

BIN
plugins/libCAmaster.so Executable file

Binary file not shown.

111
process/command.cpp Normal file
View File

@@ -0,0 +1,111 @@
#include "command.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
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);
}
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) {
qDebug() << "EXECUTED" << m_command
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
return true;
} else {
qCritical() << "EXECUTED" << m_command
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
}
} else {
qCritical() << "PROCESS" << m_command << "CRASHED with code"
<< p->exitCode()
<< "IN" << p->workingDirectory();
}
} else {
qCritical() << "PROCESS" << m_command
<< "DID NOT FINISH WITH" << wait
<< "MS IN" << p->workingDirectory();
}
} else {
qCritical() << "WRONG PROCESS STATE" << p->state()
<< "IN" << p->workingDirectory();
}
} else {
qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"
<< "IN" << p->workingDirectory();
}
return false;
}

35
process/command.h Normal file
View 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
progress_event.cpp Normal file
View 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
progress_event.h Normal file
View 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

861
update.cpp Normal file
View File

@@ -0,0 +1,861 @@
#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);
}
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(hwinf *hw,
Worker *worker,
QString customerRepository,
QString customerNrStr,
QString branchName,
QString pluginName,
QString workingDir,
bool dryRun,
QObject *parent,
char const *serialInterface,
char const *baudrate)
: QObject(parent)
, m_hw(hw)
, 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) {
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() {
}
Update::DownloadResult Update::sendStatus(int ret) const {
switch (ret) { // return values of dc are:
case 0: // 0: no answer by now
return DownloadResult::NOP; // 1: error
case 10: // 10: success
return DownloadResult::OK;
default:;
}
return DownloadResult::ERROR;
}
Update::DownloadResult Update::sendNextAddress(int bNum) const {
// sends address only if blockNumber is one of 0, 1024, 2048, 3072, 4096
int noAnswerCount = 0;
int errorCount = 0;
if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) {
// qDebug() << "addr-block" << bNum << "...";
while (noAnswerCount <= 250) {
m_hw->bl_sendAddress(bNum);
QThread::msleep(100);
DownloadResult const res = sendStatus(m_hw->bl_wasSendingAddOK());
if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) {
if (++errorCount >= 10) {
qCritical() << "addr-block" << bNum << "...FAILED";
return res;
}
} else { // res == DownloadResult::OK
// qInfo() << "addr-block" << bNum << "...OK";
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
// blockNumber is not one of 0, 1024, 2048, 3072, 4096 -> do nothing
return DownloadResult::NOP;
}
Update::DownloadResult Update::sendNextDataBlock(QByteArray const &binary,
int bNum) const {
uint8_t local[66];
int const bAddr = bNum * 64;
int noAnswerCount = 0;
int errorCount = 0;
memcpy(local, binary.constData() + bAddr, 64);
local[64] = local[65] = 0x00;
// QByteArray b((const char *)(&local[0]), 64);
// qCritical() << "SNDB" << bNum << b.size() << b.toHex();
while (noAnswerCount <= 250) {
m_hw->bl_sendDataBlock(64, local);
QThread::msleep(10);
DownloadResult const res = sendStatus(m_hw->bl_wasSendingDataOK());
if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) {
if (++errorCount >= 10) {
qCritical() << "data for block" << bNum << "...FAILED";
return res;
}
} else {
// qInfo() << "data for block" << bNum << "OK";
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
Update::DownloadResult Update::dc_downloadBinary(QByteArray const &b) const {
int const nBlocks = (((b.size())%64)==0) ? (b.size()/64) : (b.size()/64)+1;
// fill lst block of data to be sent with 0xFF
QByteArray ba = b.leftJustified(nBlocks*64, (char)(0xFF));
qInfo() << "total number of bytes to send to dc" << ba.size();
qInfo() << "total number of blocks to send to dc" << nBlocks;
int bNum = 0;
DownloadResult res = DownloadResult::OK;
fprintf(stderr, "\n64-byte block %04d ", bNum);
while (res != DownloadResult::ERROR && bNum < nBlocks) {
if ((res = sendNextAddress(bNum)) != DownloadResult::ERROR) {
if ((res = sendNextDataBlock(ba, bNum)) != DownloadResult::ERROR) {
bNum += 1;
fprintf(stderr, ".");
if ((bNum % 80) == 0) {
fprintf(stderr, "\n64-byte block %04d ", bNum);
}
}
}
}
fprintf(stderr, "\nlast 64-byte block %04d\n", bNum);
int const rest = ba.size() % 64;
int const offset = ba.size() - rest;
char const *startAddress = ba.constData() + offset;
if (rest > 0) {
// SHOULD NEVER HAPPEN !!!
uint8_t local[66];
memset(local, 0xFF, sizeof(local));
memcpy(local, startAddress, rest);
qCritical() << "ERROR SEND REMAINING" << rest << "BYTES";
m_hw->bl_sendDataBlock(64, local);
}
m_hw->bl_sendLastBlock();
qInfo() << "last result" << (int)sendStatus(m_hw->bl_wasSendingDataOK());
return res;
}
bool Update::startBootloader() const { // deprecated
return false;
#if 0
int nStartTry = 5;
while (--nStartTry >= 0) {
m_hw->bl_startBL();
QThread::msleep(500);
int nCheckTry = 10;
while (--nCheckTry >= 0) {
m_hw->bl_checkBL();
QThread::msleep(500);
if (m_hw->bl_isUp()) {
qInfo() << "starting bootloader...OK";
return true;
} else {
qCritical() << "bootloader not up ("
<< nStartTry << "," << nCheckTry << ")" << QThread::currentThread();
}
}
}
qCritical() << "starting bootloader...FAILED" << QThread::currentThread();
return false;
#endif
}
bool Update::stopBootloader() const {
// stop bootloader: this MUST work -> otherwise the PSA has to be restarted
// manually
emit m_worker->showErrorMessage("dc update", "stopping bootloader...");
int nTryFinalize = 1; // could do this in an endless loop
do {
// in principle, any value except BL_STOP will do, as we want to detect
// change to BL_STOP
m_worker->mainWindow()->setUpdateStep(UpdateDcEvent::UpdateStep::BL_CHECK);
QApplication::postEvent(
m_worker->mainWindow(),
new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::BL_STOP, nTryFinalize));
QThread::sleep(1);
int const cntLimit = 20;
int cnt = 0;
while (++cnt < cntLimit &&
m_worker->mainWindow()->updateStep() != UpdateDcEvent::UpdateStep::BL_STOP) {
// wait until bl_stopBL() has been sent
QThread::msleep(500);
}
QApplication::postEvent(
m_worker->mainWindow(),
new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::BL_CHECK, nTryFinalize));
QThread::sleep(1);
QApplication::postEvent(
m_worker->mainWindow(),
new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::BL_IS_UP, nTryFinalize));
QThread::sleep(1);
cnt = 0;
while (++cnt < cntLimit &&
m_worker->mainWindow()->updateStep() != UpdateDcEvent::UpdateStep::BL_IS_DOWN) {
// wait until done
QThread::msleep(200);
}
} while (++nTryFinalize <= MainWindow::BL_STOP_COUNT &&
m_worker->mainWindow()->updateStep() != UpdateDcEvent::UpdateStep::BL_IS_DOWN);
return (m_worker->mainWindow()->updateStep() == UpdateDcEvent::UpdateStep::BL_IS_DOWN);
}
// 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();
}
bool Update::resetDeviceController() const { // deprecated
return false;
#if 0
qDebug() << "resetting device controller...";
m_hw->bl_rebootDC();
// wait maximally 3 seconds, before starting bootloader
qInfo() << "resetting device controller...OK";
return true;
#endif
}
QByteArray Update::loadBinaryDCFile(QString filename) const {
qDebug() << "loading dc binary" << filename << "...";
QFile file(filename); // closed in destructor call
if (!file.exists()) {
qCritical() << file.fileName() << "does not exist";
return QByteArray();
}
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "cannot open file" << file.fileName();
return QByteArray();
}
qInfo() << "loading dc binary" << filename << "...OK";
return file.readAll();
}
bool Update::downloadBinaryToDC(QString const &bFile) const {
qDebug() << "sending" << bFile << "to dc...";
QByteArray const dcBinary = loadBinaryDCFile(bFile);
if (dcBinary.size() > 0) {
if (dc_downloadBinary(dcBinary) != DownloadResult::OK) {
qCritical() << "sending" << bFile << "to dc...FAILED";
return false;
} else {
qInfo() << "sending" << bFile << "to dc...OK";
}
} else {
qCritical() << "sending" << bFile << "to dc...FAILED";
qCritical() << "loading binary" << bFile << "FAILED";
return false;
}
return true;
}
/*
///////////////////////////////////////////////////////////////////////////////
//
// 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(char const *fileToSendToDC) {
qInfo() << "UPDATING DEVICE CONTROLLER FIRMWARE BINARY" << fileToSendToDC;
QFile fn(fileToSendToDC);
bool r;
if ((r = fn.exists()) == true) {
QFileInfo fi(fn);
if ((r = updateDC(fileToSendToDC)) == true) {
Utils::printInfoMsg(
QString(" UPDATING BINARY ") + fi.fileName()
+ QString(" (size=%1").arg(fi.size()) + ") DONE");
} else {
Utils::printCriticalErrorMsg(
QString(" UPDATING BINARY ") + fi.fileName()
+ QString(" (size=%1").arg(fi.size()) + ") FAILED");
}
} else {
Utils::printCriticalErrorMsg(
QString(fileToSendToDC) + " DOES NOT EXIST -> NO UPDATE OF DC FIRMWARE");
}
return r;
}
bool Update::updateDC(QString bFile) const {
qDebug() << "IN UPDATEDC: UPDATING DC: FILE TO SEND" << bFile;
m_worker->mainWindow()->setUpdateStep(UpdateDcEvent::UpdateStep::NONE);
QApplication::postEvent( // step 1: reset device controller
m_worker->mainWindow(),
new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::DC_REBOOT, 1));
QThread::sleep(1);
for (int i=1; i <= MainWindow::BL_START_COUNT; ++i) {
QApplication::postEvent( // step 2: start bootloader (5x)
m_worker->mainWindow(),
new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::BL_START, i));
QThread::sleep(1);
}
int const cntLimit = 100; // wait until its for sure that bl_startBL()
int cnt = 0; // has been excuted
while (++cnt < cntLimit &&
m_worker->mainWindow()->updateStep() != UpdateDcEvent::UpdateStep::BL_START) {
// wait until all bl_startBL() are done
QThread::msleep(200);
}
if (cnt == cntLimit) {
// start events not received ???
Utils::printCriticalErrorMsg("BL_START EVENT NOT RECEIVED AFTER 20 SECS");
return false;
}
m_worker->mainWindow()->setUpdateStep(UpdateDcEvent::UpdateStep::BL_CHECK);
for (int i=1; i <= MainWindow::BL_IS_UP_COUNT; ++i) {
QApplication::postEvent(m_worker->mainWindow(), new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::BL_CHECK, i));
QThread::sleep(1);
QApplication::postEvent(m_worker->mainWindow(), new UpdateDcEvent(m_worker, UpdateDcEvent::UpdateStep::BL_IS_UP, i));
if (m_worker->mainWindow()->updateStep() == UpdateDcEvent::UpdateStep::BL_IS_UP) {
break;
}
QThread::sleep(1);
}
cnt = 0;
while (++cnt < cntLimit &&
m_worker->mainWindow()->updateStep() != UpdateDcEvent::UpdateStep::BL_IS_UP) {
// wait until all bl_startBL() are done
QThread::msleep(200);
}
if (cnt == cntLimit) {
// really not up
Utils::printCriticalErrorMsg("BL_IS_UP EVENT NOT RECEIVED AFTER 20 SECS");
stopBootloader(); // try to stop bootloader whichhas been already started
return false;
}
if (m_worker->mainWindow()->updateStep() == UpdateDcEvent::UpdateStep::BL_IS_UP) {
// bootloader MUST be running to download device-controller
#if 0
if (!downloadBinaryToDC(bFile)) {
Utils::printCriticalErrorMsg(
QString("UPDATING DC: ") + bFile + " ...DOWNLOAD FAILED");
}
#endif
} else {
Utils::printCriticalErrorMsg(
QString("UPDATING DC: ") + bFile + " BOOT LOADER NOT RUNNING -> NO DOWNLOAD ("
+ QThread::currentThread()->objectName() + ")");
return false;
}
// do this unconditionally, even if bootloader is not running at all ->
// the controller possibly tells us nonsense.
if (!stopBootloader()) {
Utils::printCriticalErrorMsg(
QString("UPDATING DC: ") + bFile + " BOOT LOADER STILL RUNNING ("
+ QThread::currentThread()->objectName() + ")");
return false;
}
Utils::printInfoMsg(QString("UPDATING DC: ") + bFile + " ...OK");
return true;
}
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 {
Utils::printInfoMsg(
QString("UPDATING JSON-FILE=%1, TEMPLATE-INDEX=%2, JSON-TYPE=%3")
.arg(jsFileToSendToDC)
.arg(templateIdx)
.arg(jsonType(type)));
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
qDebug() << "SET AUTO-REQUEST=TRUE";
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())) {
QThread::sleep(1);
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";
}
bool Update::doUpdate(int &displayIndex, QStringList const &filesToWorkOn) {
// always assume that serial line is open
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 UPDATE_DC == 1
static const QRegularExpression version("^.*dc2c[.][0-9]{1,2}[.][0-9]{1,2}[.]bin.*$");
if (fToWorkOn.contains(version)) {
Utils::printInfoMsg("DO-UPDATE FILE-TO-WORK-ON " + fToWorkOn);
QFile fn(fToWorkOn);
QFileInfo finfo(fn);
if (!fn.exists()) { // check for broken link
Utils::printCriticalErrorMsg("DO-UPDATE FILE-TO-WORK-ON "
+ fToWorkOn + " DOES NOT EXIST");
res = false;
} else {
bool updateBinaryRes = true;
qInfo() << "DOWNLOADING" << finfo.completeBaseName() << "TO DC";
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
qInfo() << "SET AUTO-REQUEST=FALSE";
if ((updateBinaryRes = updateBinary(fToWorkOn.toStdString().c_str())) == 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;
}
#endif
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;
}
// m_worker->stopProgressLoop();
// m_worker->setProgress(100);
if (res == false) {
break;
}
} // for (it = openLines.cbegin(); it != openLines.end(); ++it) {
m_hw->dc_autoRequest(true); // ALWAYS turn autoRequest ON
qDebug() << "SET AUTO-REQUEST=TRUE";
return res;
}

102
update.h Normal file
View File

@@ -0,0 +1,102 @@
#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;
Worker *m_worker;
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;
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(hwinf *hw,
Worker *worker,
QString customerRepository,
QString customerNrStr,
QString branchName,
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);
//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);
DownloadResult sendStatus(int ret) const;
DownloadResult sendNextAddress(int bNum) const;
DownloadResult sendNextDataBlock(QByteArray const &b, int bNum) const;
DownloadResult dc_downloadBinary(QByteArray const &binary) const;
bool startBootloader() const;
bool stopBootloader() const;
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 updateDC(QString bFile) const;
bool updatePrinterTemplate(int templateIdx, QString fname) const;
bool updateBinary(char 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();
private slots:
void readyReadStandardOutput();
void readyReadStandardError();
void finished(int exitCode, QProcess::ExitStatus exitStatus);
};
#endif // UPDATE_H_INCLUDED

25
update_dc_event.cpp Normal file
View 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
update_dc_event.h Normal file
View 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

284
utils.cpp Normal file
View File

@@ -0,0 +1,284 @@
#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::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) {
debug << QString(80, 'U');
for (int i = 0; i < updateMsg.size(); ++i) {
debug << updateMsg.at(i);
}
debug << QString(80, 'U');
}
void Utils::printUpdateStatusMsg(QStringList const &updateMsg) {
qCritical() << QString(80, 'U');
for (int i = 0; i < updateMsg.size(); ++i) {
qCritical() << updateMsg.at(i);
}
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');
debug << 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) {
qCritical() << QString(80, 'I');
for (int i = 0; i < infoMsg.size(); ++i) {
qCritical() << infoMsg.at(i);
}
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;
}

35
utils.h Normal file
View File

@@ -0,0 +1,35 @@
#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 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

1256
worker.cpp Normal file

File diff suppressed because it is too large Load Diff

1202
worker.h Normal file

File diff suppressed because it is too large Load Diff

13
worker_thread.cpp Normal file
View 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
worker_thread.h Normal file
View 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