Compare commits

...

525 Commits

Author SHA1 Message Date
1ea1cdc3e6 set version to 1.5.7 after merge of pu/portrait 2025-02-19 12:08:17 +01:00
348fb15508
Ui: support portrait mode 2025-02-19 11:39:08 +01:00
061c57ef51 set verion to 1.5.6 2024-11-22 12:59:13 +01:00
e82417dde7 MainWindow::MainWindow():
Add status timer, to show proceeding update, so user does not exit
	application / restart machine.
2024-11-22 12:55:27 +01:00
1e271201c5 Set version to 1.5.5. 2024-11-21 09:15:33 +01:00
da66d75a45 getPSAInstalled():
call ptuPackagesVersion. Convert returned JSON-array into JsonObject
	to be appended to CMD_SENDVERSION.
2024-11-21 09:14:05 +01:00
7accabfa53 Add variables for handling ptu-package-versions and append corresponding data
to CMD_SENDVERSION.
2024-11-21 09:12:35 +01:00
201a1cbab9 privateUpdate():
Make sure opkg-commands re executed aunder certain error conditions:

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

Adapt percent-counters to show progress of update process.
2024-05-17 08:43:37 +02:00
bd785e7df1 Minor: changes some debug text 2024-05-16 16:44:35 +02:00
f2534c7763 Fix: updateNewsToIsmas(): format TIMESTAMP with UTC-Offset suffix. 2024-05-16 10:36:58 +02:00
d2a6ae239d Set version to 1.4.9. 2024-05-15 15:06:54 +02:00
19273daa55 Do not install an own message-handler to prevent double-debug-output in
linux-journals.
2024-05-15 15:05:49 +02:00
ca67d1d159 Ignore RECORD-messages sent by APISM which do not have JSON format. 2024-05-15 15:04:51 +02:00
7c3e4ea497 Minor: remove some debug output. Error messages still intact. 2024-05-15 15:03:47 +02:00
f8897c2950 Implement Update::getInstalledJsonVersions(). 2024-05-15 15:02:53 +02:00
94a658ce8a Add some IMPORTANT comments about the format of JSON files to be downloaded. 2024-05-15 15:02:10 +02:00
9d9865e3c7 downloadJson(): continue update-process even when downloading of some JSON file fails. 2024-05-15 15:01:16 +02:00
a7d5a8f5cd Declaration of getInstalledJsonVersions() with default parameter. 2024-05-15 14:59:08 +02:00
cafd16a744 Read versions of JSON files installed on PSA (DC!).
If version is available, use as blob-value to be visible
in ISMAS.
2024-05-15 14:57:15 +02:00
5876c50a32 Make sure that SEND-LAST-VERSION is executed exactly once. 2024-05-15 14:56:41 +02:00
3b2200c0bf Make sure that SEND-LAST-VERSION is executed exactly once. 2024-05-15 14:55:55 +02:00
e8070a9e16 set port name 2024-05-14 16:39:09 +02:00
da10d6c2f6 make compile 2024-05-14 16:38:47 +02:00
c52b276722 first draft 2024-05-14 16:38:19 +02:00
e9cb421ac5 Add first draft 2024-05-14 16:37:45 +02:00
a3aef7594e Minor: add comment 2024-05-14 12:52:09 +02:00
afbcccf785 Minor: add comment about index shift: 4 -> 5 2024-05-14 12:51:32 +02:00
90e4e21391 System::getJsonFilesOnUsbStick(): return list of JSON files for configured
directory under mount path.
2024-05-14 12:49:28 +02:00
4536284f34 getUSBMountPath(): check for directory 'dirPathUnderMountPath' under mount path. 2024-05-14 12:48:19 +02:00
a3a4c09c7f checkForUSBStick(): look for etc/psa_config in mountpath-directory. 2024-05-14 12:46:38 +02:00
a5dd9af29a Add System::allowedJsonFiles to name default JSON file names. 2024-05-14 12:45:43 +02:00
5124e1cca6 Use return value of type std::optional<QString> for
checkForUSBStick() and getUSBMountPath().
Add getJsonFilesOnUsbStick().
2024-05-14 12:43:46 +02:00
fc75585de3 Parse psa-config-directory and psa-tariff-directory. 2024-05-14 12:40:32 +02:00
1964b08349 doUpdate(): use parameter 'usbStickDetected' to use the correct JSON
filenames.
2024-05-14 12:38:31 +02:00
c0d014644c Update (conf) JSON-Files using USB stick. When plugged in, look for
JSON-files in directory psa-config-directory and load them to the PSA.
Note: these files are overwritten during a usual ISMAS-update if not
checked in into the customer repository.
2024-05-14 12:35:18 +02:00
b24c50c572 Parse psa-config-directory and psa-tariff-directory settings. 2024-05-14 12:33:40 +02:00
bbdadc9063 Include psa_config_directory and psa_tariff_directory settings. 2024-05-14 12:32:26 +02:00
dc7f839d3f Include ATBUpdateTool.ini 2024-05-14 12:31:19 +02:00
0a33d078be Set version to 1.4.8 2024-05-08 16:20:54 +02:00
1d64769094 Fix: shift jsonNr by 1 in checkDownloadedJsonVersions(); print-templates start now with 6 instead of 5. 2024-05-08 16:17:28 +02:00
2e3af64c02 getFileVersion(): use only 16 byte of buffer filled by DC with version-info
of JSON-file.
2024-05-08 16:16:13 +02:00
f8472a3b87 call update.checkJsonVersions(filesToUpdate) after doUpdate(). 2024-05-08 16:10:20 +02:00
24addad11e Implement getFileversion(). 2024-05-08 16:09:18 +02:00
5a8298a078 Implemented checkJsonVersions(). 2024-05-08 16:08:53 +02:00
52af7894db Minor: remove useless assignments. 2024-05-08 16:08:01 +02:00
a6592ffd3e Check m_hw for nullprt. 2024-05-08 16:07:27 +02:00
696db7de39 Don't call exit(), but return nullptr. 2024-05-08 16:06:14 +02:00
b31588bfab checkJsonVersions(): provide default parameters 2024-05-08 16:04:53 +02:00
6651920f4a Merge branch 'release_1.4.6' 2024-05-06 11:29:29 +02:00
ef800366e1
Make compile with yocto/bitbake 2024-05-06 10:59:31 +02:00
1acec4d876 revert to original version of the file (tag: 1.4.7) 2024-05-06 10:28:43 +02:00
46c481b862 Add worker_thread.h/.cpp 2024-05-06 06:25:03 +02:00
8945ead5d6 set setting for opening serial device 2024-05-06 06:24:25 +02:00
bc064c38c6 use only one thread 2024-05-06 06:23:52 +02:00
f741fb96f9 start main sources 2024-05-05 17:26:34 +02:00
8d1c719626 form fir mainwindow 2024-05-05 17:25:07 +02:00
b5389a599e add main window 2024-05-05 17:24:28 +02:00
ea2f42beed Add gui-form and sneder/receiver-thread source. 2024-05-05 17:23:08 +02:00
22e751e197 Minor: add comment 2024-05-03 13:35:33 +02:00
05c7d11ef8 Only create m_update-object if it is configured to update hardware (JSONs and DC). 2024-05-03 13:32:39 +02:00
63dc70dda9 Check if it has to be possible to update hardware (JSONs, DC). If yes, then exit(). 2024-05-03 13:31:04 +02:00
e5ab9b98cd Set Version to 1.4.7 2024-05-03 13:14:57 +02:00
4477647acf Check m_hw before its use 2024-05-03 13:11:33 +02:00
d64b029a2d loadDCPlugin(): never call exit() inside a library. 2024-05-03 13:08:25 +02:00
e24022a612 Set version to 1.4.6. Fix: do not send all jsons down to DC unconditionally 2024-04-29 15:05:10 +02:00
60d78790ba Minor: remove trailing ")" in msg 2024-04-29 15:03:43 +02:00
543e712c62 Minor: Replace trailing "," 2024-04-29 15:02:37 +02:00
8402fde6b5 Reformat m_versionInfo in case a version is included in the commit-message. 2024-04-29 15:00:52 +02:00
f15cc636c6 FIX: set m_pulledNewBranch = false in case no new branch has to be fetched from remote repository. 2024-04-29 14:59:10 +02:00
adaa12395e Trigger CHECK_ISMAS_TRIGGER_SUCCESS-message to ISMAS. 2024-04-29 14:58:29 +02:00
853c29e448 Set result code NO_UPDATE_NECESSARY instead of just SUCCESS. 2024-04-29 14:54:27 +02:00
78c214ceb4 CHECK_ISMAS_TRIGGER_SUCCESS: send message to ISMAS if WAIT-button as been set to "WAIT". 2024-04-29 14:52:50 +02:00
88bec387c5 Minor: formatted code for readability. 2024-04-29 14:50:43 +02:00
05b68f21c2 Add System.h/System.cpp -> to be adapted later 2024-04-26 13:05:19 +02:00
9ca394db46 Begin with fetching versions of downloaded json-files. 2024-04-26 13:03:10 +02:00
0d268a1d9d set INCLUDEPATH to use System.h/.cpp 2024-04-26 13:02:12 +02:00
da102b5ed0 Set version to 1.4.6 2024-04-26 12:53:30 +02:00
7031c0e349 Replace INSTALL_ERROR with proper error codes. 2024-04-26 12:49:06 +02:00
c528ce377d Add some new messages sent to ISMAS. 2024-04-26 12:47:44 +02:00
5e7c848fca Replaced INSTALL_ERROR by proper error codes. 2024-04-26 12:47:13 +02:00
3165d77f49 Replaced U0010 by its macro _ISMAS_CONTINUE 2024-04-26 12:46:28 +02:00
f0d2d5f958 Replaced U0010 by its macro _ISMAS_CONTINUE 2024-04-26 12:45:08 +02:00
1da4c3b224 Add _ISMAS_TEST_TRIGGER 2024-04-26 12:43:21 +02:00
f1cedbf1d5 Define new error codes (and actually use them) -> ISMAS not affected. 2024-04-26 12:41:21 +02:00
0933274c82 Add update functionality (again using ATBUpdateTool as template) 2024-04-23 16:25:36 +02:00
2aa676f18c Implement json-download tool with ATBUpdateTool as template. 2024-04-23 16:23:58 +02:00
6c0d49b90c Start with project file for json-download tool. 2024-04-23 16:22:56 +02:00
18d04d15cf Set version to 1.4.5. 2024-04-11 16:31:44 +02:00
b81120f8dc Implemented:
bool branchExistsRemotely();
	Check if branch exists in remote customer-repository.

    bool branchExistsLocally();
	Check if branch exists locally in customer-repository.

    bool gitPullNewBranches();
	In case the remote branch exists, but not the corresponding local one,
	then fetch the remote-branch.
2024-04-11 16:25:36 +02:00
8b2fcb25db Added declarations for:
bool branchExistsRemotely();
    bool branchExistsLocally();
    bool gitPullNewBranches();
2024-04-11 16:24:33 +02:00
698cf74516 doUpdate(): re-check again if there are valid data form the device-controller. 2024-04-11 16:23:08 +02:00
20681b0d6c If we have pull a new remote branch, the behave as if the customer-repo
did not exist before: especially download all json-files inside
the new local branch.
2024-04-11 16:20:46 +02:00
763647c145 If customer-repo is already existent (i.e. not cloned),
then check for the existence of remote branch (zg/zone<zone-number of psa>).
If it exists remotely, but not locally, then execute 'git pull'
(could also be 'git pull origin zg1/zone<zone-number>').
A follwing 'git checkout zg1/zone<zone-number>' will switch to the
now local branch.
2024-04-11 16:16:34 +02:00
4aad14b181 Added PULL_NEW_BRANCH, PULL_NEW_BRANCH_FAILED, PULL_NEW_BRANCH_SUCCESS and corresponding output messages. 2024-04-11 16:15:49 +02:00
0a03228dea Added PULL_NEW_BRANCH, PULL_NEW_BRANCH_FAILED, PULL_NEW_BRANCH_SUCCESS and corresponding output messages. 2024-04-11 16:14:45 +02:00
23551066c1 Set version to 1.4.4 2024-04-09 15:02:59 +02:00
24f2ba7c44 Move rsyncing the customer-repository after filesToUpdate(), as
the repository is pulled in filesToUpdate().
2024-04-09 14:56:25 +02:00
2ed6768953 Minor: remove ismasTriggerValue-(debug)-message, as it was too confusing. 2024-04-09 14:55:45 +02:00
a1327388bc execute(): Enhance debug output. 2024-04-09 14:53:50 +02:00
8d18ae10fe downLoadJson(): add more debug-output (visible in ISMAS as well)
to see what actuelly went wrong when downloading json-Files.
2024-04-09 14:51:54 +02:00
31bc2d0fa2 Minor: update comment 2024-04-09 14:49:42 +02:00
175b8fd3a1 If the update-trigger (aka WAIT-button) is empty and we have an automatic
update (i.e. time is 0:00 - 4:00 am), then do not inform ISMAS with an U0003
error signal, but send an U0002 (setting the trigger-value to "OK").
2024-03-19 12:41:42 +01:00
a57fa6c31e Add path to global device-controller library 2024-03-19 09:30:20 +01:00
c22c924e38 Add path to global device-controller library 2024-03-19 09:29:51 +01:00
bdc64920a2 Minor: remove superfluous include 2024-03-19 09:29:17 +01:00
7bc9fa0c04 Minor: fix typo 2024-03-19 09:28:37 +01:00
334da1fe4a Merge branch 'master' of https://git.mimbach49.de/GerhardHoffmann/ATBUpdateTool 2024-03-19 09:23:54 +01:00
e5054582c2 set version to 1.4.3 2024-03-19 09:20:31 +01:00
bbd287c92b Minor: comment out a line 2024-03-19 09:19:52 +01:00
5c152c9dc2 Minor: remove plugins/interfaces.h 2024-03-19 09:13:27 +01:00
367ffaa3a1 Minor: adapt header-include 2024-03-19 09:12:46 +01:00
2fd004f249 Add PATH for device-controller-library as well. 2024-03-19 09:12:07 +01:00
721a156fce Remove functionality for downloading firmware-device-controller 2024-03-15 12:59:59 +01:00
b7576d04e1 Add *.user 2024-03-15 12:58:32 +01:00
753954ecd7 Use <DeviceController/interfaces.h> 2024-03-15 12:07:15 +01:00
df7cabe2c1 Remove references to interfaces.h. Add refs to device-controller 2024-03-15 12:05:50 +01:00
cfca8d2ef4 remove interfaces.h plus CA-libs 2024-03-15 11:55:21 +01:00
829932f29d Load libCAslave.so not libCAmaster.so 2024-03-15 11:26:57 +01:00
8968667c23 Add comment. Set version to 1.4.2. 2024-03-08 08:47:54 +01:00
a5e0154757 Do not check if etc/psa_tariff and /etc/psa_tariff are equal after the rsync:
reason is that this might be not the case if the customer-number has been changed.
2024-03-08 08:44:39 +01:00
f346390631 Add UpdatePTUDevCtrl subdirectory 2024-02-29 15:02:12 +01:00
c77fa097c1 Use UpdatePTUDevCtrl.pro 2024-02-29 15:01:40 +01:00
074e60d8dc Merge remote-tracking branch 'UpdatePTUDevCtrl/dc-download' 2024-02-29 14:48:59 +01:00
8eff6e5d10 Move UpdatePTUDevCtrl files into subdir UpdatePTUDevCtrl 2024-02-29 14:41:45 +01:00
4233ca8637 Merge remote-tracking branch 'UpdatePTUDevCtrl/master' 2024-02-29 14:38:14 +01:00
68fc83ba67 Add DownloadDCFirmware and DownloadDCJsonFiles 2024-02-29 11:36:24 +01:00
052028afe8 Check if download/reporting thread are running 2024-02-29 11:30:24 +01:00
a240711946 (R)sync files of customer repository (under ./etc in the repository)
with file-susyem /etc as very forst step of the update process, even
before executing the opkg commands.
2024-02-27 13:56:38 +01:00
75fdca95d9 set version to 1.4.1 2024-02-27 13:56:24 +01:00
9b087f62f9 Check if json-file to be downloaded to device-controller is empty before
starting a download.
2024-02-17 08:04:06 +01:00
7d38cc1269 Set version to 2.0.0 2024-02-09 13:07:22 +01:00
f5baad16d5 Prepend last-commit with pid of ATBUpdateTool (to be used in ISMAS). 2024-02-09 13:02:35 +01:00
b35e6812aa getDCVersionPreparedForDownload(): implemented. 2024-02-09 13:02:11 +01:00
d7e709d997 Minor: make a 2-sec nap before starting reporting threadw 2024-02-09 13:01:15 +01:00
4d93aa1392 getDCVersionPreparedForDownload(): added for future use. 2024-02-09 12:59:25 +01:00
b0f1e0a493 Minor: reformatting code.w 2024-02-06 11:28:01 +01:00
0dffc1d1c2 Create m_update-object inside of constructor of worker-class:
this way the object belongs to the GUI-thread, and can be addressed via emit
by the reporting thread.
2024-02-06 11:25:46 +01:00
3581dd4b1d doUpdate(): start reorting thread to report download-progress to GUI. 2024-02-05 16:31:24 +01:00
8d2d7bbb15 Connect slots
void onReportDCDownloadStatus(QString const &status);
    void onReportDCDownloadSuccess(QString const &msg);
    void onReportDCDownloadFailure(QString const &errorMsg);
2024-02-05 16:30:41 +01:00
e2e7c0772d Implemented slots:
void onReportDCDownloadStatus(QString const &status);
    void onReportDCDownloadSuccess(QString const &msg);
    void onReportDCDownloadFailure(QString const &errorMsg);
2024-02-05 16:30:01 +01:00
807cea1042 Added slots:
void onReportDCDownloadStatus(QString const &status);
    void onReportDCDownloadSuccess(QString const &msg);
    void onReportDCDownloadFailure(QString const &errorMsg);
2024-02-05 16:28:34 +01:00
80712964ef Use of pointer m_update. 2024-02-05 16:26:53 +01:00
978e98b2ee removed dependency to interface.h 2024-02-05 14:53:56 +01:00
44c2820130 Make sure to lookup only "apism", not the new "apism-tools" 2024-02-02 08:18:13 +01:00
123f22cd21 add .gitignore file 2024-01-29 09:03:16 +01:00
b60af1a4fc Flowchart for ATBUpdateTool 1.4.0 2024-01-26 14:19:50 +01:00
bb3ecc4b76 Use same interfaces.h as DCLibraries (master branch) 2024-01-26 11:39:21 +01:00
fa30fe045b Minor: added interfaces.h 2024-01-26 11:38:43 +01:00
bae014822d Fix: set version info several times to reflect real current git commit 2024-01-26 11:17:06 +01:00
6c472b542e Merge remote-tracking branch 'origin/korneuburg-improvements' 2024-01-26 08:55:50 +01:00
7578746d2f make it explicit that no device-controller is loaded down with this version 2024-01-25 15:46:46 +01:00
0b1ed62df1 Optimization: if customer repository does not exist, do noy check the
ISMAS trigger, but proceed with the update procedure.
2024-01-25 15:14:42 +01:00
76ec41c291 Minor: add some comment. 2024-01-25 15:13:56 +01:00
630cd36f13 Minor: removed typo 2024-01-25 11:54:13 +01:00
cbe8bb7aeb Minor: add comment 2024-01-25 09:01:04 +01:00
e04636e3f7 Minor: add debug output 2024-01-24 13:07:39 +01:00
728185ddb9 Set
m_lastFailedUpdateStep = UPDATE_STEP::NONE
as last step in case of a successful update.
2024-01-24 08:31:22 +01:00
aaa485e2fc Send messages to ISMAS for checking/repairing the customer repository 2024-01-23 16:09:15 +01:00
9a9480035b Improve output, esecially to ISMAS 2024-01-23 15:31:12 +01:00
0a43654f9b Improve output, esecially to ISMAS 2024-01-23 15:30:31 +01:00
4dba36a420 Add and use UPDATE_STEP::UPDATE_FINALIZE in debug output. 2024-01-23 15:29:19 +01:00
f9ce6a6c1b Minor: remove obsolete line. 2024-01-23 12:22:48 +01:00
c2c6bc3f8a Minor: removed typo. 2024-01-23 12:18:10 +01:00
8c02ebcf15 Minor: debug output to GUI. 2024-01-23 12:07:42 +01:00
100bfd63ab Do not write to GUO when running in loop to check ISMAS trigger button 2024-01-23 12:03:46 +01:00
23ff4977d9 Disable exit button after checking update trigger button. 2024-01-23 12:02:18 +01:00
8da6443833 Send additional messages to ISMAS about recovering the customer-repository 2024-01-19 13:58:08 +01:00
6b3ebde2b5 Check for automatic update and add a hint in SEND-LAST-MESSAGE. 2024-01-19 13:40:24 +01:00
41392a98e3 Minor: added comment. 2024-01-19 13:11:12 +01:00
1c9bb11f0b Moved final processing into destructor of subclsee UpdateProcessRunning. 2024-01-19 13:06:58 +01:00
ec0e687c21 Adapt step order: check of ISMAS trigger is done with percent value 2. 2024-01-19 13:06:11 +01:00
e040e784fc Add members
bool m_updateNotNecessary = false;
    QStringList m_ismasTriggerStatusMessage;
2024-01-19 13:05:46 +01:00
d2300b87c6 Move final processing to subclass UpdateProcessRunning. 2024-01-19 13:04:12 +01:00
0dff2ece75 Check ISMAS update trigger as very first thing.
Save the result in m_ismasTriggerActive for later use.
2024-01-19 13:02:59 +01:00
db24853062 Initialize new member m_ismasTriggerStatusMessage. 2024-01-19 13:01:46 +01:00
530ea33460 Minor: debug output. 2024-01-19 08:29:03 +01:00
005e4d249f Set m_lastFailedUpdateStep (future use for downloading the firmware-device-controller). 2024-01-19 08:27:07 +01:00
1c0786e28c Minor: Add NONE constant (for UPDATE_NECESSARY). 2024-01-19 08:24:54 +01:00
0aa8d9ba5a Check if update-process was really necessary, i.e. NOT activated
by an automatic nightly update.
2024-01-19 08:22:03 +01:00
1ecb844b64 Added for future use when updating device-controller-frimware:
hwinf *m_hw = nullptr;
    UPDATE_STEP m_lastFailedUpdateStep = UPDATE_STEP::NONE;
2024-01-19 08:20:21 +01:00
9a687e6628 Minor: add some debug output 2024-01-19 08:16:26 +01:00
979afa37d3 Minor: add comment 2024-01-17 15:38:05 +01:00
1e1820724d Set version to v1.4.0. Set compile-option -O (FORTIFY_SOURCE). 2024-01-17 15:32:26 +01:00
d90954c6eb Add location, version and info to send-last-version object. 2024-01-17 15:30:34 +01:00
cf77d0ff76 Initialize m_versionInfo and send its contents to ISMAS in the update-process. 2024-01-17 15:28:49 +01:00
73d02d214a Send contant of m_versionInfo(0) (git commit of repository) to ISMAS. 2024-01-17 15:26:53 +01:00
6a67d8e9b0 Minor: update percent numbers in some cases. 2024-01-17 15:26:14 +01:00
30d8cc3684 Add m_version_info as memeber. 2024-01-17 15:25:35 +01:00
bc9ebb7d68 Implemented helpers:
QString getLocation(QString fileName);
    QString getTariffVersion(QString fileName);
    QString getTariffInfo(QString fileName);

Read project location, tariff location and tariff-info
from tariff[].json file.
2024-01-17 15:18:03 +01:00
e6f6d43bf2 Adden helpers:
QString getLocation(QString fileName);
    QString getTariffVersion(QString fileName);
    QString getTariffInfo(QString fileName);
2024-01-17 15:17:16 +01:00
854c8b9706 Minor: add some additional debug output 2024-01-10 09:58:37 +01:00
d521fd977a Using interface.h, verion 4.4, from 20230802. set version to v.1.3._25_ 2023-12-21 13:02:12 +01:00
ebbdc2f864 Use interface file from 20230802, version 4.4 2023-12-21 13:00:00 +01:00
62496c5d95 Prepare special version for szeged. set version to 1.3._24_ 2023-12-20 12:27:29 +01:00
edd606fe78 Change for szeged (dc-version: 4.42): do not check if dc is alive.
Comment out some functions which are not available in old interface.h
2023-12-20 12:20:06 +01:00
1748c35c45 Add interfaces.h as given for 26.Sep 2023 (szeged) 2023-12-20 12:18:02 +01:00
4c46932a3c Specail version for szeged (dc-version: 4.42): use master lib. 2023-12-20 12:16:07 +01:00
686e113c3a Fix: add break when checking dc alive status. set version to 1.3.24. 2023-12-19 14:30:58 +01:00
6ddfbbfd9e add a break to prevent possible endless loop 2023-12-19 14:25:59 +01:00
7bfbdc0f07 Update flowchart for UpdateTool. 2023-12-19 13:05:10 +01:00
dd591fdd23 Amde some preparations for sendLastVersion 2023-12-17 16:25:31 +01:00
18c7b656c3 Add some new points. 2023-12-17 15:23:00 +01:00
5e9b05e887 Set version to 1.3.23. 2023-12-15 09:48:14 +01:00
37aae73f21 Fix: Make sure the path for the json-files and the decive-controller is correct. 2023-12-15 09:39:46 +01:00
0b4eed9dc0 doUpdate(): add another level in if-case when downloading json-files. 2023-12-15 09:38:01 +01:00
12f48ad1bb Remove only half-working check if download of json-conf-file worked. 2023-12-15 09:33:57 +01:00
5d7d1a2870 Implement helpers getFileVersions() and checkDownloadedJsonVersions(). 2023-12-15 09:32:54 +01:00
5d7f13a254 Future: add getFileVersion() and checkDownloadedJsonVersions() to
check if download of Json-File worked and to ask what Json-Version
is actually installed
2023-12-15 09:30:02 +01:00
d332a990d5 Turn on automatic download of json-files. 2023-12-15 09:27:49 +01:00
bfa39eb3df Set version to 1.3.22.
After git clone: execute full update process (modulo settings in ATBUpdateTool.ini).
2023-12-13 14:00:21 +01:00
d7fcfa3d0f Click the Exit button after 5 seconds timeout (old timeout: 60s). 2023-12-13 13:59:00 +01:00
f1e449c108 Change known filename of device controller: dc2c.bin. 2023-12-13 13:57:46 +01:00
32346c2665 If the repository is cloned (or repaired and cloned) and the settings
always-download-config and always-download-dc are set in the ini-file,
then download the json-files and dc-file, even without an activated
WAIT-button. The tariff-files are always synced for a clone.
2023-12-13 13:49:22 +01:00
38e7bf4985 Minor: call rsync with -v instead of -vvv. 2023-12-13 13:48:23 +01:00
6df73e1082 Minor: change some debug output. 2023-12-13 13:47:02 +01:00
19250a0a2f If the update process is activated without a valid ISMAS trigger, then
wait for a valid trigger value 15x (=90s) instaed of 100x.
2023-12-13 13:44:55 +01:00
6f5c8103e4 When checking the sanity of the customer repository, check also for existence
of etc-directory inside repository.
2023-12-13 13:42:12 +01:00
07dcf0ba30 Minor: add some GUI debug output when checking ISMAS trigger. 2023-12-13 13:41:06 +01:00
1e379cf086 Fix: set directory of application for directory of the ini-file. 2023-12-13 13:38:34 +01:00
e87456f26b set version to 1.3.21 2023-12-13 10:06:04 +01:00
0c9a7bc7b5 let ISMAS know if some opkg commands fail 2023-12-13 10:04:38 +01:00
a35c6afcb8 Minor: add debug output if some opkg commands fail 2023-12-13 10:03:37 +01:00
b06f4f46bb
Update interfaces.h (DeviceController) 2023-12-08 13:02:23 +01:00
33d45eab2e
Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/UpdatePTUDevCtrl 2023-12-08 13:01:03 +01:00
d2e11d8f07 Replace the last line of the text edit when the new line is
the last line followed by a suffix.
2023-11-29 14:18:01 +01:00
fbffdc923f Minor: When appendig text, scroll down the text edit. 2023-11-29 14:17:28 +01:00
8faf5af2bf Typo: replace m_files_to_update with m_files_to_download. 2023-11-29 12:07:25 +01:00
1d532c13a4 Minor: show files to update with a direct qCritical() 2023-11-29 12:06:17 +01:00
d2d3afc28e Show debug output in text-edit only when at least one file to update. 2023-11-29 12:05:09 +01:00
f4bb201633 Minor: Add debug message to console 2023-11-29 11:37:08 +01:00
b68cf1fd1d Set version to 1.3.20. 2023-11-29 11:30:50 +01:00
0888c1b525 Read machine-nr, customer-nr and zone-nr from /mnt/system_data/
rather then the deprecated /etc-directory.
2023-11-29 11:29:52 +01:00
a6faf9ce21 Init triggerValue with "NOT CHECKED YET" otherwise one might be confused. 2023-11-29 11:28:35 +01:00
5577cc5d6d Add m_sys_areDCdataValid plus its handling 2023-11-24 14:08:54 +01:00
9967d5cc45 Add comment 2023-11-24 14:08:19 +01:00
e20ed57bd5 Set version to 1.3.19 2023-11-21 16:18:17 +01:00
6986007b16 Set all parameters to default values other than "" 2023-11-21 16:17:15 +01:00
9ecdf73bc0 Minor: output all command parameters 2023-11-21 16:16:28 +01:00
59d6c49cb2 Set version to 1.3.18 2023-11-21 15:27:34 +01:00
f6a8059e2d Activated downloading of json to device 2023-11-21 15:25:20 +01:00
4372cb578b Added additional output to CONSOLE() and ISMAS(). 2023-11-21 15:23:28 +01:00
d683a8fc32 Added some comments. 2023-11-21 10:09:52 +01:00
4e92522578 Activate downloading device controller. 2023-11-21 10:09:04 +01:00
b45f3a04b4 Add debug output (for testing, and commented out) in downloadJson(). 2023-11-21 10:08:31 +01:00
0db39746db Aupdate updateBinary() to download device controller using new library fucntions. 2023-11-21 10:07:50 +01:00
f2844aa4d9 Remove obsolete functions: sendStatus(), sendNextAddress(), sendNextDataBlock(),
dc_downloadBinary(), startBootloader(), stopBootloader().
2023-11-21 10:01:11 +01:00
d4043bd7d2 Remove obsolete functions:
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;

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

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

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

and static variables

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

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
tags
*.tags
*.user

21
ATBUpdateTool.ini Normal file
View File

@ -0,0 +1,21 @@
[REPOSITORY_URL]
repository-url="gitea@ptu-config.atb-comm.de:ATB/"
[DIRECTORIES]
plugin-directory="/usr/lib/"
working-directory="/opt/app/tools/atbupdate/"
psa-config-directory="etc/psa_config/"
psa-tariff-directory="etc/psa_tariff/"
[PLUGINS]
plugin-name="libCAslave.so"
[FLAGS]
no-psa-hardware-update=false
dry-run=false
extended-version=false
yocto-version=false
yocto-install=false
always-download-config=true
always-download-dc=false

3
ATBUpdateTool.pro Normal file
View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = DownloadDCFirmware DownloadDCJsonFiles UpdatePTUDevCtrl

41
DCPlugin/.gitignore vendored
View File

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

@ -1,25 +0,0 @@
INCLUDEPATH += $${PWD}/include
DEPENDPATH += $${PWD}
HEADERS += $${PWD}/include/com.h \
$${PWD}/include/controlBus.h \
$${PWD}/include/datIf.h \
$${PWD}/include/dcBL.h \
$${PWD}/include/hwapi.h \
$${PWD}/include/interfaces.h \
$${PWD}/include/prot.h \
$${PWD}/include/sendWRcmd.h \
$${PWD}/include/storeINdata.h \
$${PWD}/include/tslib.h \
$${PWD}/include/shared_mem_buffer.h
SOURCES += $${PWD}/src/com.cpp \
$${PWD}/src/controlBus.cpp \
$${PWD}/src/datIf.cpp \
$${PWD}/src/dcBL.cpp \
$${PWD}/src/hwapi.cpp \
$${PWD}/src/prot.cpp \
$${PWD}/src/sendWRcmd.cpp \
$${PWD}/src/storeINdata.cpp \
$${PWD}/src/tslib.cpp \
$${PWD}/src/shared_mem_buffer.cpp

View File

@ -1,94 +0,0 @@
TEMPLATE = lib
CONFIG += plugin
#CONFIG += c++11 console
#CONFIG -= app_bundle
#QT += widgets
QT -= gui
QT += widgets serialport
INCLUDEPATH += $${PWD}/plugins
INCLUDEPATH += $${PWD}/include
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# default
ARCH = PTU5
include(DCPlugin.pri)
contains( CONFIG, DesktopLinux ) {
QMAKE_CC = ccache $$QMAKE_CC
QMAKE_CXX = ccache $$QMAKE_CXX
QMAKE_CXXFLAGS += -std=c++11
# QMAKE_CXXFLAGS += -Wno-deprecated-ctor
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux
}
contains( CONFIG, PTU5 ) {
# QMAKE_CC = ccache $$QMAKE_CC
# QMAKE_CXX = ccache $$QMAKE_CXX
QMAKE_CXXFLAGS += -std=c++11
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
CONFIG += link_pkgconfig
ARCH = PTU5
}
contains( CONFIG, PTU5_YOCTO ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
PTU5BASEPATH = /opt/devel/ptu5
ARCH = PTU5
# add qmqtt lib
#LIBS += -lQt5Qmqtt
}
TARGET = ATBDeviceControllerPlugin
#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
# 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
# Default rules for deployment.
#qnx: target.path = /tmp/$${TARGET}/bin
#else: unix:!android: target.path = /opt/$${TARGET}/bin
#!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

View File

@ -1,155 +0,0 @@
#!/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

@ -1,105 +0,0 @@
//CAT is always master, no receive before request
#ifndef SER_H
#define SER_H
#include <stdint.h>
#include <QMainWindow>
#include <QString>
#include <QTimer>
#include <QSerialPort>
#include "tslib.h"
#include "controlBus.h"
#define MAXTELEGRAMLEN 90
// display all inputs and outputs in output window:
//#define PRINTALLDEBUGS 1
class T_com : public QMainWindow //, public QPlainTextEdit
{
Q_OBJECT
// complete send message (protocol frame)
QByteArray sendBuffer; //[MAXTELEGRAMLEN];
uint16_t sendLen; // >0: Daten Sendebereit, nach senden wieder auf 0 setzen
// right after reception:
QByteArray rawInput; //[MAXTELEGRAMLEN];
uint16_t rawInLen; // 0: keine neuen Daten erhalten
// QSerialPort *CatSerial = nullptr;
QSerialPort *CatSerial;
//char oeffneSerialPort();
char open_Serial_Port();
void closeSerialPort();
void receiveByLength(void);
private slots:
void readSomeBytes(void);
void serialSendComplete(void);
//void incomingWake(void); //bool LevelOfTheBit);
void receiveTO(void);
void ser_ISR100ms();
public:
T_com(QWidget *parent = nullptr);
~T_com();
QTimer *serRecTime;
bool isPortOpen(void);
void writeToSerial(const QByteArray &data, uint16_t sendLength);
void receiveFixLen(int64_t nrOfbytesToReceive);
bool readFromSerial(QByteArray &data, uint16_t &sendLength);
// retval: true: data available
/*
uint8_t getAllPortPins(void);
// rs232pins: all signals bitwise coded in one byte:
// readback output: bit 0=TxD(=output) bit2=DTR (=output) bit 6=RTS (=output)
// unused inputs: bit1=RxD bit 3=DCD bit 5 = RING
// handshake inputs: bit 4=DSR (0x10) bit 7=CTS (0x80)
bool getHSin_CTS(void);
// return the CTS Handshake input): true= high level (+8V)
bool getHSin_DSR(void);
// return the DSR Handshake input): true= high level (+8V)
bool setHSout_RTS(bool hsout);
// hsout true=positiv voltage +12V false= -12V
// retval: true=setting OK
bool setHSout_DTR(bool hsout);
// hsout true=positiv voltage +12V false= -12V
// retval: true=setting OK
*/
signals:
void receivingFinished();
void sendingFinished();
//void wasWokenBySerialHandshake();
};
#endif // SER_H

View File

@ -1,194 +0,0 @@
#ifndef CONTROLBUS_H
#define CONTROLBUS_H
#include <stdint.h>
#include "tslib.h"
#include <QString>
// ///////////////////////////////////////////////////////////////////////////////////
// control serial interface gui <--> serial
// ///////////////////////////////////////////////////////////////////////////////////
void epi_setSerial(int BaudNr, QString BaudStr, QString ComName, uint8_t connect);
// Actions: open serial port with parameters
void epi_closeSerial(void);
// Actions: close serial port
// Actions, GUI Buttons -> API, start cyclic transmission
void epi_startEmmision(char start); // 1: start sending activated
//void epi_setPeriodicSendTimeVal(uint16_t val);
// Port -> API
void gpi_serialChanged(void);
// serial confirms that port was closed or opened
// Actions, API -> serialPort
uint8_t gpi_getSerialConn(void); // connect if 1, disconnect if 0
int gpi_getBaudNr(void);
QString gpi_getComPortName(void);
void gpi_serialIsOpen(bool offen);
bool epi_isSerialPortOpen();
// true: port is open false: port is closed
// Meldung von TabCom an Datif: starte zyklische Sendung:
bool gpi_isEmmisionOn(void);
//uint16_t gpi_getPeriodicSendTimeVal();
//bool gpi_PeriodicSendTimeHasChanged();
//void epi_setCurrSlavAddr(int slavAd);
//int gpi_getCurrSlavAddr(void);
// ///////////////////////////////////////////////////////////////////////////////////
// Status Display gui <--> serial
// ///////////////////////////////////////////////////////////////////////////////////
//---------------------
// Statuszeile COM Port (serial Port) (open, closed)
// Display in tab_com
QString epi_getTxt4comStateLine(void);
void epi_clrTxt4comStateLine();
// GUI: get Text for serial Comport-State Line
//---------------------
// Statuszeile Handshakes (serial Control) flow.cpp
// geht überhaupt was raus? kommt überhaupt was zurück?
// I
QString epi_getTxt4HsStateLine(void);
void epi_clrTxt4HsStateLine();
// GUI: get Text
// II Master receive state (empfangenes Telgramm OK? crc? length? )
// Statuszeile Auswertung der SlaveResponse (serial Frame, CRC usw) (prot.cpp)
QString epi_getTxt4masterStateLine(void);
void epi_clrTxt4masterStateLine();
// III Slave receive (from Master) OK? if then show results, if not then show errors
// entweder Empfangsfehler anzeigen (crc? length?) oder result OUT-OK, OUT_ERR, IN_OK, IN_ERR
// Hintergrund: wenn der Slave Fehler im Master-Telegramm gefunden hat, dann kann er es auch
// nicht verwenden und nichts ausgeben oder einlesen
QString epi_getTxt4resultStateLine(void);
void epi_clrTxt4resultStateLine();
// IV Statuszeile Sende- und Empfangsdaten (Datif)
// Display in tab_com
QString epi_getTxt4dataStateLine(void);
void epi_clrTxt4dataStateLine();
// GUI: get Text for serial Comport-State Line
// V, unten, Datif
QString epi_getTxt4datifLine(void);
void epi_clrTxt4datifLine();
//---------------------
// sende-empfangs-Rohdaten-Fenster
// Display in tab_com
QString epi_getTxt4RsDiagWin(void);
void epi_clrTxt4RsDiagWin();
QString epi_get2ndTxt4RsDiagWin(void);
void epi_clr2ndTxt4RsDiagWin();
// Statuszeile COM Port (serial Port) (open, closed)
// Display in tab_com
void gpi_setTxt4comStateLine(QString txtline);
// serial: write Text to be displayed in serial Comport-State line (like "connected")
// used in vcp.cpp, links in tabCom
// Statuszeile Handshakes (serial Control)
// I obere Zeile
void gpi_setTxt4HsStateLine(QString txtline);
// used in flow.cc
// II
void gpi_setTxt4masterStateLine(QString txtline);
// III
void gpi_setTxt4resultStateLine(QString txtline);
// IV
void gpi_setTxt4dataStateLine(QString txtline);
// serial: write Text to be displayed in serial Comport-State line (like "connected")
// used in prot.cpp
// V unten:
void gpi_setTxt4datifLine(QString txtline);
// sende-empfangs-Rohdaten-Fenster
// Display in tab_com
void gpi_setTxt4RsDiagWin(QString txtline);
void gpi_set2ndTxt4RsDiagWin(QString txtline);
// ///////////////////////////////////////////////////////////////////////////////////
// Memory for Slave responses, common data
// ///////////////////////////////////////////////////////////////////////////////////
bool epi_getResult_serialTestOK();
// retval: true: test was successful, got right response
// result of serial line test, slave sent fixed string
void gpi_storeResult_serialTestOK(bool wasOn);
// ///////////////////////////////////////////////////////////////////////////////////
// restore just received data
// ///////////////////////////////////////////////////////////////////////////////////
uint8_t gpi_startNewRequest();
// called by Datif
uint8_t gpi_storeResultOfLastRequest(bool answisok);
// written by Datif
uint8_t epi_getResultOfLastRequest();
// retval: 0: in progress 1: OK 2: error
void gpi_storeRecPayLoad(uint8_t RdDlen, uint8_t const *receivedData);
// stored by Datif
uint16_t epi_getLastPayLoad(uint16_t plBufSiz, uint8_t *payLoad);
// get data back in *pl, max 64 byte
// retval = nr of bytes received. If host buffer too small then
// only plBufSíz bytes are copied to pl
// plBufSíz=size of host buffer
#endif

View File

@ -1,341 +0,0 @@
// Data Interface between slave (DC) and pi buffer
// determines sending and receiving order of data
// cares for storing input data and restoring output data
#ifndef DIF_H
#define DIF_H
#include <stdint.h>
#include "tslib.h"
#include "prot.h"
#include "dcBL.h"
#include <QMainWindow>
#include <QString>
#include <QTimer>
#include <QDebug>
#include <QDateTime>
#include <QDate>
#include <QTime>
#define CMD2DC_sendTime 20
#define CMD2DC_setWakeFrequ 112
#define CMD2DC_MOV_UPLOCK 113
#define CMD2DC_MOV_DNLOCK 114
#define CMD2DC_UPPER_DOOR 115
#define CMD2DC_LOWER_DOOR 116
#define CMD2DC_VAULT_DOOR 117
#define CMD2DC_REJMOT_ON 118
#define CMD2DC_REJMOT_RUN 119
#define CMD2DC_LED_COIN 100
#define CMD2DC_LED_ILLU 101
#define CMD2DC_LED_TICKET 102
#define CMD2DC_LED_START 104
#define CMD2DC_LED_PIN 103
#define CMD2DC_LED_IN 105
#define CMD2DC_FAN 106
#define CMD2DC_SIREN 107
#define CMD2DC_BARRIER 108
#define CMD2DC_WAKEPTU 109
#define CMD2DC_SWITCHAUXPWR 110
#define CMD2DC_SWITCHAUXDDR 18
#define CMD2DC_SWITCHAUXOUT 19
#define CMD2DC_UCONTACTON 111
#define CMD2DC_DEVICE_PARAM 23
#define CMD2DC_SEND_MACH_ID 11
#define CMD2DC_RDBK_DEV_PARA 14
#define CMD2DC_RDBK_MACH_ID 15
#define CMD2DC_MDB_ON 120
#define CMD2DC_MDB_GET_STATE 107 // REQ
#define CMD2DC_MDB_DORESET 121
#define CMD2DC_MDB_SETWAK 122
//#define CMD2DC_MDB_GETWAK 0x2812 // REQ not nec.
#define CMD2DC_MDB_SENDCMD 123
#define CMD2DC_MDB_SENDMSG 12
#define CMD2DC_MDB_GETRESP 22 // REQ
#define CMD2DC_EMP_SET 24
#define CMD2DC_EMP_GET_ALL 23 // REQ
#define CMD2DC_EMP_STARTPOLL 124
#define CMD2DC_EMP_STARTPAY 125
#define CMD2DC_EMP_STOPPAY 126
#define CMD2DC_EMP_GOTCOIN 108 // REQ
#define CMD2DC_SHUTTER_OPEN 129
#define CMD2DC_ESCR_OPEN 132
#define CMD2DC_ESCR_TAKE 133
#define CMD2DC_ESCR_RETURN 134
#define CMD2DC_MOD_ON 135
#define CMD2DC_MOD_WAK 136
#define CMD2DC_CRED_ON 137
#define CMD2DC_CRED_WAK 138
// READ Commands ((e.g. get input)
#define CMD2DC_TestSerial 10
#define CMD2DC_GetSerialConfig 105
#define CMD2DC_RdBkHWversion 11
#define CMD2DC_RdBkSWversion 12
#define CMD2DC_RdBkDCstate 101
#define CMD2DC_RdBkUID 18
#define CMD2DC_RdBkTime 104
#define CMD2DC_RdBkAnalog 106
#define CMD2DC_GetAllInputs 102
#define CMD2DC_RdBkAllOutputs 103
#define CMD2DC_MIFREADERON 127
#define CMD2DC_ATB_CREATE 128
// Mif read data:
#define CMD2DC_RdBk_MifState 109
#define CMD2DC_RdBk_MifData 24
#define CMD2DC_RdBk_AtbCardType 25
#define CMD2DC_SHUTTER_COIN 131
#define CMD2DC_SHUTTER_OPEN3S 130
#define CMD2DC_SEND_SHUT_TIME 0x2915
#define CMD2DC_ESCR_TAKE 133
#define CMD2DC_ESCR_RETURN 134
#define CMD2DC_PRINTERON 139
#define CMD2DC_RdBk_PrnState 110
#define CMD2DC_RdBk_PrnFonts 26
#define CMD2DC_RdBk_AllPrnData 27
// nr of params:
#define CMD2DC_PRI_SYS_CMD 25 // 3
#define CMD2DC_PRI_ESC_CMD 26 // 4
#define CMD2DC_PRI_SETUP 27 // 5
#define CMD2DC_PRI_MOVE 140 // 2
#define CMD2DC_PRI_SETFONT 141 // 4
#define CMD2DC_PRI_SETLETTER 142 // 3
#define CMD2DC_PRI_CUT 143 // 1
#define CMD2DC_PRI_PRINT_TXT 13 // 64
#define CMD2DC_PRI_LF 144 // 1
#define CMD2DC_PRI_PRIFONTTABLE 145
#define CMD2DC_PRI_BARCODE 14 // ca 15...25
#define CMD2DC_STOR_QR_DATA 15 // 150
#define CMD2DC_PRI_QR_CODE 146 // 0
#define CMD2DC_PRI_LOGOFROMFLASH 147 // 2
#define CMD2DC_PRI_STORE_DOC 16 // 1
#define CMD2DC_PRI_DOCUMENT_NR 17 // 1 + 64
#define CMD2DC_PRI_CLEAR_DOC 148 // 1
/*
// WRITE Commands (e.g. switch relay)
#define CMD2DC_sendTime 0x1310
#define CMD2DC_setWakeFrequ 0x1320
#define CMD2DC_MOV_UPLOCK 0x1801
#define CMD2DC_MOV_DNLOCK 0x1802
#define CMD2DC_UPPER_DOOR 0x1810
#define CMD2DC_LOWER_DOOR 0x1811
#define CMD2DC_VAULT_DOOR 0x1812
// neu 7.10.21:
#define CMD2DC_REJMOT_ON 0x1813
#define CMD2DC_REJMOT_RUN 0x1814
#define CMD2DC_LED_COIN 0x1204
#define CMD2DC_LED_ILLU 0x1205
#define CMD2DC_LED_TICKET 0x1206
#define CMD2DC_LED_START 0x1208
#define CMD2DC_LED_PIN 0x1207
#define CMD2DC_LED_IN 0x1209
#define CMD2DC_FAN 0x1210
#define CMD2DC_SIREN 0x1211
#define CMD2DC_BARRIER 0x1212
#define CMD2DC_WAKEPTU 0x1218
#define CMD2DC_SWITCHAUXPWR 0x1220
#define CMD2DC_SWITCHAUXDDR 0x1222
#define CMD2DC_SWITCHAUXOUT 0x1224
#define CMD2DC_UCONTACTON 0x1226
#define CMD2DC_DEVICE_PARAM 0x2000
#define CMD2DC_SEND_MACH_ID 0x2002
#define CMD2DC_RDBK_DEV_PARA 0x2001
#define CMD2DC_RDBK_MACH_ID 0x2003
// --------------------------- MDB --------------
#define CMD2DC_MDB_ON 0x2800
#define CMD2DC_MDB_GET_STATE 0x2801 // REQ
#define CMD2DC_MDB_DORESET 0x2802
#define CMD2DC_MDB_SETWAK 0x2811
//#define CMD2DC_MDB_GETWAK 0x2812 // REQ not nec.
#define CMD2DC_MDB_SENDCMD 0x2820
#define CMD2DC_MDB_SENDMSG 0x2821
#define CMD2DC_MDB_GETRESP 0x2822 // REQ
// --------------------------- EMP --------------
#define CMD2DC_EMP_SET 0x2830
#define CMD2DC_EMP_GET_ALL 0x2831 // REQ
#define CMD2DC_EMP_STARTPOLL 0x2832
#define CMD2DC_EMP_STARTPAY 0x2834
#define CMD2DC_EMP_STOPPAY 0x2836
#define CMD2DC_EMP_GOTCOIN 0x2837 // REQ
#define CMD2DC_SHUTTER_OPEN 0x2911
#define CMD2DC_ESCR_OPEN 0x2920
#define CMD2DC_ESCR_TAKE 0x2921
#define CMD2DC_ESCR_RETURN 0x2922
#define CMD2DC_MOD_ON 0x2940
#define CMD2DC_MOD_WAK 0x2941
#define CMD2DC_CRED_ON 0x2960
#define CMD2DC_CRED_WAK 0x2961
// READ Commands ((e.g. get input)
#define CMD2DC_TestSerial 0x1101
#define CMD2DC_GetSerialConfig 0x1107
#define CMD2DC_RdBkHWversion 0x110A
#define CMD2DC_RdBkSWversion 0x110B
#define CMD2DC_RdBkDCstate 0x110C
#define CMD2DC_RdBkUID 0x1305
#define CMD2DC_RdBkTime 0x1313
#define CMD2DC_RdBkAnalog 0x1550
#define CMD2DC_GetAllInputs 0x1201
#define CMD2DC_RdBkAllOutputs 0x1202
#define CMD2DC_MIFREADERON 0x2900
#define CMD2DC_ATB_CREATE 0x2907
// Mif read data:
#define CMD2DC_RdBk_MifState 0x2902
#define CMD2DC_RdBk_MifData 0x2903
#define CMD2DC_RdBk_AtbCardType 0x2905
//#define CMD2DC_RdBk_CardData 0x2906
// higher Level operation commands
//#define CMD2DC_SHUTTER_ONE 0x2912
#define CMD2DC_SHUTTER_COIN 0x2913
#define CMD2DC_SHUTTER_OPEN3S 0x2912
#define CMD2DC_SEND_SHUT_TIME 0x2915
#define CMD2DC_ESCR_TAKE 0x2921
#define CMD2DC_ESCR_RETURN 0x2922
#define CMD2DC_PRINTERON 0x2A01
#define CMD2DC_RdBk_PrnState 0x2A02
#define CMD2DC_RdBk_PrnFonts 0x2A12
#define CMD2DC_RdBk_AllPrnData 0x2A40
// nr of params:
#define CMD2DC_PRI_SYS_CMD 0x2A03 // 3
#define CMD2DC_PRI_ESC_CMD 0x2A04 // 4
#define CMD2DC_PRI_SETUP 0x2A05 // 5
#define CMD2DC_PRI_MOVE 0x2A06 // 2
#define CMD2DC_PRI_SETFONT 0x2A10 // 4
#define CMD2DC_PRI_SETLETTER 0x2A11 // 3
#define CMD2DC_PRI_CUT 0x2A13 // 1
#define CMD2DC_PRI_PRINT_TXT 0x2A14 // 64
#define CMD2DC_PRI_LF 0x2A15 // 1
#define CMD2DC_PRI_PRIFONTTABLE 0x2A16
#define CMD2DC_PRI_BARCODE 0x2A17 // ca 15...25
#define CMD2DC_STOR_QR_DATA 0x2A18 // 150
#define CMD2DC_PRI_QR_CODE 0x2A19 // 0
#define CMD2DC_PRI_LOGOFROMFLASH 0x2A1A // 2
#define CMD2DC_PRI_STORE_DOC 0x2A41 // 1
#define CMD2DC_PRI_DOCUMENT_NR 0x2A42 // 1 + 64
#define CMD2DC_PRI_CLEAR_DOC 0x2A43 // 1
*/
#define FIX_SLAVE_ADDR 0
#define SEND_ATONCE 1
#define SENDCOMBINED 0
class T_datif : public QMainWindow
{
Q_OBJECT
char sendINrequestsAutomatic(void);
// sende alle Befehle um die Eingangsdaten abzufragen der Reihe nach
char loadRecDataFromFrame();
void datif_startSending(void);
void datif_sendIOrequest(uint16_t WRcmd, uint16_t RDcmd, uint8_t nrOfWrData);
void datif_send8byteOutCmd(uint16_t WRcmd, uint16_t RDcmd);
bool verifyLineTestresponse(uint8_t RdDlen, uint8_t *receivedData);
void datif_OUT_setTime(void);
uint8_t datif_OUT_SendRandomData(uint8_t *buf, uint8_t Length);
void datif_send64byteOutCmd(uint16_t WRcmd, uint16_t addr, uint16_t RDcmd);
void datif_sendToMemory(uint16_t WRcmd, uint16_t docNr, uint16_t blockNr, uint8_t *data64);
// send printer documents to DC2 memory
// docNr: 0...15(31) with 1280 byte each (20 blocks a 64byte)
// blockNr=0...19 with 64byte each
// docNr =transmitted in WRITEADDRESS high byte
// blockNr=transmitted in WRITEADDRESS low byte
T_prot *myDCIF;
QTimer *datif_trigger;
uint8_t selectedSlaveAddr;
private slots:
char datif_cycleSend();
void StoredRecData();
public:
T_datif(QWidget *parent = nullptr);
T_prot *getProt() { return myDCIF; }
T_prot const *getProt() const { return myDCIF; }
void resetChain(void);
char isPortOpen(void);
void sendWRcommand(uint16_t nxtAsCmd);
// Sende Schreibbefehle die bereits vorher asynchron gespeichert wurden
void send_requests(uint16_t nextWrCmd);
void sendHighLevel(uint16_t nxtHLCmd);
bool areDataValid(void);
signals:
void ResponseRecieved();
//the requested data are stored in peripheral image
// can be loaded with epi
void datif_templatePrintFinished_OK();
void datif_templatePrintFinished_Err();
void datif_gotNewCoin();
};
#endif // CI_H

View File

@ -1,102 +0,0 @@
#ifndef DCBL_H
#define DCBL_H
#include <stdint.h>
#include "qbytearray.h"
#include "qstring.h"
#include <QFile>
uint8_t dcBL_prepareDC_BLcmd(uint8_t Cmd, uint8_t SendDataLength, uint8_t *sendData, uint8_t *outBuf);
// make BL protocol, retval = outbuf length (5...133)
// bring data in correct form: start always with 0x02 finish with 0x03 and append checksum
// 0x02 Cmd < ...sendData ..> CRC CRC 0x03
// Data length = 0...64
// special conversion: if data contain 2 or 3 (STX, ETX) then write two bytes: 0x1B (=ESC) and data|0x80
// so maxlength = 5 + 2 x 64 (if all data are 2 or 3) without 2,3: maxlength = 5 + 64
uint8_t dcBL_readBLversion(uint8_t *sendData);
// minimum size of sendData-buffer: 5byte retval: length
uint8_t dcBL_readFWversion(uint8_t *sendData);
// minimum size of sendData-buffer: 5byte retval: length
uint8_t dcBL_exitBL(uint8_t *sendData);
// minimum size of sendData-buffer: 5byte retval: length
uint8_t dcBL_sendFlashStartAddr2BL(uint32_t startAddr, uint8_t *sendData);
// minimum size of sendData-buffer: 13byte retval: length (9...13)
uint8_t dcBL_writeLastPage(uint8_t *sendData);
// minimum size of sendData-buffer: 5byte retval: length
uint8_t dcBL_restartDC(uint8_t *sendData);
// minimum size of sendData-buffer: 20 byte retval: length
uint8_t dcBL_activatBootloader(uint8_t *sendData);
// minimum size of sendData-buffer: 20 byte retval: length
uint8_t dcBL_getResponse(uint8_t *respBuff);
// retval: nr of received bytes
bool dcBL_responseOK();
// retval: 0: response OK (cmd |0x80) 1: response error (cmd or "0xe0")
bool dcBL_importBinFile(QByteArray readBinFile, uint32_t fileSize, char withDispl);
bool dcBL_isTextMemFree(void);
void dcBL_writeText(QString newTxt);
bool dcBL_checkForText(void);
// if pointer at 0 then no more content
QString dcBL_readText(void);
// read from 0...9 (oldest first)
void dcBL_iniChain(void);
uint8_t dcBL_startChain(void);
uint8_t dcBL_runChain(void);
void dcBL_iniLoading(void);
void dcBL_startLoading(void);
uint8_t dcBL_sendHexfile(void);
uint8_t dcBL_getResult(void);
// call after every step to what's going on....
// 1: connected to BL
// 2: transmission started
// 3: transmission successful
#define RAW_BL_DATALEN 150
void gpi_storeRawReceivedData(uint8_t RdDlen, uint8_t *receivedData);
uint8_t epi_getRawReceivedData(uint8_t *receivedData);
// retval=length, will be zeroed after first reading
uint8_t epi_getRawRecLength(void);
// retval=length
QString epi_getRawReceivedString();
void epi_clrRawReceivedString();
uint8_t dcBL_sendSuccess(uint8_t lastCommand);
// return val: 0: no response by now 1:error 10: OK
// lastCommand=0x21 for sendAddr or 0x22 for send data
char dcBL_loadBinary(char withDisplay);
#endif // DCBL_H

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +0,0 @@
#ifndef SERIAL_FRAME_H
#define SERIAL_FRAME_H
#include <stdint.h>
#include <QMainWindow>
#include <QString>
#include <QTimer>
#include "tslib.h"
#include "com.h"
/*
get's OUT-data from datif,
get's IN-data from datif
get's send command from datif
makes frame and calls: isSerialFree(), setSendData(),
if not free retrigger datif sending period (normally 500ms or 50ms for direct cmds)
with control-signal: gotReceiveData():
getRecData();
send results to diag window/line
send IN-data to datif
*/
#define FRAME_DATALEN 64
#define FRAME_MAXLEN FRAME_DATALEN+20
#define BL_DATA_LEN 150
#define DATALEN_SEND_FAST 4
#define DATALEN_SEND_LONG 64
#define HEADERLEN_SEND 4
#define TELEGRAMLEN_SEND_FAST 12
#define TELEGRAMLEN_SEND_LONG 70
#define STARTSIGN_SEND_FAST 0x3F
#define STARTSIGN_SEND_LONG 0x3D
#define DATALEN_RECEIVE_FAST 8
#define DATALEN_RECEIVE_LONG 64
#define HEADERLEN_RECEIVE 2
#define TELEGRAMLEN_RECEIVE_FAST 12
#define TELEGRAMLEN_RECEIVE_LONG 68
#define STARTSIGN_RECEIVE_FAST 0x5F
#define STARTSIGN_RECEIVE_LONG 0x5D
class T_prot : public QMainWindow
{
Q_OBJECT
// Dateneingang von Datif:
uint8_t SendDataValid; // bit1: WR OK bit 2: RD OK
uint16_t slaveAddr;
uint16_t WriteCommand;
uint16_t WriteAddr;
uint8_t WrDataLength;
uint8_t ui8OutputData[FRAME_DATALEN];
char chOut_Data[FRAME_DATALEN];
uint8_t kindOfData; // 0: binaries, 1:text
uint16_t ReadCommand;
uint16_t ReadAddr;
uint16_t reserve;
// Ausgangs-Daten, werden vom Datif geholt:
// nur wenn CommandState und readState OK
uint8_t RecSlaveAddr;
bool INdataValid; // nur true wenn CommandState OK und readState OK
uint16_t readSource; // diese (Eingangs-)Daten stehen im Puffer
uint16_t readAddress; // von dieser Adr wurden die Daten gelesen
//uint8_t lastWakeSrc; // falls der Slave den Master geweckt hat
uint8_t RdDataLength;
uint8_t InputData[FRAME_DATALEN];
// 11.11.2020:
uint8_t BLsendDataLength;
uint8_t ui8BLsendData[BL_DATA_LEN];
T_com *mySerialPort;
void startPacking(void);
void startFastPacking(void);
uint8_t FramecheckInData(uint8_t *Inbuf, uint16_t LL);
uint8_t FastCheckInData(uint8_t *Inbuf, uint16_t LL);
uint8_t CheckInResult(uint8_t *Inbuf);
uint8_t ShowFastInData(uint8_t *recBuffer);
uint8_t ShowInData(uint8_t *recBuffer); // was CheckInData
void setRecLen(uint16_t WriteCmd);
private slots:
void analyseRecData(void);
public:
T_com *getSerialPort() { return mySerialPort; }
T_com const *getSerialPort() const { return mySerialPort; }
T_prot();
bool isPortOpen(void);
bool isSerialFree(void);
void setUserWriteData(uint16_t WriteCmd, uint16_t WrAddr, uint8_t WrDatLen, uint8_t *data);
void setUserWriteData(uint16_t WriteCmd, uint16_t WrAddr);
void setUserWriteData(uint16_t WriteCmd);
void setUserWriteText(uint16_t WriteCmd, uint16_t WrAddr, uint8_t WrDatLen, char *data);
void setUserWrite1DB(uint16_t WriteCmd, uint16_t WrAddr, uint8_t val);
void setUserWrite2DB(uint16_t WriteCmd, uint16_t WrAddr, uint8_t val0, uint8_t val1);
void setUserReadData( uint16_t ReadCmd, uint16_t RdAddr, uint16_t reserv);
void setUserReadData( uint16_t ReadCmd, uint16_t RdAddr);
void setUserReadData( uint16_t ReadCmd);
void setBLsendData( uint8_t len, uint8_t *buf);
void receiveFixLen(int64_t nrOfbytesToReceive);
void sendUserData(uint16_t slaveAdr);
bool ifDataReceived();
bool getReceivedInData(uint8_t *SlavAddr, uint16_t *readSrc, uint16_t *readAddr,
uint8_t *RdDlen, uint8_t *receivedData);
// retval: data valid, only one time true
signals:
void framerecieved(); //bool gotINdata);
void rawDataRecieved();
};
#endif // T_prot_H

View File

@ -1,250 +0,0 @@
#ifndef SENDWRCMDS_DEFS_H
#define SENDWRCMDS_DEFS_H
#include <stdint.h>
#include "tslib.h"
#include <QString>
// asynch. Commands
// store OUTPUT commands until time to send
// problem: OUT commands are set if a button is pressed or a transaction event happens
// so it's never synchron with sending grid
// but sending must apply the 100ms time grid as we have to wait for the response before sending the next command!!!
// Level 0 (DC direct)
#define SENDDIRCMD_TestSerial 1
#define SENDDIRCMD_MakeReset 2
#define SENDDIRCMD_setTime 3
#define SENDDIRCMD_setWakeFrequ 4
// Level 1 (DC DO's switching connected parts)
#define SENDDIRCMD_MOVEUP_LOCK 5
#define SENDDIRCMD_MOVEDN_LOCK 6
#define SENDDIRCMD_OPENUP_DOOR 7
#define SENDDIRCMD_OPENDN_DOOR 8
#define SENDDIRCMD_LEDILLU 9
#define SENDDIRCMD_LEDCOIN 10
#define SENDDIRCMD_LEDTICKET 11
#define SENDDIRCMD_LEDPAD 12
#define SENDDIRCMD_LEDSTART 13
#define SENDDIRCMD_LEDINSIDE 14
//#define SENDDIRCMD_LED_ALL 15
#define SENDDIRCMD_FAN 16
#define SENDDIRCMD_LAERM 17
#define SENDDIRCMD_REL1 18
#define SENDDIRCMD_WAKEPTU 20
#define SENDDIRCMD_AUXPWR 21
#define SENDDIRCMD_AUXDDR 22
#define SENDDIRCMD_AUXOUT 23
#define SENDDIRCMD_UCONTACT_ON 30
#define SENDDIRCMD_PRN2_SWONOFF 31
#define SENDDIRCMD_MIF_SWONOFF 32 // 0x2900
#define SENDDIRCMD_MIF_ATBCREATE 33 // 0x2907
#define SENDDIRCMD_MOD_SWONOFF 40
#define SENDDIRCMD_MOD_WAKE 41
#define SENDDIRCMD_MDB_POWER 42
#define SENDDIRCMD_MDB_WAKE 43
#define SENDDIRCMD_CRED_ON 44
#define SENDDIRCMD_CRED_WAKE 45
#define SENDDIRCMD_SHUT_MOV 50
#define SENDDIRCMD_ESCRO_MOV 51
#define SENDDIR_OPENVAULT 52
#define SENDDIR_REJMOT_ON 53
#define SENDDIR_REJMOT_RUN 54
// Level 2 (serial from DC to devices)
#define SEND_REQU_SERCONF 100
#define SEND_REQU_HWversion 101
#define SEND_REQU_SWversion 102
#define SEND_REQU_CONDITION 103
#define SEND_REQU_UID 104
#define SEND_REQU_TIME 105
// includes wake frequency
#define SEND_REQU_ANALOGS 110
#define SEND_REQU_DIG_INPUTS 111
#define SEND_REQU_DIG_OUTPUTS 112
#define SEND_REQU_PRN_STATE 120
#define SEND_REQU_PRN_FONTS 121
#define SEND_REQU_PRN_ALL 122
#define SEND_REQU_MIFSTATE 123
// Type and state of reader
#define SEND_REQU_MIFDATA 124
// Type, UID, Header of card
// read one card sector
// sectors must be addressed by RD_ADD
#define SEND_REQU_MIF_ATB_TYPE 125
#define SEND_REQU_MDB_GETSTAT 126
//#define SEND_REQU_MDB_GETWAK 127
#define SEND_REQU_MDB_GETRESP 128
#define SEND_REQU_EMP_GETALL 129
#define SEND_REQU_EMP_GETCOIN 130
#define SENDDIRCMD_DEVICE_PARA 131
#define SENDDIRCMD_MACHINE_ID 132
#define SEND_REQU_DEVICE_PARA 133
#define SEND_REQU_MACINE_ID 134
// further: mdb state, coinchecker state, bill state, modem state, credit_state....
#define SENDDIRCMD_SHUTOPENBYTIME 60
#define SENDDIRCMD_SHUTOPENBYCOIN 61
//#define SENDDIRCMD_SHUT_SENDTIME 62
#define SENDDIRCMD_ESCRO_TAKE 63
#define SENDDIRCMD_ESCRO_GIVE 64
#define SENDDIRCMD_PRN_SYS_CMD 70
#define SENDDIRCMD_PRN_ESC_CMD 71
#define SENDDIRCMD_PRN_SETUP 72
#define SENDDIRCMD_PRN_MOVE 73
#define SENDDIRCMD_PRN_SETFONT 74
#define SENDDIRCMD_PRN_SETLETT 75
#define SENDDIRCMD_PRN_CUT 76
//#define SENDDIRCMD_PRN_TXT // not needed
#define SENDDIRCMD_PRN_LF 78
#define SENDDIRCMD_PRN_FONTTAB 79
#define SENDDIRCMD_PRN_BC 80
#define SENDDIRCMD_PRN_QR 81
#define SENDDIRCMD_PRN_STOREDQR 82
#define SENDDIRCMD_PRN_LOGO_FL 83
//#define SENDDIRCMD_PRN_LOGO_GRAF 84
//#define SENDDIRCMD_PRN_LOGODAT 85
//#define SENDDIRCMD_PRN_STORBC 86
#define SENDDIRCMD_PRN_STORQR 87
#define SENDDIRCMD_PRN_DOC 88
#define SENDDIRCMD_PRN_CLEARDOC 89
//#define SENDDIRCMD_MDB_POWER 42
//#define SENDDIRCMD_MDB_WAKE 43
#define SENDDIRCMD_MDB_RES 90
#define SENDDIRCMD_MDB_SENDCMD 91
#define SENDDIRCMD_MDB_SNDMSG 92
#define SENDDIRCMD_EMP_SETT 93
#define SENDDIRCMD_EMP_POLL 94
#define SENDDIRCMD_EMP_STARPPAY 95
#define SENDDIRCMD_EMP_STOPPAY 96
// obsolete:
#define SENDDIRCMD_PRN1_SENDTEXT 54
#define SENDDIRCMD_PRN1_SENDCMD 55
#define SENDDIRCMD_PRN1_SERPAR 56
#define SENDDIRCMD_PRN_LEVEL2_4B 58
#define SENDDIRCMD_PRN_LEVEL2_64 59
// highest priority
#define CMDSTACKDEPTH 16
// means: up to 16 cmd can be stored. They are issued one by one every 100ms
void sendWRcmd_clrCmdStack(void);
bool sendWRcmd_setSendCommand0(uint16_t nextCmd);
// GUI or app sends a command to DC transfered by serial
uint16_t sendWRcmd_getSendCommand0(void);
// lower priority
#define CMD4STACKDEPTH 8
void sendWRcmd_clrCmd4Stack(void);
bool sendWRcmd_setSendCommand4(uint16_t nextCmd, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4);
uint16_t sendWRcmd_getSendCommand4(uint8_t *dat1, uint8_t *dat2, uint8_t *dat3, uint8_t *dat4);
#define CMD8STACKDEPTH 4
void sendWRcmd_clrCmd8Stack(void);
bool sendWRcmd_setSendCommand8(uint16_t nextCmd, uint8_t dat1, uint8_t dat2, uint16_t dat3, uint32_t dat4);
uint16_t sendWRcmd_getSendCommand8(uint8_t *dat1, uint8_t *dat2, uint16_t *dat3, uint32_t *dat4);
// lowest priority
// wait for resonse before send next!
bool sendWRcmd_setSendBlock160(uint8_t leng, uint8_t *buf);
uint8_t sendWRcmd_getSendBlock160(uint8_t *leng, uint8_t *buf);
// retval = *leng
void sendWRcmd_INI(void);
uint8_t epi_store64ByteSendData(uint8_t length, uint8_t *buf);
// HWapi writes data to be forwarded to DC and further to mdb-device
// not batched! don't use twice within 100ms
uint8_t gpi_restore64ByteSendData(uint8_t *length, uint8_t *buf);
// datif reads data to forward to dc
// ONE printer doc consists of 20 x 64 byte
#define MAXNROF_PRNBYTES 64
#define MAXNROF_PRNBLOCKS 20
void epi_resetPrinterStack(void);
uint8_t epi_storePrnText(char *buf, uint8_t leng);
// store text and binary data from Gui in next higher free memory 0....9
uint8_t gpi_restorePrnText(uint8_t *retbuf);
// read printer text and send to slave, size of retbuf== 64
uint8_t gpi_chk4remainingText(void);
// retval: 0: no more textline left (to send) >0: nr of lines
void epi_storeUserOfSendingTextBuffer(uint8_t user, uint8_t para1, uint8_t para2, uint8_t para3, uint8_t para4 );
// user=1: Text-Print is using this buffer
// 2: QR-code-Printer is using this buffer
uint8_t gpi_getUserOfSendingTextBuffer(uint8_t *para1, uint8_t *para2, uint8_t *para3, uint8_t *para4);
// user=1: Text-Print is using this buffer
// 2: QR-code-Printer is using this buffer
#define FDCMD_STACKDEPTH 16
void sendFDcmd_clrStack(void);
bool sendFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4);
// write Command to memory, wait for transport
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);
// returns number of waiting command, maxFDCMD_STACKDEPTH
uint8_t check4freeFDshortCmd(void);
// returns number of free places in short-command stack
#define FDLONG_STACKDEPTH 16
void longFDcmd_clrStack(void);
bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t length, uint8_t *data);
// write Command to memory, wait for transport
// data buffer size always 64! data[64], padded with 0
bool longFDcmd_get(uint8_t *nextWrCmd, uint8_t *nextRdCmd, uint8_t *blockNum, uint8_t *length, uint8_t *data);
uint8_t check4FDlongCmd(void);
// 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

View File

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

@ -1,427 +0,0 @@
#ifndef STOREINDATA_H
#define STOREINDATA_H
#include <stdint.h>
//#include "tslib.h"
#include <QString>
#define MAXNROF_AO 3
//#define MAXNROF_GENSTR 16
#define MAXNROF_CONTR_PORTS 11
#define MAXNROF_DIports 2
#define MAXNROF_DOports 2
#define MAXNROF_CTR 2
#define MEASCHAN_TEMPERATURE 0
#define MEASCHAN_VOLTAGE 1
// gpi: DC-driver stores data for graphic peripheral interface
// epi: gui reads values from external peripheral interface
// store power on/off condition of the devices to control the data request
void indat_storePrinterPower(bool isOn);
bool indat_isPrinterOn();
void indat_storeMifarePower(bool isOn);
bool indat_isMifareOn();
void indat_storeMDBisOn(bool isOn);
bool indat_isMdbOn();
void gpi_storeSlaveSerParams(uint8_t slaveBaudRate, uint8_t NrDataBits,
uint8_t parity, uint8_t NrStopBits);
void epi_getSlaveSerParams(uint8_t *slaveBaudRate, uint8_t *NrDataBits,
uint8_t *parity, uint8_t *NrStopBits);
QString epi_getSlaveParamSTR();
void gpi_storeGenerals(uint8_t genNr, QString text);
// 0=HW 1=SW 2=State
QString epi_loadGenerals(uint8_t genNr);
// genNr=0=HW 1=SW 2=State
void gpi_storeUID(uint8_t const *buf8byteUid);
// buffer size: 8 byte
void epi_getUIDdec(uint8_t *buf8byteUid);
// buffer size: 8 byte
QString epi_getUIDstr();
// ///////////////////////////////////////////////////////////////////////////////////
// Time and Date
// ///////////////////////////////////////////////////////////////////////////////////
uint8_t epi_getSquareMode();
void gpi_backupSquareMode(uint8_t squMode);
void gpi_backupTime(uint8_t *timeBuffer, uint8_t Leng); // 104, <=8byte
void epi_getTime(uint8_t *hh, uint8_t *mm, uint8_t *ss);
void epi_getDate(uint8_t *yy, uint8_t *mm, uint8_t *dd);
void epi_getToday(uint8_t *dow, uint16_t *minOfToday, uint32_t *secOfToday);
bool epi_isLeapYear(uint8_t *lastLeapYear, uint8_t *NextLeapYear);
bool epi_isLeapYear();
void epi_getSpecialWeekTimeDate(uint8_t *DayOfWeek, uint8_t *HoursOfWeek, uint16_t *MinutesOfWeek);
void epi_getSpecialMonthTimeDate(uint8_t *DayOfMonth, uint16_t *HoursOfMonth, uint16_t *MinutesOfMonth);
void epi_getSpecialYearTimeDate(uint16_t *DayOfYear, uint16_t *HoursOfYear, uint32_t *MinutesOfYear);
// ///////////////////////////////////////////////////////////////////////////////////
// Analog values
// ///////////////////////////////////////////////////////////////////////////////////
// #define MAXNROF_AI 4
void gpi_storeAIs(uint8_t aiNr, uint16_t val); // rs -> Sdata
uint8_t gpi_getMaxNrAIs();
uint16_t epi_loadAIs(uint8_t aiNr); // Sdata -> gui
// return value of one ADC with channel nr: aiNr 0...15
uint32_t epi_loadMeasureValue(uint8_t ValueNr);
// ValueNr 0=ADC0, 1=ADC1 aso...
void gpi_storeMeasureValue(uint8_t ValueNr, uint32_t val);
// in mV, also bis 65,535V
QString epi_getSlaveTemperatureStr();
QString epi_getSlaveVoltageStr();
// value in "meas_volt" in mV, also bis 65,535V. Value range [6000...16000] (6V...16V)
// ///////////////////////////////////////////////////////////////////////////////////
// digital inputs
// ///////////////////////////////////////////////////////////////////////////////////
void gpi_storeDI_doorSwitches(uint8_t upperDoor, uint8_t lowerDoor, uint8_t vaultDoor);
uint8_t epi_getDI_doorSwitches(void);
// bit0: upper door 1: low door 2:vault door
void gpi_storeDI_vaultSwitches(uint8_t CashBoxIn, uint8_t BillBoxIn);
uint8_t epi_getDI_vaultSwitches(void);
// bit0: cash box 1: bill box in
void gpi_storeDI_lockSwitches(uint8_t indatUL, uint8_t indatLL);
// D5: bit 0: upper lockbar up bit1:down
// D6: bit 0: lower lockbar up bit1:down
uint8_t epi_getDI_lockSwitches(void);
// retval: bit 0: upper lockbar up bit1: upper lockbar is down
// bit 2: lower lockbar up bit1: lower lockbar is down
void gpi_storeDI_optos(uint8_t indatOpto);
// OptoIn bit 0,1: optoin 1,2
uint8_t epi_getDI_optos(void);
// bit0: opto in 1 1: opto in 2
uint8_t gpi_storeDI_auxIn(uint8_t indatAuxIn); // Aux0...5
uint8_t epi_getDI_auxIn(void); // bit0: auxin 1 ... 5: auxin 6
bool gpi_storeDI_ptuWake(bool w);
bool epi_getDI_ptuWake(void);
bool gpi_storeDI_mbdWake(bool w);
bool epi_getDI_mdbWake(void);
bool gpi_storeDI_prnReady(bool ready);
bool epi_getDI_prnReady(void);
bool gpi_storeDI_CoinAttach(bool attach);
bool epi_getDI_CoinAttach(void);
bool gpi_storeDI_CoinEscrow(bool ce);
bool epi_getDI_CoinEscrow(void);
bool gpi_storeDI_mifareCardTapped(bool tapped);
bool epi_getDI_mifareCardTapped(void);
bool gpi_storeDI_modemWake(bool w);
bool epi_getDI_modemWake(void);
bool gpi_storeDI_contactPowerIsOn(bool on);
bool epi_getDI_contactPwr(void);
bool gpi_storeDI_MifarePowerIsOn(bool on);
bool epi_getDI_mifarePwr(void);
bool gpi_storeDI_readbackMdbTxD(bool rdbkMdbTxd);
bool epi_getDI_mdbTxd(void);
bool gpi_storeDI_AuxPowerIsOn(bool on);
bool epi_getDI_auxPwr(void);
bool gpi_storeDI_GsmPowerIsOn(bool on);
bool epi_getDI_gsmPwr(void);
bool gpi_storeDI_CreditPowerIsOn(bool on);
bool epi_getDI_creditPwr(void);
bool gpi_storeDI_PrinterPowerIsOn(bool on);
bool epi_getDI_printerPwr(void);
bool gpi_storeDI_MdbPowerIsOn(bool on);
bool epi_getDI_mdbPwr(void);
bool gpi_storeDI_rejMot_home(bool reject);
bool epi_getDI_rejectMotor_homepos(void);
uint8_t gpi_storeDI_paperLow(uint8_t di);
uint8_t epi_getDI_npe_sensor(void);
// 0: Sensor sees paper 1: no paper 99: off
// ///////////////////////////////////////////////////////////////////////////////////
// readback digital outputs
// ///////////////////////////////////////////////////////////////////////////////////
uint8_t gpi_storeDO_mdbRxTst(uint8_t do_mbdRxTst);
bool epi_getDO_mdbRxTestOut(void);
uint8_t gpi_storeDO_motorOutputs(uint8_t Pwr);
uint8_t epi_getDO_motorOuts(void);
// bit0: upper lock forward bit 1 backward
// bit2: lower lock forward bit 3 backward
uint8_t gpi_storeDO_serialSwitch(uint8_t state);
// serial drv on/off, Serial mux1, Serial mux2
uint8_t epi_getDO_serialSwitch(void);
// serial drv on/off, Serial mux1, Serial mux2
bool epi_getDO_serialDriverIsOn(void);
bool epi_getDO_serialMux1isSetToPrinter(void);
// mux1 off: serial is switched to printer
bool epi_getDO_serialMux1isSetToModem(void);
// mux1 on: serial is switched to modem
bool epi_getDO_serialMux2isSetToCredit(void);
// mux2 off: serial is switched to credit card terminal
bool epi_getDO_serialMux2isSetToMifare(void);
// mux2 on: serial is switched to mifare reader
uint8_t gpi_storeDO_ledsAndFan(uint8_t ledState);
bool epi_getDO_led_coin(void);
bool epi_getDO_led_front(void);
bool epi_getDO_led_ticket(void);
bool epi_getDO_led_pin(void);
bool epi_getDO_led_start(void);
bool epi_getDO_led_inside(void);
bool epi_getDO_fan(void);
uint8_t gpi_storeDO_sirenAndRelay(uint8_t sirenRelay);
bool epi_getDO_sirene(void);
bool epi_getDO_relay(void);
uint8_t gpi_storeDO_ptuWake(uint8_t state);
bool epi_getDO_ptuWake(void);
uint8_t gpi_storeDO_auxPower(uint8_t pwr);
bool epi_getDO_auxPower(void);
uint8_t gpi_storeDO_coinShutter(uint8_t state);
bool epi_getDO_coinShutterOpen(void);
bool epi_getDO_coinShutterTest(void);
uint8_t gpi_storeDO_coinEscrow(uint8_t state);
uint8_t epi_getDO_coinEscrow(void);
// retval: 1:return flap is open 2:take flap is open 0:closed
uint8_t gpi_storeDO_printerPwrOn(uint8_t state);
uint8_t epi_getDO_printerPwr(void);
// ---------------------------------------------------------------------------------------------
// counterchecks, make sure that DC-outputs are correct
/*
bool epi_cntchk_wakePtu(void);
bool epi_cntchk_enabDrv01(void); // no communication possible if 0 !!!!!
bool epi_cntchk_swRs1toModem(void);
bool epi_cntchk_modemWake(void);
bool epi_cntchk_enabDrv2(void);
bool epi_cntchk_swRs2toMIF(void);
bool epi_cntchk_shutterIsOpen(void);
// counter check if shutter is really open, PJ4 must be OUT and HIGH, PB5 must be OUT and HIGH
// retval TRUE: shutter is open FALSE: shutter is closed
bool epi_cntchk_escrowReturnIsOpen(void);
bool epi_cntchk_escrowTakeIsOpen(void);
bool epi_cntchk_aux1DirOut(uint8_t auxNr);
bool epi_cntchk_aux1OutHigh(uint8_t auxNr);
bool epi_cntchk_ledPaperOn(void);
bool epi_cntchk_ledPinpadOn(void);
bool epi_cntchk_ledStartOn(void);
bool epi_cntchk_ledServiceOn(void);
bool epi_cntchk_ledCoinOn(void);
bool epi_cntchk_ledIllumOn(void);
bool epi_cntchk_FanOn(void);
bool epi_cntchk_RelaisOn(void);
bool epi_cntchk_LaermOn(void);
bool epi_cntchk_Mot1Ron(void);
bool epi_cntchk_Mot1Fon(void);
bool epi_cntchk_Mot2Ron(void);
bool epi_cntchk_Mot2Fon(void);
*/
// ------------------------------------------------------------------------------------
// MDB Sendind Data are store here for next transport to DC (Device Controller)
// Transport to Slave runs every 100ms, answer from mdb-slave (e.g. coin changer) comes right
// with next slave answer
// start with: SENDDIRCMD_EXCHGMDB,
// send crude data from here to DC, DC to mdb slaves, mdb answer, return here within 50ms
uint8_t gpi_storeMdbRecData(uint8_t length, uint8_t *buf);
// datif store received mdb data
uint8_t epi_getMdbResponse(void);
// 0=no response 1=ACK 2=NAK 3=ACK with data
uint8_t epi_getMdbRecLength(void);
// 0...31
uint8_t epi_restoreMdbRecData(uint8_t *buf);
// hwapi reads received mdb data from PI
uint8_t gpi_storeMifReaderStateAndCardType(uint8_t const *buf);
/* data description:
byte 0: current read state: 0=power off 1=reader-fault 2=ready
3=just reading 4=read complete
5=read partial, removed too early
6=state unknown
byte 1,2: read data length from card
3: 1=reader is OK (reported serial nr is OK) 0=wrong or no reader
4...15: reader version, expected "SL025-1.8"
byte16: 1=card is present 0:not
17: 0
18: card type reported from reader
19: 1=allowed card type 0=not
20: card size: 1 or 4 (dec) = card size
21: LengthOfUID: 4 or 7 (dec) (byte)
22: UID 8 byte in hex
byte 30: sector logged: 0
byte 31: current sector: 0
byte 32: result, always 0
*/
uint8_t epi_restoreMifState(uint8_t *buf, uint8_t maxBufferSize);
// retval 0=OK 1=error host buffer too small
bool gpi_storeMifCardData(uint8_t blkNr, uint8_t const *receivedData);
// blkNr=0...11 receivedData[64]
uint8_t epi_restoreMifData(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize);
// blkNr=0...11 return buf[64]
// retval: 1=error 0=OK
void epi_restorePrinterState(uint8_t *buf);
void gpi_storePrinterState(uint8_t const *buf);
void epi_restorePrinterFonts(uint8_t *buf);
void gpi_storePrinterFonts(uint8_t const *buf);
bool gpi_storeMdbState(bool busReady, bool V12on, bool V5on);
bool epi_restoreMdbBusReady(void);
bool epi_restoreMdbV12Ready(void);
bool epi_restoreMdbV5Ready(void);
void gpi_storeMdbResponse(uint8_t leng, uint8_t const *data);
void epi_restoreMdbResponse(uint8_t *leng, uint8_t *data);
// last received mdb answer (from mdb device)
// only needed if a special command was sent directly
// DB0: mdb Device-Nr
// DB1: last sent mdb command
// DB2: nr of received (payload) data bytes (apart from ACK, can be 0....34)
// DB3...DB38: rec.data (payload)
void gpi_storeEmpSettings(uint8_t leng, uint8_t const *data);
void epi_restoreEmpSettings(uint8_t *leng, uint8_t *data);
/*
void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t *data);
void epi_restoreEmpCoinSignal(uint8_t *leng, uint8_t *data);
// return 5 byte:
// data[0]=got coin 0xFF=emp reported an error 0=got nothing
// data[1]=emp-signal of last inserted coin
// data[2,3]=emp-value of last inserted coin
// data[4] = emp-error or warning
void epi_clearEmpCoinSignal();
*/
void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t const *data);
uint8_t epi_isNewCoinLeft(void);
// retval: 0...16 coins left in FIFO
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 epi_restoreRbDeviceSettings(uint8_t *leng, uint8_t *data);
void gpi_storeMachineIDsettings(uint8_t leng, uint8_t const *data);
void epi_restoreMachineIDsettings(uint8_t *leng, uint8_t *data);
void epi_clearCurrentPayment(void);
void gpi_storeCurrentPayment(uint32_t insertedAmount, uint16_t lastCoinType, uint16_t lastCoinValue);
uint32_t epi_CurrentPaymentGetAmount(void);
uint16_t epi_CurrentPaymentGetLastCoin(void);
bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values);
// alle bei diesem Verkauf eingeworfenen Münzen sind gespeichert falls die jmd. braucht
void gpi_storeWakeSources(uint8_t const *receivedData);
uint64_t epi_getWakeSources(void);
uint8_t epi_getWakeReason(void);
void gpi_storeExtendedTime(uint8_t leng, uint8_t const *data);
void epi_restoreExtendedTime(uint8_t *leng, uint8_t *data);
void gpi_storeDeviceConditions(uint8_t leng, uint8_t const *data);
void epi_restoreDeviceConditions(uint8_t *leng, uint8_t *data);
void gpi_storeDynMachineConditions(uint8_t leng, uint8_t const *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();
#endif

View File

@ -1,90 +0,0 @@
#ifndef TSLIB_H
#define TSLIB_H
#include <stdint.h>
#include <QByteArray>
#define LOWBYTE false
#define HIGHBYTE true
uint16_t uchar2uint(char Highbyte, char Lowbyte);
uint16_t uchar2uint(uint8_t Highbyte, uint8_t Lowbyte);
uint32_t uchar2ulong(uint8_t Highbyte, uint8_t MHbyte, uint8_t MLbyte, uint8_t Lowbyte);
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);
#define MITSEK 1
#define OHNESEK 0
#define HourSys12h 1
#define HourSys24h 0
void GetTimeString(uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t System12h, uint8_t ShowSec, uint8_t *buf);
// generate time as ascii string from integers hours/minutes/seconds
// System12h=0: 24h system =1: 12h System
// ShowSec=0: String has 5 digits (hh:mm) =1: String has 8 digits (hh:mm:ss)
// return String in *buf // 12 byte für buf!
#define DateFormatDeutsch 0
#define DateFormatAmerica 1
#define UsePointSeperator 0
#define UseSlashSeperator 1
void GetDateString(uint8_t day, uint8_t month, uint8_t yearhigh, uint8_t yearlow, uint8_t format, uint8_t sep, uint8_t *buf);
// generate date as ascii string from integers day/month/year
// yearhigh in europe always 20 (not in arabia)
// format= 0: dd.mm.yyyy (deutsch)
// 1: mm.dd.yyyy (amerika)
// 2: yyyy.mm.dd (Iran, Dubai)
// 3: dd.yyyy.mm
// 4: mm.yyyy.dd
// 5: yyyy.dd.mm
// sep: 0: use . as seperator 1: use / as seperator
// return String in *buf // 11 byte für buf!
void GetShortDateString(uint8_t day, uint8_t month, uint8_t yearlow, uint8_t format, uint8_t sep, uint8_t *buf);
// generate date as ascii string from integers day/month/year
// format= 0: dd.mm.yy (deutsch)
// 1: mm.dd.yy (amerika)
// 2: yy.mm.dd (Iran, Dubai)
// 3: dd.yy.mm
// 4: mm.yy.dd
// 5: yy.dd.mm
// sep: 0: use . as seperator 1: use / as seperator
// return String in *buf // 11byte für buf!
uint16_t tslib_strlen(char *buf);
uint16_t tslib_strlen(uint8_t *buf);
void tslib_strclr(char *buf, char clrsign, uint16_t len);
void tslib_strclr(uint8_t *buf, char clrsign, uint16_t len);
void tslib_strcpy(char *srcbuf, char *destbuf, uint16_t len);
void tslib_strcpy(char *srcbuf, uint8_t *destbuf, uint16_t len);
void tslib_strcpy(uint8_t *srcbuf, uint8_t *destbuf, uint16_t len);
uint16_t tslib_calcCrcCcitt(uint16_t BufLength, uint8_t *buf);
bool tslib_isDecAsciiNumber(char sign);
bool tslib_isHexAsciiNumber(char sign);
int tslib_getMinimum(int val1, int val2);
void tslib_text2array(QByteArray text, char *aray, uint16_t maxArayLen);
// usage: tslib_text2array("my text", ctmp, 50);
void biox_CopyBlock(uint8_t *src, uint16_t srcPos, uint8_t *dest, uint16_t destPos, uint16_t len);
// both buffers starting from pos 0
#endif // TSLIB_H

View File

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

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

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

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

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

@ -1,142 +0,0 @@
#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,449 +0,0 @@
#include "com.h"
#include <QDebug>
//#include "controlBus.h"
//////////////////////////////////////////////////////////////////////////////////
///
/// serial hardware layer
///
//////////////////////////////////////////////////////////////////////////////////
static int64_t com_want2read;
// -------------------------------------------------------------------------------------------------------------
// --------- PUBLIC --------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
void T_com::writeToSerial(const QByteArray &data, uint16_t sendLength)
{
sendBuffer=data;
sendLen=sendLength;
if (CatSerial->isOpen())
{
//qDebug() << "sending..." << sendBuffer;
CatSerial->write(sendBuffer);
} else
qDebug() << "error sending, port is not open";
}
bool T_com::readFromSerial(QByteArray &data, uint16_t &sendLength)
{
// return one time true if new data (completly) read.
// return new data in &data and &sendLength to other objects
uint16_t ll=rawInLen;
if (!CatSerial->isOpen())
return false;
data.clear();
data.append(rawInput);
sendLength=ll;
rawInLen=0; // beim 2. Aufruf 0 zurück weil nichts neues da
if (ll>0)
return true;
return false;
}
// -------------------------------------------------------------------------------------------------------------
// --------- PRIVATES --------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
T_com::T_com(QWidget *parent) : QMainWindow(parent)
{
// port settings come from tabCom->Sdata->serial
gpi_serialChanged();
CatSerial = new QSerialPort(); // PortHW object for Control&Analyse Tool
//CatSerial->clear();
//CatSerial->clearError();
connect(CatSerial, &QSerialPort::readyRead, this, &T_com::readSomeBytes);
// still reading, not sure if complete, undefined number of calls while reading
connect(CatSerial, &QSerialPort::bytesWritten, this, &T_com::serialSendComplete);
// system confirms sending complete
//connect(CatSerial, &QSerialPort::dataTerminalReadyChanged, this, &T_com::incomingWake);
//connect(CatSerial, &QSerialPort::requestToSendChanged, this, &T_com::incomingWake);
// timer detects time gap in input flow
serRecTime = new QTimer();
connect(serRecTime, SIGNAL(timeout()), this, SLOT(receiveTO()));
serRecTime->setSingleShot(true); // single shot! only one impulse if receive complete
serRecTime->stop(); // on hold
// check COM-TAB periodic if user wants to connect or disconnect
QTimer *ChkConnectTimer = new QTimer();
connect(ChkConnectTimer, SIGNAL(timeout()), this, SLOT(ser_ISR100ms()));
ChkConnectTimer->setSingleShot(false);
ChkConnectTimer->start(100); // in ms
com_want2read=0;
}
T_com::~T_com()
{
if (CatSerial->isOpen())
CatSerial->close();
}
void T_com::ser_ISR100ms()
{
//qDebug() << "~~>LIB" << "ENTER...";
// call every 100ms to check if user(HMI) wants to connect or disconnect
uint8_t chkConn = gpi_getSerialConn(); // from global GUI buffer (Sdata)
//qDebug() << "~~>LIB" << "checking connect button... " << chkConn;
switch (chkConn)
{
case 0: // 0 button "connect" was just released
//qDebug() << "close serial port" << chkConn;
closeSerialPort();
gpi_serialChanged(); // set chkConn to 2, thus getting edge
break;
case 1: // 1 button "connect" was just pressed
//qDebug() << "open serial port" << chkConn;
open_Serial_Port();
gpi_serialChanged(); // set chkConn to 2, thus getting edge
break;
}
if (CatSerial->isOpen()) {
gpi_serialIsOpen(true);
} else {
gpi_serialIsOpen(false);
}
//qDebug() << "LEAVE " << chkConn;
}
// -------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
char T_com::open_Serial_Port()
{
//qDebug() << "ENTER";
bool ret;
QString myString=nullptr, myPortName=nullptr, myBaudStr=nullptr;
int myBaudNr;
if (CatSerial->isOpen()) {
qDebug() << "!!!IS OPEN!!!";
return 0; // opening twice is not allowed
}
//qDebug() << "connecting..." << myPortName;
myPortName=gpi_getComPortName(); // was selected and stored from GUI
CatSerial->setPortName(myPortName);
myBaudNr=gpi_getBaudNr(); // was selected and stored from GUI
//qDebug() << "myPortName" << myPortName << ", myBaudNr" << myBaudNr;
switch (myBaudNr)
{
// 0:1200 1:9600 2:19200 3:38400 4:57600 5:115200
case 0: CatSerial->setBaudRate(QSerialPort::Baud1200); myBaudStr="1200"; break;
case 1: CatSerial->setBaudRate(QSerialPort::Baud9600); myBaudStr="9600"; break;
case 2: CatSerial->setBaudRate(QSerialPort::Baud19200); myBaudStr="19200"; break;
case 3: CatSerial->setBaudRate(QSerialPort::Baud38400); myBaudStr="38400"; break;
case 4: CatSerial->setBaudRate(QSerialPort::Baud57600); myBaudStr="57600"; break;
case 5: CatSerial->setBaudRate(QSerialPort::Baud115200); myBaudStr="115200"; break;
}
CatSerial->setDataBits(QSerialPort::Data8);
// alt: QSerialPort::Data5,6,7,8
CatSerial->setParity(QSerialPort::NoParity);
// alt: EvenParity, OddParity, NoParity
CatSerial->setStopBits(QSerialPort::OneStop);
// alternative: OneStop, TwoStop, OneAndHalfStop
CatSerial->setFlowControl(QSerialPort::NoFlowControl);
// alt: HardwareControl, SoftwareControl, NoFlowControl
ret=CatSerial->open(QIODevice::ReadWrite);
// alt: QIODevice::ReadWrite QIODevice::ReadOnly QIODevice::WriteOnly
if (!ret)
{
myString.clear();
myString = "error ";
myString.append(CatSerial->errorString());
qDebug() << myString;
gpi_setTxt4comStateLine(myString);
//qDebug() << "LEAVE";
return 0;
} else
{
myString.clear();
myString.append(myPortName);
//lang=myString.size();
myString.append(" opened with ");
myString.append(myBaudStr);
myString.append(" 8N1");
qDebug() << myString;
gpi_setTxt4comStateLine(myString);
gpi_setTxt4RsDiagWin(myString+"\n");
}
//qDebug() << "LEAVE";
return 0;
}
void T_com::closeSerialPort()
{
//qDebug() << "ENTER";
if (CatSerial->isOpen())
{
qDebug() << "closing connection";
CatSerial->close();
gpi_setTxt4comStateLine("closed");
gpi_setTxt4RsDiagWin("closed");
}
//qDebug() << "LEAVE";
}
void T_com::readSomeBytes(void)
{
// called by serial-read-detection
// restart off-time as input flow is ongoing
// timer for slow receive
// and serves as timeout for fast receive is msg is shorter as expected
serRecTime->stop();
serRecTime->start(20); // in ms
//qDebug()<< "com-rec read some bytes";
this->receiveByLength(); // since 14.12.21: fast receive
}
void T_com::receiveFixLen(int64_t nrOfbytesToReceive)
{
// call this before sending a request to slave
// then we know exactly when reception is complete -> much faster
com_want2read=nrOfbytesToReceive;
// since 14.12.21: FastDevice Protocol has two lengthen:
// fast: 12byte reception long: 68byte
}
void T_com::receiveByLength(void)
{
if (CatSerial->isOpen())
{
QString myString=nullptr, tmpStr=nullptr;
int64_t nrOfBytesreceived = CatSerial->bytesAvailable(); // nr of received bytes
//qDebug()<< "com-rec current Len: "<< nrOfBytesreceived;
if (nrOfBytesreceived >= com_want2read)
{
QByteArray data = CatSerial->readAll(); // erst auslesen wenn alles da! löscht den Empfangspuffer
serRecTime->stop(); // stop timeout to avoid 2nd emit
rawInLen=uint16_t (nrOfBytesreceived);
rawInput.clear();
rawInput.append(data);
// report "new data received" to other objects
//qDebug()<< "com-recFinished by Len "<< rawInLen;
emit receivingFinished();
}
}
}
void T_com::receiveTO(void)
{
// no new input data for 20ms, --> assuming frame complete
// save data in private "rawInput"-buffer
if (CatSerial->isOpen())
{
QString myString=nullptr, tmpStr=nullptr;
int64_t nrOfBytesreceived = CatSerial->bytesAvailable(); // nr of received bytes
QByteArray data = CatSerial->readAll();
rawInLen=uint16_t (nrOfBytesreceived);
rawInput.clear();
rawInput.append(data);
//rawInput[rawInLen]=0; // Zwangsterminierung bei QByteArray nicht nötig
// diag display in serial in/out window and debug window
myString.clear();
myString.setNum(rawInLen);
myString.append(" in: ");
//myString.append(rawInput);
for (int ii=0; ii<rawInLen; ii++)
{
tmpStr.clear();
tmpStr.setNum(rawInput[ii],16); // problem: wenn >0x80 dann wird EIN Byte 16 stellig angezeigt
int ll=tmpStr.length();
if (ll>2)
{
myString.append(tmpStr[ll-2]);
myString.append(tmpStr[ll-1]);
} else
{
myString.append(tmpStr);
}
myString.append(" ");
}
myString.append("\n");
#ifdef PRINTALLDEBUGS
qDebug() << "VCP:" << myString; // display all inputs and outputs in output window
#endif
gpi_setTxt4RsDiagWin(myString);
//gpi_set2ndTxt4RsDiagWin(myString);
// report "new data received" to other objects
//qDebug()<< "com-recFinished by TO";
emit receivingFinished();
}
}
void T_com::serialSendComplete(void)
{
// system confirms sending complete, diag display
QString myString=nullptr, tmpStr=nullptr;
myString.clear();
myString.setNum(sendLen);
myString.append(" out: ");
for (int ii=0; ii<sendLen; ii++)
{
tmpStr.clear();
tmpStr.setNum(sendBuffer[ii],16); // problem: wenn >0x80 dann 16stellig
int ll=tmpStr.length();
if (ll>2)
{
//qDebug() << "long_string" << ll << "\n";
myString.append(tmpStr[ll-2]);
myString.append(tmpStr[ll-1]);
} else
{
myString.append(tmpStr);
}
myString.append(" ");
}
#ifdef PRINTALLDEBUGS
myString.append("\n");
qDebug() << myString; // display all output data in out-window
#endif
gpi_setTxt4RsDiagWin(myString);
emit sendingFinished(); // for whom it may interest
}
bool T_com::isPortOpen(void)
{
if (CatSerial->isOpen())
return true;
return false;
}
// -------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
/*
uint8_t T_com::getAllPortPins(void)
{
uint8_t rs232pins=0;
rs232pins= uint8_t(CatSerial->pinoutSignals());
// rs232pins: all signals bitwise coded in one byte:
// readback output: bit 0=TxD(=output) bit2=DTR (=output) bit 6=RTS (=output)
// unused inputs: bit1=RxD bit 3=DCD bit 5 = RING
// handshake inputs: bit 4=DSR (0x10) bit 7=CTS (0x80)
//qDebug()<<"serial port pins: " << rs232pins;
return rs232pins;
}
bool T_com::getHSin_CTS(void)
{
// return the used Handshake IN (CTS, alt. DSR): true= high level (+8V)
uint8_t rs232pins=0;
rs232pins= uint8_t(CatSerial->pinoutSignals());
// rs232pins: all signals bitwise coded in one byte:
// readback output: bit 0=TxD(=output) bit2=DTR (=output) bit 6=RTS (=output)
// unused inputs: bit1=RxD bit 3=DCD bit 5 = RING
// handshake inputs: bit 4=DSR (0x10) bit 7=CTS (0x80)
if (rs232pins & 0x80) // CTS
return true;
return false;
}
bool T_com::getHSin_DSR(void)
{
uint8_t rs232pins=0;
rs232pins= uint8_t(CatSerial->pinoutSignals());
if (rs232pins & 0x10) // DSR
return true;
return false;
}
void T_com::incomingWake(void) //(bool LevelOfTheBit)
{
emit wasWokenBySerialHandshake();
}
bool T_com::setHSout_RTS(bool hsout)
{
// hsout true=positiv voltage +12V false= -12V
// retval: true=setting OK
bool cc;
// 10.5.19, am Windows-PC nachgemessen, funktioniert gut
// false ergibt -12V true ergibt +12V
cc=CatSerial->setRequestToSend(hsout); // RTS out
// retval true means "setting was successful"
// alternative: use DTR as Handshake:
//cc=CatSerial->setDataTerminalReady(false); // DTR out
// retval true means "setting was successful"
//qDebug()<<"RTS " <<cc;
return cc;
}
bool T_com::setHSout_DTR(bool hsout)
{
// hsout true=positiv voltage +12V false= -12V
// retval: true=setting OK
bool cc;
// 10.5.19, am Windows-PC nachgemessen, funktioniert gut
// false ergibt -12V true ergibt +12V
cc=CatSerial->setDataTerminalReady(hsout); // DTR out
// retval true means "setting was successful"
//qDebug()<<"DTR " <<cc;
return cc;
}
*/

View File

@ -1,326 +0,0 @@
#include <stdint.h>
#include <algorithm>
#include <QString>
#include <QDebug>
#include "tslib.h"
#include "shared_mem_buffer.h"
// ///////////////////////////////////////////////////////////////////////////////////
// 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);
memset(&SharedMemBuffer::getData()->rs.baudStr[0], 0x00,
sizeof(SharedMemBuffer::getData()->rs.baudStr));
strncpy(SharedMemBuffer::getData()->rs.baudStr,
BaudStr.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->rs.baudStr)-1);
SharedMemBuffer::getData()->rs.baudNr = BaudNr;
SharedMemBuffer::getData()->rs.connect = connect;
}
void epi_closeSerial(void) {
SharedMemBuffer::getData()->rs.connect = 0;
}
void gpi_serialChanged(void) {
// serial confirms that port was closed or opened
// rs_connect=2; // Flanke, nur 1x öffnen/schließen
SharedMemBuffer::getData()->rs.connect = 2;
}
uint8_t gpi_getSerialConn(void) {
return SharedMemBuffer::getDataConst()->rs.connect;
}
int gpi_getBaudNr(void) {
return SharedMemBuffer::getDataConst()->rs.baudNr;
}
QString gpi_getComPortName(void) {
return SharedMemBuffer::getDataConst()->rs.comportName;
}
void gpi_serialIsOpen(bool offen) {
SharedMemBuffer::getData()->rs.portIsOpen = offen;
}
bool epi_isSerialPortOpen() {
// true: port is open false: port is closed
return SharedMemBuffer::getDataConst()->rs.portIsOpen;
}
// ///////////////////////////////////////////////////////////////////////////////////
// Control transfer gui <--> serial
// ///////////////////////////////////////////////////////////////////////////////////
void epi_startEmmision(char start) {
SharedMemBuffer::getData()->AutoEmissionOn = start;
}
bool gpi_isEmmisionOn(void) {
return SharedMemBuffer::getDataConst()->AutoEmissionOn;
}
uint16_t gpi_getPeriodicSendTimeVal() {
SharedMemBuffer::getData()->datif.sendingPer_changed = 0;
if ((SharedMemBuffer::getDataConst()->datif.sendingPeriod < 3) ||
(SharedMemBuffer::getDataConst()->datif.sendingPeriod > 10000)) {
return 130; // ms, default
}
return SharedMemBuffer::getDataConst()->datif.sendingPeriod;
}
void epi_setPeriodicSendTimeVal(uint16_t val) {
if (val>=3 && val<10000) {
SharedMemBuffer::getData()->datif.sendingPer_changed = 1;
SharedMemBuffer::getData()->datif.sendingPeriod = val;
}
}
bool gpi_PeriodicSendTimeHasChanged() {
return SharedMemBuffer::getDataConst()->datif.sendingPer_changed;
}
// ///////////////////////////////////////////////////////////////////////////////////
// Status Display gui <--> serial
// ///////////////////////////////////////////////////////////////////////////////////
// linke Spalte, über Connect Button
static QString txt4comStateLine;
QString epi_getTxt4comStateLine(void) {
// GUI: get Text for serial Comport-State Line
return txt4comStateLine;
}
void gpi_setTxt4comStateLine(QString txtline) {
// serial: write Text to be displayed in serial Comport-State line (like "connected")
txt4comStateLine.clear();
if (txtline=="")
txt4comStateLine.clear();
else
txt4comStateLine=txtline;
}
void epi_clrTxt4comStateLine() {
txt4comStateLine.clear();
}
// rechte Spalte, oberste Statuszeile
// I) "Handshakes" (serial Control) flow.cpp
// geht überhaupt was raus? kommt überhaupt was zurück?
static QString txt4HsStateLine;
QString epi_getTxt4HsStateLine(void) {
return txt4HsStateLine;
}
void gpi_setTxt4HsStateLine(QString txtline) {
txt4HsStateLine.clear();
if (txtline=="")
txt4HsStateLine.clear();
else
txt4HsStateLine=txtline;
}
void epi_clrTxt4HsStateLine() {
txt4HsStateLine.clear();
}
// II) Master receive state (empfangenes Telgramm OK? crc? length? )
// Statuszeile Auswertung der SlaveResponse (serial Frame, CRC usw) (prot.cpp)
static QString txt4masterStateLine;
QString epi_getTxt4masterStateLine(void) {
return txt4masterStateLine;
}
void gpi_setTxt4masterStateLine(QString txtline) {
txt4masterStateLine.clear();
if (txtline=="")
txt4masterStateLine.clear();
else
txt4masterStateLine=txtline;
}
void epi_clrTxt4masterStateLine() {
txt4masterStateLine.clear();
}
//---------------------------------------------------------------------------------------------
// III Slave receive (from Master) OK? if then show results, if not then show errors
// entweder Empfangsfehler anzeigen (crc? length?) oder result OUT-OK, OUT_ERR, IN_OK, IN_ERR
// Hintergrund: wenn der Slave Fehler im Master-Telegramm gefunden hat, dann kann er es auch
// nicht verwenden und nichts ausgeben oder einlesen
static QString txt4resultStateLine;
QString epi_getTxt4resultStateLine(void) {
return txt4resultStateLine;
}
void gpi_setTxt4resultStateLine(QString txtline) {
txt4resultStateLine.clear();
if (txtline=="")
txt4resultStateLine.clear();
else
txt4resultStateLine=txtline;
}
void epi_clrTxt4resultStateLine() {
txt4resultStateLine.clear();
}
//---------------------------------------------------------------------------------------------
// IV Statuszeile Empfangsdaten
static QString txt4dataLine;
QString epi_getTxt4dataStateLine(void) {
// GUI: get Text for serial Comport-State Line
return txt4dataLine;
}
void gpi_setTxt4dataStateLine(QString txtline) {
// serial: write Text to be displayed in serial Comport-State line (like "connected")
txt4dataLine.clear();
if (txtline=="")
txt4dataLine.clear();
else
txt4dataLine=txtline;
}
void epi_clrTxt4dataStateLine() {
txt4dataLine.clear();
}
//---------------------------------------------------------------------------------------------
// 5. Zeile: Datif Ergebnis, Daten brauchbar?
static QString txt4datifReceive;
QString epi_getTxt4datifLine(void) {
return txt4datifReceive;
}
void gpi_setTxt4datifLine(QString txtline) {
txt4datifReceive.clear();
if (txtline=="")
txt4datifReceive.clear();
else
txt4datifReceive=txtline;
}
void epi_clrTxt4datifLine() {
txt4datifReceive.clear();
}
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
static QString txt4diagWindow;
QString epi_getTxt4RsDiagWin(void) {
return txt4diagWindow;
}
void gpi_setTxt4RsDiagWin(QString txtline) {
txt4diagWindow.clear();
if (txtline=="")
txt4diagWindow.clear();
else
txt4diagWindow=txtline;
}
void epi_clrTxt4RsDiagWin() {
txt4diagWindow.clear();
}
//---------------------------------------------------------------------------------------------
static QString sndTxt4diagWindow;
QString epi_get2ndTxt4RsDiagWin(void) {
return sndTxt4diagWindow;
}
void gpi_set2ndTxt4RsDiagWin(QString txtline) {
sndTxt4diagWindow.clear();
if (txtline=="")
sndTxt4diagWindow.clear();
else
sndTxt4diagWindow=txtline;
}
void epi_clr2ndTxt4RsDiagWin() {
sndTxt4diagWindow.clear();
}
// ///////////////////////////////////////////////////////////////////////////////////
// Memory for Slave responses, common data
// ///////////////////////////////////////////////////////////////////////////////////
void gpi_storeResult_serialTestOK(bool wasOk) {
SharedMemBuffer::getData()->Sdata.serialTestResult = wasOk;
}
bool epi_getResult_serialTestOK() {
// retval: true: test was successful, got right response
return SharedMemBuffer::getDataConst()->Sdata.serialTestResult;
}
// ///////////////////////////////////////////////////////////////////////////////////
// Store received data for hwapi
// ///////////////////////////////////////////////////////////////////////////////////
void gpi_startNewRequest() {
SharedMemBuffer::getData()->Sdata.pProtResultOk = 0;
}
void gpi_storeResultOfLastRequest(bool answisok) {
SharedMemBuffer::getData()->Sdata.pProtResultOk = answisok ? 1 : 2;
}
uint8_t epi_getResultOfLastRequest() {
// retval: 0: in progress 1: OK 2: error
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));
memset((char *)(&SharedMemBuffer::getData()->Sdata.receivedDataBlock[0]),
0x00, sizeof(SharedMemBuffer::getData()->Sdata.receivedDataBlock));
strncpy((char *)(&SharedMemBuffer::getData()->Sdata.receivedDataBlock[0]),
(char const *)receivedData,
sizeof(SharedMemBuffer::getData()->Sdata.receivedDataBlock)-1);
}
uint16_t epi_getLastPayLoad(uint16_t plBufSiz, uint8_t *payLoad) {
// get data back in *pl, max 64 byte
// retval = nr of bytes received. If host buffer too small then
// only plBufSíz bytes are copied to pl
// plBufSíz=size of host buffer
uint16_t ml = std::min(plBufSiz, (uint16_t)(64));
if (SharedMemBuffer::getDataConst()->Sdata.receivedDataLength < ml) {
ml = SharedMemBuffer::getDataConst()->Sdata.receivedDataLength;
}
strncpy((char *)payLoad,
(char const *)(&SharedMemBuffer::getData()->Sdata.receivedDataBlock[0]),
ml);
return SharedMemBuffer::getDataConst()->Sdata.receivedDataLength;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

@ -1,764 +0,0 @@
#include "prot.h"
#include <QDebug>
#include "controlBus.h"
#include "dcBL.h"
T_prot::T_prot()
{
mySerialPort = new T_com();
connect(mySerialPort, SIGNAL(receivingFinished()), this, SLOT( analyseRecData() ));
//connect(mySerialPort, SIGNAL(sendingFinished()), this, SLOT(sendeFin()));
for (int nn=0; nn<FRAME_DATALEN; nn++)
{
chOut_Data[nn]=0;
ui8OutputData[nn]=0;
InputData[nn]=0;
}
for (int nn=0; nn<BL_DATA_LEN; nn++)
{
ui8BLsendData[nn]=0;
}
WriteCommand=0;
WriteAddr=0;
WrDataLength=0;
SendDataValid=0;
kindOfData=0;
slaveAddr=0;
ReadCommand=0;
ReadAddr=0;
reserve =0;
RecSlaveAddr =0;
INdataValid=0;
readSource =0;
readAddress=0;
RdDataLength=0;
BLsendDataLength=0;
}
// ---------------------------------------------------------------------------------------------------------
// sending.....
// ---------------------------------------------------------------------------------------------------------
bool T_prot::isPortOpen(void)
{
return mySerialPort->isPortOpen();
}
bool T_prot::isSerialFree(void)
{
return true; // ohne HS's kann er nicht blockiert sein
}
void T_prot::setRecLen(uint16_t WriteCmd)
{
if (WriteCmd<100)
{
RdDataLength=DATALEN_RECEIVE_LONG; // store here already because it's no longer
// returned from slave
mySerialPort->receiveFixLen(TELEGRAMLEN_RECEIVE_LONG);
} else
{
RdDataLength=DATALEN_RECEIVE_FAST;
mySerialPort->receiveFixLen(TELEGRAMLEN_RECEIVE_FAST);
}
}
void T_prot::setUserWriteData(uint16_t WriteCmd, uint16_t WrAddr, uint8_t WrDatLen, uint8_t *data)
{
WriteCommand=WriteCmd;
WriteAddr=WrAddr;
WrDataLength=WrDatLen;
if (WrDataLength>FRAME_DATALEN)
WrDataLength=FRAME_DATALEN;
for (int nn=0; nn<WrDataLength; nn++)
ui8OutputData[nn]=data[nn];
SendDataValid=1; // always set WR first
kindOfData=0; // 0: binaries, 1:text
this->setRecLen(WriteCmd);
}
void T_prot::setUserWriteData(uint16_t WriteCmd, uint16_t WrAddr)
{
WriteCommand=WriteCmd;
WriteAddr=WrAddr;
WrDataLength=0;
for (int nn=0; nn<FRAME_DATALEN; nn++)
ui8OutputData[nn]=0;
SendDataValid=1; // always set WR first
kindOfData=0; // 0: binaries, 1:text
this->setRecLen(WriteCmd);
}
void T_prot::setUserWriteData(uint16_t WriteCmd)
{
WriteCommand=WriteCmd;
WriteAddr=0;
WrDataLength=0;
for (int nn=0; nn<FRAME_DATALEN; nn++)
ui8OutputData[nn]=0;
SendDataValid=1; // always set WR first
kindOfData=0; // 0: binaries, 1:text
this->setRecLen(WriteCmd);
}
void T_prot::setUserWrite1DB(uint16_t WriteCmd, uint16_t WrAddr, uint8_t val)
{
// wie oben, jedoch einfachere Datenübergabe
WriteCommand=WriteCmd;
WriteAddr=WrAddr;
WrDataLength=1;
ui8OutputData[0]=val;
SendDataValid=1; // always set WR first
kindOfData=0; // 0: binaries, 1:text
this->setRecLen(WriteCmd);
}
void T_prot::setUserWrite2DB(uint16_t WriteCmd, uint16_t WrAddr, uint8_t val0, uint8_t val1)
{
WriteCommand=WriteCmd;
WriteAddr=WrAddr;
WrDataLength=2;
ui8OutputData[0]=val0;
ui8OutputData[1]=val1;
SendDataValid=1; // always set WR first
kindOfData=0; // 0: binaries, 1:text
this->setRecLen(WriteCmd);
}
void T_prot::setUserWriteText(uint16_t WriteCmd, uint16_t WrAddr, uint8_t WrDatLen, char *data)
{
WriteCommand=WriteCmd;
WriteAddr=WrAddr;
WrDataLength=WrDatLen;
if (WrDataLength>FRAME_DATALEN)
WrDataLength=FRAME_DATALEN;
for (int nn=0; nn<WrDataLength; nn++)
chOut_Data[nn]=data[nn];
SendDataValid=1; // always set WR first
kindOfData=1; // 0: binaries, 1:text
this->setRecLen(WriteCmd);
}
void T_prot::setUserReadData( uint16_t ReadCmd, uint16_t RdAddr, uint16_t reserv)
{
ReadCommand=ReadCmd;
ReadAddr=RdAddr;
reserve=reserv;
SendDataValid |=2;
readAddress=RdAddr; // store here already because it's no longer returned from slave
readSource=ReadCmd;
}
void T_prot::setUserReadData( uint16_t ReadCmd, uint16_t RdAddr)
{
ReadCommand=ReadCmd;
ReadAddr=RdAddr;
reserve=0;
SendDataValid |=2;
readAddress=RdAddr; // store here already because it's no longer returned from slave
readSource=ReadCmd;
}
void T_prot::setUserReadData( uint16_t ReadCmd)
{
ReadCommand=ReadCmd;
ReadAddr=0;
reserve=0;
SendDataValid |=2;
readAddress=0; // store here already because it's no longer returned from slave
readSource=ReadCmd;
}
void T_prot::setBLsendData( uint8_t len, uint8_t *buf)
{
for (int nn=0; nn<BL_DATA_LEN; nn++)
ui8BLsendData[nn]=0;
BLsendDataLength=len;
if ( BLsendDataLength>BL_DATA_LEN) BLsendDataLength=BL_DATA_LEN;
for (int nn=0; nn<BLsendDataLength; nn++)
ui8BLsendData[nn]=buf[nn];
WriteCommand=0xFFFF;
this->setRecLen(100); // how many??
//readAddress= // needed??
//qDebug()<<"prot: got BL data " << len << "bytes, ";
//for (int i=0; i<len; ++i) {
// printf("%02x ", (unsigned char)buf[i]);
//} printf("\n");
/*
qDebug()<<buf[0] <<buf[1] <<buf[2] <<buf[3] <<buf[4] <<buf[5] <<buf[6] <<buf[7];
qDebug() <<buf[8] <<buf[9] <<buf[10] <<buf[11] <<buf[12] <<buf[13]<<buf[14]<<buf[15];
qDebug() <<buf[16] <<buf[17] <<buf[18] <<buf[19] <<buf[20] <<buf[21]<<buf[22]<<buf[23];
qDebug() <<buf[24] <<buf[25] <<buf[26] <<buf[27] <<buf[28] <<buf[29]<<buf[30]<<buf[31];
qDebug() <<buf[32] <<buf[33] <<buf[34] <<buf[35] <<buf[36] <<buf[37]<<buf[38]<<buf[39];
qDebug() <<buf[40] <<buf[41] <<buf[42] <<buf[43] <<buf[44] <<buf[45]<<buf[46]<<buf[47];
qDebug() <<buf[48] <<buf[49] <<buf[50] <<buf[51] <<buf[52] <<buf[53] <<buf[54]<<buf[55];
qDebug() <<buf[56] <<buf[57] <<buf[58] <<buf[59] <<buf[60] <<buf[61] <<buf[62]<<buf[63];
qDebug() <<buf[64] <<buf[65] <<buf[66] <<buf[67] <<buf[68] <<buf[69] <<buf[70]<<buf[71];
qDebug() <<buf[72] <<buf[73] <<buf[74] <<buf[75] <<buf[76] <<buf[77] <<buf[78]<<buf[79];
*/
}
void T_prot::receiveFixLen(int64_t nrOfbytesToReceive)
{
mySerialPort->receiveFixLen(nrOfbytesToReceive);
}
void T_prot::sendUserData(uint16_t slaveAdr)
{
// man könnte hier noch "SendDataValid" abfragen,
// muss immer 3 sein, muss man aber nicht
//qDebug() << "prot send user data "<<slaveAdr;
QByteArray packBuf_2;
slaveAddr=slaveAdr;
if (WriteCommand==0xFFFF)
{
// Bypass for bootloader, no protocol frame but send as is...
packBuf_2.clear();
for (int nn=0; nn<BLsendDataLength; nn++)
packBuf_2[nn]=char(ui8BLsendData[nn]);
mySerialPort->writeToSerial(packBuf_2, BLsendDataLength);
} else
startFastPacking(); // quicker since 15.12.21TS
//startPacking();
}
void T_prot::startFastPacking(void)
{
uint16_t mycrc;
uint16_t sendLen;
uint8_t uctmp, nn, pp, CrcLp;
char sendBuffer[FRAME_MAXLEN], ctmp;
//qDebug() << "prot start fast packing "<<slaveAddr;
for (int nn=0; nn<FRAME_MAXLEN; nn++)
sendBuffer[nn]=0;
if (WriteCommand>9 && WriteCommand<100)
{
// long command 10...99
// WriteCommand==0 if only read request, then use short sending
sendBuffer[0]=STARTSIGN_SEND_LONG;
WrDataLength=DATALEN_SEND_LONG; // immer
//qDebug() << "send long cmd, len: " << WrDataLength;
} else
{
// fast command
sendBuffer[0]=STARTSIGN_SEND_FAST;
WrDataLength=DATALEN_SEND_FAST; // immer
//qDebug() << "send fast cmd, len: " << WrDataLength;
}
sendBuffer[1]= uint8_t(WriteCommand);
sendBuffer[2]= uint8_t(ReadCommand);
if (WriteAddr>0)
sendBuffer[3]= char(WriteAddr); // bei fast nur EINE adresse, wr hat Vorrang
else
sendBuffer[3]= char(ReadAddr);
// beim Fast prot. ist das reserve dann ists egal was drin steht
if (kindOfData) // 0: binaries, 1:text
{
for (nn=0; nn<WrDataLength; nn++)
{
pp=HEADERLEN_SEND+nn;
ctmp=(chOut_Data[nn]); // text
sendBuffer[pp]= char(ctmp);
}
} else
{
for (nn=0; nn<WrDataLength; nn++)
{
pp=HEADERLEN_SEND+nn;
uctmp=(ui8OutputData[nn]); // bin
sendBuffer[pp]= char(uctmp);
}
}
CrcLp= HEADERLEN_SEND + WrDataLength;
mycrc=0;
for (nn=0; nn<CrcLp; nn++)
{
uctmp=sendBuffer[nn];
mycrc+=uint16_t(uctmp);
//qDebug() << mycrc;
}
sendBuffer[CrcLp]=char(mycrc);
mycrc>>=8;
sendBuffer[CrcLp+1]=char(mycrc);
sendLen=CrcLp+2;
// send to VCP:
QByteArray packBuff;
packBuff.clear();
packBuff.append(sendBuffer, sendLen); // ohne sendLen wird beim ersten \0 abgeschnitten!!!
mySerialPort->writeToSerial(packBuff, sendLen);
}
/*
void T_prot::startPacking(void)
{
uint16_t mycrc;
uint16_t uitmp, sendLen;
uint8_t uctmp, nn, pp, CrcLp;
char sendBuffer[FRAME_MAXLEN], ctmp;
//qDebug() << "prot start packing "<<slaveAddr;
for (int nn=0; nn<FRAME_MAXLEN; nn++)
sendBuffer[nn]=0;
sendBuffer[0]='>';
uitmp=slaveAddr;
sendBuffer[1]= char(uitmp);
uitmp>>=8;
sendBuffer[2]= char(uitmp);
uitmp=WriteCommand;
sendBuffer[3]= char(uitmp);
uitmp>>=8;
sendBuffer[4]= char(uitmp);
uitmp=WriteAddr;
sendBuffer[5]= char(uitmp);
uitmp>>=8;
sendBuffer[6]= char(uitmp);
uitmp=ReadCommand;
sendBuffer[7]= char(uitmp);
uitmp>>=8;
sendBuffer[8]= char(uitmp);
uitmp=ReadAddr;
sendBuffer[9]= char(uitmp);
uitmp>>=8;
sendBuffer[10]= char(uitmp);
uitmp=reserve;
sendBuffer[11]= '-'; //char(uitmp);
uitmp>>=8;
sendBuffer[12]= '-'; //char(uitmp);
sendBuffer[13]= char(WrDataLength);
CrcLp= 14 + WrDataLength;
if (kindOfData) // 0: binaries, 1:text
{
for (nn=0; nn<WrDataLength; nn++)
{
pp=14+nn;
ctmp=(chOut_Data[nn]);
sendBuffer[pp]= ctmp;
}
} else
{
for (nn=0; nn<WrDataLength; nn++)
{
pp=14+nn;
uctmp=(ui8OutputData[nn]);
sendBuffer[pp]= char(uctmp);
}
}
mycrc=0;
for (nn=0; nn<CrcLp; nn++)
{
uctmp=sendBuffer[nn];
mycrc+=uint16_t(uctmp);
//qDebug() << mycrc;
}
sendBuffer[CrcLp]=char(mycrc);
mycrc>>=8;
sendBuffer[CrcLp+1]=char(mycrc);
sendLen=CrcLp+2;
sendBuffer[CrcLp+2]=13;
sendBuffer[CrcLp+3]=10;
sendLen+=2;
// send to VCP:
QByteArray packBuff;
packBuff.clear();
packBuff.append(sendBuffer, sendLen); // ohne sendLen wird beim ersten \0 abgeschnitten!!!
mySerialPort->writeToSerial(packBuff, sendLen);
// void T_com::writeToSerial(const QByteArray &data, uint16_t sendLength)
}
*/
// ---------------------------------------------------------------------------------------------------------
// receiving.....
// ---------------------------------------------------------------------------------------------------------
void T_prot::analyseRecData(void)
{
// Aufruf per connect aus serialcontrol wenn Daten empfangen wurden
// getRecData(QByteArray &data, uint16_t &sendLength);
QByteArray Indata;
QString myString, tempStr;
//char recBuffer[FRAME_MAXLEN];
uint8_t recBuffer[FRAME_MAXLEN];
uint16_t recLength;
INdataValid=false;
gpi_setTxt4HsStateLine("");
gpi_setTxt4masterStateLine("");
gpi_setTxt4resultStateLine("");
gpi_setTxt4dataStateLine("");
gpi_setTxt4datifLine("");
// read from "VCP":
mySerialPort->readFromSerial(Indata, recLength);
//qDebug()<<"prot: got data " << recLength;
if (recLength>FRAME_MAXLEN)
recLength=FRAME_MAXLEN;
for (int nn=0; nn<recLength; nn++)
recBuffer[nn]=uint8_t(Indata[nn]);
myString.clear();
tempStr.clear();
//uint8_t result=FramecheckInData(recBuffer, recLength); // check input data (response from slave)
uint8_t result=FastCheckInData(recBuffer, recLength); // check input data (response from slave)
if (result>0)
{
// dann anzeige
switch (result)
{
case 1: gpi_setTxt4masterStateLine("wrong length received"); break;
case 2: gpi_setTxt4masterStateLine("wrong start sign received"); break;
case 3: gpi_setTxt4masterStateLine("received datalen too big"); break;
case 4: gpi_setTxt4masterStateLine("wrong data len received"); break;
case 5: gpi_setTxt4masterStateLine("wrong crc received"); break;
}
myString.setNum(result);
// Daten abspeichern, könnten vom BL sein:
gpi_storeRawReceivedData(uint8_t(recLength), recBuffer);
emit rawDataRecieved();
} else
{
//& result ==0
gpi_setTxt4masterStateLine("slave response OK");
// Daten OK, also prüfe Inhalt.
// Konnte der Slave das Master-Command verwenden oder hatte es Fehler?
// konnte der Slave die geforderten Daten ausgeben (DOs, AOs)?
// konnte der Slave die geforderten Daten einlesen (AIs, DIs)?
//CheckInResult(recBuffer); // Ergebnisse des Slaves anzeigen
// stimmt nicht mehr bei FastProt
ShowFastInData(recBuffer); // Eingangs-Daten des Slaves anzeigen
}
emit framerecieved();
//qDebug() << "framereceived emitted";
}
uint8_t T_prot::FastCheckInData(uint8_t *Inbuf, uint16_t LL)
{
uint16_t rawInLen=LL, crcL_Addr, recCrc, myCrc, nn, datalen, nxt;
if (Inbuf[0]!=STARTSIGN_RECEIVE_FAST && Inbuf[0]!=STARTSIGN_RECEIVE_LONG)
{
//qDebug() << "prot: got wrong start sign: " << Inbuf[0];
return 2; // wrong start sign
}
if ( (rawInLen<TELEGRAMLEN_RECEIVE_FAST && Inbuf[0]==STARTSIGN_RECEIVE_FAST) ||
(rawInLen<TELEGRAMLEN_RECEIVE_LONG && Inbuf[0]==STARTSIGN_RECEIVE_LONG) )
{
//qDebug("prot: got %d bytes only", rawInLen);
return 1; // wrong length
}
if (Inbuf[0]==0x5F)
datalen=DATALEN_RECEIVE_FAST;
else
datalen=DATALEN_RECEIVE_LONG;
crcL_Addr=datalen+HEADERLEN_RECEIVE; // weil im definierten protocol 2 bytes vor den Daten stehen
recCrc=0;
recCrc=uchar2uint(uint8_t(Inbuf[crcL_Addr+1]), uint8_t(Inbuf[crcL_Addr]));
myCrc=0;
for (nn=0; nn<crcL_Addr; nn++)
{
nxt=uint16_t (Inbuf[nn]);
nxt &=0x00FF; // the casting makes 0xFFFF out of 0xFF !!!!!!!!!
myCrc+=nxt;
//qDebug("CRC: nxt: %d sum: %d", nxt, myCrc);
}
if (myCrc != recCrc)
{
//qDebug() << "crc does not match: mycrc=" << myCrc<< " receivedCRC=" << recCrc;
//qDebug("calculated over %d bytes", crcL_Addr);
return 5; // crc wrong
}
return 0;
}
/*
uint8_t T_prot::FramecheckInData(uint8_t *Inbuf, uint16_t LL)
{
uint16_t rawInLen=LL, crcL_Addr, recCrc, myCrc, nn, datalen, nxt;
if (rawInLen<12)
{
qDebug("prot: got %d bytes only", rawInLen);
return 1; // wrong length
}
if ( Inbuf[0] != '<')
return 2; // wrong start sign
datalen=uint16_t(Inbuf[9]);
if ( datalen > FRAME_DATALEN) //[9]=reported data lenght
return 3; // reported datalen too big
if ((datalen !=(rawInLen-12)) && (datalen !=(rawInLen-13)) && (datalen !=(rawInLen-14)) )
{
// angehängtes CR und/oder LF tolerieren
qDebug() << "wrong data length, " << datalen << " " << rawInLen;
return 4; // data len does not match to complete length
}
crcL_Addr=datalen+10; // weil im definierten protocol 10 bytes vor den Daten stehen
recCrc=0;
recCrc=uchar2uint(uint8_t(Inbuf[crcL_Addr+1]), uint8_t(Inbuf[crcL_Addr]));
myCrc=0;
for (nn=0; nn<crcL_Addr; nn++)
{
nxt=uint16_t (Inbuf[nn]);
nxt &=0x00FF; // the casting makes 0xFFFF out of 0xFF !!!!!!!!!
myCrc+=nxt;
//qDebug("CRC: nxt: %d sum: %d", nxt, myCrc);
}
if (myCrc != recCrc)
{
qDebug() << "crc does not match: mycrc=" << myCrc<< " receivedCRC=" << recCrc;
qDebug("calculated over %d bytes", crcL_Addr);
return 5; // crc wrong
}
return 0;
}
*/
uint8_t T_prot::CheckInResult(uint8_t *Inbuf)
{
char slaveresult;
QString myString=nullptr, tempStr=nullptr;
// slave results anzeigen
slaveresult=Inbuf[2]; // hier steht das "Command Result" des slaves,
// d.h das Ergebnis der Protokol-Prüfung (Master->Slave)
switch (slaveresult)
{
// received message (from master) analysis:
// 0: got valid request
// this errors can only come back from a single device (not bus)
// or from a bus slave in local mode
// 1: wrong start 2: wrong length
// 3: wrong crc 4: wrong addr
case 1: gpi_setTxt4resultStateLine("slave got wrong start sign"); break;
case 2: gpi_setTxt4resultStateLine("slave got wrong length"); break;
case 3: gpi_setTxt4resultStateLine("slave got wrong crc"); break;
case 4: gpi_setTxt4resultStateLine("slave got wrong addr"); break;
case 10: gpi_setTxt4resultStateLine("slave is in local mode"); break;
case 13: gpi_setTxt4resultStateLine("local mode with wrong crc"); break;
case 14: gpi_setTxt4resultStateLine("local mode with wrong addr"); break;
// wenn 1..4 dann konnte der Slave das Mastertelegramm gar nicht verwenden, also hier Stoppen
}
if (slaveresult>0 && slaveresult<10)
return 1;
// Slave hat gültiges Kommando empfangen:
// 2.result auswerten:
// recBuffer[3]; // Write result, d.h. Ergebnis des Schreibvorganges (z.B. DOs) des Slaves
// recBuffer[4]; // Read result, d.h. Ergebnis des Lesevorganges (z.B. DIs) des Slaves
// bisher nicht bekannt welche Fehlercodes es gibt, also den code direkt ausgeben.
// bisher bekannt: 0=OK
myString.clear();
myString = "Slave OUT and IN Result: ";
tempStr.setNum(Inbuf[3],16);
myString.append(tempStr);
myString.append(" ");
tempStr.setNum(Inbuf[4],16);
myString.append(tempStr);
gpi_setTxt4resultStateLine(myString);
return 0;
}
uint8_t T_prot::ShowFastInData(uint8_t *recBuffer)
{
QString myString=nullptr, tempStr=nullptr;
uint8_t result;
RecSlaveAddr=0;
result=recBuffer[1]; // total result
result &=0x60; // only read result (bit 5,6)
if (result==0) // read result =OK,
// dann sind die Eingangsdaten gültig
{
myString.append("valid INdata: ");
INdataValid=true;
//readSource already set with sending
readAddress=0;
// RdDataLength already set with sending
if (RdDataLength>FRAME_DATALEN)
RdDataLength=FRAME_DATALEN;
for (int ii=0; ii<RdDataLength; ii++)
InputData[ii]=uint8_t(recBuffer[ii+HEADERLEN_RECEIVE]);
tempStr.setNum(readSource,16);
myString.append(tempStr);
myString.append(" add:");
tempStr.setNum(readAddress);
myString.append(tempStr);
//myString.append(" wakeSrc:");
//tempStr.setNum(lastWakeSrc);
//myString.append(tempStr);
myString.append(" Dlen:");
tempStr.setNum(RdDataLength);
myString.append(tempStr);
} else
{
myString=" "; // Eingangsdaten nicht gültig, sieht man aber weiter oben schon
}
gpi_setTxt4dataStateLine(myString);
//qDebug() << myString;
//qDebug("prot_checkInData_bindata: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d ",
// InputData[0], InputData[1], InputData[2], InputData[3],
// InputData[4], InputData[5], InputData[6], InputData[7],
// InputData[8], InputData[9], InputData[10], InputData[11],
// InputData[12], InputData[13], InputData[14], InputData[15]);
return 0;
}
/*
uint8_t T_prot::ShowInData(uint8_t *recBuffer)
{
QString myString=nullptr, tempStr=nullptr;
RecSlaveAddr=recBuffer[1];
if (recBuffer[2]==0 && recBuffer[4]==0) // comand result=OK und read result =OK,
// dann sind die Eingangsdaten gültig
{
myString.append("valid INdata: ");
INdataValid=true;
readSource=uchar2uint(recBuffer[6],recBuffer[5]);
readAddress=uchar2uint(recBuffer[8],recBuffer[7]);
//lastWakeSrc=uint8_t(recBuffer[4]);
RdDataLength=uint8_t(recBuffer[9]);
if (RdDataLength>FRAME_DATALEN)
RdDataLength=FRAME_DATALEN;
for (int ii=0; ii<RdDataLength; ii++)
InputData[ii]=uint8_t(recBuffer[ii+10]);
tempStr.setNum(readSource,16);
myString.append(tempStr);
myString.append(" add:");
tempStr.setNum(readAddress);
myString.append(tempStr);
//myString.append(" wakeSrc:");
//tempStr.setNum(lastWakeSrc);
//myString.append(tempStr);
myString.append(" Dlen:");
tempStr.setNum(RdDataLength);
myString.append(tempStr);
} else
{
myString=" "; // Eingangsdaten nicht gültig, sieht man aber weiter oben schon
}
gpi_setTxt4dataStateLine(myString);
//qDebug() << myString;
//qDebug("prot_checkInData_bindata: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d ",
// InputData[0], InputData[1], InputData[2], InputData[3],
// InputData[4], InputData[5], InputData[6], InputData[7],
// InputData[8], InputData[9], InputData[10], InputData[11],
// InputData[12], InputData[13], InputData[14], InputData[15]);
return 0;
}
*/
bool T_prot::ifDataReceived()
{
return INdataValid;
}
bool T_prot::getReceivedInData(uint8_t *SlavAddr, uint16_t *readSrc, uint16_t *readAddr,
uint8_t *RdDlen, uint8_t *receivedData)
{
uint8_t nn;
*SlavAddr=RecSlaveAddr;
*readSrc=readSource; // diese (Eingangs-)Daten stehen im Puffer
*readAddr=readAddress; // von dieser Adr wurden die Daten gelesen
//*lastWakSourc=lastWakeSrc; // falls der Slave den Master geweckt hat
*RdDlen=RdDataLength;
for (nn=0; nn<FRAME_DATALEN; nn++)
receivedData[nn]=0;
for (nn=0; nn<RdDataLength; nn++)
receivedData[nn]=InputData[nn];
return INdataValid; // nur true wenn CommandState OK und readState OK
}

View File

@ -1,704 +0,0 @@
#include <stdint.h>
#include <QString>
#include <QDebug>
#include "tslib.h"
#include "sendWRcmd.h"
void indat_PrnPwr(void);
void sendWRcmd_INI(void)
{
sendWRcmd_clrCmdStack();
sendWRcmd_clrCmd4Stack();
sendFDcmd_clrStack();
longFDcmd_clrStack();
}
// Command Stack for commands without parameters
static uint16_t nextAsynchsendCmd0[CMDSTACKDEPTH];
static uint8_t nrOfCmdsInQueue;
/* convention: use simple (not rotating) FIFO Stack:
Example: nrOfCmdsInQueue=4 then
nextAsynchsendCmd0[0]=cmd1 // was stored as first
nextAsynchsendCmd0[1]=cmd2
nextAsynchsendCmd0[2]=cmd3
nextAsynchsendCmd0[3]=cmd4 // came in as last
Send: [0] first, then move buffer 1 down:
nextAsynchsendCmd0[0]=cmd2
nextAsynchsendCmd0[1]=cmd3
nextAsynchsendCmd0[2]=cmd4
nextAsynchsendCmd0[3]=0;
nrOfCmdsInQueue=3 now
*/
void sendWRcmd_clrCmdStack(void)
{
uint8_t nn;
for (nn=0; nn<CMDSTACKDEPTH; nn++)
nextAsynchsendCmd0[nn]=0;
nrOfCmdsInQueue=0;
}
bool sendWRcmd_setSendCommand0(uint16_t nextCmd)
{
// write Command to memory, wait for transport
if (nrOfCmdsInQueue>=CMDSTACKDEPTH)
{
qDebug() << "cannot save cmd because stack is full";
return false; // not possible
}
nextAsynchsendCmd0[nrOfCmdsInQueue++]=nextCmd;
//qDebug() << "PI cmd queued:"<< nextCmd << ", saved, pp=" << nrOfCmdsInQueue;
return true; // ok, will be sent
}
uint16_t sendWRcmd_getSendCommand0(void)
{
uint16_t nxtAsynchCmd;
uint8_t nn, ll;
if (nrOfCmdsInQueue==0 || nrOfCmdsInQueue>CMDSTACKDEPTH)
return 0; // error
nxtAsynchCmd=nextAsynchsendCmd0[0];
// move Puffer down by one element
if (CMDSTACKDEPTH>0)
ll=CMDSTACKDEPTH-1;
else
ll=0;
for (nn=0; nn<ll; nn++)
nextAsynchsendCmd0[nn]=nextAsynchsendCmd0[nn+1];
if (nrOfCmdsInQueue>0)
nrOfCmdsInQueue--;
//qDebug() << "PI cmd queued:"<< nxtAsynchCmd << ", restored, pp now =" << nrOfCmdsInQueue;
return nxtAsynchCmd;
}
//---------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------
// Command Stack for commands with 4 parameters
static uint16_t nextAsynchsendCmd4[CMD4STACKDEPTH];
static uint8_t nextCmd4para1[CMD4STACKDEPTH];
static uint8_t nextCmd4para2[CMD4STACKDEPTH];
static uint8_t nextCmd4para3[CMD4STACKDEPTH];
static uint8_t nextCmd4para4[CMD4STACKDEPTH];
static uint8_t nrOfCmds4InQueue;
/* convention: use simple (not rotating) FIFO Stack:
Example: nrOfCmdsInQueue=4 then
nextAsynchsendCmd0[0]=cmd1 // was stored as first
nextAsynchsendCmd0[1]=cmd2
nextAsynchsendCmd0[2]=cmd3
nextAsynchsendCmd0[3]=cmd4 // came in as last
Send: [0] first, then move buffer 1 down:
nextAsynchsendCmd0[0]=cmd2
nextAsynchsendCmd0[1]=cmd3
nextAsynchsendCmd0[2]=cmd4
nextAsynchsendCmd0[3]=0;
nrOfCmdsInQueue=3 now
*/
void sendWRcmd_clrCmd4Stack(void)
{
uint8_t nn;
for (nn=0; nn<CMD4STACKDEPTH; nn++)
{
nextAsynchsendCmd4[nn]=0;
nextCmd4para1[nn]=0;
nextCmd4para2[nn]=0;
nextCmd4para3[nn]=0;
nextCmd4para4[nn]=0;
}
nrOfCmds4InQueue=0;
}
bool sendWRcmd_setSendCommand4(uint16_t nextCmd, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4)
{
// write Command to memory, wait for transport
if (nrOfCmds4InQueue>=CMD4STACKDEPTH)
{
qDebug() << "cannot save cmd because stack is full";
return false; // not possible
}
nextAsynchsendCmd4[nrOfCmds4InQueue]=nextCmd;
nextCmd4para1[nrOfCmds4InQueue]=dat1;
nextCmd4para2[nrOfCmds4InQueue]=dat2;
nextCmd4para3[nrOfCmds4InQueue]=dat3;
nextCmd4para4[nrOfCmds4InQueue]=dat4;
//qDebug() << "data with 4 data byte saved, pp=" << nrOfCmds4InQueue;
//qDebug() << " dat1=" << nextCmd4para1[nrOfCmds4InQueue] << " dat2=" << nextCmd4para2[nrOfCmds4InQueue]
// << " dat3=" << nextCmd4para3[nrOfCmds4InQueue] << " dat4=" << nextCmd4para4[nrOfCmds4InQueue];
nrOfCmds4InQueue++;
return true; // ok, will be sent
}
uint16_t sendWRcmd_getSendCommand4(uint8_t *dat1, uint8_t *dat2, uint8_t *dat3, uint8_t *dat4)
{
uint16_t nxtAsynchCmd;
uint8_t nn, ll;
if (nrOfCmds4InQueue==0 || nrOfCmds4InQueue>CMD4STACKDEPTH)
return 0; // error
nxtAsynchCmd=nextAsynchsendCmd4[0];
*dat1=nextCmd4para1[0];
*dat2=nextCmd4para2[0];
*dat3=nextCmd4para3[0];
*dat4=nextCmd4para4[0];
//qDebug() << "cmd4 restored to send from [0]; pp=" << nrOfCmds4InQueue;
//qDebug() << " data1: " << nextCmd4para1[0] << " data2: " << nextCmd4para2[0] <<
// " data3: " << nextCmd4para3[0] << " data4: " << nextCmd4para4[0];
// move Puffer down by one element
if (CMD4STACKDEPTH>0)
ll=CMD4STACKDEPTH-1;
else
ll=0;
for (nn=0; nn<ll; nn++)
{
nextAsynchsendCmd4[nn]=nextAsynchsendCmd4[nn+1];
nextCmd4para1[nn]=nextCmd4para1[nn+1];
nextCmd4para2[nn]=nextCmd4para2[nn+1];
nextCmd4para3[nn]=nextCmd4para3[nn+1];
nextCmd4para4[nn]=nextCmd4para4[nn+1];
}
if (nrOfCmds4InQueue>0)
nrOfCmds4InQueue--;
//qDebug() << "cmd4 after push down: pp=" << nrOfCmds4InQueue;
return nxtAsynchCmd;
}
static uint16_t nextAsynchsendCmd8[CMD8STACKDEPTH];
static uint8_t nextCmd8para1[CMD8STACKDEPTH];
static uint8_t nextCmd8para2[CMD8STACKDEPTH];
static uint16_t nextCmd8para3[CMD8STACKDEPTH];
static uint32_t nextCmd8para4[CMD8STACKDEPTH];
static uint8_t nrOfCmds8InQueue;
void sendWRcmd_clrCmd8Stack(void)
{
uint8_t nn;
for (nn=0; nn<CMD8STACKDEPTH; nn++)
{
nextAsynchsendCmd8[nn]=0;
nextCmd8para1[nn]=0;
nextCmd8para2[nn]=0;
nextCmd8para3[nn]=0;
nextCmd8para4[nn]=0;
}
nrOfCmds8InQueue=0;
}
bool sendWRcmd_setSendCommand8(uint16_t nextCmd, uint8_t dat1, uint8_t dat2, uint16_t dat3, uint32_t dat4)
{
// write Command to memory, wait for transport
if (nrOfCmds8InQueue>=CMD8STACKDEPTH)
{
qDebug() << "cannot save cmd because stack is full";
return false; // not possible
}
nextAsynchsendCmd8[nrOfCmds8InQueue]=nextCmd;
nextCmd8para1[nrOfCmds8InQueue]=dat1;
nextCmd8para2[nrOfCmds8InQueue]=dat2;
nextCmd8para3[nrOfCmds8InQueue]=dat3;
nextCmd8para4[nrOfCmds8InQueue]=dat4;
nrOfCmds8InQueue++;
return true; // ok, will be sent
}
uint16_t sendWRcmd_getSendCommand8(uint8_t *dat1, uint8_t *dat2, uint16_t *dat3, uint32_t *dat4)
{
uint16_t nxtAsynchCmd;
uint8_t nn, ll;
if (nrOfCmds8InQueue==0 || nrOfCmds8InQueue>CMD8STACKDEPTH)
return 0; // error
nxtAsynchCmd=nextAsynchsendCmd8[0];
*dat1=nextCmd8para1[0];
*dat2=nextCmd8para2[0];
*dat3=nextCmd8para3[0];
*dat4=nextCmd8para4[0];
// move buffer down by one element
if (CMD8STACKDEPTH>0)
ll=CMD8STACKDEPTH-1;
else
ll=0;
for (nn=0; nn<ll; nn++)
{
nextAsynchsendCmd8[nn]=nextAsynchsendCmd8[nn+1];
nextCmd8para1[nn]=nextCmd8para1[nn+1];
nextCmd8para2[nn]=nextCmd8para2[nn+1];
nextCmd8para3[nn]=nextCmd8para3[nn+1];
nextCmd8para4[nn]=nextCmd8para4[nn+1];
}
if (nrOfCmds8InQueue>0)
nrOfCmds8InQueue--;
return nxtAsynchCmd;
}
static uint8_t sendAsynchDataBuf[160]; // no stack, only ONE buffer
static uint8_t sendAsyDatLen;
bool sendWRcmd_setSendBlock160(uint8_t leng, uint8_t *buf)
{
//qDebug() << "pi epi: storing send data";
if (leng>160) leng=160;
sendAsyDatLen=leng;
tslib_strclr(sendAsynchDataBuf, 0, 160);
for (uint8_t nn=0; nn<leng; nn++)
sendAsynchDataBuf[nn]=buf[nn];
return true; // ok, will be sent
}
uint8_t sendWRcmd_getSendBlock160(uint8_t *leng, uint8_t *buf)
{
//qDebug() << "pi gpi: restoring send data";
*leng=sendAsyDatLen;
for (uint8_t nn=0; nn<sendAsyDatLen; nn++)
buf[nn]=sendAsynchDataBuf[nn];
sendAsyDatLen=0;
//tslib_strclr(sendAsynchDataBuf, 0, 64);
return *leng;
}
// ------------------------------------------------------------------------------------
// MDB Sendind Data are store here for next transport to DC (Device Controller)
// Transport to Slave runs every 100ms, answer from mdb-slave (e.g. coin changer) comes rigth
// with next slave answer
// start with: SENDDIRCMD_EXCHGMDB,
// send crude data from here to DC, DC to mdb slaves, mdb answer, return here within 50ms
static uint8_t Sdata_mdbSendBuffer[64];
static uint8_t Sdata_mdbSendLen;
uint8_t epi_store64ByteSendData(uint8_t length, uint8_t *buf)
{
// HWapi writes data to be forwarded to DC and further to mdb-device
for (uint8_t nn=0; nn<length; nn++)
Sdata_mdbSendBuffer[nn]=buf[nn];
Sdata_mdbSendLen=length;
return 0;
}
uint8_t gpi_restore64ByteSendData(uint8_t *length, uint8_t *buf)
{
// datif reads data to forward to dc
for (uint8_t nn=0; nn<Sdata_mdbSendLen; nn++)
buf[nn]=Sdata_mdbSendBuffer[nn];
*length=Sdata_mdbSendLen;
Sdata_mdbSendLen=0;
return 0;
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//---------------------------------------- Printer Text Fifo -------------------------
static uint8_t prnDataParameters[4];
static uint8_t prnDataBufferUser;
void epi_storeUserOfSendingTextBuffer(uint8_t user, uint8_t para1, uint8_t para2, uint8_t para3, uint8_t para4 )
{
// user=1: Text-Print is using this buffer
// 2: QR-code-Printer is using this buffer
prnDataBufferUser=user;
prnDataParameters[0]=para1;
prnDataParameters[1]=para2;
prnDataParameters[2]=para3;
prnDataParameters[3]=para4;
// qDebug() << "new user stored: " << user;
}
uint8_t gpi_getUserOfSendingTextBuffer(uint8_t *para1, uint8_t *para2, uint8_t *para3, uint8_t *para4)
{
// user=1: Text-Print is using this buffer
// 2: QR-code-Printer is using this buffer
//qDebug() << "returning user "<< prnDataBufferUser;
*para1=prnDataParameters[0];
*para2=prnDataParameters[1];
*para3=prnDataParameters[2];
*para4=prnDataParameters[3];
return prnDataBufferUser;
}
// Sending Text Fifo
// ONE printer doc consists of 20 x 64 byte
// #define MAXNROF_PRNBYTES 64
// #define MAXNROF_PRNBLOCKS 20
static char Sdata_PRN_TEXT[MAXNROF_PRNBLOCKS][MAXNROF_PRNBYTES];
static uint8_t pPrnDataBuff; // points to next PRINTER_BLOCK
//static uint8_t pPrnDataBuff; // points to next waiting printer text
// defined above, needed if more then one text is stored (before sent)
// every block will be sent after 100ms, if 8 blocks are stored within this 100ms
// then pointer goes up to 8. Important: FIFO!!!!!!!!
void epi_resetPrinterStack(void)
{
pPrnDataBuff=0;
}
uint8_t epi_storePrnText(char *buf, uint8_t leng)
{
// store text from Gui in next higher free memory 0....9
uint16_t len;
uint8_t pp, nn;
pp=pPrnDataBuff; // next free memory block with 64byte each
if (pp>=MAXNROF_PRNBLOCKS)
return 1; // not possible, no free mem
//len=tslib_strlen(buf); // kennt keine Binärzeichen!!!!!!
len=leng;
if (len>MAXNROF_PRNBYTES)
len=MAXNROF_PRNBYTES;
tslib_strclr(Sdata_PRN_TEXT[pp], 0, MAXNROF_PRNBYTES);
for (nn=0; nn<len; nn++)
Sdata_PRN_TEXT[pp][nn]=buf[nn]; // copy new text into buffer
if (pPrnDataBuff<MAXNROF_PRNBLOCKS)
pPrnDataBuff++; // inc pointer if end not yet reached
return 0; // OK
}
uint8_t gpi_restorePrnText(uint8_t *retbuf)
{
// read printer text and send to slave, size of retbuf == 64
// always read from [0] because this is the oldest (Fifo)
// then move all text lines down by one and dec pointer
uint8_t nn, pp=pPrnDataBuff;
if (pp==0) // next free memory block with 64byte each
return 1; // no text in buffer
// example: pp=5: then buffers [0...4] are occupied
for (nn=0; nn<MAXNROF_PRNBYTES; nn++)
retbuf[nn] = uint8_t (Sdata_PRN_TEXT[0][nn]); // restore oldest text
// now copy textline [1] to [0], then
// copy textline [2] to [1], then
// copy textline [3] to [2] .... upto [pp-1] to [pp-2]
// hint: copying from 9....0 would delete all strings!!!!!!
for (nn=0; nn<(pp-1); nn++)
tslib_strcpy(Sdata_PRN_TEXT[nn+1], Sdata_PRN_TEXT[nn], MAXNROF_PRNBYTES);
if (pPrnDataBuff>0)
pPrnDataBuff--;
pp=pPrnDataBuff;
// example: pp=4: then buffers [0...3] are still occupied, pp=0: all buffers empty
// now clear highest copyed line (which got free now)
tslib_strclr(Sdata_PRN_TEXT[pp], 0, MAXNROF_PRNBYTES);
// optionally: clear all remaining higher lines:
for (nn=(pp+1); nn<MAXNROF_PRNBLOCKS; nn++)
tslib_strclr(Sdata_PRN_TEXT[nn], 0, MAXNROF_PRNBYTES);
return 0;
}
uint8_t gpi_chk4remainingText(void)
{
// retval: 0: no more textline left (to send) >0: nr of 64byte-blocks
return (pPrnDataBuff);
}
// ---------------------------------------------------------------------------------
// 11.4.23 neu, Kommando direkt an "FastDevice"-protokoll senden, nicht mehr umsetzen
// ---------------------------------------------------------------------------------
// short command, 4 data bytes
static uint8_t nextFDwrCmd[FDCMD_STACKDEPTH];
static uint8_t nextFDrdCmd[FDCMD_STACKDEPTH];
static uint8_t nextFDblkNr[FDCMD_STACKDEPTH];
static uint8_t nextFDpara1[FDCMD_STACKDEPTH];
static uint8_t nextFDpara2[FDCMD_STACKDEPTH];
static uint8_t nextFDpara3[FDCMD_STACKDEPTH];
static uint8_t nextFDpara4[FDCMD_STACKDEPTH];
static uint8_t p_nextFDcmdsInQueue;
/* convention: use simple (not rotating) FIFO Stack:
Example: nrOfCmdsInQueue=4 then
nextAsynchsendCmd0[0]=cmd1 // was stored as first
nextAsynchsendCmd0[1]=cmd2
nextAsynchsendCmd0[2]=cmd3
nextAsynchsendCmd0[3]=cmd4 // came in as last
Send: [0] first, then move buffer 1 down:
nextAsynchsendCmd0[0]=cmd2
nextAsynchsendCmd0[1]=cmd3
nextAsynchsendCmd0[2]=cmd4
nextAsynchsendCmd0[3]=0;
nrOfCmdsInQueue=3 now
*/
void sendFDcmd_clrStack(void)
{
uint8_t nn;
for (nn=0; nn<FDCMD_STACKDEPTH; nn++)
{
nextFDwrCmd[nn]=0;
nextFDrdCmd[nn]=0;
nextFDblkNr[nn]=0;
nextFDpara1[nn]=0;
nextFDpara2[nn]=0;
nextFDpara3[nn]=0;
nextFDpara4[nn]=0;
}
p_nextFDcmdsInQueue=0;
}
bool sendFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4)
{
// write Command to memory, wait for transport
if (p_nextFDcmdsInQueue>=FDCMD_STACKDEPTH)
{
qDebug() << "cannot save cmd because stack is full";
return false; // not possible
}
nextFDwrCmd[p_nextFDcmdsInQueue]=nextWrCmd;
nextFDrdCmd[p_nextFDcmdsInQueue]=nextRdCmd;
nextFDblkNr[p_nextFDcmdsInQueue]=blockNum;
nextFDpara1[p_nextFDcmdsInQueue]=dat1;
nextFDpara2[p_nextFDcmdsInQueue]=dat2;
nextFDpara3[p_nextFDcmdsInQueue]=dat3;
nextFDpara4[p_nextFDcmdsInQueue]=dat4;
//qDebug() << "data with 4 data byte saved, pp=" << nrOfCmds4InQueue;
//qDebug() << " dat1=" << nextCmd4para1[nrOfCmds4InQueue] << " dat2=" << nextCmd4para2[nrOfCmds4InQueue]
// << " dat3=" << nextCmd4para3[nrOfCmds4InQueue] << " dat4=" << nextCmd4para4[nrOfCmds4InQueue];
p_nextFDcmdsInQueue++;
return true; // ok, will be sent
}
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 nn, ll;
if (p_nextFDcmdsInQueue==0 || p_nextFDcmdsInQueue>FDCMD_STACKDEPTH)
return false; // not possible
*nextWrCmd=nextFDwrCmd[0];
*nextRdCmd=nextFDrdCmd[0];
*blockNum=nextFDblkNr[0];
*dat1=nextFDpara1[0];
*dat2=nextFDpara2[0];
*dat3=nextFDpara3[0];
*dat4=nextFDpara4[0];
//qDebug() << "cmd4 restored to send from [0]; pp=" << nrOfCmds4InQueue;
//qDebug() << " data1: " << nextCmd4para1[0] << " data2: " << nextCmd4para2[0] <<
// " data3: " << nextCmd4para3[0] << " data4: " << nextCmd4para4[0];
// move Puffer down by one element
if (FDCMD_STACKDEPTH>0)
ll=FDCMD_STACKDEPTH-1;
else
ll=0;
for (nn=0; nn<ll; nn++)
{
nextFDwrCmd[nn]=nextFDwrCmd[nn+1];
nextFDrdCmd[nn]=nextFDrdCmd[nn+1];
nextFDblkNr[nn]=nextFDblkNr[nn+1];
nextFDpara1[nn]=nextFDpara1[nn+1];
nextFDpara2[nn]=nextFDpara2[nn+1];
nextFDpara3[nn]=nextFDpara3[nn+1];
nextFDpara4[nn]=nextFDpara4[nn+1];
}
if (p_nextFDcmdsInQueue>0)
p_nextFDcmdsInQueue--;
//qDebug() << "cmd4 after push down: pp=" << nrOfCmds4InQueue;
return true; // ok, will be sent
}
uint8_t check4FDshortCmd(void)
{
// returns number of waiting command, max FDCMD_STACKDEPTH
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
static uint8_t longFDwrCmd[FDLONG_STACKDEPTH];
static uint8_t longFDrdCmd[FDLONG_STACKDEPTH];
static uint8_t longFDblkNr[FDLONG_STACKDEPTH];
static uint8_t longFDlength[FDLONG_STACKDEPTH];
static uint8_t longFDpara[FDLONG_STACKDEPTH][64];
static uint8_t p_longFDcmdsInQueue;
void longFDcmd_clrStack(void)
{
uint8_t nn, mm;
for (nn=0; nn<FDLONG_STACKDEPTH; nn++)
{
longFDwrCmd[nn]=0;
longFDrdCmd[nn]=0;
longFDblkNr[nn]=0;
longFDlength[nn]=0;
for (mm=0; mm<64; mm++)
longFDpara[nn][mm]=0;
}
p_longFDcmdsInQueue=0;
}
bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t length, uint8_t *data)
{
// write Command to memory, wait for transport
// data buffer size always 64! data[64], padded with 0
uint8_t nn;
if (p_longFDcmdsInQueue>=FDLONG_STACKDEPTH)
{
qDebug() << "cannot save cmd because stack is full";
return false; // not possible
}
longFDwrCmd[p_longFDcmdsInQueue]=nextWrCmd;
longFDrdCmd[p_longFDcmdsInQueue]=nextRdCmd;
longFDblkNr[p_longFDcmdsInQueue]=blockNum;
longFDlength[p_longFDcmdsInQueue]=length;
for (nn=0; nn<64; nn++)
longFDpara[p_longFDcmdsInQueue][nn]=data[nn];
p_longFDcmdsInQueue++;
return true; // ok, will be sent
}
bool longFDcmd_get(uint8_t *nextWrCmd, uint8_t *nextRdCmd, uint8_t *blockNum, uint8_t *length, uint8_t *data)
{
uint8_t nn, mm, ll;
if (p_longFDcmdsInQueue==0 || p_longFDcmdsInQueue>FDLONG_STACKDEPTH)
return false; // not possible
*nextWrCmd= longFDwrCmd[0];
*nextRdCmd= longFDrdCmd[0];
*blockNum = longFDblkNr[0];
*length = longFDlength[0];
for (mm=0; mm<64; mm++)
data[mm] = longFDpara[0][mm];
// move Puffer down by one element
if (FDLONG_STACKDEPTH>0)
ll=FDLONG_STACKDEPTH-1;
else
ll=0;
for (nn=0; nn<ll; nn++)
{
longFDwrCmd[nn] = longFDwrCmd[nn+1];
longFDrdCmd[nn] = longFDrdCmd[nn+1];
longFDblkNr[nn] = longFDblkNr[nn+1];
longFDlength[nn] = longFDlength[nn+1];
for (mm=0; mm<64; mm++)
longFDpara[nn][mm] = longFDpara[nn+1][mm];
}
if (p_longFDcmdsInQueue>0)
p_longFDcmdsInQueue--;
return true; // ok, will be sent
}
uint8_t check4FDlongCmd(void)
{
// returns number of waiting command
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

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

@ -1,598 +0,0 @@
#include "tslib.h"
#include <QThread>
//tslib::tslib()
//{
//}
/*
uint16_t tslib::uchar2uint(uint8_t Highbyte, uint8_t Lowbyte)
{
uint16_t uitmp;
uitmp=0;
uitmp |= uint8_t(Highbyte);
uitmp<<=8;
uitmp |= uint8_t(Lowbyte);
return uitmp;
}
uint8_t tslib::uint2uchar(uint16_t uival, bool getHighB)
{
// getHighB: low=GetLowByte
uint16_t uitmp=uival;
if (getHighB==0)
return uint8_t(uitmp);
uitmp>>=8;
return uint8_t(uitmp);
}*/
uint16_t uchar2uint(char Highbyte, char Lowbyte)
{
uint16_t uitmp;
uitmp=0;
uitmp |= uint8_t(Highbyte);
uitmp<<=8;
uitmp |= uint8_t(Lowbyte);
return uitmp;
}
uint16_t uchar2uint(uint8_t Highbyte, uint8_t Lowbyte)
{
uint16_t uitmp;
uitmp=0;
uitmp |= uint8_t(Highbyte);
uitmp<<=8;
uitmp |= uint8_t(Lowbyte);
return uitmp;
}
uint32_t uchar2ulong(uint8_t Highbyte, uint8_t MHbyte, uint8_t MLbyte, uint8_t Lowbyte)
{
uint32_t ultmp=0;
ultmp |= uint8_t(Highbyte);
ultmp<<=8;
ultmp |= uint8_t(MHbyte);
ultmp<<=8;
ultmp |= uint8_t(MLbyte);
ultmp<<=8;
ultmp |= uint8_t(Lowbyte);
return ultmp;
}
uint8_t uint2uchar(uint16_t uival, bool getHighB)
{
// getHighB: low=GetLowByte
uint16_t uitmp=uival;
if (getHighB==0)
return uint8_t(uitmp);
uitmp>>=8;
return uint8_t(uitmp);
}
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)
{
QThread::msleep(uint32_t(MilliSec));
}
void GetTimeString(uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t System12h, uint8_t ShowSec, uint8_t *buf)
{
// Zahlenwerte in String wandeln, 12/24h-Format // 12byte für buf!
uint8_t usa;
uint16_t jj;
uint8_t hh, mm, ss, with_sec;
// buf[0]= ganz linkes Zeichen
hh=hours;
mm=minutes;
ss=seconds;
// 15.10.12, Plausibilitätsprüfung --------------------------------------------------
if (hh>23) hh=0;
if (mm>59) mm=0;
if (ss>59) ss=0;
with_sec=ShowSec;
for (jj=0; jj<12; jj++) buf[jj]=0;
usa = System12h; // 1:12h 0:24h
// Stunden:
if (usa)
{
// 12h System
if (hh==0 || hh==12)
{
// 12AM (Mitternacht) oder 12PM (Mittag)
buf[0]=0x31;
buf[1]=0x32;
} else
if (hh<12)
{
// 1..11AM
buf[0]=hh/10+0x30;
buf[1]=hh%10+0x30;
} else
{
//13:00 bis 23Uhr
buf[0]=(hh-12)/10+0x30;
buf[1]=(hh-12)%10+0x30;
}
} else
{
// 24h System
buf[0]=hh/10+0x30;
buf[1]=hh%10+0x30;
}
// Minuten:
buf[2]=':';
buf[3]=mm/10+0x30;
buf[4]=mm%10+0x30;
jj=5;
if (with_sec)
{
buf[jj++]=':';
buf[jj++]=ss/10+0x30;
buf[jj++]=ss%10+0x30;
}
if (usa)
{
buf[jj++]=' ';
if (hh<12)
buf[jj++]='A';
else
buf[jj++]='P';
buf[jj++]='M';
}
}
// ------------------- ********************************************************************************
void GetDateString(uint8_t day, uint8_t month, uint8_t yearhigh, uint8_t yearlow, uint8_t format, uint8_t sep, uint8_t *buf)
{
// generate date as ascii string from integers day/month/year
// yearhigh: 10..29, in europe always 20 (not in arabia!) comes as hex number, e.g. 0x20
// format= 0: dd.mm.yyyy (deutsch)
// 1: mm.dd.yyyy (amerika)
// 2: yyyy.mm.dd (Iran, Dubai)
// 3: dd.yyyy.mm
// 4: mm.yyyy.dd
// 5: yyyy.dd.mm
// sep: 0: use . as seperator 1: use / as seperator
// return String in *buf // 11byte für buf!
uint8_t tag, mon, jahr, d10, d1, m10, m1, y1000, y100, y10, y1;
uint8_t slash;
y100= (yearhigh & 0x0F)+0x30;
y1000=((yearhigh & 0xF0)>>4)+0x30;
// if (yearhigh>=20)
// {
// y1000='2';
// y100=28+yearhigh; // '0' + (yearhigh-20)
// } else
// if (yearhigh<20)
// {
// y1000='1';
// y100=38-yearhigh; // '9' - (19-yearhigh)
// }
tag=day;
mon=month;
jahr=yearlow;
if (mon>12 || mon==0) mon=1; // 23.10.12
if (tag>31 || tag==0) tag=1;
if (jahr>50 || jahr<11) jahr=1;
if (sep==0)
slash='.'; // slash==0
else if (sep==1)
slash='/';
else
if (sep>=0x20)
slash=sep;
else
slash='.';
d10 =tag/10;
d1 =tag%10;
m10 =mon/10;
m1 =mon%10;
y10 =jahr/10;
y1 =jahr%10;
d10 +=0x30; // in Asccii wandeln
d1 +=0x30;
m10 +=0x30;
m1 +=0x30;
y10 +=0x30;
y1 +=0x30;
switch (format)
{
// 0: dd.mm.yyyy
case 0: buf[0]=d10; buf[1]=d1; buf[2]=slash; buf[3]=m10; buf[4]=m1; buf[5]=slash;
buf[6]=y1000; buf[7]=y100; buf[8]=y10; buf[9]=y1; break;
// 1: mm.dd.yyyy
case 1: buf[0]=m10; buf[1]=m1; buf[2]=slash; buf[3]=d10; buf[4]=d1; buf[5]=slash;
buf[6]=y1000; buf[7]=y100; buf[8]=y10; buf[9]=y1; break;
// 2: yyyy.mm.dd
case 2: buf[0]=y1000; buf[1]=y100; buf[2]=y10; buf[3]=y1; buf[4]=slash; buf[5]=m10;
buf[6]=m1; buf[7]=slash; buf[8]=d10; buf[9]=d1; break;
// 3: dd.yyyy.mm
case 3: buf[0]=d10; buf[1]=d1; buf[2]=slash; buf[3]=y1000; buf[4]=y100;
buf[5]=y10; buf[6]=y1; buf[7]=slash; buf[8]=m10; buf[9]=m1; break;
// 4: mm.yyyy.dd
case 4: buf[0]=m10; buf[1]=m1; buf[2]=slash; buf[3]=y1000; buf[4]=y100;
buf[5]=y10; buf[6]=y1; buf[7]=slash; buf[8]=d10; buf[9]=d1; break;
// 5: yyyy.dd.mm
case 5: buf[0]=y1000; buf[1]=y100; buf[2]=y10; buf[3]=y1; buf[4]=slash; buf[5]=d10;
buf[6]=d1; buf[7]=slash; buf[8]=m10; buf[9]=m1; break;
}
buf[10]=0;
}
// ------------------- ********************************************************************************
void GetShortDateString(uint8_t day, uint8_t month, uint8_t yearlow, uint8_t format, uint8_t sep, uint8_t *buf)
{
// generate date as ascii string from integers day/month/year
// format= 0: dd.mm.yy (deutsch)
// 1: mm.dd.yy (amerika)
// 2: yy.mm.dd (Iran, Dubai)
// 3: dd.yy.mm
// 4: mm.yy.dd
// 5: yy.dd.mm
// sep: 0: use . as seperator 1: use / as seperator
// return String in *buf // 11byte für buf!
uint8_t tag, mon, jahr, d10, d1, m10, m1, y10, y1;
uint8_t slash;
tag=day;
mon=month;
jahr=yearlow;
if (mon>12 || mon==0) mon=1; // 23.10.12
if (tag>31 || tag==0) tag=1;
if (jahr>50 || jahr<11) jahr=1;
if (sep==0)
slash='.'; // slash==0
else if (sep==1)
slash='/';
else if (sep>=0x20)
slash=sep;
else
slash='.';
d10 =tag/10;
d1 =tag%10;
m10 =mon/10;
m1 =mon%10;
y10 =jahr/10;
y1 =jahr%10;
d10 +=0x30; // in Asccii wandeln
d1 +=0x30;
m10 +=0x30;
m1 +=0x30;
y10 +=0x30;
y1 +=0x30;
switch (format)
{
// 0: dd.mm.yyyy
case 0: buf[0]=d10; buf[1]=d1; buf[2]=slash; buf[3]=m10; buf[4]=m1; buf[5]=slash;
buf[6]=y10; buf[7]=y1; break;
// 1: mm.dd.yyyy
case 1: buf[0]=m10; buf[1]=m1; buf[2]=slash; buf[3]=d10; buf[4]=d1; buf[5]=slash;
buf[6]=y10; buf[7]=y1; break;
// 2: yyyy.mm.dd
case 2: buf[0]=y10; buf[1]=y1; buf[2]=slash; buf[3]=m10;
buf[4]=m1; buf[5]=slash; buf[6]=d10; buf[7]=d1; break;
// 3: dd.yyyy.mm
case 3: buf[0]=d10; buf[1]=d1; buf[2]=slash;
buf[3]=y10; buf[4]=y1; buf[5]=slash; buf[6]=m10; buf[7]=m1; break;
// 4: mm.yyyy.dd
case 4: buf[0]=m10; buf[1]=m1; buf[2]=slash;
buf[3]=y10; buf[4]=y1; buf[5]=slash; buf[6]=d10; buf[7]=d1; break;
// 5: yyyy.dd.mm
case 5: buf[0]=y10; buf[1]=y1; buf[2]=slash; buf[3]=d10;
buf[4]=d1; buf[5]=slash; buf[6]=m10; buf[7]=m1; break;
}
buf[8]=0;
}
uint16_t tslib_strlen(char *buf)
{
uint16_t nn;
for (nn=0; nn<0xFFF0; nn++)
if (buf[nn]==0)
return nn;
return 0;
}
uint16_t tslib_strlen(uint8_t *buf)
{
uint16_t nn;
for (nn=0; nn<0xFFF0; nn++)
if (buf[nn]==0)
return nn;
return 0;
}
void tslib_strclr(char *buf, char clrsign, uint16_t len)
{
uint16_t nn;
for (nn=0; nn<len; nn++)
buf[nn]=clrsign;
}
void tslib_strclr(uint8_t *buf, char clrsign, uint16_t len)
{
uint16_t nn;
for (nn=0; nn<len; nn++)
buf[nn]=uint8_t (clrsign);
}
void tslib_strcpy(char *srcbuf, char *destbuf, uint16_t len)
{
uint16_t nn;
for (nn=0; nn<len; nn++)
destbuf[nn]=srcbuf[nn];
}
void tslib_strcpy(char *srcbuf, uint8_t *destbuf, uint16_t len)
{
uint16_t nn;
for (nn=0; nn<len; nn++)
destbuf[nn]=uint8_t(srcbuf[nn]);
}
void tslib_strcpy(uint8_t *srcbuf, uint8_t *destbuf, uint16_t len)
{
uint16_t nn;
for (nn=0; nn<len; nn++)
destbuf[nn]=srcbuf[nn];
}
bool tslib_isDecAsciiNumber(char sign)
{
if (sign>=0x30 && sign<=0x39)
return true;
return false;
}
bool tslib_isHexAsciiNumber(char sign)
{
if (sign>=0x30 && sign<=0x39)
return true;
if (sign>=0x61 && sign<=0x66) // a...f
return true;
if (sign>=0x41 && sign<=0x46) // A...F
return true;
return false;
}
int tslib_getMinimum(int val1, int val2)
{
if (val1<val2)
return val1;
return val2;
}
void tslib_text2array(QByteArray text, char *aray, uint16_t maxArayLen)
{
QByteArray sloc;
int ii, LL=text.length();
if (LL>maxArayLen) LL=maxArayLen;
for (ii=0; ii<LL; ii++)
{
aray[ii]=text.at(ii);
}
if (LL==maxArayLen)
aray[LL-1]=0;
else
aray[LL]=0;
}
// -----------------------------------------------------------------------------------------------
// functions for DeviceController's Bootloader ---------------------------------------------------
// -----------------------------------------------------------------------------------------------
/*
uint16_t tslib_calcCrcCcitt(uint16_t BufLength, uint8_t *buf)
{
uint8_t nn, B15H, element;
uint16_t crc = 0x84cf;
while (BufLength--)
{
element = *buf++;
for (nn = 0; nn < 8; nn++)
{
B15H = 0;
if(crc & 0x8000)
B15H = 1;
crc = (crc << 1) | ((element >> (7 - nn)) & 0x01);
if (B15H)
{
crc ^= 0x1021;
}
}
}
for (nn = 0; nn < 16; nn++)
{
B15H = 0;
if(crc & 0x8000)
B15H = 1;
crc = (crc << 1) | 0x00;
if (B15H)
{
crc ^= 0x1021;
}
}
return crc;
}
static uint8_t LastBLcmd; // stored the last sent cmd in order to analys response
// cmd echo'ed: error cmd or'ed with 0x80: OK
uint8_t tslib_prepareDC_BLcmd(uint8_t Cmd, uint8_t SendDataLength, uint8_t *sendData, uint8_t *outBuf)
{
// make BL protocol, retval = outbuf length (5...133)
// bring data in correct form: start always with 0x02 finish with 0x03 and append checksum
// 0x02 Cmd < ...sendData ..> CRC CRC 0x03
// Data length = 0...64
// special conversion: if data contain 2 or 3 (STX, ETX) then write two bytes: 0x1B (=ESC) and data|0x80
// so maxlength = 5 + 2 x 64 (if all data are 2 or 3) without 2,3: maxlength = 5 + 64
uint8_t myBuf[140], pp=0, nn, uctmp, currLen=0;
uint16_t calcCrc;
tslib_strclr(myBuf, 0, 140);
myBuf[pp++]=2; // STX
myBuf[pp++]=Cmd;
LastBLcmd=Cmd;
// append data:
for (nn=0; nn<SendDataLength; nn++)
{
uctmp=sendData[nn];
if (uctmp==2 || uctmp==3) // STX or ETX in normal data!
{
myBuf[pp++]=0x1B; // ESC
myBuf[pp++]=uctmp | 0x80;
} else
myBuf[pp++]=uctmp;
}
currLen=pp;
// calc crc: (over cmd and data, without STX)
calcCrc=tslib_calcCrcCcitt(uint16_t(currLen), myBuf);
myBuf[pp++]=uint8_t(calcCrc & 0x00FF);
myBuf[pp++]=uint8_t((calcCrc>>8) & 0x00FF);
myBuf[pp++]=3;
currLen=pp;
return currLen;
}
// some special commands (right out of bootloader manual)
uint8_t tslib_readBLversion(uint8_t *sendData)
{
// minimum size of sendData-buffer: 5byte retval: length
uint8_t myBuf[2];
tslib_strclr(myBuf, 0, 2);
return tslib_prepareDC_BLcmd(0x11, 0, myBuf, sendData);
}
uint8_t tslib_readFWversion(uint8_t *sendData)
{
// minimum size of sendData-buffer: 5byte retval: length
uint8_t myBuf[2];
tslib_strclr(myBuf, 0, 2);
return tslib_prepareDC_BLcmd(0x12, 0, myBuf, sendData);
}
uint8_t tslib_exitBL(uint8_t *sendData)
{
// minimum size of sendData-buffer: 5byte retval: length
uint8_t myBuf[2];
tslib_strclr(myBuf, 0, 2);
return tslib_prepareDC_BLcmd(0x18, 0, myBuf, sendData);
}
uint8_t tslib_sendFlashStartAddr2BL(uint32_t startAddr, uint8_t *sendData)
{
// minimum size of sendData-buffer: 13byte retval: length (9...13)
uint8_t myBuf[2];
tslib_strclr(myBuf, 0, 2);
return tslib_prepareDC_BLcmd(0x11, 0, myBuf, sendData);
}
*/
// -----------------------------------------------------------------------------------------------
void biox_CopyBlock(uint8_t *src, uint16_t srcPos, uint8_t *dest, uint16_t destPos, uint16_t len)
{
// both buffers starting from pos 0
uint16_t xx,yy,zz,ii;
xx = srcPos;
yy = destPos;
zz = len;
for (ii = 0; ii < zz; ++ii)
{
dest[yy + ii] = src[xx + ii];
}
}

View File

@ -0,0 +1,111 @@
QT += core gui
QT += widgets serialport network
TARGET = ATBDownloadDCFirmware
VERSION="0.1.0"
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}"
!contains(CONFIG, INCLUDEINTERFACES) {
INCLUDEINTERFACES=/opt/ptu5/opt/DCLibraries/include
}
INCLUDEPATH += \
plugins \
$${INCLUDEINTERFACES} \
$${_PRO_FILE_PWD_}/../UpdatePTUDevCtrl \
$${_PRO_FILE_PWD_}/../common/include
CONFIG += c++17
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
# keep comments, as /* fall through */
QMAKE_CXXFLAGS += -C
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -Wno-deprecated-copy -O
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -O2 -std=c++17 # for GCC >= 4.7
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
PTU5BASEPATH = /opt/devel/ptu5
INCLUDEPATH += $$PTU5BASEPATH/qt/libs/devicecontroller/include
LIBS += -L$$PTU5BASEPATH/qt/libs/devicecontroller/library
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 \
mainwindow.cpp \
../common/src/message_handler.cpp \
../UpdatePTUDevCtrl/commandline_parser.cpp \
update.cpp \
dc_download.cpp \
../common/src/System.cpp
HEADERS += \
mainwindow.h \
../common/include/message_handler.h \
../UpdatePTUDevCtrl/commandline_parser.h \
update.h \
dc_download.h \
../common/include/System.h
OTHER_FILES += \
ATBDownloadDCFirmware.ini \
../ATBUpdateTool.ini
FORMS += \
mainwindow.ui
##########################################################################################
# for running program on target through QtCreator
contains( CONFIG, PTU5 ) {
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/app/tools/atbupdate/
!isEmpty(target.path): INSTALLS += target
}

View File

View File

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

View File

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

135
DownloadDCFirmware/main.cpp Normal file
View File

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

View File

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

View File

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

View File

@ -25,25 +25,11 @@
<x>10</x>
<y>10</y>
<width>781</width>
<height>461</height>
<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">
<item row="0" column="0" rowspan="3" colspan="2">
<widget class="QTextEdit" name="updateStatus">
<property name="enabled">
<bool>true</bool>
@ -52,9 +38,19 @@
<font>
<family>Misc Fixed</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>

View File

View File

View File

View File

View File

@ -0,0 +1,438 @@
#include "update.h"
#include <QCoreApplication>
#include <QFile>
#include <QTemporaryFile>
#include <QDebug>
#include <QTextStream>
#include <QRegularExpression>
#include <QRegExp>
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
#include "unistd.h"
#endif
#include <DeviceController/interfaces.h>
#include <QSharedMemory>
#include <QScopedPointer>
#include <QDir>
#include <QThread>
#include <QDateTime>
#include <QPluginLoader>
#include <QMap>
#define UPDATE_OPKG (1)
#define UPDATE_DC (0)
static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
{"57600" , 4}, {"115200" , 5}
};
QPluginLoader Update::pluginLoader;
hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
hwinf *hw = nullptr;
if (plugInDir.exists()) {
QString pluginLibName(fname);
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
QFileInfo info(pluginLibName);
if (info.exists()) {
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
pluginLoader.setFileName(pluginLibName);
// static QPluginLoader pluginLoader(pluginLibName);
if (!pluginLoader.load()) {
qCritical() << "in directory" << plugInDir.absolutePath();
qCritical() << "cannot load plugin" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString();
return nullptr;
}
qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString();
return nullptr;
}
QObject *plugin = pluginLoader.instance();
if (!plugin) {
qCritical() << "cannot start instance";
return nullptr;
}
if (! (hw = qobject_cast<hwinf *>(plugin))) {
qCritical() << "cannot cast plugin" << plugin << "to hwinf";
return nullptr;
}
} else {
qCritical() << pluginLibName << "does not exist";
return nullptr;
}
} else {
qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist";
return nullptr;
}
return hw;
}
bool Update::unloadDCPlugin() {
if (pluginLoader.unload()) {
qCritical() << "unloaded plugin" << pluginLoader.fileName();
// Note: will re-instantiate the library !
// QObject *rootObject = pluginLoader.instance();
// if (rootObject) {
// qCritical() << "reloaded plugin: root object again available";
// return false;
// }
// qCritical()unloaded plugin: root object gone";
return true;
}
return false;
}
class hwapi;
Update::Update(QString customerRepository,
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
bool dryRun,
QObject *parent,
char const *serialInterface,
char const *baudrate)
: QObject(parent)
, m_hw(loadDCPlugin(QDir(plugInDir), pluginName))
, m_serialInterface(serialInterface)
, m_baudrate(baudrate)
, m_customerRepository(customerRepository)
, m_customerNrStr(customerNrStr)
, m_branchName(branchName)
, m_pluginName(pluginName)
, m_workingDir(workingDir)
, m_dryRun(dryRun)
, m_sys_areDCdataValid(false) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin loaded ???";
} else {
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "ERROR!!! DC DATA NOT VALID -> CA-MASTER-PLUGIN NOT CONNECTED";
break;
}
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_sys_areDCDataValid ..."
<< m_sys_areDCdataValid;
}
}
Update::~Update() {
unloadDCPlugin();
}
bool Update::doUpdate(QStringList const &filesToWorkOn, bool usbStickDetected) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return false;
}
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED";
return false;
}
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")";
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
bool res = false;
QList<QString>::const_iterator it;
for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) {
QString const &fToWorkOn = usbStickDetected ? QDir::cleanPath(it->trimmed())
: QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
int i = fToWorkOn.indexOf("DC2C_print", Qt::CaseInsensitive);
int const templateIdx = fToWorkOn.mid(i).midRef(10, 2).toInt();
if ((templateIdx < 1) || (templateIdx > 32)) {
qCritical() << "WRONG TEMPLATE INDEX" << templateIdx;
res = false;
} else {
if ((res = updatePrinterTemplate(templateIdx, fToWorkOn))) {
qCritical() <<
QString("DOWNLOADED PRINTER TEMPLATE %1 WITH INDEX=%2")
.arg(fToWorkOn)
.arg(templateIdx);
}
}
} else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateCashConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn);
}
} else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateConfig(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn);
}
} else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateDeviceConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn);
}
} else {
qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn;
res = false;
}
}
return res;
}
bool Update::checkJsonVersions(QStringList const& jsonFileNames) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return false;
}
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED";
return false;
}
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")";
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
uint8_t jsonNr = 0;
QString const &fName = jsonFileNames[i];
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 6=printer template 1 ..... 36= template 32
if (fName.endsWith("conf.json")) {
jsonNr = 1;
} else
if (fName.endsWith("device.json")) {
jsonNr = 2;
} else
if (fName.endsWith("cash.json")) {
jsonNr = 3;
} else {
QRegularExpressionMatch match;
static const QRegularExpression re("^(.*print)([0-3][0-9])\\.json\\s*$");
int idx = fName.indexOf(re, 0, &match);
if (idx != -1) {
QString captured = match.captured(match.lastCapturedIndex());
bool ok = false;
int n = captured.toInt(&ok);
if (ok) {
// note: use 5 (instead of 4 -> index has been shifted)
jsonNr = n + 5;
}
}
}
if (jsonNr != 0) {
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
m_hw->sys_requestJsonVersions(jsonNr);
QThread::msleep(500);
char buf[64];
memset(buf, 0x00, sizeof(buf));
m_hw->sys_getJsonVersions(jsonNr, buf);
buf[16] = '\0'; // the DC only handles 16 bytes
static const QByteArray cb(16, (char)0xff);
QString const installedVersion(QString::fromStdString(buf));
QString const fileVersion = getFileVersion(jsonFileNames[i]);
QFileInfo fi(jsonFileNames[i]);
qCritical() << endl;
qCritical() << " json request nr:" << jsonNr;
if (installedVersion == fileVersion) {
qCritical() << " json file:" << fi.fileName();
qCritical() << " installed version in DC:" << installedVersion;
} else
if (cb == QByteArray(buf) && fileVersion == "") {
qCritical() << "unknown json file (repo and DC):" << fi.fileName();
} else {
qCritical() << " json file:" << fi.fileName();
qCritical() << " installed version in DC:" << installedVersion;
qCritical() << " file version in repository:" << fileVersion;
}
} else {
qCritical() << "CANNOT FIND JSON-NR FOR" << fName;
}
}
return false;
}
QString Update::getFileVersion(QString const& jsonFileName) {
// "version":"15.10.2023 14:55 02.00.06",
static const QRegularExpression re("^.*(\\\"[Vv]ersion\\\":)([\\s\\\"]{0,})([^,\\\"]{0,}).*$");
QString fileVersion("");
QFile inputFile(QDir::cleanPath(m_customerRepository + QDir::separator() + jsonFileName));
if (inputFile.exists()) {
if (inputFile.open(QIODevice::ReadOnly)) {
QTextStream in(&inputFile);
while (!in.atEnd()) {
QString line = in.readLine();
QRegularExpressionMatch match;
int idx = line.indexOf(re, 0, &match);
if (idx != -1) {
int const lastCaptured = match.lastCapturedIndex();
// the dc only sends 16 Byte
fileVersion = match.captured(lastCaptured);
fileVersion.truncate(16);
break;
}
}
inputFile.close();
}
} else {
// qCritical() << "ERROR" << inputFile.fileName() << "does not exist";
}
return fileVersion;
}
bool Update::downloadJson(enum FileTypeJson type,
int templateIdx,
QString jsFileToSendToDC) const {
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
qDebug() << "SET AUTO-REQUEST=TRUE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
QStringList lst;
bool ready = false;
int nTry = 25;
while ((ready = m_hw->sys_ready4sending()) == false) {
QThread::msleep(200);
if (--nTry <= 0) {
qCritical() << "SYS NOT READY FOR SENDING AFTER 5 SECONDS";
break;
}
}
bool ret = false;
QString msg;
lst.clear();
if (ready) {
QFile file(jsFileToSendToDC);
QFileInfo fi(jsFileToSendToDC); // max. size of template file is 800 bytes
if (file.exists()) {
if (file.open(QIODevice::ReadOnly)) {
if (fi.size() > 0 && fi.size() <= 800) {
QByteArray ba = file.readAll();
// kindOfFile: 1=config, 2=device, 3=cash, 4=serial, 5=time, 6=printer
// nrOfTemplate=1...32 if kindOfFile==6
// content = content of the Json file, max 800byte ascii signs
if (m_hw->sys_sendJsonFileToDc((uint8_t)(type),
templateIdx,
(uint8_t *)ba.data())) {
/*
* Note: the machine id is contained in DC2C_conf.json.
* The idea was to use this to check if the download of
* the json-file was correct. It did not work, as the
* update of the PSA (to reflect a change in the
* machine id) did not happen immediately.
*
m_hw->dc_autoRequest(true);
QThread::msleep(500);
// testing
m_hw->request_ReadbackMachineID();
QThread::msleep(500);
uint8_t data[64];
memset(data, 0x00, sizeof(data));
uint8_t length = 0;
m_hw->readback_machineIDdata(&length, data);
QThread::msleep(500);
QByteArray ba((const char*)data, length);
qCritical() << length << "MACHINE ID =" << ba.toHex(':');
*/
ret = true;
} else {
qCritical() << QString("ERROR SEND JSON-FILE %1 TO DC").arg(file.fileName());
}
} else {
qCritical() << QString("SIZE OF %1 TOO BIG (%2 BYTES)").arg(jsFileToSendToDC).arg(fi.size());
}
} else {
qCritical() << QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING";
}
} else {
qCritical() << (QString(jsFileToSendToDC) + " DOES NOT EXIST");
}
}
m_hw->dc_autoRequest(false);
qDebug() << "SET AUTO-REQUEST=FALSE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
return ret;
}
bool Update::updatePrinterTemplate(int templateIdx, QString jsFile) const {
return downloadJson(FileTypeJson::PRINTER, templateIdx, jsFile);
}
bool Update::updateConfig(QString jsFile) {
return downloadJson(FileTypeJson::CONFIG, 0, jsFile);
}
bool Update::updateCashConf(QString jsFile) {
return downloadJson(FileTypeJson::CASH, 0, jsFile);
}
bool Update::updateDeviceConf(QString jsFile) {
return downloadJson(FileTypeJson::DEVICE, 0, jsFile);
}

148
DownloadDCFirmware/update.h Normal file
View File

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

View File

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

View File

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

View File

@ -0,0 +1,103 @@
QT += core
QT += serialport network
TARGET = ATBDownloadDCJsonFiles
VERSION="0.1.0"
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}"
!contains(CONFIG, INCLUDEINTERFACES) {
INCLUDEINTERFACES=/opt/ptu5/opt/DCLibraries/include
}
INCLUDEPATH += \
plugins \
$${INCLUDEINTERFACES} \
$${_PRO_FILE_PWD_}/../UpdatePTUDevCtrl \
$${_PRO_FILE_PWD_}/../common/include
CONFIG += c++17
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
# keep comments, as /* fall through */
QMAKE_CXXFLAGS += -C
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -Wno-deprecated-copy -O
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -O2 -std=c++17 # for GCC >= 4.7
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
PTU5BASEPATH = /opt/devel/ptu5
INCLUDEPATH += $$PTU5BASEPATH/qt/libs/devicecontroller/include
LIBS += -L$$PTU5BASEPATH/qt/libs/devicecontroller/library
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 \
../UpdatePTUDevCtrl/message_handler.cpp \
../UpdatePTUDevCtrl/commandline_parser.cpp \
update.cpp \
../common/src/System.cpp
HEADERS += \
../UpdatePTUDevCtrl/message_handler.h \
../UpdatePTUDevCtrl/commandline_parser.h \
update.h \
../common/include/System.h
OTHER_FILES += \
ATBDownloadDCJsonFiles.ini \
../ATBUpdateTool.ini
##########################################################################################
# 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

@ -0,0 +1,445 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 5.0.2, 2024-02-28T16:01:22. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{6a494cc5-6dea-4681-86fc-d47b9761a1f4}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
<value type="bool" key="AutoTest.Framework.Boost">true</value>
<value type="bool" key="AutoTest.Framework.CTest">false</value>
<value type="bool" key="AutoTest.Framework.Catch">true</value>
<value type="bool" key="AutoTest.Framework.GTest">true</value>
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
</valuemap>
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
<value type="int" key="AutoTest.RunAfterBuild">0</value>
<value type="bool" key="AutoTest.UseGlobal">true</value>
<valuemap type="QVariantMap" key="ClangTools">
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">3</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
</valuemap>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">GenericLinuxOsType</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Yocto i.MX6-ATB-PTU5</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Yocto i.MX6-ATB-PTU5</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{804f60e1-6e88-41af-b072-9f5c6a606099}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-DownloadDCJsonFiles-Yocto_i_MX6_ATB_PTU5-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-DownloadDCJsonFiles-Yocto_i_MX6_ATB_PTU5-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments">CONFIG+=PTU5</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand">/usr/bin/make</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand">/usr/bin/make</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-DownloadDCJsonFiles-Yocto_i_MX6_ATB_PTU5-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-DownloadDCJsonFiles-Yocto_i_MX6_ATB_PTU5-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-DownloadDCJsonFiles-Yocto_i_MX6_ATB_PTU5-Profile</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-DownloadDCJsonFiles-Yocto_i_MX6_ATB_PTU5-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
<value type="int" key="SeparateDebugInfo">0</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.CheckForFreeDiskSpaceStep</value>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
<value type="QString" key="RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck">/</value>
<value type="qlonglong" key="RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace">5242880</value>
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.KillAppStep</value>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">DeployToGenericLinux</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">1</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">DownloadDCJsonFiles</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinuxRunConfiguration:/opt/ptu5/opt/DownloadDCJsonFiles/DownloadDCJsonFiles.pro</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/opt/ptu5/opt/DownloadDCJsonFiles/DownloadDCJsonFiles.pro</value>
<value type="int" key="RemoteLinux.EnvironmentAspect.Version">1</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.X11Forwarding">:0</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.1</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.12.12 GCC 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.12.12 GCC 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.51212.gcc_64_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-DownloadDCJsonFiles-Desktop_Qt_5_12_12_GCC_64bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-DownloadDCJsonFiles-Desktop_Qt_5_12_12_GCC_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-DownloadDCJsonFiles-Desktop_Qt_5_12_12_GCC_64bit-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-DownloadDCJsonFiles-Desktop_Qt_5_12_12_GCC_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/opt/ptu5/opt/build-DownloadDCJsonFiles-Desktop_Qt_5_12_12_GCC_64bit-Profile</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/opt/ptu5/opt/build-DownloadDCJsonFiles-Desktop_Qt_5_12_12_GCC_64bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
<value type="int" key="SeparateDebugInfo">0</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">2</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>

View File

View File

@ -0,0 +1,158 @@
#include <QtGlobal>
#include <QCoreApplication>
#include <QByteArray>
#include <QProcess>
#include <QCommandLineParser>
#include <QStandardPaths>
#include <QSettings>
#include <QDir>
#include <QDebug>
#include "message_handler.h"
#include "commandline_parser.h"
#include "utils.h"
#include "update.h"
#include "System.h"
#include <DeviceController/interfaces.h>
//#include <unistd.h>
//#include <errno.h>
#ifdef PTU5
#define SERIAL_PORT "ttymxc2"
#else
#define SERIAL_PORT "ttyUSB0"
#endif
int read1stLineOfFile(QString fileName) {
QFile f(fileName);
if (f.exists()) {
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&f);
in.setCodec("UTF-8");
while(!in.atEnd()) {
return in.readLine().toInt();
}
}
}
return -1;
}
int main(int argc, char **argv) {
QByteArray const value = qgetenv("LC_ALL");
if (value != "C") {
qputenv("LC_ALL", "C");
}
// qputenv("XDG_RUNTIME_DIR", "/var/run/user/0");
openlog("ATB-DL-JSON", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
QCoreApplication a(argc, argv);
QCoreApplication::setApplicationName("ATBDownloadDCJsonFiles");
QCoreApplication::setApplicationVersion(APP_VERSION);
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(LOG_NOTICE);
}
CommandLineParser parser;
parser.process(a);
parser.readSettings();
QString repositoryUrl = parser.repositoryUrl();
QString plugInDir = parser.plugInDir();
QString plugInName = parser.plugInName();
QString workingDir = parser.workingDir();
QString psaConfigDir = parser.psaConfigDir();
QString psaTariffDir = parser.psaTariffDir();
QString iniFileName = parser.iniFileName();
bool const dryRun = parser.dryRun();
bool const noUpdatePsaHardware = parser.noUpdatePsaHardware();
bool const showYoctoVersion = parser.yoctoVersion();
bool const showYoctoInstallStatus = parser.yoctoInstallStatus();
bool const showExtendedVersion = parser.extendedVersion();
bool const alwaysDownloadConfig = parser.alwaysDownloadConfig();
bool const alwaysDownloadDC = parser.alwaysDownloadDC();
QString const rtPath = QCoreApplication::applicationDirPath();
int const machineNr = read1stLineOfFile("/mnt/system_data/machine_nr");
int const customerNr = read1stLineOfFile("/mnt/system_data/cust_nr");
int const zoneNr = read1stLineOfFile("/mnt/system_data/zone_nr");
QString const branchName = (zoneNr != 0)
? QString("zg1/zone%1").arg(zoneNr) : "master";
qInfo() << "pwd ......................" << rtPath;
qInfo() << "repositoryUrl ............" << repositoryUrl;
qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir;
qInfo() << "psaConfigDir ............." << psaConfigDir;
qInfo() << "psaTariffDir ............." << psaTariffDir;
qInfo() << "dryRun ..................." << dryRun;
qInfo() << "noUpdatePsaHardware ......" << noUpdatePsaHardware;
qInfo() << "alwaysDownloadConfig ....." << alwaysDownloadConfig;
qInfo() << "alwaysDownloadDC ........." << alwaysDownloadDC;
qInfo() << "showYoctoVersion ........." << showYoctoVersion;
qInfo() << "showYoctoInstallStatus ..." << showYoctoInstallStatus;
qInfo() << "showExtendedVersion ......" << showExtendedVersion;
qInfo() << "iniFileName .............." << iniFileName;
qInfo() << "extended-version ........." << APP_EXTENDED_VERSION;
qInfo() << "machineNr ................" << machineNr;
qInfo() << "customerNr ..............." << customerNr;
qInfo() << "zoneNr ..................." << zoneNr;
if (showExtendedVersion) {
printf(APP_EXTENDED_VERSION"\n");
return 0;
}
QString const &customerRepo = QDir::cleanPath(workingDir + QDir::separator() + QString("customer_%1").arg(customerNr));
QStringList filesToUpdate;
// etc/psa_config: located under mount-path
std::optional<QString> mountPath = System::checkForUSBStick(psaConfigDir);
if (mountPath.has_value()) {
filesToUpdate = System::getJsonFilesOnUsbStick(mountPath.value());
} else {
qCritical() << "Using customer repository" << customerRepo;
QDir dir(QDir::cleanPath(customerRepo + QDir::separator() + "etc/psa_config"));
if (dir.exists()) {
QStringList jsons = dir.entryList(QStringList() << "DC2C*.json", QDir::Files);
if (!jsons.isEmpty()) {
for (QStringList::size_type i=0; i<jsons.size(); ++i) {
filesToUpdate << QDir::cleanPath(QString("etc/psa_config/") + jsons.at(i));
}
}
} else {
qCritical() << "DIRECTORY" << dir << "DOES NOT EXIST";
return -1;
}
}
// qCritical() << "JSON FILES TO UPDATE" << filesToUpdate;
Update update(customerRepo,
QString::number(customerNr),
branchName,
plugInDir,
plugInName,
workingDir);
update.doUpdate(filesToUpdate, mountPath.has_value());
update.checkJsonVersions();
//update.checkJsonVersions(filesToUpdate);
if (mountPath.has_value()) {
System::umountUSBStick();
}
return 0;
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
#include "command.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
#include <QDateTime>
Command::Command(QString const &command, int start_timeout, int finish_timeout)
: m_command(command.trimmed())
, m_commandResult("")
, m_waitForStartTimeout(start_timeout)
, m_waitForFinishTimeout(finish_timeout)
, m_exitCode(-1) {
}
QString Command::getCommandResult() const {
return m_commandResult;
}
void Command::readyReadStandardOutput() {
QProcess *p = (QProcess *)sender();
m_commandResult += p->readAllStandardOutput();
// qCritical() << m_commandResult;
}
void Command::readyReadStandardError() {
QProcess *p = (QProcess *)sender();
QByteArray buf = p->readAllStandardError();
qCritical() << buf;
}
void Command::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
QProcess *p = (QProcess *)sender();
// read all remaining data sent to the process, just in case
QString d = p->readAllStandardOutput();
if (!d.isEmpty()) {
m_commandResult += d;
}
disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardOutput()));
disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardError()));
}
bool Command::execute(QString workingDirectory, QStringList args) {
if (!QDir::setCurrent(workingDirectory)) {
qCritical() << "SET WORKING_DIRECTORY" << workingDirectory
<< "FAILED FOR" << m_command;
return false;
}
QScopedPointer<QProcess> p(new QProcess(this));
p->setWorkingDirectory(workingDirectory);
p->setProcessChannelMode(QProcess::MergedChannels);
connect(&(*p), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
connect(&(*p), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
if (!args.isEmpty()) {
qDebug() << "START COMMAND" << m_command << "WITH ARGS" << args
<< "IN" << p->workingDirectory();
p->start(m_command, args);
} else {
qDebug() << "START COMMAND" << m_command
<< "IN" << p->workingDirectory();
p->start(m_command);
}
qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch();
if (p->waitForStarted(m_waitForStartTimeout)) {
qDebug() << "PROCESS" << m_command << "STARTED IN" << p->workingDirectory();
if (p->state() == QProcess::ProcessState::Running) {
qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory();
// wait forever for git/opkg-commands to finish
int wait = m_waitForFinishTimeout;
if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) ||
m_command.trimmed().startsWith("opkg", Qt::CaseInsensitive)) {
wait = -1;
}
bool const no_timeout = p->waitForFinished(wait);
if (no_timeout) {
qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory();
if (p->exitStatus() == QProcess::NormalExit) {
if ((m_exitCode = p->exitCode()) == 0) {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qDebug() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
return true;
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "CRASHED with code"
<< p->exitCode()
<< QString("(after %1ms)").arg(end-start)
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command
<< "DID NOT FINISH WITH" << wait
<< "MS IN" << p->workingDirectory()
<< QString("(runtime %1ms)").arg(end-start);
}
} else {
qCritical() << "WRONG PROCESS STATE" << p->state()
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"
<< QString("(runtime %1ms)").arg(end-start)
<< "IN" << p->workingDirectory();
}
return false;
}

View File

@ -1,6 +1,5 @@
#ifndef COMMAND_H_INCLUDED
#define COMMAND_H_INCLUDED
#endif // COMMAND_H_INCLUDED
#include <QObject>
#include <QCoreApplication>
@ -16,18 +15,22 @@ class Command : public QObject {
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);
};
#endif // COMMAND_H_INCLUDED

View File

@ -0,0 +1,434 @@
#include "update.h"
#include <QCoreApplication>
#include <QFile>
#include <QTemporaryFile>
#include <QDebug>
#include <QTextStream>
#include <QRegularExpression>
#include <QRegExp>
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
#include "unistd.h"
#endif
#include <DeviceController/interfaces.h>
#include <QSharedMemory>
#include <QScopedPointer>
#include <QDir>
#include <QThread>
#include <QDateTime>
#include <QPluginLoader>
#include <QMap>
#define UPDATE_OPKG (1)
#define UPDATE_DC (0)
static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
{"57600" , 4}, {"115200" , 5}
};
QPluginLoader Update::pluginLoader;
hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
hwinf *hw = nullptr;
if (plugInDir.exists()) {
QString pluginLibName(fname);
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
QFileInfo info(pluginLibName);
if (info.exists()) {
pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
pluginLoader.setFileName(pluginLibName);
// static QPluginLoader pluginLoader(pluginLibName);
if (!pluginLoader.load()) {
qCritical() << "in directory" << plugInDir.absolutePath();
qCritical() << "cannot load plugin" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString();
return nullptr;
}
qCritical() << "loadDCPlugin() plugin directory:" << plugInDir.absolutePath();
qCritical() << "loadDCPlugin() plugin file name:" << pluginLoader.fileName();
if (!pluginLoader.isLoaded()) {
qCritical() << pluginLoader.errorString();
return nullptr;
}
QObject *plugin = pluginLoader.instance();
if (!plugin) {
qCritical() << "cannot start instance";
return nullptr;
}
if (! (hw = qobject_cast<hwinf *>(plugin))) {
qCritical() << "cannot cast plugin" << plugin << "to hwinf";
return nullptr;
}
} else {
qCritical() << pluginLibName << "does not exist";
return nullptr;
}
} else {
qCritical() << "plugins directory" << plugInDir.absolutePath()
<< "does not exist";
return nullptr;
}
return hw;
}
bool Update::unloadDCPlugin() {
if (pluginLoader.unload()) {
qCritical() << "unloaded plugin" << pluginLoader.fileName();
// Note: will re-instantiate the library !
// QObject *rootObject = pluginLoader.instance();
// if (rootObject) {
// qCritical() << "reloaded plugin: root object again available";
// return false;
// }
// qCritical()unloaded plugin: root object gone";
return true;
}
return false;
}
class hwapi;
Update::Update(QString customerRepository,
QString customerNrStr,
QString branchName,
QString plugInDir,
QString pluginName,
QString workingDir,
bool dryRun,
QObject *parent,
char const *serialInterface,
char const *baudrate)
: QObject(parent)
, m_hw(loadDCPlugin(QDir(plugInDir), pluginName))
, m_serialInterface(serialInterface)
, m_baudrate(baudrate)
, m_customerRepository(customerRepository)
, m_customerNrStr(customerNrStr)
, m_branchName(branchName)
, m_pluginName(pluginName)
, m_workingDir(workingDir)
, m_dryRun(dryRun)
, m_sys_areDCdataValid(false) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_hw == nullptr -> ca-slave plugin loaded ???";
} else {
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "ERROR!!! DC DATA NOT VALID -> CA-MASTER-PLUGIN NOT CONNECTED";
break;
}
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
qCritical() << "(" << __func__ << ":" << __LINE__ << ") m_sys_areDCDataValid ..."
<< m_sys_areDCdataValid;
}
}
Update::~Update() {
unloadDCPlugin();
}
bool Update::doUpdate(QStringList const &filesToWorkOn, bool usbStickDetected) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return false;
}
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED";
return false;
}
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")";
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
bool res = false;
QList<QString>::const_iterator it;
for (it = filesToWorkOn.cbegin(); it != filesToWorkOn.cend(); ++it) {
QString const &fToWorkOn = usbStickDetected ? QDir::cleanPath(it->trimmed())
: QDir::cleanPath(m_customerRepository + QDir::separator() + it->trimmed());
if (fToWorkOn.contains("DC2C_print", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
res = true;
int i = fToWorkOn.indexOf("DC2C_print", Qt::CaseInsensitive);
int const templateIdx = fToWorkOn.mid(i).midRef(10, 2).toInt();
if ((templateIdx < 1) || (templateIdx > 32)) {
qCritical() << "WRONG TEMPLATE INDEX" << templateIdx;
res = false;
} else {
if ((res = updatePrinterTemplate(templateIdx, fToWorkOn))) {
qCritical() <<
QString("DOWNLOADED PRINTER TEMPLATE %1 WITH INDEX=%2")
.arg(fToWorkOn)
.arg(templateIdx);
}
}
} else if (fToWorkOn.contains("DC2C_cash", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateCashConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CASH TEMPLATE %1").arg(fToWorkOn);
}
} else if (fToWorkOn.contains("DC2C_conf", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateConfig(fToWorkOn))) {
qCritical() << QString("DOWNLOADED CONFIG TEMPLATE %1").arg(fToWorkOn);
}
} else if (fToWorkOn.contains("DC2C_device", Qt::CaseInsensitive)
&& fToWorkOn.endsWith(".json", Qt::CaseInsensitive)) {
if ((res = updateDeviceConf(fToWorkOn))) {
qCritical() << QString("DOWNLOADED DEVICE TEMPLATE %1").arg(fToWorkOn);
}
} else {
qCritical() << "UNKNOWN JSON FILE NAME" << fToWorkOn;
res = false;
}
}
return res;
}
bool Update::checkJsonVersions(QStringList const& jsonFileNames) {
if (!m_hw) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! m_hw == nullptr";
return false;
}
int tries = 20;
while ((m_sys_areDCdataValid = m_hw->sys_areDCdataValid()) == false) {
// must deliver 'true', only then are all data from hwapi valid
if (--tries < 0) {
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED";
return false;
}
qCritical() << "(" << __func__ << ":" << __LINE__ << "):"
<< "ERROR!!! DC DATA NOT VALID -> CA-SLAVE-PLUGIN NOT CONNECTED (" << tries << ")";
m_hw->dc_autoRequest(true);
QThread::msleep(500);
}
for (QStringList::size_type i=0; i < jsonFileNames.size(); ++i) {
uint8_t jsonNr = 0;
QString const &fName = jsonFileNames[i];
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 6=printer template 1 ..... 36= template 32
if (fName.endsWith("conf.json")) {
jsonNr = 1;
} else
if (fName.endsWith("device.json")) {
jsonNr = 2;
} else
if (fName.endsWith("cash.json")) {
jsonNr = 3;
} else {
QRegularExpressionMatch match;
static const QRegularExpression re("^(.*print)([0-3][0-9])\\.json\\s*$");
int idx = fName.indexOf(re, 0, &match);
if (idx != -1) {
QString captured = match.captured(match.lastCapturedIndex());
bool ok = false;
int n = captured.toInt(&ok);
if (ok) {
// note: use 5 (instead of 4 -> index has been shifted)
jsonNr = n + 5;
}
}
}
if (jsonNr != 0) {
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
m_hw->sys_requestJsonVersions(jsonNr);
QThread::msleep(500);
char buf[64];
memset(buf, 0x00, sizeof(buf));
m_hw->sys_getJsonVersions(jsonNr, buf);
buf[16] = '\0'; // the DC only handles 16 bytes
static const QByteArray cb(16, (char)0xff);
QString const installedVersion(QString::fromStdString(buf));
QString const fileVersion = getFileVersion(jsonFileNames[i]);
QFileInfo fi(jsonFileNames[i]);
qCritical() << endl;
qCritical() << " json request nr:" << jsonNr;
if (installedVersion == fileVersion) {
qCritical() << " json file:" << fi.fileName();
qCritical() << " installed version in DC:" << installedVersion;
} else
if (cb == QByteArray(buf) && fileVersion == "") {
qCritical() << "unknown json file (repo and DC):" << fi.fileName();
} else {
qCritical() << " json file:" << fi.fileName();
qCritical() << " installed version in DC:" << installedVersion;
qCritical() << " file version in repository:" << fileVersion;
}
} else {
qCritical() << "CANNOT FIND JSON-NR FOR" << fName;
}
}
return false;
}
QString Update::getFileVersion(QString const& jsonFileName) {
// "version":"15.10.2023 14:55 02.00.06",
static const QRegularExpression re("^.*(\\\"[Vv]ersion\\\":)([\\s\\\"]{0,})([^,\\\"]{0,}).*$");
QString fileVersion("");
QFile inputFile(QDir::cleanPath(m_customerRepository + QDir::separator() + jsonFileName));
if (inputFile.exists()) {
if (inputFile.open(QIODevice::ReadOnly)) {
QTextStream in(&inputFile);
while (!in.atEnd()) {
QString line = in.readLine();
QRegularExpressionMatch match;
int idx = line.indexOf(re, 0, &match);
if (idx != -1) {
int const lastCaptured = match.lastCapturedIndex();
// the dc only sends 16 Byte
fileVersion = match.captured(lastCaptured);
fileVersion.truncate(16);
break;
}
}
inputFile.close();
}
} else {
// qCritical() << "ERROR" << inputFile.fileName() << "does not exist";
}
return fileVersion;
}
bool Update::downloadJson(enum FileTypeJson type,
int templateIdx,
QString jsFileToSendToDC) const {
m_hw->dc_autoRequest(true); // downloading Json needs the AutoEmission flag
qDebug() << "SET AUTO-REQUEST=TRUE";
QThread::sleep(1); // make sure the auto-request flag is acknowledged
QStringList lst;
bool ready = false;
int nTry = 25;
while ((ready = m_hw->sys_ready4sending()) == false) {
QThread::msleep(200);
if (--nTry <= 0) {
qCritical() << "SYS NOT READY FOR SENDING AFTER 5 SECONDS";
break;
}
}
bool ret = false;
QString msg;
lst.clear();
if (ready) {
QFile file(jsFileToSendToDC);
QFileInfo fi(jsFileToSendToDC); // max. size of template file is 800 bytes
if (file.exists()) {
if (file.open(QIODevice::ReadOnly)) {
if (fi.size() > 0 && fi.size() <= 800) {
QByteArray ba = file.readAll();
// kindOfFile: 1=config, 2=device, 3=cash, 4=serial, 5=time, 6=printer
// nrOfTemplate=1...32 if kindOfFile==6
// content = content of the Json file, max 800byte ascii signs
if (m_hw->sys_sendJsonFileToDc((uint8_t)(type),
templateIdx,
(uint8_t *)ba.data())) {
/*
* Note: the machine id is contained in DC2C_conf.json.
* The idea was to use this to check if the download of
* the json-file was correct. It did not work, as the
* update of the PSA (to reflect a change in the
* machine id) did not happen immediately.
*
m_hw->dc_autoRequest(true);
QThread::msleep(500);
// testing
m_hw->request_ReadbackMachineID();
QThread::msleep(500);
uint8_t data[64];
memset(data, 0x00, sizeof(data));
uint8_t length = 0;
m_hw->readback_machineIDdata(&length, data);
QThread::msleep(500);
QByteArray ba((const char*)data, length);
qCritical() << length << "MACHINE ID =" << ba.toHex(':');
*/
ret = true;
} else {
qCritical() << QString("ERROR SEND JSON-FILE %1 TO DC").arg(file.fileName());
}
} else {
qCritical() << QString("SIZE OF %1 TOO BIG (%2 BYTES)").arg(jsFileToSendToDC).arg(fi.size());
}
} else {
qCritical() << QString("CAN NOT OPEN ") + jsFileToSendToDC + " FOR READING";
}
} else {
qCritical() << (QString(jsFileToSendToDC) + " DOES NOT EXIST");
}
}
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);
}

View File

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

View File

@ -1,127 +0,0 @@
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
VERSION=1.0.0
INCLUDEPATH += plugins
CONFIG += c++17 console
# CONFIG -= app_bundle
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# custom target for 'git subtree'
# subtree.target = subtree
# subtree.commands = git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# subtree.depends =
# QMAKE_EXTRA_UNIX_TARGETS += subtree
# ! exists(DCPlugin) {
# $$system("git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
# } else {
# $$system("git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
# }
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -std=c++17 # for GCC >= 4.7
QMAKE_CXXFLAGS += -Wno-deprecated-copy
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 \
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 \
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
OTHER_FILES += \
/opt/app/tools/atbupdate/update_log.csv \
main.cpp.bck \
main.cpp.bck2 \
main.cpp.bck3
# https://blog.developer.atlassian.com/the-power-of-git-subtree/?_ga=2-71978451-1385799339-1568044055-1068396449-1567112770
# git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
# include(./DCPlugin/DCPlugin.pri)
##########################################################################################
# for running program on target through QtCreator
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

@ -0,0 +1,267 @@
QT += core gui
QT += widgets serialport network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ATBUpdateTool
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# 1.3.6 : Do not update device-controller/json files, but have the library
# (in a later step) do that.
# Fixed sending messages to ISMAS.
# Always execute contents of opkg_commands-file (even if there are no
# changes).
# 1.3.7 : Wait forever for git-commands to finish in QProcess executing such
# a command.
# 1.3.8 : Remove accessing opkg_commands under file-system-path /etc/psa_update.
# Activate download of json-configuration files.
# 1.3.9 : Fix sendLastVersion: use configured branch and not master branch in
# git show origin/master -s --format="c=%h m=%s d=%cI" ==>
# git show origin/zg1/zone1 -s --format="c=%h m=%s d=%cI"
# Use dynamic values for os-release and apism-version when sending
# last version info.
# 1.3.10: Fix premature killing opkg-commands: detected timeout of 100s was
# too small when updating apism.
# Fix display of UPDATE_SUCCESS when opkg_command fails. Detected when
# updating apsim failed.
# 1.3.11: Integrate version of ATBUpdateTool in SendLastVersion-ISMAS-message.
# 1.3.12: Add command parameters for output of yocto-infos about ATBUpdateTool.
# Use 'git pull' instead of 'git fetch'.
# Use 'git clone --filter=blob:none' instead of 'git clone' to speed
# up cloning of customer repository.
# 1.3.13: Fix: if the customer repository is corrupted, remove it and re-clone
# the repository (without checking the ISMAS-trigger (WAIT-)button.
# 1.3.14: Add additional check for sanity of customer repository using
# "git fsck".
# Stream-lined code of update process: massive refactoring.
# Added functionality: If WAIT button is not active, then an existing
# customer repository will be repaired, or a not existing repository
# will be cloned. The process stops then.
# However, if the WAIT button is active, the at least the commands in
# opkg_commands will be executed. Changed files in the customer
# repository will be worked on: tariff-files will be synced with the
# local filesystem, json-files will be downloaded to firmware.
# The device-controller firmware will be handled in a later version.
# 1.3.15: Bug fixes found during testing.
# Do not disable Exit-button during update-process.
# Removed worker-thread with an own event-loop: only the GUI thread
# has an event loop. Tested JSON-downloads several times successfully
# (using the slave lib where the CA helper tool was active as master).
# Turned previous worker-object into its own thread, but without any
# own event-loop (so it cannot block anything inside the CA-plugin).
# 1.3.16: Bug fixes found during testing.
# 1.3.17: Add ATBUpdateTool.ini and custom command line parser. Settings
# given in ATBUpdateTool.ini can be overwritten on the command-line.
# 1.3.18: Bug fixes found during testing.
# 1.3.19: Bug fixes found during testing.
# 1.3.20: Bug fixes found during testing.
# 1.3.21: Bug fixes found during testing:
# Fix directory of ATBUpdateTool.ini to be the working directory of
# the application rather than just ".".
# Check existance of etc-directory inside customer repository.
# Check for valid ISMAS trigger (button) 15x (=90s).
# NOTE: if the customer repository is cloned (or repaired and cloned
# again), and if the settings always-download-config=true and
# always-download-dc=true in the ATBUpdateTool.ini file, the download
# the printer-json files and the device controller file, even without
# an activated ISMAS trigger (button). The tariff-files are rsynced to
# the local filesystem for such clone.
# Set new filename for device controller: dc2c.bin.
# 1.3.22: Bug fixes found during testing:
# Fix the path-names of the json-files and the device-controller.
# Set automatic download of json-file in ATBUpdateTool.ini file for
# a fresh clone of the repository.
# 1.3.23: Added a 'break' to prevent a possible endless loop when checking if
# the device is alive.
#
# NOTE: The versioning info has to be shifted up by one version, i.e. what
# happened for 1.3.23 was actually done in 1.3.24.
# 1.3.24
#
# 1.3._24_: Special version for szeged using a old dc-controller (4.42):
# Changes:
# (1) the ini-File now uses the libCAmaster.so.
# 1.3._25_: Again special version for szeged, using interface.h, version 4.4.
# 1.4.0 : Start with version at 1.4.0 (mainly to see a difference with Szeged)
# Set hash-value in EVENT-objects. Set location (project), version
# and info in send-last-version.
# If the customer repository does not exist, then do not check the
# ISMAS trigger, but proceed with the update procedure. Otherwise,
# check the ISMAS update-trigger as first step.
# If the current time is between 0.00 - 4.00 o'clock, then a wrong
# trigger-value will result in an UPDATE_STEP_NOT_NECESSARY.
# Move final processing to subclass UpdateProcessRunning.
# Disable EXIT-button for the whole update-process, except for the
# checking of the ISMAS-trigger-button (aka WAIT-button).
# 1.4.1 : Sync files in the customer repository (under ./etc) as the very
# first step
VERSION="1.4.1"
# PLANNED TODOS:
# 1: Das Repository wird repariert bwz. neu geklont. Unabhaengig vom WAIT.
# 2: Wenn der WAIT-Button aktiv ist, dann wird ein Repository repariert (neu
# geklont), aber zusaetzlich werden alle verfuegbaren Dateien als neu
# angesehen und die entsprechenden Aktionen durchgefuehrt: tariff-files
# spiegeln, json-files laden und dc laden. Also VORSICHT: das repository
# muss in diesem fall wirklich in ordnung sein.
# 3: Wurde keine Datei geaendert, kein initiales Clone und der WAIT-button
# nicht aktiv, so (passiert natuerlich nichts) kann man davon ausgehen,
# dass es sich um ein automatisches Update handelt. Dann koennte man im
# ISMAS eine entsprechende Meldung anzeigen als Teil von SEND-LAST-VERSION.
# Wenn der WAIT-button aktiv ist, dann werden zumindest die opkg-commands
# ausgefuehrt.
# 5: Falls das Tool mal abstuerzt, dann einen Signal-Handler (fuer TERM)
# installieren, sodass zumnidest SEND-LAST-VERSION mit rausgeht.
# 6: rsync: explizites Binary, nicht das in busybox enthaltene.
# 7: Versionen der Json-Files lassen sich auslesen.
# Problem: Einstellungen in den Json-Files lassen sich auch mittels
# Funktionen in der CD-Library ueberschreiben. Damit ist dann wieder nicht
# mehr so klar, was jetzt eigentlich aktiv ist.
# 8: m_alwaysDownloadConfig und m_alwaysDownloadDC: vorbereitet: man koennte
# es so arrangieren, dass der DC plus die Json-files im Repository immer
# runtergeladen werden, obwohl sich im Repository gar nicts veraendert
# hat. Eeventuell nuetzlich beim initialen Setuo eines PSA.
# 9: Das Kunden-Repository sollte immer gezogen werden, unabhaengig von der
# Stellung des WAIT-Button. Grund: es koennte sein, dass andernfalls ein
# PSA weit hiter anderen steht, und dann ploetzlich einmal alle vorher-
# gehenden Aenderungen anzieht, die gar nicht fuer ihn gemeint waren.
# 11: Das Edit-Fenster teilen um die Anzeige zu verbessern.
# 12: Bei einem Update muss immer ersichtlich sein, warum es ueberhaupt
# angestossen wurde. Steht kein "WAIT" im ISMAS-Trigger, dann kann man
# davon ausgehen, dass es sich um ein automatisches Update handelt.
# In jedem Fall wird bei einem automatischen Update, bei dem der WAIT-
# Button nicht gesetzt war, ein "OK" gesendet, falls sonst nichts weiter
# zu tun ist. Beachte aber: wir haben auch noch den Fall, dass eine SD-
# Karte gesteckt wird. In diesem Fall wird ein komplettes Update gefahren,
# und zwar explizit auch ohne WAIT-Button.
# Am Ende eines Updates steht im ISMAS entweder ein "OK" oder ein "FAIL".
# 13: SendLastVersion: fuer jedes erfolgreich installierte Paket eine
# Send-Last-Version-Nachricht an ISMAS. Dadurch entsteht im ISMAS eine
# History (Christian darueber informieren).
# 14: Installiert werden nur Dateien, die neu sind oder geaendert wurden.
# Nicht etwas Dateien, die geloescht wurden: sicherstellen, dass man hier
# immer direkt im repository arbeitet, nicht auf dem Filesystem.
# Ferner: der DeviceController heisst dc2c.bin, auch fuer die Jsons
# sind Dtandard-Namen vergeben. Alternativ: alle vorhandenen Jsons
# werden runtergeladen: Thomas ist eh fuer deren Inhalte verantworlich.
# WICHTIG: immer ueberpruefen, ob die Dateien im Customer-Repository
# wirklich die richtigen Dateien sind.
# 15: Der WAIT-Button laesst sich auf WAIT zuruecksetzen (etwa wenn git
# selber Probleme hatte).
# 16: Der Download-Thread sollte sowohl die auto-Variable auf false setzen
# als auch den cycle-Timer stoppen, damit sichergestellt ist, dass der
# Download des DC nicht gestoert wird.
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
}
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
INCLUDEPATH += plugins
CONFIG += c++17
# CONFIG -= app_bundle
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
# keep comments, as /* fall through */
QMAKE_CXXFLAGS += -C
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -Wno-deprecated-copy -O
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -O2 -std=c++17 # for GCC >= 4.7
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
ARCH = PTU5
DEFINES+=PTU5
}
contains( CONFIG, PTU5_YOCTO ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
QMAKE_CXXFLAGS += -std=c++17 # for GCC >= 4.7
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
PTU5BASEPATH = /opt/devel/ptu5
ARCH = PTU5
DEFINES+=PTU5
# add qmqtt lib
#LIBS += -lQt5Qmqtt
}
contains( CONFIG, DesktopLinux ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
lessThan(QT_MAJOR_VERSION, 5): CONFIG += extserialport
# QMAKE_CC = ccache $$QMAKE_CC
# QMAKE_CXX = ccache $$QMAKE_CXX
QMAKE_CXXFLAGS += -std=c++17
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux
DEFINES+=DesktopLinux
}
SOURCES += \
main.cpp \
progress_event.cpp \
update_dc_event.cpp \
mainwindow.cpp \
utils.cpp \
update.cpp \
git/git_client.cpp \
ismas/ismas_client.cpp \
process/command.cpp \
message_handler.cpp \
worker.cpp \
commandline_parser.cpp
HEADERS += \
update.h \
progress_event.h \
update_dc_event.h \
utils.h \
mainwindow.h \
git/git_client.h \
apism/ismas_data.h \
ismas/ismas_client.h \
process/command.h \
message_handler.h \
worker.h \
interfaces.h \
commandline_parser.h \
plugins/interfaces.h
OTHER_FILES += \
ATBUpdateTool.ini
FORMS += \
mainwindow.ui
##########################################################################################
# for running program on target through QtCreator
contains( CONFIG, PTU5 ) {
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/app/tools/atbupdate/
!isEmpty(target.path): INSTALLS += target
}

View File

@ -0,0 +1,314 @@
QT += core gui
QT += widgets serialport network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ATBUpdateTool
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# 1.3.6 : Do not update device-controller/json files, but have the library
# (in a later step) do that.
# Fixed sending messages to ISMAS.
# Always execute contents of opkg_commands-file (even if there are no
# changes).
# 1.3.7 : Wait forever for git-commands to finish in QProcess executing such
# a command.
# 1.3.8 : Remove accessing opkg_commands under file-system-path /etc/psa_update.
# Activate download of json-configuration files.
# 1.3.9 : Fix sendLastVersion: use configured branch and not master branch in
# git show origin/master -s --format="c=%h m=%s d=%cI" ==>
# git show origin/zg1/zone1 -s --format="c=%h m=%s d=%cI"
# Use dynamic values for os-release and apism-version when sending
# last version info.
# 1.3.10: Fix premature killing opkg-commands: detected timeout of 100s was
# too small when updating apism.
# Fix display of UPDATE_SUCCESS when opkg_command fails. Detected when
# updating apsim failed.
# 1.3.11: Integrate version of ATBUpdateTool in SendLastVersion-ISMAS-message.
# 1.3.12: Add command parameters for output of yocto-infos about ATBUpdateTool.
# Use 'git pull' instead of 'git fetch'.
# Use 'git clone --filter=blob:none' instead of 'git clone' to speed
# up cloning of customer repository.
# 1.3.13: Fix: if the customer repository is corrupted, remove it and re-clone
# the repository (without checking the ISMAS-trigger (WAIT-)button.
# 1.3.14: Add additional check for sanity of customer repository using
# "git fsck".
# Stream-lined code of update process: massive refactoring.
# Added functionality: If WAIT button is not active, then an existing
# customer repository will be repaired, or a not existing repository
# will be cloned. The process stops then.
# However, if the WAIT button is active, the at least the commands in
# opkg_commands will be executed. Changed files in the customer
# repository will be worked on: tariff-files will be synced with the
# local filesystem, json-files will be downloaded to firmware.
# The device-controller firmware will be handled in a later version.
# 1.3.15: Bug fixes found during testing.
# Do not disable Exit-button during update-process.
# Removed worker-thread with an own event-loop: only the GUI thread
# has an event loop. Tested JSON-downloads several times successfully
# (using the slave lib where the CA helper tool was active as master).
# Turned previous worker-object into its own thread, but without any
# own event-loop (so it cannot block anything inside the CA-plugin).
# 1.3.16: Bug fixes found during testing.
# 1.3.17: Add ATBUpdateTool.ini and custom command line parser. Settings
# given in ATBUpdateTool.ini can be overwritten on the command-line.
# 1.3.18: Bug fixes found during testing.
# 1.3.19: Bug fixes found during testing.
# 1.3.20: Bug fixes found during testing.
# 1.3.21: Bug fixes found during testing:
# Fix directory of ATBUpdateTool.ini to be the working directory of
# the application rather than just ".".
# Check existance of etc-directory inside customer repository.
# Check for valid ISMAS trigger (button) 15x (=90s).
# NOTE: if the customer repository is cloned (or repaired and cloned
# again), and if the settings always-download-config=true and
# always-download-dc=true in the ATBUpdateTool.ini file, the download
# the printer-json files and the device controller file, even without
# an activated ISMAS trigger (button). The tariff-files are rsynced to
# the local filesystem for such clone.
# Set new filename for device controller: dc2c.bin.
# 1.3.22: Bug fixes found during testing:
# Fix the path-names of the json-files and the device-controller.
# Set automatic download of json-file in ATBUpdateTool.ini file for
# a fresh clone of the repository.
# 1.3.23: Added a 'break' to prevent a possible endless loop when checking if
# the device is alive.
#
# NOTE: The versioning info has to be shifted up by one version, i.e. what
# happened for 1.3.23 was actually done in 1.3.24.
# 1.3.24
#
# 1.3._24_: Special version for szeged using a old dc-controller (4.42):
# Changes:
# (1) the ini-File now uses the libCAmaster.so.
# 1.3._25_: Again special version for szeged, using interface.h, version 4.4.
# 1.4.0 : Start with version at 1.4.0 (mainly to see a difference with Szeged)
# Set hash-value in EVENT-objects. Set location (project), version
# and info in send-last-version.
# If the customer repository does not exist, then do not check the
# ISMAS trigger, but proceed with the update procedure. Otherwise,
# check the ISMAS update-trigger as first step.
# If the current time is between 0.00 - 4.00 o'clock, then a wrong
# trigger-value will result in an UPDATE_STEP_NOT_NECESSARY.
# Move final processing to subclass UpdateProcessRunning.
# Disable EXIT-button for the whole update-process, except for the
# checking of the ISMAS-trigger-button (aka WAIT-button).
# 1.4.1 : Sync files in the customer repository (under ./etc) as the very
# first step
# 1.4.2 : Do not check if <repo_dir>/etc/psa_tariff and /etc/psa_tariff are
# the same after an rsync. They might be noy after a change of the
# customer-number.
# 1.4.3 : Use global directory for device-controller interfaces.h-file.
# 1.4.4 : Add additional debug messages when downloading json-files.
# Move rsyncing of the customer-repository after the actual fetching
# of the repository. Otherwise, the update of, for instance
# tariff-files, would always be a step behind.
# 1.4.5 : In case a new branch has been created in a remote
# customer-repository (e.g. origin/zg1/zone101), then fetch/pull
# this branch before switching to this now locally existen branch.
# : Improve output of GUI/Console and messages sent to ISMAS.
# : Fix: do not send the json-files to dc in any case. Bug introduced
# when pulling new branch, but branch already existed locally.
# 1.4.6 : No exit()-call if loading CA-plugin fails.
# Check m_hw (pointer to CA-(Slave)Plugin) before its use.
# Only exit() if firmware is configured to be possibly updated, but
# loading the CA-plugin failed.
# 1.4.7 : Read Json-file versions of Json-files actually loaded into DC.
# 1.4.8 : Improve reading Json-file versions of Json-files actually loaded
# in DC. If available, show version info instead of blob-info of
# Json file.
# 1.4.9 : Improve ISMAS output: add messages for JSON downloads.
# Do not send CHECK_ISMAS_TRIGGER_SUCCESS to ISMAS for an automatic
# update.
# In case there is an automatic update (00:00-04:00) use M0100 instead
# of U0002.
# 1.4.10 : Fix: for the time being, never set the autoRequest-flag to false.
# 1.4.11 : Fix: remove hard-coded path to git-repos of gitea in mimbach. Read
# from ATBUpdateTool.ini the url for the gitrepositories.
# 1.5.0 : Use ptu-config.atb-comm.de (given in ini-file) as new server for
# customer repositories.
# Fix: allow empty lines in opkg_commands.
# 1.5.1 : Fix: do not use cleanPath() on a url-address.
# 1.5.2 : Remove .ipk and .gz files in /var/cache/opkg.
# 1.5.3 : Build customer_(id) name without right justification.
# 1.5.4 : Try to run opkg-commands even under some error conditions (failure
# of customerEnvironment(), filesToUpdate() or
# syncCustomerRepositoryAndFS().
# 1.5.5 : Call into binary ptuPackageVersion to get installed package
# versions.
# 1.5.6 : Show additional update progress info in status bar.
# 1.5.7 : Add support for dynamic portrait / landscape.
VERSION="1.5.7"
# PLANNED TODOS:
# 1: Das Repository wird repariert bwz. neu geklont. Unabhaengig vom WAIT.
# 2: Wenn der WAIT-Button aktiv ist, dann wird ein Repository repariert (neu
# geklont), aber zusaetzlich werden alle verfuegbaren Dateien als neu
# angesehen und die entsprechenden Aktionen durchgefuehrt: tariff-files
# spiegeln, json-files laden und dc laden. Also VORSICHT: das repository
# muss in diesem fall wirklich in ordnung sein.
# 3: Wurde keine Datei geaendert, kein initiales Clone und der WAIT-button
# nicht aktiv, so (passiert natuerlich nichts) kann man davon ausgehen,
# dass es sich um ein automatisches Update handelt. Dann koennte man im
# ISMAS eine entsprechende Meldung anzeigen als Teil von SEND-LAST-VERSION.
# Wenn der WAIT-button aktiv ist, dann werden zumindest die opkg-commands
# ausgefuehrt.
# 5: Falls das Tool mal abstuerzt, dann einen Signal-Handler (fuer TERM)
# installieren, sodass zumnidest SEND-LAST-VERSION mit rausgeht.
# 6: rsync: explizites Binary, nicht das in busybox enthaltene.
# 7: Versionen der Json-Files lassen sich auslesen.
# Problem: Einstellungen in den Json-Files lassen sich auch mittels
# Funktionen in der CD-Library ueberschreiben. Damit ist dann wieder nicht
# mehr so klar, was jetzt eigentlich aktiv ist.
# 8: m_alwaysDownloadConfig und m_alwaysDownloadDC: vorbereitet: man koennte
# es so arrangieren, dass der DC plus die Json-files im Repository immer
# runtergeladen werden, obwohl sich im Repository gar nicts veraendert
# hat. Eeventuell nuetzlich beim initialen Setuo eines PSA.
# 9: Das Kunden-Repository sollte immer gezogen werden, unabhaengig von der
# Stellung des WAIT-Button. Grund: es koennte sein, dass andernfalls ein
# PSA weit hiter anderen steht, und dann ploetzlich einmal alle vorher-
# gehenden Aenderungen anzieht, die gar nicht fuer ihn gemeint waren.
# 11: Das Edit-Fenster teilen um die Anzeige zu verbessern.
# 12: Bei einem Update muss immer ersichtlich sein, warum es ueberhaupt
# angestossen wurde. Steht kein "WAIT" im ISMAS-Trigger, dann kann man
# davon ausgehen, dass es sich um ein automatisches Update handelt.
# In jedem Fall wird bei einem automatischen Update, bei dem der WAIT-
# Button nicht gesetzt war, ein "OK" gesendet, falls sonst nichts weiter
# zu tun ist. Beachte aber: wir haben auch noch den Fall, dass eine SD-
# Karte gesteckt wird. In diesem Fall wird ein komplettes Update gefahren,
# und zwar explizit auch ohne WAIT-Button.
# Am Ende eines Updates steht im ISMAS entweder ein "OK" oder ein "FAIL".
# 13: SendLastVersion: fuer jedes erfolgreich installierte Paket eine
# Send-Last-Version-Nachricht an ISMAS. Dadurch entsteht im ISMAS eine
# History (Christian darueber informieren).
# 14: Installiert werden nur Dateien, die neu sind oder geaendert wurden.
# Nicht etwas Dateien, die geloescht wurden: sicherstellen, dass man hier
# immer direkt im repository arbeitet, nicht auf dem Filesystem.
# Ferner: der DeviceController heisst dc2c.bin, auch fuer die Jsons
# sind Dtandard-Namen vergeben. Alternativ: alle vorhandenen Jsons
# werden runtergeladen: Thomas ist eh fuer deren Inhalte verantworlich.
# WICHTIG: immer ueberpruefen, ob die Dateien im Customer-Repository
# wirklich die richtigen Dateien sind.
# 15: Der WAIT-Button laesst sich auf WAIT zuruecksetzen (etwa wenn git
# selber Probleme hatte).
# 16: Der Download-Thread sollte sowohl die auto-Variable auf false setzen
# als auch den cycle-Timer stoppen, damit sichergestellt ist, dass der
# Download des DC nicht gestoert wird.
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
}
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
INCLUDEPATH += plugins
CONFIG += c++17
# CONFIG -= app_bundle
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
# keep comments, as /* fall through */
QMAKE_CXXFLAGS += -C
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS += -Wno-deprecated-copy -O
contains( CONFIG, PTU5 ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
CONFIG += link_pkgconfig
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
QMAKE_CXXFLAGS += -O2 -std=c++17 # for GCC >= 4.7
PTU5BASEPATH = /opt/devel/ptu5
INCLUDEPATH += $$PTU5BASEPATH/qt/libs/devicecontroller/include
LIBS += -L$$PTU5BASEPATH/qt/libs/devicecontroller/library
# 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
LIBS += -lCAslave
LIBS += -lCAmaster
}
contains( CONFIG, DesktopLinux ) {
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
lessThan(QT_MAJOR_VERSION, 5): CONFIG += extserialport
# QMAKE_CC = ccache $$QMAKE_CC
# QMAKE_CXX = ccache $$QMAKE_CXX
QMAKE_CXXFLAGS += -std=c++17
# QMAKE_CXXFLAGS += -Wno-deprecated-copy
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux
DEFINES+=DesktopLinux
}
SOURCES += \
main.cpp \
progress_event.cpp \
update_dc_event.cpp \
mainwindow.cpp \
utils.cpp \
update.cpp \
git/git_client.cpp \
ismas/ismas_client.cpp \
process/command.cpp \
message_handler.cpp \
worker.cpp \
commandline_parser.cpp
HEADERS += \
update.h \
progress_event.h \
update_dc_event.h \
utils.h \
mainwindow.h \
git/git_client.h \
apism/ismas_data.h \
ismas/ismas_client.h \
process/command.h \
message_handler.h \
worker.h \
commandline_parser.h
OTHER_FILES += \
ATBUpdateTool.ini
FORMS += \
mainwindow.ui
##########################################################################################
# for running program on target through QtCreator
contains( CONFIG, PTU5 ) {
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/app/tools/atbupdate/
!isEmpty(target.path): INSTALLS += target
}

View File

@ -0,0 +1,302 @@
#include "commandline_parser.h"
#include <QDir>
#include <QSettings>
#include <QDebug>
#include <QFile>
CommandLineParser::CommandLineParser()
: m_repositoryUrl("https://git.mimbach49.de/GerhardHoffmann")
, m_plugInDir("/usr/lib/")
, m_plugInName("libCAslave.so")
, m_workingDir("/opt/app/tools/atbupdate/")
, m_dryRun("false")
, m_noUpdatePsaHardware("false")
, m_showYoctoVersion("false")
, m_showYoctoInstallStatus("false")
, m_showExtendedVersion("false")
, m_iniFileName("ATBUpdateTool.ini")
, m_alwaysDownloadConfig("false")
, m_alwaysDownloadDC("false")
, m_repositoryUrlOption(
QCommandLineOption(
QStringList() << "repository-url" << "repository-url",
QCoreApplication::translate("main", "Where to find a customer repository."),
QCoreApplication::translate("main", "directory")))
, m_iniFileDirectoryOption(
QCommandLineOption(
QStringList() << "ini-directory" << "ini-directory",
QCoreApplication::translate("main", "Where to find an ini-file."),
QCoreApplication::translate("main", "directory")))
, m_iniFileNameOption(
QCommandLineOption(
QStringList() << "ini-filename" << "ini-filename",
QCoreApplication::translate("main", "Name of ini-file."),
QCoreApplication::translate("main", "file")))
, m_pluginDirectoryOption(
QCommandLineOption(
QStringList() << "plugin-directory" << "plugin-directory",
QCoreApplication::translate("main", "Where to find dc-plugin."),
QCoreApplication::translate("main", "directory")))
, m_pluginNameOption(
QCommandLineOption(
QStringList() << "plugin-name" << "plugin-name",
QCoreApplication::translate("main", "Name of dc-plugin."),
QCoreApplication::translate("main", "directory")))
, m_noDownloadOption(
QCommandLineOption(
"no-psa-hardware-update",
QCoreApplication::translate("main", "Do not update the PSA firmware (json, device-controller).")))
, m_alwaysDownloadConfigOption(
QCommandLineOption(
"always-download-config",
QCoreApplication::translate("main", "Always download the (json-)configs to DC).")))
, m_alwaysDownloadDCOption(
QCommandLineOption(
"always-download-dc",
QCoreApplication::translate("main", "Always download the dc-bin-file to DC).")))
, m_workingDirectoryOption(
QCommandLineOption(
QStringList() << "working-directory" << "working-directory",
QCoreApplication::translate("main", "working directory of update-script."),
QCoreApplication::translate("main", "directory")))
, m_psaConfigDirectoryOption(
QCommandLineOption(
QStringList() << "psa-config-directory" << "psa-config-directory",
QCoreApplication::translate("main", "config directory of json-files sent to dc."),
QCoreApplication::translate("main", "directory")))
, m_psaTariffDirectoryOption(
QCommandLineOption(
QStringList() << "psa-tariff-directory" << "psa-tariff-directory",
QCoreApplication::translate("main", "tariff directory of tariff-json-files."),
QCoreApplication::translate("main", "directory")))
, m_dryRunOption(
QCommandLineOption(
QStringList() << "d" << "dry-run",
QCoreApplication::translate("main", "Start ATBUpdateTool in dry-run-mode. No actual actions.")))
, m_extendedVersionOption(
QCommandLineOption(
QStringList() << "V" << "extended-version",
QCoreApplication::translate("main", "Show extended version (including last git commit).")))
, m_yoctoVersionOption(
QCommandLineOption(
QStringList() << "y" << "yocto-version",
QCoreApplication::translate("main", "Show yocto version of ATBUpdateTool.")))
, m_yoctoInstallStatusOption(
QCommandLineOption(
QStringList() << "Y" << "yocto-install",
QCoreApplication::translate("main", "Show yocto install status of ATBUpdateTool."))) {
configure();
}
void CommandLineParser::configure() {
m_parser.setApplicationDescription("Download tool for downloading device controller firmware, printer json-files and executing opkg-commands.");
m_parser.addHelpOption();
m_parser.addVersionOption();
m_repositoryUrlOption.setDefaultValue("https://git.mimbach49.de/GerhardHoffmann");
m_parser.addOption(m_repositoryUrlOption);
m_iniFileDirectoryOption.setDefaultValue(QCoreApplication::applicationDirPath());
m_parser.addOption(m_iniFileDirectoryOption);
m_iniFileNameOption.setDefaultValue("ATBUpdateTool.ini");
m_parser.addOption(m_iniFileNameOption);
m_pluginDirectoryOption.setDefaultValue("/usr/lib/");
m_parser.addOption(m_pluginDirectoryOption);
m_pluginNameOption.setDefaultValue("libCAslave.so");
m_parser.addOption(m_pluginNameOption);
m_alwaysDownloadConfigOption.setDefaultValue("false");
m_parser.addOption(m_alwaysDownloadConfigOption);
m_alwaysDownloadDCOption.setDefaultValue("false");
m_parser.addOption(m_alwaysDownloadDCOption);
m_noDownloadOption.setDefaultValue("false");
m_parser.addOption(m_noDownloadOption);
m_workingDirectoryOption.setDefaultValue("/opt/app/tools/atbupdate/");
m_parser.addOption(m_workingDirectoryOption);
m_psaConfigDirectoryOption.setDefaultValue("etc/psa_config/");
m_parser.addOption(m_psaConfigDirectoryOption);
m_psaTariffDirectoryOption.setDefaultValue("etc/psa_tariff/");
m_parser.addOption(m_psaTariffDirectoryOption);
m_dryRunOption.setDefaultValue("false");
m_parser.addOption(m_dryRunOption);
m_extendedVersionOption.setDefaultValue("false");
m_parser.addOption(m_extendedVersionOption);
m_yoctoVersionOption.setDefaultValue("false");
m_parser.addOption(m_yoctoVersionOption);
m_yoctoInstallStatusOption.setDefaultValue("false");
m_parser.addOption(m_yoctoInstallStatusOption);
}
void CommandLineParser::readSettings() {
QString const iniFileDir = m_parser.value(m_iniFileDirectoryOption);
QString const iniFileName = m_parser.value(m_iniFileNameOption);
m_iniFileName = QDir::cleanPath(iniFileDir + QDir::separator() + iniFileName);
qCritical() << __PRETTY_FUNCTION__ << " iniFileDir" << iniFileDir;
qCritical() << __PRETTY_FUNCTION__ << "iniFileName" << m_iniFileName;
if (!m_iniFileName.isEmpty()) {
if (QFile(m_iniFileName).exists()) {
QSettings settings(m_iniFileName, QSettings::IniFormat);
QStringList keys = settings.allKeys();
for (QString const &key: keys) {
QVariant v = settings.value(key);
qCritical() << __PRETTY_FUNCTION__
<< key << " -> " << v.toString();
if (key.contains("repository-url")) {
m_repositoryUrl = v.toString();
} else
if (key.contains("plugin-directory")) {
m_plugInDir = v.toString();
} else
if (key.contains("working-directory")) {
m_workingDir = v.toString();
} else
if (key.contains("psa-config-directory")) {
m_psaConfigDir = v.toString();
} else
if (key.contains("psa-tariff-directory")) {
m_psaTariffDir = v.toString();
} else
if (key.contains("dry-run")) {
m_dryRun = (v.toBool() ? "true" : "false");
} else
if (key.contains("extended-version")) {
m_showExtendedVersion = (v.toBool() ? "true" : "false");
} else
if (key.contains("no-psa-hardware-update")) {
m_noUpdatePsaHardware = (v.toBool() ? "true" : "false");
} else
if (key.contains("always-download-config")) {
m_alwaysDownloadConfig = (v.toBool() ? "true" : "false");
} else
if (key.contains("always-download-dc")) {
m_alwaysDownloadDC = (v.toBool() ? "true" : "false");
} else
if (key.contains("yocto-install")) {
m_showYoctoInstallStatus = (v.toBool() ? "true" : "false");
} else
if (key.contains("yocto-version")) {
m_showYoctoVersion = (v.toBool() ? "true" : "false");
} else
if (key.contains("plugin-name")) {
m_plugInName = v.toString();
} else {
qCritical() << __PRETTY_FUNCTION__
<< key << " -> (UNKNOWN) " << v.toString();
}
}
} else {
qCritical() << __PRETTY_FUNCTION__ << "iniFileName" << m_iniFileName
<< "DOES NOT EXIST";
}
}
}
QString CommandLineParser::repositoryUrl() {
if (m_parser.isSet(m_repositoryUrlOption)) {
m_repositoryUrl = m_parser.value(m_repositoryUrlOption);
}
return m_repositoryUrl;
}
QString CommandLineParser::plugInDir() {
if (m_parser.isSet(m_pluginDirectoryOption)) {
m_plugInDir = m_parser.value(m_pluginDirectoryOption);
}
return m_plugInDir;
}
QString CommandLineParser::plugInName() {
if (m_parser.isSet(m_pluginNameOption)) {
m_plugInName = m_parser.value(m_pluginNameOption);
}
return m_plugInName;
}
QString CommandLineParser::psaConfigDir() {
if (m_parser.isSet(m_psaConfigDirectoryOption)) {
m_psaConfigDir = m_parser.value(m_psaConfigDirectoryOption);
}
return m_psaConfigDir;
}
QString CommandLineParser::psaTariffDir() {
if (m_parser.isSet(m_psaTariffDirectoryOption)) {
m_psaTariffDir = m_parser.value(m_psaTariffDirectoryOption);
}
return m_psaTariffDir;
}
QString CommandLineParser::workingDir() {
if (m_parser.isSet(m_workingDirectoryOption)) {
m_workingDir = m_parser.value(m_workingDirectoryOption);
}
return m_workingDir;
}
bool CommandLineParser::dryRun() {
if (m_parser.isSet(m_dryRunOption)) {
m_dryRun = m_parser.value(m_dryRunOption);
}
return m_dryRun == "false" ? false : true;
}
bool CommandLineParser::noUpdatePsaHardware() {
if (m_parser.isSet(m_noDownloadOption)) {
m_noUpdatePsaHardware = m_parser.value(m_noDownloadOption);
}
return m_noUpdatePsaHardware == "false" ? false : true;
}
bool CommandLineParser::yoctoVersion() {
if (m_parser.isSet(m_yoctoVersionOption)) {
m_showYoctoVersion = m_parser.value(m_yoctoVersionOption);
}
return m_showYoctoVersion == "false" ? false : true;
}
bool CommandLineParser::yoctoInstallStatus() {
if (m_parser.isSet(m_yoctoInstallStatusOption)) {
m_showYoctoInstallStatus = m_parser.value(m_yoctoInstallStatusOption);
}
return m_showYoctoInstallStatus == "false" ? false : true;
}
bool CommandLineParser::extendedVersion() {
if (m_parser.isSet(m_extendedVersionOption)) {
m_showExtendedVersion = m_parser.value(m_extendedVersionOption);
}
return m_showExtendedVersion == "false" ? false : true;
}
bool CommandLineParser::alwaysDownloadConfig() {
if (m_parser.isSet(m_alwaysDownloadConfigOption)) {
m_alwaysDownloadConfig = m_parser.value(m_alwaysDownloadConfigOption);
qCritical() << "m_alwaysDownloadConfigOption IS SET" << m_alwaysDownloadConfig;
}
qCritical() << "m_alwaysDownloadConfig" << m_alwaysDownloadConfig;
return m_alwaysDownloadConfig == "false" ? false : true;
}
bool CommandLineParser::alwaysDownloadDC() {
if (m_parser.isSet(m_alwaysDownloadDCOption)) {
m_alwaysDownloadDC = m_parser.value(m_alwaysDownloadDCOption);
}
return m_alwaysDownloadDC == "false" ? false : true;
}

View File

@ -0,0 +1,69 @@
#ifndef COMMAND_LINE_PARSER_H_INCLUDED
#define COMMAND_LINE_PARSER_H_INCLUDED
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QString>
class CommandLineParser : public QCommandLineParser {
QString m_repositoryUrl;
QString m_plugInDir;
QString m_plugInName;
QString m_workingDir;
QString m_psaConfigDir;
QString m_psaTariffDir;
QString m_dryRun;
QString m_noUpdatePsaHardware;
QString m_showYoctoVersion;
QString m_showYoctoInstallStatus;
QString m_showExtendedVersion;
QString m_iniFileName;
QString m_alwaysDownloadConfig;
QString m_alwaysDownloadDC;
QCommandLineOption m_repositoryUrlOption;
QCommandLineOption m_iniFileDirectoryOption;
QCommandLineOption m_iniFileNameOption;
QCommandLineOption m_pluginDirectoryOption;
QCommandLineOption m_pluginNameOption;
QCommandLineOption m_noDownloadOption;
QCommandLineOption m_alwaysDownloadConfigOption;
QCommandLineOption m_alwaysDownloadDCOption;
QCommandLineOption m_workingDirectoryOption;
QCommandLineOption m_psaConfigDirectoryOption;
QCommandLineOption m_psaTariffDirectoryOption;
QCommandLineOption m_dryRunOption;
QCommandLineOption m_extendedVersionOption;
QCommandLineOption m_yoctoVersionOption;
QCommandLineOption m_yoctoInstallStatusOption;
QCommandLineParser m_parser;
void configure();
public:
explicit CommandLineParser();
~CommandLineParser() = default;
QCommandLineParser &parser() { return m_parser; }
QCommandLineParser const &parser() const { return m_parser; }
void process(const QCoreApplication &app) { m_parser.process(app); }
QString const &iniFileName() const { return m_iniFileName; }
void readSettings();
QString repositoryUrl();
QString plugInDir();
QString plugInName();
QString workingDir();
QString psaConfigDir();
QString psaTariffDir();
bool dryRun();
bool noUpdatePsaHardware();
bool yoctoVersion();
bool yoctoInstallStatus();
bool extendedVersion();
bool alwaysDownloadConfig();
bool alwaysDownloadDC();
};
#endif // COMMAND_LINE_PARSER_H_INCLUDED

View File

@ -0,0 +1,230 @@
<mxfile host="www.draw.io" modified="2023-11-07T10:37:35.350Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0" etag="ldmgaDoAxcOIqmOptaKH" version="22.0.8" type="device">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="1042" dy="633" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-2" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-3" target="WIyWlLk6GJQsqaUBKTNV-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-3" value="START" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="350" y="10" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-6">
<mxGeometry relative="1" as="geometry">
<mxPoint x="220" y="180" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-6" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Existent customer repository&lt;/div&gt;&lt;div&gt;?&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="170" y="60" width="100" height="90" as="geometry" />
</mxCell>
<object label="" id="KwNStDcgQ-FNAQaH3l0E-18">
<mxCell style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-7" target="KwNStDcgQ-FNAQaH3l0E-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</object>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-7" value="Clone customer repository" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="310" y="130" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-10" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Repository corrupted&lt;/div&gt;&lt;div&gt;?&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="170" y="180" width="100" height="80" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.15;entryY=0.55;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-9" target="KwNStDcgQ-FNAQaH3l0E-110">
<mxGeometry relative="1" as="geometry">
<mxPoint x="600" y="150" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-9" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Repository corrupted&lt;/div&gt;&lt;div&gt;?&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="480" y="150" width="90" height="80" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-11" value="FAIL" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="585" y="10" width="100" height="40" as="geometry" />
</mxCell>
<UserObject label="Yes" placeholders="1" name="Variable" id="KwNStDcgQ-FNAQaH3l0E-20">
<mxCell style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="560" y="160" width="80" height="20" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-23" value="&lt;div&gt;No&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="430" y="280" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-25" value="Delete corrupted repository" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="310" y="200" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-26" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-25">
<mxGeometry width="80" relative="1" as="geometry">
<mxPoint x="270" y="220" as="sourcePoint" />
<mxPoint x="310" y="220" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-27" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-25" target="WIyWlLk6GJQsqaUBKTNV-7">
<mxGeometry width="80" relative="1" as="geometry">
<mxPoint x="540" y="240" as="sourcePoint" />
<mxPoint x="620" y="240" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-93" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-28" target="KwNStDcgQ-FNAQaH3l0E-92">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-28" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;ISMAS trigger&lt;/div&gt;&lt;div&gt;&lt;b&gt;WAIT&lt;/b&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;?&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="300" y="380" width="140" height="90" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-29" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-9" target="KwNStDcgQ-FNAQaH3l0E-78">
<mxGeometry width="80" relative="1" as="geometry">
<mxPoint x="540" y="240" as="sourcePoint" />
<mxPoint x="420" y="300" as="targetPoint" />
<Array as="points">
<mxPoint x="525" y="300" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-34" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-37">
<mxGeometry width="80" relative="1" as="geometry">
<mxPoint x="220" y="260" as="sourcePoint" />
<mxPoint x="320" y="300" as="targetPoint" />
<Array as="points">
<mxPoint x="220" y="300" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-37" value="&lt;div&gt;No&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="250" y="280" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-42" value="" style="edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-28" target="KwNStDcgQ-FNAQaH3l0E-72">
<mxGeometry width="80" relative="1" as="geometry">
<mxPoint x="260" y="430" as="sourcePoint" />
<mxPoint x="99" y="560" as="targetPoint" />
<Array as="points">
<mxPoint x="40" y="425" />
<mxPoint x="40" y="570" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-43" value="&lt;div&gt;Yes&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="240" y="405" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-65" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-45">
<mxGeometry relative="1" as="geometry">
<mxPoint x="120" y="585" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-46">
<mxGeometry relative="1" as="geometry">
<mxPoint x="120" y="670" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="KwNStDcgQ-FNAQaH3l0E-44">
<mxGeometry relative="1" as="geometry">
<mxPoint x="120" y="510" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.994;exitY=0.491;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-75" target="KwNStDcgQ-FNAQaH3l0E-107">
<mxGeometry relative="1" as="geometry">
<mxPoint x="760" y="445" as="targetPoint" />
<mxPoint x="730" y="580" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-78" target="KwNStDcgQ-FNAQaH3l0E-28">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-78" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="360" y="290" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-6" target="WIyWlLk6GJQsqaUBKTNV-7">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-83" value="&lt;div&gt;No&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="290" y="90" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-84" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Yes&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="170" y="140" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-86" value="opkg_commands always counts as a file to update" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="240" y="610" width="120" height="100" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-87" value="in case someone has changed the zone (which means changed the branch)" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="90" y="610" width="140" height="100" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-88" value="Update Json-configuration files) and the device controller firmware." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="370" y="610" width="180" height="100" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-89" value="Sync tariff-files and ini-files with local filesystem." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="560" y="610" width="160" height="100" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-90" value="Make sure the customer repository is in place and useable." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="20" y="110" width="140" height="95" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-91" value="&lt;b&gt;NEVER&lt;/b&gt; do any real update-steps without an active ISMAS trigger." style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="20" y="320" width="140" height="80" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-92" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Initial/repaired&lt;/div&gt;&lt;div&gt;clone&lt;/div&gt;&lt;div&gt;?&lt;br&gt;&lt;/div&gt;" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="585" y="375" width="100" height="100" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-96" value="SUCCESS" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="710" y="10" width="100" height="40" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-132" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-97" target="KwNStDcgQ-FNAQaH3l0E-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-97" value="&lt;div&gt;Send Last Version&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="580" y="100" width="110" height="30" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-99" value="No" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="450" y="400" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-103" value="No" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="580" y="330" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-104" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.15;entryY=0.4;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-92" target="KwNStDcgQ-FNAQaH3l0E-107">
<mxGeometry relative="1" as="geometry">
<mxPoint x="700" y="425" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-106" value="" style="group" vertex="1" connectable="0" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="50" y="540" width="770" height="57" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-72" value="&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; Checkout branch&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
<mxGeometry width="130" height="57" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-73" value="&lt;div&gt;Update files&lt;/div&gt;&lt;div&gt;(Json, DeviceController)&lt;br&gt;&lt;/div&gt;" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
<mxGeometry x="350" width="194" height="57" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-74" value="&lt;div&gt;Compute files &lt;br&gt;&lt;/div&gt;&lt;div&gt;to update&lt;br&gt;&lt;/div&gt;" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
<mxGeometry x="110" width="140" height="57" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-75" value="&lt;div&gt;(R)Sync with local&lt;/div&gt;&lt;div&gt;filesystem&lt;br&gt;&lt;/div&gt;" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
<mxGeometry x="520" width="170" height="57" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-105" value="&lt;div&gt;Exec&lt;/div&gt;&lt;div&gt;opkg-commands&lt;/div&gt;" style="shape=step;perimeter=stepPerimeter;fixedSize=1;points=[];whiteSpace=wrap;html=1;" vertex="1" parent="KwNStDcgQ-FNAQaH3l0E-106">
<mxGeometry x="230" width="140" height="57" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-107" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="750" y="415" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-109" value="&lt;div&gt;Yes&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="690" y="415" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-120" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-110" target="KwNStDcgQ-FNAQaH3l0E-97">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-110" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="625" y="180" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-129" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.95;entryY=0.95;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-92" target="KwNStDcgQ-FNAQaH3l0E-110">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-135" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-130" target="KwNStDcgQ-FNAQaH3l0E-96">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-130" value="&lt;div&gt;Send Last Version&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.5,0,0,0,0],[0.5,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="705" y="100" width="110" height="30" as="geometry" />
</mxCell>
<mxCell id="KwNStDcgQ-FNAQaH3l0E-131" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="KwNStDcgQ-FNAQaH3l0E-107" target="KwNStDcgQ-FNAQaH3l0E-130">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,594 @@
#include "git_client.h"
#include "update.h"
#include "worker.h"
#include "utils.h"
#include <QRegularExpression>
#include <QDebug>
#include <QDir>
#include <QStringList>
GitClient::GitClient(QString const &customerRepositoryPath,
QString const &customerNrStr,
QString const &customerRepository,
QString const &workingDirectory,
QString const &branchName,
QObject *parent)
: QObject(parent)
, m_worker(qobject_cast<Worker *>(parent))
, m_repositoryPath(customerRepositoryPath)
, 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;
}
bool GitClient::branchExistsRemotely() {
bool remoteBranchExists = false;
if (QDir(m_customerRepository).exists()) {
qInfo() << "BRANCH NAME" << m_branchName;
QString const cmd = QString("git ls-remote --exit-code --heads origin %1").arg(m_branchName);
Command c(cmd);
if (c.execute(m_customerRepository)) {
// expected result: c16c833c8778c1b3691a74afee5a469177e4e69b refs/heads/zg1/zone1000
QString const s = c.getCommandResult().trimmed();
if (!s.isEmpty()) {
// the result is only one line
if ((remoteBranchExists = s.contains(m_branchName)) == true) {
qCritical() << "(" << __func__ << ":" << __LINE__ << ") branch"
<< m_branchName << "EXISTS REMOTELY. (" << s << ")";
}
} else {
Utils::printCriticalErrorMsg(QString("EMPTY RESULT FOR CMD %1").arg(cmd));
}
} else {
Utils::printCriticalErrorMsg(QString("FAILED TO EXEC '%1'").arg(cmd));
}
}
return remoteBranchExists;
}
bool GitClient::branchExistsLocally() {
Command c("git branch -l");
if (c.execute(m_customerRepository)) {
QString const s = c.getCommandResult().trimmed();
if (!s.isEmpty()) {
QStringList lines = Update::split(s, '\n');
if (!lines.empty()) {
for (int i=0; i < lines.size(); ++i) {
QString line = lines.at(i);
// expected: * [new branch] zg1/zone12 -> origin/zg1/zone12"
if (line.contains(m_branchName)) {
if (m_worker) {
QStringList lst(QString("BRANCH-NAME %1 CONTAINED IN RESULT %2").arg(m_branchName).arg(s));
m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::PULL_NEW_BRANCH;
}
return true;
}
}
if (m_worker) {
QStringList lst(QString("BRANCH-NAME %1 NOT CONTAINED IN RESULT %2").arg(m_branchName).arg(s));
m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::PULL_NEW_BRANCH_FAILURE;
}
} else {
if (m_worker) {
QStringList lst(QString("'git branch -l' RETURNED NO LINES"));
m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::PULL_NEW_BRANCH_FAILURE;
}
}
} else {
if (m_worker) {
QStringList lst(QString("'git branch -l' RETURNED EMPTY RESULT"));
m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::PULL_NEW_BRANCH_FAILURE;
}
}
} else {
if (m_worker) {
QStringList lst(QString("FAILED TO EXEC 'git branch -l'"));
m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::PULL_NEW_BRANCH_FAILURE;
}
}
return false;
}
bool GitClient::gitPullNewBranches() {
if (QDir(m_customerRepository).exists()) {
Command c("git pull");
if (c.execute(m_customerRepository)) {
QString const s = c.getCommandResult().trimmed();
// expected: Already up-to-date.
if (!s.isEmpty()) {
QStringList lst;
QString msg(QString("GIT-PULL-NEW-BRANCH. RESULT=%1").arg(s));
if (m_worker) {
m_worker->CONSOLE(lst) << Worker::UPDATE_STEP::PULL_NEW_BRANCH;
}
return true;
}
}
}
return false;
}
/*
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;
#if 0
IMPORTANT COMMENT:
If remote host keys are changed, then
export GIT_SSH_COMMAND="ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig"
git pull
leads to the following warning/error message:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:vOD5jF2hglGktqLhK9ABxfEjwEgIK68/v9erdT05NDQ.
Please contact your system administrator.
Add correct host key in /home/root/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/root/.ssh/known_hosts:1
Password authentication is disabled to avoid man-in-the-middle attacks.
Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.
Agent forwarding is disabled to avoid man-in-the-middle attacks.
X11 forwarding is disabled to avoid man-in-the-middle attacks.
Already up to date.
This first part is from ssh itself. Only the last line is the git message.
Here an output of running ATBUpdateTool with a corrupted known-hosts-file:
...
Oct 23 14:18:18 ATB_PTU5 ATBUpdateTool[2696]: ( branchExistsRemotely : 310 ) branch "zg1/zone1" EXISTS REMOTELY. ( "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\nIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\r\nSomeone could be eavesdropping on you right now (man-in-the-middle attack)!\r\nIt is also possible that a host key has just been changed.\r\nThe fingerprint for the ECDSA key sent by the remote host is\nSHA256:vOD5jF2hglGktqLhK9ABxfEjwEgIK68/v9erdT05NDQ.\r\nPlease contact your system administrator.\r\nAdd correct host key in /home/root/.ssh/known_hosts to get rid of this message.\r\nOffending ECDSA key in /home/root/.ssh/known_hosts:1\r\nPassword authentication is disabled to avoid man-in-the-middle attacks.\r\nKeyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.\r\nAgent forwarding is disabled to avoid man-in-the-middle attacks.\r\nX11 forwarding is disabled to avoid man-in-the-middle attacks.\r\nbd4e8da4780b1a7d6be3d3ce8419f43ccf7e706f\trefs/heads/zg1/zone1" )
Oct 23 14:18:18 ATB_PTU5 ATBUpdateTool[2696]: EXECUTED "git branch -l" "(runtime 16ms)" with code 0 IN "/opt/app/tools/atbupdate/customer_336"
Oct 23 14:18:18 ATB_PTU5 ATBUpdateTool[2696]: "UPDATE_STEP::PULL_NEW_BRANCH"
Oct 23 14:18:18 ATB_PTU5 ATBUpdateTool[2696]: "BRANCH-NAME zg1/zone1 CONTAINED IN RESULT master\n* zg1/zone1" .....
The download continues.
#endif
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
//
// More exactly:
// remote: Counting objects: 382, done.
// remote: Compressing objects: 100% (203/203), done.
// remote: Total 278 (delta 177), reused 103 (delta 59)
// Receiving objects: 100% (278/278), 4.89 MiB | 539 KiB/s, done.
// Resolving deltas: 100% (177/177), completed with 40 local objects.
// From ssh://longair@pacific.mpi-cbg.de/srv/git/fiji
// 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030
// * [new branch] debian-release-20081112 -> origin/debian-release-20081112
// * [new branch] debian-release-20081112.1 -> origin/debian-release-20081112.1
// 3d619e7..6260626 master -> origin/master
//
// The most important bits here are the lines like these:
//
// 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030
// * [new branch] debian-release-20081112 -> origin/debian-release-20081112
//
// The first line of these two shows that your remote-tracking branch
// origin/debian-release-20081030 has been advanced from the commit 3036acc to 9eb5e40.
// The bit before the arrow is the name of the branch in the remote repository.
// The second line similarly show that since we last did this, a new remote tracking
// branch has been created. (git fetch may also fetch new tags if they have appeared
// in the remote repository.)
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")
//}

View File

@ -22,7 +22,8 @@ class GitClient : public QObject {
bool copyGitConfigFromMaster();
public:
explicit GitClient(QString const &customerNrStr,
explicit GitClient(QString const &customerRepositoryUrl,
QString const &customerNrStr,
QString const &repositoryPath,
QString const &workingDirectory = QCoreApplication::applicationDirPath(),
QString const &branchName = "master",
@ -43,16 +44,24 @@ class GitClient : public QObject {
bool gitCloneAndCheckoutBranch();
std::optional<QString> gitFetch();
bool gitFetchAndDiff();
bool gitPull();
Worker *worker() { return m_worker; }
Worker const *worker() const { return m_worker; }
std::optional<QString> gitPull();
std::optional<QStringList> gitDiff(QString const &commit);
std::optional<QStringList> gitMerge();
bool gitFsck();
QString gitLastCommit(QString fileName);
QString gitBlob(QString fileName);
QStringList gitShowReason(QString branchName);
static QString gitBlob(QString fileName);
QString gitCommitForBlob(QString blob);
bool gitIsFileTracked(QString file2name);
bool branchExistsRemotely();
bool branchExistsLocally();
bool gitPullNewBranches();
};
#endif // GIT_CLIENT_H_INCLUDED

View File

@ -1,4 +1,5 @@
#include "ismas/ismas_client.h"
#include "utils.h"
#include <cstring>
#include <cstdio>
@ -22,6 +23,15 @@
#include <QJsonObject>
#if 0
########################
# Spec vom 27.10.2023:
# U0010 -> %-Werte
# U0001 -> 100%
# U0003 -> "FAIL"
# U0002 -> "" (OK -> WAIT state reset)
# ISMAS -> "WAIT"
########################
#
# $1: EVENT: U0001 update finished: 100%
# U0002 reset TRG
# U0003 error
@ -46,6 +56,12 @@ void IsmasClient::printDebugMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
#if 0
Q_UNUSED(port);
Q_UNUSED(clientIP);
Q_UNUSED(clientPort);
Q_UNUSED(message);
#else
qDebug().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
@ -54,12 +70,19 @@ void IsmasClient::printDebugMessage(int port,
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
#endif
}
void IsmasClient::printInfoMessage(int port,
QString const &clientIP,
int clientPort,
QString const &message) {
#if 0
Q_UNUSED(port);
Q_UNUSED(clientIP);
Q_UNUSED(clientPort);
Q_UNUSED(message);
#else
qInfo().noquote()
<< "\n"
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
@ -68,6 +91,7 @@ void IsmasClient::printInfoMessage(int port,
<< "local address ..." << clientIP << "\n"
<< "local port ......" << clientPort << "\n"
<< message;
#endif
}
void IsmasClient::printErrorMessage(int port,
@ -137,7 +161,12 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
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;
@ -151,24 +180,56 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
int loop = 0;
int bytesWritten = 0;
while (bytesWritten < bytesToWrite) {
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
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("WRITE INTERRUPTED BY SIGNAL (1) (") + strerror(errno) + ")");
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;
}
}
}
}
@ -180,7 +241,7 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
// QString("CANNOT CLOSE WRITING END (") + strerror(errno) + ")");
// }
printInfoMessage(port, clientIP, clientPort, QString("MESSAGE SENT ") + buf);
printInfoMessage(port, clientIP, clientPort, QString("MESSAGE SENT <<<") + buf + ">>>");
loop = 0;
bzero(buf, sizeof(buf));
@ -188,37 +249,73 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
int bytesRead = 0;
while (bytesRead < bytesToRead) {
errno = 0;
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) + ")");
::close(sockfd);
return std::nullopt;
} else
if (n < 0) {
if (errno == EWOULDBLOCK) {
if (++loop < 10) {
QThread::msleep(500);
continue;
}
printErrorMessage(port, clientIP, clientPort,
QString("READ TIMEOUT %1(").arg(loop) + strerror(errno) + ")");
::close(sockfd);
return std::nullopt;
}
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);
// printInfoMessage(port, clientIP, clientPort, QString("MESSAGE RECEIVED ") + buf);
QString response(buf);
if (int idx = response.indexOf("{\"error\":\"ISMAS is offline\"}")) {
@ -245,8 +342,11 @@ IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
return std::nullopt;
}
} else {
printDebugMessage(port, clientIP, clientPort,
QString("PARSE ERROR ") + response + " " + parseError.errorString());
if (!response.contains("RECORD")) {
// maybe APISM does not send valid JSON: "RECORD SAVED" etc.
printDebugMessage(port, clientIP, clientPort,
QString("PARSE ERROR ") + response + " " + parseError.errorString());
}
::close(sockfd);
return std::nullopt;
}
@ -263,7 +363,19 @@ QString IsmasClient::updateNewsToIsmas(char const *event,
char buf[1024];
memset(buf, 0, sizeof(buf));
QString const ts = QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
QDateTime const local(QDateTime::currentDateTime());
QDateTime utc(local);
utc.setTimeSpec(Qt::UTC);
int const diff = (int)local.secsTo(utc); // diff between UTC and local time
QTime t(0, 0, 0);
t = t.addSecs((uint)diff);
QString const st(QString("%1%2").arg(diff < 0 ? "-" : "+").arg(t.toString("hh:mm")));
QString const ts(local.toString(Qt::ISODateWithMs) + st);
snprintf(buf, sizeof(buf)-1,
"{"
"\"REASON\":\"SW_UP\","
@ -287,22 +399,24 @@ QString IsmasClient::errorBackendNotConnected(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
RESULT_CODE::INSTALL_ERROR,
RESULT_CODE::ISMAS_NO_CONNECTION_ERROR,
"CHECK BACKEND CONNECTIVITY",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::errorGitClone(int percent, QString const &info, QString const &version) {
QString IsmasClient::errorGitClone(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0003",
percent,
RESULT_CODE::INSTALL_ERROR,
m_progressInPercent,
RESULT_CODE::GIT_CLONE_ERROR,
"CLONE CUSTOMER REPOSITORY FAILED",
info.toStdString().c_str(),
version.toStdString().c_str());
}
QString IsmasClient::backendConnected(QString const &info, QString const &version) {
QString IsmasClient::backendConnected(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
@ -311,7 +425,8 @@ QString IsmasClient::backendConnected(QString const &info, QString const &versio
version.toStdString().c_str());
}
QString IsmasClient::execOpkgCommand(QString const &info, QString const &version) {
QString IsmasClient::execOpkgCommand(QString const &info,
QString const &version) {
return updateNewsToIsmas("U0010",
m_progressInPercent,
RESULT_CODE::SUCCESS,
@ -320,6 +435,15 @@ QString IsmasClient::execOpkgCommand(QString const &info, QString const &version
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,
@ -333,7 +457,7 @@ QString IsmasClient::updateTriggerSet(QString const &info, QString const &versio
QString IsmasClient::errorUpdateTrigger(QString const &info, QString const &version) {
return updateNewsToIsmas("U0003",
m_progressInPercent,
RESULT_CODE::INSTALL_ERROR,
RESULT_CODE::ISMAS_TRIGGER_ERROR,
"CHECK UPDATE TRIGGER",
info.toStdString().c_str(),
version.toStdString().c_str());
@ -345,13 +469,11 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
static char buf[4096*2];
memset(buf, 0, sizeof(buf));
QString const ts = QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
QString sendVersionHash = "N/A";
// local data="#M=APISM#C=CMD_SENDVERSION#J=
snprintf(buf, sizeof(buf)-1,
"{"
"\"VERSION_INFO\" : {"
"\"REASON\":\"%s\","
"\"CREATED\":\"%s\","
"\"HASH\":\"%s\""
"},"
@ -361,6 +483,13 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
"\"ZONE\" : %d,"
"\"INFO\" : \"%s\","
"\"BLOB\" : \"%s\","
"\"LAST-COMMIT\" : \"%s\","
"\"SIZE\" : %d,"
"\"LOADED\" : \"%s\""
"},"
"\"OPKG_COMMANDS\" : {"
"\"BLOB\" : \"%s\","
"\"LAST-COMMIT\" : \"%s\","
"\"SIZE\" : %d,"
"\"LOADED\" : \"%s\""
"},"
@ -529,10 +658,14 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
"}"
"},"
"\"SOFTWARE\": {"
"\"RAUC\" : \"%s\","
"\"OPKG\" : \"%s\","
"\"APISM\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"ATBQT\" : {"
"\"VERSION\" : \"%s\""
"},"
"\"ATB-UPDATE-TOOL\" : {"
"\"VERSION\" : \"%s\""
"}"
"},"
"\"PLUGINS\" : {"
@ -557,19 +690,27 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
"\"libTCP_ZVT_CCPlugin.so\" : {"
"\"VERSION\" : \"%s\""
"}"
"}"
"},"
"\"PTU-PACKAGE-VERSIONS\" : %s"
"}",
ts.toStdString().c_str(),
sendVersionHash.toStdString().c_str(),
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(),
@ -651,9 +792,9 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
psa.dc.gitBlob.toStdString().c_str(),
psa.dc.gitLastCommit.toStdString().c_str(),
psa.sw.raucVersion.toStdString().c_str(),
psa.sw.opkgVersion.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(),
@ -661,12 +802,160 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
psa.pluginVersion.mobilisisCalculatePriceConfigUi.toStdString().c_str(),
psa.pluginVersion.prmCalculatePrice.toStdString().c_str(),
psa.pluginVersion.prmCalculatePriceConfigUi.toStdString().c_str(),
psa.pluginVersion.tcpZVT.toStdString().c_str());
psa.pluginVersion.tcpZVT.toStdString().c_str(),
psa.ptuPackageVersion.toStdString().c_str());
qInfo() << buf;
return buf;
}
#if 0
// prepare
QString IsmasClient::sendLastVersion(UPDATE_COMPONENT updateComponent,
PSAInstalled const &psa) {
static char buf[4096*2];
memset(buf, 0, sizeof(buf));
switch (updateComponent) {
case UPDATE_COMPONENT::TARIFF:
snprintf(buf, sizeof(buf)-1,
"{"
"\"VERSION_INFO\" : {"
"\"UPDATE_REASON\":\"%s\","
"\"CREATED\":\"%s\","
"\"GIT_COMMIT\":\"%s\""
"},"
"\"TARIFF\" : {"
"\"VERSION\" : \"%s\","
"\"PROJECT\" : \"%s\","
"\"ZONE\" : %d,"
"\"INFO\" : \"%s\","
"\"SIZE\" : %d\""
"},"
"}",
psa.tariff.versionInfo.reason.toStdString().c_str(),
psa.tariff.versionInfo.created.toStdString().c_str(),
psa.tariff.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.size);
break;
case UPDATE_COMPONENT::SOFTWARE_ATBQT:
break;
case UPDATE_COMPONENT::SOFTWARE_APISM:
break;
case UPDATE_COMPONENT::SOFTWARE_ATB_UPDATE_TOOL:
break;
case UPDATE_COMPONENT::CONFIG_PTU5_CPU_SERIAL:
break;
case UPDATE_COMPONENT::CONFIG_DEVICE_CONTROLLER:
break;
case UPDATE_COMPONENT::CONFIG_PRINTER:
break;
case UPDATE_COMPONENT::CONFIG_BNA:
break;
case UPDATE_COMPONENT::PLUGIN_ATB_DEVICE_CONTROLLER:
break;
case UPDATE_COMPONENT::PLUGIN_INGENICO_CC:
break;
case UPDATE_COMPONENT::PLUGIN_MOBILISIS_CALC_PRICE:
break;
case UPDATE_COMPONENT::PLUGIN_MOBILISIS_CALC_PRICE_UI:
break;
case UPDATE_COMPONENT::PLUGIN_PRM_CALC_PRICE:
break;
case UPDATE_COMPONENT::PLUGIN_PRM_CALC_PRICE_UI:
break;
case UPDATE_COMPONENT::PLUGIN_TCP_ZVT_CC:
break;
case UPDATE_COMPONENT::OPKG_COMMANDS:
break;
case UPDATE_COMPONENT::HARDWARE_DEVICES:
break;
case UPDATE_COMPONENT::OS:
break;
case UPDATE_COMPONENT::DC2C_CASH_JSON:
break;
case UPDATE_COMPONENT::DC2C_CONF_JSON:
break;
case UPDATE_COMPONENT::DC2C_DEVICE_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT01_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT02_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT03_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT04_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT05_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT06_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT07_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT08_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT09_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT10_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT11_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT12_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT13_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT14_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT15_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT16_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT17_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT18_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT19_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT20_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT21_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT22_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT23_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT24_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT25_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT26_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT27_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT28_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT29_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT30_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT31_JSON:
break;
case UPDATE_COMPONENT::DC2C_PRINT32_JSON:
break;
}
qInfo() << buf;
return buf;
}
#endif
QString IsmasClient::updateOfPSAContinues(QString currentStage,
QString currentStageInfo,
@ -735,7 +1024,7 @@ QString IsmasClient::updateOfPSAActivated(QString const &version) { // sent ev
}
QString IsmasClient::updateOfPSASucceeded(QString const &version) {
m_progressInPercent = 0;
m_progressInPercent = 100;
return updateNewsToIsmas("U0001",
m_progressInPercent,
RESULT_CODE::SUCCESS,
@ -762,14 +1051,21 @@ QString IsmasClient::jsonParseFailed(int resultCode, QString reason, QString con
version.toStdString().c_str());
}
std::optional<QString> IsmasClient::finalResult(int resultCode, QString reason, QString const &version) {
m_progressInPercent = 0;
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,
RESULT_CODE::SUCCESS,
resultCode,
"FINAL-UPDATE-RESULT",
"(re-)set WAIT state",
reason.toStdString().c_str(),
version.toStdString().c_str());
}
if (resultCode == RESULT_CODE::INSTALL_ERROR) {
@ -780,6 +1076,7 @@ std::optional<QString> IsmasClient::finalResult(int resultCode, QString reason,
reason.toStdString().c_str(),
version.toStdString().c_str());
}
*/
return std::nullopt;
}
@ -792,3 +1089,18 @@ QString IsmasClient::updateOfPSAFailed(int resultCode, QString step,
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];
}

View File

@ -7,7 +7,14 @@
#include <optional>
struct PSAInstalled {
struct VersionInfo {
QString created;
QString reason;
QString lastCommit;
} versionInfo;
struct Tariff {
// VersionInfo versionInfo;
QString name;
QString version;
QString project;
@ -24,7 +31,16 @@ struct PSAInstalled {
QString cpuSerial;
} hw;
struct Opkg {
// VersionInfo versionInfo;
int size;
QString blob;
QString lastCommit;
QString loadTime;
} opkg;
struct DC {
// VersionInfo versionInfo;
QString versionHW;
QString versionSW;
QString gitBlob;
@ -33,9 +49,9 @@ struct PSAInstalled {
} dc;
struct SoftWare {
QString raucVersion;
QString opkgVersion;
QString apismVersion;
QString atbQTVersion;
QString atbUpdateToolVersion;
} sw;
struct PluginVersion {
@ -49,6 +65,7 @@ struct PSAInstalled {
} pluginVersion;
struct DC2C {
// VersionInfo versionInfo;
QString name;
QString blob;
int size;
@ -60,6 +77,8 @@ struct PSAInstalled {
DC2C print[32];
QString ptuPackageVersion;
explicit PSAInstalled() {
tariff.name = "N/A";
tariff.version = "N/A";
@ -73,15 +92,20 @@ struct PSAInstalled {
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.raucVersion = "N/A";
sw.opkgVersion = "N/A";
sw.apismVersion = "N/A";
sw.atbQTVersion = "N/A";
sw.atbUpdateToolVersion = "N/A";
pluginVersion.deviceController = "N/A";
pluginVersion.ingenicoISelfCC = "N/A";
@ -125,14 +149,60 @@ public:
enum RESULT_CODE {
SUCCESS=0,
// if between 00:00 - 04:00 Wait-button state not WAIT, then we assume
// that's an automatic nightly (not-necessary) update
NO_UPDATE_NECESSARY=1,
BACKUP_FAILED=2,
WRONG_PACKAGE=3,
INSTALL_ERROR=4};
// if APISM reports the ISMAS is not available (15x, 6s delay each)
ISMAS_NO_CONNECTION_ERROR=2,
// if not within 00:00-04:00 and WAIT-button was not in state WAIT
ISMAS_TRIGGER_ERROR=3,
// cloning git repo. not possible
GIT_CLONE_ERROR=4,
// pulling from remote git server not possible
GIT_PULL_ERROR=5,
// fetching from remote git server not possible
GIT_FETCH_ERROR=6,
// merging fetched data not possible
GIT_MERGE_ERROR=7,
// check sanity of local customer-repository failed
GIT_CHECK_REPOSITORY_ERROR=8,
// switch/checkout of branch (i.e. zone) on error
GIT_SWITCH_BRANCH_ERROR=9,
// fetch/pull of new branch failed. the new branch was not available
// when installing via SD-card followed by intial clone during the
// update process.
GIT_FETCH_NEW_BRANCH_ERROR=10,
// error computing git-blob hash-value
GIT_HASH_ERROR=11,
// update for general json files failed.
JSON_FILES_UPDATE_ERROR=12,
// error downloading config-json-files to device controller
JSON_FILES_DOWNLOAD_ERROR=13,
// error downloading device-controller
DC_DOWNLOAD_ERROR=14,
// error rsyncing json/ini-files to local filesystem
RSYN_ERROR=15,
// HASH_VALUE_ERROR=14,
// HW_COMPATIBILITY_ERROR=15,
OPKG_COMMANDS_ERROR=16,
// CLEANUP_ERROR=18,
UPDATE_IN_ERROR_STATE=99
};
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; }
@ -147,12 +217,13 @@ public:
QString cloneAndCheckoutCustomerRepository(QString const &info, QString const &version = QString()); // clone and checkout customer repository
QString checkoutBranch(QString const &info, QString const &version = QString()); // checkout branch
QString errorBackendNotConnected(QString const &info, QString const &version = QString()); // checkout branch
QString errorGitClone(int percent, QString const &info, QString const &version = QString());
QString errorGitClone(QString const &info, QString const &version = QString());
QString backendConnected(QString const &info, QString const &version = QString());
QString updateTriggerSet(QString const &info, QString const &version = QString());
QString errorUpdateTrigger(QString const &info, QString const &version = QString());
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
@ -163,8 +234,68 @@ public:
QString jsonParseFailed(int resultCode, QString reason, QString const &version = QString());
std::optional<QString> finalResult(int resultCode, QString reason, QString const &version = QString());
// legacy
QString updateOfPSASendVersion(PSAInstalled const &psa);
#if 0
enum class UPDATE_COMPONENT {
TARIFF,
SOFTWARE_ATBQT,
SOFTWARE_APISM,
SOFTWARE_ATB_UPDATE_TOOL,
CONFIG_PTU5_CPU_SERIAL,
CONFIG_DEVICE_CONTROLLER,
CONFIG_PRINTER,
CONFIG_BNA,
PLUGIN_ATB_DEVICE_CONTROLLER,
PLUGIN_INGENICO_CC,
PLUGIN_MOBILISIS_CALC_PRICE,
PLUGIN_MOBILISIS_CALC_PRICE_UI,
PLUGIN_PRM_CALC_PRICE,
PLUGIN_PRM_CALC_PRICE_UI,
PLUGIN_TCP_ZVT_CC,
OPKG_COMMANDS,
HARDWARE_DEVICES,
OS,
DC2C_CASH_JSON,
DC2C_CONF_JSON,
DC2C_DEVICE_JSON,
DC2C_PRINT01_JSON,
DC2C_PRINT02_JSON,
DC2C_PRINT03_JSON,
DC2C_PRINT04_JSON,
DC2C_PRINT05_JSON,
DC2C_PRINT06_JSON,
DC2C_PRINT07_JSON,
DC2C_PRINT08_JSON,
DC2C_PRINT09_JSON,
DC2C_PRINT10_JSON,
DC2C_PRINT11_JSON,
DC2C_PRINT12_JSON,
DC2C_PRINT13_JSON,
DC2C_PRINT14_JSON,
DC2C_PRINT15_JSON,
DC2C_PRINT16_JSON,
DC2C_PRINT17_JSON,
DC2C_PRINT18_JSON,
DC2C_PRINT19_JSON,
DC2C_PRINT20_JSON,
DC2C_PRINT21_JSON,
DC2C_PRINT22_JSON,
DC2C_PRINT23_JSON,
DC2C_PRINT24_JSON,
DC2C_PRINT25_JSON,
DC2C_PRINT26_JSON,
DC2C_PRINT27_JSON,
DC2C_PRINT28_JSON,
DC2C_PRINT29_JSON,
DC2C_PRINT30_JSON,
DC2C_PRINT31_JSON,
DC2C_PRINT32_JSON,
};
QString sendLastVersion(UPDATE_COMPONENT comp, PSAInstalled const &psa);
#endif
private:
static void printDebugMessage(int port, QString const &clientIP, int clientPort,
QString const &message);

203
UpdatePTUDevCtrl/main.cpp Normal file
View File

@ -0,0 +1,203 @@
#include <QCoreApplication>
#include <QApplication>
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
#ifdef __linux__
#include <stdlib.h> // system()
#endif
#include "message_handler.h"
#include <DeviceController/interfaces.h>
#include "commandline_parser.h"
#include <unistd.h>
#include <memory>
#include <QSharedMemory>
#include <QRunnable>
#include <QThreadPool>
#include <QDir>
#include <QProcess>
#include <QCommandLineParser>
#include <QStandardPaths>
#include <QMainWindow>
#include <QSettings>
#include "update.h"
#include "git/git_client.h"
#include "ismas/ismas_client.h"
#include "worker_thread.h"
#include "worker.h"
#include "mainwindow.h"
#include "utils.h"
#include <QThread>
#include <QtWidgets>
#include <QScopedPointer>
#if defined (Q_OS_UNIX) || defined (Q_OS_LINUX)
#include <unistd.h>
#include <errno.h>
#endif
#ifdef PTU5
#define SERIAL_PORT "ttymxc2"
#else
#define SERIAL_PORT "ttyUSB0"
#endif
// argv[1]: file to send to dc
int main(int argc, char *argv[]) {
QByteArray const value = qgetenv("LC_ALL");
if (value.isEmpty() || value != "C") {
qputenv("LC_ALL", "C");
}
// qputenv("XDG_RUNTIME_DIR", "/var/run/user/0");
openlog("ATB-UPDATE", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
QApplication a(argc, argv);
QApplication::setApplicationName("ATBUpdateTool");
QApplication::setApplicationVersion(APP_VERSION);
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
atbInstallMessageHandler(nullptr);
//atbInstallMessageHandler(atbDebugOutput);
setDebugLevel(LOG_NOTICE);
}
CommandLineParser parser;
parser.process(a);
parser.readSettings();
QString repositoryUrl = parser.repositoryUrl();
if (repositoryUrl.endsWith('/')) {
repositoryUrl.chop(1);
}
QString gitSSHCommand("");
if (repositoryUrl.contains("ptu-config.atb-comm.de")) {
QByteArray const v = qgetenv("GIT_SSH_COMMAND");
if (v.isEmpty()) {
QString sshKeyFile("/opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig");
if (QFileInfo(sshKeyFile).exists()) {
gitSSHCommand = "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig";
if (!qputenv("GIT_SSH_COMMAND", QByteArray(gitSSHCommand.toStdString().c_str()))) {
qCritical() << "ERROR: GIT_SSH_COMMAND not put into env. Exiting...";
return -1;
}
} else {
qCritical() << "ERROR ssh-key-file" << sshKeyFile << "does not exists. Exiting...";
return -1;
}
} else {
gitSSHCommand = QString(v.toStdString().c_str());
qCritical() << "WARNING GIT_SSH_COMMAND already set in enviroment:"
<< gitSSHCommand;
if (gitSSHCommand != "ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig") {
qCritical() << "ERROR" << gitSSHCommand << "wrong. Exiting...";
return -1;
}
}
}
QString plugInDir = parser.plugInDir();
QString plugInName = parser.plugInName();
QString workingDir = parser.workingDir();
QString iniFileName = parser.iniFileName();
bool const dryRun = parser.dryRun();
bool const noUpdatePsaHardware = parser.noUpdatePsaHardware();
bool const showYoctoVersion = parser.yoctoVersion();
bool const showYoctoInstallStatus = parser.yoctoInstallStatus();
bool const showExtendedVersion = parser.extendedVersion();
bool const alwaysDownloadConfig = parser.alwaysDownloadConfig();
bool const alwaysDownloadDC = parser.alwaysDownloadDC();
QString const rtPath = QCoreApplication::applicationDirPath();
int const machineNr = Utils::read1stLineOfFile("/mnt/system_data/machine_nr");
int const customerNr = Utils::read1stLineOfFile("/mnt/system_data/cust_nr");
int const zoneNr = Utils::read1stLineOfFile("/mnt/system_data/zone_nr");
QString const branchName = (zoneNr != 0)
? QString("zg1/zone%1").arg(zoneNr) : "master";
qInfo() << "pwd ......................" << rtPath;
qInfo() << "repositoryUrl ............" << repositoryUrl;
if (!gitSSHCommand.isEmpty()) {
qInfo() << "GIT_SSH_COMMAND .........." << gitSSHCommand;
}
qInfo() << "plugInDir ................" << plugInDir;
qInfo() << "plugInName ..............." << plugInName;
qInfo() << "workingDir ..............." << workingDir;
qInfo() << "dryRun ..................." << dryRun;
qInfo() << "noUpdatePsaHardware ......" << noUpdatePsaHardware;
qInfo() << "alwaysDownloadConfig ....." << alwaysDownloadConfig;
qInfo() << "alwaysDownloadDC ........." << alwaysDownloadDC;
qInfo() << "showYoctoVersion ........." << showYoctoVersion;
qInfo() << "showYoctoInstallStatus ..." << showYoctoInstallStatus;
qInfo() << "showExtendedVersion ......" << showExtendedVersion;
qInfo() << "iniFileName .............." << iniFileName;
qInfo() << "extended-version ........." << APP_EXTENDED_VERSION;
qInfo() << "machineNr ................" << machineNr;
qInfo() << "customerNr ..............." << customerNr;
qInfo() << "zoneNr ..................." << zoneNr;
if (showExtendedVersion) {
printf(APP_EXTENDED_VERSION"\n");
return 0;
}
if (showYoctoVersion) {
printf("%s\n", Worker::getATBUpdateToolYoctoVersion().toStdString().c_str());
return 0;
}
if (showYoctoInstallStatus) {
printf("%s\n", Worker::getATBUpdateToolYoctoInstallationStatus().toStdString().c_str());
return 0;
}
QThread::currentThread()->setObjectName("main thread");
qInfo() << "Main thread" << QThread::currentThreadId();
if (!QDir(plugInDir).exists()) {
qCritical() << plugInDir
<< "does not exists, but has to contain dc-library";
if (noUpdatePsaHardware == false) {
exit(-1);
}
}
// before loading the library, delete all possible shared memory segments
#if defined Q_OS_LINUX || defined Q_OS_UNIX
// system("rm -rf /tmp/qipc*");
#else
#error "Only tested under UNIX/LINUX"
#endif
Worker worker(customerNr,
machineNr,
zoneNr,
repositoryUrl,
branchName,
plugInDir,
plugInName,
workingDir,
noUpdatePsaHardware,
alwaysDownloadConfig,
alwaysDownloadDC,
dryRun);
MainWindow mw(&worker);
worker.setMainWindow(&mw);
mw.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
mw.showFullScreen();
return a.exec();
}

View File

@ -0,0 +1,381 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
#include "utils.h"
#include "progress_event.h"
#include "update_dc_event.h"
#include <DeviceController/interfaces.h>
#include <QDateTime>
#include <QMessageBox>
#include <QDebug>
#include <QScrollBar>
#include <QEvent>
#include <QScreen>
MainWindow::MainWindow(Worker *worker, QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_worker(worker)
, m_width(70)
, m_progressRunning(false)
, m_updateStep(UpdateDcEvent::UpdateStep::NONE) {
this->setStatusBar(new QStatusBar(this));
QFont f;
f.setStyleHint(QFont::Monospace);
f.setWeight(QFont::Bold);
f.setFamily("Misc Fixed");
f.setPixelSize(12);
this->statusBar()->setFont(f);
ui->setupUi(this);
checkOrientation();
ui->updateProgress->setRange(0, 100);
ui->updateProgress->reset();
QStringList lst;
QString start = QDateTime::currentDateTime().toString(Qt::ISODate);
lst << QString("Start: ") + start.leftJustified(m_width-10);
lst << QString("").leftJustified(m_width-3, '=');
lst << QString("Update tool version: %1 - %2 %3").arg(APP_VERSION).arg(APP_BUILD_DATE).arg(APP_BUILD_TIME).leftJustified(m_width-3);
lst << QString("Machine number : %1 ").arg(m_worker->machineNr()).leftJustified(m_width-3);
lst << QString("Customer number : %1 ").arg(m_worker->customerNr()).leftJustified(m_width-3);
lst << QString("Zone number : %1 (%2)").arg(m_worker->zoneNr()).arg(Utils::zoneName(m_worker->zoneNr())).leftJustified(m_width-3);
lst << QString("APISM version : %1").arg(m_worker->apismVersion()).leftJustified(m_width-3);
lst << QString("").leftJustified(m_width-3, '=');
ui->updateStatus->setText(lst.join('\n'));
ui->updateStatus->setEnabled(true);
// ui->updateStatus->installEventFilter(this);
m_startTimer = new QTimer(this);
connect(m_startTimer, SIGNAL(timeout()), m_worker, SLOT(start()));
m_startTimer->setSingleShot(true);
m_startTimer->start(1000);
m_exitTimer = new QTimer(this);
connect(m_exitTimer, SIGNAL(timeout()), ui->exit, SLOT(click()));
m_exitTimer->setSingleShot(true);
m_exitTimer->start(1800 * 1000);
m_statusTimer = new QTimer(this);
if (m_statusTimer) {
connect(m_statusTimer, &QTimer::timeout, [this]() {
static QString p(".");
QTime const &t = QDateTime::currentDateTime().time();
QString s = t.toString(Qt::ISODate);
s += ": Update might take several minutes " + p;
if (p.length() >= 5) {
p = ".";
} else {
p += ".";
}
this->statusBar()->showMessage(s);
});
m_statusTimer->setSingleShot(false);
m_statusTimer->start(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 m_statusTimer;
delete ui;
}
// ----------------------------- Ui::LAYOUT setting -------------------------------------
void MainWindow::checkOrientation()
{
QScreen *screen = QGuiApplication::primaryScreen();
Qt::ScreenOrientation orientation = screen->orientation();
switch (orientation) {
case Qt::PrimaryOrientation:
this->setLandscapeLayout();
break;
case Qt::LandscapeOrientation:
this->setLandscapeLayout();
break;
case Qt::PortraitOrientation:
this->setPortraitLayout();
break;
case Qt::InvertedLandscapeOrientation:
this->setLandscapeLayout();
break;
case Qt::InvertedPortraitOrientation:
this->setPortraitLayout();
break;
}
this->currentOrientation = orientation;
}
void MainWindow::setPortraitLayout()
{
// Adjust layout for portrait mode (480x800)
this->setFixedSize(480, 800);
ui->centralwidget->setFixedSize(480, 800);
}
void MainWindow::setLandscapeLayout()
{
// Adjust layout for landscape mode (800x480)
this->setFixedSize(800, 480);
ui->centralwidget->setFixedSize(800, 480);
}
void MainWindow::customEvent(QEvent *event) {
if (event->type() == ProgressEvent::type()) {
ProgressEvent *pevent = (ProgressEvent *)event;
int const progress = pevent->progressPercent();
QObject const *sender = pevent->sender();
if (sender == this) {
switch(progress) {
case 0: {
ui->updateProgress->reset();
} break;
case START_PROGRESS_LOOP: {
m_progressRunning = true;
ui->updateProgress->reset();
// m_progressValue = 10;
QApplication::postEvent(this, new ProgressEvent(this, 1));
} break;
case STOP_PROGRESS_LOOP: {
m_progressRunning = false;
// m_progressValue -= 10;
// m_worker->setProgress(m_progressValue/10);
} break;
default: {
if (m_progressRunning) {
// m_progressValue = progress;
ui->updateProgress->setValue(progress);
// ueberpruefen: hauptfenster schickt sich selber ein event
// QApplication::postEvent(this, new ProgressEvent(this, progress));
// QThread::msleep(500);
}}
}
} else
if (sender == m_worker) {
switch(progress) {
case 0: {
ui->updateProgress->reset();
} break;
case START_PROGRESS_LOOP: {
QApplication::postEvent(this, new ProgressEvent(this, START_PROGRESS_LOOP));
} break;
case STOP_PROGRESS_LOOP: {
QApplication::postEvent(this, new ProgressEvent(this, STOP_PROGRESS_LOOP));
} break;
default:{
ui->updateProgress->setValue(progress);
}}
} else {
qCritical() << "!!! UNKNOWN SENDER !!!";
}
}
QThread::yieldCurrentThread();
}
void MainWindow::onStopStartTimer() {
m_startTimer->stop();
}
void MainWindow::onDisableExit() {
ui->exit->setEnabled(false);
}
void MainWindow::onEnableExit() {
ui->exit->setEnabled(true);
}
void MainWindow::onRestartExitTimer() {
m_exitTimer->stop();
m_exitTimer->start(5 * 1000);
scrollDownTextEdit();
ui->updateStatus->setEnabled(false);
}
void MainWindow::onQuit() {
m_exitTimer->stop();
int errorCode = 0;
qCritical()
<< QString("ON QUIT: CURRENT STEP %1")
.arg(m_worker->getSmap()[m_worker->currentStep()]);
// TODO: replace SEND_LAST_VERSION with UPDATE_SUCCEEDED
if (m_worker->currentStep() != Worker::UPDATE_STEP::SEND_LAST_VERSION) {
errorCode = -1;
}
qCritical() << QString("ON QUIT: EXIT CODE %1").arg(errorCode);
qApp->exit(errorCode);
}
void MainWindow::scrollDownTextEdit() {
// Utils::printInfoMsg(QString("SCROLL-DOWN-TEXT_EDIT CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
ui->updateStatus->setEnabled(true);
QTextCursor tmpCursor = ui->updateStatus->textCursor();
tmpCursor.movePosition(QTextCursor::End);
ui->updateStatus->setTextCursor(tmpCursor);
ui->updateStatus->ensureCursorVisible();
}
void MainWindow::onAppendText(QString text, QString suffix) {
// Utils::printInfoMsg(QString("ON APPEND CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
QString editText = ui->updateStatus->toPlainText();
scrollDownTextEdit();
if (!suffix.isNull() && suffix.size() > 0) {
//qInfo() << "TEXT" << text << "SUFFIX" << suffix;
if (suffix == Worker::UPDATE_STEP_SUCCESS || suffix == Worker::UPDATE_STEP_FAIL) {
ui->updateStatus->insertPlainText(QString("\n").leftJustified(m_width-3, '=') + " ");
// editText += QString("\n").leftJustified(m_width-3, '=');
// editText += " ";
}
QString const &add = (QString("\n") + text).leftJustified(m_width - (2 + suffix.size())) + suffix;
ui->updateStatus->insertPlainText(add);
// editText += add;
} else {
QString const &add = text.leftJustified(m_width-9);
ui->updateStatus->insertPlainText(add);
//editText += add;
}
// debug
// QString editText = ui->updateStatus->toPlainText();
// Utils::printLineEditInfo(editText.split('\n', QString::SplitBehavior::SkipEmptyParts));
// ui->updateStatus->setText(editText.trimmed());
scrollDownTextEdit();
}
void MainWindow::onReplaceLast(QStringList newTextLines, QString suffix) {
// Utils::printInfoMsg(QString("ON REPLACE LAST (LIST) CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
int const s = newTextLines.size();
if (s > 0) {
QString editText = ui->updateStatus->toPlainText();
QStringList lines = editText.split('\n', QString::SplitBehavior::SkipEmptyParts);
QString newText;
if (lines.size() >= s) {
for (int i = 0; i < s; ++i) {
lines.removeLast();
}
if (lines.size() > 0) {
newText = lines.join('\n');
newText += '\n';
}
QStringList newLines;
for (int i = 0; i < s; ++i) {
if (i == 0 && !suffix.isNull() && suffix.size() > 0 && suffix != "\n") {
newLines += Utils::rstrip(newTextLines.at(i).leftJustified(m_width-10) + suffix);
} else {
newLines += Utils::rstrip(newTextLines.at(i).leftJustified(m_width-10));
}
}
lines += newLines;
newText += newLines.join(' ');
}
ui->updateStatus->setText(newText);
Utils::printLineEditInfo(lines);
scrollDownTextEdit();
}
}
void MainWindow::onReplaceLast(QString text, QString suffix) {
// Utils::printInfoMsg(QString("ON REPLACE LAST (TEXT) CALLED AT ")
// + QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
QString editText = ui->updateStatus->toPlainText();
QStringList lines = editText.split('\n', QString::SplitBehavior::SkipEmptyParts);
if (lines.size() > 0) {
// removing the last line is really meant for refreshing the last line
// with a string very similar than the original one, typically only
// followed by a suffix.
if (lines.last().contains(text)) {
lines.removeLast();
}
if (!suffix.isNull() && suffix.size() > 0 && suffix != "\n") {
QString const add = text.leftJustified(m_width-10) + suffix;
if (!add.isEmpty()) {
lines += text.leftJustified(m_width-10) + suffix;
}
} else {
QString const add = text.leftJustified(m_width-10);
if (!add.isEmpty()) {
lines += text.leftJustified(m_width-10);
}
}
}
Utils::printLineEditInfo(lines);
ui->updateStatus->setText(lines.join('\n').trimmed());
scrollDownTextEdit();
}
void MainWindow::onShowMessage(QString title, QString text) {
this->statusBar()->clearMessage();
this->statusBar()->showMessage( // timeout: 10000
QString(title + " " + text).leftJustified(80, ' '), 10000);
}
void MainWindow::onShowErrorMessage(QString title, QString text) {
onShowMessage(title, text);
}
void MainWindow::onShowStatusMessage(QString title, QString text) {
onShowMessage(title, text);
}
void MainWindow::onShowErrorMessage(QStringList lst) {
if (lst.size() >= 2) {
onShowMessage(lst.at(0), lst.at(1));
}
if (lst.size() == 1) {
onShowMessage(lst.at(0), "");
}
}
void MainWindow::onShowStatusMessage(QStringList lst) {
if (lst.size() >= 2) {
onShowMessage(lst.at(0), lst.at(1));
}
if (lst.size() == 1) {
onShowMessage(lst.at(0), "");
}
}

View File

@ -0,0 +1,84 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include <QStatusBar>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
#include "worker.h"
#include "update.h"
#include "update_dc_event.h"
#define EMERGENCY_LEAVE_BL 0
class hwinf;
class MainWindow : public QMainWindow {
Q_OBJECT
protected:
void customEvent(QEvent *event) override;
public:
MainWindow(Worker *worker, QWidget *parent = nullptr);
~MainWindow();
static const int START_PROGRESS_LOOP = -1;
static const int STOP_PROGRESS_LOOP = -2;
static const int BL_START_COUNT = 5;
static const int BL_CHECK_COUNT = 5;
static const int BL_IS_UP_COUNT = 5;
static const int BL_STOP_COUNT = 5;
UpdateDcEvent::UpdateStep updateStep() const { return m_updateStep; }
void setUpdateStep(UpdateDcEvent::UpdateStep updateStep) { m_updateStep = updateStep; }
public slots:
void onAppendText(QString, QString suffix = "");
void onReplaceLast(QStringList, QString suffix = "");
void onReplaceLast(QString, QString suffix = "");
void onShowErrorMessage(QString, QString);
void onShowStatusMessage(QString, QString);
void onShowErrorMessage(QStringList);
void onShowStatusMessage(QStringList);
void onStopStartTimer();
void onRestartExitTimer();
void onEnableExit();
void onDisableExit();
#if EMERGENCY_LEAVE_BL==1
void emergencyLeaveBL();
#endif
signals:
#if EMERGENCY_LEAVE_BL==1
void leaveBL();
#endif
private slots:
void onQuit();
private:
void scrollDownTextEdit();
void onShowMessage(QString, QString);
Ui::MainWindow *ui;
void checkOrientation();
void setPortraitLayout();
void setLandscapeLayout();
Qt::ScreenOrientation currentOrientation;
Worker *m_worker;
int const m_width;
QTimer *m_startTimer;
QTimer *m_exitTimer;
bool m_progressRunning;
//int m_progressValue;
UpdateDcEvent::UpdateStep m_updateStep;
QTimer *m_statusTimer;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,73 @@
<?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="minimumSize">
<size>
<width>480</width>
<height>480</height>
</size>
</property>
<property name="font">
<font>
<family>Source Code Pro</family>
</font>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<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>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

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

View File

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

View File

@ -0,0 +1,124 @@
#include "command.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QRegularExpression>
#include <QDateTime>
Command::Command(QString const &command, int start_timeout, int finish_timeout)
: m_command(command.trimmed())
, m_commandResult("")
, m_waitForStartTimeout(start_timeout)
, m_waitForFinishTimeout(finish_timeout)
, m_exitCode(-1) {
}
QString Command::getCommandResult() const {
return m_commandResult;
}
void Command::readyReadStandardOutput() {
QProcess *p = (QProcess *)sender();
m_commandResult += p->readAllStandardOutput();
// qCritical() << m_commandResult;
}
void Command::readyReadStandardError() {
QProcess *p = (QProcess *)sender();
QByteArray buf = p->readAllStandardError();
qCritical() << buf;
}
void Command::finished(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) {
QProcess *p = (QProcess *)sender();
// read all remaining data sent to the process, just in case
QString d = p->readAllStandardOutput();
if (!d.isEmpty()) {
m_commandResult += d;
}
disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardOutput()));
disconnect(p, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(readyReadStandardError()));
}
bool Command::execute(QString workingDirectory, QStringList args) {
if (!QDir::setCurrent(workingDirectory)) {
qCritical() << "SET WORKING_DIRECTORY" << workingDirectory
<< "FAILED FOR" << m_command;
return false;
}
QScopedPointer<QProcess> p(new QProcess(this));
p->setWorkingDirectory(workingDirectory);
p->setProcessChannelMode(QProcess::MergedChannels);
connect(&(*p), SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
connect(&(*p), SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
if (!args.isEmpty()) {
//qDebug() << "START COMMAND" << m_command << "WITH ARGS" << args
// << "IN" << p->workingDirectory();
p->start(m_command, args);
} else {
//qDebug() << "START COMMAND" << m_command
// << "IN" << p->workingDirectory();
p->start(m_command);
}
qint64 const start = QDateTime::currentDateTime().toMSecsSinceEpoch();
if (p->waitForStarted(m_waitForStartTimeout)) {
// qDebug() << "PROCESS" << m_command << "STARTED IN" << p->workingDirectory();
if (p->state() == QProcess::ProcessState::Running) {
// qDebug() << "PROCESS" << m_command << "RUNNING IN" << p->workingDirectory();
// wait forever for git/opkg-commands to finish
int wait = m_waitForFinishTimeout;
if (m_command.trimmed().startsWith("git", Qt::CaseInsensitive) ||
m_command.trimmed().startsWith("opkg", Qt::CaseInsensitive)) {
wait = -1;
}
bool const no_timeout = p->waitForFinished(wait);
if (no_timeout) {
// qDebug() << "PROCESS" << m_command << "FINISHED IN" << p->workingDirectory();
if (p->exitStatus() == QProcess::NormalExit) {
if ((m_exitCode = p->exitCode()) == 0) {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qDebug() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
return true;
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "EXECUTED" << m_command
<< QString("(runtime %1ms)").arg(end-start)
<< "with code" << m_exitCode
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "CRASHED with code"
<< p->exitCode()
<< QString("(after %1ms)").arg(end-start)
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command
<< "DID NOT FINISH WITH" << wait
<< "MS IN" << p->workingDirectory()
<< QString("(runtime %1ms)").arg(end-start);
}
} else {
qCritical() << "WRONG PROCESS STATE" << p->state()
<< "IN" << p->workingDirectory();
}
} else {
qint64 const end = QDateTime::currentDateTime().toMSecsSinceEpoch();
qCritical() << "PROCESS" << m_command << "TIMEOUT AT START"
<< QString("(runtime %1ms)").arg(end-start)
<< "IN" << p->workingDirectory();
}
return false;
}

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);
};

Some files were not shown because too many files have changed in this diff Show More