Compare commits

...

29 Commits
2.2.7 ... 2.6.0

Author SHA1 Message Date
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
ac93e9e631 Send W255 on restart CArun 2024-07-15 11:09:37 +02:00
c1dd20ec4f Restart carun on consecutive E255 2024-07-15 11:09:28 +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
6c2717c56b Diag: check doors in sub_componentAssessment ...
... this prevents sending Operate "O000" in case of an opend door and
enables sending Operate "O000" after closing all doors because
'lastResult' has not changed.
2024-06-11 09:27:07 +02:00
9 changed files with 391 additions and 69 deletions

View File

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

View File

@@ -6,6 +6,7 @@
#include "src/ATBAPP/support/DBusControllerInterface.h" #include "src/ATBAPP/support/DBusControllerInterface.h"
#include "src/ATBAPP/support/PTUSystem.h" #include "src/ATBAPP/support/PTUSystem.h"
#include "src/ATBAPP/support/CashUtils.h" #include "src/ATBAPP/support/CashUtils.h"
#include "src/ATBAPP/support/TicketUtils.h"
#include <QTimer> #include <QTimer>
#include <QThread> #include <QThread>
@@ -310,6 +311,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() void ATBDeviceControllerPlugin::cashAbort()
{ {
hw->vend_failed(); hw->vend_failed();
@@ -579,7 +647,7 @@ void ATBDeviceControllerPlugin::onNewVoltage(uint32_t voltage)
json = JSON::objectBuilder() json = JSON::objectBuilder()
->set("Name", "batt") ->set("Name", "batt")
->set("Value", voltageString) ->set("Value", voltageString)
->set("Unit", "V") ->set("Unit", "mV")
->create(); ->create();
@@ -654,10 +722,21 @@ void ATBDeviceControllerPlugin::requestPrintReceipt(const QHash<QString, QVarian
void ATBDeviceControllerPlugin::requestPrintReceipt(const QString & printingString) 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_switchPower(true);
hw->prn_setFonts(8,12,0,0); 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; this->printResultCheckCounter = 0;
QTimer::singleShot(4000, this, SLOT(onPrinterWaitForPrintingReceipt())); QTimer::singleShot(4000, this, SLOT(onPrinterWaitForPrintingReceipt()));
@@ -713,15 +792,31 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket( " << endl qCritical() << "ATBDeviceControllerPlugin::requestPrintTicket( " << endl
<< " licenseplate = " << printingData["licenseplate"] << endl << " licenseplate = " << printingData["licenseplate"] << endl
<< " productText = " << printingData["productText"] << endl
<< " amount = " << printingData["amount"] << endl << " amount = " << printingData["amount"] << endl
<< " parkingEnd = " << printingData["parkingEnd"] << 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); QDateTime currentDateTime = QDateTime::fromString(printingData["currentDateTime"].toString(), Qt::ISODate);
QString parkingEndDateString = this->printerLocale.toString(parkingEndDateTime.date(), QLocale::ShortFormat); QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QString currentDateString = this->printerLocale.toString(currentDateTime.date(), QLocale::ShortFormat); 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! * note: the following highly depends on printer template files!
@@ -747,6 +842,13 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
QByteArray ba_currentDate = codec->fromUnicode(currentDateString); QByteArray ba_currentDate = codec->fromUnicode(currentDateString);
memcpy((char*)dynTicketData->currentDate, ba_currentDate.data(), std::min(ba_currentDate.size(),8)); 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 // DEBUG
/* /*
@@ -780,7 +882,8 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
<< " amount = " << printingData["amount"] << endl << " amount = " << printingData["amount"] << endl
<< " parkingEnd = " << printingData["parkingEnd"] << endl << " parkingEnd = " << printingData["parkingEnd"] << endl
<< " currentTime = " << printingData["currentTime"] << endl << " currentTime = " << printingData["currentTime"] << endl
<< " currentDate = " << printingData["currentDate"] << endl; << " currentDate = " << printingData["currentDate"] << endl
<< " ticketNumber = " << printingData["ticketNumber"] << endl;
this->onPrintFinishedERR(); this->onPrintFinishedERR();
@@ -801,19 +904,39 @@ void ATBDeviceControllerPlugin::requestPrintTicket(const QHash<QString, QVariant
QString paymentType = printingData["paymentType"].toString(); // must be "CASH" | "CARD" QString paymentType = printingData["paymentType"].toString(); // must be "CASH" | "CARD"
QString productName = printingData["product"].toString(); // must be "ShortTimeParking" | "DayTicket" 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" this->currentSelectedTicketType = 1; // "Kombiticket #1"
} }
else 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" this->currentSelectedTicketType = 2; // "Kombiticket #2"
} }
else 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" this->currentSelectedTicketType = 3; // "Kombiticket #3"
} }
else 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" this->currentSelectedTicketType = 4; // "Kombiticket #4"
} }
else else
@@ -983,12 +1106,18 @@ void ATBDeviceControllerPlugin::prepareDynTemplateData()
case nsDeviceControllerInterface::TICKET_VARIANT::STOP_RECEIPT: case nsDeviceControllerInterface::TICKET_VARIANT::STOP_RECEIPT:
private_setupDynTemplatData_STOP_RECEIPT(dynTicketData, this->currentTicket); private_setupDynTemplatData_STOP_RECEIPT(dynTicketData, this->currentTicket);
break; break;
case nsDeviceControllerInterface::TICKET_VARIANT::FINE_PAYMENT:
private_setupDynTemplatData_FINE_PAYMENT(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::RECEIPT: case nsDeviceControllerInterface::TICKET_VARIANT::RECEIPT:
break; break;
case nsDeviceControllerInterface::TICKET_VARIANT::ERROR_RECEIPT: case nsDeviceControllerInterface::TICKET_VARIANT::ERROR_RECEIPT:
break; break;
case nsDeviceControllerInterface::TICKET_VARIANT::PARKING_TICKET: case nsDeviceControllerInterface::TICKET_VARIANT::PARKING_TICKET:
break; break;
case nsDeviceControllerInterface::TICKET_VARIANT::FREE_TICKET:
private_setupDynTemplatData_FREE_TICKET(dynTicketData, this->currentTicket);
break;
case nsDeviceControllerInterface::TICKET_VARIANT::FOOD_STAMP: case nsDeviceControllerInterface::TICKET_VARIANT::FOOD_STAMP:
private_setupDynTemplatData_FOOD_STAMP(dynTicketData, this->currentTicket); private_setupDynTemplatData_FOOD_STAMP(dynTicketData, this->currentTicket);
break; break;
@@ -1014,9 +1143,8 @@ void ATBDeviceControllerPlugin::private_setupDynTemplateData_START_RECEIPT(struc
QDateTime parkingEndDateTime = QDateTime::fromString(ticket->getPrintingData()["parkingEnd"].toString(), Qt::ISODate); QDateTime parkingEndDateTime = QDateTime::fromString(ticket->getPrintingData()["parkingEnd"].toString(), Qt::ISODate);
QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate); QDateTime currentDateTime = QDateTime::fromString(ticket->getPrintingData()["currentDateTime"].toString(), Qt::ISODate);
QString parkingEndDateString = this->printerLocale.toString(parkingEndDateTime.date(), QLocale::ShortFormat); QString parkingEndDateString = TicketUtils::getLocaleDateString(this->printerLocale, parkingEndDateTime.date());
QString currentDateString = this->printerLocale.toString(currentDateTime.date(), QLocale::ShortFormat); QString currentDateString = TicketUtils::getLocaleDateString(this->printerLocale, currentDateTime.date());
// set dynamic printer data: // set dynamic printer data:
QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString()); QByteArray ba_licenseplate = codec->fromUnicode(ticket->getPrintingData()["licenseplate"].toString());
@@ -1091,6 +1219,62 @@ void ATBDeviceControllerPlugin::private_setupDynTemplatData_FOOD_STAMP(struct T_
qCritical() << "-------------------------------------------------------"; 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'
}
/************************************************************************************************ /************************************************************************************************
@@ -1149,8 +1333,8 @@ void ATBDeviceControllerPlugin::onCashPayStopByEscrow()
"", "",
"", "",
"", "",
"", "CashPayStopByEscrow",
""); "CashPayStopByEscrow");
} }
void ATBDeviceControllerPlugin::onCashPayStopByError() void ATBDeviceControllerPlugin::onCashPayStopByError()
@@ -1167,8 +1351,8 @@ void ATBDeviceControllerPlugin::onCashPayStopByError()
"", "",
"", "",
"", "",
"", "onCashPayStopByError",
""); "onCashPayStopByError");
} }
void ATBDeviceControllerPlugin::onCashPayStopByTimeout() void ATBDeviceControllerPlugin::onCashPayStopByTimeout()
@@ -1185,8 +1369,8 @@ void ATBDeviceControllerPlugin::onCashPayStopByTimeout()
"", "",
"", "",
"", "",
"", "CashPayStopByTimeout",
""); "CashPayStopByTimeout");
} }
void ATBDeviceControllerPlugin::onCashPayStopedSuccess() void ATBDeviceControllerPlugin::onCashPayStopedSuccess()
@@ -1331,6 +1515,10 @@ void ATBDeviceControllerPlugin::onCashChangerState()
""); "");
changerStateRequestCounter = 0; changerStateRequestCounter = 0;
lastChangerResult = 0; lastChangerResult = 0;
// finalize vending:
hw->vend_success();
return; return;
} }
else else
@@ -1385,6 +1573,10 @@ void ATBDeviceControllerPlugin::onCashChangerState()
errorDescription); errorDescription);
changerStateRequestCounter = 0; changerStateRequestCounter = 0;
lastChangerResult = 0; lastChangerResult = 0;
// finalize vending:
hw->vend_success();
return; return;
} }
@@ -1524,6 +1716,7 @@ void ATBDeviceControllerPlugin::onWokeUp(uchar source)
{ {
if (source == 0x01 || source == 0xFE) { if (source == 0x01 || source == 0xFE) {
// woke up from device controller // woke up from device controller
hw->dc_autoRequest(true);
this->diag->diagRequest(); this->diag->diagRequest();
} }
} }

View File

@@ -50,6 +50,7 @@ public:
void requestStartCashInput(const QString & amount); void requestStartCashInput(const QString & amount);
void requestStopCashInput(); void requestStopCashInput();
void cashCollect(); void cashCollect();
void cashCollect(const QString & amount);
void cashAbort(); void cashAbort();
// read coin/cash processing variants ----------------------------------------- // read coin/cash processing variants -----------------------------------------
@@ -144,6 +145,8 @@ private:
void private_setupDynTemplateData_START_RECEIPT(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_STOP_RECEIPT(struct T_dynDat *dynTicketData, Ticket *ticket);
void private_setupDynTemplatData_FOOD_STAMP(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: private slots:

View File

@@ -5,6 +5,8 @@
#include <QUuid> #include <QUuid>
#include <QDebug> #include <QDebug>
#include <QProcess>
#include "support/JSON.h" #include "support/JSON.h"
@@ -18,6 +20,7 @@ DeviceControllerDiag::DeviceControllerDiag(PersistentData *pData, QObject *paren
, lastState(DeviceController::State::INITIAL_STATE) , lastState(DeviceController::State::INITIAL_STATE)
, _isErrorState(false) , _isErrorState(false)
, pData(pData) , pData(pData)
, E255counter(0)
{ {
diagRequestTimeoutTimer = new QTimer(this); diagRequestTimeoutTimer = new QTimer(this);
diagRequestTimeoutTimer->setInterval(1000*45); diagRequestTimeoutTimer->setInterval(1000*45);
@@ -104,14 +107,20 @@ void DeviceControllerDiag::private_startDiag()
this->private_sendDiagEvent(DeviceController::State::E255); this->private_sendDiagEvent(DeviceController::State::E255);
this->isRequestRunning = false; this->isRequestRunning = false;
this->flagInterruptDiag = false; this->flagInterruptDiag = false;
if (this->E255counter > 5) {
this->restartCArun();
}
else {
this->E255counter++;
// try it again, until success: // try it again, until success:
QTimer::singleShot(400, this, &DeviceControllerDiag::diagRequest); QTimer::singleShot(400, this, &DeviceControllerDiag::diagRequest);
/** /**
* But please note: * But please note:
* - diag does currently not stop suspend (start a background task) * - diag does currently not stop suspend (start a background task)
* - diag is called again in ModeOOO wokeup() * - diag is called again in ModeOOO wokeup()
*/ */
}
return; return;
} }
@@ -126,6 +135,7 @@ void DeviceControllerDiag::private_startDiag()
qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is +++not+++ valid"; qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is +++not+++ valid";
// try it again // try it again
hw->dc_autoRequest(true);
QTimer::singleShot(200, this, &DeviceControllerDiag::private_startDiag); QTimer::singleShot(200, this, &DeviceControllerDiag::private_startDiag);
} }
} }
@@ -133,8 +143,8 @@ void DeviceControllerDiag::private_startDiag()
void DeviceControllerDiag::sys_superviseSystem() void DeviceControllerDiag::sys_superviseSystem()
{ // this function proofs if vending is possible depending of doors state { // this function proofs if vending is possible depending of doors state
struct T_dynamicCondition dynMaCond; struct T_dynamicCondition dynMaCond = {};
struct T_moduleCondition modCond; struct T_moduleCondition modCond = {};
qCritical() << " sys_superviseSystem()"; qCritical() << " sys_superviseSystem()";
@@ -146,6 +156,8 @@ void DeviceControllerDiag::sys_superviseSystem()
this->private_sendDiagEvent(DeviceController::State::E255); this->private_sendDiagEvent(DeviceController::State::E255);
this->flagInterruptDiag = false; this->flagInterruptDiag = false;
this->isRequestRunning = false; this->isRequestRunning = false;
if (this->E255counter > 5) { this->restartCArun(); }
else { this->E255counter++; }
return; return;
} }
@@ -153,9 +165,12 @@ void DeviceControllerDiag::sys_superviseSystem()
{ {
// es gibt keinerlei gültige Daten vom DC // es gibt keinerlei gültige Daten vom DC
qCritical() << "DeviceControllerDiag::sys_superviseSystem() no valid data!"; qCritical() << "DeviceControllerDiag::sys_superviseSystem() no valid data!";
this->private_sendDiagEvent(DeviceController::State::E254); hw->dc_autoRequest(true);
this->private_sendDiagEvent(DeviceController::State::M0254);
this->diagRequestTimeoutTimer->stop(); this->diagRequestTimeoutTimer->stop();
this->isRequestRunning = false; this->isRequestRunning = false;
if (this->E255counter > 5) { this->restartCArun(); }
else { this->E255counter++; }
return; return;
} }
@@ -168,7 +183,7 @@ void DeviceControllerDiag::sys_superviseSystem()
{ {
// noch keine Testergebnisse // noch keine Testergebnisse
if (dynMaCond.startupTestIsRunning) { if (dynMaCond.startupTestIsRunning) {
// TODO? qCritical() << " startupTestIsRunning --> call again";
} }
@@ -178,18 +193,6 @@ void DeviceControllerDiag::sys_superviseSystem()
return; return;
} }
// all doors: 99: undefined 0:closed 1:open
if (dynMaCond.lowerDoor || dynMaCond.upperDoor) {
// Service or battery door is open, goto INTRUSION MODE
qCritical() << "DeviceControllerDiag::sys_superviseSystem() Service or battery door is open, goto INTRUSION MODE";
this->private_sendDiagEvent(DeviceController::State::E253);
}
if (dynMaCond.middleDoor) {
// vault door is open, goto INTRUSION MODE
qCritical() << "DeviceControllerDiag::sys_superviseSystem() vault door is open, goto INTRUSION MODE";
this->private_sendDiagEvent(DeviceController::State::E252);
}
qCritical() << " --> call sub_componentAssessment()"; qCritical() << " --> call sub_componentAssessment()";
sub_componentAssessment(); sub_componentAssessment();
@@ -201,13 +204,13 @@ void DeviceControllerDiag::sub_componentAssessment()
{ {
bool flag_sendOperate = true; bool flag_sendOperate = true;
struct T_moduleCondition modCond; struct T_moduleCondition modCond = {};
hw->sys_getDeviceConditions(&modCond); hw->sys_getDeviceConditions(&modCond);
struct T_dynamicCondition dynMaCond; struct T_dynamicCondition dynMaCond = {};
hw->sys_getDynMachineConditions(&dynMaCond); hw->sys_getDynMachineConditions(&dynMaCond);
struct T_devices devPara; struct T_devices devPara = {};
hw->sys_restoreDeviceParameter(&devPara); hw->sys_restoreDeviceParameter(&devPara);
// store some interesting results: // store some interesting results:
@@ -223,6 +226,21 @@ void DeviceControllerDiag::sub_componentAssessment()
this->private_sendDiagEvent(DeviceController::State::A000); this->private_sendDiagEvent(DeviceController::State::A000);
} }
// check for open doors
// all doors: 99: undefined 0:closed 1:open
if (dynMaCond.lowerDoor || dynMaCond.upperDoor) {
// 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::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::M0252);
}
// check for invalid states: // check for invalid states:
if (modCond.rtc>=200) { if (modCond.rtc>=200) {
@@ -348,12 +366,12 @@ void DeviceControllerDiag::sub_componentAssessment()
if (dynMaCond.nowCardTest>0) { if (dynMaCond.nowCardTest>0) {
flag_sendOperate = false; flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E072); this->private_sendDiagEvent(DeviceController::State::M0072);
} }
if (dynMaCond.startupTestIsRunning>0) { if (dynMaCond.startupTestIsRunning>0) {
flag_sendOperate = false; flag_sendOperate = false;
this->private_sendDiagEvent(DeviceController::State::E073); this->private_sendDiagEvent(DeviceController::State::M0073);
} }
if (modCond.voltage>=200) { if (modCond.voltage>=200) {
@@ -508,28 +526,28 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
this->_isErrorState = true; this->_isErrorState = true;
break; break;
case DeviceController::State::E071: // cash box change is ongoing case DeviceController::State::M0071: // cash box change is ongoing
eventClass = EVENT_CLASS::STATE; eventClass = EVENT_CLASS::STATE;
parameter = "cash box change is ongoing"; parameter = "cash box change is ongoing";
break; break;
case DeviceController::State::E072: // card test running case DeviceController::State::M0072: // card test running
eventClass = EVENT_CLASS::STATE; eventClass = EVENT_CLASS::STATE;
parameter = "card test running"; parameter = "card test running";
break; break;
case DeviceController::State::E073: // startup-test is running case DeviceController::State::M0073: // startup-test is running
eventClass = EVENT_CLASS::STATE; eventClass = EVENT_CLASS::STATE;
parameter = "startup-test is running"; parameter = "startup-test is running";
break; break;
case DeviceController::State::E252: // cash box door open case DeviceController::State::M0252: // cash box door open
eventClass = EVENT_CLASS::STATE; eventClass = EVENT_CLASS::STATE;
parameter = "cash box door open"; parameter = "cash box door open";
break; break;
case DeviceController::State::E253: // service or battery door open case DeviceController::State::M0253: // service or battery door open
eventClass = EVENT_CLASS::STATE; eventClass = EVENT_CLASS::STATE;
parameter = "service or battery door open"; parameter = "service or battery door open";
break; break;
case DeviceController::State::E254: // no valid data from DeviceController case DeviceController::State::M0254: // no valid data from DeviceController
eventClass = EVENT_CLASS::STATE; eventClass = EVENT_CLASS::STATE;
parameter = "no valid data from DeviceController"; parameter = "no valid data from DeviceController";
break; break;
@@ -567,6 +585,10 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
eventClass = EVENT_CLASS::WARNING; eventClass = EVENT_CLASS::WARNING;
parameter = "temperatur warning"; parameter = "temperatur warning";
break; break;
case DeviceController::State::W255: // restart carun
eventClass = EVENT_CLASS::WARNING;
parameter = "restart carun";
break;
} }
this->lastState = result; this->lastState = result;
@@ -586,7 +608,7 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
"DC", "DC",
eventClass, eventClass,
eventName, eventName,
1, 1, // eventState
parameter, parameter,
"" // second level info "" // second level info
); );
@@ -596,3 +618,13 @@ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result)
} }
/**
* reset / restart / reinit deviceController
*/
void DeviceControllerDiag::restartCArun()
{
this->E255counter = 0;
this->private_sendDiagEvent(DeviceController::State::W255);
QProcess::startDetached("/bin/systemctl", {"restart", "carun"});
}

View File

@@ -41,13 +41,14 @@ namespace DeviceController {
E034, E034,
E071, M0071, // cashbox change is ongoing
E072, M0072, // cardtest is running
E073, M0073, // startup-test is running
M0252, // cashbox door open
M0253, // service or battery door is open
M0254, // no valid data from DC
E252,
E253,
E254,
E255, E255,
W001, W001,
@@ -55,6 +56,8 @@ namespace DeviceController {
W003, W003,
W004, W004,
W255,
INITIAL_STATE INITIAL_STATE
}; };
Q_ENUM_NS(State) Q_ENUM_NS(State)
@@ -94,6 +97,11 @@ public slots:
*/ */
void diagReInit(); void diagReInit();
/**
* reset / restart / reinit deviceController
*/
void restartCArun();
signals: signals:
void diagResponse(ATBMachineEvent* machineEvent); void diagResponse(ATBMachineEvent* machineEvent);
@@ -118,6 +126,8 @@ private:
PersistentData* pData; PersistentData* pData;
int E255counter;
private slots: private slots:
void onDiagRequestTimeoutTimerTimeout(); void onDiagRequestTimeoutTimerTimeout();
@@ -126,7 +136,6 @@ private slots:
void sys_superviseSystem(); void sys_superviseSystem();
}; };
#endif // DEVICECONTROLLERDIAG_H #endif // DEVICECONTROLLERDIAG_H

View File

@@ -60,9 +60,10 @@ public:
virtual void requestStopCashInput() = 0; 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() = 0;
virtual void cashCollect(const QString & amount) = 0;
virtual void cashAbort() = 0; virtual void cashAbort() = 0;
// TASKS: Account ------------------------------------------------------------- // TASKS: Account -------------------------------------------------------------
@@ -138,6 +139,14 @@ signals:
const QString & errorCode, const QString & errorCode,
const QString & errorDescription); 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(): * emitted if cashPayment has been finished, e.g. in result to task cashCollect():
* -> ticket should be printed sucessfully * -> ticket should be printed sucessfully
@@ -145,7 +154,7 @@ signals:
* Provides data for logging, especially changed value * Provides data for logging, especially changed value
*/ */
void cashPaymentFinished(nsDeviceControllerInterface::RESULT_STATE resultState, 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 & coinValue, // inserted amount, paid with coins
const QString & noteValue, // inserted amount, paid with notes const QString & noteValue, // inserted amount, paid with notes
const QString & changeValue, // amount changed by changer/escrow const QString & changeValue, // amount changed by changer/escrow
@@ -203,7 +212,7 @@ signals:
Q_DECLARE_INTERFACE(DeviceControllerInterface, Q_DECLARE_INTERFACE(DeviceControllerInterface,
"eu.atb.ptu.plugin.DeviceControllerInterface/1.1.4") "eu.atb.ptu.plugin.DeviceControllerInterface/1.2.0")
namespace nsDeviceControllerInterface { namespace nsDeviceControllerInterface {
@@ -236,7 +245,9 @@ namespace nsDeviceControllerInterface {
ERROR_RECEIPT, ERROR_RECEIPT,
START_RECEIPT, // e.g. Szeged Start START_RECEIPT, // e.g. Szeged Start
STOP_RECEIPT, // e.g. Szeged Stop STOP_RECEIPT, // e.g. Szeged Stop
FOOD_STAMP FINE_PAYMENT, // e.g. Klaipeda
FOOD_STAMP,
FREE_TICKET
}; };
enum class COIN_PROCESSOR : quint8 { enum class COIN_PROCESSOR : quint8 {

View File

@@ -64,6 +64,12 @@ bool Ticket::initNew(TICKET_VARIANT ticketVariant, const QList<quint8> & templat
case TICKET_VARIANT::STOP_RECEIPT: case TICKET_VARIANT::STOP_RECEIPT:
this->_templateList << 24 << 25 << 26; this->_templateList << 24 << 25 << 26;
break; break;
case TICKET_VARIANT::FINE_PAYMENT:
this->_templateList << 24 << 25 << 26;
break;
case TICKET_VARIANT::FREE_TICKET:
this->_templateList << 24 << 25 << 26;
break;
case TICKET_VARIANT::FOOD_STAMP: case TICKET_VARIANT::FOOD_STAMP:
if (printingData.contains("dyn1_list")) { if (printingData.contains("dyn1_list")) {
this->_hasTemplateDynData = true; this->_hasTemplateDynData = true;
@@ -160,9 +166,15 @@ QDebug operator<<(QDebug debug, TICKET_VARIANT ticketVariant)
case TICKET_VARIANT::STOP_RECEIPT: case TICKET_VARIANT::STOP_RECEIPT:
debug << "TICKET_VARIANT::STOP_RECEIPT"; debug << "TICKET_VARIANT::STOP_RECEIPT";
break; break;
case TICKET_VARIANT::FINE_PAYMENT:
debug << "TICKET_VARIANT::FINE_PAYMENT";
break;
case TICKET_VARIANT::FOOD_STAMP: case TICKET_VARIANT::FOOD_STAMP:
debug << "TICKET_VARIANT::FOOD_STAMP"; debug << "TICKET_VARIANT::FOOD_STAMP";
break; break;
case TICKET_VARIANT::FREE_TICKET:
debug << "TICKET_VARIANT::FREE_TICKET";
break;
} }
return debug; 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