Compare commits

..

1 Commits

Author SHA1 Message Date
fb75074955 Checking to test compilation 2023-04-26 14:39:32 +02:00
34 changed files with 3213 additions and 3423 deletions

42
.gitignore vendored
View File

@@ -1,41 +1 @@
# 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
*.user

View File

@@ -11,7 +11,9 @@ HEADERS += $${PWD}/include/com.h \
$${PWD}/include/sendWRcmd.h \
$${PWD}/include/storeINdata.h \
$${PWD}/include/tslib.h \
$${PWD}/include/shared_mem_buffer.h
$${PWD}/include/shared_mem_buffer.h \
$${PWD}/include/serial_port_thread.h \
$${PWD}/include/serial_port_worker.h
SOURCES += $${PWD}/src/com.cpp \
$${PWD}/src/controlBus.cpp \
@@ -22,4 +24,6 @@ SOURCES += $${PWD}/src/com.cpp \
$${PWD}/src/sendWRcmd.cpp \
$${PWD}/src/storeINdata.cpp \
$${PWD}/src/tslib.cpp \
$${PWD}/src/shared_mem_buffer.cpp
$${PWD}/src/shared_mem_buffer.cpp \
$${PWD}/src/serial_port_thread.cpp \
$${PWD}/src/serial_port_worker.cpp

View File

@@ -14,8 +14,6 @@ QMAKE_CXXFLAGS += -Wno-deprecated-copy
# default
ARCH = PTU5
include(DCPlugin.pri)
contains( CONFIG, DesktopLinux ) {
QMAKE_CC = ccache $$QMAKE_CC
QMAKE_CXX = ccache $$QMAKE_CXX
@@ -23,6 +21,7 @@ contains( CONFIG, DesktopLinux ) {
# QMAKE_CXXFLAGS += -Wno-deprecated-ctor
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
ARCH = DesktopLinux
include(DCPlugin.pri)
}
contains( CONFIG, PTU5 ) {
@@ -32,23 +31,22 @@ contains( CONFIG, PTU5 ) {
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
CONFIG += link_pkgconfig
ARCH = PTU5
# NOTE: include contents of DCPlugin.pri. Also used by ATBQT.
# Add new files in DCPlugin.pri.
include(DCPlugin.pri)
}
contains( CONFIG, PTU5_YOCTO ) {
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
TARGET = CashAgentLib
DESTDIR = ../plugins
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
@@ -68,27 +66,3 @@ DEFINES += QT_DEPRECATED_WARNINGS
#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

@@ -308,8 +308,6 @@ class T_datif : public QMainWindow
QTimer *datif_trigger;
uint8_t selectedSlaveAddr;
int datif_noResponseCtr;
private slots:
char datif_cycleSend();
void StoredRecData();
@@ -326,7 +324,6 @@ public:
// 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();

View File

@@ -78,7 +78,7 @@ uint8_t dcBL_getResult(void);
#define RAW_BL_DATALEN 150
void gpi_storeRawReceivedData(uint8_t RdDlen, uint8_t *receivedData);
void gpi_storeRawReceivedData(uint8_t RdDlen, uint8_t const *receivedData);
uint8_t epi_getRawReceivedData(uint8_t *receivedData);
// retval=length, will be zeroed after first reading

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

View File

@@ -17,14 +17,78 @@ matching interfaces.h:
//#define HWINF_iid "Atb.Psa2020.software.HWapi/3.1"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.1"
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.3"
PSA1259 hardware control using the DeviceController DC2
covering enclosure (switches and doors) and money devices,
controls mifare card to access or program
optional it can control printer, modem, bar code reader and credit card
* API to the PSA1259 Hardware
* All data come in from device controller via serial interface and will be stored
* in "PI" = peripheral image
* PI is updated every 100ms (up to 30ms possible)
* This api uses stored pi data and returns them in the following functions
* created: Q1/2020 TS
*
The devices, connected to device controller2 (DC2) can be controlled in different access levels.
Level 1:
direct connection to DC2, check versions, state and parameters
control serial interfaces
digital/analog IO's
read and write to connected devices on lowest level, this is a kind of fall-back-level
in case higher levels fail or do not support the needed (new) function
Example: send a specific printer command, several bytes that need to be conform to
printer manual. This command is routed to the printer through the DC2 without
any action of the DC. You can write your own device driver that way.
Level 1 is flexible but complicated
Level 2:
The DC controls the connected devices containing a device driver. The DC offers
usage of the device by simple commands,
Example: "Printer on", "set Font size 3" "print "hello world"", "cut"
In opposite to level 1 where you had to send a set of numbers and letters.
In other words: you "talk" to the device controller, not to the device itself.
Level 3:
start/stop complete processes.
Example: 1) print (predefined) document nr 3 with Text, letter size, font set, cut.
Also power up/down the printer, check if paper ok and so on.
*/
/*
Another access example: control the coin unit
Level 1): read digital inputs to detect coin,
switch digital output which opens coin slot
communicate with coin checker by certain mdb-commands (manual conform)
poll coin checker for inserted coins
close coin slot after 3seconds by setting DO to 0....
Level 2): get message of attached coin from DC
send command "initialize coin checker" to DC
send command "open slot for 3s"
poll DC for inserted coins, DC polls coin checker in right way, no need
to know the data sheet of the coin checker or mdb-bus
command to DC "open coin escrow's return flap for 1s"
Level 3): send command: "start payment process"
all coin devices are started up
coin blocker opens for 3s if a coin is attached
coin checker summarizes inserted value and reports sum
later send command "stop payment process" (puts coins to vault) or
send command "cancel payment process" (returns coins to user)
*/
#ifndef hwapi_H
#define hwapi_H
#include <stdint.h>
#include <QTimer>
#include <QTabWidget>
#include <QtPlugin>
#include <QObject>
#include "interfaces.h"
#include "datIf.h"
@@ -34,10 +98,10 @@ class hwapi : public QObject,
public hwinf
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "Atb.Psa2020.software.HWapi/1.0" ) //FILE "HWapi.json")
Q_INTERFACES(hwinf)
private:
void sub_storeSendingText(QByteArray *buf) const;
QTimer *hwapi_TimerPayment;
DownloadResult sendNextAddress(int bNum) const;
DownloadResult sendNextDataBlock(QByteArray const &b, int bNum) const;
@@ -54,13 +118,13 @@ private:
QSharedMemory *m_sharedMem;
public:
explicit hwapi(QObject *parent = nullptr);
explicit hwapi(QWidget *parent = nullptr);
virtual ~hwapi();
T_datif *myDatif;
virtual QStringList dc_getStatus() const override;
virtual QStringList dc_getStatus() const;
// ------------------------------------------------------------------------------
// Level 0 commands, interface
@@ -184,13 +248,6 @@ public:
uint8_t bl_exitBL(uint8_t *sendData) const override;
// minimum size of sendData-buffer: 5byte retval: length
// ------------------------------------------------------------------------------
// Level 2 DC2-onboard devices
// WR: set time
@@ -993,17 +1050,6 @@ public:
bool cash_startPayment(uint32_t amount) const override;
// 17.4.23TS: extended to 32bit
uint8_t cash_paymentProcessing(void) const override;
// run this function periodically while coin payment process to generate necessary signals
// return value:
// 0: stopped 1: starting up 2: coin collection
// 3: finished by User (Push button) 4: finished, Max-Value collected
// 5: finished by escrow
// 10,11: error cannot start
// 12: timeout while payment, coins returned
// 13: stopped by unexpected error
bool cash_cancelPayment(void) const override;
// and return coins
@@ -1037,16 +1083,6 @@ public:
uint64_t sys_getWakeSource(void) const override;
// retval: 6 bytes, bit coded, 1=event keeps DC awake
uint8_t sys_getWakeReason(void) const override;
// Master was woken by following reason:
// 1: MDB Event
// 2: Coin Event
// ( 3: Master Event) - will not set the wake line
// ( 4: 32s pulse) - will not set the wake line
// 5: Door Event
// ( 6: Diag Event) - will not set the wake line
// 7: 30min-Pulse for HB
void sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const override;
void sys_getDeviceConditions(struct T_moduleCondition *devCond) const override;
@@ -1069,80 +1105,18 @@ public:
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
void sys_sendDeviceParameter(struct T_devices *deviceSettings) const override;
void sys_restoreDeviceParameter(struct T_devices *deviceSettings) const override;
bool sys_areDCdataValid(void) const override;
/* ---------------------------------------------------------------------------------------------
// ------------ supervise all hardware components
// ------------ assess the machine state
1. check if DC startup test is through, retrigger if not
2. get results and find errors
3. in case of error check if component is used (e.g. billreader is seldom used)
4: check doors
5. return value: 0: no response from DC
1: no Test results and Test not running. need retrigger!
2: state not clear by now, test ongoing, wait
3: Service or battery door is open, goto INTRUSION MODE
from here: after valid ID-card goto SERVICE MODE
4: vault door is open, goto INTRUSION MODE
from here: after valid ID-card and vault door closed goto TEST MODE
in TEST MODE: complete system check decides if vending mode allowed
5: All doors are closed but errors found,
goto OOO MODE (out-of-order)
from here: run system test until problem is fixed
6: All doors are closed, no error, maybe warnings,
goto VENDING MODE (normal operation)
(priority sinks from 0 to 6)
--------------------------------------------------------------------------------------------- */
uint8_t sys_componentAssessment(void) const override;
// this function decides if vending mode is possible, independant from door
// return >0 in case of error
// is inncluded in sys_superviseSystem
uint8_t sys_superviseSystem(void) const override;
// this function proofs if vending is possible depending of doors state
uint8_t sys_getSystemErrors(void) const override;
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
signals:
void hwapi_templatePrintFinished_OK(void) const override;
void hwapi_templatePrintFinished_Err(void) const override;
void hwapi_coinCollectionJustStarted(void) const override;
void hwapi_coinCollectionAborted(void) const override;
void hwapi_gotNewCoin(void) const override;
void hwapi_payStopByMax(void) const override;
void hwapi_payStopByPushbutton(void) const override;
void hwapi_payStopByEscrow(void) const override;
void hwapi_payStopByError(void) const override;
void hwapi_payStopByTimeout(void) const override;
void hwapi_payCancelled(void) const override;
void hwapi_coinProcessJustStopped(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);
void hwapi_slotPayProc(void);
};

View File

@@ -76,8 +76,8 @@ struct Tprn_currentSettings {
struct T_dynDat {
uint8_t licensePlate[8];
uint8_t vendingPrice[8];
uint8_t parkingEndTime[8];
uint8_t parkingEndDate[8];
uint8_t parkingEnd[8];
uint8_t currentTime[8];
uint8_t currentDate[8];
uint8_t dynDat5[8];
uint8_t dynDat6[8];
@@ -182,25 +182,29 @@ struct T_moduleCondition {
uint8_t ResetReason;
uint8_t allModulesChecked;
uint8_t alarmState;
uint8_t res11;
uint8_t res12;
uint8_t res13;
};
struct T_dynamicCondition {
char allDoorsDebounced; // 99: undefined, 0=all closed, bit1=upper door open 2=midlle door open 3=lower door open
char allDoorsDebounced;
char openedAuthorized;
uint8_t CBinDebounced;
char upperDoor; // 99: undefined 0:closed 1:open
char middleDoor; // 99: undefined 0:closed 1:open
char lowerDoor; // 99: undefined 0:closed 1:open
char reserve; // not used, always 0
char upperDoor; // 0:fehlt 1:drin
char middleDoor;
char lowerDoor;
char coinBox;
char billBox;
char modeAbrech;
char onAlarm; // 0:alarm aus 1:alarm 2:alarm mit Sirene 3: Sirenentest
char onAlarm;
char nowCardTest;
char nowPayment;
char lastMifCardType;
uint8_t lastSDoorState;
uint8_t lastVDoorState;
uint8_t lastCBstate; // 99: undefined 0:not there 1:insered
uint8_t lastCBstate;
char paymentInProgress;
char res1;
uint16_t U_Batt;
@@ -228,8 +232,7 @@ struct T_dynamicCondition {
// bit4: paper jam in cutter
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
uint8_t startupTestIsRunning;
//54
//54
};
struct T_extTime {
@@ -260,39 +263,6 @@ struct T_extTime {
uint32_t MinutesOfMillenium;
};
typedef uint8_t UCHAR;
typedef uint16_t UINT;
struct T_devices
{
// set by master, used(1) or notused (0) or type 2....20
UCHAR kindOfPrinter; // 0:off 1:Gebe
UCHAR kindOfCoinChecker; // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW)
UCHAR kindOfMifareReader; // by now only stronglink SL025 =1
UCHAR suppressSleepMode; // 0:sleep allowed 1: no sleep
UCHAR kindOfModem; // 0:off 1:Sunlink
UCHAR kindOfCreditcard; // 0:off 1:Feig NFC
UCHAR CoinEscrow;
UCHAR CoinRejectUnit;
UCHAR CoinShutter;
UCHAR BillAcceptor;
UCHAR usevaultLock;
UCHAR autoAlarm; // 1: switch on siren for 1min in doors opened unauthorized
UCHAR autoOpen; // 1: open door covers after valid ATBcard
UCHAR printAccReceipt; // 0/1
UCHAR printDoorReceipt;
UCHAR printTokenTicket;
UINT VaultFullWarnLevel;
UINT VaultFullErrorLevel;
};
class hwinf {
public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
@@ -1452,8 +1422,6 @@ public:
virtual bool cash_startPayment(uint32_t amount) const=0;
// 17.4.23TS: extended to 32bit
virtual uint8_t cash_paymentProcessing(void) const=0;
virtual uint32_t getInsertedAmount(void) const=0;
virtual uint16_t getLastInsertedCoin(void) const=0;
@@ -1483,16 +1451,6 @@ public:
virtual uint64_t sys_getWakeSource(void) const =0;
// retval: 6 bytes, bit coded, 1=event keeps DC awake
virtual uint8_t sys_getWakeReason(void) const=0;
// Master was woken by following reason:
// 1: MDB Event
// 2: Coin Event
// ( 3: Master Event) - will not set the wake line
// ( 4: 32s pulse) - will not set the wake line
// 5: Door Event
// ( 6: Diag Event) - will not set the wake line
// 7: 30min-Pulse for HB
virtual void sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const=0;
/*
@@ -1614,79 +1572,12 @@ public:
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
virtual void sys_sendDeviceParameter(struct T_devices *deviceSettings) const=0;
virtual void sys_restoreDeviceParameter(struct T_devices *deviceSettings) const=0;
virtual bool sys_areDCdataValid(void) const=0;
/* ---------------------------------------------------------------------------------------------
// ------------ supervise all hardware components
// ------------ assess the machine state
1. check if DC startup test is through, retrigger if not
2. get results and find errors
3. in case of error check if component is used (e.g. billreader is seldom used)
4: check doors
5. return value: 0: no response from DC
1: no Test results and Test not running. need retrigger!
2: state not clear by now, test ongoing, wait
3: Service or battery door is open, goto INTRUSION MODE
from here: after valid ID-card goto SERVICE MODE
4: vault door is open, goto INTRUSION MODE
from here: after valid ID-card and vault door closed goto TEST MODE
in TEST MODE: complete system check decides if vending mode allowed
5: All doors are closed but errors found,
goto OOO MODE (out-of-order)
from here: run system test until problem is fixed
6: All doors are closed, no error, maybe warnings,
goto VENDING MODE (normal operation)
(priority sinks from 0 to 6)
--------------------------------------------------------------------------------------------- */
virtual uint8_t sys_componentAssessment(void) const=0;
// this function decides if vending mode is possible, independant from door
// return >0 in case of error
// is inncluded in sys_superviseSystem
virtual uint8_t sys_superviseSystem(void) const=0;
// this function proofs if vending is possible depending of doors state
virtual uint8_t sys_getSystemErrors(void) const=0;
// retrigger System-Check with:
// bool hwapi::sys_runCompleteTest(void) const
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
signals:
virtual void hwapi_templatePrintFinished_OK(void) const=0;
virtual void hwapi_templatePrintFinished_Err(void) const=0;
virtual void hwapi_coinCollectionJustStarted(void) const=0;
virtual void hwapi_coinCollectionAborted(void) const=0;
virtual void hwapi_gotNewCoin(void) const=0;
virtual void hwapi_payStopByMax(void) const=0;
virtual void hwapi_payStopByPushbutton(void) const=0;
virtual void hwapi_payStopByEscrow(void) const=0;
virtual void hwapi_payStopByError(void) const=0;
virtual void hwapi_payStopByTimeout(void) const=0;
virtual void hwapi_payCancelled(void) const=0;
virtual void hwapi_coinProcessJustStopped(void) const=0;
virtual void hwapi_vendStopByMax(void) const=0;
virtual void hwapi_vendStopByPushbutton(void) const=0;
};

View File

@@ -148,21 +148,23 @@
// highest priority
#define CMDSTACKDEPTH 16
// #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);
bool sendWRcmd_setSendCommand0(uint16_t nextCmd, uint8_t dat1=0, uint8_t dat2=0,
uint8_t dat3=0, uint8_t dat4=0);
// GUI or app sends a command to DC transfered by serial
uint16_t sendWRcmd_getSendCommand0(void);
uint16_t sendWRcmd_getSendCommand0(uint8_t *dat1=0, uint8_t *dat2=0,
uint8_t *dat3=0, uint8_t *dat4=0);
// lower priority
#define CMD4STACKDEPTH 8
// #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
// #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);
@@ -171,7 +173,7 @@ uint16_t sendWRcmd_getSendCommand8(uint8_t *dat1, uint8_t *dat2, uint16_t *dat3,
// lowest priority
// wait for resonse before send next!
bool sendWRcmd_setSendBlock160(uint8_t leng, uint8_t *buf);
bool sendWRcmd_setSendBlock160(uint8_t leng, uint8_t const *buf);
uint8_t sendWRcmd_getSendBlock160(uint8_t *leng, uint8_t *buf);
// retval = *leng
@@ -179,7 +181,7 @@ void sendWRcmd_INI(void);
uint8_t epi_store64ByteSendData(uint8_t length, uint8_t *buf);
uint8_t epi_store64ByteSendData(uint8_t length, uint8_t const *buf);
// HWapi writes data to be forwarded to DC and further to mdb-device
// not batched! don't use twice within 100ms
@@ -211,7 +213,7 @@ uint8_t gpi_getUserOfSendingTextBuffer(uint8_t *para1, uint8_t *para2, uint8_t *
// user=1: Text-Print is using this buffer
// 2: QR-code-Printer is using this buffer
#define FDCMD_STACKDEPTH 16
//#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
@@ -223,9 +225,9 @@ uint8_t check4FDshortCmd(void);
uint8_t check4freeFDshortCmd(void);
// returns number of free places in short-command stack
#define FDLONG_STACKDEPTH 16
//#define FDLONG_STACKDEPTH 16
void longFDcmd_clrStack(void);
bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t length, uint8_t *data);
bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t length, uint8_t const *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);
@@ -237,14 +239,6 @@ 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

@@ -0,0 +1,22 @@
#ifndef SERIAL_PORT_THREAD_H_INCLUDED
#define SERIAL_PORT_THREAD_H_INCLUDED
#include <QThread>
#include <QString>
#include <QEventLoop>
class SerialPortThread : public QThread {
Q_OBJECT
QEventLoop m_loop;
public:
SerialPortThread(QObject *parent = nullptr);
virtual ~SerialPortThread();
virtual void run() override;
QEventLoop &getEventLoop() { return m_loop; }
};
#endif // SERIAL_PORT_THREAD_H_INCLUDED

View File

@@ -0,0 +1,121 @@
#ifndef SERIAL_PORT_WORKER_H_INCLUDED
#define SERIAL_PORT_WORKER_H_INCLUDED
#include <QObject>
#include <QString>
#include <QTimer>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QThread>
#include <assert.h>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <deque>
#include <iostream>
#include <atomic>
struct Command {
enum : uint16_t {PRIORITY_1, PRIORITY_2, PRIORITY_3, PRIORITY_4, END_MARK};
enum : uint16_t {QUIT_SENTINEL = 0x1000, SEND_BLOCK_SIZE = 160};
uint32_t m_priority;
uint16_t m_priorityClass;
uint16_t m_cmdId;
char *m_sendBuffer;
char *m_recvBuffer;
uint8_t m_sendBufferLength;
uint8_t m_recvBufferLength; // expected result length
static std::atomic<uint8_t> m_nextSendBufferIndex;
static std::atomic<uint8_t> m_nextRecvBufferIndex;
static char m_sendBuffers[256][SEND_BLOCK_SIZE];
static char m_recvBuffers[256][SEND_BLOCK_SIZE];
static uint32_t getNextCommandPriority(uint8_t cmdType);
static char *getNextSendBuffer();
static char *getNextRecvBuffer();
public:
Command(uint16_t cmdId, uint8_t sendBufferLength, uint8_t recvBufferLength, uint8_t priorityClass);
Command();
friend bool operator< (Command const& lhs, Command const& rhs) {
return lhs.m_priority < rhs.m_priority;
}
friend std::ostream& operator<< (std::ostream& os, Command const& cmd) {
return os << "{ " << cmd.m_priority << ", '" << cmd.m_priority << "' } ";
}
};
/// \brief SerialPortWorker
///
/// SerialPortWorker sends and receives data from serial port
///
class SerialPortWorker : public QThread {
Q_OBJECT
/// \brief Internal serial port.
QSerialPort m_serialPort;
/// \brief Internal serial port info.
QSerialPortInfo m_serialPortInfo;
/// \brief Flag indicating if serial port is opened.
bool m_serialPortOpened;
/// \brief Port name of serial port.
QString m_portName;
/// \brief Baudrate of internal serial port.
enum QSerialPort::BaudRate m_baudRate;
std::priority_queue<Command, std::deque<Command>> m_sendQueue;
std::deque<Command> m_recvQueue;
std::mutex m_sendQueueMutex;
std::mutex m_recvQueueMutex;
std::condition_variable m_sendQueueCondVar;
std::condition_variable m_recvQueueCondVar;
std::atomic<uint32_t> m_bytesWritten;
std::atomic<uint32_t> m_bytesAvailable;
SerialPortWorker(QString portName, QSerialPort::BaudRate baudRate, QObject *parent = nullptr);
Command getNextCommand();
void insertResult(Command const &result);
enum : uint16_t {TIMEOUT = 100, WAIT_TIME_MAX = 1000};
public:
~SerialPortWorker();
SerialPortWorker(SerialPortWorker const &) = delete;
void operator=(SerialPortWorker const &) = delete;
// serial port im plugin anlegen. erst dann kann getInstance() benutzt werden
static SerialPortWorker &getInstance(QString portName, QSerialPort::BaudRate baudRate, QObject *parent = nullptr) {
static SerialPortWorker serialPortWorker(portName, baudRate, parent);
return serialPortWorker;
}
bool openSerialPort();
void closeSerialPort();
bool isPortOpen() const { return m_serialPortOpened; }
void insertCommand(Command const &cmd);
bool getNextResult(Command &result, int timeout = 1000);
virtual void run() override;
void quit();
private slots:
void getBytesAvailable();
bool getNumberOfBytesWritten(qint64);
};
#endif // SERIAL_PORT_WORKER_H_INCLUDED

View File

@@ -6,7 +6,33 @@
#include <QSharedMemory>
// TODO: pid eintragen und convars/mutexe eintragen
#ifdef __linux__
#include <pthread.h>
// PTHREAD_PROCESS_SHARED
#else
// WIN32
#endif
struct SharedMemBuffer {
int init;
char appName[32];
pid_t pid;
pthread_condattr_t sndCndA;
pthread_cond_t sndCndV;
pthread_mutexattr_t sndMtxA;
pthread_mutex_t sndMtx;
pthread_condattr_t rcvCndA;
pthread_cond_t rcvCndV;
pthread_mutexattr_t rcvMtxA;
pthread_mutex_t rcvMtx;
struct rs {
char comportName[16]; // z.B. "COM48"
char baudStr[16]; // z.B. "19200"
@@ -18,109 +44,130 @@ struct SharedMemBuffer {
char AutoEmissionOn; // 1: zyklisch Anfragen zum Slave senden
struct datif {
#define DATIF_MAXCMDS 16
uint16_t sendingPeriod;
bool sendingPer_changed;
uint8_t OutCmdpara1;
uint8_t OutCmdpara2;
uint8_t OutCmdpara3;
uint8_t OutCmdpara4;
uint16_t OutCmdpara5;
uint32_t OutCmdpara6;
uint8_t dataStep;
uint8_t scanStep;
uint8_t RDBLKNR;
uint8_t cycl_running;
} 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];
struct txt4 {
char comStateLine[32];
char HsStateLine[32];
char masterStateLine[32];
char resultStateLine[32];
char dataLine[32];
char datifReceive[32];
char diagWindow[32];
char sndDiagWindow[32];
} txt4;
// 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;
struct dcBL {
#define SIZEBLRESP 50
#define RAW_BL_DATALEN 150
uint8_t LastBLcmd; // stored the last sent cmd in order to analys response
uint8_t AtbBinFile[300000];
uint32_t fileSize;
uint16_t nrOfBlocks;
uint16_t fileCrc;
uint8_t myBuf[300000]; // same content like "dcBL_AtbBinFile" but bytewise
char Resp[SIZEBLRESP][32];
int pResp;
uint8_t step;
uint8_t state;
uint16_t BlkCtr;
uint16_t cyclCtr;
uint16_t repeatCtr;
} dcBL;
uint16_t datif_OutCmdpara5;
uint32_t datif_OutCmdpara6;
uint8_t cycl_running;
struct {
uint16_t shutterTime;
char ticketTemplate[1024];
} hwapi;
// 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
struct {
uint8_t sendAsynchDataBuf[160]; // no stack, only ONE buffer
uint8_t sendAsyDatLen;
} next;
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;
struct { // highest priority
#define CMDSTACKDEPTH 16
// up to 16 cmd can be stored. They are issued one by one every 100ms
uint16_t AsynchSend[CMDSTACKDEPTH];
uint8_t para1[CMDSTACKDEPTH]; /* used to streamline source */
uint8_t para2[CMDSTACKDEPTH]; /* used to streamline source */
uint8_t para3[CMDSTACKDEPTH]; /* used to streamline source */
uint8_t para4[CMDSTACKDEPTH]; /* used to streamline source */
uint8_t nrOfCmdsInQueue;
} Cmd0;
// hwapi.cpp
uint16_t hwapi_shutterTime;
char ticketTemplate[1024];
struct { // lower priority
// Command Stack for commands with 4 parameters
#define CMD4STACKDEPTH 8
uint16_t AsynchSend[CMD4STACKDEPTH];
uint8_t para1[CMD4STACKDEPTH];
uint8_t para2[CMD4STACKDEPTH];
uint8_t para3[CMD4STACKDEPTH];
uint8_t para4[CMD4STACKDEPTH];
uint8_t nrOfCmdsInQueue;
} Cmd4;
// 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];
struct {
#define CMD8STACKDEPTH 4
uint16_t AsynchSend[CMD8STACKDEPTH];
uint8_t para1[CMD8STACKDEPTH];
uint8_t para2[CMD8STACKDEPTH];
uint16_t para3[CMD8STACKDEPTH];
uint32_t para4[CMD8STACKDEPTH];
uint8_t nrOfCmdsInQueue;
} Cmd8;
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];
struct { // short command, 4 data bytes
#define FDCMD_STACKDEPTH 16
uint8_t wrCmd[FDCMD_STACKDEPTH];
uint8_t rdCmd[FDCMD_STACKDEPTH];
uint8_t blkNr[FDCMD_STACKDEPTH];
uint8_t para1[FDCMD_STACKDEPTH];
uint8_t para2[FDCMD_STACKDEPTH];
uint8_t para3[FDCMD_STACKDEPTH];
uint8_t para4[FDCMD_STACKDEPTH];
uint8_t cmdsInQueue;
} FDShort;
uint8_t longFDpara[16][64];
uint8_t p_longFDcmdsInQueue;
struct { // long command, 64 data bytes
#define FDLONG_STACKDEPTH 16
uint8_t wrCmd[FDLONG_STACKDEPTH];
uint8_t rdCmd[FDLONG_STACKDEPTH];
uint8_t blkNr[FDLONG_STACKDEPTH];
uint8_t length[FDLONG_STACKDEPTH];
uint8_t para[FDLONG_STACKDEPTH][64];
uint8_t cmdsInQueue;
} FDLong;
// storeInData.cpp
bool indat_savePrnPwr;
bool indat_saveMifPwr;
bool indat_MdbIsOn;
#endif
struct {
uint8_t DataParameters[4];
uint8_t DataBufferUser;
uint8_t pDataBuff; // points to next PRINTER_BLOCK
} prn;
uint8_t ndbs;
uint8_t pari;
uint8_t nsb;
uint8_t br;
struct {
bool savePrnPwr;
bool saveMifPwr;
bool MdbIsOn;
} indat;
uint8_t ndbs;
uint8_t pari;
uint8_t nsb;
uint8_t br;
#define MAXNROF_GENSTR 16
char genStrings[MAXNROF_GENSTR][64];
@@ -170,10 +217,13 @@ struct SharedMemBuffer {
#define NROFMIFSTATEBYTES 40
#define PRN_STATE_ARRAY_SIZE 20
#define PRN_STATE_FONT_SIZE 20
#define MAXNROF_PRNBYTES 64
#define MAXNROF_PRNBLOCKS 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];
char PRN_TEXT[MAXNROF_PRNBLOCKS][MAXNROF_PRNBYTES];
bool mdb_busRdy;
bool mdb_V12on;
bool mdb_V5on;
@@ -193,6 +243,10 @@ struct SharedMemBuffer {
uint8_t pProtResultOk;
uint16_t receivedDataLength;
uint8_t receivedDataBlock[64];
uint8_t rawData[150];
uint8_t LengthRawData;
uint8_t mdbSendBuffer[64];
uint8_t mdbSendLen;
} Sdata;
uint8_t mif_cardType;
@@ -225,9 +279,6 @@ struct SharedMemBuffer {
uint8_t vaultrecord[360];
uint32_t amount;
uint16_t nrOfCoins;
bool dcDataValid;
uint8_t wakeReason;
char curPayNewCoin;
} store;
struct T_globTime {

View File

@@ -3,7 +3,7 @@
#define STOREINDATA_H
#include <stdint.h>
//#include "tslib.h"
#include "tslib.h"
#include <QString>
@@ -384,7 +384,6 @@ bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values);
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);
@@ -416,12 +415,6 @@ 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();
bool epi_areDcDataValid();
#endif

1585
plugins/interfaces.h Normal file

File diff suppressed because it is too large Load Diff

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,316 +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
<< " 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->parkingEndTime, ba_parkingEndTime.data(), std::min(ba_parkingEndTime.size(),8));
QByteArray ba_parkingEndDate = codec->fromUnicode(parkingEndDateTime.toString("dd.MM.yy"));
memcpy((char*)dynTicketData->parkingEndDate, ba_parkingEndDate.data(), std::min(ba_parkingEndDate.size(),8));
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;
}
QTimer::singleShot(500, 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(500, this, SLOT(onPrintFinishedOK()));
}
else {
// print next template
this->currentTemplate++;
QTimer::singleShot(1000, 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

@@ -19,7 +19,7 @@ void T_com::writeToSerial(const QByteArray &data, uint16_t sendLength)
sendLen=sendLength;
if (CatSerial->isOpen())
{
qCritical() << "sending..." << sendBuffer;
//qDebug() << "sending..." << sendBuffer;
CatSerial->write(sendBuffer);
} else
qDebug() << "error sending, port is not open";

View File

@@ -96,66 +96,64 @@ bool gpi_PeriodicSendTimeHasChanged() {
// Status Display gui <--> serial
// ///////////////////////////////////////////////////////////////////////////////////
// linke Spalte, über Connect Button
static QString txt4comStateLine;
// linke Spalte, über Connect Button
QString epi_getTxt4comStateLine(void) {
// GUI: get Text for serial Comport-State Line
return txt4comStateLine;
return SharedMemBuffer::getDataConst()->txt4.comStateLine;
}
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;
memset(SharedMemBuffer::getData()->txt4.comStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.comStateLine));
memcpy(SharedMemBuffer::getData()->txt4.comStateLine,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.comStateLine)-1);
}
void epi_clrTxt4comStateLine() {
txt4comStateLine.clear();
memset(SharedMemBuffer::getData()->txt4.comStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.comStateLine));
}
// 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;
return SharedMemBuffer::getDataConst()->txt4.HsStateLine;
}
void gpi_setTxt4HsStateLine(QString txtline) {
txt4HsStateLine.clear();
if (txtline=="")
txt4HsStateLine.clear();
else
txt4HsStateLine=txtline;
// serial: write Text to be displayed in serial Comport-State line (like "connected")
memset(SharedMemBuffer::getData()->txt4.HsStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.HsStateLine));
memcpy(SharedMemBuffer::getData()->txt4.HsStateLine,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.HsStateLine)-1);
}
void epi_clrTxt4HsStateLine() {
txt4HsStateLine.clear();
memset(SharedMemBuffer::getData()->txt4.HsStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.HsStateLine));
}
// 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;
return SharedMemBuffer::getDataConst()->txt4.masterStateLine;
}
void gpi_setTxt4masterStateLine(QString txtline) {
txt4masterStateLine.clear();
if (txtline=="")
txt4masterStateLine.clear();
else
txt4masterStateLine=txtline;
memset(SharedMemBuffer::getData()->txt4.masterStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.masterStateLine));
memcpy(SharedMemBuffer::getData()->txt4.masterStateLine,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.masterStateLine)-1);
}
void epi_clrTxt4masterStateLine() {
txt4masterStateLine.clear();
memset(SharedMemBuffer::getData()->txt4.masterStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.masterStateLine));
}
//---------------------------------------------------------------------------------------------
@@ -164,110 +162,96 @@ void epi_clrTxt4masterStateLine() {
// 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;
return SharedMemBuffer::getDataConst()->txt4.resultStateLine;
}
void gpi_setTxt4resultStateLine(QString txtline) {
txt4resultStateLine.clear();
if (txtline=="")
txt4resultStateLine.clear();
else
txt4resultStateLine=txtline;
memset(SharedMemBuffer::getData()->txt4.resultStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.resultStateLine));
memcpy(SharedMemBuffer::getData()->txt4.resultStateLine,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.resultStateLine)-1);
}
void epi_clrTxt4resultStateLine() {
txt4resultStateLine.clear();
memset(SharedMemBuffer::getData()->txt4.resultStateLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.resultStateLine));
}
//---------------------------------------------------------------------------------------------
// IV Statuszeile Empfangsdaten
static QString txt4dataLine;
QString epi_getTxt4dataStateLine(void) {
// GUI: get Text for serial Comport-State Line
return txt4dataLine;
return SharedMemBuffer::getDataConst()->txt4.dataLine;
}
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;
memset(SharedMemBuffer::getData()->txt4.dataLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.dataLine));
memcpy(SharedMemBuffer::getData()->txt4.dataLine,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.dataLine)-1);
}
void epi_clrTxt4dataStateLine() {
txt4dataLine.clear();
memset(SharedMemBuffer::getData()->txt4.dataLine,
0x00, sizeof(SharedMemBuffer::getData()->txt4.dataLine));
}
//---------------------------------------------------------------------------------------------
// 5. Zeile: Datif Ergebnis, Daten brauchbar?
static QString txt4datifReceive;
QString epi_getTxt4datifLine(void) {
return txt4datifReceive;
return SharedMemBuffer::getDataConst()->txt4.datifReceive;
}
void gpi_setTxt4datifLine(QString txtline) {
txt4datifReceive.clear();
if (txtline=="")
txt4datifReceive.clear();
else
txt4datifReceive=txtline;
memset(SharedMemBuffer::getData()->txt4.datifReceive,
0x00, sizeof(SharedMemBuffer::getData()->txt4.datifReceive));
memcpy(SharedMemBuffer::getData()->txt4.datifReceive,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.datifReceive)-1);
}
void epi_clrTxt4datifLine() {
txt4datifReceive.clear();
memset(SharedMemBuffer::getData()->txt4.datifReceive,
0x00, sizeof(SharedMemBuffer::getData()->txt4.datifReceive));
}
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
static QString txt4diagWindow;
QString epi_getTxt4RsDiagWin(void) {
return txt4diagWindow;
return SharedMemBuffer::getDataConst()->txt4.diagWindow;
}
void gpi_setTxt4RsDiagWin(QString txtline) {
txt4diagWindow.clear();
if (txtline=="")
txt4diagWindow.clear();
else
txt4diagWindow=txtline;
memset(SharedMemBuffer::getData()->txt4.diagWindow,
0x00, sizeof(SharedMemBuffer::getData()->txt4.diagWindow));
memcpy(SharedMemBuffer::getData()->txt4.diagWindow,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.diagWindow)-1);
}
void epi_clrTxt4RsDiagWin() {
txt4diagWindow.clear();
memset(SharedMemBuffer::getData()->txt4.diagWindow,
0x00, sizeof(SharedMemBuffer::getData()->txt4.diagWindow));
}
//---------------------------------------------------------------------------------------------
static QString sndTxt4diagWindow;
QString epi_get2ndTxt4RsDiagWin(void) {
return sndTxt4diagWindow;
return SharedMemBuffer::getDataConst()->txt4.sndDiagWindow;
}
void gpi_set2ndTxt4RsDiagWin(QString txtline) {
sndTxt4diagWindow.clear();
if (txtline=="")
sndTxt4diagWindow.clear();
else
sndTxt4diagWindow=txtline;
memset(SharedMemBuffer::getData()->txt4.sndDiagWindow,
0x00, sizeof(SharedMemBuffer::getData()->txt4.sndDiagWindow));
memcpy(SharedMemBuffer::getData()->txt4.sndDiagWindow,
txtline.toStdString().c_str(),
sizeof(SharedMemBuffer::getData()->txt4.sndDiagWindow)-1);
}
void epi_clr2ndTxt4RsDiagWin() {
sndTxt4diagWindow.clear();
memset(SharedMemBuffer::getData()->txt4.sndDiagWindow,
0x00, sizeof(SharedMemBuffer::getData()->txt4.sndDiagWindow));
}
// ///////////////////////////////////////////////////////////////////////////////////

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()
{
}

View File

@@ -24,18 +24,17 @@
#include "shared_mem_buffer.h"
#include <QDebug>
#include <QSharedMemory>
#include "interfaces.h"
static uint32_t hwapi_lastStartAmount;
static uint8_t hwapi_cash_lastCollectionState;
static uint8_t hwapi_paymentStarted;
static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
{"57600" , 4}, {"115200" , 5}
};
hwapi::hwapi(QObject *parent) : QObject(parent) {
hwapi::hwapi(QWidget *parent) : QObject(parent) {
// create or attach shared memory segment
// !!! The compoment creating the shared memory MUST be ATBQT !!!
m_sharedMem = SharedMemBuffer::getShm(sizeof(SharedMemBuffer));
@@ -53,18 +52,6 @@ hwapi::hwapi(QObject *parent) : QObject(parent) {
connect(myDatif, SIGNAL(datif_templatePrintFinished_OK()), this, SLOT(hwapi_slotPrintFinished_OK()));
connect(myDatif, SIGNAL(datif_templatePrintFinished_Err()), this, SLOT(hwapi_slotPrintFinished_Err()));
connect(myDatif, SIGNAL(datif_gotNewCoin()), this, SLOT(hwapi_slotGotCoin()));
hwapi_TimerPayment = new QTimer();
hwapi_TimerPayment->setSingleShot(true);
QTimer *hwapi_callPayProc = new QTimer();
connect(hwapi_callPayProc, SIGNAL(timeout()), this, SLOT(hwapi_slotPayProc()));
hwapi_callPayProc->setSingleShot(false);
hwapi_callPayProc->start(100); // in ms
hwapi_lastStartAmount=0;
hwapi_cash_lastCollectionState=0;
hwapi_paymentStarted=0;
}
hwapi::~hwapi() {
@@ -73,12 +60,6 @@ hwapi::~hwapi() {
}
}
void hwapi::hwapi_slotPayProc(void)
{
cash_paymentProcessing();
}
void hwapi::hwapi_slotPrintFinished_OK(void) {
emit hwapi_templatePrintFinished_OK();
}
@@ -94,7 +75,7 @@ void hwapi::hwapi_slotGotCoin(void) {
uint32_t newSum=epi_CurrentPaymentGetAmount();
if (newSum>=hwapi_lastStartAmount)
emit hwapi_payStopByMax();
emit hwapi_vendStopByMax();
}
@@ -1791,8 +1772,7 @@ void hwapi::readback_machineIDdata(uint8_t *length, uint8_t *data) const
static uint16_t hwapi_shutterTime;
// locks, 2.Level: (Motor stops automatical on end switch or by 5s timeout)
uint8_t hwapi::lock_openUpperDoor(void) const
{
uint8_t hwapi::lock_openUpperDoor(void) const {
//bool sendWRcmd_setSendCommand4(uint16_t nextCmd, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4);
// commands are defined in PIdefines.h
sendWRcmd_setSendCommand4(SENDDIRCMD_OPENUP_DOOR, 1, 0, 0, 0);
@@ -1820,54 +1800,39 @@ uint8_t hwapi::lock_closeLowerDoor(void) const
return 0;
}
void hwapi::shut_openOnce(void) const
{
void hwapi::shut_openOnce(void) const {
// and close automatic after shutter time
uint16_t zeit=hwapi_shutterTime;
zeit/=100;
uint16_t zeit = (SharedMemBuffer::getDataConst()->hwapi.shutterTime) / 100;
sendWRcmd_setSendCommand4(SENDDIRCMD_SHUTOPENBYTIME, uint8_t(zeit) ,0,0,0);
}
void hwapi::shut_openForCoin(bool start) const
{
void hwapi::shut_openForCoin(bool start) const {
// start=true: start opening flap if coin is attached
// start=false: stop process
uint16_t zeit=hwapi_shutterTime;
zeit/=100;
uint16_t zeit = (SharedMemBuffer::getDataConst()->hwapi.shutterTime) / 100;
sendWRcmd_setSendCommand4(SENDDIRCMD_SHUTOPENBYCOIN, uint8_t(start), uint8_t(zeit),0,0);
}
void hwapi::shut_sendOpeningTime(uint16_t timeIn_ms ) const
{
void hwapi::shut_sendOpeningTime(uint16_t timeIn_ms ) const {
// after this time without retrigger the flap is closed
//sendWRcmd_setSendCommand4(SENDDIRCMD_SHUT_SENDTIME, timeIn100ms,0,0,0);
hwapi_shutterTime=timeIn_ms;
SharedMemBuffer::getData()->hwapi.shutterTime = timeIn_ms;
}
void hwapi::esc_takeMoney(void) const
{
void hwapi::esc_takeMoney(void) const {
// and close automatically after escrow time (1s)
sendWRcmd_setSendCommand0(SENDDIRCMD_ESCRO_TAKE);
}
void hwapi::esc_returnMoney(void) const
{
void hwapi::esc_returnMoney(void) const {
// and close automatically after time
sendWRcmd_setSendCommand0(SENDDIRCMD_ESCRO_GIVE);
}
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- MIFARE -----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
@@ -3535,7 +3500,6 @@ bool hwapi::prn_sendDynamicPrnValues(uint8_t *dynPrnVal ) const
}
bool hwapi::prn_printTemplate(uint8_t nrOftemplate) const
// print one of the templates loaded by Json prior
// nr = 1..32
@@ -3638,192 +3602,11 @@ bool hwapi::cash_startPayment(uint32_t amount) const
dat2=ulong2uchar(amount, 1);
dat3=ulong2uchar(amount, 2);
dat4=ulong2uchar(amount, 3);
hwapi_cash_lastCollectionState=0;
sendFDcmd_set(155, 0,0, dat1,dat2,dat3,dat4);
hwapi_paymentStarted=1;
hwapi_TimerPayment->start(5000); // in ms
return sendFDcmd_set(155, 0,0, dat1,dat2,dat3,dat4);
return true;
}
uint8_t hwapi::cash_paymentProcessing(void) const
{
// run this function periodically while coin payment process to generate necessary signals:
// virtual void hwapi_coinCollectionJustStarted(void) const=0;
// virtual void hwapi_coinCollectionAborted(void) const=0;
// virtual void hwapi_gotNewCoin(void) const=0; // comes from: hwapi_slotGotCoin()
// virtual void hwapi_payStopByMax(void) const=0; // comes from: hwapi_slotGotCoin()
// virtual void hwapi_payStopByPushbutton(void) const=0; // comes from cash_stopPayment()
// virtual void hwapi_payStopByEscrow(void) const=0;
// virtual void hwapi_payStopByError(void) const=0;
// virtual void hwapi_payStopByTimeout(void) const=0;
// virtual void hwapi_payCancelled(void) const=0;
// virtual void hwapi_coinProcessJustStopped(void) const=0;
// return value:
// 0: stopped 1: starting up 2: coin collection
// 3: finished by User (Push button) 4: finished, Max-Value collected
// 5: finished by escrow
// 6: money encashed
// 7: cancelled
// 10,11: error cannot start
// 12: timeout while payment, coins returned
// 13: stopped by unexpected error
struct T_emp empStat;
struct T_dynamicCondition myDynMachCond;
uint8_t collActiv=0, payInProg, empState;
if (hwapi_paymentStarted<1)
return 0; // off
collActiv=1; // starting up payment
emp_getAllParameters(&empStat);
//collActiv=empStat.paymentRunning;
empState=empStat.state;
// 0=start command
// 1=powered, do emp ini, send reset
// 2=delay
// 3=wait for response, requesting status after response
// 4,5 through, startup
// 6: wait for status
// 7: through, startup
// 8: IDLE state. EMP is up and ready, polling is running
// 9: polling on, payment not yet on
// 10: payment, check coins
// 11: through
// 12: wait 1s for last coin
// 90: stop all, 1s delay
// 99: off, all stopped
//qCritical() << "empState = " << empState;
sys_getDynMachineConditions(&myDynMachCond);
payInProg= myDynMachCond.paymentInProgress;
// 0: stopped by timeout
// 1: running 2: wait4lastCoin
// 3: payment stopped manually, coins in Escrow
// 4: payment stopped autom, amount collected, coins in Escrow
// 5: payment stopped, escrow full, coins in Escrow
// 6: coins encashed 7:coins returned
// 8: CoinChecker or MDB on Error
if (payInProg==8)
{
// coin checker faulty, cannot start
if (hwapi_paymentStarted==1)
{
hwapi_paymentStarted=90; // stop due to error
emit hwapi_coinCollectionAborted();
//sendFDcmd_set(156, 0,0, 2,0,0,0); // cancel payment
collActiv=10; // error cannot start
}
} else
if (empState>=10 && empState<=12)
{
// coin acceptance is active now:
hwapi_TimerPayment->stop(); // to avoid error signal
if (hwapi_paymentStarted==1) // 1=wait for coin checker being ready
{
hwapi_paymentStarted=2; // coins can be inserted no
emit hwapi_coinCollectionJustStarted();
}
} else
{
// EMP not (yet) ready
if (!hwapi_TimerPayment->isActive())
{
// 5s after start-payment the coin-checker is still not ready
hwapi_TimerPayment->stop();
if (hwapi_paymentStarted==1)
{
hwapi_paymentStarted=90; // stop due to error
emit hwapi_coinCollectionAborted(); // error cannot start
//sendFDcmd_set(156, 0,0, 2,0,0,0); // cancel payment
collActiv=11; // error cannot start
}
}
}
if (hwapi_paymentStarted==2)
{
collActiv=2; // coin collection active
// coins can be inserted now, wait for end
if (payInProg==0) // timeout
{
hwapi_paymentStarted++;
collActiv=12; // stop by timeout
emit hwapi_payStopByTimeout();
} else
if (payInProg==3) // user pressed "Next/Continue"
{
hwapi_paymentStarted++;
collActiv=3;
emit hwapi_payStopByPushbutton();
} else
if (payInProg==4) // max achieved
{
hwapi_paymentStarted++;
collActiv=4;
emit hwapi_payStopByMax();
} else
if (payInProg==5) // escrow full
{
hwapi_paymentStarted++;
collActiv=5;
emit hwapi_payStopByEscrow();
} else
if (payInProg==6) // encashed
{
hwapi_paymentStarted++;
collActiv=6;
} else
if (payInProg==7) // returned, user pressed Cancel button
{
hwapi_paymentStarted++;
collActiv=7;
emit hwapi_payCancelled();
} else
if (empState<9 || payInProg==8)
{
hwapi_paymentStarted++;
collActiv=13; // stopped by unexpected error
emit hwapi_payStopByError();
}
}
if (empState<8 || empState>12)
epi_clearCurrentPayment(); // to avoid wrong "got-coin" messages
if (hwapi_paymentStarted==90 || hwapi_paymentStarted==3 )
{
// EMP error, wait till process finished
if (empState==99 && (payInProg==0 || payInProg>5) )
{
// everything stopped, no more coins in escrow
hwapi_paymentStarted=0;
emit hwapi_coinProcessJustStopped();
}
}
return collActiv;
}
uint32_t hwapi::getInsertedAmount(void) const
{
return epi_CurrentPaymentGetAmount();
@@ -3854,7 +3637,7 @@ bool hwapi::cash_stopPayment(void) const
{
// DB1: 1=encash 2=cancel & return coins
// 3=stop and keep coins in escrow
emit hwapi_payStopByPushbutton();
emit hwapi_vendStopByPushbutton();
return sendFDcmd_set(156, 0,0, 3,0,0,0);
}
@@ -3877,11 +3660,6 @@ bool hwapi::vend_failed(void) const
}
uint8_t hwapi::mif_getCardType(QString *cardholder) const
// return 1,2,3,4 = upper, lower access card, printer test, coin test
// cardholder: 7byte Name-String
@@ -3908,20 +3686,6 @@ uint64_t hwapi::sys_getWakeSource(void) const
return epi_getWakeSources();
}
uint8_t hwapi::sys_getWakeReason(void) const
{
// Master was woken by following reason:
// 1: MDB Event
// 2: Coin Event
// ( 3: Master Event) - will not set the wake line
// ( 4: 32s pulse) - will not set the wake line
// 5: Door Event
// ( 6: Diag Event) - will not set the wake line
// 7: 30min-Pulse for HB
return epi_getWakeReason();
}
void hwapi::sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const
{
@@ -4057,212 +3821,3 @@ uint8_t hwapi::prn_getCurrentPrinterState() const
}
// 21.4.23TS: change function "sendDeviceSettings()" to use this struct: "struct T_devices"
void hwapi::sys_sendDeviceParameter(struct T_devices *deviceSettings) const
{
// same as "sendDeviceSettings()" but with much more data
uint8_t buf[64];
uint16_t LL, nn;
tslib_strclr(buf,0,64);
uint8_t *start;
// den gesamten struct in einen Puffer kopieren
LL=sizeof(struct T_devices);
start = &deviceSettings->kindOfPrinter;
nn=0;
do
{
buf[nn] = *start;
start++;
} while(++nn<LL);
epi_store64BdevParameter(LL,buf); // this buffer holds the device settings to be used here in hwapi
epi_store64ByteSendData(LL, buf); // this buffer holds sending data temporarely
sendWRcmd_setSendCommand0(SENDDIRCMD_DEVICE_PARA);
}
void hwapi::sys_restoreDeviceParameter(struct T_devices *deviceSettings) const
{
uint8_t buf[64];
uint8_t LL, nn;
tslib_strclr(buf,0,64);
uint8_t *start;
epi_restore64BdevParameter(&LL, buf);
// Puffer in struct eintragen:
start = &deviceSettings->kindOfPrinter;
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
}
bool hwapi::sys_areDCdataValid(void) const
{
return epi_areDcDataValid();
}
/* ---------------------------------------------------------------------------------------------
// ------------ supervise all hardware components
// ------------ assess the machine state
1. check if DC startup test is through, retrigger if not
2. get results and find errors
3. in case of error check if component is used (e.g. billreader is seldom used)
4: check doors
5. return value: 0: no response from DC
1: no Test results and Test not running. need retrigger!
2: state not clear by now, test ongoing, wait
3: Service or battery door is open, goto INTRUSION MODE
from here: after valid ID-card goto SERVICE MODE
4: vault door is open, goto INTRUSION MODE
from here: after valid ID-card and vault door closed goto TEST MODE
in TEST MODE: complete system check decides if vending mode allowed
5: All doors are closed but errors found,
goto OOO MODE (out-of-order)
from here: run system test until problem is fixed
6: All doors are closed, no error, maybe warnings,
goto VENDING MODE (normal operation)
(priority sinks from 0 to 6)
--------------------------------------------------------------------------------------------- */
uint8_t hwapi::sys_componentAssessment(void) const
{
// this function decides if vending mode is possible, independant from door
// return >0 in case of error
// is inncluded in sys_superviseSystem
struct T_moduleCondition *modCond=0;
sys_getDeviceConditions(modCond);
struct T_dynamicCondition *dynMaCond=0;
sys_getDynMachineConditions(dynMaCond);
struct T_devices *devPara=0;
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;
}
// retrigger System-Check with:
// bool hwapi::sys_runCompleteTest(void) const
uint8_t hwapi::sys_superviseSystem(void) const
{
// this function proofs if vending is possible depending of doors state
struct T_dynamicCondition *dynMaCond=0;
struct T_moduleCondition *modCond=0;
if (!gpi_areDcDataValid())
{
// es gibt keinerlei gültige Daten vom DC
return 0;
}
// jetzt sind die DC-Daten aktuell, also reinholen:
sys_getDynMachineConditions(dynMaCond);
sys_getDeviceConditions(modCond);
if (!modCond->allModulesChecked)
{
// noch keine Testergebnisse
if (dynMaCond->startupTestIsRunning)
return 2; // Starttest läuft gerade
else
return 1; // Starttest ist noch nicht gelaufen
}
// all doors: 99: undefined 0:closed 1:open
if (dynMaCond->lowerDoor || dynMaCond->upperDoor)
return 3;
if (dynMaCond->middleDoor)
return 4;
if (sys_componentAssessment() >0)
return 5; // errors found
return 6; // everything fine
}
uint8_t hwapi::sys_getSystemErrors(void) const
{
return sys_componentAssessment();
}

9
src/main.cpp Normal file
View File

@@ -0,0 +1,9 @@
#include <QCoreApplication>
#include "tslib.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}

View File

@@ -433,8 +433,7 @@ uint8_t recBuffer[FRAME_MAXLEN];
// read from "VCP":
mySerialPort->readFromSerial(Indata, recLength);
qCritical()<<"prot: got data " << recLength;
qCritical()<<" Indata: " << Indata;
//qDebug()<<"prot: got data " << recLength;
if (recLength>FRAME_MAXLEN)
recLength=FRAME_MAXLEN;
for (int nn=0; nn<recLength; nn++)
@@ -444,9 +443,6 @@ uint8_t recBuffer[FRAME_MAXLEN];
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)
qCritical()<<" FastCheckInData() result = " << result;
if (result>0)
{
// dann anzeige

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
#include "serial_port_thread.h"
SerialPortThread::SerialPortThread(QObject *parent)
: QThread(parent) {
this->setObjectName("SerialPortThread");
}
SerialPortThread::~SerialPortThread() {
m_loop.quit();
}
void SerialPortThread::run() {
m_loop.exec();
}

244
src/serial_port_worker.cpp Normal file
View File

@@ -0,0 +1,244 @@
#include "serial_port_worker.h"
#include "serial_port_thread.h"
#include <QDebug>
#include <QCoreApplication>
std::atomic<uint8_t> Command::m_nextSendBufferIndex{0};
std::atomic<uint8_t> Command::m_nextRecvBufferIndex{0};
char Command::m_sendBuffers[256][SEND_BLOCK_SIZE]{{0}};
char Command::m_recvBuffers[256][SEND_BLOCK_SIZE]{{0}};
uint32_t Command::getNextCommandPriority(uint8_t priorityClass) {
static std::atomic<std::uint32_t> priority_1{0};
static std::atomic<std::uint32_t> priority_2{1000000000};
static std::atomic<std::uint32_t> priority_3{2000000000};
static std::atomic<std::uint32_t> priority_4{3000000000};
switch (priorityClass) {
case PRIORITY_1:
return priority_1.fetch_add(1);
case PRIORITY_2:
return priority_2.fetch_add(1);
case PRIORITY_3:
return priority_3.fetch_add(1);
case PRIORITY_4:
return priority_4.fetch_add(1);
}
return -1;
}
char *Command::getNextSendBuffer() {
uint8_t const nextIndex = m_nextSendBufferIndex.fetch_add(1);
return &m_sendBuffers[nextIndex][0];
}
char *Command::getNextRecvBuffer() {
uint8_t const nextIndex = m_nextRecvBufferIndex.fetch_add(1);
return &m_recvBuffers[nextIndex][0];
}
Command::Command(uint16_t cmdId, uint8_t sendBufferLength,
uint8_t recvBufferLength, uint8_t priorityClass)
: m_priority(getNextCommandPriority(priorityClass))
, m_priorityClass(priorityClass)
, m_cmdId(cmdId)
, m_sendBuffer(Command::getNextSendBuffer())
, m_recvBuffer(Command::getNextRecvBuffer())
, m_sendBufferLength(sendBufferLength)
, m_recvBufferLength(recvBufferLength) {
memset(m_sendBuffer, 0x00, sizeof(m_sendBuffers[0]));
}
Command::Command()
: m_priority(0)
, m_priorityClass(0)
, m_cmdId(0)
, m_sendBuffer(0)
, m_recvBuffer(0)
, m_sendBufferLength(0)
, m_recvBufferLength(0) {
}
/**
* \brief Constructor for SerialPort
*
* @date 08.11.2022 first draft.
*
*/
SerialPortWorker::SerialPortWorker(QString portName, enum QSerialPort::BaudRate baudRate, QObject *parent)
: QThread(parent)
, m_serialPort()
, m_serialPortOpened(false)
, m_portName(portName)
, m_baudRate(baudRate)
, m_bytesWritten(0) {
this->setObjectName("SerialPortWorker");
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
if (!info.isNull()) {
qDebug() << "Name .......... " << info.portName();
qDebug() << "Description ... " << info.description();
qDebug() << "Manufacturer .. " << info.manufacturer();
qDebug() << "SerialNumber .. " << info.serialNumber();
if (info.hasProductIdentifier()) {
qDebug() << "Product-ID .... " << info.productIdentifier();
}
if (info.hasVendorIdentifier()) {
qDebug() << "Vendor-ID ..... " << info.vendorIdentifier();
}
qDebug() << "Location ...... " << info.systemLocation();
if (info.portName() == m_portName) {
m_serialPortInfo = info;
}
}
}
if (m_serialPortInfo.portName() == m_portName) {
m_serialPort.setPort(m_serialPortInfo);
m_serialPort.setPortName(m_portName);
m_serialPort.setDataBits(QSerialPort::Data8);
m_serialPort.setParity(QSerialPort::NoParity);
m_serialPort.setStopBits(QSerialPort::OneStop);
m_serialPort.setFlowControl(QSerialPort::NoFlowControl);
m_serialPortOpened = m_serialPort.open(QIODevice::ReadWrite);
}
}
SerialPortWorker::~SerialPortWorker() {
closeSerialPort();
}
void SerialPortWorker::run() {
SerialPortThread serialPortThread;
this->moveToThread(&serialPortThread); // not really necessary
// Note: because this thread is moved to serialPortThread, the event loop
// used will be the one of serialPortThread (this-thread does not even have one).
// This is the only purpose of serialPortThread.
serialPortThread.start();
connect(&m_serialPort, SIGNAL(readyRead()), this, SLOT(getBytesAvailable()));
connect(&m_serialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(getNumberOfBytesWritten(qint64)));
while (m_serialPortOpened) {
Command nextCmd = getNextCommand();
if (nextCmd.m_cmdId == Command::QUIT_SENTINEL) {
break;
}
QByteArray data(nextCmd.getNextSendBuffer(), nextCmd.m_sendBufferLength);
m_bytesWritten = 0;
m_serialPort.write(data);
// process events in event loop of associated thread
serialPortThread.getEventLoop().processEvents(QEventLoop::ExcludeUserInputEvents, TIMEOUT);
int maxWaitTime = WAIT_TIME_MAX;
while (maxWaitTime > 0 && m_bytesWritten < (uint32_t)data.size()) {
if (!m_serialPort.waitForBytesWritten(100)) { // wait timeout-ms for the bytes to be written
// process events in event loop of associated thread
serialPortThread.getEventLoop().processEvents(QEventLoop::ExcludeUserInputEvents, TIMEOUT);
maxWaitTime -= TIMEOUT;
}
}
if (m_bytesWritten == (uint32_t)data.size()) { // data written, wait for result
if (nextCmd.m_recvBufferLength > 0) {
// process events in event loop of associated thread
serialPortThread.getEventLoop().processEvents(QEventLoop::ExcludeUserInputEvents, TIMEOUT);
maxWaitTime = WAIT_TIME_MAX;
while (maxWaitTime > 0 && m_bytesAvailable < nextCmd.m_recvBufferLength) {
if (!m_serialPort.waitForReadyRead(100)) {
// process events in event loop of associated thread
serialPortThread.getEventLoop().processEvents(QEventLoop::ExcludeUserInputEvents, TIMEOUT);
maxWaitTime -= TIMEOUT;
}
}
uint32_t const bytesAvailable = m_bytesAvailable;
if (bytesAvailable == nextCmd.m_recvBufferLength) {
QByteArray result = m_serialPort.read(bytesAvailable);
if (!result.isEmpty() && ((uint32_t)result.size() == bytesAvailable)) {
memcpy(nextCmd.m_recvBuffer, result.data(), bytesAvailable);
insertResult(nextCmd);
}
} else {
// error
}
}
} else {
// error
}
} // while (m_serialPortOpened)
serialPortThread.quit();
serialPortThread.wait();
}
bool SerialPortWorker::openSerialPort() {
if (!m_serialPortOpened) {
return m_serialPort.open(QIODevice::ReadWrite);
}
return false; // opening twice is not allowed
}
void SerialPortWorker::closeSerialPort() {
if (m_serialPortOpened) {
m_serialPort.close();
m_serialPortOpened = false;
}
}
void SerialPortWorker::quit() {
Command cmd(Command::QUIT_SENTINEL, 0, 0, Command::PRIORITY_1);
insertCommand(cmd);
}
void SerialPortWorker::insertCommand(Command const &cmd) {
{ std::lock_guard<std::mutex> lock(m_sendQueueMutex);
m_sendQueue.push(cmd);
} // release lock
m_sendQueueCondVar.notify_one();
}
Command SerialPortWorker::getNextCommand() {
Command nextCmd;
{ std::unique_lock<std::mutex> lock(m_sendQueueMutex);
m_sendQueueCondVar.wait(lock, [this]{ return !this->m_sendQueue.empty(); });
nextCmd = m_sendQueue.top();
m_sendQueue.pop();
} // release lock
return nextCmd;
}
void SerialPortWorker::insertResult(Command const &result) {
{ std::lock_guard<std::mutex> lock(m_recvQueueMutex);
m_recvQueue.push_back(result);
} // release lock
m_recvQueueCondVar.notify_one();
}
bool SerialPortWorker::getNextResult(Command &nextResult, int timeout) {
bool timed_out = false;
{ std::unique_lock<std::mutex> lock(m_recvQueueMutex);
if (m_recvQueueCondVar.wait_for(lock, std::chrono::milliseconds(timeout),
[this]{ return !this->m_recvQueue.empty(); })) {
nextResult = m_recvQueue.front();
m_recvQueue.pop_front();
return true;
} else {
timed_out = true;
}
} // release lock
return (timed_out == false);
}
void SerialPortWorker::getBytesAvailable() {
m_bytesAvailable += m_serialPort.bytesAvailable();
}
bool SerialPortWorker::getNumberOfBytesWritten(qint64 bytesWritten) {
if (bytesWritten > 0) {
m_bytesWritten += (uint32_t)bytesWritten;
return true;
}
return false;
}

View File

@@ -1,6 +1,7 @@
#include "shared_mem_buffer.h"
#include <QDebug>
#include <QCoreApplication>
#include <atomic>
#ifdef QT_POSIX_IPC
@@ -12,6 +13,12 @@
#include <sys/ipc.h> // ftok
#endif
#ifdef __linux__
#include <unistd.h>
#endif
#define PROCESS_SHARED (PTHREAD_PROCESS_SHARED)
// std::atomic_bool SharedMemBuffer::__sharedMemLocked{false};
QSharedMemory *SharedMemBuffer::getShm(std::size_t size) {
@@ -22,6 +29,83 @@ QSharedMemory *SharedMemBuffer::getShm(std::size_t size) {
shMem.setKey(fkey);
if (!shMem.isAttached()) {
if (shMem.create(size)) {
// the creator is the owner of the shared-memory segment
SharedMemBuffer *shm = (SharedMemBuffer *)(shMem.data());
if (shm) {
shm->init = 0;
// mark the shm
memset(shm->appName, 0x00, sizeof(shm->appName));
strncpy(shm->appName,
QCoreApplication::applicationName().toLocal8Bit().constData(),
sizeof(shm->appName)-1);
shm->pid = getpid();
// create condition variables plus associated mutexes for
// sending/receiving commands to dc
int r = 0;
if ((r = pthread_mutexattr_init(&shm->sndMtxA)) != 0) {
qCritical() << "init mutex attribute"
<< strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_mutexattr_setpshared(
&shm->sndMtxA, PTHREAD_PROCESS_SHARED) != 0)) {
qCritical() << "set s-mutex attribute to process shared"
<< strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_mutex_init(&shm->sndMtx,
&shm->sndMtxA) != 0)) {
qCritical() << "init s-mutex" << strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_condattr_init(&shm->sndCndA) != 0)) {
qCritical() << "init s-mutex" << strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_condattr_setpshared(
&shm->sndCndA, PTHREAD_PROCESS_SHARED) != 0)) {
qCritical() << "init s-cond attribute to process shared"
<< strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_cond_init(&shm->sndCndV,
&shm->sndCndA) != 0)) {
qCritical() << "init s-condvar" << strerror(errno) << r;
}
if ((r = pthread_mutexattr_init(&shm->rcvMtxA)) != 0) {
qCritical() << "init r-mutex attribute"
<< strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_mutexattr_setpshared(
&shm->rcvMtxA, PTHREAD_PROCESS_SHARED) != 0)) {
qCritical() << "set r-mutex attribute to process shared"
<< strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_mutex_init(&shm->rcvMtx,
&shm->rcvMtxA) != 0)) {
qCritical() << "init r-mutex" << strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_condattr_init(&shm->rcvCndA) != 0)) {
qCritical() << "init r-mutex" << strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_condattr_setpshared(
&shm->rcvCndA, PTHREAD_PROCESS_SHARED) != 0)) {
qCritical() << "init r-cond attribute to process shared"
<< strerror(errno) << r;
}
if ((r == 0) &&
(r = pthread_cond_init(&shm->rcvCndV,
&shm->rcvCndA) != 0)) {
qCritical() << "init s-condvar" << strerror(errno) << r;
}
shm->init = 1;
}
return &shMem;
} else {
if (shMem.error() == QSharedMemory::AlreadyExists) {

View File

@@ -24,7 +24,6 @@ bool indat_isPrinterOn() {
return indat_savePrnPwr;
}
static bool indat_saveMifPwr;
void indat_storeMifarePower(bool isOn) {
@@ -35,7 +34,6 @@ bool indat_isMifareOn() {
return indat_saveMifPwr;
}
static bool indat_MdbIsOn;
void indat_storeMDBisOn(bool isOn) {
@@ -46,11 +44,6 @@ bool indat_isMdbOn() {
return indat_MdbIsOn;
}
// //////////////////////////////////////////////////////////////////////////
void gpi_storeSlaveSerParams(uint8_t slaveBaudRate, uint8_t NrDataBits,
uint8_t parity, uint8_t NrStopBits) {
// store numbers
@@ -102,7 +95,6 @@ void gpi_storeGenerals(uint8_t genNr, QString text) {
text.toStdString().c_str(),
sizeof(SharedMemBuffer::getDataConst()->genStrings[0]));
}
}
QString epi_loadGenerals(uint8_t genNr) {
@@ -116,9 +108,6 @@ QString epi_loadGenerals(uint8_t genNr) {
return " ";
}
// -------------------------------
void gpi_storeUID(uint8_t const *buf8byteUid) {
@@ -293,7 +282,6 @@ QString epi_getSlaveTimeDateStr() {
}
// ///////////////////////////////////////////////////////////////////////////////////
// analog values
// ///////////////////////////////////////////////////////////////////////////////////
@@ -322,7 +310,6 @@ uint16_t epi_loadAIs(uint8_t aiNr) {
// ADC0: temp
// 1: voltage
// 2: brightness
#define MAXNROF_MEASURE 4
uint32_t epi_loadMeasureValue(uint8_t ValueNr) {
// ValueNr 0=ADC0, 1=ADC1 aso...
@@ -1002,15 +989,6 @@ void gpi_storePrinterFonts(uint8_t const *buf) {
sizeof(SharedMemBuffer::getData()->Sdata.PRN_FONTS));
}
/*
qDebug()<<"printer fonts stored " <<Sdata_PRN_FONTS[0]<<" "<<Sdata_PRN_FONTS[1]<<" " \
<<Sdata_PRN_FONTS[2]<<" "<<Sdata_PRN_FONTS[3]<<" " \
<<Sdata_PRN_FONTS[4]<<" "<<Sdata_PRN_FONTS[5]<<" " \
<<Sdata_PRN_FONTS[6]<<" "<<Sdata_PRN_FONTS[7]<<" " \
<<Sdata_PRN_FONTS[8]<<" "<<Sdata_PRN_FONTS[9]<<" " \
<<Sdata_PRN_FONTS[10]<<" "<<Sdata_PRN_FONTS[11];
*/
// DB0: mdb_bus_ready (switched on)
// DB1: rdBackV12devicePower
// DB2: rdBackV5busPwr
@@ -1094,10 +1072,6 @@ void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t const *data) {
{
vv=uchar2uint(data[pp+4], data[pp+3]);
sub_enterData(data[pp], data[pp+1], data[pp+2], vv );
//qDebug()<< "emp IN data: " << data[pp] << " " << data[pp+1]
// << " " <<data[pp+2] <<" " <<data[pp+3] <<" " <<data[pp+4] <<" ";
pp+=5;
LL--;
}
@@ -1159,11 +1133,6 @@ void epi_clearCurrentPayment(void) {
// call at beginning of coin collection
SharedMemBuffer::getData()->store.insertedAmount = 0;
p_lastCoin = 0;
memset((char *)&SharedMemBuffer::getData()->store.lastCoinType[0],
0x00, sizeof(SharedMemBuffer::getData()->store.lastCoinType));
memset((char *)&SharedMemBuffer::getData()->store.lastCoinValue[0],
0x00, sizeof(SharedMemBuffer::getData()->store.lastCoinValue));
SharedMemBuffer::getData()->store.curPayNewCoin = 0;
}
void gpi_storeCurrentPayment(uint32_t insertedAmount,
@@ -1171,9 +1140,7 @@ void gpi_storeCurrentPayment(uint32_t insertedAmount,
SharedMemBuffer::getData()->store.insertedAmount = insertedAmount;
SharedMemBuffer::getData()->store.lastCoinType[p_lastCoin] = lastCoinType;
SharedMemBuffer::getData()->store.lastCoinValue[p_lastCoin] = lastCoinValue;
p_lastCoin++;
SharedMemBuffer::getData()->store.curPayNewCoin++;
}
uint32_t epi_CurrentPaymentGetAmount(void) {
@@ -1205,26 +1172,17 @@ bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values) {
void gpi_storeWakeSources(uint8_t const *receivedData) {
SharedMemBuffer::getData()->store.wakeSrc = 0;
for (int nn=5; nn>=0; nn--) {
for (int nn=7; nn>=0; nn--) {
uint8_t const uctmp = receivedData[nn];
SharedMemBuffer::getData()->store.wakeSrc |= uctmp;
SharedMemBuffer::getData()->store.wakeSrc <<= 8;
}
SharedMemBuffer::getData()->store.wakeReason = receivedData[6];
}
uint64_t epi_getWakeSources(void) {
return SharedMemBuffer::getDataConst()->store.wakeSrc;
}
uint8_t epi_getWakeReason(void)
{
return SharedMemBuffer::getDataConst()->store.wakeReason;
}
void gpi_storeExtendedTime(uint8_t leng, uint8_t const *data) {
leng = std::min(leng, (uint8_t)(64));
SharedMemBuffer::getData()->store.rbDevParamLen = leng;
@@ -1258,8 +1216,6 @@ void epi_restoreDeviceConditions(uint8_t *leng, uint8_t *data) {
*leng);
}
// store dynamic machine conditions
void gpi_storeDynMachineConditions(uint8_t leng, uint8_t const *data) {
SharedMemBuffer::getData()->store.machCondLen = leng;
@@ -1347,24 +1303,3 @@ uint32_t epi_getCashBoxContent(void) {
uint16_t epi_getNrOfCoinsInCashBox(void) {
return SharedMemBuffer::getDataConst()->store.nrOfCoins;
}
void gpi_storeDcDataValid(bool isVal)
{
SharedMemBuffer::getData()->store.dcDataValid = isVal;
}
bool gpi_areDcDataValid()
{
return SharedMemBuffer::getDataConst()->store.dcDataValid;
}
bool epi_areDcDataValid()
{
return SharedMemBuffer::getData()->store.dcDataValid;
}