Compare commits

...

71 Commits

Author SHA1 Message Date
2452499073 Diag: call diagRequest() on wokeup from rtc 2025-09-03 13:42:30 +02:00
5c40e088aa Diag: restart carun is M0255 (was W255) 2025-07-29 15:46:26 +02:00
577411289e Trigger diagRequest() on MODE SERVICE => MODE OOO 2025-07-23 09:29:16 +02:00
cc27b982ff Add/Track: currentProgramMode 2025-07-23 09:28:53 +02:00
a87a4e6c14 Merge branch 'improveDeviceControllerDiag' into pu/integration 2025-06-25 10:38:31 +02:00
0467db23d1 Merge branch 'ImproveE255Handling' into improveDeviceControllerDiag 2025-06-25 10:36:19 +02:00
e1470d13f1 Diag: clear machine machineEventSet on valid data
This is allowed only here: dc-data is valid (i.e. check for E255 was
sucessfull).
This method sub_componentAssessment() will check all criteria of
dc-module conditions.
2025-06-25 10:29:58 +02:00
1165c4b92f Diag: set W255 only once 2025-06-24 15:03:21 +02:00
40acd0e0c4 Diag: set E255 only once 2025-06-24 14:25:52 +02:00
fe3696ce9c Diag: E255
- handle E255 in previousMachineEventSet (because machineEventSet will
   be cleared regularely)
 - do not call finishDiag() on E255 because this will interscect
   previous- with current machineEventSet and thus remove all Errors/
   Warnings because machineEventSet was cleared and includes only E255!
2025-06-24 14:18:35 +02:00
cc6dfee0e2 Diag: set E255 only once 2025-06-12 16:33:32 +02:00
91d8eb03b3 Diag: clear machineEventSet on diagRequest 2025-06-12 10:50:29 +02:00
3bef73ce4b Diag: remove E255 / W255 on valid data 2025-06-12 10:37:26 +02:00
8d03926de4 Diag: do no clear machineEventSet on diagRequest 2025-06-12 10:24:25 +02:00
b34716ef93 Minor: order debug output 2025-06-12 08:40:59 +02:00
f75f2c57df Diag: E255 / W255 / M0254 -> set, send and finish diag
This states are rather meta infos about dc condition. Therefore the
where created and sent outside of superviseSystem()-method.
This commit should ensure that:
 - this states are sent to ISMAS
 - this states are inserted in machineEventSet in order to enable
   a reset in next diagRun
2025-06-12 08:35:58 +02:00
18a35acf20 Diag: add single exit method for ReqDiag 2025-06-12 08:35:00 +02:00
ccc2b8120d Diag: new constructor for DCMachineEvent 2025-06-12 08:33:28 +02:00
ccc1c6033f Diag: Send operate O000 as last event (after set/reset events) 2025-06-11 14:13:09 +02:00
c23364874e Diag: machineEventSet:
- do not overwrite previous events, only insert new events (unite)
 - remove all events not in machineEventSet
2025-06-11 12:35:27 +02:00
1e5020132f Diag: DEBUG EventSets 2025-06-11 09:58:31 +02:00
6bd02f1831 Diag: care about EventSet.clear() (-> TEST / TODO) 2025-06-11 09:58:31 +02:00
923bff1117 Diag: Operate O000 is not part of machineEventSet
- O000 is not a direct result from DC
 - O000 is constructed in DCDiag, if no Error EXXXX and no Warning WXXXX
   ocurred
 -> O000 must not be part of machineEventSet (e.g. O000 can not be
    reset)
2025-06-11 09:58:31 +02:00
12be31ee49 Diag: getCurrentMachineState: return previousState ...
... if diag is running.
This method is currently not used, but maybe in future it could be
usefull to read current state.
2025-06-11 09:58:31 +02:00
f8757b352d Diag: clear machineEventSet on the begin of DCDiag ...
... not on end.
This is to keep current machineEventSet during normal IDLE process.
2025-06-11 09:58:25 +02:00
4567aed6d1 Introduce DCMachineEvent ...
... this is an DC-Plugin internal data-structure which can be
transformed to an ATBMachineEvent and sent to ISMAS.

DCMachineEvent is in fact a couple ot DeviceController::State and a
QString eventID.

Thi eventID is necessary to send a state-reset to ISMAS. ISMAS needs
same enventID for set- and reset Events.
2025-06-11 09:55:25 +02:00
4df3a83126 Debug diag: print machineEventSet 2025-06-11 09:43:53 +02:00
5c66abfd87 Improve E255 handling:
- start BackgroundTask on first data not valid
 - in any case of E255/data-no-valid: try to restart diag;
   This is because there were only 'returns' without initiating
   something, so that next check/restart carun happened first on next
   wokeup.
2025-05-28 13:57:48 +02:00
efe56672ff DCDiag: add dbus interface 2025-05-27 12:59:12 +02:00
58c99753a9 PrintTicket: Support FIXED_PRICE Tickets 2025-05-16 08:48:58 +02:00
e703befb2f Merge branch 'improveTicketPrint' into pu/integration 2025-05-13 13:46:48 +02:00
83bcdcb47e Print: improve printing receipt:
- call prn_cut() 200ms after prn_switchPower(true)
 - make an "emergency cut" on error
 - improve log output on error
2025-05-13 13:44:12 +02:00
70e6ec293d Merge branch 'improveDeviceControllerDiag' into pu/integration 2025-05-08 10:12:54 +02:00
3601f2d868 Merge branch 'improveTICKET_VARIANTS' into pu/integration 2025-05-08 10:12:46 +02:00
0876fa229e Diag: do not send reset errors/warnings ...
... this is a proposal for future.
2025-05-08 10:11:19 +02:00
1c13d92171 New proposal for DeviceControllerDiag:
Manage two sets of errors and compare to previous run.
2025-04-14 08:18:11 +02:00
10b0e494b2 requestPrintTicket: switch to legacy, if no template list is configured 2025-04-08 08:58:29 +02:00
24a1390a11 Interface: add TICKET_VARIANTS for FIXED_PRICE_TICKETS 2025-04-07 14:30:27 +02:00
c8508a0c62 Read config TICKET_TEMPLATES: read list- or string-value 2025-03-25 12:26:18 +01:00
fbfbe3d243 prepareDynTemplateData: setup for all TICKET_VARIANTs 2025-03-12 16:12:44 +01:00
cbc0dd0ad6 Ticket: Use printer templates from config 2025-03-12 15:56:51 +01:00
1abd6bfa90 default templateList is empty 2025-03-12 14:25:33 +01:00
a03dfe87a5 requestPrintTicket: improve debug output: print template list 2025-03-12 14:07:23 +01:00
03b192fb60 Read ticket templates from config:
- config group is [TICKET_TEMPLATES]
 - reads list of printer templates for each TICKET_VARIANT
2025-03-12 13:57:36 +01:00
e8b3bb1aa0 Interface: 1.2.1 (add additional TICKET_VARIANTs) 2025-03-12 13:55:14 +01:00
8fe705f49b DCState: send EVENT_CLASS::STATE as eventName "Mxxxx" 2024-11-20 15:42:29 +01:00
bf1bdc34bb Fix: onNewVoltage: Unit is "mV" 2024-11-20 14:04:35 +01:00
73ae01573d cashInputFinished: set errorCode/-description 2024-10-10 15:20:49 +02:00
bc595e1c7e Printing: set "productText" to dynTicketData.dynDat5 2024-10-08 16:49:59 +02:00
18104b7271 Start dc_autoRequest() on wokeup 2024-09-25 12:33:52 +02:00
d720c7190f Merge branch 'PayUpWithChanger' into pu/integration 2024-09-16 15:09:44 +02:00
3fff6a0ebe PayUp: CashCollect(amount) 2024-09-16 15:09:04 +02:00
bacee366b8 DeviceControllerInterface 1.2.0 2024-09-13 14:54:48 +02:00
acf3e143c1 Fix: debug ouput 2024-08-21 18:15:50 +02:00
c84050091b Fix: TICKET_ID for FINE_PAYMENT 2024-08-09 14:08:53 +02:00
9be2841187 Init DC structs 2024-08-09 08:06:14 +02:00
3e4db6cfcc Add test code for printing date-strings 2024-08-08 10:21:55 +02:00
5898be8807 TicketUtils: fix date format string 2024-08-08 10:17:11 +02:00
f20957c14a Use TicketUtils to format date string on ticket 2024-08-08 10:12:35 +02:00
1bcdb5ba21 Add TicketUtils class for ...
Ticket helper methods e.g. string format helpers.
Currently only on method for getting a date string in short format
according to selected language.
2024-08-08 10:10:27 +02:00
a43af8ab86 Print ticket-number on ticket 2024-08-07 15:29:12 +02:00
d7443974e2 requestPrintTicket() add new product names 2024-07-23 14:36:45 +02:00
346c953175 Print ticket FREE_TICKET 2024-07-23 11:01:13 +02:00
8cf6897a21 FREE_TICKET defaults to templates 24, 25, 26 2024-07-23 11:00:03 +02:00
69eb87e358 DeviceController Interface 1.1.6 (Ticket Variant FREE_TICKET) 2024-07-23 10:58:56 +02:00
8eab11479c Merge branch 'pu/klaipeda' into pu/integration 2024-07-15 15:30:54 +02:00
2d60a7bd5c Send W255 on restart CArun 2024-07-15 10:08:56 +02:00
6d7d9ade70 Restart carun on consecutive E255 2024-07-15 10:03:41 +02:00
72dbc8b858 Print receipt: encode QString 2024-06-27 11:55:35 +02:00
32d70abf44 Proposal for usage of TICKET_VARIANT::FINE_PAYMENT 2024-06-27 11:48:16 +02:00
c076090e03 DeviceController Interface 1.1.5 (Ticket Variant FINE_PAYMENT) 2024-06-27 11:46:40 +02:00
9 changed files with 940 additions and 133 deletions

View File

@@ -88,7 +88,8 @@ HEADERS += \
src/ATBAPP/support/JSON.h \
src/ATBAPP/support/PTUSystem.h \
src/ATBAPP/support/PersistentData.h \
src/ATBAPP/support/Ticket.h
src/ATBAPP/support/Ticket.h \
src/ATBAPP/support/TicketUtils.h
SOURCES += \
src/ATBAPP/ATBHealthEvent.cpp \
@@ -101,7 +102,8 @@ SOURCES += \
src/ATBAPP/support/JSON.cpp \
src/ATBAPP/support/PTUSystem.cpp \
src/ATBAPP/support/PersistentData.cpp \
src/ATBAPP/support/Ticket.cpp
src/ATBAPP/support/Ticket.cpp \
src/ATBAPP/support/TicketUtils.cpp
DISTFILES += \
generate-version.sh

View File

@@ -6,6 +6,7 @@
#include "src/ATBAPP/support/DBusControllerInterface.h"
#include "src/ATBAPP/support/PTUSystem.h"
#include "src/ATBAPP/support/CashUtils.h"
#include "src/ATBAPP/support/TicketUtils.h"
#include <QTimer>
#include <QThread>
@@ -23,7 +24,8 @@
ATBDeviceControllerPlugin::ATBDeviceControllerPlugin(QObject *parent)
: isMaster(false)
: currentProgramMode(PROGRAM_MODE::INIT)
, isMaster(false)
, pluginState(PLUGIN_STATE::NOT_INITIALIZED)
, eventReceiver(nullptr)
{
@@ -44,6 +46,7 @@ PLUGIN_STATE ATBDeviceControllerPlugin::initDCPlugin(QObject *eventReceiver, con
QString printerLocaleString = settings.value("ATBDeviceControllerPlugin/printerLocale", "de_DE").toString().toLatin1();
this->printerLocale = QLocale(printerLocaleString);
this->initTicketTemplateList(&settings);
this->init_sc_dbus();
@@ -131,7 +134,7 @@ PLUGIN_STATE ATBDeviceControllerPlugin::initDCPlugin(QObject *eventReceiver, con
qCritical() << "ATBDeviceControllerPlugin: Set printer encoding to " << printerEncoding;
}
this->diag->init(this->hw, this->eventReceiver);
this->diag->init(this->hw, this->dbus, this->eventReceiver);
this->pluginState = PLUGIN_STATE::INITIALIZED;
@@ -139,6 +142,58 @@ PLUGIN_STATE ATBDeviceControllerPlugin::initDCPlugin(QObject *eventReceiver, con
}
void ATBDeviceControllerPlugin::initTicketTemplateList(const QSettings * settings)
{
QList<quint8> templateList;
QString templateListString;
QMetaEnum metaTicketVariants = QMetaEnum::fromType<nsDeviceControllerInterface::TICKET_VARIANT>();
for (int i = 0; i < metaTicketVariants.keyCount(); i++) {
const char* ticketVariant_char = metaTicketVariants.key(i);
quint8 intValue = metaTicketVariants.value(i);
// DEBUG
//qCritical() << " processing TICKET_VARIANT::" << ticketVariant_char;
QString configKey = QString("TICKET_TEMPLATES/") + ticketVariant_char;
QVariant raw_templateList = settings->value(configKey, "");
if (raw_templateList.type() == QVariant::StringList) {
templateListString = raw_templateList.toStringList().join(",");
} else {
templateListString = raw_templateList.toString();
}
// DEBUG
//qCritical() << " configKey: " << configKey;
//qCritical() << " templateListString: " << templateListString;
QStringList templateListStringList = templateListString.split(",", QString::SplitBehavior::SkipEmptyParts);
quint8 templateEntry;
bool ok;
for (const auto & ListEntry : templateListStringList) {
templateEntry = ListEntry.toInt(&ok);
if (ok) {
templateList.append(templateEntry);
}
}
// DEBUG
/*
QStringList elements;
for (const auto &item : templateList) {
elements << QString::number(item);
}
qCritical() << " template list: " << elements.join(',');
*/
this->ticketTemplateList.insert(static_cast<nsDeviceControllerInterface::TICKET_VARIANT>(intValue), templateList);
templateList.clear();
}
}
void ATBDeviceControllerPlugin::sendDeviceParameter(const QJsonObject &jsonObject)
{
@@ -236,12 +291,14 @@ void ATBDeviceControllerPlugin::onChangedProgramModeToSELL()
hw->dc_autoRequest(true);
hw->rtc_setDateTime();
hw->mdb_switchWake(0); // wakeup MDB components
this->currentProgramMode = PROGRAM_MODE::SELL;
}
void ATBDeviceControllerPlugin::onChangedProgramModeToSERVICE()
{
hw->dc_autoRequest(true);
hw->mdb_switchWake(0); // wakeup MDB components
this->currentProgramMode = PROGRAM_MODE::SERVICE;
}
void ATBDeviceControllerPlugin::onChangedProgramModeToIDLE()
@@ -249,12 +306,19 @@ void ATBDeviceControllerPlugin::onChangedProgramModeToIDLE()
hw->dc_autoRequest(true);
this->diag->diagRequest();
hw->mdb_switchWake(1);
this->currentProgramMode = PROGRAM_MODE::IDLE;
}
void ATBDeviceControllerPlugin::onChangedProgramModeToOOO()
{
// trigger diagRequest on SERVICE -> IDLE
if (this->currentProgramMode == PROGRAM_MODE::SERVICE) {
hw->dc_autoRequest(true);
this->diag->diagRequest();
hw->mdb_switchWake(1);
}
this->currentProgramMode = PROGRAM_MODE::OOO;
}
@@ -310,6 +374,73 @@ void ATBDeviceControllerPlugin::cashCollect()
}
}
void ATBDeviceControllerPlugin::cashCollect(const QString & amount)
{
if (this->coinProcessor() != nsDeviceControllerInterface::COIN_PROCESSOR::CHANGER) {
this->cashCollect();
return;
}
// check if we must change coins:
// inserted amount
uint32_t amountInsertedInt = this->hw->getInsertedAmount();
bool ok;
uint32_t amountToPayInt = amount.toInt(&ok);
// check if we must change coins:
if (amountInsertedInt > amountToPayInt) {
uint32_t amountToChangeInt = amountInsertedInt - amountToPayInt;
qCritical() << "cashCollect(" << amount << ")";
qCritical() << " amount to change: " << QString::number(amountToChangeInt);
// trigger changer:
emit this->cashPaymentChanging(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
QString::number(amountToChangeInt),
"", // ErrorCode
""); // ErrorDescription
// change
hw->changer_returnCoins(amountToChangeInt);
QTimer::singleShot(1000, this, &ATBDeviceControllerPlugin::onCashChangerState);
}
else {
// nothing to change:
qCritical() << "cashCollect(" << amount << ")";
qCritical() << " nothing to change. ";
hw->vend_success();
QString amountString = QString::number(amountInsertedInt);
// inserted coins
uint32_t amountCoinsInt = CashUtils::getAmountOfInsertedCoins(this->hw);
QString amountCoinsString = QString::number(amountCoinsInt);
// inserted notes
uint32_t amountNotesInt = CashUtils::getAmountOfInsertedNotes(this->hw);
QString amountNotesString = QString::number(amountNotesInt);
emit this->cashPaymentFinished(nsDeviceControllerInterface::RESULT_STATE::SUCCESS,
amountString,
amountCoinsString, // coins
amountNotesString, // notes
0, // proposed change
"",
"");
this->currentCashState = CASH_STATE::CACHE_EMPTY;
}
}
void ATBDeviceControllerPlugin::cashAbort()
{
hw->vend_failed();
@@ -542,8 +673,6 @@ void ATBDeviceControllerPlugin::onCBinAndAllDoorsClosed()
{
qCritical() << "ATBDeviceControllerPlugin::onCBinAndAllDoorsClosed()";
this->diag->diagReInit();
QTimer::singleShot(2000, this, SIGNAL(requestModeIDLE()));
this->dbus->finishedBackgroundTask("DOOR_OPEN");
@@ -579,7 +708,7 @@ void ATBDeviceControllerPlugin::onNewVoltage(uint32_t voltage)
json = JSON::objectBuilder()
->set("Name", "batt")
->set("Value", voltageString)
->set("Unit", "V")
->set("Unit", "mV")
->create();
@@ -610,17 +739,32 @@ void ATBDeviceControllerPlugin::onNewVoltage(uint32_t voltage)
*/
void ATBDeviceControllerPlugin::requestPrintTicket(nsDeviceControllerInterface::TICKET_VARIANT ticketVariant, const QHash<QString, QVariant> & printingData)
{
QList<quint8> templateList;
// TODO: read template list from .ini
QList<quint8> templateList = this->ticketTemplateList[ticketVariant];
if (templateList.isEmpty()) {
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket()";
qCritical() << " TICKET_VARIANT: " << ticketVariant;
qCritical() << " -> templateList is empty!";
qCritical() << " -> switching to legacy interface";
this->requestPrintTicket(printingData);
return;
}
// DEBUG
qCritical() << "------------------------------------------------------------------------";
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket()";
qCritical() << " TICKET_VARIANT: " << ticketVariant;
if (ticketVariant == nsDeviceControllerInterface::TICKET_VARIANT::FOOD_STAMP) {
qCritical() << " dyn1_list: " << printingData["dyn1_list"].toStringList();
qCritical() << " dyn2_list: " << printingData["dyn2_list"].toStringList();
}
QStringList listElements;
for (const auto &item : templateList) {
listElements << QString::number(item);
}
qCritical() << " template list: " << listElements.join(',');
qCritical() << "------------------------------------------------------------------------";
@@ -654,12 +798,23 @@ void ATBDeviceControllerPlugin::requestPrintReceipt(const QHash<QString, QVarian
void ATBDeviceControllerPlugin::requestPrintReceipt(const QString & printingString)
{
QByteArray ba = printingString.toUtf8();
QByteArray ba_receipt = this->codec->fromUnicode(printingString);
//QByteArray ba = printingString.toUtf8();
hw->prn_switchPower(true);
hw->prn_setFonts(8,12,0,0);
hw->prn_sendText(&ba);
hw->prn_sendText(&ba_receipt);
// DEBUG
//qCritical() << "---------------------------------------------------------------";
//qCritical() << "ATBDeviceControllerPlugin::requestPrintReceipt()";
//qCritical() << " receipt data:";
//qCritical() << QString(ba_receipt);
//qCritical() << "---------------------------------------------------------------";
this->printResultCheckCounter = 0;
QTimer::singleShot(4000, this, SLOT(onPrinterWaitForPrintingReceipt()));
QTimer::singleShot(2000, this, SLOT(onPrinterWaitForPrintingReceipt()));
//QTimer::singleShot(2000, this, [this](){ hw->prn_cut(3); } );
}
@@ -680,7 +835,7 @@ void ATBDeviceControllerPlugin::onPrinterWaitForPrintingReceipt()
"",
"");
hw->prn_switchPower(true);
hw->prn_cut(3);
QTimer::singleShot(200, this, [this](){ hw->prn_cut(3); } );
break;
case 2: // printing finished, Error
qCritical() << "DC Error: wait for printing receipt";
@@ -690,15 +845,21 @@ void ATBDeviceControllerPlugin::onPrinterWaitForPrintingReceipt()
emit this->printReceiptFinished(nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND,
this->errorCode,
this->errorDescription);
hw->prn_switchPower(true);
QTimer::singleShot(200, this, [this](){ hw->prn_cut(3); } );
break;
default:
qCritical() << "DC Error: wait for printing receipt";
qCritical() << "DC Error: wait for printing receipt: printerResult = " << printerResult;
this->errorCode = "PRINTER"; // TODO: get more detailed error code from low level API
this->errorDescription = "Printer error"; // TODO: get more detailed error description from low level API
this->errorDescription = "Printer error(" + QString(printerResult) + ")";
emit this->printReceiptFinished(nsDeviceControllerInterface::RESULT_STATE::ERROR_BACKEND,
this->errorCode,
this->errorDescription);
// do an emergency cut
hw->prn_switchPower(true);
QTimer::singleShot(200, this, [this](){ hw->prn_cut(3); } );
break;
}
@@ -713,15 +874,31 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket( " << endl
<< " licenseplate = " << printingData["licenseplate"] << endl
<< " productText = " << printingData["productText"] << endl
<< " amount = " << printingData["amount"] << endl
<< " parkingEnd = " << printingData["parkingEnd"] << endl
<< " currentDateTime = " << printingData["currentDateTime"] << endl;
<< " currentDateTime = " << printingData["currentDateTime"] << endl
<< " ticketNumber = " << printingData["ticketNumber"] << endl;
QDateTime parkingEndDateTime = QDateTime::fromString(printingData["parkingEnd"].toString(), Qt::ISODate);
QDateTime parkingEndDateTime = QDateTime::fromString(printingData["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(printingData["currentDateTime"].toString(), Qt::ISODate);
QString parkingEndDateString = this->printerLocale.toString(parkingEndDateTime.date(), QLocale::ShortFormat);
QString currentDateString = this->printerLocale.toString(currentDateTime.date(), QLocale::ShortFormat);
QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QString currentDateString = TicketUtils::getLocaleDateString(this->printerLocale, currentDateTime.date());
/*******************************************************************************************
* TEST date formate strings:
QLocale ltLocale("lt_LT");
QLocale deLocale("de_DE");
QString ltShortDate = ltLocale.toString(currentDateTime.date(), QLocale::ShortFormat);
QString deShortDate = deLocale.toString(currentDateTime.date(), QLocale::ShortFormat);
qCritical() << "*********************************************************************";
qCritical() << " ltShortDate = " << ltShortDate;
qCritical() << " deShortDate = " << deShortDate;
qCritical() << "*********************************************************************";
*/
/* -----------------------------------------------------------------------------------------
* note: the following highly depends on printer template files!
@@ -747,6 +924,13 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
QByteArray ba_currentDate = codec->fromUnicode(currentDateString);
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
// Product-Text
QByteArray ba_productText = codec->fromUnicode(printingData["productText"].toString());
memcpy((char*)dynTicketData->dynDat5, ba_productText.data(), std::min(ba_productText.size(),8));
// Ticket-Number
QByteArray ba_ticketNumber = codec->fromUnicode(printingData["ticketNumber"].toString());
memcpy((char*)dynTicketData->dynDat7, ba_ticketNumber.data(), std::min(ba_ticketNumber.size(),8));
// DEBUG
/*
@@ -780,7 +964,8 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
<< " amount = " << printingData["amount"] << endl
<< " parkingEnd = " << printingData["parkingEnd"] << endl
<< " currentTime = " << printingData["currentTime"] << endl
<< " currentDate = " << printingData["currentDate"] << endl;
<< " currentDate = " << printingData["currentDate"] << endl
<< " ticketNumber = " << printingData["ticketNumber"] << endl;
this->onPrintFinishedERR();
@@ -801,19 +986,39 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
QString paymentType = printingData["paymentType"].toString(); // must be "CASH" | "CARD"
QString productName = printingData["product"].toString(); // must be "ShortTimeParking" | "DayTicket"
if ( (paymentType == "CASH") && (productName == "SHORT_TERM_PARKING") ) {
if ( (paymentType == "CASH") && ( (productName == "SHORT_TERM_PARKING") ||
(productName == "SHORT_TERM_PARKING_CAR") ||
(productName == "SHORT_TERM_PARKING_VAN") ||
(productName == "SHORT_TERM_PARKING_CAMPER")
))
{
this->currentSelectedTicketType = 1; // "Kombiticket #1"
}
else
if ( (paymentType == "CARD") && (productName == "SHORT_TERM_PARKING") ) {
if ( (paymentType == "CARD") && ( (productName == "SHORT_TERM_PARKING") ||
(productName == "SHORT_TERM_PARKING_CAR") ||
(productName == "SHORT_TERM_PARKING_VAN") ||
(productName == "SHORT_TERM_PARKING_CAMPER")
))
{
this->currentSelectedTicketType = 2; // "Kombiticket #2"
}
else
if ( (paymentType == "CASH") && (productName == "DAY_TICKET") ) {
if ( (paymentType == "CASH") && ( (productName == "DAY_TICKET") ||
(productName == "DAY_TICKET_CAR") ||
(productName == "DAY_TICKET_VAN") ||
(productName == "DAY_TICKET_CAMPER")
))
{
this->currentSelectedTicketType = 3; // "Kombiticket #3"
}
else
if ( (paymentType == "CARD") && (productName == "DAY_TICKET") ) {
if ( (paymentType == "CARD") && ( (productName == "DAY_TICKET") ||
(productName == "DAY_TICKET_CAR") ||
(productName == "DAY_TICKET_VAN") ||
(productName == "DAY_TICKET_CAMPER")
))
{
this->currentSelectedTicketType = 4; // "Kombiticket #4"
}
else
@@ -983,15 +1188,57 @@ void ATBDeviceControllerPlugin::prepareDynTemplateData()
case nsDeviceControllerInterface::TICKET_VARIANT::STOP_RECEIPT:
private_setupDynTemplatData_STOP_RECEIPT(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FINE_PAYMENT:
private_setupDynTemplatData_FINE_PAYMENT(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::RECEIPT:
private_setupDynTemplateData_DEFAULT(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::ERROR_RECEIPT:
private_setupDynTemplateData_DEFAULT(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::PARKING_TICKET:
private_setupDynTemplateData_DEFAULT(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FREE_TICKET:
private_setupDynTemplatData_FREE_TICKET(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FOOD_STAMP:
private_setupDynTemplatData_FOOD_STAMP(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_1:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_2:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_3:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_4:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_5:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_6:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_7:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_8:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_9:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FIXED_PRICE_10:
private_setupDynTemplateData_FIXED_PRICE(dynTicketData, this->currentTicket);
break;
default:
private_setupDynTemplateData_DEFAULT(dynTicketData, this->currentTicket);
break;
}
// C-Programmierung: wird hier nur 'licensePlate' gedruckt?
@@ -1014,9 +1261,8 @@ void ATBDeviceControllerPlugin::private_setupDynTemplateData_START_RECEIPT(struc
QDateTime parkingEndDateTime = QDateTime::fromString(ticket->getPrintingData()["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate);
QString parkingEndDateString = this->printerLocale.toString(parkingEndDateTime.date(), QLocale::ShortFormat);
QString currentDateString = this->printerLocale.toString(currentDateTime.date(), QLocale::ShortFormat);
QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QString currentDateString = TicketUtils::getLocaleDateString(this->printerLocale, currentDateTime.date());
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString());
@@ -1091,6 +1337,139 @@ void ATBDeviceControllerPlugin::private_setupDynTemplatData_FOOD_STAMP(struct T_
qCritical() << "-------------------------------------------------------";
}
void ATBDeviceControllerPlugin::private_setupDynTemplatData_FINE_PAYMENT(struct T_dynDat *dynTicketData, Ticket *ticket)
{
QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate);
QString currentDateString = this->printerLocale.toString(currentDateTime.date(), QLocale::ShortFormat);
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString());
memcpy((char*)dynTicketData->licensePlate, ba_licenseplate.data(), std::min(ba_licenseplate.size(),8));
QByteArray ba_amount = codec->fromUnicode(ticket->getPrintingData()["amount"].toString());
memcpy((char*)dynTicketData->vendingPrice, ba_amount.data(), std::min(ba_amount.size(),8)); // Szeged
memcpy((char*)dynTicketData->dynDat6, ba_amount.data(), std::min(ba_amount.size(),8)); // Schoenau
QByteArray ba_currentDate = codec->fromUnicode(currentDateString);
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
QByteArray ba_ticketId = codec->fromUnicode(ticket->getPrintingData()["ticketId"].toString());
memcpy((char*)dynTicketData->dynDat7, ba_ticketId.data(), std::min(ba_ticketId.size(),8));
}
void ATBDeviceControllerPlugin::private_setupDynTemplatData_FREE_TICKET(struct T_dynDat *dynTicketData, Ticket *ticket)
{
QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate);
QString currentDateString = this->printerLocale.toString(currentDateTime.date(), QLocale::ShortFormat);
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString());
memcpy((char*)dynTicketData->licensePlate, ba_licenseplate.data(), std::min(ba_licenseplate.size(),8));
QByteArray ba_amount = codec->fromUnicode(ticket->getPrintingData()["amount"].toString());
memcpy((char*)dynTicketData->vendingPrice, ba_amount.data(), std::min(ba_amount.size(),8)); // Szeged
memcpy((char*)dynTicketData->dynDat6, ba_amount.data(), std::min(ba_amount.size(),8)); // Schoenau
QByteArray ba_currentDate = codec->fromUnicode(currentDateString);
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
// FREE_TICKET needs parking endtime:
QDateTime parkingEndDateTime = QDateTime::fromString(ticket->getPrintingData()["parkingEnd"].toString(), Qt::ISODate);
QByteArray ba_parkingEndTime = codec->fromUnicode(parkingEndDateTime.toString("hh:mm"));
memcpy((char*)dynTicketData->parkingEnd, ba_parkingEndTime.data(), std::min(ba_parkingEndTime.size(),8));
QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QByteArray ba_parkingEndDate = codec->fromUnicode(parkingEndDateString);
memcpy((char*)dynTicketData->currentTime, ba_parkingEndDate.data(), std::min(ba_parkingEndDate.size(),8));
// ! and yes... 'ParkingEndDate' is 'currentTime'
}
void ATBDeviceControllerPlugin::private_setupDynTemplateData_DEFAULT(struct T_dynDat *dynTicketData, Ticket *ticket)
{
QDateTime parkingEndDateTime = QDateTime::fromString(ticket->getPrintingData()["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate);
QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QString currentDateString = TicketUtils::getLocaleDateString(this->printerLocale, currentDateTime.date());
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString());
memcpy((char*)dynTicketData->licensePlate, ba_licenseplate.data(), std::min(ba_licenseplate.size(),8));
QByteArray ba_amount = codec->fromUnicode(ticket->getPrintingData()["amount"].toString());
memcpy((char*)dynTicketData->vendingPrice, ba_amount.data(), std::min(ba_amount.size(),8)); // Szeged
memcpy((char*)dynTicketData->dynDat6, ba_amount.data(), std::min(ba_amount.size(),8)); // Schoenau
QByteArray ba_parkingEndTime = codec->fromUnicode(parkingEndDateTime.toString("hh:mm"));
memcpy((char*)dynTicketData->parkingEnd, ba_parkingEndTime.data(), std::min(ba_parkingEndTime.size(),8));
QByteArray ba_parkingEndDate = codec->fromUnicode(parkingEndDateString);
memcpy((char*)dynTicketData->currentTime, ba_parkingEndDate.data(), std::min(ba_parkingEndDate.size(),8));
// ! and yes... 'ParkingEndDate' is 'currentTime'
QByteArray ba_currentDate = codec->fromUnicode(currentDateString);
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
// Product-Text
QByteArray ba_productText = codec->fromUnicode(ticket->getPrintingData()["productText"].toString());
memcpy((char*)dynTicketData->dynDat5, ba_productText.data(), std::min(ba_productText.size(),8));
// Ticket-Number
QByteArray ba_ticketNumber = codec->fromUnicode(ticket->getPrintingData()["ticketNumber"].toString());
memcpy((char*)dynTicketData->dynDat7, ba_ticketNumber.data(), std::min(ba_ticketNumber.size(),8));
}
void ATBDeviceControllerPlugin::private_setupDynTemplateData_FIXED_PRICE(struct T_dynDat *dynTicketData, Ticket *ticket)
{
QDateTime parkingEndDateTime = QDateTime::fromString(ticket->getPrintingData()["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate);
QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QString currentDateString = TicketUtils::getLocaleDateString(this->printerLocale, currentDateTime.date());
// set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString());
memcpy((char*)dynTicketData->licensePlate, ba_licenseplate.data(), std::min(ba_licenseplate.size(),8));
QByteArray ba_amount = codec->fromUnicode(ticket->getPrintingData()["amount"].toString());
memcpy((char*)dynTicketData->vendingPrice, ba_amount.data(), std::min(ba_amount.size(),8));
QByteArray ba_parkingEndTime = codec->fromUnicode(parkingEndDateTime.toString("hh:mm"));
memcpy((char*)dynTicketData->parkingEnd, ba_parkingEndTime.data(), std::min(ba_parkingEndTime.size(),8));
QByteArray ba_parkingEndDate = codec->fromUnicode(parkingEndDateString);
memcpy((char*)dynTicketData->currentTime, ba_parkingEndDate.data(), std::min(ba_parkingEndDate.size(),8));
// ! and yes... 'ParkingEndDate' is 'currentTime'
QByteArray ba_currentDate = codec->fromUnicode(currentDateString);
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8));
// Ticket-Number
QByteArray ba_ticketNumber = codec->fromUnicode(ticket->getPrintingData()["ticketNumber"].toString());
memcpy((char*)dynTicketData->dynDat5, ba_ticketNumber.data(), std::min(ba_ticketNumber.size(),8));
// Product-Text 1
QByteArray ba_productText1 = codec->fromUnicode(ticket->getPrintingData()["productText"].toString()).left(8);
memcpy((char*)dynTicketData->dynDat6, ba_productText1.data(), std::min(ba_productText1.size(),8));
// Product-Text 2
QByteArray ba_productText2 = codec->fromUnicode(ticket->getPrintingData()["productText"].toString()).mid(8,8);
memcpy((char*)dynTicketData->dynDat7, ba_productText2.data(), std::min(ba_productText2.size(),8));
}
/************************************************************************************************
@@ -1149,8 +1528,8 @@ void ATBDeviceControllerPlugin::onCashPayStopByEscrow()
"",
"",
"",
"",
"");
"CashPayStopByEscrow",
"CashPayStopByEscrow");
}
void ATBDeviceControllerPlugin::onCashPayStopByError()
@@ -1167,8 +1546,8 @@ void ATBDeviceControllerPlugin::onCashPayStopByError()
"",
"",
"",
"",
"");
"onCashPayStopByError",
"onCashPayStopByError");
}
void ATBDeviceControllerPlugin::onCashPayStopByTimeout()
@@ -1185,8 +1564,8 @@ void ATBDeviceControllerPlugin::onCashPayStopByTimeout()
"",
"",
"",
"",
"");
"CashPayStopByTimeout",
"CashPayStopByTimeout");
}
void ATBDeviceControllerPlugin::onCashPayStopedSuccess()
@@ -1331,6 +1710,10 @@ void ATBDeviceControllerPlugin::onCashChangerState()
"");
changerStateRequestCounter = 0;
lastChangerResult = 0;
// finalize vending:
hw->vend_success();
return;
}
else
@@ -1385,6 +1768,10 @@ void ATBDeviceControllerPlugin::onCashChangerState()
errorDescription);
changerStateRequestCounter = 0;
lastChangerResult = 0;
// finalize vending:
hw->vend_success();
return;
}
@@ -1522,8 +1909,18 @@ int ATBDeviceControllerPlugin::init_sc_dbus()
void ATBDeviceControllerPlugin::onWokeUp(uchar source)
{
if (source == 0x01 || source == 0xFE) {
// woke up from device controller
/* PTU5 wakeup sources:
* 0x01 - on wakeup from DeviceController
* 0x02 - on wakeup from WakeupButton
* 0x03 - on wakeup from ResetKey
* 0x04 - on wakeup from rtc
* 0xFE - signal emitted by timer (on mains powered machines)
* 0xFF - unknown wakeup source
*/
if (source == 0x01 || source == 0x03 || source == 0xFE) {
// woke up from device controller, rtc or timer
hw->dc_autoRequest(true);
this->diag->diagRequest();
}
}

View File

@@ -25,6 +25,16 @@ using namespace nsDeviceControllerInterface;
class QSettings;
enum class PROGRAM_MODE {
INIT,
IDLE,
SELL,
SERVICE,
OOO,
NOT_DEFINED
};
class ATBDeviceControllerPlugin :
public DeviceControllerInterface
@@ -50,6 +60,7 @@ public:
void requestStartCashInput(const QString & amount);
void requestStopCashInput();
void cashCollect();
void cashCollect(const QString & amount);
void cashAbort();
// read coin/cash processing variants -----------------------------------------
@@ -99,6 +110,8 @@ private:
QString serialPortName;
PROGRAM_MODE currentProgramMode;
bool useDebug;
bool isMaster;
@@ -139,11 +152,18 @@ private:
Ticket * currentTicket;
QLocale printerLocale;
QHash<TICKET_VARIANT, QList<quint8>> ticketTemplateList;
void initTicketTemplateList(const QSettings * settings);
void prepareDynTemplateData();
void private_setupDynTemplateData_DEFAULT(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplateData_FIXED_PRICE(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplateData_START_RECEIPT(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplatData_STOP_RECEIPT(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplatData_FOOD_STAMP(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplatData_FINE_PAYMENT(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplatData_FREE_TICKET(struct T_dynDat *dynTicketData, Ticket *ticket);
// ---------------------------------------------------------------------------------------------
private slots:

View File

@@ -8,6 +8,7 @@
#include <QProcess>
#include "support/JSON.h"
#include "src/ATBAPP/support/DBusControllerInterface.h"
DeviceControllerDiag::DeviceControllerDiag(PersistentData *pData, QObject *parent)
@@ -17,6 +18,7 @@ DeviceControllerDiag::DeviceControllerDiag(PersistentData *pData, QObject *paren
, eventReceiver(nullptr)
, isRequestRunning(false)
, flagInterruptDiag(false)
, isDiagBackgroundTask(false)
, lastState(DeviceController::State::INITIAL_STATE)
, _isErrorState(false)
, pData(pData)
@@ -29,10 +31,11 @@ DeviceControllerDiag::DeviceControllerDiag(PersistentData *pData, QObject *paren
}
void DeviceControllerDiag::init(hwinf *hw, QObject* eventReceiver)
void DeviceControllerDiag::init(hwinf *hw, DBusControllerInterface *dbus, QObject* eventReceiver)
{
this->hw = hw;
this->eventReceiver = eventReceiver;
this->dbus = dbus;
// make a system check on startup:
QTimer::singleShot(2000, this, &DeviceControllerDiag::diagRequest);
@@ -42,6 +45,7 @@ void DeviceControllerDiag::init(hwinf *hw, QObject* eventReceiver)
void DeviceControllerDiag::diagReInit()
{
this->machineEventSet.clear();
this->previousMachineEventSet.clear();
this->_isErrorState = false;
}
@@ -92,8 +96,11 @@ bool DeviceControllerDiag::isOperatingState()
return !this->_isErrorState;
}
QSet<DeviceController::State> DeviceControllerDiag::getCurrentMachineState()
QSet<DCMachineEvent> DeviceControllerDiag::getCurrentMachineState()
{
// ensure that currentMachineEventSet is delivered here
if (this->isRequestRunning) return this->previousMachineEventSet;
return this->machineEventSet;
}
@@ -104,11 +111,15 @@ void DeviceControllerDiag::private_startDiag()
// check for DiagRequestTimeoutTimerTimeout:
if (this->flagInterruptDiag) {
qCritical() << "DeviceControllerDiag::private_startDiag() interrupted!";
this->private_sendDiagEvent(DeviceController::State::E255);
this->isRequestRunning = false;
this->flagInterruptDiag = false;
DCMachineEvent E255Event = DCMachineEvent(DeviceController::State::E255);
if (!this->previousMachineEventSet.contains(E255Event)) {
machineEventSet.insert(E255Event);
private_sendDiagEvent(E255Event, DeviceController::Action::SET);
}
if (this->E255counter > 5) {
this->restartCArun();
// try it again, until success:
QTimer::singleShot(1000, this, &DeviceControllerDiag::diagRequest);
}
else {
this->E255counter++;
@@ -121,6 +132,9 @@ void DeviceControllerDiag::private_startDiag()
* - diag is called again in ModeOOO wokeup()
*/
}
this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false;
this->flagInterruptDiag = false;
return;
}
@@ -129,11 +143,20 @@ void DeviceControllerDiag::private_startDiag()
if (result) {
qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is valid";
this->machineEventSet.remove(DCMachineEvent(DeviceController::State::E255));
this->machineEventSet.remove(DCMachineEvent(DeviceController::State::M0255));
QTimer::singleShot(200, this, &DeviceControllerDiag::sys_superviseSystem);
}
else {
qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is +++not+++ valid";
hw->dc_autoRequest(true);
if (! this->isDiagBackgroundTask) {
this->isDiagBackgroundTask = true;
this->dbus->startBackgroundTask("E255");
}
// try it again
QTimer::singleShot(200, this, &DeviceControllerDiag::private_startDiag);
}
@@ -142,8 +165,8 @@ void DeviceControllerDiag::private_startDiag()
void DeviceControllerDiag::sys_superviseSystem()
{ // this function proofs if vending is possible depending of doors state
struct T_dynamicCondition dynMaCond;
struct T_moduleCondition modCond;
struct T_dynamicCondition dynMaCond = {};
struct T_moduleCondition modCond = {};
qCritical() << " sys_superviseSystem()";
@@ -152,11 +175,18 @@ void DeviceControllerDiag::sys_superviseSystem()
// check for DiagRequestTimeoutTimerTimeout:
if (this->flagInterruptDiag) {
qCritical() << "DeviceControllerDiag::sys_superviseSystem() interrupted!";
this->private_sendDiagEvent(DeviceController::State::E255);
this->flagInterruptDiag = false;
this->isRequestRunning = false;
// send
DCMachineEvent E255Event = DCMachineEvent(DeviceController::State::E255);
if (!this->previousMachineEventSet.contains(E255Event)) {
machineEventSet.insert(E255Event);
private_sendDiagEvent(E255Event, DeviceController::Action::SET);
}
if (this->E255counter > 5) { this->restartCArun(); }
else { this->E255counter++; }
QTimer::singleShot(400, this, &DeviceControllerDiag::diagRequest);
this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false;
this->flagInterruptDiag = false;
return;
}
@@ -164,11 +194,18 @@ void DeviceControllerDiag::sys_superviseSystem()
{
// es gibt keinerlei gültige Daten vom DC
qCritical() << "DeviceControllerDiag::sys_superviseSystem() no valid data!";
this->private_sendDiagEvent(DeviceController::State::E254);
this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false;
hw->dc_autoRequest(true);
DCMachineEvent E255Event = DCMachineEvent(DeviceController::State::M0254);
previousMachineEventSet.insert(E255Event);
private_sendDiagEvent(E255Event, DeviceController::Action::SET);
if (this->E255counter > 5) { this->restartCArun(); }
else { this->E255counter++; }
QTimer::singleShot(400, this, &DeviceControllerDiag::diagRequest);
this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false;
this->flagInterruptDiag = false;
return;
}
@@ -200,15 +237,17 @@ void DeviceControllerDiag::sys_superviseSystem()
void DeviceControllerDiag::sub_componentAssessment()
{
this->machineEventSet.clear();
bool flag_sendOperate = true;
struct T_moduleCondition modCond;
struct T_moduleCondition modCond = {};
hw->sys_getDeviceConditions(&modCond);
struct T_dynamicCondition dynMaCond;
struct T_dynamicCondition dynMaCond = {};
hw->sys_getDynMachineConditions(&dynMaCond);
struct T_devices devPara;
struct T_devices devPara = {};
hw->sys_restoreDeviceParameter(&devPara);
// store some interesting results:
@@ -221,7 +260,7 @@ void DeviceControllerDiag::sub_componentAssessment()
if (dynMaCond.onAlarm>0) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::A000);
this->private_setDiagEvent(DeviceController::State::A000);
}
// check for open doors
@@ -230,41 +269,41 @@ void DeviceControllerDiag::sub_componentAssessment()
// Service or battery door is open
flag_sendOperate = false;
qCritical() << "DeviceControllerDiag::sys_superviseSystem() Service or battery door is open, goto INTRUSION MODE";
this->private_sendDiagEvent(DeviceController::State::E253);
this->private_setDiagEvent(DeviceController::State::M0253);
}
if (dynMaCond.middleDoor) {
// vault door is open
flag_sendOperate = false;
qCritical() << "DeviceControllerDiag::sys_superviseSystem() vault door is open, goto INTRUSION MODE";
this->private_sendDiagEvent(DeviceController::State::E252);
this->private_setDiagEvent(DeviceController::State::M0252);
}
// check for invalid states:
if (modCond.rtc>=200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E002);
this->private_setDiagEvent(DeviceController::State::E002);
}
if (modCond.printer==200 || modCond.printer==201) { // 200: not connected 201: printer-HW-error 202: no paper
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E020);
this->private_setDiagEvent(DeviceController::State::E020);
}
if (modCond.printer==202) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E018);
this->private_setDiagEvent(DeviceController::State::E018);
}
if (modCond.coinBlocker>=200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E025);
this->private_setDiagEvent(DeviceController::State::E025);
}
if (modCond.mdbBus>=200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E034);
this->private_setDiagEvent(DeviceController::State::E034);
}
if (modCond.intEe>=200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E011);
this->private_setDiagEvent(DeviceController::State::E011);
}
// 2023-07-26: workaround for 00281/Szeged --------------------------------------------------------------
@@ -274,16 +313,16 @@ void DeviceControllerDiag::sub_componentAssessment()
if (devPara.kindOfCoinChecker > 0) {
if (modCond.coinSafe==201) { // full
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E007);
this->private_setDiagEvent(DeviceController::State::E007);
}
if (modCond.coinSafe==200) { // 200: kasse fehlt 201: voll 100:fast voll 1:ok
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E009);
this->private_setDiagEvent(DeviceController::State::E009);
}
if (modCond.coinEscrow>=200) {
flag_sendOperate = false;
// coinEscrow>200 is considered a warning:
this->private_sendDiagEvent(DeviceController::State::W010);
this->private_setDiagEvent(DeviceController::State::W010);
}
}
// -----------------------------------------------------------------------------------------------
@@ -306,15 +345,15 @@ void DeviceControllerDiag::sub_componentAssessment()
if (modCond.coinEscrow>=200) {
flag_sendOperate = false;
// coinEscrow>200 is considered a warning:
this->private_sendDiagEvent(DeviceController::State::W010);
this->private_setDiagEvent(DeviceController::State::W010);
}
if (modCond.coinSafe==201) { // full
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E007);
this->private_setDiagEvent(DeviceController::State::E007);
}
if (modCond.coinSafe==200) { // 200: kasse fehlt 201: voll 100:fast voll 1:ok
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E009);
this->private_setDiagEvent(DeviceController::State::E009);
}
} else
if (devPara.kindOfCoinChecker==3)
@@ -322,15 +361,15 @@ void DeviceControllerDiag::sub_componentAssessment()
if (modCond.changer>=200) {
// Fehler Münzver.
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E026);
this->private_setDiagEvent(DeviceController::State::E026);
}
if (modCond.coinSafe==201) { // full
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E007);
this->private_setDiagEvent(DeviceController::State::E007);
}
if (modCond.coinSafe == 200) { // 200: kasse fehlt 201: voll 100:fast voll 1:ok
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E009);
this->private_setDiagEvent(DeviceController::State::E009);
}
}
@@ -359,61 +398,113 @@ void DeviceControllerDiag::sub_componentAssessment()
if (dynMaCond.modeAbrech>0) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E011);
this->private_setDiagEvent(DeviceController::State::E011);
}
if (dynMaCond.nowCardTest>0) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E072);
this->private_setDiagEvent(DeviceController::State::M0072);
}
if (dynMaCond.startupTestIsRunning>0) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E073);
this->private_setDiagEvent(DeviceController::State::M0073);
}
if (modCond.voltage>=200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E003);
this->private_setDiagEvent(DeviceController::State::E003);
}
if (modCond.temper>=200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::W004);
this->private_setDiagEvent(DeviceController::State::W004);
}
// check for warnings
if (modCond.printer>=100 && modCond.printer<200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::W001);
this->private_setDiagEvent(DeviceController::State::W001);
}
if (modCond.coinSafe>=100 && modCond.coinSafe<200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::W002);
this->private_setDiagEvent(DeviceController::State::W002);
}
if (modCond.voltage>=100 && modCond.voltage<200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::W003);
this->private_setDiagEvent(DeviceController::State::W003);
}
if (modCond.temper>=100 && modCond.temper<200) {
flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::W004);
this->private_setDiagEvent(DeviceController::State::W004);
}
// compare machineEventSets
// New events: present in current but not previous
QSet<DCMachineEvent> newEvents = this->machineEventSet - this->previousMachineEventSet;
// Reset events: present in previous but not current
QSet<DCMachineEvent> resetEvents = this->previousMachineEventSet - this->machineEventSet;
// DEBUG EventSets:
qCritical() << "sub_componentAssessment():";
qCritical() << " newEvents: " << newEvents.size();
qCritical() << " resetEvents: " << resetEvents.size();
QStringList DeviceControllerStateStringList;
for (const DCMachineEvent& event : this->machineEventSet) {
DeviceControllerStateStringList.append(QMetaEnum::fromType<DeviceController::State>().valueToKey(event.state));
}
qCritical() << "diagReq result: " << DeviceControllerStateStringList;
// Triggering Actions
// Iterate through the results
// send SET:
for (const DCMachineEvent& event : newEvents) {
private_sendDiagEvent(event, DeviceController::Action::SET); // New event detected
}
// send RESET:
for (const DCMachineEvent& event : resetEvents) {
private_sendDiagEvent(event, DeviceController::Action::RESET); // Event no longer present
}
// send Operate if there is no error
if (flag_sendOperate) {
this->private_sendDiagEvent(DeviceController::State::O000);
// O000 must not be part of machineEventSet
DCMachineEvent O000DCMachineEvent = DCMachineEvent(DeviceController::State::O000);
this->private_sendDiagEvent(O000DCMachineEvent, DeviceController::Action::SET);
}
// finish diag
this->private_finishDiag();
}
/**
* @brief DeviceControllerDiag::private_finishDiag
*
* Single point to finish a diag process:
* -
*/
void DeviceControllerDiag::private_finishDiag()
{
this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false;
this->flagInterruptDiag = false;
this->previousMachineEventSet.unite(machineEventSet); // add new elements from machineEventSet
this->previousMachineEventSet.intersect(machineEventSet); // remove elements not in machineEventSet
if (this->isDiagBackgroundTask) {
this->isDiagBackgroundTask = false;
this->dbus->finishedBackgroundTask("E255");
}
}
/**
* @brief DeviceControllerDiag::private_sendDiagEvent
* @brief DeviceControllerDiag::private_setDiagEvent
* @param result - result value from 'sub_componentAssessment()',
* - 0x00 everything is fine
* - 0xFF on timer interrupt
@@ -421,31 +512,38 @@ void DeviceControllerDiag::sub_componentAssessment()
* - 0xFD Service or battery door is open
* - 0xFE vault door is open
*/
void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
void DeviceControllerDiag::private_setDiagEvent(DeviceController::State result)
{
qCritical() << "DeviceControllerDiag::private_sendDiagEvent() result: " << result;
qCritical() << "DeviceControllerDiag::private_setDiagEvent() result: " << result;
if (this->eventReceiver == nullptr) {
qCritical() << "DeviceControllerDiag: no eventReceiver";
return;
}
if (machineEventSet.contains(result)) {
// do not send already sent events
qCritical() << " ... is in machineEventList";
return;
}
else {
machineEventSet.insert(result);
}
DCMachineEvent newState = DCMachineEvent(result);
// DEBUG
qCritical() << "----> setDiagEvent: " << newState.state << " with id: " << newState.eventId;
machineEventSet.insert(newState);
}
QString eventId = QUuid::createUuid().toString(QUuid::WithoutBraces).mid(0, 8);
QString eventName = QMetaEnum::fromType<DeviceController::State>().valueToKey(result);;
/**
* @brief DeviceControllerDiag::private_sendDiagEvent
* @param result WXXX | EXXX | O000
* @param action SET|RESET
*/
void DeviceControllerDiag::private_sendDiagEvent(DCMachineEvent result, DeviceController::Action action)
{
QString eventId = result.eventId;
QString eventName = QMetaEnum::fromType<DeviceController::State>().valueToKey(result.state);
EVENT_CLASS eventClass = EVENT_CLASS::STATE;
QString parameter;
switch (result) {
switch (result.state) {
case DeviceController::State::INITIAL_STATE:
break;
@@ -524,28 +622,28 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
this->_isErrorState = true;
break;
case DeviceController::State::E071: // cash box change is ongoing
case DeviceController::State::M0071: // cash box change is ongoing
eventClass = EVENT_CLASS::STATE;
parameter = "cash box change is ongoing";
break;
case DeviceController::State::E072: // card test running
case DeviceController::State::M0072: // card test running
eventClass = EVENT_CLASS::STATE;
parameter = "card test running";
break;
case DeviceController::State::E073: // startup-test is running
case DeviceController::State::M0073: // startup-test is running
eventClass = EVENT_CLASS::STATE;
parameter = "startup-test is running";
break;
case DeviceController::State::E252: // cash box door open
case DeviceController::State::M0252: // cash box door open
eventClass = EVENT_CLASS::STATE;
parameter = "cash box door open";
break;
case DeviceController::State::E253: // service or battery door open
case DeviceController::State::M0253: // service or battery door open
eventClass = EVENT_CLASS::STATE;
parameter = "service or battery door open";
break;
case DeviceController::State::E254: // no valid data from DeviceController
case DeviceController::State::M0254: // no valid data from DeviceController
eventClass = EVENT_CLASS::STATE;
parameter = "no valid data from DeviceController";
break;
@@ -554,7 +652,6 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
parameter = "no valid data from DeviceController";
break;
case DeviceController::State::O000: // everything is fine
this->machineEventSet.clear();
this->_isErrorState = false;
eventClass = EVENT_CLASS::OPERATE;
parameter = "";
@@ -583,13 +680,13 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
eventClass = EVENT_CLASS::WARNING;
parameter = "temperatur warning";
break;
case DeviceController::State::W255: // restart carun
eventClass = EVENT_CLASS::WARNING;
case DeviceController::State::M0255: // restart carun
eventClass = EVENT_CLASS::STATE;
parameter = "restart carun";
break;
}
this->lastState = result;
this->lastState = result.state;
/**
* Variant: send 'parameter' as JSON:
@@ -606,7 +703,7 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
"DC",
eventClass,
eventName,
1,
action, // eventState
parameter,
"" // second level info
);
@@ -623,6 +720,27 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
void DeviceControllerDiag::restartCArun()
{
this->E255counter = 0;
this->private_sendDiagEvent(DeviceController::State::W255);
DCMachineEvent M0255Event = DCMachineEvent(DeviceController::State::M0255);
if (!this->previousMachineEventSet.contains(M0255Event)) {
machineEventSet.insert(M0255Event);
private_sendDiagEvent(M0255Event, DeviceController::Action::SET);
}
QProcess::startDetached("/bin/systemctl", {"restart", "carun"});
}
/****************************************************************************************************
*
* DCMachineEvent
*/
DCMachineEvent::DCMachineEvent(DeviceController::State state) : state(state)
{
this->eventId = QUuid::createUuid().toString(QUuid::WithoutBraces).mid(0, 8);
}

View File

@@ -12,6 +12,7 @@
#include "support/PersistentData.h"
class DBusControllerInterface;
namespace DeviceController {
Q_NAMESPACE
@@ -41,13 +42,15 @@ namespace DeviceController {
E034,
E071,
E072,
E073,
M0071, // cashbox change is ongoing
M0072, // cardtest is running
M0073, // startup-test is running
M0252, // cashbox door open
M0253, // service or battery door is open
M0254, // no valid data from DC
M0255, // restart carun
E252,
E253,
E254,
E255,
W001,
@@ -55,14 +58,44 @@ namespace DeviceController {
W003,
W004,
W255,
INITIAL_STATE
};
Q_ENUM_NS(State)
enum Action {
SET = 1,
RESET = 0
};
Q_ENUM_NS(Action)
}
// ----------------------------- DCMachineEvent -----------------------------------------
class DCMachineEvent {
public:
DCMachineEvent() = default;
DCMachineEvent(DeviceController::State state);
DeviceController::State state;
QString eventId;
// Equality operator (required for QSet)
bool operator==(const DCMachineEvent& other) const {
return (state == other.state);
}
};
// Hash function (required for QSet)
inline uint qHash(const DCMachineEvent& key, uint seed = 0) {
return qHash(static_cast<int>(key.state), seed);
}
// ------------------------ DeviceControllerDiag --------------------------------------
class DeviceControllerDiag : public QObject
{
Q_OBJECT
@@ -70,7 +103,7 @@ class DeviceControllerDiag : public QObject
public:
DeviceControllerDiag(PersistentData *pData, QObject *parent = nullptr);
void init(hwinf* hw, QObject* eventReceiver);
void init(hwinf* hw, DBusControllerInterface *dbus, QObject* eventReceiver);
nsDeviceControllerInterface::COIN_PROCESSOR coinProcessorType;
nsDeviceControllerInterface::BILL_ACCEPTOR billAcceptor;
@@ -80,7 +113,7 @@ public:
*/
bool isErrorState();
bool isOperatingState();
QSet<DeviceController::State> getCurrentMachineState();
QSet<DCMachineEvent> getCurrentMachineState();
void setTimeout(int timeout);
@@ -109,9 +142,11 @@ signals:
private:
QObject *eventReceiver;
hwinf* hw;
DBusControllerInterface* dbus;
bool isRequestRunning;
bool flagInterruptDiag;
bool isDiagBackgroundTask;
QTimer *diagRequestTimeoutTimer;
@@ -120,7 +155,8 @@ private:
int lastVoltage;
DeviceController::State lastState;
QSet<DeviceController::State> machineEventSet;
QSet<DCMachineEvent> machineEventSet;
QSet<DCMachineEvent> previousMachineEventSet;
bool _isErrorState;
PersistentData* pData;
@@ -131,7 +167,10 @@ private slots:
void onDiagRequestTimeoutTimerTimeout();
void private_startDiag(); // diag entry method
void private_sendDiagEvent(DeviceController::State result);
void private_setDiagEvent(DeviceController::State result);
void private_sendDiagEvent(DCMachineEvent result, DeviceController::Action action);
void private_finishDiag();
void sys_superviseSystem();

View File

@@ -6,6 +6,7 @@
#include <QSettings>
#include <QString>
#include <QJsonObject>
#include <QtCore/QHash>
#include "ATBAPPplugin.h"
@@ -60,9 +61,10 @@ public:
virtual void requestStopCashInput() = 0;
/**
* called e.g. on Button "NEXT" in pay-up (direct coin input)
* called e.g. after printing
*/
virtual void cashCollect() = 0;
virtual void cashCollect(const QString & amount) = 0;
virtual void cashAbort() = 0;
// TASKS: Account -------------------------------------------------------------
@@ -138,6 +140,14 @@ signals:
const QString & errorCode,
const QString & errorDescription);
/**
* emitted if cashPayment has been finished, e.g. in result to task cashCollect():
* if coins in changer must be given back to user.
*/
void cashPaymentChanging(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & changeValue, // amount changed by changer/escrow
const QString & errorCode,
const QString & errorDescription);
/**
* emitted if cashPayment has been finished, e.g. in result to task cashCollect():
* -> ticket should be printed sucessfully
@@ -145,7 +155,7 @@ signals:
* Provides data for logging, especially changed value
*/
void cashPaymentFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
const QString & newCashValue, // total inserted amount amount
const QString & newCashValue, // total inserted amount
const QString & coinValue, // inserted amount, paid with coins
const QString & noteValue, // inserted amount, paid with notes
const QString & changeValue, // amount changed by changer/escrow
@@ -203,10 +213,11 @@ signals:
Q_DECLARE_INTERFACE(DeviceControllerInterface,
"eu.atb.ptu.plugin.DeviceControllerInterface/1.1.4")
"eu.atb.ptu.plugin.DeviceControllerInterface/1.2.1")
namespace nsDeviceControllerInterface {
Q_NAMESPACE
enum class PLUGIN_STATE : quint8 {
NOT_INITIALIZED = 0,
@@ -231,13 +242,43 @@ namespace nsDeviceControllerInterface {
enum class TICKET_VARIANT : quint8 {
INVALID,
NO_TICKET,
PARKING_TICKET,
PARKING_TICKET_CAR,
PARKING_TICKET_VAN,
PARKING_TICKET_CAMPER,
DAY_TICKET,
DAY_TICKET_ADULT,
DAY_TICKET_TEEN,
DAY_TICKET_CHILD,
DAY_TICKET_CAR,
DAY_TICKET_VAN,
DAY_TICKET_CAMPER,
RECEIPT,
ERROR_RECEIPT,
START_RECEIPT, // e.g. Szeged Start
STOP_RECEIPT, // e.g. Szeged Stop
FOOD_STAMP
FINE_PAYMENT, // e.g. Klaipeda
FOOD_STAMP,
FIXED_PRICE_1,
FIXED_PRICE_2,
FIXED_PRICE_3,
FIXED_PRICE_4,
FIXED_PRICE_5,
FIXED_PRICE_6,
FIXED_PRICE_7,
FIXED_PRICE_8,
FIXED_PRICE_9,
FIXED_PRICE_10,
FREE_TICKET
};
Q_ENUM_NS(TICKET_VARIANT)
inline uint qHash(const nsDeviceControllerInterface::TICKET_VARIANT &key, uint seed = 0)
{
return ::qHash(static_cast<quint8>(key), seed);
}
enum class COIN_PROCESSOR : quint8 {
CHANGER,
@@ -259,4 +300,6 @@ namespace nsDeviceControllerInterface {
};
}
#endif // DEVICECONTROLLERINTERFACE_H

View File

@@ -50,19 +50,42 @@ bool Ticket::initNew(TICKET_VARIANT ticketVariant, const QList<quint8> & templat
qCritical() << " -> " << ticketVariant;
int multiplicatorInt = 1; // default
quint8 headerTemplate;
quint8 multiTemplate;
quint8 footerTemplate;
switch (this->ticketVariant) {
case TICKET_VARIANT::PARKING_TICKET:
break;
case TICKET_VARIANT::RECEIPT:
break;
case TICKET_VARIANT::ERROR_RECEIPT:
break;
case TICKET_VARIANT::START_RECEIPT:
this->_templateList << 21 << 22 << 23;
if (templateList.isEmpty()) {
this->_templateList << 21 << 22 << 23;
}
else {
this->_templateList = templateList;
}
break;
case TICKET_VARIANT::STOP_RECEIPT:
this->_templateList << 24 << 25 << 26;
if (templateList.isEmpty()) {
this->_templateList << 24 << 25 << 26;
}
else {
this->_templateList = templateList;
}
break;
case TICKET_VARIANT::FINE_PAYMENT:
if (templateList.isEmpty()) {
this->_templateList << 24 << 25 << 26;
}
else {
this->_templateList = templateList;
}
break;
case TICKET_VARIANT::FREE_TICKET:
if (templateList.isEmpty()) {
this->_templateList << 24 << 25 << 26;
}
else {
this->_templateList = templateList;
}
break;
case TICKET_VARIANT::FOOD_STAMP:
if (printingData.contains("dyn1_list")) {
@@ -72,19 +95,52 @@ bool Ticket::initNew(TICKET_VARIANT ticketVariant, const QList<quint8> & templat
this->dyn2List = printingData["dyn2_list"].toStringList();
}
if (templateList.isEmpty()) {
headerTemplate = 0;
multiTemplate = 1;
footerTemplate = 2;
}
else
if (templateList.size() == 2) {
headerTemplate = 0;
multiTemplate = templateList.at(0);
footerTemplate = templateList.at(1);
}
else
if (templateList.size() == 3) {
headerTemplate = templateList.at(0);
multiTemplate = templateList.at(1);
footerTemplate = templateList.at(2);
}
else {
headerTemplate = 0;
multiTemplate = 1;
footerTemplate = 2;
}
// header is optional:
if (headerTemplate != 0) {
this->_templateList << headerTemplate;
}
if (printingData.contains("multiplicator")) {
multiplicatorInt = printingData["multiplicator"].toInt();
for (int i = 1; i < multiplicatorInt; i++) {
this->_templateList << 1;
this->_templateList << multiTemplate;
}
// last template:
this->_templateList << 2;
this->_templateList << footerTemplate;
}
else {
this->_templateList = templateList;
}
// DEBUG FOOD_STAMP:
qCritical() << " --> printingData[\"multiplicator\"]" << multiplicatorInt;
break;
default:
this->_templateList = templateList;
}
@@ -148,6 +204,66 @@ QDebug operator<<(QDebug debug, TICKET_VARIANT ticketVariant)
case TICKET_VARIANT::PARKING_TICKET:
debug << "TICKET_VARIANT::PARKING_TICKET";
break;
case TICKET_VARIANT::PARKING_TICKET_CAR:
debug << "TICKET_VARIANT::PARKING_TICKET_CAR";
break;
case TICKET_VARIANT::PARKING_TICKET_CAMPER:
debug << "TICKET_VARIANT::PARKING_TICKET_CAMPER";
break;
case TICKET_VARIANT::PARKING_TICKET_VAN:
debug << "TICKET_VARIANT::PARKING_TICKET_VAN";
break;
case TICKET_VARIANT::DAY_TICKET:
debug << "TICKET_VARIANT::DAY_TICKET";
break;
case TICKET_VARIANT::DAY_TICKET_CHILD:
debug << "TICKET_VARIANT::DAY_TICKET_CHILD";
break;
case TICKET_VARIANT::DAY_TICKET_TEEN:
debug << "TICKET_VARIANT::DAY_TICKET_TEEN";
break;
case TICKET_VARIANT::DAY_TICKET_ADULT:
debug << "TICKET_VARIANT::DAY_TICKET_ADULT";
break;
case TICKET_VARIANT::DAY_TICKET_CAR:
debug << "TICKET_VARIANT::DAY_TICKET_CAR";
break;
case TICKET_VARIANT::DAY_TICKET_CAMPER:
debug << "TICKET_VARIANT::DAY_TICKET_CAMPER";
break;
case TICKET_VARIANT::DAY_TICKET_VAN:
debug << "TICKET_VARIANT::DAY_TICKET_VAN";
break;
case TICKET_VARIANT::FIXED_PRICE_1:
debug << "TICKET_VARIANT::FIXED_PRICE_1";
break;
case TICKET_VARIANT::FIXED_PRICE_2:
debug << "TICKET_VARIANT::FIXED_PRICE_2";
break;
case TICKET_VARIANT::FIXED_PRICE_3:
debug << "TICKET_VARIANT::FIXED_PRICE_3";
break;
case TICKET_VARIANT::FIXED_PRICE_4:
debug << "TICKET_VARIANT::FIXED_PRICE_4";
break;
case TICKET_VARIANT::FIXED_PRICE_5:
debug << "TICKET_VARIANT::FIXED_PRICE_5";
break;
case TICKET_VARIANT::FIXED_PRICE_6:
debug << "TICKET_VARIANT::FIXED_PRICE_6";
break;
case TICKET_VARIANT::FIXED_PRICE_7:
debug << "TICKET_VARIANT::FIXED_PRICE_7";
break;
case TICKET_VARIANT::FIXED_PRICE_8:
debug << "TICKET_VARIANT::FIXED_PRICE_8";
break;
case TICKET_VARIANT::FIXED_PRICE_9:
debug << "TICKET_VARIANT::FIXED_PRICE_9";
break;
case TICKET_VARIANT::FIXED_PRICE_10:
debug << "TICKET_VARIANT::FIXED_PRICE_10";
break;
case TICKET_VARIANT::RECEIPT:
debug << "TICKET_VARIANT::RECEIPT";
break;
@@ -160,9 +276,21 @@ QDebug operator<<(QDebug debug, TICKET_VARIANT ticketVariant)
case TICKET_VARIANT::STOP_RECEIPT:
debug << "TICKET_VARIANT::STOP_RECEIPT";
break;
case TICKET_VARIANT::FINE_PAYMENT:
debug << "TICKET_VARIANT::FINE_PAYMENT";
break;
case TICKET_VARIANT::FOOD_STAMP:
debug << "TICKET_VARIANT::FOOD_STAMP";
break;
case TICKET_VARIANT::FREE_TICKET:
debug << "TICKET_VARIANT::FREE_TICKET";
break;
case TICKET_VARIANT::NO_TICKET:
debug << "TICKET_VARIANT::NO_TICKET";
break;
case TICKET_VARIANT::INVALID:
debug << "TICKET_VARIANT::INVALID";
break;
}
return debug;

View File

@@ -0,0 +1,26 @@
#include "TicketUtils.h"
#include <QLocale>
#include <QDate>
TicketUtils::TicketUtils(QObject *parent) : QObject(parent)
{
}
QString TicketUtils::getLocaleDateString(const QLocale & qLocale, const QDate & qDate)
{
QString dateString;
if (qLocale.language() == QLocale::Lithuanian) {
// QLocale::ShortFormat produces date string: "yyyy-mm-dd" ...
// this is to long for the printer.
dateString = qDate.toString("yy-MM-dd");
}
else {
dateString = qLocale.toString(qDate, QLocale::ShortFormat);
}
return dateString;
}

View File

@@ -0,0 +1,34 @@
#ifndef TICKETUTILS_H
#define TICKETUTILS_H
#include <QObject>
class TicketUtils : public QObject
{
Q_OBJECT
public:
explicit TicketUtils(QObject *parent = nullptr);
/**
* @brief getLocaleDateString
* @param qLocale
* @param qDate
* @return a localized date string short format
*
* Note QLocale::ShortFormat does not result to the
* string we need for ticket printing therefore this
* helper method was created.
*
* e.g. using Lithuanian (lt_LT) we get a date in short format:
* "2024-08-08" unfortunately this is to long, we need
* the year with only two digits.
* e.g. in German (de_DE) it is enought: "08.08.24"
*
*/
static QString getLocaleDateString(const QLocale &qLocale, const QDate &qDate);
signals:
};
#endif // TICKETUTILS_H