#include "DeviceControllerDiag.h" #include #include #include #include DeviceControllerDiag::DeviceControllerDiag(QObject *parent) : QObject(parent) , eventReceiver(nullptr) , isRequestRunning(false) , flagInterruptDiag(false) { diagRequestTimeoutTimer = new QTimer(this); diagRequestTimeoutTimer->setInterval(1000*20); // 20s diagRequestTimeoutTimer->setSingleShot(true); connect(diagRequestTimeoutTimer, &QTimer::timeout, this, &DeviceControllerDiag::onDiagRequestTimeoutTimerTimeout); } void DeviceControllerDiag::init(hwinf *hw, QObject* eventReceiver) { this->hw = hw; this->eventReceiver = eventReceiver; // make a system check on startup: QTimer::singleShot(2000, this, &DeviceControllerDiag::diagRequest); } void DeviceControllerDiag::diagRequest() { qCritical() << "DeviceControllerDiag::diagRequest()"; if (this->isRequestRunning) { qCritical() << "DeviceControllerDiag::diagRequest() is already running"; return; } this->isRequestRunning = true; this->diagRequestTimeoutTimer->start(); this->private_startDiag(); } void DeviceControllerDiag::onDiagRequestTimeoutTimerTimeout() { qCritical() << "DeviceControllerDiag::onDiagRequestTimeoutTimerTimeout()"; this->flagInterruptDiag = true; } void DeviceControllerDiag::private_startDiag() { // check for DiagRequestTimeoutTimerTimeout: if (this->flagInterruptDiag) { qCritical() << "DeviceControllerDiag::private_startDiag() interrupted!"; this->private_sendDiagEvent(DeviceController::State::E255); return; } bool result; result = hw->sys_areDCdataValid(); if (result) { qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is valid"; QTimer::singleShot(200, this, &DeviceControllerDiag::sys_superviseSystem); } else { qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is +++not+++ valid"; // try it again QTimer::singleShot(200, this, &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; qCritical() << " sys_superviseSystem()"; // check for DiagRequestTimeoutTimerTimeout: if (this->flagInterruptDiag) { qCritical() << "DeviceControllerDiag::sys_superviseSystem() interrupted!"; this->private_sendDiagEvent(DeviceController::State::E255); return; } if (!hw->sys_areDCdataValid()) { // es gibt keinerlei gültige Daten vom DC qCritical() << "DeviceControllerDiag::sys_superviseSystem() no valid data!"; this->private_sendDiagEvent(DeviceController::State::E254); return; } // jetzt sind die DC-Daten aktuell, also reinholen: hw->sys_getDynMachineConditions(&dynMaCond); hw->sys_getDeviceConditions(&modCond); qCritical() << "DeviceControllerDiag::sys_superviseSystem() get condition data"; if (!modCond.allModulesChecked) { // noch keine Testergebnisse if (dynMaCond.startupTestIsRunning) { // TODO? } qCritical() << " allModulesChecked is false --> call again"; QTimer::singleShot(200, this, &DeviceControllerDiag::sys_superviseSystem); 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()"; sub_componentAssessment(); } void DeviceControllerDiag::sub_componentAssessment() { bool flag_sendOperate = true; struct T_moduleCondition modCond; hw->sys_getDeviceConditions(&modCond); struct T_dynamicCondition dynMaCond; hw->sys_getDynMachineConditions(&dynMaCond); struct T_devices devPara; hw->sys_restoreDeviceParameter(&devPara); // store some interesting results: // -> voltage: uint32_t voltage = hw->dc_getVoltage(); emit newVoltage(voltage); // check for alarm: if (dynMaCond.onAlarm>0) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::A000); } // check for invalid states: if (modCond.rtc>=200) { flag_sendOperate = false; this->private_sendDiagEvent(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); } if (modCond.printer==202) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E018); } if (modCond.coinBlocker>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E025); } if (modCond.mdbBus>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E034); } if (modCond.intEe>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E011); } // 2023-07-26: workaround for 00281/Szeged -------------------------------------------------------------- // because we need certain errors and we do get for 'kindOfCoinChecker' -> 16 ! qCritical() << "-----------diag: kindOfCoinChecker = " << devPara.kindOfCoinChecker; qCritical() << " modCond.coinSafe = " << modCond.coinSafe; if (devPara.kindOfCoinChecker > 0) { if (modCond.coinSafe==201) { // full flag_sendOperate = false; this->private_sendDiagEvent(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); } if (modCond.coinEscrow>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E010); } } // ----------------------------------------------------------------------------------------------- if (devPara.kindOfCoinChecker==1 || devPara.kindOfCoinChecker==2) // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW) { if (modCond.coinEscrow>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E010); } if (modCond.coinSafe==201) { // full flag_sendOperate = false; this->private_sendDiagEvent(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); } } else if (devPara.kindOfCoinChecker==3) { if (modCond.changer>=200) { // Fehler Münzver. flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E026); } if (modCond.coinSafe==201) { // full flag_sendOperate = false; this->private_sendDiagEvent(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); } } /* if ( modCond.billReader>=200 && devPara.BillAcceptor>0) { if (modCond.billReader == 200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok { return TODO; } if (modCond.billReader == 201) // 200: kasse fehlt 201: voll 100:fast voll 1:ok { return TODO; } } */ if (dynMaCond.modeAbrech>0) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E011); } if (dynMaCond.nowCardTest>0) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E072); } if (dynMaCond.startupTestIsRunning>0) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E073); } if (modCond.voltage>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E003); } if (modCond.temper>=200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::E004); } // check for warnings if (modCond.printer>=100 && modCond.printer<200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::W001); } if (modCond.coinSafe>=100 && modCond.coinSafe<200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::W002); } if (modCond.voltage>=100 && modCond.voltage<200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::W003); } if (modCond.temper>=100 && modCond.temper<200) { flag_sendOperate = false; this->private_sendDiagEvent(DeviceController::State::W004); } if (flag_sendOperate) { this->private_sendDiagEvent(DeviceController::State::O000); } // finish diag this->diagRequestTimeoutTimer->stop(); this->isRequestRunning = false; this->flagInterruptDiag = false; } /** * @brief DeviceControllerDiag::private_sendDiagEvent * @param result - result value from 'sub_componentAssessment()', * - 0x00 everything is fine * - 0xFF on timer interrupt * - 0xFE no valid data from DeviceController * - 0xFD Service or battery door is open * - 0xFE vault door is open */ void DeviceControllerDiag::private_sendDiagEvent(DeviceController::State result) { qCritical() << "DeviceControllerDiag::private_sendDiagEvent() 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); } QString eventId = QUuid::createUuid().toString(QUuid::WithoutBraces).mid(0, 8); QString eventName = QMetaEnum::fromType().valueToKey(result);; EVENT_CLASS eventClass = EVENT_CLASS::STATE; QString parameter; switch (result) { case DeviceController::State::A000: // alarm / intrusion eventClass = EVENT_CLASS::ALARM; parameter = "alarm / intrusion"; break; case DeviceController::State::E002: // real time clock error eventClass = EVENT_CLASS::ERROR; parameter = "real time clock error"; break; case DeviceController::State::E003: // voltage error eventClass = EVENT_CLASS::ERROR; parameter = "voltage error"; break; case DeviceController::State::E004: // temperature error eventClass = EVENT_CLASS::ERROR; parameter = "temperature error"; break; case DeviceController::State::E007: // coin safe full eventClass = EVENT_CLASS::ERROR; parameter = "coin safe full"; break; case DeviceController::State::E008: // bill acceptor full eventClass = EVENT_CLASS::ERROR; parameter = "bill acceptor full"; break; case DeviceController::State::E009: // no cash box eventClass = EVENT_CLASS::ERROR; parameter = "no cash box"; break; case DeviceController::State::E010: // coin escrow eventClass = EVENT_CLASS::ERROR; parameter = "coin escrow"; break; case DeviceController::State::E011: // mem error int.ee. eventClass = EVENT_CLASS::ERROR; parameter = "mem error int.ee."; break; case DeviceController::State::E018: // no paper eventClass = EVENT_CLASS::ERROR; parameter = "no paper"; break; case DeviceController::State::E020: // printer error eventClass = EVENT_CLASS::ERROR; parameter = "printer error"; break; case DeviceController::State::E025: // coin blocker eventClass = EVENT_CLASS::ERROR; parameter = "coin blocker"; break; case DeviceController::State::E026: // error coin validator eventClass = EVENT_CLASS::ERROR; parameter = "error coin validator"; break; case DeviceController::State::E034: // mdb error eventClass = EVENT_CLASS::ERROR; parameter = "mdb error"; break; case DeviceController::State::E071: // cash box change is ongoing eventClass = EVENT_CLASS::STATE; parameter = "cash box change is ongoing"; break; case DeviceController::State::E072: // card test running eventClass = EVENT_CLASS::STATE; parameter = "card test running"; break; case DeviceController::State::E073: // startup-test is running eventClass = EVENT_CLASS::STATE; parameter = "startup-test is running"; break; case DeviceController::State::E252: // cash box door open eventClass = EVENT_CLASS::STATE; parameter = "cash box door open"; break; case DeviceController::State::E253: // 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 eventClass = EVENT_CLASS::STATE; parameter = "no valid data from DeviceController"; break; case DeviceController::State::E255: // no valid data from DeviceController eventClass = EVENT_CLASS::STATE; parameter = ""; qCritical() << " ... ignore " << QMetaEnum::fromType().valueToKey(result); return; break; case DeviceController::State::O000: // everything is fine this->machineEventSet.clear(); eventClass = EVENT_CLASS::OPERATE; parameter = ""; qCritical() << " ... everything fine"; break; case DeviceController::State::W001: // paper low eventClass = EVENT_CLASS::WARNING; parameter = "paper low"; break; case DeviceController::State::W002: // cashbox almost full eventClass = EVENT_CLASS::WARNING; parameter = "cashbox almost full"; break; case DeviceController::State::W003: // voltage low eventClass = EVENT_CLASS::WARNING; parameter = "voltage low"; break; case DeviceController::State::W004: // temperatur warning eventClass = EVENT_CLASS::WARNING; parameter = "temperatur warning"; break; } ATBMachineEvent *machineEvent = new ATBMachineEvent( eventId, "DC", eventClass, eventName, 1, parameter, "" // second level info ); //emit diagResponse(machineEvent); QCoreApplication::postEvent(eventReceiver, machineEvent); }