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