#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::E002; if (modCond.printer==200 || modCond.printer==201) // 200: not connected 201: printer-HW-error 202: no paper return DeviceController::State::E020; if (modCond.printer==202) return DeviceController::State::E018; if (modCond.coinBlocker>=200) return DeviceController::State::E025; if (modCond.mdbBus>=200) return DeviceController::State::E034; if (modCond.intEe>=200) return DeviceController::State::E011; if (devPara.kindOfCoinChecker==1 || devPara.kindOfCoinChecker==2) // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW) { if (modCond.coinEscrow>=200) { return DeviceController::State::E010; } if (modCond.coinSafe==201) // full { return DeviceController::State::E007; } if (modCond.coinSafe==200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok { return DeviceController::State::E009; } } else if (devPara.kindOfCoinChecker==3) { if (modCond.changer>=200) { // Fehler Münzver. return DeviceController::State::E026; } if (modCond.coinSafe==201) // full { return DeviceController::State::E007; } if (modCond.coinSafe == 200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok { return 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.onAlarm>0) return DeviceController::State::A000; if (dynMaCond.modeAbrech>0) return DeviceController::State::E011; if (dynMaCond.nowCardTest>0) return DeviceController::State::E072; if (dynMaCond.startupTestIsRunning>0) return DeviceController::State::E073; if (modCond.voltage>=200) return DeviceController::State::E003; if (modCond.temper>=200) return DeviceController::State::E004; // check for warnings if (modCond.printer>=100 && modCond.printer<200) return DeviceController::State::W001; if (modCond.coinSafe>=100 && modCond.coinSafe<200) return DeviceController::State::W002; if (modCond.voltage>=100 && modCond.voltage<200) return DeviceController::State::W003; if (modCond.temper>=100 && modCond.temper<200) return DeviceController::State::W004; return DeviceController::State::O000; } DeviceController::State DeviceControllerDiag::sys_getSystemErrors() { 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; } 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: // 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); }