/** * Controler interface for the DMF vehicle terminal * $Id$ * $HeadURL$ * $Author$ * Created by Florian Schult, NLSE, 2018-06-06 */ #include "control_unit_handler.h" #include "connection_handler.h" namespace EffectShowClient { ControlUnitHandler::ControlUnitHandler(QObject *parent) : QObject(parent) , m_connectionHandler(new ConnectionHandler(this)) , m_timer(new QTimer(this)) , m_feature(EffectShowManagement::Feature_e::NotSpecified) , m_logger(getLogger("ControlUnitHandler")) { m_timer->setInterval(10000); connect(m_timer, &QTimer::timeout, this, &ControlUnitHandler::onConnectedToSerialConveter); m_timer->start(); } ControlUnitHandler::~ControlUnitHandler() { delete m_connectionHandler; } bool ControlUnitHandler::init() { if (!m_connectionHandler->init()) { DEBUG_LOG(m_logger) << "Could not init ConnectionHandler"; return false; } connect(m_connectionHandler, &ConnectionHandler::received, this, &ControlUnitHandler::onDataReceived); connect(m_connectionHandler, &ConnectionHandler::connectedToSerialConverter, this, &ControlUnitHandler::onConnectedToSerialConveter); connect(m_connectionHandler, &ConnectionHandler::connectedToSerialConverter, this, &ControlUnitHandler::vehicleConnected); connect(m_connectionHandler, &ConnectionHandler::disconnectedFromSerialConverter, this, &ControlUnitHandler::onDisconnectedFromSerialConveter); send(CommandSignal::FT_SE_CB_FZRSTYP); return true; } bool ControlUnitHandler::send(const CommandSignal command, const unsigned int roundCount) { unsigned int commandByte = 0; // Check and use input switch (command) { case CommandSignal::FT_SE_CB_WERFER_STATUS: { if (roundCount <= 48) commandByte = command + roundCount; else { DEBUG_LOG(m_logger) << "Bad round count for command FT_SE_CB_WERFER_STATUS"; return false; } break; } case CommandSignal::FT_SE_CB_WERFER_MUNITION: { if (roundCount <= 48) commandByte = command + roundCount; else { DEBUG_LOG(m_logger) << "Bad round count for command FT_SE_CB_WERFER_MUNITION"; return false; } break; } default: { commandByte = command; break; } } DEBUG_LOG(m_logger) << "Sending int/byte to connectionHandler: " << commandByte << QString::number(commandByte, 2); // todorm // emit sending(QString(QStringLiteral("%1 - %2")).arg(QString::number(commandByte, 2).rightJustified(8, QLatin1Char('0'))).arg(commandByte)); QByteArray data; data.append(commandByte & 0xFF); data.resize(1); // emit hasWarnings(); return m_connectionHandler->send(data); } void ControlUnitHandler::onDataReceived(const QByteArray &ba) { if (ba.size() >= 1) { TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived ba.at(0) " << (ba.at(0)); TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived ba.at(0) & 0xFF " << (ba.at(0) & 0xFF); } else { DEBUG_LOG(m_logger) << "ControlUnitHandler::onDataReceived ba is empty"; return; } if (ba.size() >= 2) { TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived ba.at(1) " << (ba.at(1)); TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived ba.at(1) & 0xFF " << (ba.at(1) & 0xFF); } const unsigned int data = ba.at(0); if (data >= SE_FT_CB_WERFER_MUNITION && data < 93) { DEBUG_LOG(m_logger) << "ControlUnitHandler::SE_FT_CB_WERFER_MUNITION: " << data; DEBUG_LOG(m_logger) << "ControlUnitHandler::SE_FT_CB_WERFER_MUNITION real: " << data - SE_FT_CB_WERFER_MUNITION; emit vehicleRoundCount(data - SE_FT_CB_WERFER_MUNITION); return; } // todo catch exception SE_FT_CB_WERFER_MUNITION, it does not have any payload... -> // What a shitty design... seriously :/ /* * variable 'byte' has 32 bits: XXXX XXXX XXXX XXXX * command part: XXXX XXXX * payload: XXXX XXXX * * we copy the left 8 bit to a new variable 'commandByte' to check it against * our defined ReturningSignals enum. */ TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived ba " << ba; const unsigned int commandByte = ba.at(0) & 0xFF; TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived byte " << commandByte; const unsigned int byte = ba.at(1) & 0xFF; TRACE_LOG(m_logger) << "ControlUnitHandler::onDataReceived cmdbyte" << byte; TRACE_LOG(m_logger) << "onDataReceived byte: " << byte << " commandByte: " << commandByte; switch (commandByte) { case ReturningSignal::SE_FT_CB_SCHALTER_STATUS: { SafetyStatus sst; sst.loadingBoardWall = !(byte & BIT_POSITION_3); // sst.loadingBoardWall = byte & BIT_POSITION_3; if (m_feature != EffectShowManagement::Feature_e::Smoke) sst.loadingBoardWall = false; sst.safetyWarning = byte & BIT_POSITION_4; sst.temperaturWarning = byte & BIT_POSITION_5; sst.emergencyStop = byte & BIT_POSITION_6; sst.safetyOn = byte & BIT_POSITION_7; if (sst.safetyOn && !sst.safetyWarning && !sst.temperaturWarning && !sst.emergencyStop) emit safetyStatus(SafetyConfirmation_e::SafetyConfirmed); else if (sst.safetyWarning && !sst.temperaturWarning && !sst.emergencyStop) emit safetyStatus(SafetyConfirmation_e::SafetyExpiring); else emit safetyStatus(SafetyConfirmation_e::SafetyNotConfirmed); DEBUG_LOG(m_logger) << "safety warning "; emit safetyWarnings(sst); break; } case ReturningSignal::SE_FT_CB_FZRSTYP: { if (byte & BIT_POSITION_5) m_feature = EffectShowManagement::Feature_e::Explosion24; else if (byte & BIT_POSITION_6) m_feature = EffectShowManagement::Feature_e::Explosion48; else if (byte & BIT_POSITION_7) m_feature = EffectShowManagement::Feature_e::Smoke; else m_feature = EffectShowManagement::Feature_e::NotSpecified; DEBUG_LOG(m_logger) << "Got Vehicle Type " << m_feature; emit vehicleType(m_feature); break; } case ReturningSignal::SE_FT_CB_ERROR_STATUS: //tne fehler { CardRidges scr; scr.cardrige1 = byte & BIT_POSITION_7; scr.cardrige2 = byte & BIT_POSITION_6; scr.cardrige3 = byte & BIT_POSITION_5; scr.cardrige4 = byte & BIT_POSITION_4; scr.cardrige5 = byte & BIT_POSITION_3; DEBUG_LOG(m_logger) << " CB STATUS FEUER " << byte; emit vehicleErrorStatus(scr); break; } case ReturningSignal::SE_FT_CB_UBATT: // Followed by 0-255 = 0V - 51V | dez * 0,2 = V { emit vehicleBattery((double)byte * 0.2); break; } case ReturningSignal::SE_FT_CB_WERFER_STATUS: { CardRidges scr; scr.cardrige1 = byte & BIT_POSITION_7; scr.cardrige2 = byte & BIT_POSITION_6; scr.cardrige3 = byte & BIT_POSITION_5; scr.cardrige4 = byte & BIT_POSITION_4; scr.cardrige5 = byte & BIT_POSITION_3; //emit vehicleSmokeCardridgesStatus(scr); DEBUG_LOG(m_logger) << " WERFER STATUS "; emit vehicleFireUnits(scr); break; } case ReturningSignal::SE_FT_CB_NK_STATUS: { CardRidges scr; scr.cardrige1 = byte & BIT_POSITION_7; scr.cardrige2 = byte & BIT_POSITION_6; scr.cardrige3 = byte & BIT_POSITION_5; scr.cardrige4 = byte & BIT_POSITION_4; scr.cardrige5 = byte & BIT_POSITION_3; DEBUG_LOG(m_logger) << " NB STATUS "; emit vehicleSmokeCardridgesStatus(scr); break; } case ReturningSignal::SE_FT_CB_NK_ZUENDUNGS_STATUS: { CardRidges scr; scr.cardrige1 = byte & BIT_POSITION_7; scr.cardrige2 = byte & BIT_POSITION_6; scr.cardrige3 = byte & BIT_POSITION_5; scr.cardrige4 = byte & BIT_POSITION_4; scr.cardrige5 = byte & BIT_POSITION_3; emit vehicleSmokeCardridgesFireStatus(scr); break; } case ReturningSignal::SE_FT_CB_RECHNER_BEENDEN: { emit vehicleShutDown(); break; } case ReturningSignal::SE_FT_CB_SALVE_ERLEDIGT: { DEBUG_LOG(m_logger) << "Volley Done"; emit vehicleFinshedVolley(byte); break; } case ReturningSignal::SE_FT_CB_SALVE_UNTERBROCHEN: { DEBUG_LOG(m_logger) << "Volley Stopped!!"; emit vehicleStoppedVolley(byte); //add error to ui CardRidges scr; scr.cardrige2 = true; emit vehicleErrorStatus(scr); break; } case ReturningSignal::SE_FT_CB_SICHERHEIT_WIDERRUFEN: { DEBUG_LOG(m_logger) << "Sicherheit widerrufen!!"; emit vehicleSafetyRevoked(); break; } default: { DEBUG_LOG(m_logger) << "onDataReceived switch default"; break; } } TRACE_LOG(m_logger) << "end of onDataReceived"; } void ControlUnitHandler::onConnectedToSerialConveter() { DEBUG_LOG(m_logger) << "Send Type Request"; send(CommandSignal::FT_SE_CB_FZRSTYP); } void ControlUnitHandler::onDisconnectedFromSerialConveter() { m_feature = EffectShowManagement::Feature_e::NotSpecified; emit vehicleType(m_feature); emit vehicleStoppedVolley(0); //abbort fire just in case } } // namespace EffectShowClient