502 lines
16 KiB
C++
502 lines
16 KiB
C++
#include "DeviceControllerDiag.h"
|
|
|
|
#include <QCoreApplication>
|
|
#include <QMetaEnum>
|
|
#include <QUuid>
|
|
#include <QDebug>
|
|
|
|
DeviceControllerDiag::DeviceControllerDiag(QObject *parent)
|
|
: QObject(parent)
|
|
, coinProcessorType(nsDeviceControllerInterface::COIN_PROCESSOR::ESCROW)
|
|
, billAcceptor(nsDeviceControllerInterface::BILL_ACCEPTOR::NO)
|
|
, 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);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
switch (devPara.kindOfCoinChecker) {
|
|
case 1:
|
|
case 2:
|
|
this->coinProcessorType = nsDeviceControllerInterface::COIN_PROCESSOR::ESCROW;
|
|
break;
|
|
case 3:
|
|
this->coinProcessorType = nsDeviceControllerInterface::COIN_PROCESSOR::CHANGER;
|
|
break;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
switch (devPara.BillAcceptor) {
|
|
case 0:
|
|
this->billAcceptor = nsDeviceControllerInterface::BILL_ACCEPTOR::NO;
|
|
break;
|
|
default:
|
|
this->billAcceptor = nsDeviceControllerInterface::BILL_ACCEPTOR::YES;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
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<DeviceController::State>().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<DeviceController::State>().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);
|
|
|
|
}
|
|
|
|
|