#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_finishedDiag(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_finishedDiag(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_finishedDiag(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_finishedDiag(DeviceController::State::E253); return; } if (dynMaCond.middleDoor) { // vault door is open, goto INTRUSION MODE qCritical() << "DeviceControllerDiag::sys_superviseSystem() vault door is open, goto INTRUSION MODE"; this->private_finishedDiag(DeviceController::State::E252); return; } qCritical() << " --> call sub_componentAssessment()"; DeviceController::State proposedError = sub_componentAssessment(); this->private_finishedDiag(proposedError); } DeviceController::State DeviceControllerDiag::sub_componentAssessment() { // this function decides if vending mode is possible, independant from door // return >0 in case of error 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 invalid states: if (modCond.rtc>=200) return DeviceController::State::E001; if (modCond.printer==200 || modCond.printer==201) // 200: not connected 201: printer-HW-error 202: no paper return DeviceController::State::E002; if (modCond.printer==202) return DeviceController::State::E003; if (modCond.coinBlocker>=200) return DeviceController::State::E004; if (modCond.mdbBus>=200) return DeviceController::State::E005; if (modCond.intEe>=200) return DeviceController::State::E006; if (devPara.kindOfCoinChecker==1 || devPara.kindOfCoinChecker==2) // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW) { if (modCond.coinChecker>=200 || modCond.coinEscrow>=200) { // Fehler Münzver. return DeviceController::State::E007; } if (modCond.coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok { return DeviceController::State::E008; } } else if (devPara.kindOfCoinChecker==3) { if (modCond.changer>=200) { // Fehler Münzver. return DeviceController::State::E007; } if (modCond.coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok { return DeviceController::State::E008; } } if ( modCond.billReader>=200 && devPara.BillAcceptor>0) { // Fehler BNA return DeviceController::State::E009; } if (dynMaCond.onAlarm>0) return DeviceController::State::E010; if (dynMaCond.modeAbrech>0) return DeviceController::State::E011; if (dynMaCond.nowCardTest>0) return DeviceController::State::E012; if (dynMaCond.startupTestIsRunning>0) return DeviceController::State::E013; if (modCond.voltage>=200) return DeviceController::State::E014; if (modCond.temper>=200) return DeviceController::State::E015; // check for warnings return DeviceController::State::O000; } DeviceController::State DeviceControllerDiag::sys_getSystemErrors() { // 0: everything fine 1..15: errors /* 1: real time clock error 2: printer error 3: no paper 4: coin blocker 5: mdb error 6: mem error int.ee. 7: error coin validator 8: coin safe missed or full 9: bill acceptor error 10: alarm / intrusion 11: cash box change is ongoing 12: card test running 13: startup-test is running 14: voltage error 15: temperature error */ return this->sub_componentAssessment(); } /** * @brief DeviceControllerDiag::private_finishedDiag * @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_finishedDiag(DeviceController::State result) { this->diagRequestTimeoutTimer->stop(); this->isRequestRunning = false; this->flagInterruptDiag = false; qCritical() << "DeviceControllerDiag::private_finishedDiag() result: " << result; if (this->eventReceiver == nullptr) { qCritical() << "DeviceControllerDiag: no eventReceiver"; return; } // Errors are in this range 1...15: 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::E001: // real time clock error eventClass = EVENT_CLASS::ERROR; parameter = "real time clock error"; break; case DeviceController::State::E002: // printer error eventClass = EVENT_CLASS::ERROR; parameter = "printer error"; break; case DeviceController::State::E003: // no paper eventClass = EVENT_CLASS::ERROR; parameter = "no paper"; break; case DeviceController::State::E004: // coin blocker eventClass = EVENT_CLASS::ERROR; parameter = "coin blocker"; break; case DeviceController::State::E005: // mdb error eventClass = EVENT_CLASS::ERROR; parameter = "mdb error"; break; case DeviceController::State::E006: // mem error int.ee. eventName = "E006"; eventClass = EVENT_CLASS::ERROR; parameter = "mem error int.ee."; break; case DeviceController::State::E007: // error coin validator eventClass = EVENT_CLASS::ERROR; parameter = "error coin validator"; break; case DeviceController::State::E008: // coin safe missed or full eventClass = EVENT_CLASS::ERROR; parameter = "coin safe missed or full"; break; case DeviceController::State::E009: // bill acceptor error eventClass = EVENT_CLASS::ERROR; parameter = "bill acceptor error"; break; case DeviceController::State::E010: // alarm / intrusion eventClass = EVENT_CLASS::ALARM; parameter = "alarm / intrusion"; break; case DeviceController::State::E011: // cash box change is ongoing eventClass = EVENT_CLASS::STATE; parameter = "cash box change is ongoing"; break; case DeviceController::State::E012: // card test running eventClass = EVENT_CLASS::STATE; parameter = "card test running"; break; case DeviceController::State::E013: // startup-test is running eventClass = EVENT_CLASS::STATE; parameter = "startup-test is running"; break; case DeviceController::State::E014: // voltage error eventClass = EVENT_CLASS::ERROR; parameter = "voltage error"; break; case DeviceController::State::E015: // temperature error eventClass = EVENT_CLASS::STATE; parameter = "temperature error"; break; case DeviceController::State::E252: // oper door / lower door open eventClass = EVENT_CLASS::STATE; parameter = "oper door / lower door open"; break; case DeviceController::State::E253: // cash box door open eventClass = EVENT_CLASS::STATE; parameter = "cash box 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 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); }