#include "runProc.h" #include #include "controlBus.h" #include "dcBL.h" #include "interfaces.h" static uint32_t hwapi_lastStartAmount; static uint32_t hwapi_lastTotalAmount; static uint8_t hwapi_cash_lastCollectionState; static uint8_t hwapi_paymentStarted; static uint8_t hwapi_lastDoorState; static uint8_t bl_startupStep; T_runProc::T_runProc() { hwapi_TimerPayment = new QTimer(); hwapi_TimerPayment->setSingleShot(true); hwapi_lastStartAmount=0; hwapi_lastTotalAmount=0; hwapi_cash_lastCollectionState=0; hwapi_paymentStarted=0; hwapi_lastDoorState=0; bl_startupStep=0; QTimer *runProc_callProcesses = new QTimer(); connect(runProc_callProcesses, SIGNAL(timeout()), this, SLOT(runProc_slotProcess())); runProc_callProcesses->setSingleShot(false); runProc_callProcesses->start(100); // in ms hwapi_lastDoorState=0; // default: all doors (should be) closed, coin box inserted // bit0: upper door 1:middle 2:lower 3=cash-box out hwapi_triggerBL = new QTimer(); connect(hwapi_triggerBL, SIGNAL(timeout()), this, SLOT(bl_performComplStart())); hwapi_triggerBL->setSingleShot(false); hwapi_triggerBL->stop(); } void T_runProc::runProc_slotProcess(void) { cash_paymentProcessing(); doors_supervise(); dcBL_cycle(); } bool T_runProc::cash_startPayment(uint32_t amount) { uint8_t dat1, dat2, dat3, dat4; hwapi_lastStartAmount=amount; epi_clearCurrentPayment(); dat1=ulong2uchar(amount, 0); dat2=ulong2uchar(amount, 1); dat3=ulong2uchar(amount, 2); dat4=ulong2uchar(amount, 3); hwapi_cash_lastCollectionState=0; sendFDcmd_set(155, 0,0, dat1,dat2,dat3,dat4); // wird im DC auf 65500 gesetzt wenn 0 (Maximalwert 0 macht keinen Sinn!) hwapi_paymentStarted=1; hwapi_TimerPayment->start(5000); // in ms hwapi_lastTotalAmount=0; epi_setNowCoinPay(true); // new since 20.9.23 qDebug() << "payment started with " << amount ; return true; } uint8_t T_runProc::cash_paymentProcessing(void) { // run this function periodically while coin payment process to generate necessary signals: // am 5.10.23 umgebaut, geht jetzt auch fuer MW. Für EMP und MW getestet // 12.10.23: epi_store64BdevParameter() MUSS vorher aufgerufen werden zur Unterscheidung EMP / MW !!!!! // return value: // 0: stopped 1: starting up 2: coin collection // 3: finished by User (Push button) 4: finished, Max-Value collected // 5: finished by escrow // 6: money encashed // 7: cancelled // 10,11: error cannot start // 12: timeout while payment, coins returned // 13: stopped by unexpected error struct T_emp empStat; struct T_changer chgrStat; struct T_dynamicCondition myDynMachCond; struct T_devices devParameter; uint8_t collActiv=0, payInProg, empState, kcc; uint32_t newSum; if (hwapi_paymentStarted<1) return 0; // off collActiv=1; // starting up payment devParameter.kindOfCoinChecker=0; restoreDeviceParameter(&devParameter); kcc=devParameter.kindOfCoinChecker; /* buf66[0]=devPara.kindOfPrinter; buf66[1]=devPara.kindOfCoinChecker; buf66[2]=devPara.kindOfMifareReader; buf66[3]=devPara.suppressSleepMode; buf66[4]=devPara.kindOfModem; buf66[5]=devPara.kindOfCreditcard; buf66[6]=devPara.CoinEscrow; buf66[7]=devPara.CoinRejectUnit; buf66[8]=devPara.CoinShutter; buf66[9]=devPara.BillAcceptor; buf66[10]=devPara.usevaultLock; buf66[11]=devPara.autoAlarm; buf66[12]=devPara.autoOpen; buf66[13]=devPara.printAccReceipt; buf66[14]=devPara.printDoorReceipt; buf66[15]=devPara.printTokenTicket; uitmp=devPara.VaultFullWarnLevel; buf66[16]=swl_getOneByteFromUint(uitmp, GETLOWBYT); buf66[17]=swl_getOneByteFromUint(uitmp, GETHIGHBYT); uitmp=devPara.VaultFullErrorLevel; buf66[18]=swl_getOneByteFromUint(uitmp, GETLOWBYT); buf66[19]=swl_getOneByteFromUint(uitmp, GETHIGHBYT); */ if (kcc<3) { sub_emp_getAllParameters(&empStat); empState=empStat.state; } else { changer_getAllParameters(&chgrStat); empState=chgrStat.state; } // 0=start command // 1=powered, do emp ini, send reset // 2=delay // 3=wait for response, requesting status after response // 4,5 through, startup // 6: wait for status // 7: through, startup // 8: IDLE state. EMP is up and ready, polling is running // 9: polling on, payment not yet on // 10: payment, check coins // 11: through // 12: wait 1s for last coin // 90: stop all, 1s delay // 99: off, all stopped sub_getDynMachineConditions(&myDynMachCond); payInProg= myDynMachCond.paymentInProgress; // 0: stopped by timeout // 1: running 2: wait4lastCoin // 3: payment stopped manually, coins in Escrow // 4: payment stopped autom, amount collected, coins in Escrow // 5: payment stopped, escrow full, coins in Escrow // 6: coins encashed // 7: coins returned 2 cases: due to cancel-button or printer-error // 8: CoinChecker or MDB on Error // qCritical() << "emitting signal payCancelled"; // emit runProc_payCancelled(); if (payInProg==8) { // coin checker faulty, cannot start if (hwapi_paymentStarted==1) { hwapi_paymentStarted=90; // stop due to error qCritical() << "emitting signal coinCollectionAborted 1"; emit runProc_coinCollectionAborted(); //sendFDcmd_set(156, 0,0, 2,0,0,0); // cancel payment } return 10; // error cannot start } if (empState>=10 && empState<=12 && (payInProg==1 || payInProg==2) ) { // coin acceptance is active now: if (hwapi_paymentStarted==1) // && (( payInProg==0) || ( payInProg>5))) //16.6.23 { // 1=wait for coin checker being ready hwapi_paymentStarted=2; // coins can be inserted now qCritical() << "emitting signal coinCollectionJustStarted"; emit runProc_coinCollectionJustStarted(); } } if (hwapi_paymentStarted==2) { // coins can be inserted now, wait for end collActiv=2; // coin collection active newSum=epi_CurrentPaymentGetAmount(); if (newSum>hwapi_lastTotalAmount) { hwapi_lastTotalAmount=newSum; qCritical() << "emitting signal gotNewCoin"; emit runProc_gotNewCoin(); } if (payInProg==0) // timeout, coins returned by DC { hwapi_paymentStarted=90; collActiv=12; // stop by timeout qCritical() << "emitting signal payStopByTimeout"; emit runProc_payStopByTimeout(); } else if (payInProg==3) // user pressed "Next/Continue", keep coin { hwapi_paymentStarted++; collActiv=3; qCritical() << "emitting signal payStopByPushbutton 1"; emit runProc_payStopByPushbutton(); } else if (payInProg==4) // max achieved, keep coins { hwapi_paymentStarted++; collActiv=4; qCritical() << "emitting signal payStopByMax"; emit runProc_payStopByMax(); } else if (payInProg==5) // escrow full, keep coins { hwapi_paymentStarted++; collActiv=5; qCritical() << "emitting signal payStopByEscrow"; emit runProc_payStopByEscrow(); } /* 5.10.23 raus, geht auf 99 wenn Betrag erreicht, ist aber kein fehler if ( (empState<10) || (empState>12)) // error { collActiv=13; hwapi_paymentStarted=90; qCritical() << "emitting signal payStopByError" << empState; emit runProc_payStopByError(); } */ } if (hwapi_paymentStarted==3) { // coin collection finished, but coins kept until printing done collActiv=2; if (payInProg==6) // coins encashed { collActiv=6; hwapi_paymentStarted++; qCritical() << "emitting signal coinProcessJustStopped"; emit runProc_coinProcessJustStopped(); } else if (payInProg==7) // coins returned, printing failed { collActiv=7; hwapi_paymentStarted++; qCritical() << "emitting signal payCancelled"; emit runProc_payCancelled(); } } if (hwapi_paymentStarted==4) { // transaction finished hwapi_paymentStarted=0; } //if ( (empState<8) || (empState>12)) // epi_clearCurrentPayment(); // to avoid wrong "got-coin" messages if (hwapi_paymentStarted==90 ) { // EMP error, wait till process finished // everything stopped, no more coins in escrow hwapi_paymentStarted=0; } return collActiv; } void T_runProc::sub_emp_getAllParameters(struct T_emp *emp) { uint8_t leng, data[66], ii, pp; epi_restoreEmpSettings(&leng, data); // expected length = 64 byte // get 64 bytes about EMP: see h-file emp->gotSetup = data[0]; emp->state = data[1]; emp->shaft = data[2]; emp->countryCode= uchar2uint(data[4], data[3]); emp->scale = data[5]; emp->decimals = data[6]; for (ii=0; ii<16; ii++) emp->coinValues[ii] = data[7+ii]; emp->coinAccept = uchar2uint(data[24], data[23]); emp->tokenChannel = data[25]; emp->pollingRunning = data[26]; emp->paymentRunning = data[27]; pp=28; for (ii=0; ii<16; ii++) { emp->denomination[ii] = uchar2uint(data[pp+1], data[pp]); pp+=2; } emp->routing= uchar2uint(data[61], data[60]); } void T_runProc::changer_getAllParameters(struct T_changer *mw) { // requested automatically with 23, same like EMP uint8_t leng, data[66], pp, nn; epi_restoreEmpSettings(&leng, data); // expected length = 64 byte // get 64 bytes about Changer (mw), see interfaces.h-file mw->setup = data[0]; mw->state = data[1]; mw->level = data[2]; mw->countryCode = uchar2uint(data[4], data[3]); mw->scale = data[5]; mw->decimals= data[6]; for (nn=0; nn<16; nn++) mw->coinSetup[nn]= data[nn+7]; // 7...22 mw->intendedAcceptance = uchar2uint(data[24], data[23]); mw->tokenChannel= data[25]; mw->pollingRunning= data[26]; mw->paymentRunning= data[27]; pp=28; for (nn=0; nn<16; nn++) { mw->denomination[nn] = uchar2uint(data[pp+1], data[pp]); pp+=2; } // bis pp=60 mw->availableTubes = uchar2uint(data[61], data[60]); } void T_runProc::sub_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) { uint16_t LL, nn; char *start; uint8_t buf[70], leng; epi_restoreDynMachineConditions(&leng, buf); // Puffer in struct eintragen: LL=sizeof(struct T_dynamicCondition); start = &dynMachCond->allDoorsDebounced; nn=0; do { *start = buf[nn]; start++; } while(++nnkindOfPrinter; nn=0; do { *start = buf[nn]; start++; } while(++nn16000)) // 8...16V erlaubt return false; // Fehler if ((myDynMachCond.Temperatur<40) || (myDynMachCond.Temperatur>260)) // -30°C...80°C erleubt return false; // Fehler uctmp=(hwapi_lastDoorState & 1); // 0: upper door is closed if (uctmp==0 && myDynMachCond.upperDoor>0) { hwapi_lastDoorState |= 1; qCritical()<<"hwapi emitting signal ServiceDoorOpened"; emit runProc_doorServiceDoorOpened(); } uctmp=(hwapi_lastDoorState & 2); if (uctmp==0 && myDynMachCond.middleDoor>0) { hwapi_lastDoorState |= 2; qCritical()<<"hwapi emitting signal VaultDoorOpened "; emit runProc_doorVaultDoorOpened(); } uctmp=(hwapi_lastDoorState & 4); if (uctmp==0 && myDynMachCond.lowerDoor>0) { hwapi_lastDoorState |= 4; qCritical()<<"hwapi emitting signal ServiceDoorOpened (Batt)"; emit runProc_doorServiceDoorOpened(); } uctmp=(hwapi_lastDoorState & 8); // 0: cash box was in if (uctmp==0 && myDynMachCond.CBinDebounced==0) // 0:fehlt 1:drin { // wurde gerade entnommen hwapi_lastDoorState |= 8; qCritical()<<"hwapi emitting signal CoinBoxRemoved "; emit runProc_doorCoinBoxRemoved(); } uctmp=(hwapi_lastDoorState & 8); if (uctmp>0 && myDynMachCond.CBinDebounced>0) // 0:fehlt 1:drin { // war draussen, ist wieder drin hwapi_lastDoorState &= ~0x08; qCritical()<<"hwapi emitting signal CoinBoxInserted"; emit runProc_doorCoinBoxInserted(); } uctmp=(hwapi_lastDoorState & 0x07); doorTemp=0; if (myDynMachCond.upperDoor>0) doorTemp |=1; if (myDynMachCond.middleDoor>0) doorTemp |=2; if (myDynMachCond.lowerDoor>0) doorTemp |=4; if (uctmp>0 && doorTemp==0) // vorher war mind. EINE Tuer offen UND jetzt sind alle zu { hwapi_lastDoorState &= ~0x07; // soeben wurde die letzte Tür geschlossen, prüfe ob Kasse eingesetzt wurde: if (myDynMachCond.CBinDebounced) { qCritical()<<"hwapi emitting signal CBinAndAllDoorsClosed"; emit runProc_doorCBinAndAllDoorsClosed(); hwapi_lastDoorState &=~0x08; // keine Wirkung } else { qCritical()<<"hwapi emitting signal AllDoorsClosed"; emit runProc_doorAllDoorsClosed(); } } return true; } uint8_t T_runProc::prn_getHwState(struct Tprn_hw_state *prn_hw_state) { // return printer hardware state: power is on? rs-driver on? rs_switch ok? hw-ready-line ok? // printer on error or ok? uint8_t prnHWstate[20]; epi_restorePrinterState(prnHWstate); // byte 1...6 come right from printer, see printer manual // byte 0 = all important infos: // byte 0 = 0: prnter OK, >0: error // bit0: paper low 1: no paper 2: temperature error // 3: head open 4: paper jam in cutter // 6: no response 7: bad response from printer prn_hw_state->powerRdBk = epi_getDI_printerPwr(); prn_hw_state->rsSwOk = epi_getDO_serialMux1isSetToPrinter(); // mux1 off: serial is switched to printer prn_hw_state->rsDrvOk = epi_getDO_serialDriverIsOn(); prn_hw_state->ReadyLine = epi_getDI_prnReady(); if (prnHWstate[0]==0) prn_hw_state->inIdle = true; // no errors else prn_hw_state->inIdle = false; // off or errors if (prnHWstate[0] & 1) prn_hw_state->paperNearEnd=true; else prn_hw_state->paperNearEnd = false; if (prnHWstate[0] & 2) prn_hw_state->noPaper=true; else prn_hw_state->noPaper = false; if (prnHWstate[0] & 4) prn_hw_state->ErrorTemp=true; else prn_hw_state->ErrorTemp = false; if (prnHWstate[0] & 8) prn_hw_state->HeadOpen=true; else prn_hw_state->HeadOpen = false; if (prnHWstate[0] & 16) prn_hw_state->cutterJam=true; else prn_hw_state->cutterJam = false; if (prnHWstate[0] & 64) prn_hw_state->noResponse=true; else prn_hw_state->noResponse = false; if (prnHWstate[0] & 128) prn_hw_state->badResponse=true; else prn_hw_state->badResponse = false; return prnHWstate[0]; } void T_runProc::dc_autoRequest(bool on) { // automatically request ALL digital and analog sensors, get time/date, get status information epi_startEmmision(on); } void T_runProc::bl_rebootDC(void) { // send command to normal DC-Program requesting a restart // BL is working for 5s after power-on-reset. uint8_t len, buf[20]; len=dcBL_restartDC(buf); sendWRcmd_setSendBlock160(len, buf); } void T_runProc::bl_startBL(void) { // use this function within the first 5s after reboot to startup the BL, // otherwise the BL jumps to normal DC application uint8_t len, buf[20]; len=dcBL_activatBootloader(buf); sendWRcmd_setSendBlock160(len, buf); epi_setNowIsBootload(true); } void T_runProc::bl_checkBL(void) { // call this function in order to get information, afterwards use "bl_isUp()" uint8_t len, buf[20]; len=dcBL_readFWversion(buf); sendWRcmd_setSendBlock160(len, buf); } bool T_runProc::bl_isUp(void) { uint8_t receivedData[160]; uint8_t LL, nn; for (nn=0; nn<160; nn++) receivedData[nn]=0; LL=epi_getRawRecLength(); if (LL>0) { epi_getRawReceivedData(receivedData); // response to "readFWversion" if (receivedData[0]==2 && receivedData[1]==146 && receivedData[2]==45 && receivedData[3]==45 && receivedData[4] ==95 && receivedData[5]==176) { qDebug() << "got BL response to readFWversion"; epi_clrRawReceivedString(); return true; } // response to "start BL" if (receivedData[0]==2 && receivedData[1]==101 && receivedData[2]==48 && receivedData[3]==223 && receivedData[4] ==131 ) { qDebug() << "hwapi_bl_isUp: got BL response to start"; epi_clrRawReceivedString(); return true; } } return false; } void T_runProc::bl_completeStart(void) { bl_startupStep=1; } bool T_runProc::bl_performComplStart(void) { // must be called cyclic by timer static uint8_t retryCtr; if ((bl_startupStep<1) || (bl_startupStep>10)) return false; if (bl_startupStep==1) { dc_autoRequest(false); bl_startupStep++; } else if (bl_startupStep==2) { bl_rebootDC(); hwapi_triggerBL->stop(); hwapi_triggerBL->start(1000); // call next step in 1s retryCtr=0; bl_startupStep++; } else if (bl_startupStep==3) { //qDebug()<<"starting BL"; bl_startBL(); hwapi_triggerBL->stop(); hwapi_triggerBL->start(100); bl_startupStep++; } else if (bl_startupStep==4) { //if (!myTO->isActive()) //{ bl_checkBL(); hwapi_triggerBL->stop(); hwapi_triggerBL->start(100); bl_startupStep++; //} } else if (bl_startupStep==5) { hwapi_triggerBL->stop(); if (bl_isUp()) { bl_startupStep=99; // BL is up and running } else { retryCtr++; // start again if (retryCtr>=15) { bl_startupStep=99; //qDebug()<<"BL error!!!"; } else { bl_startupStep=3; //qDebug()<<"BL retry..."; } } } return true; }