From 6a19fd7608182675b49d22dfcead876349f996cf Mon Sep 17 00:00:00 2001 From: Siegfried Siegert Date: Thu, 22 Jun 2023 08:44:16 +0200 Subject: [PATCH] Add class DeviceControllerDiag to supervise DeviceController state --- DCPlugin.pro | 2 + src/ATBAPP/ATBDeviceControllerPlugin.h | 5 + src/ATBAPP/DeviceControllerDiag.cpp | 373 +++++++++++++++++++++++++ src/ATBAPP/DeviceControllerDiag.h | 49 ++++ 4 files changed, 429 insertions(+) create mode 100644 src/ATBAPP/DeviceControllerDiag.cpp create mode 100644 src/ATBAPP/DeviceControllerDiag.h diff --git a/DCPlugin.pro b/DCPlugin.pro index d1abb70..8c31421 100644 --- a/DCPlugin.pro +++ b/DCPlugin.pro @@ -71,6 +71,7 @@ DEFINES += QT_DEPRECATED_WARNINGS HEADERS += \ include/interfaces.h \ src/ATBAPP/ATBAPPplugin.h \ + src/ATBAPP/DeviceControllerDiag.h \ src/ATBAPP/DeviceControllerInterface.h \ src/ATBAPP/ATBHealthEvent.h \ src/ATBAPP/ATBMachineEvent.h \ @@ -81,6 +82,7 @@ SOURCES += \ src/ATBAPP/ATBHealthEvent.cpp \ src/ATBAPP/ATBMachineEvent.cpp \ src/ATBAPP/ATBDeviceControllerPlugin.cpp \ + src/ATBAPP/DeviceControllerDiag.cpp \ src/ATBAPP/Utils.cpp DISTFILES += \ diff --git a/src/ATBAPP/ATBDeviceControllerPlugin.h b/src/ATBAPP/ATBDeviceControllerPlugin.h index 4022b6c..3db8941 100644 --- a/src/ATBAPP/ATBDeviceControllerPlugin.h +++ b/src/ATBAPP/ATBDeviceControllerPlugin.h @@ -5,6 +5,8 @@ #include "src/ATBAPP/DeviceControllerInterface.h" #include "src/ATBAPP/ATBAPPplugin.h" +#include "src/ATBAPP/DeviceControllerDiag.h" + #include "version.h" @@ -94,6 +96,9 @@ private: hwinf* hw; + DeviceControllerDiag* diag; + + QTextCodec *codec; bool private_loadCashAgentLib(QString pluginName); diff --git a/src/ATBAPP/DeviceControllerDiag.cpp b/src/ATBAPP/DeviceControllerDiag.cpp new file mode 100644 index 0000000..ce6035e --- /dev/null +++ b/src/ATBAPP/DeviceControllerDiag.cpp @@ -0,0 +1,373 @@ +#include "DeviceControllerDiag.h" + +#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(0xff); + return; + } + + bool result; + result = hw->sys_areDCdataValid(); + + if (result) { + QTimer::singleShot(200, this, &DeviceControllerDiag::sys_superviseSystem); + } + else { + qCritical() << "DeviceControllerDiag::private_startDiag() DCdata is not valid"; + + + this->private_finishedDiag(0xfe); + + // try it again + // -> this results in a seg. fault after ~10 loops! + //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=0; + struct T_moduleCondition *modCond=0; + + // check for DiagRequestTimeoutTimerTimeout: + if (this->flagInterruptDiag) { + qCritical() << "DeviceControllerDiag::sys_superviseSystem() interrupted!"; + this->private_finishedDiag(0xff); + return; + } + + if (!hw->sys_areDCdataValid()) + { + // es gibt keinerlei gültige Daten vom DC + qCritical() << "DeviceControllerDiag::sys_superviseSystem() no valid data!"; + this->private_finishedDiag(0xfe); + return; + } + + // jetzt sind die DC-Daten aktuell, also reinholen: + hw->sys_getDynMachineConditions(dynMaCond); + hw->sys_getDeviceConditions(modCond); + + if (!modCond->allModulesChecked) + { + // noch keine Testergebnisse + if (dynMaCond->startupTestIsRunning) { + // TODO? + } + + 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(0xFD); + 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(0xFE); + return; + } + + uint8_t proposedError = sub_componentAssessment(); + if (proposedError) { + // All doors are closed but errors found, goto OOO MODE (out-of-order) + qCritical() << "DeviceControllerDiag::sys_superviseSystem() All doors are closed but errors found, goto OOO MODE (out-of-order)"; + this->private_finishedDiag(proposedError); + return; + } + + // everything fine + qCritical() << "DeviceControllerDiag::sys_superviseSystem() everything fine"; + this->private_finishedDiag(0x00); +} + + + +uint8_t DeviceControllerDiag::sub_componentAssessment() +{ + // this function decides if vending mode is possible, independant from door + // return >0 in case of error + + struct T_moduleCondition *modCond=0; + hw->sys_getDeviceConditions(modCond); + + struct T_dynamicCondition *dynMaCond=0; + hw->sys_getDynMachineConditions(dynMaCond); + + struct T_devices *devPara=0; + if (modCond->rtc>=200) + return 1; + if (modCond->printer==200 || modCond->printer==201) // 200: not connected 201: printer-HW-error 202: no paper + return 2; + if (modCond->printer==202) + return 3; + + if (modCond->coinBlocker>=200) + return 4; + if (modCond->mdbBus>=200) + return 5; + if (modCond->intEe>=200) + return 6; + + 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 7; + } + if (modCond->coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok + { + return 8; + } + } else + if (devPara->kindOfCoinChecker==3) + { + if (modCond->changer>=200) + { + // Fehler Münzver. + return 7; + } + if (modCond->coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok + { + return 8; + } + } + + if ( modCond->billReader>=200 && devPara->BillAcceptor>0) + { + // Fehler BNA + return 9; + } + + if (dynMaCond->onAlarm>0) + return 10; + + if (dynMaCond->modeAbrech>0) + return 11; + + if (dynMaCond->nowCardTest>0) + return 12; + + if (dynMaCond->startupTestIsRunning>0) + return 13; + + if (modCond->voltage>=200) + return 14; + if (modCond->temper>=200) + return 15; + + return 0; +} + + +uint8_t 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()', + * - 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(uint8_t result) +{ + this->diagRequestTimeoutTimer->stop(); + this->isRequestRunning = false; + this->flagInterruptDiag = false; + + if (result == 0) return; + + qCritical() << "DeviceControllerDiag::private_finishedDiag() result: " << result; + + + if (this->eventReceiver == nullptr) { + qCritical() << "DeviceControllerDiag: no eventReceiver"; + return; + } + + if (result > 15 && result != 0xFE) return; + + + // Errors are in this range 1...15: + QString eventId = QUuid::createUuid().toString(QUuid::WithoutBraces).mid(0, 8); + QString eventName; + EVENT_CLASS eventClass = EVENT_CLASS::STATE; + QString parameter; + switch (result) { + case 1: // real time clock error + eventName = "E001"; + eventClass = EVENT_CLASS::ERROR; + parameter = "real time clock error"; + break; + case 2: // printer error + eventName = "E002"; + eventClass = EVENT_CLASS::ERROR; + parameter = "printer error"; + break; + case 3: // no paper + eventName = "E003"; + eventClass = EVENT_CLASS::ERROR; + parameter = "no paper"; + break; + case 4: // coin blocker + eventName = "E004"; + eventClass = EVENT_CLASS::ERROR; + parameter = "coin blocker"; + break; + case 5: // mdb error + eventName = "E005"; + eventClass = EVENT_CLASS::ERROR; + parameter = "mdb error"; + break; + case 6: // mem error int.ee. + eventName = "E006"; + eventClass = EVENT_CLASS::ERROR; + parameter = "mem error int.ee."; + break; + case 7: // error coin validator + eventName = "E007"; + eventClass = EVENT_CLASS::ERROR; + parameter = "error coin validator"; + break; + case 8: // coin safe missed or full + eventName = "E008"; + eventClass = EVENT_CLASS::ERROR; + parameter = "coin safe missed or full"; + break; + case 9: // bill acceptor error + eventName = "E009"; + eventClass = EVENT_CLASS::ERROR; + parameter = "bill acceptor error"; + break; + case 10: // alarm / intrusion + eventName = "E010"; + eventClass = EVENT_CLASS::ERROR; + parameter = "alarm / intrusion"; + break; + case 11: // cash box change is ongoing + eventName = "E011"; + eventClass = EVENT_CLASS::STATE; + parameter = "cash box change is ongoing"; + break; + case 12: // card test running + eventName = "E012"; + eventClass = EVENT_CLASS::STATE; + parameter = "card test running"; + break; + case 13: // startup-test is running + eventName = "E013"; + eventClass = EVENT_CLASS::STATE; + parameter = "startup-test is running"; + break; + case 14: // voltage error + eventName = "E014"; + eventClass = EVENT_CLASS::ERROR; + parameter = "voltage error"; + break; + case 15: // temperature error + eventName = "E015"; + eventClass = EVENT_CLASS::STATE; + parameter = "temperature error"; + break; + case 0xFE: // no valid data from DeviceController + eventName = "E254"; + eventClass = EVENT_CLASS::STATE; + parameter = "no valid data from DeviceController"; + break; + } + + + ATBMachineEvent *machineEvent = new ATBMachineEvent( + eventId, + "DC", + eventClass, + eventName, + 1, + parameter, + "" // second level info + ); + + //emit diagResponse(machineEvent); + + QCoreApplication::postEvent(eventReceiver, machineEvent); + +} diff --git a/src/ATBAPP/DeviceControllerDiag.h b/src/ATBAPP/DeviceControllerDiag.h new file mode 100644 index 0000000..f09bf6f --- /dev/null +++ b/src/ATBAPP/DeviceControllerDiag.h @@ -0,0 +1,49 @@ +#ifndef DEVICECONTROLLERDIAG_H +#define DEVICECONTROLLERDIAG_H + +#include +#include + +#include "ATBMachineEvent.h" +#include "interfaces.h" + +class DeviceControllerDiag : public QObject +{ + Q_OBJECT + +public: + DeviceControllerDiag(QObject *parent = nullptr); + + void init(hwinf* hw, QObject* eventReceiver); + +public slots: + void diagRequest(); + +signals: + void diagResponse(ATBMachineEvent* machineEvent); + + +private: + QObject *eventReceiver; + hwinf* hw; + + bool isRequestRunning; + bool flagInterruptDiag; + + QTimer *diagRequestTimeoutTimer; + + uint8_t sub_componentAssessment(); + uint8_t sys_getSystemErrors(); + +private slots: + void onDiagRequestTimeoutTimerTimeout(); + + void private_startDiag(); // diag entry method + void private_finishedDiag(uint8_t result); // diag exit method + + void sys_superviseSystem(); + + +}; + +#endif // DEVICECONTROLLERDIAG_H