2746 lines
102 KiB
C++
2746 lines
102 KiB
C++
#include "AppControl.h"
|
|
#include "ATBHMIconfig.h"
|
|
#include "VMC/vmc.h"
|
|
#include "atb_system.h"
|
|
|
|
#include "support/VendingData.h"
|
|
|
|
#include <QTimer>
|
|
#include <QTranslator>
|
|
#include <QLocale>
|
|
#include <QDebug>
|
|
#include <QCoreApplication>
|
|
#include <QDateTime>
|
|
|
|
AppControl::AppControl(QObject *parent) :
|
|
QObject(parent),
|
|
programmode(PROGRAM_MODE::IDLE)
|
|
{
|
|
this->config = new ATBHMIconfig();
|
|
this->system = new ATB_system(config, this);
|
|
this->vmc = new VMC(this, config, this);
|
|
|
|
this->prepareInternalOOO = 0;
|
|
|
|
// ------------------- -----------------------------------------------
|
|
this->vendingData = new VendingData(this);
|
|
|
|
// ------------------- connect HMI ---------------------------------------------
|
|
|
|
// -------------------- connect vmc --------------------------------------------
|
|
connect(vmc, SIGNAL(VMCFormatedString(FormatedStringList)), this, SLOT(onVMCFormatedString(FormatedStringList)), Qt::QueuedConnection);
|
|
|
|
connect(vmc, SIGNAL(sysCommand(quint16, QByteArray)), system, SLOT(executeSystemCommand(quint16, QByteArray)), Qt::QueuedConnection);
|
|
connect(vmc, SIGNAL(newDateTime(QString)), system, SLOT(setDateTime(QString)), Qt::QueuedConnection);
|
|
|
|
connect(vmc, SIGNAL(setCustNr(QString)), config, SLOT(setCustNr(QString)), Qt::QueuedConnection);
|
|
connect(vmc, SIGNAL(setGroupNr(QString)), config, SLOT(setGroupNr(QString)), Qt::QueuedConnection);
|
|
connect(vmc, SIGNAL(setZoneNr(QString)), config, SLOT(setZoneNr(QString)), Qt::QueuedConnection);
|
|
connect(vmc, SIGNAL(setMachineNr(QString)), config, SLOT(setMachineNr(QString)), Qt::QueuedConnection);
|
|
|
|
connect(vmc, SIGNAL(setDefaultLanguage(quint8)), config, SLOT(setDefaultLanguage(quint8)), Qt::QueuedConnection);
|
|
|
|
connect(vmc, SIGNAL(displayData(quint8,QString)), this, SLOT(onVMCSellData(quint8,QString)), Qt::QueuedConnection);
|
|
|
|
connect(vmc, SIGNAL(retriggerModeSell()), this, SLOT(restartSellModeTimeoutTimer()), Qt::QueuedConnection);
|
|
|
|
connect(vmc, SIGNAL(wakeVMC()), system, SLOT(onWakeVMC()));
|
|
|
|
connect(vmc, SIGNAL(setVendingData(QString,QByteArray)), this, SLOT(onSetVendingData(QString,QByteArray)), Qt::QueuedConnection);
|
|
|
|
|
|
|
|
// -------------------- connect system errors ---------------------------------------
|
|
/*
|
|
connect(<object>, SIGNAL(signalStateError(QString, QString)),
|
|
this,
|
|
SLOT(onSignalSystemErrors(QString, QString)));
|
|
*/
|
|
|
|
/* ----------------------------- load style -------------------------------------- */
|
|
// Note: style should be loaded after all Widgets are created. This is partialy
|
|
// done in 'initDefered()'; so loading and applying StyleSheet is done here.
|
|
//QString styleSheet = "style.qss";
|
|
//styleSheet.prepend('/').prepend(QApplication::applicationDirPath());
|
|
QString styleSheet = ":/style/resources/style/style.qss";
|
|
|
|
QFile File(styleSheet);
|
|
|
|
File.open(QFile::ReadOnly);
|
|
QString StyleSheet = QLatin1String(File.readAll());
|
|
|
|
// ------------------- TIMERS -----------------------------------------------
|
|
// this timer resets to mode idle, if in sell mode.
|
|
sellModeTimeoutTimer = new QTimer(this);
|
|
sellModeTimeoutTimer->setInterval(1000*(config->getSellTimeoutTime().toInt()));
|
|
sellModeTimeoutTimer->setSingleShot(false);
|
|
connect(sellModeTimeoutTimer, SIGNAL(timeout()), this, SLOT(onSellModeTimerTimeout()));
|
|
|
|
|
|
/* ----------------------------- load plugins ------------------------------------ */
|
|
#ifdef USE_PLUGINS
|
|
//QString ApplicationPluginPath = QCoreApplication::applicationDirPath() + "/plugins";
|
|
//QCoreApplication::addLibraryPath(ApplicationPluginPath);
|
|
// -> 20190728: path is set (see debug output below)...
|
|
// but plugin is not loaded with QPluginLoader!!!
|
|
|
|
this->pluginManager = new PluginManager(config, this);
|
|
|
|
#ifdef USE_CC_PLUGIN
|
|
/* ----------------------------- CC plugin -------------------------------------- */
|
|
this->private_initCCPlugin();
|
|
#endif
|
|
|
|
#ifdef USE_CALCULATEPRICE_PLUGIN
|
|
/* ----------------------------- Calculate Price -------------------------------- */
|
|
this->private_initCalculatePricePlugin();
|
|
#endif
|
|
|
|
#ifdef USE_SIMULATION_PLUGIN
|
|
/* ----------------------------- Simulation Plugin ------------------------------- */
|
|
this->private_initSimulationPlugin();
|
|
#endif
|
|
|
|
|
|
#endif // USE_PLUGINS
|
|
|
|
/* ----------------------------- setup hardware --------------------------------- */
|
|
|
|
#ifdef USE_BARCODESCANNER
|
|
// create and init barcode scanner
|
|
if (config->getUseBarcodeScanner()) {
|
|
this->barcodeScanner = new BarcodeScanner(this->config->getBarcodeScannerInputDevice(), this);
|
|
connect(this->barcodeScanner, SIGNAL(readHID(QString&)), this, SLOT(onReadBarcode(QString&)));
|
|
}
|
|
else { this->barcodeScanner = nullptr; }
|
|
#endif
|
|
|
|
/* ----------------------------- ISMAS ------------------------------------------ */
|
|
// used for PIN-generation and transaction
|
|
|
|
#ifdef USE_ISMAS
|
|
this->ismas = new ATB_ISMAS(this->config, this);
|
|
connect(ismas, SIGNAL(received_ATBQRCODE_RESULT_response(QHash<QString,QByteArray>)), this, SLOT(onProcessed_QRCode(QHash<QString,QByteArray>)));
|
|
|
|
connect(ismas, SIGNAL(requestOfflineProcessing()), this, SLOT(onRequestOfflineProcessing()), Qt::QueuedConnection);
|
|
connect(this, SIGNAL(doOfflineProcessing()), ismas, SLOT(onDoOfflineProcessing()), Qt::QueuedConnection);
|
|
connect(this, SIGNAL(changedModeToSELL()), ismas, SLOT(onChangedModeToSELL()));
|
|
#endif
|
|
|
|
|
|
/* ----------------------------- dim high on program start ---------------------- */
|
|
if (config->hasFeatureDBusDisplayControl()) {
|
|
system->dbus_DimControlStart();
|
|
}
|
|
|
|
/* -------------------- install event filter for global error handling ---------- */
|
|
QCoreApplication *app = QCoreApplication::instance();
|
|
app->installEventFilter(this);
|
|
|
|
connect(system, SIGNAL(wakeUp()), this, SLOT(onWakeUp()));
|
|
|
|
system->switchBlinkButtonOff();
|
|
|
|
/* ----------------------------- start first run -------------------------------- */
|
|
QTimer::singleShot(500, this, SLOT(firstRun()));
|
|
|
|
|
|
/* ----------------------------- TESTS ------------------------------------------ */
|
|
#if defined (ARCH_DesktopLinux)
|
|
/************************************************************************
|
|
* test utils:
|
|
*
|
|
QString amount = "122";
|
|
QString amountTax = "144";
|
|
QString amountNet = "56";
|
|
QString amount1 = "2";
|
|
QString amount2 = "99";
|
|
QString amount3 = "899";
|
|
QString amount4 = "7809";
|
|
qDebug() << "utils::getPriceString(" << amount << ") = " << utils::getPriceString(amount);
|
|
qDebug() << "utils::getPriceString(" << amountTax << "," << amountNet << ") = " << utils::getPriceString(amountTax, amountNet);
|
|
qDebug() << "utils::getPriceString(" << amountNet << ") = " << utils::getPriceString(amountNet);
|
|
|
|
qDebug() << "utils::getPriceString(" << amountNet << ") = " << utils::getPriceString(amount1);
|
|
qDebug() << "utils::getPriceString(" << amountNet << ") = " << utils::getPriceString(amount2);
|
|
qDebug() << "utils::getPriceString(" << amountNet << ") = " << utils::getPriceString(amount3);
|
|
qDebug() << "utils::getPriceString(" << amountNet << ") = " << utils::getPriceString(amount4);
|
|
qDebug() << " ";
|
|
*/
|
|
|
|
/************************************************************************
|
|
* test QR-Code receipt:
|
|
*/
|
|
/*
|
|
#if defined (USE_QRCODE_RECEIPT)
|
|
|
|
// Test: Beleg als QR-Code
|
|
QString tmpReceipt;
|
|
tmpReceipt.append(" ** Kundenbeleg ** \n");
|
|
tmpReceipt.append(" Bezahlung Mastercard \n");
|
|
tmpReceipt.append("Karte: xxxxxxxxxxxx9404 0\n");
|
|
tmpReceipt.append("01.12.2021 09:57:12\n");
|
|
tmpReceipt.append("Term.-ID:60213845 TA-Nr.:000069\n");
|
|
tmpReceipt.append("Vorgangs- \n");
|
|
tmpReceipt.append("Nr.:0064 Beleg:0009\n");
|
|
tmpReceipt.append("App-ID: A0000000041010\n");
|
|
tmpReceipt.append("Erfassungsart: Kontaktlos\n");
|
|
tmpReceipt.append("Autor.:555058 -\n");
|
|
tmpReceipt.append("VU-Nummer: 455600764906\n");
|
|
tmpReceipt.append("Betrag: EUR 1,00\n");
|
|
tmpReceipt.append(" Zahlung erfolgt \n");
|
|
tmpReceipt.append(" \n");
|
|
|
|
// Test: Link als QR-Code
|
|
tmpReceipt.clear();
|
|
tmpReceipt.append("https://www.betterpark.de/receipt?licencePlate=ABCD123&ticketNumber=123456");
|
|
|
|
this->vendingData->setParameter("RECEIPT", QVariant(tmpReceipt));
|
|
|
|
QRCodeGenerator::generateQRCode(this->vendingData->getParameter("RECEIPT").toString());
|
|
#endif
|
|
*/
|
|
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
* program mode management
|
|
*
|
|
*/
|
|
bool AppControl::requestProgramMode(PROGRAM_MODE newProgramMode)
|
|
{
|
|
bool result = false;
|
|
|
|
if (this->programmode == newProgramMode) {
|
|
return result;
|
|
}
|
|
|
|
switch (newProgramMode) {
|
|
case PROGRAM_MODE::IDLE:
|
|
if (this->prepareInternalOOO) {
|
|
vmc->blockScreenSwitch(1);
|
|
this->requestProgramMode(PROGRAM_MODE::OOO);
|
|
return false;
|
|
}
|
|
else {
|
|
this->private_setupProgramModeIDLE();
|
|
this->programmode = PROGRAM_MODE::IDLE;
|
|
result = true;
|
|
}
|
|
break;
|
|
case PROGRAM_MODE::SELL_ENABLE:
|
|
this->private_setupProgramModeSELL_ENABLE();
|
|
this->programmode = PROGRAM_MODE::SELL_ENABLE;
|
|
result = true;
|
|
break;
|
|
case PROGRAM_MODE::SELL:
|
|
this->private_setupProgramModeSELL();
|
|
this->programmode = PROGRAM_MODE::SELL;
|
|
result = true;
|
|
break;
|
|
case PROGRAM_MODE::SERVICE:
|
|
this->private_setupProgramModeSERVICE();
|
|
this->programmode = PROGRAM_MODE::SERVICE;
|
|
result = true;
|
|
break;
|
|
case PROGRAM_MODE::OOO:
|
|
this->private_setupProgramModeOOO();
|
|
this->programmode = PROGRAM_MODE::OOO;
|
|
result = true;
|
|
break;
|
|
}
|
|
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "changed programmode to " << this->programmode;
|
|
|
|
switch (this->programmode) {
|
|
case PROGRAM_MODE::IDLE:
|
|
emit this->changedModeToIDLE();
|
|
break;
|
|
case PROGRAM_MODE::SELL_ENABLE:
|
|
|
|
break;
|
|
case PROGRAM_MODE::SELL:
|
|
emit this->changedModeToSELL();
|
|
break;
|
|
case PROGRAM_MODE::SERVICE:
|
|
emit this->changedModeToSERVICE();
|
|
break;
|
|
case PROGRAM_MODE::OOO:
|
|
emit this->changedModeToOOO();
|
|
break;
|
|
}
|
|
|
|
emit this->changedProgramMode(this->programmode);
|
|
return result;
|
|
}
|
|
|
|
PROGRAM_MODE AppControl::getCurrentProgramMode()
|
|
{
|
|
return this->programmode;
|
|
}
|
|
|
|
bool AppControl::isProgramModeSELL()
|
|
{
|
|
return this->programmode == PROGRAM_MODE::SELL ? true : false;
|
|
}
|
|
|
|
bool AppControl::isProgramModeSELL_ENABLE()
|
|
{
|
|
return this->programmode == PROGRAM_MODE::SELL_ENABLE ? true : false;
|
|
}
|
|
bool AppControl::isProgramModeSERVICE()
|
|
{
|
|
return this->programmode == PROGRAM_MODE::SERVICE ? true : false;
|
|
}
|
|
bool AppControl::isProgramModeIDLE()
|
|
{
|
|
return this->programmode == PROGRAM_MODE::IDLE ? true : false;
|
|
}
|
|
bool AppControl::isProgramModeOOO()
|
|
{
|
|
return this->programmode == PROGRAM_MODE::OOO ? true : false;
|
|
}
|
|
|
|
|
|
/* private mode setup routines */
|
|
|
|
void AppControl::private_setupProgramModeSELL()
|
|
{
|
|
if (config->hasFeatureDBusSuspendControl()) {
|
|
system->dbus_preventSuspend();
|
|
}
|
|
if (config->hasFeatureDBusDisplayControl()) {
|
|
system->dbus_DimHighPermanent();
|
|
}
|
|
|
|
// start SellModeTimeoutTimer
|
|
this->sellModeTimeoutTimer->start();
|
|
|
|
bool changed = false;
|
|
if (this->programmode != PROGRAM_MODE::SELL) {
|
|
changed = true;
|
|
}
|
|
|
|
// do the following only once (only on mode change)
|
|
if (changed) {
|
|
// clear (old) vending data
|
|
vendingData->clear();
|
|
}
|
|
}
|
|
|
|
void AppControl::private_setupProgramModeSELL_ENABLE()
|
|
{
|
|
|
|
}
|
|
|
|
void AppControl::private_setupProgramModeSERVICE()
|
|
{
|
|
this->sellModeTimeoutTimer->stop();
|
|
|
|
if (config->hasFeatureDBusSuspendControl()) {
|
|
system->dbus_preventSuspend();
|
|
}
|
|
if (config->hasFeatureDBusDisplayControl()) {
|
|
system->dbus_DimHighPermanent();
|
|
}
|
|
|
|
#ifdef USE_BARCODESCANNER
|
|
// reinit barcode scanner
|
|
if (config->getUseBarcodeScanner()) {
|
|
this->barcodeScanner->reopen(this->config->getBarcodeScannerInputDevice());
|
|
}
|
|
#endif
|
|
#ifdef USE_RFIDREADER
|
|
// reinit rfid reader
|
|
if (config->getUseRFIDReader()) {
|
|
this->rfidReader->reopen(this->config->getRFIDReaderInputDevice());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void AppControl::private_setupProgramModeIDLE()
|
|
{
|
|
// DEBUG Transactions:
|
|
if (vendingData->hasParameter("MISSINGTRANSACTION")) {
|
|
qCritical() << "setProgramModeIDLE: unsubmitted transaction: ";
|
|
qCritical() << " ACCESSINFORMATION = " << vendingData->getParameter("ACCESSINFORMATION").toString();
|
|
}
|
|
|
|
this->sellModeTimeoutTimer->stop();
|
|
|
|
if (this->programmode == PROGRAM_MODE::SERVICE) {
|
|
this->private_unsetProgramModeSERVICE();
|
|
}
|
|
|
|
if (this->programmode == PROGRAM_MODE::OOO) {
|
|
this->private_unsetProgramModeOOO();
|
|
}
|
|
|
|
if (config->hasFeatureDBusSuspendControl()) {
|
|
system->dbus_permitSuspend();
|
|
}
|
|
if (config->hasFeatureDBusDisplayControl()) {
|
|
// do the following only if there is a mode transition from SELL,OOO,SERVICE
|
|
// If we are already in idle, this would cause the backlight to be switched on.
|
|
if (!this->isProgramModeIDLE()) {
|
|
system->dbus_DimControlStart();
|
|
}
|
|
}
|
|
}
|
|
|
|
void AppControl::private_setupProgramModeOOO()
|
|
{
|
|
this->sellModeTimeoutTimer->stop();
|
|
|
|
this->prepareInternalOOO = 0;
|
|
|
|
if (this->programmode == PROGRAM_MODE::SERVICE) {
|
|
this->private_unsetProgramModeSERVICE();
|
|
}
|
|
|
|
this->LEDs_ooo();
|
|
|
|
if (config->hasFeatureDBusSuspendControl()) {
|
|
system->dbus_permitSuspend();
|
|
}
|
|
if (config->hasFeatureDBusDisplayControl()) {
|
|
system->dbus_DimControlStart();
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* for cleanup from SERVICE-Mode:
|
|
* close service menu, show stackedWidget, ...
|
|
*/
|
|
void AppControl::private_unsetProgramModeSERVICE()
|
|
{
|
|
this->LEDs_default();
|
|
|
|
|
|
#ifdef USE_BARCODESCANNER
|
|
// reinit barcode scanner
|
|
if (config->getUseBarcodeScanner()) {
|
|
this->barcodeScanner->reopen(this->config->getBarcodeScannerInputDevice());
|
|
}
|
|
#endif
|
|
#ifdef USE_RFIDREADER
|
|
// reinit rfid reader
|
|
if (config->getUseRFIDReader()) {
|
|
this->rfidReader->reopen(this->config->getRFIDReaderInputDevice());
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* for cleanup from OOO-Mode:
|
|
*/
|
|
void AppControl::private_unsetProgramModeOOO()
|
|
{
|
|
this->LEDs_default();
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onRequestOfflineProcessing()
|
|
{
|
|
if (this->programmode == PROGRAM_MODE::IDLE)
|
|
emit this->doOfflineProcessing();
|
|
}
|
|
|
|
|
|
void AppControl::restartSellModeTimeoutTimer()
|
|
{
|
|
if (this->isProgramModeSELL()) { this->sellModeTimeoutTimer->start(); }
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
* process VMC commands
|
|
*
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* VMC: received formated string
|
|
*
|
|
* Precondition:
|
|
* VMC sends this message only in case of a successful and finished selling process
|
|
* (i.e. a ticket was printed).
|
|
* In case of e.g. a printing error, VMC must not send this message.
|
|
*
|
|
*/
|
|
void AppControl::onVMCFormatedString(FormatedStringList data)
|
|
{
|
|
// DEBUG
|
|
qCritical() << "AppControl::onVMCFormatedString(): received " << data.size() << " list elements";
|
|
foreach ( const QByteArray &dataElement, data)
|
|
{
|
|
qCritical() << " " << dataElement;
|
|
}
|
|
|
|
#ifdef USE_CALCULATEPRICE_PLUGIN
|
|
/* for ProcessTransaction:
|
|
* - 7 Parameters:
|
|
* - 1 - "TRANS"
|
|
* - 2 - licenseplate (accessInformation)
|
|
* - 3 - accessInformationType
|
|
* - 4 - timestamp
|
|
* - 5 - amount
|
|
* - 6 - TransactionNumber
|
|
* - 7 - ReceiptNumber
|
|
*
|
|
*/
|
|
|
|
if ( (data.size() >= 7) && (data.at(0).at(0) == 'T') ) {
|
|
|
|
QStringList tmpList;
|
|
for (int i = 0; i < data.size(); i++) {
|
|
tmpList << QString(data.at(i));
|
|
}
|
|
|
|
this->calcPriceBackend->requestProcessTransaction(tmpList.at(1),
|
|
"LICENSEPLATE",
|
|
tmpList.at(4),
|
|
false,
|
|
"", // receipt data
|
|
tmpList.at(5), // TransactionId
|
|
this->vendingData->getParameter("PermitType").toString(),
|
|
this->vendingData->getParameter("PaymentType").toString());
|
|
|
|
// clear vending data parameter to indicate, that transaction is done:
|
|
vendingData->clearParameter("TRANS");
|
|
vendingData->clearParameter("MISSINGTRANSACTION");
|
|
}
|
|
#else
|
|
qCritical() << "AppControl::onVMCFormatedString(): calculate price backend is not in this part of this program";
|
|
#endif
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* private initializer
|
|
*
|
|
* note: init is done in constructor
|
|
*/
|
|
void AppControl::private_initCCPlugin()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
// load CCPlugin:
|
|
this->cc = qobject_cast<CCInterface*>(this->pluginManager->getInstance("CCPlugin"));
|
|
|
|
if (this->cc == nullptr) {
|
|
qCritical() << "ERROR on loading Plugin CCInterface!";
|
|
return;
|
|
}
|
|
|
|
if ( ! static_cast<quint32>(cc->initCCInterfacePlugin(this, config->getSettings()))) {
|
|
qCritical() << "ERROR on init Plugin CCInterface:";
|
|
qCritical() << " " << cc->getLastErrorDescription();
|
|
return;
|
|
}
|
|
|
|
qCritical() << "pluginInfo: " << cc->getPluginInfo();
|
|
|
|
// control cc by VMC (deprecated):
|
|
connect(vmc, SIGNAL(ccStartTransaction()), this, SLOT(onVMC_ccStartTransaction()));
|
|
connect(vmc, SIGNAL(ccCancelTransaction()), this, SLOT(onVMC_ccCancelTransaction()));
|
|
connect(vmc, SIGNAL(ccConfirmTransaction()), this, SLOT(onVMC_ccConfirmTransaction()));
|
|
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendStartTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCStartTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendConfirmTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCConfirmTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendCancelTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCCancelTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendRevertTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCRevertTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
//connect(dynamic_cast<QObject*>(cc), SIGNAL(sendRevertTransactionResult(nsCCInterface::RESULT_STATE, QString&)), vmc, SLOT()));
|
|
//connect(dynamic_cast<QObject*>(cc), SIGNAL(sendDayCloseResult(nsCCInterface::RESULT_STATE, QString&)), vmc, SLOT(QString)));
|
|
|
|
#ifdef USE_CC_PREAUTHORISATION
|
|
// control cc by VMC (deprecated):
|
|
connect(vmc, SIGNAL(ccStartPreauthorisation()), this, SLOT(onVMC_ccStartPreauthorisation()));
|
|
connect(vmc, SIGNAL(ccCancelPreauthorisation()), this, SLOT(onVMC_ccCancelPreauthorisation()));
|
|
connect(vmc, SIGNAL(ccConfirmPreauthorisation()), this, SLOT(onVMC_ccConfirmPreauthorisation()));
|
|
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendPreAuthTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCPreAuthTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendBookTotalTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCBookTotalTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendCancelPreAuthTransactionResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCCancelPreAuthTransactionResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
#endif
|
|
|
|
#ifdef USE_CC_READCARD
|
|
connect(vmc, SIGNAL(ccStartReadCard()), this, SLOT(onVMC_ccStartReadCard()));
|
|
connect(dynamic_cast<QObject*>(cc), SIGNAL(sendCardInfoResult(nsCCInterface::RESULT_STATE, QString&)),
|
|
this, SLOT(onCCRequestCardInfoResult(nsCCInterface::RESULT_STATE, QString&)));
|
|
|
|
#endif
|
|
|
|
// this is customer dependent
|
|
#if defined (CUST00308)
|
|
// Altmuehlsee
|
|
connect(vmc, SIGNAL(ccWakup()), dynamic_cast<QObject*>(cc), SLOT(wakeupCC()));
|
|
connect(vmc, SIGNAL(ccSleep()), dynamic_cast<QObject*>(cc), SLOT(sleepCC()));
|
|
#else
|
|
connect(this, SIGNAL(changedModeToSELL()), dynamic_cast<QObject*>(cc), SLOT(wakeupCC()));
|
|
connect(this, SIGNAL(changedModeToIDLE()), dynamic_cast<QObject*>(cc), SLOT(sleepCC()));
|
|
#endif
|
|
connect(this, SIGNAL(changedModeToSERVICE()), dynamic_cast<QObject*>(cc), SLOT(wakeupCC()));
|
|
|
|
// extract plugin name form pluginInfo:
|
|
bool ok;
|
|
QVariantMap jsonCommand = JSON::parse(cc->getPluginInfo(), ok).toMap();
|
|
QString ccPluginName = jsonCommand["PluginName"].toString();
|
|
|
|
|
|
// configure HMI according to CC plugin:
|
|
// note: there could be also or addtional a customer specific config in the defined screen.
|
|
// also, there could be a specific text variant for a certain used terminal variant
|
|
if (ccPluginName == "TCP_ZVT_CCPlugin") {
|
|
hmi->setCCVariant(CC_VARIANT::TERMINAL::FEIG_CCTOPP);
|
|
}
|
|
else
|
|
if (ccPluginName == "IngenicoZVT_CCPlugin") {
|
|
hmi->setCCVariant(CC_VARIANT::TERMINAL::INGENICO_CCTOPP);
|
|
}
|
|
else
|
|
if (ccPluginName == "IngenicoISelf_CCPlugin") {
|
|
hmi->setCCVariant(CC_VARIANT::TERMINAL::INGENICO_CHIP_AND_PIN);
|
|
}
|
|
else {
|
|
hmi->setCCVariant(CC_VARIANT::TERMINAL::INGENICO_CCTOPP);
|
|
}
|
|
|
|
#endif // USE_CC_PLUGIN
|
|
}
|
|
|
|
|
|
void AppControl::private_initCalculatePricePlugin()
|
|
{
|
|
#ifdef USE_CALCULATEPRICE_PLUGIN
|
|
|
|
// load CalculatePricePlugin:
|
|
this->calcPriceBackend = qobject_cast<CalculatePriceInterface*>(this->pluginManager->getInstance("CalculatePricePlugin"));
|
|
|
|
if (this->calcPriceBackend == nullptr) {
|
|
qCritical() << "plugin CalculatePrice ist not used, instantiate default...";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, "", "Can not instantiate CalculatePricePlugin!");
|
|
this->calcPriceBackend = new CalculatePriceDefault(this);
|
|
return;
|
|
}
|
|
|
|
if ( ! static_cast<quint32>(calcPriceBackend->initCalculatePricePlugin(this, config->getSettings()))) {
|
|
qCritical() << "ERROR init Plugin Calculate Price:";
|
|
qCritical() << " " << calcPriceBackend->getLastErrorDescription();
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, "", "Can not init CalculatePricePlugin!");
|
|
return;
|
|
}
|
|
|
|
qCritical() << "pluginInfo: " << calcPriceBackend->getPluginInfo();
|
|
|
|
connect(dynamic_cast<QObject*>(calcPriceBackend),
|
|
SIGNAL(requestCalculatePriceResult(nsCalculatePriceInterface::RESULT_STATE,QString,QString,QString,QString,PriceInfo,QString,QString)),
|
|
this,
|
|
SLOT(onCalculatedPrice(nsCalculatePriceInterface::RESULT_STATE,QString,QString,QString,QString,PriceInfo,QString,QString)));
|
|
|
|
connect(dynamic_cast<QObject*>(calcPriceBackend),
|
|
SIGNAL(requestProcessTransactionResult(nsCalculatePriceInterface::RESULT_STATE,QString,QString)),
|
|
this,
|
|
SLOT(onProcessTransaction(nsCalculatePriceInterface::RESULT_STATE,QString,QString)));
|
|
|
|
#endif // USE_CALCULATEPRICE_PLUGIN
|
|
}
|
|
|
|
void AppControl::private_initSimulationPlugin()
|
|
{
|
|
#ifdef USE_SIMULATION_PLUGIN
|
|
|
|
// load SimulationPlugin:
|
|
this->simulation = qobject_cast<SimulationInterface*>(this->pluginManager->getInstance("SimulationPlugin"));
|
|
|
|
if (this->simulation == nullptr) {
|
|
qCritical() << "plugin Simulation ist not available...";
|
|
}
|
|
else {
|
|
if ( ! static_cast<quint32>(simulation->initSimulationInterfacePlugin(this, config->getSettings()))) {
|
|
qCritical() << "ERROR io init Plugin SimulationInterface:";
|
|
qCritical() << " " << simulation->getLastErrorDescription();
|
|
}
|
|
|
|
qCritical() << "pluginInfo: " << simulation->getPluginInfo();
|
|
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, "", "Touch Simulation!");
|
|
}
|
|
|
|
#endif // USE_SIMULATION_PLUGIN
|
|
}
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
* first run initialisation
|
|
*
|
|
* This methode is called, by a timer, 500ms after program start.
|
|
*/
|
|
void AppControl::firstRun()
|
|
{
|
|
this->LEDs_default();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
* set a value in vending data
|
|
*/
|
|
void AppControl::onSetVendingData(QString key, QByteArray value)
|
|
{
|
|
this->vendingData->setParameter(key, QVariant(value));
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* CC slots
|
|
*
|
|
*/
|
|
|
|
// public interface for vmc (deprecated)
|
|
void AppControl::onVMC_ccStartTransaction()
|
|
{
|
|
this->onCCStartTransaction();
|
|
}
|
|
void AppControl::onVMC_ccCancelTransaction()
|
|
{
|
|
this->onCCCancelTransaction();
|
|
}
|
|
void AppControl::onVMC_ccConfirmTransaction()
|
|
{
|
|
this->onCCStartConfirmTransaction();
|
|
}
|
|
void AppControl::onVMC_ccStartPreauthorisation()
|
|
{
|
|
this->onCCStartPreauthorisation();
|
|
}
|
|
void AppControl::onVMC_ccCancelPreauthorisation()
|
|
{
|
|
this->onCCCancelPreauthorisationRequest();
|
|
}
|
|
void AppControl::onVMC_ccConfirmPreauthorisation()
|
|
{
|
|
this->onCCConfirmPreauthorisation();
|
|
}
|
|
void AppControl::onVMC_ccStartReadCard()
|
|
{
|
|
this->onCCStartReadCard();
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCCStartTransaction()
|
|
{
|
|
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
cc->requestStartTransaction(this->vendingData->getUintParameter("AMOUNT"));
|
|
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCCStartTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
qCritical() << "AppControl::onCCStartTransactionResult() result = " << result;
|
|
|
|
// restart sell mode timeout timer on every message from CC.
|
|
if (this->isProgramModeSELL()) { this->sellModeTimeoutTimer->start(); }
|
|
|
|
QString vmcResult; // 'String', sent to vmc
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::INFO:
|
|
qCritical() << "AppControl::onCCStartTransactionResult() resultState is INFO: " << result;
|
|
if (result.contains("PAYMENT PREPARED")) {
|
|
hmi->setCCBusy(false);
|
|
hmi->enableCCAbort(true);
|
|
}
|
|
else
|
|
if (result.contains("PAYMENT DISABLE ABORT")) {
|
|
hmi->enableCCAbort(false);
|
|
}
|
|
else
|
|
if (result.startsWith("04FF#")) {
|
|
hmi->displayCCMessage(result);
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCStartTransactionResult() resultState is ERROR_BUSY";
|
|
if (this->isProgramModeSELL()) {
|
|
// set mode busy
|
|
hmi->setCCBusy(true);
|
|
QTimer::singleShot(2000, this, SLOT(onCCStartTransaction()));
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
qCritical() << "AppControl::onCCStartTransactionResult() resultState is SUCCESS";
|
|
qCritical() << " result is: " << result;
|
|
vendingData->setParameter("PaymentType", QVariant(1)); // '1' - CardPayment
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x00;
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_STATE:
|
|
qCritical() << "AppControl::onCCStartTransactionResult() resultState is ERROR_STATE";
|
|
qCritical() << " result is: " << result;
|
|
if (result.contains("DAYCLOSE RUNNING")) {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
else
|
|
if (result.contains("INIT RUNNING")) {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
else
|
|
if (result.contains("AMOUNT ZERO")) {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
else {
|
|
qCritical() << "ASSERT: unhandled RESULT_STATE::ERROR_STATE";
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
// ignore this result message
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BACKEND:
|
|
qCritical() << "AppControl::onCCStartTransactionResult() resultState is ERROR_BACKEND";
|
|
this->onCCErrorBackend(result);
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
qCritical() << "AppControl::onCCStartTransactionResult() resultState is ERROR_TIMEOUT";
|
|
vmcResult[0] = result.at(0);
|
|
vmcResult[1] = result.at(1);
|
|
if (result.at(0) == 0x45 && result.at(1) == 0x00) {
|
|
qCritical() << "ASSERT: RESULT_STATE::ERROR_TIMEOUT: sending 0x45 00 to VMC";
|
|
}
|
|
else {
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
break;
|
|
default:
|
|
if(result.size()>0) {
|
|
qCritical() << "ASSERT: unhandled RESULT_STATE";
|
|
qCritical() << " result is: " << result;
|
|
if (result.at(0) == 0x45 && result.at(1) == 0x00) {
|
|
qCritical() << "ASSERT: 'default' sending 0x45 00 to VMC";
|
|
}
|
|
else {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
Q_UNUSED(resultState);
|
|
Q_UNUSED(result);
|
|
#endif
|
|
}
|
|
|
|
|
|
void AppControl::onCCCancelTransaction()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
cc->requestCancelTransaction();
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* check, if we do have already a receipt in this selling process...
|
|
* this is to prevent for multiple screen calls.
|
|
* It has to be ensured, that 'RECEIPT' is cleared/removed from vending data after selling process.
|
|
*/
|
|
void AppControl::onCCStartConfirmTransaction()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
if (this->vendingData->hasParameter("RECEIPT")) {
|
|
qCritical() << "AppControl::onCCStartConfirmTransaction() hasParameter(\"RECEIPT\") => omit repeated transaction";
|
|
}
|
|
else {
|
|
qCritical() << "AppControl::onCCStartConfirmTransaction(): start confirm transaction";
|
|
cc->requestConfirmTransaction();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void AppControl::onCCConfirmTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
qCritical() << "AppControl::onCCConfirmTransactionResult() result = " << result;
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
this->vendingData->setParameter("RECEIPT", QVariant(result));
|
|
QTimer::singleShot(1000, this, SLOT(onCCPrintReceipt()));
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCConfirmTransactionResult() resultState is ERROR_BUSY";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void AppControl::onCCCancelTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
qCritical() << "AppControl::onCCCancelTransactionResult() result = " << result;
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
vmc->SendLongFormatedStringReference(result);
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCCancelTransactionResult() resultState is ERROR_BUSY";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// send receipt for printing
|
|
void AppControl::onCCPrintReceipt()
|
|
{
|
|
if (this->vendingData->hasParameter("RECEIPT")) {
|
|
qCritical() << "DEBUG: onCCPrintReceipt() hasParameter(\"RECEIPT\")";
|
|
vmc->ccPrintReceipt(this->vendingData->getParameter("RECEIPT").toString());
|
|
|
|
#if defined (USE_QRCODE_RECEIPT)
|
|
if (config->qrCodeReceiptIsUsed()) {
|
|
QRCodeGenerator::generateQRCode(this->vendingData->getParameter("RECEIPT").toString());
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
qCritical() << "onCCPrintReceipt() vendingData Parameter(\"RECEIPT\") not available";
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AppControl::onCCStartPreauthorisation()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
#ifdef USE_CC_PREAUTHORISATION
|
|
cc->requestPreAuthTransaction(this->vendingData->getUintParameter("AMOUNT"));
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCCPreAuthTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
#ifdef USE_CC_PREAUTHORISATION
|
|
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() result = " << result;
|
|
|
|
QString vmcResult; // 'String', sent to vmc
|
|
|
|
|
|
bool ok;
|
|
QVariantMap jsonCardInfo;
|
|
QString cardInfo;
|
|
QString cardTransactionInfo;
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::INFO:
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() resultState is INFO: " << result;
|
|
if (result.contains("PAYMENT PREPARED")) {
|
|
hmi->setCCBusy(false);
|
|
hmi->enableCCAbort(true);
|
|
}
|
|
else
|
|
if (result.contains("PAYMENT DISABLE ABORT")) {
|
|
hmi->enableCCAbort(false);
|
|
}
|
|
else
|
|
if (result.startsWith("04FF#")) {
|
|
hmi->displayCCMessage(result);
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() resultState is ERROR_BUSY";
|
|
if (this->isProgramModeSELL()) {
|
|
// set mode busy
|
|
hmi->setCCBusy(true);
|
|
QTimer::singleShot(2000, this, SLOT(onCCStartPreauthorisation()));
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() resultState is SUCCESS";
|
|
|
|
jsonCardInfo = JSON::parse(result, ok).toMap();
|
|
|
|
if (ok) {
|
|
// TODO: set correct parameter names...
|
|
cardInfo = jsonCardInfo["INSTITUTSNUMMER"].toString(); // Institutsnummer
|
|
cardTransactionInfo = jsonCardInfo["BELEGNUMMER"].toString(); // ZVT-Belegnummer
|
|
|
|
this->vendingData->setParameter("INSTITUTSNUMMER", QVariant(cardInfo));
|
|
this->vendingData->setParameter("ZVT_BELEGNUMMER", QVariant(cardTransactionInfo));
|
|
|
|
this->onCalculatePrice(cardInfo, cardTransactionInfo);
|
|
}
|
|
else {
|
|
// result is no json: abort
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_STATE:
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() resultState is ERROR_STATE";
|
|
qCritical() << " result is: " << result;
|
|
if (result.contains("DAYCLOSE RUNNING")) {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
else
|
|
if (result.contains("INIT RUNNING")) {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
else {
|
|
qCritical() << "ASSERT: unhandled RESULT_STATE::ERROR_STATE";
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
// ignore this result message
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BACKEND:
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() resultState is ERROR_BACKEND";
|
|
this->onCCErrorBackend(result);
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
qCritical() << "AppControl::onCCPreAuthTransactionResult() resultState is ERROR_TIMEOUT";
|
|
vmcResult[0] = result.at(0);
|
|
vmcResult[1] = result.at(1);
|
|
if (result.at(0) == 0x45 && result.at(1) == 0x00) {
|
|
qCritical() << "ASSERT: RESULT_STATE::ERROR_TIMEOUT: sending 0x45 00 to VMC";
|
|
}
|
|
else {
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
break;
|
|
default:
|
|
if(result.size()>0) {
|
|
qCritical() << "ASSERT: unhandled RESULT_STATE";
|
|
qCritical() << " result is: " << result;
|
|
if (result.at(0) == 0x45 && result.at(1) == 0x00) {
|
|
qCritical() << "ASSERT: 'default' sending 0x45 00 to VMC";
|
|
}
|
|
else {
|
|
vmcResult[0] = 0x45; // 'E'
|
|
vmcResult[1] = 0x65; // 'e'
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#else
|
|
Q_UNUSED(resultState);
|
|
Q_UNUSED(result);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void AppControl::onCCConfirmPreauthorisation()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
#ifdef USE_CC_PREAUTHORISATION
|
|
if (!this->vendingData->hasParameter("ZVT_BELEGNUMMER")) {
|
|
qCritical() << "onCCConfirmPreauthorisation(): ERROR: missing vendingData \"ZVT_BELEGNUMMER\"";
|
|
return;
|
|
}
|
|
|
|
QString zvt_belegnummer = this->vendingData->getParameter("ZVT_BELEGNUMMER").toString();
|
|
|
|
cc->requestBookTotalTransaction(this->vendingData->getUintParameter("AMOUNT"),
|
|
zvt_belegnummer);
|
|
|
|
#else
|
|
qCritical() << "CC Preauthorisation is not supported, please define USE_CC_PREAUTHORISATION";
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCCCancelPreauthorisationRequest()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
#ifdef USE_CC_PREAUTHORISATION
|
|
QString zvt_belegnummer;
|
|
|
|
if (this->vendingData->hasParameter("ZVT_BELEGNUMMER")) {
|
|
zvt_belegnummer = this->vendingData->getParameter("ZVT_BELEGNUMMER").toString();
|
|
|
|
qCritical() << "onCCCancelPreauthorisationRequest() with receipt number: " << zvt_belegnummer;
|
|
|
|
cc->requestCancelPreAuthTransaction(zvt_belegnummer);
|
|
}
|
|
else {
|
|
qCritical() << "onCCCancelPreauthorisationRequest(): ERROR: missing vendingData \"ZVT_BELEGNUMMER\"";
|
|
}
|
|
|
|
#else
|
|
qCritical() << "CC Preauthorisation is not supported, please define USE_CC_PREAUTHORISATION";
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void AppControl::onCCCancelPreAuthTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
|
|
#ifdef USE_CC_PREAUTHORISATION
|
|
qCritical() << "AppControl::onCCCancelPreAuthTransactionResult() result = " << result;
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
vmc->SendLongFormatedStringReference(result);
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCCancelPreAuthTransactionResult() resultState is ERROR_BUSY";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
#else
|
|
Q_UNUSED(resultState);
|
|
Q_UNUSED(result);
|
|
#endif // USE_CC_PLUGIN
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCCBookTotalTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
qCritical() << "AppControl::onCCBookTotalTransactionResult() result = " << result;
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
this->vendingData->setParameter("RECEIPT", QVariant(result));
|
|
QTimer::singleShot(1000, this, SLOT(ccSendReceipt()));
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCBookTotalTransactionResult() resultState is ERROR_BUSY";
|
|
break;
|
|
default:
|
|
qCritical() << "AppControl::onCCBookTotalTransactionResult() ERROR:";
|
|
qCritical() << " errorDescription = " << cc->getLastErrorDescription();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCCRevertTransactionResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
qCritical() << "AppControl::onCRevertTransactionResult() result = " << result;
|
|
|
|
if (resultState == nsCCInterface::RESULT_STATE::ERROR_BUSY) {
|
|
qCritical() << "AppControl::onCCRevertTransactionResult() resultState is ERROR_BUSY";
|
|
}
|
|
|
|
vmc->SendLongFormatedStringReference(result);
|
|
#else
|
|
Q_UNUSED(resultState);
|
|
Q_UNUSED(result);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
"{
|
|
"06": {
|
|
"1F0b": "000000010000",
|
|
"1F14": "ee910b469d5f40bcba9a4c71c062769e", <-- TOKEN
|
|
"1F45": "0c788074038031c073d631c0",
|
|
"1F4c": "01",
|
|
"1F4d": "fe04",
|
|
"1F4f": "0400",
|
|
"1F50": "20",
|
|
"4c": "0000000000000880afaa", <-- UID
|
|
"62": {
|
|
"60[0]": {
|
|
"41": "0005",
|
|
"43": "a0000003591010028001"
|
|
}
|
|
}
|
|
},
|
|
"23": "6725904400002036478d22122012845018450f",
|
|
"27": "00"
|
|
}"
|
|
*/
|
|
void AppControl::onCCRequestCardInfoResult(nsCCInterface::RESULT_STATE resultState, QString & result)
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
#ifdef USE_CC_READCARD
|
|
qDebug() << "AppControl::onCCRequestCardInfoResult(): ";
|
|
|
|
bool ok;
|
|
QVariantMap jsonCardInfo;
|
|
QVariantMap TLVContrainer;
|
|
QByteArray tokenBA;
|
|
QString cardInfo;
|
|
QString cardTransactionInfo;
|
|
|
|
JSON::setPrettySerialize(true);
|
|
JSON::JsonObject json;
|
|
|
|
switch (resultState) {
|
|
case nsCCInterface::RESULT_STATE::SUCCESS:
|
|
qDebug() << " resultState = SUCCESS";
|
|
|
|
jsonCardInfo = JSON::parse(result, ok).toMap();
|
|
|
|
if (ok) {
|
|
JSON::JsonObject
|
|
TLVContrainer = jsonCardInfo["06"].toMap();
|
|
|
|
tokenBA = TLVContrainer["1F14"].toString().toLatin1();
|
|
|
|
cardInfo = jsonCardInfo["23"].toString().mid(3,5);
|
|
|
|
this->vendingData->setParameter("INSTITUTSNUMMER", QVariant(cardInfo));
|
|
}
|
|
else {
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is SUCCESS but no valid JSON";
|
|
}
|
|
|
|
// note: cardTransactionInfo = "" -> empty sting
|
|
this->onCalculatePrice(cardInfo, cardTransactionInfo);
|
|
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_BUSY:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is ERROR_BUSY";
|
|
if (this->isProgramModeSELL()) {
|
|
// set mode busy
|
|
hmi->setCCBusy(true);
|
|
QTimer::singleShot(2000, this, SLOT(onCCStartReadCard()));
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::INFO:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is INFO: " << result;
|
|
if (result.contains("STARTING CARD INFO READ ON CC")) {
|
|
hmi->setCCBusy(false);
|
|
hmi->enableCCAbort(true);
|
|
}
|
|
else
|
|
if (result.startsWith("04FF#")) {
|
|
hmi->displayCCMessage(result);
|
|
}
|
|
break;
|
|
case nsCCInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is ERROR_TIMEOUT: " << result;
|
|
/* FALLTHRU */
|
|
case nsCCInterface::RESULT_STATE::ERROR_BACKEND:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is ERROR_BACKEND: " << result;
|
|
/* FALLTHRU */
|
|
case nsCCInterface::RESULT_STATE::ERROR_NETWORK:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is ERROR_NETWORK: " << result;
|
|
/* FALLTHRU */
|
|
case nsCCInterface::RESULT_STATE::ERROR_PROCESS:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is ERROR_PROCESS: " << result;
|
|
/* FALLTHRU */
|
|
case nsCCInterface::RESULT_STATE::ERROR_STATE:
|
|
qCritical() << "AppControl::onCCRequestCardInfoResult() resultState is ERROR_STATE: " << result;
|
|
qCritical() << " -> send ButtonCancel to vmc";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x39); // "System error"
|
|
break;
|
|
}
|
|
|
|
qDebug() << " JSON-String = " << result;
|
|
|
|
#else
|
|
Q_UNUSED(resultState)
|
|
Q_UNUSED(result)
|
|
|
|
#endif // USE_CC_READCARD
|
|
#else
|
|
Q_UNUSED(resultState);
|
|
Q_UNUSED(result);
|
|
#endif // USE_CC_PLUGIN
|
|
}
|
|
|
|
|
|
void AppControl::onCCStartReadCard()
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
#ifdef USE_CC_READCARD
|
|
cc->requestCardInfo();
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
|
|
void AppControl::onCCErrorBackend(QString & result)
|
|
{
|
|
#ifdef USE_CC_PLUGIN
|
|
QString vmcResult; // 'String', sent to vmc
|
|
QString errorcode;
|
|
QString errortext;
|
|
QString protocol;
|
|
|
|
bool ok;
|
|
QVariantMap jsonResult = JSON::parse(result, ok).toMap();
|
|
|
|
if (ok) {
|
|
// new, JSON
|
|
errorcode = jsonResult["errorcode"].toString();
|
|
errortext = jsonResult["errortext"].toString();
|
|
protocol = jsonResult["protocol"].toString();
|
|
|
|
vmcResult[0] = 0x45;
|
|
vmcResult[1] = errorcode.toUInt(&ok, 16);
|
|
}
|
|
else {
|
|
// legacy
|
|
vmcResult[0] = result.at(0);
|
|
vmcResult[1] = result.at(1);
|
|
}
|
|
|
|
if (result.at(0) == 0x45 && result.at(1) == 0x00) {
|
|
qCritical() << "ASSERT: RESULT_STATE::ERROR_BACKEND: prevent sending 0x45 00 to VMC";
|
|
vmcResult[1] = 0xFF;
|
|
}
|
|
|
|
#if defined (CUST00318)
|
|
// hack for 00318/Nexobility
|
|
if (result.at(1) == 0x13)
|
|
this->private_CUST00318_handle_CC_ERROR_0x13();
|
|
else {
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
}
|
|
#else
|
|
vmc->SendLongFormatedStringReference(vmcResult);
|
|
#endif
|
|
|
|
#else
|
|
Q_UNUSED(result);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_CALCULATEPRICE_PLUGIN
|
|
/*****************************************************************************
|
|
* CalculatePricePlugin
|
|
*/
|
|
void AppControl::onCalculatePrice(QString & licensePlate)
|
|
{
|
|
Q_UNUSED(licensePlate);
|
|
|
|
this->onCalculatePrice();
|
|
}
|
|
|
|
void AppControl::onCalculatePrice()
|
|
{
|
|
|
|
#if defined (CUST00300) || defined (CUST00324)
|
|
// PRM license plate validation:
|
|
QString licensePlateString = this->vendingData->getParameter("LICENSEPLATE").toString();
|
|
|
|
// cr20201118/2: switch off lp validation
|
|
/*
|
|
if (!LicencePlateValidator::validateLicensePlate(licensePlateString)) {
|
|
this->onShowMessageBox(MessageBoxType::NOBUTTON, 0x34, QStringList() << licensePlateString);
|
|
this->onCloseBusy();
|
|
return;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
// cr20201118/3: switch off lp re-entry
|
|
/*
|
|
int lpcount = vendingData->getParameter("LPCOUNT").toInt();
|
|
|
|
if (lpcount == 0) { // -> the first try to insert licenseplate
|
|
this->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35, QStringList() << licensePlateString);
|
|
this->onCloseBusy();
|
|
vendingData->setParameter("LP1", QVariant(licensePlateString));
|
|
vendingData->setParameter("LPCOUNT", QVariant(1));
|
|
screenLicPlate->onClearUserInputData();
|
|
return;
|
|
}
|
|
else
|
|
if (lpcount == 1) { // -> the second try to insert licenseplate
|
|
vendingData->setParameter("LP2", QVariant(licensePlateString));
|
|
vendingData->setParameter("LPCOUNT", QVariant(2));
|
|
|
|
// compare to LPs:
|
|
if (vendingData->getParameter("LP1").toString() != vendingData->getParameter("LP2").toString()) {
|
|
// TODO: -> Headline Text, Screen 0x31: "Bitte Kennzeichen erneut eingeben"
|
|
|
|
this->onShowMessageBox(MessageBoxType::NOBUTTON, 0x36,
|
|
QStringList() << vendingData->getParameter("LP1").toString()
|
|
<< vendingData->getParameter("LP2").toString() );
|
|
this->onCloseBusy();
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
screenLicPlate->onClearUserInputData();
|
|
return;
|
|
}
|
|
// ... jetzt passts, jetzt wird die Preisabfrage gestellt.
|
|
}
|
|
else
|
|
if (lpcount == 2) {
|
|
qCritical() << "HMI::onCalculatePrice() PRM: invalid 'lpcount'";
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
this->onCloseBusy();
|
|
return;
|
|
}
|
|
else {
|
|
// ASSERT / LOG:
|
|
qCritical() << "HMI::onCalculatePrice() PRM: invalid state'";
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
this->onCloseBusy();
|
|
return;
|
|
}
|
|
*/
|
|
|
|
// cr20201118/4: re-entry if calculate price failed
|
|
int lpcount = vendingData->getParameter("LPCOUNT").toInt();
|
|
|
|
if (lpcount == 0) { // -> the first try to insert licenseplate
|
|
vendingData->setParameter("LPCOUNT", QVariant(1));
|
|
hmi->onClearUserInputFields();
|
|
}
|
|
else
|
|
if (lpcount == 1) { // -> the second try to insert licenseplate
|
|
vendingData->setParameter("LPCOUNT", QVariant(2));
|
|
}
|
|
else {
|
|
// ASSERT / LOG:
|
|
qCritical() << "HMI::onCalculatePrice() PRM: invalid state'";
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
hmi->onCloseBusy();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if defined (CUST00318)
|
|
// Nexobility
|
|
|
|
// CalculatePrice State is licenseplate only:
|
|
this->vendingData->setParameter("CP_STATE", QVariant().fromValue(CP_STATE::LICENSEPLATE_INPUT));
|
|
#endif
|
|
|
|
#if defined (CUST00328)
|
|
// ParkAndControl
|
|
|
|
QString licensePlateString = this->vendingData->getParameter("LICENSEPLATE").toString();
|
|
|
|
if (licensePlateString.length() == 0) return;
|
|
|
|
// re-entry if calculate price failed
|
|
int lpcount = vendingData->getParameter("LPCOUNT").toInt();
|
|
|
|
if (lpcount == 0) { // -> the first try to insert licenseplate
|
|
vendingData->setParameter("LPCOUNT", QVariant(1));
|
|
hmi->onClearUserInputFields();
|
|
}
|
|
else
|
|
if (lpcount == 1) { // -> the second try to insert licenseplate
|
|
vendingData->setParameter("LPCOUNT", QVariant(2));
|
|
}
|
|
else {
|
|
// ASSERT / LOG:
|
|
qCritical() << "HMI::onCalculatePrice() ParkAndControl: invalid state'";
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
hmi->onCloseBusy();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if defined (USE_CALCULATEPRICE_PLUGIN)
|
|
this->calcPriceBackend->requestCalculatePrice(
|
|
this->vendingData->getParameter("LICENSEPLATE").toString(),
|
|
"LICENSEPLATE",
|
|
this->vendingData->getParameter("PermitType").toString());
|
|
#endif
|
|
}
|
|
|
|
void AppControl::onCalculatePrice(uint parktime)
|
|
{
|
|
this->vendingData->setParameter("PARKTIME", QVariant(parktime));
|
|
|
|
// CalculatePrice State is licenseplate and parking time:
|
|
this->vendingData->setParameter("CP_STATE", QVariant().fromValue(CP_STATE::PARKINGTIME_INPUT));
|
|
|
|
|
|
#if defined (USE_CALCULATEPRICE_PLUGIN)
|
|
this->calcPriceBackend->requestCalculatePrice(
|
|
this->vendingData->getParameter("LICENSEPLATE").toString(),
|
|
"LICENSEPLATE",
|
|
this->vendingData->getParameter("PermitType").toString(),
|
|
this->vendingData->getParameter("PARKTIME").toString());
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void AppControl::onCalculatePrice(QString & cardInfo, QString & cardTransactionInfo)
|
|
{
|
|
this->vendingData->setParameter("CARDINFO", QVariant(cardInfo));
|
|
this->vendingData->setParameter("CARDTRANSACTIONINFO", QVariant(cardTransactionInfo));
|
|
this->vendingData->setParameter("CP_STATE", QVariant().fromValue(CP_STATE::CARDINFO_INPUT));
|
|
|
|
#if defined (USE_CALCULATEPRICE_PLUGIN)
|
|
this->calcPriceBackend->requestCalculatePrice(
|
|
this->vendingData->getParameter("LICENSEPLATE").toString(),
|
|
"LICENSEPLATE",
|
|
this->vendingData->getParameter("PermitType").toString(),
|
|
this->vendingData->getParameter("PARKTIME").toString(),
|
|
this->vendingData->getParameter("CARDINFO").toString(),
|
|
this->vendingData->getParameter("CARDTRANSACTIONINFO").toString());
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* handle CalculatePrice response data
|
|
*
|
|
*/
|
|
void AppControl::onCalculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
|
|
|
|
// DEBUG ------------------------------------------------------------------------------------
|
|
qCritical() << "onCalculatedPrice() resultState = " << this->calcPriceBackend->getString(resultState) << "\n"
|
|
<< " accessInformation = " << accessInformation << "\n"
|
|
<< " accessInformationType = " << accessInformationType << "\n"
|
|
<< " amountDuePeriodStart = " << amountDuePeriodStart << "\n"
|
|
<< " amountDuePeriodEnd = " << amountDuePeriodEnd << "\n"
|
|
<< " priceInfo.priceNet = " << QString::number(priceInfo.priceNet) << "\n"
|
|
<< " priceInfo.priceTax = " << QString::number(priceInfo.priceTax) << "\n"
|
|
<< " priceInfo.priceGross = " << QString::number(priceInfo.priceGross) << "\n"
|
|
<< " priceInfo.taxRate = " << QString::number(priceInfo.taxRate) << "\n"
|
|
<< " errorCode = " << errorCode << "\n"
|
|
<< " errorDescription = " << errorDescription;
|
|
|
|
|
|
nsCalculatePriceInterface::RESULT_STATE resultState_priv = resultState;
|
|
|
|
#if defined (ARCH_DesktopLinux)
|
|
// TEST / SIMULATION
|
|
// To call parktime input screen
|
|
/*
|
|
int simulation_run = vendingData->getParameter("SIMULATION_RUN").toInt();
|
|
if (simulation_run == 0) {
|
|
qDebug() << "HMI::onCalculatedPrice() Simulation run 1: ERROR_BACKEND";
|
|
resultState_priv = nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND;
|
|
vendingData->setParameter("SIMULATION_RUN", QVariant(1));
|
|
}
|
|
else {
|
|
qDebug() << "HMI::onCalculatedPrice() Simulation run 2";
|
|
}
|
|
*/
|
|
#endif
|
|
|
|
QString resultMessage;
|
|
switch(resultState_priv) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
resultMessage = "CalculatePrice success";
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
// in this case we print only the message from backend
|
|
resultMessage = errorDescription;
|
|
//resultMessage = "CalculatePrice error: BACKEND\n";
|
|
//resultMessage.append(" errorCode: ").append(errorCode);
|
|
//resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
resultMessage = "CalculatePrice error: NETWORK\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode).append("\n");
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
resultMessage = "CalculatePrice error: TIMEOUT\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode).append("\n");
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
resultMessage = "CalculatePrice error: PROCESS\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode).append("\n");
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_RETRY:
|
|
resultMessage = "CalculatePrice error: RETRY\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode).append("\n");
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
default:
|
|
resultMessage = "CalculatePrice error: Unknown Error\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode).append("\n");
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
}
|
|
qCritical() << resultMessage;
|
|
|
|
// call project specific handler
|
|
QString VMCCalcString;
|
|
VMCCalcString = private_calculatedPrice(resultState,
|
|
accessInformation,
|
|
accessInformationType,
|
|
amountDuePeriodStart,
|
|
amountDuePeriodEnd,
|
|
priceInfo,
|
|
errorCode,
|
|
errorDescription);
|
|
|
|
|
|
if (VMCCalcString.size() > 0) {
|
|
// Send D0-CALC to VMC ----------------------------------------------
|
|
// -> expect a screen change / response from VMC
|
|
|
|
// DEBUG
|
|
qCritical() << "onCalculatedPrice() VMCCalcString: " << VMCCalcString;
|
|
|
|
hmi->onShowBusy(1);
|
|
vmc->SendFormatedString(VMCCalcString);
|
|
}
|
|
else {
|
|
// do not send something to VMC -------------------------------------
|
|
// -> no response / action from VMC is expected
|
|
// -> this is e.g. in case of a new tariff step
|
|
hmi->onCloseBusy();
|
|
}
|
|
|
|
/*
|
|
vcl->SendAmountDueNet(QString::number(priceInfo.priceNet));
|
|
vcl->SendAmountDueTax(QString::number(priceInfo.priceTax);
|
|
vcl->SendAmountDuePeriodStart(amountDuePeriodStart);
|
|
vcl->SendAmountDuePeriodEnd(amountDuePeriodEnd);
|
|
*/
|
|
|
|
// store values in vendingData: to detect a possible missing transaction
|
|
vendingData->setParameter("TRANS", QVariant(1)); // marker, that transaction is pending
|
|
vendingData->setParameter("ACCESSINFORMATION", QVariant(accessInformation));
|
|
}
|
|
|
|
/**
|
|
* @brief AppControl::private_getAccessInformationField
|
|
* @param accessInformationType
|
|
* @return QChar
|
|
*
|
|
* Transform accessInformationType-String to a QChar for usage in VMC formated String
|
|
*/
|
|
QChar AppControl::private_getAccessInformationField(const QString & accessInformationType)
|
|
{
|
|
QChar accessInformationTypeField;
|
|
if (accessInformationType == "LICENSEPLATE") {
|
|
accessInformationTypeField = '1';
|
|
} else
|
|
if (accessInformationType == "BARCODE") {
|
|
accessInformationTypeField = '2';
|
|
} else
|
|
if (accessInformationType == "RFID") {
|
|
accessInformationTypeField = '3';
|
|
} else
|
|
if (accessInformationType == "QRCODE") {
|
|
accessInformationTypeField = '4';
|
|
} else
|
|
if (accessInformationType == "PIN") {
|
|
accessInformationTypeField = '5';
|
|
} else
|
|
if (accessInformationType == "UID") {
|
|
accessInformationTypeField = '6';
|
|
} else {
|
|
accessInformationTypeField = '\0';
|
|
qCritical() << "onCalculatedPrice() accessInformationType " << accessInformationType
|
|
<< " is currently not processed!";
|
|
}
|
|
|
|
return accessInformationTypeField;
|
|
}
|
|
|
|
|
|
#if defined (CUST00297) || defined (CUST00271) || defined (CUST00218)
|
|
// Lithunia (Kaunas, KaunasMuseum, Panevezys):
|
|
QString AppControl::private_calculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
Q_UNUSED(errorCode)
|
|
|
|
QString formatedString;
|
|
|
|
QChar accessInformationTypeField = this->private_getAccessInformationField(accessInformationType);
|
|
|
|
switch(resultState) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
// on SUCCESS: send SUCCESS-formatedString
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceNet)).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceTax)).append('#');
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
// show message box
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, "", errorDescription);
|
|
|
|
// send abort to vmc ... is sent by message box
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_RETRY:
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35);
|
|
break;
|
|
}
|
|
|
|
return formatedString;
|
|
}
|
|
// END: Lithunia (Kaunas, KaunasMuseum, Panevezys)
|
|
|
|
|
|
#elif defined (CUST02100)
|
|
// Goldbeck -> for fallback tariff
|
|
QString AppControl::private_calculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
Q_UNUSED(errorCode)
|
|
Q_UNUSED(errorDescription)
|
|
|
|
QString formatedString;
|
|
|
|
QChar accessInformationTypeField = this->private_getAccessInformationField(accessInformationType);
|
|
|
|
switch(resultState) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
// on SUCCESS: send SUCCESS-formatedString
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceNet)).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceTax)).append('#');
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append("0").append('#');
|
|
formatedString.append("ERROR").append('#');
|
|
// VMC can not handle ISO8859 encoded error texts!!!!
|
|
// -> formatedString.append(errorText).append('#');
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_RETRY:
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35);
|
|
break;
|
|
}
|
|
|
|
return formatedString;
|
|
}
|
|
// END: Goldbeck
|
|
|
|
|
|
#elif defined (CUST00300) || defined (CUST00324)
|
|
// PRM / ARIVO: "honest parking"
|
|
QString AppControl::private_calculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
Q_UNUSED(errorCode)
|
|
Q_UNUSED(errorDescription)
|
|
|
|
QString formatedString;
|
|
int lpcount;
|
|
|
|
QChar accessInformationTypeField = this->private_getAccessInformationField(accessInformationType);
|
|
|
|
switch(resultState) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
// on SUCCESS: send SUCCESS-formatedString
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceNet)).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceTax)).append('#');
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
lpcount = vendingData->getParameter("LPCOUNT").toInt();
|
|
if (lpcount == 1) { // -> re-enter lp
|
|
// -> Msg-Box: "Kennzeichen erneut eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
}
|
|
else
|
|
if (lpcount == 2) { // -> Input Parking time (honest payment)
|
|
|
|
if (config->useHonestPayment()) {
|
|
|
|
// note: in case of an error, 'accessInformation' is possibly empty so we use vendingData:
|
|
hmi->onDisplayData(0x48, this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
hmi->showScreen(Ui::SCREEN_PARKTIME1);
|
|
|
|
// -> Msg-Box: "Parkdauer eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x37, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
|
|
}
|
|
else {
|
|
|
|
// -> Msg-Box: "Kennzeichen wurde nicht gefunden":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_SEND_CANCEL, 0x40);
|
|
|
|
}
|
|
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
}
|
|
else {
|
|
// note: this could happen, e.g. if calculatePrice returns an error on an request with parking time parameter.
|
|
qCritical() << "onCalculatedPrice(): invalid lpcount!";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x38); // Network Error
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
}
|
|
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
// Network Error
|
|
qCritical() << "onCalculatedPrice(): Network error!";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x38); // Network Error
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
qCritical() << "onCalculatedPrice(): System error!";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x39); // System Error
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_RETRY:
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35);
|
|
break;
|
|
}
|
|
|
|
return formatedString;
|
|
}
|
|
// END: PRM / ARIVO
|
|
|
|
|
|
|
|
#elif defined (CUST00318)
|
|
// Nexobility: "honest parking"
|
|
QString AppControl::private_calculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
Q_UNUSED(errorCode)
|
|
Q_UNUSED(errorDescription)
|
|
|
|
QString formatedString;
|
|
|
|
CP_STATE cp_state = vendingData->getParameter("CP_STATE").value<CP_STATE>();
|
|
|
|
QChar accessInformationTypeField = this->private_getAccessInformationField(accessInformationType);
|
|
|
|
switch(resultState) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
// on SUCCESS: send SUCCESS-formatedString
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceNet)).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceTax)).append('#');
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
|
|
// Nexobility: Discount
|
|
if (vendingData->getParameter("CP_STATE").value<CP_STATE>() == CP_STATE::CARDINFO_INPUT) {
|
|
// DISCOUNT:
|
|
int oldAmountNet = this->vendingData->getParameter("PRICE").toString().toInt();
|
|
int newAmountNet = priceInfo.priceNet;
|
|
if (newAmountNet < oldAmountNet) {
|
|
// discount is valid - show a message box with new price:
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_SUCCESS, 0x34,
|
|
QStringList() << utils::getPriceString(priceInfo.priceNet, priceInfo.priceTax));
|
|
}
|
|
else {
|
|
// discount is not valid - show a message box with error:
|
|
hmi->onShowMessageBox(MessageBoxType::OK_FAILURE, 0x3a,
|
|
QStringList() << utils::getPriceString(priceInfo.priceNet, priceInfo.priceTax));
|
|
}
|
|
|
|
// Trigger VMC on CloseButton sent from message box
|
|
vendingData->setParameter("CloseAction", QVariant::fromValue(APP_ACTION::SEND_D0_CALC));
|
|
vendingData->setParameter("D0_CALC", QVariant(formatedString));
|
|
|
|
formatedString.clear();
|
|
}
|
|
else {
|
|
this->vendingData->setParameter("PRICE", QVariant(utils::getPriceString(priceInfo.priceNet)));
|
|
}
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
// action depends on CP_STATE:
|
|
switch (cp_state) {
|
|
case CP_STATE::LICENSEPLATE_INPUT:
|
|
// 1st request: only with license plate
|
|
// Ask if licence plate is correct
|
|
hmi->onShowMessageBox(MessageBoxType::YESNO, 0x35, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
vendingData->setParameter("YesAction", QVariant::fromValue(APP_ACTION::PARKINGTIME_INPUT));
|
|
vendingData->setParameter("NoAction", QVariant::fromValue(APP_ACTION::LICENSEPLATE_INPUT));
|
|
qCritical() << "-> CP: ERROR_BACKEND - CP_STATE = LICENSEPLATE_INPUT";
|
|
break;
|
|
case CP_STATE::PARKINGTIME_INPUT:
|
|
// - possibly additional request: with parking time
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x39); // "System error"
|
|
qCritical() << "-> CP: ERROR_BACKEND - CP_STATE = PARKINGTIME_INPUT";
|
|
break;
|
|
case CP_STATE::CARDINFO_INPUT:
|
|
// - 2nd request: with license plate and cardInfo
|
|
// Note: this should be a very rare case (2nd request fails!)
|
|
// It is easier to cancel vending process here. Normally we should resend the
|
|
// formated string again to vmc.
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x36); // "Keine Rabattierung möglich"
|
|
qCritical() << "-> CP: ERROR_BACKEND - CP_STATE = CARDINFO_INPUT";
|
|
break;
|
|
case CP_STATE::NO_STATE:
|
|
qCritical() << "onCalculatedPrice(): CP_STATE::NO_STATE";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x39); // System Error
|
|
break;
|
|
}
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
// Network Error
|
|
qCritical() << "onCalculatedPrice(): Network error!";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x38); // Network Error
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
// System Error
|
|
qCritical() << "onCalculatedPrice(): System error!";
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x39); // System Error
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_RETRY:
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35);
|
|
break;
|
|
}
|
|
|
|
return formatedString;
|
|
}
|
|
// END: Nexobility
|
|
|
|
#elif defined (CUST00328)
|
|
// ParkAndControl
|
|
QString AppControl::private_calculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
Q_UNUSED(errorCode)
|
|
Q_UNUSED(errorDescription)
|
|
|
|
// this is sent to VMC:
|
|
QString formatedString;
|
|
int lpcount = vendingData->getParameter("LPCOUNT").toInt();
|
|
|
|
// reference time to setup dateTime input:
|
|
QDateTime referenceDateTime = QDateTime::currentDateTime();
|
|
|
|
QChar accessInformationTypeField = this->private_getAccessInformationField(accessInformationType);
|
|
|
|
// currently tarif calculation depends on certain screens
|
|
Ui::SCREEN currentScreen = this->hmi->getCurrentScreen();
|
|
|
|
// Note for APCOA: this plugin does always provide valid sales data. Even e.g. if lookup
|
|
// fails for some reason (e.g. no network is available).
|
|
// So we have TODO:
|
|
// - set HMI-Data (onDisplayData) in any case / or even on certain Errors (ERROR_NETWORK)
|
|
// - send formated string to VMC if necessary if we need a screen change (e.g. switch to
|
|
// parking-time input.
|
|
|
|
|
|
switch(resultState) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
|
|
// on SUCCESS: send SUCCESS-formatedString
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceNet)).append('#');
|
|
formatedString.append(QString::number(priceInfo.priceTax)).append('#');
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
|
|
// set HMI-Data
|
|
this->hmi->onDisplayData(0x48, accessInformation);
|
|
this->hmi->onDisplayData(0x51, utils::getPriceStringFormated(priceInfo.priceGross,this->config->getPaymentCurrencySymbol()));
|
|
switch (config->getPaymentPointInTime()) {
|
|
case PAYMENT_POINTINTIME::PAY_ON_ARRIVAL:
|
|
this->hmi->onDisplayData(0x50, utils::getTimeStringFormated(amountDuePeriodEnd)); // Displayed ParktimeEnd
|
|
this->hmi->onDisplayData(0x54, utils::getTimeStringFormated(amountDuePeriodStart)); // Displayed EntryTime
|
|
break;
|
|
case PAYMENT_POINTINTIME::PAY_ON_EXIT:
|
|
this->hmi->onDisplayData(0x50, utils::getTimeStringFormated(amountDuePeriodStart)); // Displayed EntryTime, EndTime is currentTime
|
|
this->hmi->onDisplayData(0x54, utils::getTimeStringFormated(amountDuePeriodStart)); // Displayed EntryTime, EndTime is currentTime
|
|
break;
|
|
case PAYMENT_POINTINTIME::IGNORE:
|
|
this->hmi->onDisplayData(0x50, utils::getTimeStringFormated(amountDuePeriodStart)); // Displayed EntryTime, EndTime is not relevant
|
|
this->hmi->onDisplayData(0x54, utils::getTimeStringFormated(amountDuePeriodStart)); // Displayed EntryTime, EndTime is not relevant
|
|
break;
|
|
}
|
|
|
|
// set vendingData
|
|
this->vendingData->setParameter("AMOUNT", utils::getPriceByteArray(priceInfo.priceGross));
|
|
this->vendingData->setParameter("DATETIME_PARKEND", amountDuePeriodEnd);
|
|
|
|
// ensure, that "D0_CALC"-string is always initialized and prepared to send to VMC
|
|
vendingData->setParameter("D0_CALC", QVariant(formatedString));
|
|
|
|
switch (currentScreen) {
|
|
case Ui::SCREEN_LICPLT:
|
|
case Ui::SCREEN_DATETIME1: // honest payment: with entry date/time
|
|
case Ui::SCREEN_PARKTIME1: // honest payment: with parkingtime in minutes
|
|
// Trigger VMC immediately
|
|
break;
|
|
case Ui::SCREEN_PARKEND: // on selecting parking endtime
|
|
// Trigger VMC on NextButton, do not send formatedString immediately
|
|
formatedString.clear();
|
|
break;
|
|
default:
|
|
qCritical() << "AppControl::private_calculatedPrice() called with invalid screen.";
|
|
formatedString.clear(); // do not send formatedString
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "onCalculatedPrice(): ERROR_TIMEOUT || ERROR_NETWORK || ERROR_BACKEND:" << endl
|
|
<< " honest payment = " << config->useHonestPayment() << endl
|
|
<< " current screen = " << "0x" + QString(static_cast<quint8>(currentScreen)).toLatin1().toHex() << endl
|
|
<< " paymentTime = " << config->getPaymentPointInTime();
|
|
|
|
if (config->useHonestPayment()) {
|
|
// ------------------------------ honest payment ------------------------------------
|
|
|
|
|
|
switch (currentScreen) {
|
|
case Ui::SCREEN_LICPLT:
|
|
|
|
// cause honest payment
|
|
// => #CALC empty price
|
|
|
|
if (lpcount == 1) { // -> re-enter lp
|
|
// -> Msg-Box: "Kennzeichen erneut eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35);
|
|
}
|
|
else {
|
|
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append("").append('#'); // empty price
|
|
formatedString.append("").append('#'); // empty price
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
|
|
// ... and set HMI-Data (price is still not valid)
|
|
this->hmi->onDisplayData(0x48, accessInformation);
|
|
|
|
// setup HMI screen DateTime --------------------------
|
|
hmi->setupDateTimeInput(referenceDateTime,
|
|
Ui::DateTimeInputMode::Down,
|
|
referenceDateTime,
|
|
referenceDateTime.addDays(-10));
|
|
|
|
// prepare "D0_CALC"-string to send to VMC
|
|
vendingData->setParameter("D0_CALC", QVariant(formatedString));
|
|
|
|
// Trigger VMC on CloseButton sent from message box
|
|
vendingData->setParameter("CloseAction", QVariant::fromValue(APP_ACTION::SEND_D0_CALC));
|
|
formatedString.clear();
|
|
|
|
// -> Msg-Box: "Parkdauer eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x37, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
}
|
|
|
|
break; // Ui::SCREEN_LICPLT
|
|
default:
|
|
// should not occur!
|
|
// => log and ignore:
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "AppControl::private_calculatedPrice() ERROR_TIMEOUT || ERROR_NETWORK || ERROR_BACKEND: invalid screen.";
|
|
qCritical() << " currentScreen = " << "0x" + QString(static_cast<quint8>(currentScreen)).toLatin1().toHex();
|
|
formatedString.clear(); // do not send formatedString
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
else {
|
|
// ------------------------------ *no* honest payment ------------------------------------
|
|
switch (currentScreen) {
|
|
case Ui::SCREEN_LICPLT:
|
|
// repeat endlessly
|
|
// until „Abort“ or match
|
|
|
|
// -> Msg-Box: "Kennzeichen XY wurde nicht gefunden, Bitte erneut eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x3A, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
formatedString.clear(); // do not send formatedString
|
|
hmi->onClearUserInputFields(); // clear input fields in hmi
|
|
|
|
break;
|
|
default:
|
|
// should not occur!
|
|
// => log and ignore:
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "AppControl::private_calculatedPrice() ERROR_TIMEOUT || ERROR_NETWORK || ERROR_BACKEND: invalid screen.";
|
|
qCritical() << " currentScreen = " << QString(static_cast<quint8>(currentScreen)).toLatin1().toHex();
|
|
formatedString.clear(); // do not send formatedString
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
break; // ERROR_TIMEOUT || ERROR_NETWORK || ERROR_BACKEND
|
|
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
// System Error
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "onCalculatedPrice(): ERROR_PROCESS: System error!";
|
|
switch (currentScreen) {
|
|
case Ui::SCREEN_LICPLT:
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON_FAILURE, 0x39); // System Error
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_RETRY:
|
|
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "onCalculatedPrice(): ERROR_RETRY:" << endl
|
|
<< " honest payment = " << config->useHonestPayment() << endl
|
|
<< " current screen = " << "0x" + QString(static_cast<quint8>(currentScreen)).toLatin1().toHex() << endl
|
|
<< " paymentTime = " << config->getPaymentPointInTime();
|
|
|
|
if (config->useHonestPayment()) {
|
|
// ------------------------------ honest payment ------------------------------------
|
|
|
|
|
|
switch (currentScreen) {
|
|
case Ui::SCREEN_LICPLT:
|
|
|
|
if (lpcount == 1) { // -> re-enter lp
|
|
// -> Msg-Box: "Kennzeichen erneut eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x35);
|
|
}
|
|
else {
|
|
|
|
switch (config->getPaymentPointInTime()) {
|
|
case PAYMENT_POINTINTIME::PAY_ON_ARRIVAL:
|
|
case PAYMENT_POINTINTIME::PAY_ON_EXIT:
|
|
// cause honest payment
|
|
// => #CALC empty price
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(accessInformation).append('#');
|
|
formatedString.append(accessInformationTypeField).append('#');
|
|
formatedString.append(amountDuePeriodStart).append('#');
|
|
formatedString.append(amountDuePeriodEnd).append('#');
|
|
formatedString.append("").append('#'); // empty price
|
|
formatedString.append("").append('#'); // empty price
|
|
formatedString.append("").append('#'); // <- grace period, - deprecated
|
|
|
|
// ... and set HMI-Data (price is still not valid)
|
|
this->hmi->onDisplayData(0x48, accessInformation);
|
|
|
|
// setup HMI screen DateTime --------------------------
|
|
hmi->setupDateTimeInput(referenceDateTime,
|
|
Ui::DateTimeInputMode::Down,
|
|
referenceDateTime,
|
|
referenceDateTime.addDays(-10));
|
|
|
|
// prepare "D0_CALC"-string to send to VMC
|
|
vendingData->setParameter("D0_CALC", QVariant(formatedString));
|
|
|
|
// Trigger VMC on CloseButton sent from message box
|
|
vendingData->setParameter("CloseAction", QVariant::fromValue(APP_ACTION::SEND_D0_CALC));
|
|
|
|
// -> Msg-Box: "Parkdauer eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x37, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
|
|
break;
|
|
|
|
case PAYMENT_POINTINTIME::IGNORE:
|
|
// Calculate price without match
|
|
// => #CALC with price to VMC
|
|
#if defined (USE_CALCULATEPRICE_PLUGIN)
|
|
this->calcPriceBackend->requestCalculatePrice(
|
|
this->vendingData->getParameter("LICENSEPLATE").toString(),
|
|
"LICENSEPLATE",
|
|
this->vendingData->getParameter("PermitType").toString(),
|
|
"60"); // default parking time: 60min
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
formatedString.clear(); // do not send formatedString
|
|
vendingData->setParameter("LPCOUNT", QVariant(0));
|
|
|
|
}
|
|
|
|
break; // Ui::SCREEN_LICPLT
|
|
default:
|
|
// should not occur!
|
|
// => log and ignore:
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "AppControl::private_calculatedPrice() ERROR_RETRY: invalid screen.";
|
|
qCritical() << " currentScreen = " << "0x" + QString(static_cast<quint8>(currentScreen)).toLatin1().toHex();
|
|
formatedString.clear(); // do not send formatedString
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
else {
|
|
// ------------------------------ *no* honest payment ------------------------------------
|
|
switch (currentScreen) {
|
|
case Ui::SCREEN_LICPLT:
|
|
// repeat endlessly
|
|
// until „Abort“ or match
|
|
|
|
// -> Msg-Box: "Kennzeichen XY wurde nicht gefunden, Bitte erneut eingeben":
|
|
hmi->onShowMessageBox(MessageBoxType::NOBUTTON, 0x3A, QStringList() << this->vendingData->getParameter("LICENSEPLATE").toString());
|
|
formatedString.clear(); // do not send formatedString
|
|
hmi->onClearUserInputFields(); // clear input fields in hmi
|
|
|
|
break;
|
|
default:
|
|
// should not occur!
|
|
// => log and ignore:
|
|
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate)
|
|
<< "AppControl::private_calculatedPrice() ERROR_RETRY: invalid screen.";
|
|
qCritical() << " currentScreen = " << QString(static_cast<quint8>(currentScreen)).toLatin1().toHex();
|
|
formatedString.clear(); // do not send formatedString
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::INFO:
|
|
break;
|
|
}
|
|
|
|
// send formatedString (aka "#CALC#.." to VMC only if size > 0;
|
|
return formatedString;
|
|
}
|
|
// END: ParkAndControl
|
|
|
|
#else
|
|
|
|
// dummy for all other projects
|
|
QString AppControl::private_calculatedPrice(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & accessInformation,
|
|
const QString & accessInformationType,
|
|
const QString & amountDuePeriodStart,
|
|
const QString & amountDuePeriodEnd,
|
|
const PriceInfo & priceInfo,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
Q_UNUSED(resultState)
|
|
Q_UNUSED(accessInformation)
|
|
Q_UNUSED(accessInformationType)
|
|
Q_UNUSED(amountDuePeriodStart)
|
|
Q_UNUSED(amountDuePeriodEnd)
|
|
Q_UNUSED(priceInfo)
|
|
Q_UNUSED(errorCode)
|
|
Q_UNUSED(errorDescription)
|
|
qCritical() << "AppControl::private_calculatedPrice() dummy method called";
|
|
|
|
return "";
|
|
}
|
|
|
|
#endif
|
|
|
|
void AppControl::onProcessTransaction(nsCalculatePriceInterface::RESULT_STATE resultState,
|
|
const QString & errorCode,
|
|
const QString & errorDescription)
|
|
{
|
|
QString resultMessage;
|
|
|
|
switch(resultState) {
|
|
case nsCalculatePriceInterface::RESULT_STATE::SUCCESS:
|
|
resultMessage = "Transaction success";
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_BACKEND:
|
|
resultMessage = "Transaction error: BACKEND\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode);
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_NETWORK:
|
|
resultMessage = "Transaction error: NETWORK\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode);
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_TIMEOUT:
|
|
resultMessage = "Transaction error: TIMEOUT\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode);
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
case nsCalculatePriceInterface::RESULT_STATE::ERROR_PROCESS:
|
|
resultMessage = "Transaction error: PROCESS\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode);
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
default:
|
|
resultMessage = "Transaction error: Unknown Error\n";
|
|
resultMessage.append(" errorCode: ").append(errorCode);
|
|
resultMessage.append(" errorDescription: ").append(errorDescription);
|
|
break;
|
|
}
|
|
|
|
qCritical() << resultMessage;
|
|
}
|
|
|
|
#endif // USE_CALCULATEPRICE_PLUGIN
|
|
|
|
|
|
void AppControl::onWakeUp()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************************
|
|
* LED configurations
|
|
*
|
|
* default: one LED, green, slow flash
|
|
* ooo: one LED, red, slow flash
|
|
*/
|
|
void AppControl::LEDs_default()
|
|
{
|
|
system->onConfigLED(ATB_system::ATB_LED1, ATB_system::LED_TRIGGER_TIMER, 200, 2000);
|
|
system->onConfigLED(ATB_system::ATB_LED2, ATB_system::LED_TRIGGER_NONE);
|
|
system->onConfigLED(ATB_system::ATB_LED3, ATB_system::LED_TRIGGER_NONE);
|
|
system->onConfigLED(ATB_system::ATB_LED4, ATB_system::LED_TRIGGER_NONE);
|
|
}
|
|
void AppControl::LEDs_ooo()
|
|
{
|
|
system->onConfigLED(ATB_system::ATB_LED1, ATB_system::LED_TRIGGER_NONE);
|
|
system->onConfigLED(ATB_system::ATB_LED2, ATB_system::LED_TRIGGER_NONE);
|
|
system->onConfigLED(ATB_system::ATB_LED3, ATB_system::LED_TRIGGER_NONE);
|
|
system->onConfigLED(ATB_system::ATB_LED4, ATB_system::LED_TRIGGER_TIMER, 500, 1000);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
* timer timeout slots
|
|
*
|
|
*/
|
|
void AppControl::onSellModeTimerTimeout()
|
|
{
|
|
this->vmc->SendSystemMessageTimeout();
|
|
this->requestProgramMode(PROGRAM_MODE::IDLE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
* Signal System Errors
|
|
*
|
|
* System errors are errors that do not allow further execution of the program.
|
|
*/
|
|
void AppControl::onSignalSystemErrors(const QString & errorCode, const QString & errorDescription)
|
|
{
|
|
// TODO:
|
|
// -> send monitoring message
|
|
// -> go to ModeOOO
|
|
// ...
|
|
Q_UNUSED(errorCode);
|
|
Q_UNUSED(errorDescription);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* action handling
|
|
*/
|
|
quint8 AppControl::startAction(APP_ACTION action)
|
|
{
|
|
switch (action) {
|
|
case APP_ACTION::DEFAULT_ACTION:
|
|
qDebug() << "----> startAction: APP_ACTION::DEFAULT_ACTION";
|
|
break;
|
|
case APP_ACTION::LICENSEPLATE_INPUT:
|
|
qDebug() << "----> startAction: APP_ACTION::LICENSEPLATE_INPUT";
|
|
break;
|
|
case APP_ACTION::PARKINGTIME_INPUT:
|
|
qDebug() << "----> startAction: APP_ACTION::PARKINGTIME_INPUT";
|
|
break;
|
|
case APP_ACTION::CARD_PAYMENT:
|
|
qDebug() << "----> startAction: APP_ACTION::CARD_PAYMENT";
|
|
break;
|
|
case APP_ACTION::CHOOSE_PAYEMENT:
|
|
qDebug() << "----> startAction: APP_ACTION::CHOOSE_PAYEMENT";
|
|
break;
|
|
case APP_ACTION::COIN_PAYMENT_PAYUP:
|
|
qDebug() << "----> startAction: APP_ACTION::COIN_PAYMENT_PAYUP";
|
|
break;
|
|
case APP_ACTION::COIN_PAYMENT_PAYDOWN:
|
|
qDebug() << "----> startAction: APP_ACTION::COIN_PAYMENT_PAYDOWN";
|
|
break;
|
|
case APP_ACTION::SEND_D0_CALC:
|
|
qDebug() << "----> startAction: APP_ACTION::SEND_D0_CALC";
|
|
|
|
if (vendingData->hasParameter("D0_CALC")) {
|
|
|
|
// DEBUG
|
|
qCritical() << "startAction() APP_ACTION::SEND_D0_CALC: formatedString: " << vendingData->getParameter("D0_CALC").toString();
|
|
|
|
this->vmc->SendFormatedString(vendingData->getParameter("D0_CALC").toString());
|
|
}
|
|
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* MOUSE handling
|
|
*/
|
|
|
|
#if defined (ARCH_PTU4)
|
|
/*****************************************************************************
|
|
* private USB Input Device handling methods
|
|
*
|
|
* This slot is called if something in the directory '/dev/input/' has changed (e.g.
|
|
* if a USB-mouse is plugged in/out or if a
|
|
* "hub 1-0:1.0: port 2 disabled by hub (EMI?), re-enabling..." occurs and re-inits
|
|
* the linux input devices.
|
|
*/
|
|
// Slot to receive a removed or added input device
|
|
void AppControl::onInputDeviceWatcher_directoryChanged(const QString& path)
|
|
{
|
|
Q_UNUSED(path)
|
|
|
|
QString mouseDeviceFile = system->getEventDeviceName(ATB_system::EVENT_DEVICE_USBMOUSE);
|
|
QString touchDeviceFile = system->getEventDeviceName(ATB_system::EVENT_DEVICE_TOUCHSCREEN);
|
|
|
|
qCritical() << "AppControl::onInputDeviceWatcher_directoryChanged() mouseDeviceFile: " << mouseDeviceFile;
|
|
|
|
if (!mousePresent && mouseDeviceFile.contains("mouse")) {
|
|
// mouse is now present:
|
|
setMouse(mouseDeviceFile, touchDeviceFile);
|
|
} else if (mousePresent && !mouseDeviceFile.contains("mouse")) {
|
|
// mouse is not present anymore:
|
|
closeMouse(mouseDeviceFile, touchDeviceFile);
|
|
} else if (!mousePresent) {
|
|
// mouse is not present (e.g. on startup, without mouse)
|
|
QWSServer::setCursorVisible( false );
|
|
}
|
|
|
|
// reinit USB-HID (qrcode scanner / RFID-reader)
|
|
#ifdef USE_BARCODESCANNER
|
|
// reinit barcode scanner
|
|
if (config->getUseBarcodeScanner()) {
|
|
this->barcodeScanner->reopen(this->config->getBarcodeScannerInputDevice());
|
|
}
|
|
#endif
|
|
#ifdef USE_RFIDREADER
|
|
// reinit rfid reader
|
|
if (config->getUseRFIDReader()) {
|
|
this->rfidReader->reopen(this->config->getRFIDReaderInputDevice());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void AppControl::setMouse(const QString & mouseDeviceFile, const QString &touchDeviceFile)
|
|
{
|
|
Q_UNUSED(touchDeviceFile)
|
|
|
|
QWSMouseHandler *pMouseHandler = QMouseDriverFactory::create("IntelliMouse", mouseDeviceFile);
|
|
QWSServer* pQwsServer = QWSServer::instance();
|
|
pQwsServer->setMouseHandler(pMouseHandler);
|
|
QWSServer::setCursorVisible( true );
|
|
mousePresent = true;
|
|
|
|
// DEBUG
|
|
qCritical() << "setMouse(): using device: " << mouseDeviceFile;
|
|
}
|
|
|
|
void AppControl::closeMouse(const QString & mouseDeviceFile, const QString &touchDeviceFile)
|
|
{
|
|
// TODO: only openMouse(), if a touchscreen is available; hide mouse pointer in this case
|
|
|
|
// test: setDefaultMouse()
|
|
//
|
|
|
|
|
|
QWSServer* pQwsServer = QWSServer::instance();
|
|
|
|
// DEBUG
|
|
qCritical() << "closeMouse(): touch device: " << touchDeviceFile;
|
|
|
|
if (touchDeviceFile.contains("event")) {
|
|
// touch device is available:
|
|
|
|
// open mouse device specified by QWS_MOUSE_PROTO -> this is normally the touchscreen...
|
|
pQwsServer->openMouse();
|
|
}
|
|
else {
|
|
// touch device is not available:
|
|
|
|
pQwsServer->closeMouse();
|
|
// -> close all pointer devices (defined by QWS_MOUSE_PROTO)
|
|
}
|
|
|
|
|
|
|
|
//pQwsServer->closeMouse(); -> close all pointer devices (also defined by QWS_MOUSE_PROTO => also the touch screen!!!)
|
|
QWSServer::setCursorVisible( false );
|
|
mousePresent = false;
|
|
|
|
|
|
// DEBUG
|
|
qCritical() << "closeMouse(): device: " << mouseDeviceFile;
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (ARCH_DesktopLinux)
|
|
/*******************************************************************************
|
|
* Screenshot
|
|
*/
|
|
void AppControl::private_screenshot()
|
|
{
|
|
QString filename = QDir::homePath() + "/tmp/ATBQT_screenshot_0x"
|
|
+ QString(static_cast<quint8>(this->hmi->getCurrentScreen())).toLatin1().toHex()
|
|
+ ".png";
|
|
|
|
qDebug() << "HMI::private_screenshot(): save screenshot to: " << filename;
|
|
|
|
QWidget *w = QApplication::activeWindow();
|
|
if(w) {
|
|
QPixmap p = QPixmap::grabWidget(w);
|
|
p.save(QString(filename));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/**************************************************************************
|
|
* helpers:
|
|
* - operators
|
|
* - ...
|
|
*/
|
|
QDebug operator<<(QDebug debug, PROGRAM_MODE mode) {
|
|
switch (mode) {
|
|
case PROGRAM_MODE::IDLE:
|
|
debug << "PROGRAM_MODE::IDLE";
|
|
break;
|
|
case PROGRAM_MODE::SELL_ENABLE:
|
|
debug << "PROGRAM_MODE::SELL_ENABLE";
|
|
break;
|
|
case PROGRAM_MODE::SELL:
|
|
debug << "PROGRAM_MODE::SELL";
|
|
break;
|
|
case PROGRAM_MODE::SERVICE:
|
|
debug << "PROGRAM_MODE::SERVICE";
|
|
break;
|
|
case PROGRAM_MODE::OOO:
|
|
debug << "PROGRAM_MODE::OOO";
|
|
break;
|
|
}
|
|
return debug;
|
|
}
|
|
|
|
QDebug operator<<(QDebug debug, APP_ACTION action) {
|
|
switch (action) {
|
|
case APP_ACTION::DEFAULT_ACTION:
|
|
debug << "APP_ACTION::DEFAULT_ACTION";
|
|
break;
|
|
case APP_ACTION::LICENSEPLATE_INPUT:
|
|
debug << "APP_ACTION::LICENSEPLATE_INPUT";
|
|
break;
|
|
case APP_ACTION::PARKINGTIME_INPUT:
|
|
debug << "APP_ACTION::PARKINGTIME_INPUT";
|
|
break;
|
|
case APP_ACTION::CARD_PAYMENT:
|
|
debug << "APP_ACTION::CARD_PAYMENT";
|
|
break;
|
|
case APP_ACTION::CHOOSE_PAYEMENT:
|
|
debug << "APP_ACTION::CHOOSE_PAYEMENT";
|
|
break;
|
|
case APP_ACTION::COIN_PAYMENT_PAYUP:
|
|
debug << "APP_ACTION::COIN_PAYMENT_PAYUP";
|
|
break;
|
|
case APP_ACTION::COIN_PAYMENT_PAYDOWN:
|
|
debug << "APP_ACTION::COIN_PAYMENT_PAYDOWN";
|
|
break;
|
|
case APP_ACTION::SEND_D0_CALC:
|
|
debug << "APP_ACTION::SEND_D0_CALC";
|
|
break;
|
|
}
|
|
return debug;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* customer specific things
|
|
*/
|
|
#if defined (CUST00318)
|
|
/*****************************************************************************
|
|
* hack for 00318/Nexobility
|
|
*/
|
|
void AppControl::private_CUST00318_handle_CC_ERROR_0x13()
|
|
{
|
|
qCritical() << "CUST00318_handle_CC_ERROR_0x13";
|
|
|
|
|
|
QString formatedString;
|
|
|
|
vendingData->setParameter("CC_ERROR_0x13", QVariant(1));
|
|
|
|
formatedString.append("#CALC#");
|
|
formatedString.append(this->vendingData->getParameter("LICENSEPLATE").toString()).append('#');
|
|
formatedString.append("1").append('#');
|
|
formatedString.append("2021-08-17T16:00:00").append('#');
|
|
formatedString.append("2021-08-17T17:00:00").append('#');
|
|
formatedString.append("0").append('#');
|
|
formatedString.append("0").append('#');
|
|
formatedString.append("0").append('#');
|
|
|
|
vmc->SendFormatedString(formatedString);
|
|
}
|
|
|
|
#endif
|
|
|