Compare commits

..

153 Commits

Author SHA1 Message Date
2cd73aaa86 Add interface methods startPhysicalLayer() / stopPhysicalLayer() 2023-06-30 10:41:12 +02:00
37d45f3c69 Serial port name is object variable 2023-06-30 10:39:24 +02:00
f76a30cb07 Increase timeout for 'onCashPayStopedSuccess()' to 2,5s 2023-06-28 10:55:49 +02:00
2b6eecfed7 Fix: Debug output 2023-06-27 16:11:34 +02:00
7be678fbe0 Print: increase waittime for printerDataPrepared() 2023-06-27 16:11:04 +02:00
6e9b1018e5 Add/Implemnt additional printer methods (using templates) 2023-06-26 19:47:01 +02:00
04e2da390c Typo 2023-06-26 19:46:22 +02:00
e367538fc4 Update Interface: Add ticket variants 2023-06-26 19:45:12 +02:00
7d722e2b2c Merge branch 'pu/accountRequest' into pu/integration 2023-06-22 14:56:28 +02:00
80112f23b4 Simulate Account (-> because DeviceController ...
... functions currently do not provide usefull results.
2023-06-22 14:54:54 +02:00
9cd10bfed8 Diag: first working version to detect some system errors
Drawbacks:
 - has to be called extra, no events or signals
 - lot of integer result values (where are they documented? Mapping?)
2023-06-22 14:52:34 +02:00
ba3eabec2c Execute diagRequest() on mode change to IDLE (i.e. after vending) 2023-06-22 14:50:56 +02:00
a4d74ed0f7 Update printing ticket (version 2.1)
Use hwapi::prn_getPrintResult() to detect print result.
2023-06-22 12:14:55 +02:00
4a7022fd00 Use diag on closing doors 2023-06-22 08:50:10 +02:00
31f178b241 Remove unused includes 2023-06-22 08:46:18 +02:00
6a19fd7608 Add class DeviceControllerDiag to supervise DeviceController state 2023-06-22 08:44:16 +02:00
8fc88662d3 Add ATBMachineEvent class (QEvent) 2023-06-22 08:42:21 +02:00
29cee7fd1c Merge branch 'pu/accountRequest' into pu/integration 2023-06-20 13:28:50 +02:00
b39bbcfad5 Account: set accountData "NumberOfCoinVariants" 2023-06-20 13:26:43 +02:00
7c3bc484af Handle door events (note)
This events come somtimes very unreliably.
2023-06-20 13:23:36 +02:00
2b71705c81 Update interface: DeviceControllerInterface is derived from QObject:
This is for using new connect()-syntax in main application.
Note:
 - signals in interface must not be defined virtual
 - signals in implementation must not override signals defined
   in interface.
2023-06-20 13:18:09 +02:00
18ff5d42a7 Merge branch 'pu/integration' into pu/accountRequest 2023-06-19 16:41:08 +02:00
ac9486879e Update interfaces.h (20230619_1623) 2023-06-19 16:40:12 +02:00
1467530e3c Add debug output for account request 2023-06-19 16:27:20 +02:00
414dda009e Proposal for getting account data from CAlib/DeviceController 2023-06-19 16:26:33 +02:00
74753ce644 Add utils-class for static utils methods 2023-06-19 15:07:05 +02:00
c4cbf89182 TEST: try to track currentCashState
... but this is currently useless because we can not detect overpayment
here.
2023-06-16 15:50:25 +02:00
0baad4689a Add note about TODO: TicketNumber 2023-06-16 15:49:56 +02:00
a4a746658c TEST: use QueuedConnection for hwapi signals 2023-06-16 11:21:24 +02:00
7e65c4feda onPrinterDataPrepared: increase time for fake signal onPrinterFinishedOk 2023-06-16 11:17:38 +02:00
e236fc8bce Update interfaces.h (20230616_08006_08006_08006_08006_08006_0800) 2023-06-16 11:14:30 +02:00
76e67dbbaa Fix: return, if CashAgentLib could not be loaded 2023-06-16 10:53:27 +02:00
b52de16dbc Workaround for CashAgent: onCashVendStopByMax()
Wait 500ms until we call hw->getInsertedAmount().
2023-06-15 18:49:59 +02:00
cade03b400 Log output from hw->getInsertedAmount() 2023-06-15 18:49:29 +02:00
7a9f837b88 Refactoring 2023-06-15 18:49:13 +02:00
b10e597e59 Workaround for CashAgent: send 'vend_failed()' on program start 2023-06-15 14:18:32 +02:00
4cc4247744 CashAgent: update errorCodes 2023-06-15 14:16:03 +02:00
59432735d0 CashAgent: changed name: CAmaster 2023-06-15 14:15:13 +02:00
1f0720e52b Update interfaces.h 2023-06-15 13:45:19 +02:00
5f3e0babb1 Load CashAgentLib: print errorString if load fails 2023-06-15 10:54:32 +02:00
f2637e3af8 dc_autoRequest is allways switched on 2023-06-15 09:48:25 +02:00
ac6331e5a7 Update interfaces.h (20230615) 2023-06-15 09:47:17 +02:00
7ccbc8bb23 Proposal for requestAccount() (does not work)
... because of random signal from DeviceController.
... and wrong handling of DeviceController methods.
2023-06-14 14:38:24 +02:00
017543dd5b Door Events: Update log outputs 2023-06-14 14:37:34 +02:00
d5d2b8917a Add handling door events 2023-06-13 17:00:17 +02:00
9d686ae48d Update DeviceControllerInterface (door events) 2023-06-13 16:59:20 +02:00
a037626d6d Update interface.h (door events) 2023-06-13 16:58:17 +02:00
a3f32b576e Set dateTime on plugin init 2023-06-12 09:51:34 +02:00
668b10e55d Add interface for programmode switch 2023-06-12 09:51:16 +02:00
596cf3ed25 TicketPrint: select ticket to print
dependent on printingData.
2023-06-09 11:19:39 +02:00
c330be4f30 TicketPrint: use interface method 'prn_printKombiticket()'
... instead of printing templates.
2023-06-09 11:18:39 +02:00
3722dd4d28 Merge branch 'pu/use_cashAgentLib' into pu/integration 2023-06-06 10:14:42 +02:00
f5568f6f81 Add comment 2023-06-05 18:07:12 +02:00
98ef7b7b26 Send cashInputFinished(), when cash input is finished 2023-06-05 18:04:34 +02:00
2717c614e3 Update interface hwapi 3.6 2023-06-05 12:51:55 +02:00
de1dc88e51 Use CashAgentLib 2023-06-05 12:49:20 +02:00
50bf7e8b52 Add stubs for Account-Task 2023-06-01 16:30:50 +02:00
d8d315cd49 Update ATBAPP/DeviceControlllerInterface 2023-06-01 16:21:37 +02:00
84859064a3 Workaround: prevent signaling irregular coin inputs 2023-05-24 10:51:20 +02:00
ff4c52ddc9 Fix: remove debug output 2023-05-23 15:46:34 +02:00
f4be010e1a Fix: set flag in datIf_cycleSend() 2023-05-23 15:45:18 +02:00
75b597586f Remove dependency to QWidget / QMainWindow
This not GUI library!
2023-05-23 14:41:09 +02:00
88cc71e05f Merge branch 'pu/coinIntegration_TS18052023' into pu/integration 2023-05-23 14:36:41 +02:00
6f00d5b356 Workaround: do not use printer signals...
... this signals are sent presumably after printing first template.
As we print currently 3 templates and we use this signals to create an
event in main application this lead to an error:
Subsequent DCPlugin operations failed sometimes because DC needs a time
gap between to operations.
2023-05-23 14:29:24 +02:00
1f9cc3b8c0 Add debug output 2023-05-23 10:23:04 +02:00
584e3af035 Start CashInput with UINT_MAX (PayUp) 2023-05-23 10:21:00 +02:00
2ac0f5b275 Delay printing ...
... printing day tickets need this delay
2023-05-23 10:17:46 +02:00
a97ef4ea04 SwitchOn dc feature autorequest
This is necessary for receiving coint input events
2023-05-22 11:21:08 +02:00
30d790b84f Connect all hwapi signals 2023-05-22 11:20:28 +02:00
ca5e43e0d7 Add debug output 2023-05-19 15:34:28 +02:00
3ac91305d4 Fix: for load as plugin on target device 2023-05-19 15:33:52 +02:00
d0445949d2 Merge changes from T.Sax DC_plugin 18.5.23 2023-05-19 13:57:17 +02:00
91d9280a4a Speed up ticket printing 2023-05-18 14:01:07 +02:00
48d6a34b16 ATBAPP: Rework for ticket printing 2023-05-18 11:57:54 +02:00
e32142cd62 Implement cash input interface 2023-05-04 14:28:38 +02:00
f611e07dcf Implement printing ticket 2023-05-04 13:21:14 +02:00
6478eda581 TS: pr_printTemplate(): send 'longFDcmd_set()' 2023-05-03 13:19:01 +02:00
1663d09d3a Merge with TS 21.04.23 2023-05-03 13:06:57 +02:00
080c00eda1 Set serialPort name from config 2023-05-02 17:39:38 +02:00
bbce2b02e3 Test printing ticket 2023-05-02 17:10:17 +02:00
8ff17a2e00 DeviceControllerInterface: erroCode is a string 2023-05-02 17:09:53 +02:00
c6574280ac Project: including DCPlugin.pri globally 2023-05-02 10:08:16 +02:00
f0f0493d19 hwapi: remove unused dependency to QWidget 2023-05-02 10:07:42 +02:00
9bf99c5515 Fix: make plugin compile 2023-04-28 13:53:14 +02:00
8ff8faf007 Fix: warning 2023-04-19 16:55:38 +02:00
09a80498e4 Merge branch 'master' into pu/integration 2023-04-19 16:28:26 +02:00
21fb07b81c Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/DCPlugin 2023-04-19 16:27:27 +02:00
01f8c1e49c First compiling version for high level vending interface 2023-04-19 16:26:12 +02:00
3029b8da04 Rename TARGET name 2023-04-19 16:24:53 +02:00
2143801900 Configure project for PTU5-YOCTO 2023-04-18 17:07:28 +02:00
6f6d3b7491 Add atb/qt gitignore 2023-04-18 17:06:13 +02:00
4cfb8f1804 Add auto version generation script 2023-04-18 17:04:51 +02:00
d992ee3fad Added dc_getStatus() to send info to ISMAS 2023-04-18 15:06:57 +02:00
b7d8fabfd0 Added dc_getStatus() to send info to ISMAS 2023-04-18 15:06:48 +02:00
7129805f4e Added dc_getStatus() to send info to ISMAS 2023-04-18 15:06:36 +02:00
01140c523b Using std::min from algorithm-header 2023-04-18 14:43:30 +02:00
c99d0730ce Added additional variables into shared memory.
Cleaned source.
2023-04-18 14:42:09 +02:00
81c610c48b Included additional variables into shared memory 2023-04-18 14:41:05 +02:00
6ae7c06d42 Changed to const-pointer 2023-04-18 14:40:16 +02:00
1eb2ac3a1d Use const-pointer 2023-04-18 13:55:46 +02:00
f3adba2f0f Change parameter type from uint8_t to bool 2023-04-18 13:52:43 +02:00
652ad9b43d Included changes of TS for version 3.5. 2023-04-18 13:41:04 +02:00
c85b090306 Added ulong2uchar (version 3.5). 2023-04-18 13:39:52 +02:00
87a6ed0795 Include changes of Thomas for version 3.5.
virtual bool cash_startPayment(uint32_t amount) const=0;
        // 17.4.23TS: extended to 32bit

    virtual uint8_t prn_getPrintResult() const=0;

    // in case of print-error get detailed error:
    virtual uint8_t prn_getCurrentPrinterState() const=0;
        //        0: printer OK
        //          bit0: near paper end          bit1: no paper
        //          bit2: temperature error       bit3: error head open
        //          bit4: paper jam in cutter
        //          bit6: no response             bit7: serial rec. error
        //			bit5: printer not ready

signals:
    virtual void hwapi_templatePrintFinished_OK(void) const=0;
    virtual void hwapi_templatePrintFinished_Err(void) const=0;
    virtual void hwapi_gotNewCoin(void) const=0;
    virtual void hwapi_vendStopByMax(void) const=0;
    virtual void hwapi_vendStopByPushbutton(void) const=0;
2023-04-18 13:38:07 +02:00
99c88c7825 Included changes of Thomas for version 3.5.
prn_getPrintResult(),

signals:
    void hwapi_templatePrintFinished_OK(void) const override;
    void hwapi_templatePrintFinished_Err(void) const override;
    void hwapi_gotNewCoin(void) const override;
    void hwapi_vendStopByMax(void) const override;
    void hwapi_vendStopByPushbutton(void) const override;

 private slots:
    void hwapi_slotPrintFinished_OK(void);
    void hwapi_slotPrintFinished_Err(void);
    void hwapi_slotGotCoin(void);
2023-04-18 13:36:20 +02:00
712ea0fc6e Included changes of Thomas for version 3.5 of library:
datif_templatePrintFinished_OK(), datif_templatePrintFinished_Err(),
datif_gotNewCoin().
2023-04-18 13:34:05 +02:00
86311de486 Add use of shared memory.
Add changes for version 3.4. of library.
2023-04-18 12:23:18 +02:00
cb4412779f Added check4freeFDshortCmd. 2023-04-18 12:22:23 +02:00
a95e174356 Included some changes of Thomas. 2023-04-18 12:21:30 +02:00
c724b5b9fb Shift several device controller related variables to shared memory. 2023-04-18 12:20:23 +02:00
ef7932102f Massive change: using shared memory containing most device controller
realted variables.
2023-04-18 12:19:08 +02:00
a7aa75ae5f Massive change: using shared memory containing devcie controller variables. 2023-04-18 12:18:12 +02:00
dc00c69b82 Added check4freeFDlongCmd. 2023-04-18 12:17:11 +02:00
eeb35190e1 Adding shared memory containing all variables necessary to
check device controller related variables.
2023-04-18 12:15:27 +02:00
30338e24cc Changed struct T_moduleCondition.
Changed struct T_dynamicCondition.
Added struct T_extTime.
Added log_chkIfVaultRecordAvailable().
Added sys_getDeviceConditions().
set version to 3.4.
2023-04-18 12:12:22 +02:00
58fdea45f0 Added m_sharedMem.
Added cash_getAmountInVault.
Added cash_getNrCoinsInVault.
Added sys_getDynMachineConditions() with new interface.
Added sys_getDeviceConditions() with new interface.
Added log_chkIfVaultRecordAvailable().
2023-04-18 12:08:52 +02:00
df760f1a52 Added shared_mem_buffer.h/.cpp. 2023-04-18 12:07:28 +02:00
3e3e1efe7d Make sure the printer functions can be called without explicitly openeing the
serial device.
2023-04-14 09:04:35 +02:00
e5a8cfd1cd copy of include/interfaces.h 2023-04-13 16:23:56 +02:00
5e6e6017b3 Minor change 2023-04-13 16:22:01 +02:00
f3d9c690b7 Added dc_printTemplate. Fixed implementation of dc_updatePrinterTemplate 2023-04-13 16:18:47 +02:00
3f10469b8f Added dc_printTemplate. Changed interface for updating printer templates. 2023-04-13 16:17:28 +02:00
d92bdbfb3e Added dc_printTemplate. Changed interface for updating printer templates. 2023-04-13 16:16:57 +02:00
60c48588b0 Fixed template number: cannot be 0 2023-04-13 13:54:15 +02:00
ef48301dad Added dc_updatePrinterTemplate 2023-04-13 13:37:32 +02:00
5f7d34ef12 implemented dc_updatePrinterTemplate 2023-04-13 13:37:00 +02:00
863e4b23a9 Added dc_updatePrinterTemplate 2023-04-13 13:31:39 +02:00
37f0012ce9 converted to utf-8 2023-04-13 11:35:08 +02:00
82accc4b1a Added file types for JSON as enum 2023-04-13 11:15:22 +02:00
c1b945225b Added/merged from sources of Thomas (version CashAgentLib 3.3, 12.04.2023) 2023-04-13 10:55:37 +02:00
debade9942 using memset() to shorten some code. 2023-04-11 13:58:11 +02:00
ffbe0dfc2e don't use compiler cache (at least for development) 2023-04-11 13:54:00 +02:00
8f7d4a203d Fixed sending to less blocks 2023-04-06 17:43:06 +02:00
defe492ec6 Add DCPlugin.pri to DesktopLinux 2023-04-06 08:55:43 +02:00
002d58ba7b Added dc_updateDC plus associated helper functions.
dc_open_Serial:
    check if serial line is really open
dc_close_Serial:
    check if serial line is really closed
dc_isPortOpen:
    check if port is open directly on serial-object
bl_checkBL:
    try to check if bootloader is running
2023-04-05 14:18:29 +02:00
76f54cdc0c Added qDebug(), which are commented out. 2023-04-05 14:16:34 +02:00
591fd89cb5 Added qDebug() which are commented out:
ser_ISR100ms()
    open_serial_port
    close_serial_port
2023-04-05 14:13:17 +02:00
e7723f669f Added internal helpers for supporting dcUpdate:
DownloadResult sendNextAddress(int bNum) const;
    DownloadResult sendNextDataBlock(QByteArray const &b, int bNum) const;
    DownloadResult sendStatus(int ret) const;
    DownloadResult dc_downloadBinary(QByteArray const &binary) const;
    bool startBootloader() const;
    bool stopBootloader() const;
    bool openSerial(int br, QString baudrate, QString comPort) const;
    bool closeSerial(QString comport) const;
    bool resetDeviceController() const;
    QByteArray loadBinaryDCFile(QString filename) const;
    bool downloadBinaryToDC(QString const &bFile) const;

Redeclared returning "bool":
    dc_openSerial
    dc_closeSerial
    bl_checkDL.
    Added dc_updateDC(...).
2023-04-05 14:08:16 +02:00
d0e1be11b6 Added helper getSerialPort() 2023-04-05 14:07:18 +02:00
f63798727f Added helper getProt() 2023-04-05 14:06:38 +02:00
898f0a4af8 Redeclared to return 'bool':
dc_openSerial
    dc_closeSerial
    dc_isPortOpen
    bl_checkBL
    Added enum DownloadResult.
    Added dc_UpdateDC.
2023-04-05 14:03:01 +02:00
ed037b99c9 Aktualisiert auf Stand 29/03/2023 2023-03-30 08:48:46 +02:00
e4a2f8fce3 Aktualisiert auf Stand 29/03/2023 2023-03-30 08:44:14 +02:00
19befc2c58 add interfaces.h 2023-03-29 14:46:35 +02:00
7f23e3ea46 Add updated sources of thomas. 2023-03-29 14:32:22 +02:00
49396c22ee Add (obsolete?) directory 2023-03-17 13:22:04 +01:00
0b87f44e64 Added comments 2023-03-17 13:13:11 +01:00
66b22a4233 Add pro-file for this project 2023-03-17 13:11:33 +01:00
ba5d23d8be add gitignore file 2023-03-17 13:11:03 +01:00
75acd1e3ec Add files to be compiled 2023-03-17 12:45:49 +01:00
48a0068ebd Add pro-file for inclusion 2023-03-17 12:23:20 +01:00
f51062010e Adding src files (sax) 2023-03-17 11:22:09 +01:00
a9a5210029 Adding header files (sax) 2023-03-17 11:21:55 +01:00
16 changed files with 3560 additions and 0 deletions

41
.gitignore vendored Normal file
View File

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

100
DCPlugin.pro Normal file
View File

@@ -0,0 +1,100 @@
TEMPLATE = lib
CONFIG += plugin
#CONFIG += c++11 console
#CONFIG -= app_bundle
#QT += widgets
QT -= gui
QT += serialport
INCLUDEPATH += $${PWD}/plugins
INCLUDEPATH += $${PWD}/include
QMAKE_CXXFLAGS += -Wno-deprecated-copy
# default
ARCH = PTU5
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 += \
include/interfaces.h \
src/ATBAPP/ATBAPPplugin.h \
src/ATBAPP/DeviceControllerDiag.h \
src/ATBAPP/DeviceControllerInterface.h \
src/ATBAPP/ATBHealthEvent.h \
src/ATBAPP/ATBMachineEvent.h \
src/ATBAPP/ATBDeviceControllerPlugin.h \
src/ATBAPP/Utils.h
SOURCES += \
src/ATBAPP/ATBHealthEvent.cpp \
src/ATBAPP/ATBMachineEvent.cpp \
src/ATBAPP/ATBDeviceControllerPlugin.cpp \
src/ATBAPP/DeviceControllerDiag.cpp \
src/ATBAPP/Utils.cpp
DISTFILES += \
generate-version.sh
# Define how to create version.h
VERSION_H = $$PWD/include/version.h
version.output = $$PWD/include/version.h
version.commands = $$PWD/generate-version.sh $${ARCH} $${TARGET} $${INTERFACE} $${INTERFACE_DEFINITION} $${VERSION_H}
version.depends = FORCE
version.input = VERSION_H
version.variable_out = HEADERS
QMAKE_EXTRA_COMPILERS += version
QMAKE_CLEAN += $${PWD}/include/version.h

155
generate-version.sh Executable file
View File

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

1350
include/interfaces.h Executable file

File diff suppressed because it is too large Load Diff

22
src/ATBAPP/ATBAPPplugin.h Normal file
View File

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

View File

@@ -0,0 +1,900 @@
#include "src/ATBAPP/ATBDeviceControllerPlugin.h"
#include "src/ATBAPP/ATBHealthEvent.h"
#include "src/ATBAPP/ATBMachineEvent.h"
#include "src/ATBAPP/Utils.h"
#include <QTimer>
#include <QTextCodec>
#include <QDebug>
#include <QPluginLoader>
#include <QDateTime>
#include <QFileInfo>
#include <QCoreApplication>
#include <QUuid>
#include <cstdlib>
ATBDeviceControllerPlugin::ATBDeviceControllerPlugin(QObject *parent)
: pluginState(PLUGIN_STATE::NOT_INITIALIZED)
, eventReceiver(nullptr)
{
this->setParent(parent);
this->pluginInfo = QString::fromUtf8(pluginInfoString.c_str());
if (!this->private_loadCashAgentLib("")) {
return;
}
//connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_templatePrintFinished_OK()), this, SLOT(onPrintFinishedOK()), Qt::QueuedConnection);
//connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_templatePrintFinished_Err()), this, SLOT(onPrintFinishedERR()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_gotNewCoin()), this, SLOT(onCashGotCoin()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_payStopByMax()), this, SLOT(onCashPayStopByMax()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_payStopByEscrow()), this, SLOT(onCashPayStopByEscrow()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_payStopByError()), this, SLOT(onCashPayStopByError()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_payStopByTimeout()), this, SLOT(onCashPayStopByTimeout()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_doorServiceDoorOpened()), this, SLOT(onServiceDoorOpened()), Qt::QueuedConnection); // switch to ModeSERVICE
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_doorVaultDoorOpened()), this, SLOT(onVaultDoorOpened()), Qt::QueuedConnection); // Screen?? with message
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_doorCoinBoxRemoved()), this, SLOT(onCoinBoxRemoved()), Qt::QueuedConnection); // Create/Send Account
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_doorCoinBoxInserted()), this, SLOT(onCoinBoxInserted()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_doorCBinAndAllDoorsClosed()), this, SLOT(onCBinAndAllDoorsClosed()), Qt::QueuedConnection);
connect(dynamic_cast<QObject*>(hw), SIGNAL(hwapi_doorAllDoorsClosed()), this, SLOT(onAllDoorsClosed()), Qt::QueuedConnection); // check for errors, switch to mode IDLE
this->diag = new DeviceControllerDiag(this);
this->currentSelectedTicketType = 0;
this->currentCashState = CASH_STATE::CACHE_EMPTY;
}
ATBDeviceControllerPlugin::~ATBDeviceControllerPlugin() {}
PLUGIN_STATE ATBDeviceControllerPlugin::initDCPlugin(QObject *eventReceiver, const QSettings & settings)
{
this->eventReceiver = eventReceiver;
// read variables from setting
this->serialPortName = 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", this->serialPortName, 1);
hw->dc_autoRequest(true);
hw->rtc_setDateTime();
// this is necessary to init the CashAgentLib (!)
hw->vend_failed();
// text encoding for printer
this->codec = QTextCodec::codecForName(printerEncoding);
this->diag->init(this->hw, this->eventReceiver);
this->pluginState = PLUGIN_STATE::INITIALIZED;
return pluginState;
}
void ATBDeviceControllerPlugin::startPhysicalLayer()
{
if (this->pluginState == PLUGIN_STATE::NOT_INITIALIZED)
{
qCritical() << "ATBDeviceControllerPlugin::startPhysicalLayer(): plugin is not initialized";
return;
}
// open serial port
hw->dc_openSerial(5, "115200", this->serialPortName, 1);
hw->dc_autoRequest(true);
}
void ATBDeviceControllerPlugin::stopPhysicalLayer()
{
if (this->pluginState == PLUGIN_STATE::NOT_INITIALIZED)
{
qCritical() << "ATBDeviceControllerPlugin::startPhysicalLayer(): plugin is not initialized";
return;
}
hw->dc_autoRequest(false);
hw->dc_closeSerial();
}
// Handle Mode-Changes --------------------------------------------------------
void ATBDeviceControllerPlugin::onChangedProgramModeToSELL()
{
//hw->dc_autoRequest(true);
}
void ATBDeviceControllerPlugin::onChangedProgramModeToSERVICE()
{
//hw->dc_autoRequest(true);
}
void ATBDeviceControllerPlugin::onChangedProgramModeToIDLE()
{
//hw->dc_autoRequest(false); // <-- TODO: ???
this->diag->diagRequest();
}
void ATBDeviceControllerPlugin::onChangedProgramModeToOOO()
{
}
// 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());
if (amountInt == 0) amountInt = UINT_MAX;
hw->cash_startPayment(amountInt);
}
void ATBDeviceControllerPlugin::requestStopCashInput()
{
hw->cash_stopPayment();
// we need new cash value in application...
QTimer::singleShot(2500, this, SLOT(onCashPayStopedSuccess()));
}
void ATBDeviceControllerPlugin::cashCollect()
{
hw->vend_success();
this->currentCashState = CASH_STATE::CACHE_EMPTY;
}
void ATBDeviceControllerPlugin::cashAbort()
{
hw->vend_failed();
this->currentCashState = CASH_STATE::CACHE_EMPTY;
}
// TASKS: Account -------------------------------------------------------------
// for an external account request, e.g. by an ui-button:
void ATBDeviceControllerPlugin::requestAccount()
{
qCritical() << "ATBDeviceControllerPlugin::requestAccount()";
this->private_startAccount();
}
void ATBDeviceControllerPlugin::private_startAccount()
{
uint16_t backupedAccNumbers[8]; // array of account numbers
uint8_t nrOfVals; // number of saved accounts
// it is not defined which one is the latest account
hw->log_getHoldAccountNumbers(&nrOfVals, backupedAccNumbers);
// DEBUG
qCritical() << "Start account: ";
qCritical() << " nrOfVals = " << nrOfVals;
for (int i=0; i<nrOfVals; ++i) {
qCritical() << " backupedAccNumbers[" << i << "] = " << backupedAccNumbers[0];
}
qsort( backupedAccNumbers, nrOfVals, sizeof (uint16_t), Utils::compare );
uint16_t latestAccountNumber = backupedAccNumbers[nrOfVals-1];
// DEBUG
qCritical() << " latestAccountNumber = " << latestAccountNumber;
hw->log_selectVaultRecord(latestAccountNumber);
this->accountCheckCounter = 0;
QTimer::singleShot(500, this, SLOT(private_checkAccountData()));
}
void ATBDeviceControllerPlugin::private_checkAccountData()
{
// DEBUG
qCritical() << " --> private_checkAccountData()";
if (hw->log_chkIfVaultRecordAvailable()) {
this->private_getAccountData();
}
else {
if (this->accountCheckCounter < 10) {
this->accountCheckCounter++;
QTimer::singleShot(500, this, SLOT(private_checkAccountData()));
}
else {
// cannot get accountData within ~10*500ms
qCritical() << "checkAccountData() failed";
// simulate:
this->private_getAccountData();
// TODO: create and send an HealthEvent...
}
}
}
void ATBDeviceControllerPlugin::private_getAccountData()
{
// DEBUG
qCritical() << " --> private_getAccountData()";
struct T_vaultRecord retVR;
hw->log_getVaultRecord(&retVR);
QHash<QString, QVariant> accountData;
accountData.insert("AccountingNumber", QString::number(retVR.AccountingNumber));
int numberOfCoinVariants = sizeof(retVR.coinsInVault);
// DEBUG
qCritical() << " NumberOfCoinVariants = " << numberOfCoinVariants;
// limit numberOfCoinVariants:
if (numberOfCoinVariants > 16) { numberOfCoinVariants = 16; }
accountData.insert("NumberOfCoinVariants", numberOfCoinVariants);
for (int i = 0; i < numberOfCoinVariants; ++i) {
accountData.insert("COIN_" + QString::number(i) + "_Quantity", retVR.coinsInVault[i]);
accountData.insert("COIN_" + QString::number(i) + "_Value", retVR.coinDenomination[i]);
// DEBUG
qCritical() << "COIN_" + QString::number(i) + "_Quantity = " << accountData["COIN_" + QString::number(i) + "_Quantity"];
qCritical() << "COIN_" + QString::number(i) + "_Value = " << accountData["COIN_" + QString::number(i) + "_Value"];
}
emit requestAccountResponse(accountData);
}
// Door Events / Hardware contacts --------------------------------------------
void ATBDeviceControllerPlugin::onServiceDoorOpened()
{
qCritical() << "ATBDeviceControllerPlugin::onServiceDoorOpened()";
// switch to mode service
emit this->requestModeSERVICE();
// TODO:
// - create an HealthEvent (-> ISMAS-Event)
}
void ATBDeviceControllerPlugin::onVaultDoorOpened()
{
// TODO:
// - show special screen / message on screen
// - create an HealthEvent (-> ISMAS-Event)
qCritical() << "ATBDeviceControllerPlugin::onVaultDoorOpened()";
// TODO: Start background task "ACCOUNT"
// do not: emit this->requestModeSERVICE();
}
void ATBDeviceControllerPlugin::onCoinBoxRemoved()
{
qCritical() << "ATBDeviceControllerPlugin::onCoinBoxRemoved()";
this->private_startAccount();
}
void ATBDeviceControllerPlugin::onCoinBoxInserted()
{
qCritical() << "ATBDeviceControllerPlugin::onCoinBoxInserted()";
}
void ATBDeviceControllerPlugin::onCBinAndAllDoorsClosed()
{
qCritical() << "ATBDeviceControllerPlugin::onCBinAndAllDoorsClosed()";
this->diag->diagRequest();
// TODO: Stop background task "ACCOUNT"
QTimer::singleShot(2000, this, SIGNAL(requestModeIDLE()));
}
void ATBDeviceControllerPlugin::onAllDoorsClosed()
{
qCritical() << "ATBDeviceControllerPlugin::onAllDoorsClosed()";
emit this->requestModeIDLE();
}
// TASKS: printing ------------------------------------------------------------
void ATBDeviceControllerPlugin::requestPrintTicket(nsDeviceControllerInterface::TICKET_VARIANT ticketVariant, const QHash<QString, QVariant> & printingData)
{
struct T_dynDat *dynTicketData = new T_dynDat;
memset(dynTicketData, 0, sizeof(*dynTicketData));
QDateTime parkingEndDateTime = QDateTime::fromString(printingData["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(printingData["currentDateTime"].toString(), Qt::ISODate);
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(printingData["licenseplate"].toString());
memcpy((char*)dynTicketData->licensePlate, ba_licenseplate.data(), std::min(ba_licenseplate.size(),8));
QByteArray ba_amount = codec->fromUnicode(printingData["amount"].toString());
memcpy((char*)dynTicketData->vendingPrice, ba_amount.data(), std::min(ba_amount.size(),8));
QByteArray ba_parkingEndTime = codec->fromUnicode(parkingEndDateTime.toString("hh:mm"));
memcpy((char*)dynTicketData->parkingEnd, ba_parkingEndTime.data(), std::min(ba_parkingEndTime.size(),8));
QByteArray ba_parkingEndDate = codec->fromUnicode(parkingEndDateTime.toString("dd.MM.yy"));
memcpy((char*)dynTicketData->currentTime, ba_parkingEndDate.data(), std::min(ba_parkingEndDate.size(),8));
// ! and yes... 'ParkingEndDate' is 'currentTime'
QByteArray ba_currentDate = codec->fromUnicode(currentDateTime.toString("dd.MM.yy"));
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
// STAN for Szeged Start/Stop: must be 9 digits
// --------------------------------------------------------------------------------------
QString stan = codec->fromUnicode(printingData["STAN"].toString());
qCritical() << " requestPrintTicket() STAN = " << stan;
QString stan1;
QString stan2;
if (stan.length() == 9) {
stan1 = " " + stan.mid(0,3);
stan2 = stan.mid(3,3) + " " + stan.mid(6,3);
}
else {
qCritical() << "ASSERT: ATBDeviceControllerPlugin::requestPrintTicket() invalid STAN: " << stan;
stan1 = " 000";
stan2 = "000 000";
}
QByteArray ba_stan1 = codec->fromUnicode(stan1);
QByteArray ba_stan2 = codec->fromUnicode(stan2);
// --------------------------------------------------------------------------------------
this->templateList.clear();
switch (ticketVariant) {
case nsDeviceControllerInterface::TICKET_VARIANT::START_RECEIPT:
qCritical() << " -> TICKET_VARIANT::START_RECEIPT";
memcpy((char*)dynTicketData->dynDat6, ba_stan1.data(), std::min(ba_stan1.size(),8));
memcpy((char*)dynTicketData->dynDat7, ba_stan2.data(), std::min(ba_stan2.size(),8));
this->templateList << 21 << 22 << 23;
break;
case nsDeviceControllerInterface::TICKET_VARIANT::STOP_RECEIPT:
qCritical() << " -> TICKET_VARIANT::STOP_RECEIPT";
memcpy((char*)dynTicketData->dynDat6, ba_stan1.data(), std::min(ba_stan1.size(),8));
memcpy((char*)dynTicketData->dynDat7, ba_stan2.data(), std::min(ba_stan2.size(),8));
this->templateList << 24 << 25 << 26;
break;
case nsDeviceControllerInterface::TICKET_VARIANT::RECEIPT:
break;
case nsDeviceControllerInterface::TICKET_VARIANT::ERROR_RECEIPT:
break;
case nsDeviceControllerInterface::TICKET_VARIANT::PARKING_TICKET:
break;
}
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket()";
for (int i =0; i < this->templateList.size(); ++i) {
qCritical() << " template: " << this->templateList.at(i);
}
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
<< " stan = " << printingData["STAN"] << endl;
this->onPrintFinishedERR();
return;
}
QTimer::singleShot(1000, this, SLOT(onPrinterDataPreparedForTemplates()));
}
void ATBDeviceControllerPlugin::requestPrintReceipt(const QHash<QString, QVariant> & printingData)
{
Q_UNUSED(printingData)
qCritical() << "ATBDeviceControllerPlugin::requestPrintReceipt() is currently not implemented";
}
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
<< " currentDateTime = " << printingData["currentDateTime"] << endl;
QDateTime parkingEndDateTime = QDateTime::fromString(printingData["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(printingData["currentDateTime"].toString(), Qt::ISODate);
/* -----------------------------------------------------------------------------------------
* note: the following highly depends on printer template files!
* -----------------------------------------------------------------------------------------
*/
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(printingData["licenseplate"].toString());
memcpy((char*)dynTicketData->licensePlate, ba_licenseplate.data(), std::min(ba_licenseplate.size(),8));
QByteArray ba_amount = codec->fromUnicode(printingData["amount"].toString());
memcpy((char*)dynTicketData->vendingPrice, ba_amount.data(), std::min(ba_amount.size(),8));
QByteArray ba_parkingEndTime = codec->fromUnicode(parkingEndDateTime.toString("hh:mm"));
memcpy((char*)dynTicketData->parkingEnd, ba_parkingEndTime.data(), std::min(ba_parkingEndTime.size(),8));
QByteArray ba_parkingEndDate = codec->fromUnicode(parkingEndDateTime.toString("dd.MM.yy"));
memcpy((char*)dynTicketData->currentTime, ba_parkingEndDate.data(), std::min(ba_parkingEndDate.size(),8));
// ! and yes... 'ParkingEndDate' is 'currentTime'
QByteArray ba_currentDate = codec->fromUnicode(currentDateTime.toString("dd.MM.yy"));
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
// DEBUG
/*
uint8_t* buf = dynTicketData->licensePlate;
int length = 64;
for (int i = 0; i < length; ++i) {
fprintf(stderr, "%d %02x %c\n", i, buf[i], buf[i]);
}
fprintf(stderr, "\n");
*/
// 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;
}
// set ticket type:
// 00281 - Szeged:
// 1 - Cash / ShortTimeParking
// 2 - Card / ShortTimeParking
// 3 - Cash / DayTicket
// 4 - Card / DayTicket
QString paymentType = printingData["paymentType"].toString(); // must be "CASH" | "CARD"
QString productName = printingData["product"].toString(); // must be "ShortTimeParking" | "DayTicket"
if ( (paymentType == "CASH") && (productName == "ShortTimeParking") ) {
this->currentSelectedTicketType = 1;
}
else
if ( (paymentType == "CARD") && (productName == "ShortTimeParking") ) {
this->currentSelectedTicketType = 2;
}
else
if ( (paymentType == "CASH") && (productName == "DayTicket") ) {
this->currentSelectedTicketType = 3;
}
else
if ( (paymentType == "CARD") && (productName == "DayTicket") ) {
this->currentSelectedTicketType = 4;
}
else {
qCritical() << "ERROR: requestPrintTicket(): invalid payment data:";
qCritical() << " paymentType = " << paymentType << endl
<< " productName = " << productName << endl;
this->onPrintFinishedERR();
return;
}
QTimer::singleShot(3000, this, SLOT(onPrinterDataPrepared()));
}
void ATBDeviceControllerPlugin::onPrinterDataPreparedForTemplates()
{
if (this->templateList.isEmpty()) return;
this->onPrinterPrintNextTemplate();
}
void ATBDeviceControllerPlugin::onPrinterDataPrepared()
{
this->hw->prn_printKombiticket(this->currentSelectedTicketType);
// note: calling prn_getPrintResult() immediately may result in wrong answer!
// We have to wait "about some seconds" until calling this function!
QTimer::singleShot(4000, this, SLOT(onPrinterWaitForPrinting()));
// old: use printer templates:
// this->currentTemplate = 1;
// this->onPrinterPrintNextTemplate();
}
void ATBDeviceControllerPlugin::onPrinterWaitForPrinting()
{
quint8 printerResult = this->hw->prn_getPrintResult();
switch (printerResult) {
case 0: // still printing
qCritical() << "--> printer: WaitForPrinting";
QTimer::singleShot(2000, this, SLOT(onPrinterWaitForPrinting()));
break;
case 1: // printing finished, Ok
this->onPrintFinishedOK();
break;
case 2: // printing finished, Error
this->onPrintFinishedERR();
break;
default:
qCritical() << "DC Error: wait for printing";
this->onPrintFinishedERR();
break;
}
}
void ATBDeviceControllerPlugin::onPrinterPrintNextTemplate()
{
// template list must not be empty
if (this->templateList.isEmpty()) {
this->onPrintFinishedERR();
return;
}
qCritical() << " ... print template " << this->templateList.first();
if (!this->hw->prn_printTemplate(this->templateList.first())) {
this->errorCode = "hwapi::prn_printTemplate";
this->errorDescription = QString("hwapi method 'hwapi::onPrinterPrintNextTemplate(%1)' result is false").arg(this->templateList.first());
this->onPrintFinishedERR();
return;
}
this->templateList.removeFirst();
if (templateList.isEmpty()) {
// all templates are printed
// FAKE SIGNAL:
QTimer::singleShot(2000, this, SLOT(onPrintFinishedOK()));
}
else {
// print next template
QTimer::singleShot(2000, this, SLOT(onPrinterPrintNextTemplate()));
}
}
/************************************************************************************************
* private slots, interface to low level hwapi
*
*/
void ATBDeviceControllerPlugin::onPrintFinishedOK()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onPrintFinishedOK()";
emit this->printTicketFinished(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
// TODO: TicketNumber
"",
"");
}
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()";
this->currentCashState = CASH_STATE::CACHE_INPUT;
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::onCashPayStopByMax()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onCashVendStopByMax()";
// we need new cash value in application...
QTimer::singleShot(500, this, SLOT(onCashPayStopedSuccess()));
}
void ATBDeviceControllerPlugin::onCashPayStopByEscrow()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onCashPayStopByEscrow()";
uint32_t amountInt = this->hw->getInsertedAmount();
QString amountString = QString::number(amountInt);
emit this->cashInputFinished(nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND,
amountString,
"",
"");
}
void ATBDeviceControllerPlugin::onCashPayStopByError()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onCashPayStopByError()";
uint32_t amountInt = this->hw->getInsertedAmount();
QString amountString = QString::number(amountInt);
emit this->cashInputFinished(nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND,
amountString,
"",
"");
}
void ATBDeviceControllerPlugin::onCashPayStopByTimeout()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onCashPayStopByTimeout()";
uint32_t amountInt = this->hw->getInsertedAmount();
QString amountString = QString::number(amountInt);
emit this->cashInputFinished(nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND,
amountString,
"",
"");
}
void ATBDeviceControllerPlugin::onCashPayStopedSuccess()
{
// DEBUG
qCritical() << "ATBDeviceControllerPlugin::onCashPayStoped()";
uint32_t amountInt = this->hw->getInsertedAmount();
QString amountString = QString::number(amountInt);
qCritical() << " insertedAmount (int) = " << amountInt;
qCritical() << " insertedAmount = " << amountString;
emit this->cashInputFinished(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
amountString,
"",
"");
}
/**
* Load CashAgentLib
* @brief ATBDeviceControllerPlugin::private_loadCashAgentLib
* @param pluginName
* @return
*/
bool ATBDeviceControllerPlugin::private_loadCashAgentLib(QString pluginName)
{
if (pluginName == "") {
// search list for plugin (.so) file:
QStringList pluginNameList;
pluginNameList << "/usr/lib/libCAmaster.so"
<< "/usr/lib/libCashAgentLib.so";
// using C++11 range based loop:
for (const auto& filename : pluginNameList) {
if (QFileInfo(filename).isReadable()) {
pluginName = filename;
break;
}
}
if (pluginName == "") {
qCritical() << "ATBDeviceControllerPlugin: CashAgentLib not installed!";
this->errorCode = "CashAgentLib::NOT_FOUND";
this->errorDescription = "ERROR: no CashAgentLib: ";
return false;
}
}
if (!QLibrary::isLibrary(pluginName)) {
qCritical() << "ATBDeviceControllerPlugin: can not load CashAgentLib: " << pluginName;
this->errorCode = "CashAgentLib::NO_LIBRARY";
this->errorDescription = "ERROR: can not load CashAgentLib: " + pluginName;
return false;
}
QPluginLoader* pluginLoader = new QPluginLoader();
pluginLoader->setFileName(pluginName);
QObject* plugin = pluginLoader->instance();
if (!pluginLoader->isLoaded()) {
qCritical() << "ATBDeviceControllerPlugin: can not instantiate CashAgentLib: " << pluginName;
qCritical() << " error: " << pluginLoader->errorString();
this->errorCode = "CashAgentLib::NO_INSTANCE";
this->errorDescription = "ERROR: can not instantiate CashAgentLib: " + pluginName;
return false;
}
if (plugin == nullptr) {
qCritical() << "ATBDeviceControllerPlugin: plugin is NULL";
this->errorCode = "CashAgentLib::INSTANCE_IS_NULL";
this->errorDescription = "ERROR: CashAgentLib instance is NULL: " + pluginName;
}
qCritical() << "ATBDeviceControllerPlugin: instantiate CashAgentLib: " << pluginName;
this->hw = qobject_cast<hwinf*>(plugin);
if (this->hw == nullptr) {
qCritical() << "ATBDeviceControllerPlugin: hw is NULL";
this->errorCode = "CashAgentLib::HW_IS_NULL";
this->errorDescription = "ERROR: CashAgentLib object_cast is NULL: " + pluginName;
return false;
}
qCritical() << "ATBDeviceControllerPlugin: loaded CashAgentLib";
return true;
}
/************************************************************************************************
* Mandatory plugin methods
*
*/
PLUGIN_STATE ATBDeviceControllerPlugin::getState()
{
return this->pluginState;
}
QString & ATBDeviceControllerPlugin::getLastError()
{
return this->errorCode;
}
const QString & ATBDeviceControllerPlugin::getLastErrorDescription()
{
return this->errorDescription;
}
const QString & ATBDeviceControllerPlugin::getPluginInfo()
{
return this->pluginInfo;
}
const QString ATBDeviceControllerPlugin::getString(nsDeviceControllerInterface::RESULT_STATE resultState)
{
QString str;
switch (resultState) {
case nsDeviceControllerInterface::RESULT_STATE::SUCCESS:
str = QString("RESULT_STATE::SUCCESS");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND:
str = QString("RESULT_STATE::ERROR_BACKEND");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_TIMEOUT:
str = QString("RESULT_STATE::ERROR_TIMEOUT");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_PROCESS:
str = QString("RESULT_STATE::ERROR_PROCESS");
break;
case nsDeviceControllerInterface::RESULT_STATE::ERROR_RETRY:
str = QString("RESULT_STATE::ERROR_RETRY");
break;
case nsDeviceControllerInterface::RESULT_STATE::INFO:
str = QString("RESULT_STATE::INFO");
break;
}
return str;
}
/************************************************************************************************
* ... end
*/
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2( ATBDeviceControllerPlugin, ATBDeviceControllerPlugin )
#endif

View File

@@ -0,0 +1,148 @@
#ifndef ATBDEVICECONTROLLERPLUGIN_H
#define ATBDEVICECONTROLLERPLUGIN_H
#include <QObject>
#include "src/ATBAPP/DeviceControllerInterface.h"
#include "src/ATBAPP/ATBAPPplugin.h"
#include "src/ATBAPP/DeviceControllerDiag.h"
#include "version.h"
#include "interfaces.h"
#include <unistd.h>
class QTextCodec;
using namespace nsDeviceControllerInterface;
class QSettings;
class ATBDeviceControllerPlugin :
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 *eventReceiver, 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);
void requestPrintTicket(nsDeviceControllerInterface::TICKET_VARIANT ticketVariant, const QHash<QString, QVariant> & printingData);
void requestPrintReceipt(const QHash<QString, QVariant> & printingData);
// TASKS: Account -------------------------------------------------------------
void requestAccount();
// 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);;
public slots:
void onChangedProgramModeToSELL();
void onChangedProgramModeToSERVICE();
void onChangedProgramModeToIDLE();
void onChangedProgramModeToOOO();
void startPhysicalLayer();
void stopPhysicalLayer();
signals:
private:
QString errorCode;
QString errorDescription;
QString pluginInfo;
QList<int> templateList;
QString serialPortName;
bool useDebug;
PLUGIN_STATE pluginState;
QObject* eventReceiver;
hwinf* hw;
DeviceControllerDiag* diag;
QTextCodec *codec;
bool private_loadCashAgentLib(QString pluginName);
quint8 currentSelectedTicketType;
nsDeviceControllerInterface::CASH_STATE currentCashState;
// counts failed hw->log_chkIfVaultRecordAvailable()
int accountCheckCounter;
private slots:
// printer
void onPrinterDataPrepared();
void onPrinterDataPreparedForTemplates();
void onPrinterPrintNextTemplate();
void onPrinterWaitForPrinting();
void onPrintFinishedOK();
void onPrintFinishedERR();
// cash payment
void onCashGotCoin();
void onCashPayStopedSuccess();
void onCashPayStopByMax();
void onCashPayStopByEscrow();
void onCashPayStopByError();
void onCashPayStopByTimeout();
// doors and hardware contacts
void onServiceDoorOpened();
void onVaultDoorOpened();
void onCoinBoxRemoved();
void onCoinBoxInserted();
void onAllDoorsClosed();
void onCBinAndAllDoorsClosed();
// account handling
void private_startAccount();
void private_checkAccountData();
void private_getAccountData();
};
#endif // ATBDEVICECONTROLLERPLUGIN_H

View File

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

View File

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

View File

@@ -0,0 +1,66 @@
/* Machine Event
*
* Used e.g. to send events to ISMAS
*
* Note: It's an Event, not a State!
* -> An Event may cause a transition to a different state, depending on the current state.
* -> Compare to edge/level trigger: Event is an "edge", State is a "level"
* => Do not mix both
*
*/
#include <QDateTime>
#include "ATBMachineEvent.h"
ATBMachineEvent::ATBMachineEvent(
const QString & id,
const QString & deviceName, // PTU/PRINTER/DC/...
EVENT_CLASS eventClass, // reason of event: Error/Warning/Alarm
const QString & name, // 'Event': "E001", "W003"
const int state,
const QString & parameter,
const QString & secondLevelInfo)
: QEvent(ATB_MACHINE_EVENT)
, eventId(id)
, deviceName(deviceName)
, machineEventClass(eventClass)
, eventName(name)
, eventState(state)
// timestamp including timezone offset
, timestampString(QDateTime::currentDateTime().toOffsetFromUtc(
QDateTime::currentDateTime().offsetFromUtc()).toString(Qt::ISODate)
)
, parameterString(parameter)
, secondLevelInfoString(secondLevelInfo)
{
}
QString ATBMachineEvent::getEventClassString(EVENT_CLASS eventClass)
{
switch (eventClass) {
case EVENT_CLASS::WARNING:
return "WARNING";
break;
case EVENT_CLASS::ERROR:
return "ERROR";
break;
case EVENT_CLASS::ALARM:
return "ALARM";
break;
case EVENT_CLASS::DEBUG:
return "DEBUG";
break;
case EVENT_CLASS::STATE:
return "STATE";
break;
case EVENT_CLASS::NOT_DEFINED:
return "NOT_DEFINED";
break;
}
return "NOT_DEFINED";
}

View File

@@ -0,0 +1,47 @@
#ifndef ATBMACHINECONDITIONEVENT_H
#define ATBMACHINECONDITIONEVENT_H
#include <QEvent>
#include <QString>
enum class EVENT_CLASS : quint8;
const QEvent::Type ATB_MACHINE_EVENT = static_cast<QEvent::Type>(QEvent::User + 2);
class ATBMachineEvent : public QEvent
{
public:
explicit ATBMachineEvent(const QString & id,
const QString & deviceName, // PTU/PRINTER/DC/...
EVENT_CLASS eventClass, // reason of event: Error/Warning/Alarm
const QString & name, // 'Event': "E001", "W003"
const int state,
const QString & parameter,
const QString & secondLevelInfo
);
QString eventId;
QString deviceName;
EVENT_CLASS machineEventClass;
QString eventName;
int eventState;
QString timestampString;
QString parameterString;
QString secondLevelInfoString;
static QString getEventClassString(EVENT_CLASS eventClass);
};
enum class EVENT_CLASS : quint8 {
WARNING,
ERROR,
ALARM,
DEBUG,
STATE,
NOT_DEFINED
};
#endif // ATBMACHINEEVENT_H

View File

@@ -0,0 +1,382 @@
#include "DeviceControllerDiag.h"
#include <QCoreApplication>
#include <QUuid>
#include <QDebug>
DeviceControllerDiag::DeviceControllerDiag(QObject *parent)
: QObject(parent)
, eventReceiver(nullptr)
, isRequestRunning(false)
, flagInterruptDiag(false)
{
diagRequestTimeoutTimer = new QTimer(this);
diagRequestTimeoutTimer->setInterval(1000*20); // 20s
diagRequestTimeoutTimer->setSingleShot(true);
connect(diagRequestTimeoutTimer, &QTimer::timeout, this, &DeviceControllerDiag::onDiagRequestTimeoutTimerTimeout);
}
void DeviceControllerDiag::init(hwinf *hw, QObject* eventReceiver)
{
this->hw = hw;
this->eventReceiver = eventReceiver;
// make a system check on startup:
QTimer::singleShot(2000, this, &DeviceControllerDiag::diagRequest);
}
void DeviceControllerDiag::diagRequest()
{
qCritical() << "DeviceControllerDiag::diagRequest()";
if (this->isRequestRunning) {
qCritical() << "DeviceControllerDiag::diagRequest() is already running";
return;
}
this->isRequestRunning = true;
this->diagRequestTimeoutTimer->start();
this->private_startDiag();
}
void DeviceControllerDiag::onDiagRequestTimeoutTimerTimeout()
{
qCritical() << "DeviceControllerDiag::onDiagRequestTimeoutTimerTimeout()";
this->flagInterruptDiag = true;
}
void DeviceControllerDiag::private_startDiag()
{
// check for DiagRequestTimeoutTimerTimeout:
if (this->flagInterruptDiag) {
qCritical() << "DeviceControllerDiag::private_startDiag() interrupted!";
this->private_finishedDiag(0xff);
return;
}
bool result;
result = hw->sys_areDCdataValid();
if (result) {
qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is valid";
QTimer::singleShot(200, this, &DeviceControllerDiag::sys_superviseSystem);
}
else {
qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is +++not+++ valid";
// try it again
QTimer::singleShot(200, this, &DeviceControllerDiag::private_startDiag);
}
}
void DeviceControllerDiag::sys_superviseSystem()
{ // this function proofs if vending is possible depending of doors state
struct T_dynamicCondition dynMaCond;
struct T_moduleCondition modCond;
qCritical() << " sys_superviseSystem()";
// check for DiagRequestTimeoutTimerTimeout:
if (this->flagInterruptDiag) {
qCritical() << "DeviceControllerDiag::sys_superviseSystem() interrupted!";
this->private_finishedDiag(0xff);
return;
}
if (!hw->sys_areDCdataValid())
{
// es gibt keinerlei gültige Daten vom DC
qCritical() << "DeviceControllerDiag::sys_superviseSystem() no valid data!";
this->private_finishedDiag(0xfe);
return;
}
// jetzt sind die DC-Daten aktuell, also reinholen:
hw->sys_getDynMachineConditions(&dynMaCond);
hw->sys_getDeviceConditions(&modCond);
qCritical() << "DeviceControllerDiag::sys_superviseSystem() get condition data";
if (!modCond.allModulesChecked)
{
// noch keine Testergebnisse
if (dynMaCond.startupTestIsRunning) {
// TODO?
}
qCritical() << " allModulesChecked is false --> call again";
QTimer::singleShot(200, this, &DeviceControllerDiag::sys_superviseSystem);
return;
}
// all doors: 99: undefined 0:closed 1:open
if (dynMaCond.lowerDoor || dynMaCond.upperDoor) {
// Service or battery door is open, goto INTRUSION MODE
qCritical() << "DeviceControllerDiag::sys_superviseSystem() Service or battery door is open, goto INTRUSION MODE";
this->private_finishedDiag(0xFD);
return;
}
if (dynMaCond.middleDoor) {
// vault door is open, goto INTRUSION MODE
qCritical() << "DeviceControllerDiag::sys_superviseSystem() vault door is open, goto INTRUSION MODE";
this->private_finishedDiag(0xFC);
return;
}
qCritical() << " --> call sub_componentAssessment()";
uint8_t proposedError = sub_componentAssessment();
if (proposedError) {
// All doors are closed but errors found, goto OOO MODE (out-of-order)
qCritical() << "DeviceControllerDiag::sys_superviseSystem() All doors are closed but errors found, goto OOO MODE (out-of-order)";
this->private_finishedDiag(proposedError);
return;
}
// everything fine
qCritical() << "DeviceControllerDiag::sys_superviseSystem() everything fine";
this->private_finishedDiag(0x00);
}
uint8_t DeviceControllerDiag::sub_componentAssessment()
{
// this function decides if vending mode is possible, independant from door
// return >0 in case of error
struct T_moduleCondition modCond;
hw->sys_getDeviceConditions(&modCond);
struct T_dynamicCondition dynMaCond;
hw->sys_getDynMachineConditions(&dynMaCond);
struct T_devices devPara;
hw->sys_restoreDeviceParameter(&devPara);
if (modCond.rtc>=200)
return 1;
if (modCond.printer==200 || modCond.printer==201) // 200: not connected 201: printer-HW-error 202: no paper
return 2;
if (modCond.printer==202)
return 3;
if (modCond.coinBlocker>=200)
return 4;
if (modCond.mdbBus>=200)
return 5;
if (modCond.intEe>=200)
return 6;
if (devPara.kindOfCoinChecker==1 || devPara.kindOfCoinChecker==2) // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW)
{
if (modCond.coinChecker>=200 || modCond.coinEscrow>=200)
{
// Fehler Münzver.
return 7;
}
if (modCond.coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok
{
return 8;
}
} else
if (devPara.kindOfCoinChecker==3)
{
if (modCond.changer>=200)
{
// Fehler Münzver.
return 7;
}
if (modCond.coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok
{
return 8;
}
}
if ( modCond.billReader>=200 && devPara.BillAcceptor>0)
{
// Fehler BNA
return 9;
}
if (dynMaCond.onAlarm>0)
return 10;
if (dynMaCond.modeAbrech>0)
return 11;
if (dynMaCond.nowCardTest>0)
return 12;
if (dynMaCond.startupTestIsRunning>0)
return 13;
if (modCond.voltage>=200)
return 14;
if (modCond.temper>=200)
return 15;
return 0;
}
uint8_t DeviceControllerDiag::sys_getSystemErrors()
{
// 0: everything fine 1..15: errors
/* 1: real time clock error
2: printer error
3: no paper
4: coin blocker
5: mdb error
6: mem error int.ee.
7: error coin validator
8: coin safe missed or full
9: bill acceptor error
10: alarm / intrusion
11: cash box change is ongoing
12: card test running
13: startup-test is running
14: voltage error
15: temperature error
*/
return this->sub_componentAssessment();
}
/**
* @brief DeviceControllerDiag::private_finishedDiag
* @param result - result value from 'sub_componentAssessment()',
* - 0xFF on timer interrupt
* - 0xFE no valid data from DeviceController
* - 0xFD Service or battery door is open
* - 0xFE vault door is open
*/
void DeviceControllerDiag::private_finishedDiag(uint8_t result)
{
this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false;
this->flagInterruptDiag = false;
if (result == 0) return;
qCritical() << "DeviceControllerDiag::private_finishedDiag() result: " << result;
if (this->eventReceiver == nullptr) {
qCritical() << "DeviceControllerDiag: no eventReceiver";
return;
}
if (result > 15 && result != 0xFE) return;
// Errors are in this range 1...15:
QString eventId = QUuid::createUuid().toString(QUuid::WithoutBraces).mid(0, 8);
QString eventName;
EVENT_CLASS eventClass = EVENT_CLASS::STATE;
QString parameter;
switch (result) {
case 1: // real time clock error
eventName = "E001";
eventClass = EVENT_CLASS::ERROR;
parameter = "real time clock error";
break;
case 2: // printer error
eventName = "E002";
eventClass = EVENT_CLASS::ERROR;
parameter = "printer error";
break;
case 3: // no paper
eventName = "E003";
eventClass = EVENT_CLASS::ERROR;
parameter = "no paper";
break;
case 4: // coin blocker
eventName = "E004";
eventClass = EVENT_CLASS::ERROR;
parameter = "coin blocker";
break;
case 5: // mdb error
eventName = "E005";
eventClass = EVENT_CLASS::ERROR;
parameter = "mdb error";
break;
case 6: // mem error int.ee.
eventName = "E006";
eventClass = EVENT_CLASS::ERROR;
parameter = "mem error int.ee.";
break;
case 7: // error coin validator
eventName = "E007";
eventClass = EVENT_CLASS::ERROR;
parameter = "error coin validator";
break;
case 8: // coin safe missed or full
eventName = "E008";
eventClass = EVENT_CLASS::ERROR;
parameter = "coin safe missed or full";
break;
case 9: // bill acceptor error
eventName = "E009";
eventClass = EVENT_CLASS::ERROR;
parameter = "bill acceptor error";
break;
case 10: // alarm / intrusion
eventName = "E010";
eventClass = EVENT_CLASS::ERROR;
parameter = "alarm / intrusion";
break;
case 11: // cash box change is ongoing
eventName = "E011";
eventClass = EVENT_CLASS::STATE;
parameter = "cash box change is ongoing";
break;
case 12: // card test running
eventName = "E012";
eventClass = EVENT_CLASS::STATE;
parameter = "card test running";
break;
case 13: // startup-test is running
eventName = "E013";
eventClass = EVENT_CLASS::STATE;
parameter = "startup-test is running";
break;
case 14: // voltage error
eventName = "E014";
eventClass = EVENT_CLASS::ERROR;
parameter = "voltage error";
break;
case 15: // temperature error
eventName = "E015";
eventClass = EVENT_CLASS::STATE;
parameter = "temperature error";
break;
case 0xFE: // no valid data from DeviceController
eventName = "E254";
eventClass = EVENT_CLASS::STATE;
parameter = "no valid data from DeviceController";
break;
}
ATBMachineEvent *machineEvent = new ATBMachineEvent(
eventId,
"DC",
eventClass,
eventName,
1,
parameter,
"" // second level info
);
//emit diagResponse(machineEvent);
QCoreApplication::postEvent(eventReceiver, machineEvent);
}

View File

@@ -0,0 +1,49 @@
#ifndef DEVICECONTROLLERDIAG_H
#define DEVICECONTROLLERDIAG_H
#include <QObject>
#include <QTimer>
#include "ATBMachineEvent.h"
#include "interfaces.h"
class DeviceControllerDiag : public QObject
{
Q_OBJECT
public:
DeviceControllerDiag(QObject *parent = nullptr);
void init(hwinf* hw, QObject* eventReceiver);
public slots:
void diagRequest();
signals:
void diagResponse(ATBMachineEvent* machineEvent);
private:
QObject *eventReceiver;
hwinf* hw;
bool isRequestRunning;
bool flagInterruptDiag;
QTimer *diagRequestTimeoutTimer;
uint8_t sub_componentAssessment();
uint8_t sys_getSystemErrors();
private slots:
void onDiagRequestTimeoutTimerTimeout();
void private_startDiag(); // diag entry method
void private_finishedDiag(uint8_t result); // diag exit method
void sys_superviseSystem();
};
#endif // DEVICECONTROLLERDIAG_H

View File

@@ -0,0 +1,190 @@
#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;
enum class TICKET_VARIANT : quint8;
}
class DeviceControllerInterface : public QObject
, public ATBAPPplugin
{
Q_OBJECT
Q_INTERFACES(ATBAPPplugin)
public:
virtual ~DeviceControllerInterface() {}
/**
* @brief initDCPlugin
* @param eventReceiver - QObject to receive ATBMachineEvents or HealthEvents
* @param settings
* @return
*/
virtual nsDeviceControllerInterface::PLUGIN_STATE initDCPlugin(QObject *eventReceiver,
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: Account -------------------------------------------------------------
virtual void requestAccount() = 0;
// TASKS: printing ------------------------------------------------------------
virtual void requestPrintTicket(const QHash<QString, QVariant> & printingData) = 0;
virtual void requestPrintTicket(nsDeviceControllerInterface::TICKET_VARIANT ticketVariant, const QHash<QString, QVariant> & printingData) = 0;
virtual void requestPrintReceipt(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;
public slots:
virtual void onChangedProgramModeToSELL() = 0;
virtual void onChangedProgramModeToSERVICE() = 0;
virtual void onChangedProgramModeToIDLE() = 0;
virtual void onChangedProgramModeToOOO() = 0;
virtual void startPhysicalLayer() = 0;
virtual void stopPhysicalLayer() = 0;
signals:
void printTicketFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & errorCode,
const QString & errorDescription);
/**
* emitted on e.g. a coin input
*/
void cashInputEvent(nsDeviceControllerInterface::RESULT_STATE resultState,
nsDeviceControllerInterface::CASH_STATE cashState,
const QString & newCashValue,
/* additional variables? */
const QString & errorCode,
const QString & errorDescription);
/**
* 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
*/
void cashInputFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & newCashValue,
/* additional variables? */
const QString & errorCode,
const QString & errorDescription);
/**
* emitted e.g. if service door is opened
*/
void requestModeSERVICE();
/**
* emitted e.g. if doors are closed
*/
void requestModeIDLE();
/**
* emitted e.g. on severe errors
*/
void requestModeOOO();
/**
* emitted e.g. if service door is opened
*/
void requestAccountResponse(const QHash<QString, QVariant> & accountData);
/**
* emitted on error
* depending on errorCode:
* -> interrupt selling process
* -> machine can go to state OOO
* -> send error event to ISMAS
* -> ...
*/
void Error(
/* additional variables? */
const QString & errorCode,
const QString & errorDescription);
};
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. */
};
enum class TICKET_VARIANT : quint8 {
PARKING_TICKET,
RECEIPT,
ERROR_RECEIPT,
START_RECEIPT, // e.g. Szeged Start
STOP_RECEIPT, // e.g. Szeged Stop
};
}
#endif // DEVICECONTROLLERINTERFACE_H

18
src/ATBAPP/Utils.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include "Utils.h"
Utils::Utils(QObject *parent) : QObject(parent)
{
}
int Utils::compare(const void* a, const void* b)
{
int int_a = * ( (int*) a );
int int_b = * ( (int*) b );
if ( int_a == int_b ) return 0;
else if ( int_a < int_b ) return -1;
else return 1;
}

23
src/ATBAPP/Utils.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef UTILS_H
#define UTILS_H
#include <QObject>
class Utils : public QObject
{
Q_OBJECT
public:
static int compare(const void* a, const void* b);
private:
explicit Utils(QObject *parent = nullptr);
signals:
};
#endif // UTILS_H