/*! * * Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file MessageInterpreter.cpp * \author (last) Dara Navaei * \date (last) 06-May-2024 * \author (original) Behrouz NematiPour * \date (original) 26-Aug-2020 * */ #include "MessageInterpreter.h" // Qt #include // #include // Project #include "Logger.h" #include "format.h" #include "Settings.h" using namespace Can; using namespace Model; #define DISABLE_CHECKIN_LOG 0 #define DEBUG_SIGNAL(vID, vMODEL) // qDebug() << vID << vMODEL; // a macro to simplify the transmit message // would be better later to be replaced by a template method // like the notify method of received messages #define INTERPRET_TRANSMIT_MESSAGE(vMODEL) \ if ( ! length ) { logInvalidLength(vActionId); return false; } \ vCanId = vMODEL::canid(); \ vPayload = Format::fromVariant(vData); \ LOG_APPED_MSG(vActionId, vMODEL::toString(vData)); \ DEBUG_SIGNAL(0, typeid(vMODEL).name()) // another version of the INTERPRET_TRANSMIT_MESSAGE for empty messages // same later improvements apply to this MACRO as well. #define INTERPRET_TRSMT_MT_MESSAGE(vMODEL) \ if ( length ) { logInvalidLength(vActionId); return false; } \ vCanId = vMODEL::canid(); \ vPayload = Format::fromVariant(vData); \ LOG_APPED_MSG(vActionId, vMODEL::toString(vData)); \ DEBUG_SIGNAL(0, typeid(vMODEL).name()) /*! * \brief MessageInterpreter::MessageInterpreter * \details Constructor * \param parent - QObject parent owner object. * Qt handles the children destruction by their parent objects life-cycle. */ MessageInterpreter::MessageInterpreter(QObject *parent) : QObject(parent) { } /*! * \brief MessageInterpreter::notify * \details Checks and prepares the model with the Message Data * Regarding the type of message logs the message received. * Notifies observers by emitting the didActionReceive( < Data > ) signal * \param vMessage - The Denali message * \param vID - The Message ID to be checked against * \param vModel - The appropriate model for the Message Data * \param vData - A QVariant list of the Message Data which will be used for debugging if needed. * \return true on successful check and prepare. */ template bool MessageInterpreter::notify(const Message &vMessage, QVariantList &vData, Gui::GuiActionType vIdCheck) { bool ok = false; TModel tModel; if ( ! isValidMessage(vMessage, vIdCheck) ) return ok; ok = tModel.fromByteArray(vMessage.data); tModel.toVariantList(vData); // This code will never go false // because the isValidMessage is catching errors. // only is checking here for developer safety if logic has changed. if ( ! ok ) return false; emit didActionReceive(tModel.data()); LOG_APPED_MSG(vIdCheck, tModel.toString()); DEBUG_SIGNAL(vIdCheck, typeid(TModel).name()) return ok; } /*! * \brief MessageInterpreter::isType * \details Checks if this is the message intended to be * \param vMessage - The message * \param vType - The type of the message to be checked against * \return true on correct type */ bool MessageInterpreter::isType(const Message &vMessage, Gui::GuiActionType vType) const { if ( vMessage.actionId != vType ) { LOG_DEBUG(QString("Incorrect expected ID '%1', got '%2'") .arg(vType) .arg(vMessage.actionId) ); return false; } return true; } /*! * \brief MessageInterpreter::isPayloadLenValid * \details Checks if the Data length has been defined for this type of message * if not logs Undefined Data Length error * if defined checks if the correct length of data is provided for this type of message. * if not logs Incorrect Data Length error * otherwise returns true * \param vMessage - The message * \param vType - The type of the message to be checked against * \return true on correct data length for the type vType */ bool MessageInterpreter::isPayloadLenValid(const Message &vMessage, Gui::GuiActionType vType) const { int len = vMessage.data.length(); QString mActionIdHexString = Format::toHexString(vMessage.actionId); if ( ! payloadLen.contains(vType) ) { LOG_DEBUG(QString("Undefined data length for received Message with ID '%1'").arg(mActionIdHexString)); return false; } if ( len < payloadLen[vType] ) { LOG_DEBUG(QString("Incorrect data length (%2 of %3) for received Message with ID '%1'") .arg(mActionIdHexString) .arg(len) .arg(payloadLen[vType]) ); return false; } return true; } /*! * \brief MessageInterpreter::logInvalidLength * \details Logs invalid data length for the message type vActionId * \param vActionId - Message Type */ void MessageInterpreter::logInvalidLength(const Gui::GuiActionType &vActionId) { QString mActionIdHexString = Format::toHexString(vActionId); LOG_DEBUG(QString("Incorrect data length for transmit message with ID '%1'") .arg(mActionIdHexString)); } /*! * \brief MessageInterpreter::validateMessage * \details Validate the message by checking its type and data * \param vMessage - The message * \param vType - The type of the message to be checked against * \return true on valid massage */ bool MessageInterpreter::isValidMessage(const Message &vMessage, Gui::GuiActionType vType) const { if ( ! isType (vMessage, vType) ) return false; if ( ! isPayloadLenValid(vMessage, vType) ) return false; return true; } /*! * \brief MessageInterpreter::printUnhandled * \details Prints out the formatted string of the vMessage of type Message * In case the Message ID of received CANBus message * is known to the interpreter but has not been handled/implemented. * \param vMessage - The message contains Unhandled Message ID */ void MessageInterpreter::printUnhandled(const Message &vMessage) const { if ( logUnhandledMessage(vMessage)) return; // the message is defined as unhandled and can still be handled and logged, return. if ( gDisableUnhandledReport ) return; // if the unhandled message error has been disabled, return. QString mActionIdHexString = Format::toHexString(vMessage.actionId, false, eLenMessageIDDigits); QString logMessage = tr("Unhandled Message ID (HD)") + '\n' + QString("%1 # %2 %3") .arg(int(vMessage.can_id), 3, 16, QChar('0')) .arg(mActionIdHexString) .arg(QString(vMessage.data.toHex('.'))).toUpper(); LOG_DEBUG(logMessage); } /*! * \brief MessageInterpreter::interpretMessage * \details This method will be called * to interpret messages from UI regarding vActionId. * \param vActionId - The ActionID of type GuiActionType * to be interpreted to hex representation of Message ID. * \param vData - The data which has to be sent over the CANBus. * \param vPayload - The Payload of the frame of Type QByteArray of hex values * Which has been interpreted from vData of Type QVariantList * \return true if the vActionId is valid. * This return value will be used later for error handling. */ bool MessageInterpreter::interpretMessage(const Gui::GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload, Can_Id &vCanId) { bool ok = true; if (vCanId == Can::Can_Id::eChlid_NONE ) vCanId = Can::Can_Id::eChlid_UI_TD ; vPayload.clear(); int length = vData.length(); // DEBUG: LOG_EVENT(QString("0x%0").arg(vActionId, 4, 16,QChar('0'))); switch (vActionId) { // notice we are in transmit mode case Gui::GuiActionType::ID_Acknow: // len: 0, can have zero len break; // No data, Just registered case Gui::GuiActionType::ID_TDCheckIn: // len: 255, can have any len if ( length ) { // this message has a variable length vPayload = Format::fromVariant(vData.first()); } if ( ! gDisableCheckInLog ) { LOG_APPED_UI(QString("CheckIn")); } break; // Generic Confirm case Gui::GuiActionType::ID_DuetConfirmUIr : INTERPRET_TRANSMIT_MESSAGE(DuetConfirmUIrData ); break; // RO Water case Gui::GuiActionType::ID_DuetRoWaterModeUIi : INTERPRET_TRANSMIT_MESSAGE(DuetRoWaterModeUIiData ); break; // Power Off case Gui::GuiActionType::ID_PowerOff : INTERPRET_TRANSMIT_MESSAGE(AdjustPowerOffRequestData ); break; // POST case Gui::GuiActionType::ID_UIPostFinalResultData : INTERPRET_TRANSMIT_MESSAGE(AdjustUIPostFinalResultRequestData ); break; // Settings case Gui::GuiActionType::ID_AdjustServiceModeReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustServiceModeRequestData ); break; case Gui::GuiActionType::ID_AdjustVersionsUIRsp : INTERPRET_TRANSMIT_MESSAGE(AdjustVersionsResponseData ); break; case Gui::GuiActionType::ID_AdjustVersionsUIReq : INTERPRET_TRANSMIT_MESSAGE(AdjustVersionsRequestData ); break; case Gui::GuiActionType::ID_AdjustHDDateTimeReq : INTERPRET_TRANSMIT_MESSAGE(AdjustHDDateTimeRequestData ); break; case Gui::GuiActionType::ID_AdjustDGDateTimeReq : INTERPRET_TRANSMIT_MESSAGE(AdjustDGDateTimeRequestData ); break; case Gui::GuiActionType::ID_AdjustServiceDatesReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustServiceDatesRequestData ); break; case Gui::GuiActionType::ID_HDUsageInfoReq : INTERPRET_TRSMT_MT_MESSAGE(HDUsageInfoRequestData ); break; case Gui::GuiActionType::ID_AdjustInstitutionalRecordReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustInstitutionalRequestData ); break; // Pre-Treatment case Gui::GuiActionType::ID_AdjustInitTreatmentReq : INTERPRET_TRANSMIT_MESSAGE(AdjustInitTreatmentRequestData ); break; case Gui::GuiActionType::ID_AdjustParametersValidationReq : INTERPRET_TRANSMIT_MESSAGE(AdjustParametersValidationRequestData ); break; case Gui::GuiActionType::ID_AdjustParametersConfirmReq : INTERPRET_TRANSMIT_MESSAGE(AdjustParametersConfirmRequestData ); break; case Gui::GuiActionType::ID_AdjustWaterSampleReq : INTERPRET_TRANSMIT_MESSAGE(AdjustWaterSampleRequestData ); break; case Gui::GuiActionType::ID_AdjustWaterSampleResultReq : INTERPRET_TRANSMIT_MESSAGE(AdjustWaterSampleResultRequestData ); break; case Gui::GuiActionType::ID_AdjustConsumablesConfirmReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustConsumablesConfirmRequestData ); break; case Gui::GuiActionType::ID_AdjustDisposablesConfirmReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustDisposablesConfirmRequestData ); break; case Gui::GuiActionType::ID_AdjustDisposablesPrimeReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustDisposablesPrimeRequestData ); break; case Gui::GuiActionType::ID_AdjustPatientConnectionBeginReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustPatientConnectionBeginRequestData ); break; case Gui::GuiActionType::ID_AdjustUltrafiltrationInitReq : INTERPRET_TRANSMIT_MESSAGE(AdjustUltrafiltrationInitRequestData ); break; case Gui::GuiActionType::ID_AdjustPatientConnectionConfirmReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustPatientConnectionConfirmRequestData ); break; case Gui::GuiActionType::ID_AdjustStartTreatmentReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustStartTreatmentRequestData ); break; // in-treatment case Gui::GuiActionType::ID_AdjustDurationReq : INTERPRET_TRANSMIT_MESSAGE(AdjustDurationRequestData ); break; case Gui::GuiActionType::ID_AdjustBloodDialysateReq : INTERPRET_TRANSMIT_MESSAGE(AdjustBloodDialysateRequestData ); break; case Gui::GuiActionType::ID_AdjustPressuresLimitsReq : INTERPRET_TRANSMIT_MESSAGE(AdjustPressuresLimitsRequestData ); break; case Gui::GuiActionType::ID_AdjustSalineReq : INTERPRET_TRANSMIT_MESSAGE(AdjustSalineRequestData ); break; case Gui::GuiActionType::ID_AdjustVitalsReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustVitalsRequestData ); break; case Gui::GuiActionType::ID_AdjustHeparinReq : INTERPRET_TRANSMIT_MESSAGE(AdjustHeparinRequestData ); break; // in-treatment - ultrafiltration case Gui::GuiActionType::ID_AdjustUltrafiltrationStateReq : INTERPRET_TRANSMIT_MESSAGE(AdjustUltrafiltrationStateRequestData ); break; case Gui::GuiActionType::ID_AdjustUltrafiltrationEditReq : INTERPRET_TRANSMIT_MESSAGE(AdjustUltrafiltrationEditRequestData ); break; case Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmReq : INTERPRET_TRANSMIT_MESSAGE(AdjustUltrafiltrationConfirmRequestData ); break; // End-Treatment case Gui::GuiActionType::ID_AdjustRinsebackReq : INTERPRET_TRANSMIT_MESSAGE(AdjustRinsebackRequestData ); break; case Gui::GuiActionType::ID_AdjustRecirculateReq : INTERPRET_TRANSMIT_MESSAGE(AdjustRecirculateRequestData ); break; case Gui::GuiActionType::ID_AdjustTreatmentEndReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustTreatmentEndRequestData ); break; // Post-Treatment case Gui::GuiActionType::ID_AdjustPatientDisconnectNotifyReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustPatientDisconnectionNotifyRequestData ); break; case Gui::GuiActionType::ID_AdjustPatientDisconnectConfirmReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustPatientDisconnectionConfirmRequestData ); break; case Gui::GuiActionType::ID_AdjustDisposablesRemovalConfirmReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustDisposablesRemovalConfirmRequestData ); break; case Gui::GuiActionType::ID_AdjustTreatmentLogReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustTreatmentLogRequestData ); break; // Disinfection case Gui::GuiActionType::ID_AdjustDisinfectModeReq : INTERPRET_TRANSMIT_MESSAGE(AdjustDisinfectModeRequestData ); break; case Gui::GuiActionType::ID_AdjustDisinfectStartReq : INTERPRET_TRANSMIT_MESSAGE(AdjustDisinfectStartRequestData ); break; // DG Cleaning case Gui::GuiActionType::ID_AdjustDGCleaningUsageReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustDGCleaningUsageRequestData ); break; // alarms case Gui::GuiActionType::ID_AlarmSilenceReq : INTERPRET_TRANSMIT_MESSAGE(AlarmSilenceRequestData ); break; case Gui::GuiActionType::ID_AlarmUserActionReq : INTERPRET_TRANSMIT_MESSAGE(AlarmUserActionRequestData ); break; case Gui::GuiActionType::ID_AlarmVolumeSetReq : INTERPRET_TRANSMIT_MESSAGE(AdjustHDAlarmVolumeRequestData ); break; // This model class is a placeholder for the message 63(0x3F00) and there is no use case for this now. case Gui::GuiActionType::ID_AlarmActiveListReq : INTERPRET_TRSMT_MT_MESSAGE(AlarmActiveListRequestData ); break; case Gui::GuiActionType::ID_AlarmTriggered : INTERPRET_TRANSMIT_MESSAGE(AlarmTriggeredRequestData ); break; // HD reset in service mode case Gui::GuiActionType::ID_ResetHDInServiceModeReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustHDResetInSrvcRequestData ); break; default: QString mActionIdHexString = Format::toHexString(vActionId); LOG_DEBUG(tr("Unknown transmit Message with ID '%1'").arg(mActionIdHexString)); ok = false; break; } return ok; } /*! * \brief MessageInterpreter::identifySource * \details Identifies the source of the message regarding the channel id * \return the source of the message in enum * \sa can::Can_Source */ Can_Source MessageInterpreter::identifySource(Can_Id vCanId, QString *vText) { switch (vCanId) { case eChlid_TD_DD : case eChlid_TD_UI : case eChlid_TD_Alarm: case eChlid_TD_Sync : if (vText) *vText = "TD"; return Can_Source::eCan_TD; case eChlid_DD_TD : case eChlid_DD_FP : //case eChlid_DD_UI : // has duplicate value as eChlid_DD_Sync case eChlid_DD_Alarm: case eChlid_DD_Sync : if (vText) *vText = "DD"; return Can_Source::eCan_DD; //case eChlid_FP_UI : // has duplicate value as eChlid_FP_Sync case eChlid_FP_Alarm: case eChlid_FP_Sync : if (vText) *vText = "FP"; return Can_Source::eCan_FP; case eDialin_TD : case eTD_Dialin : case eDialin_DD : case eDD_Dialin : case eDialin_FP : case eFP_Dialin : case eDialin_UI : case eUI_Dialin : if (vText) *vText = "DI"; return Can_Source::eCan_DI; default: if (vText) *vText = "XX"; return Can_Source::eCan_Unknown; } } /*! * \brief MessageInterpreter::identifyDestination * \details Identifies the destination of the message regarding the channel id for the ACKNOWLEDGES * \return the destination of the message in enum * \sa can::Can_Source * \sa can::Can_Id */ Can_Id MessageInterpreter::identifyDestination(Can_Id vCanId, QString *vText) { //// //TODO: let's decide if UI should ack anything other than direct recieved message ( [ TD, DD ] => UI ) //// switch (vCanId) { case eChlid_TD_UI : case eChlid_TD_Alarm: case eChlid_TD_Sync : if (vText) *vText = "TD"; return Can_Id::eChlid_UI_TD; //case eChlid_DD_UI : // has duplicate value as eChlid_DD_Sync case eChlid_DD_FP : case eChlid_DD_Alarm: case eChlid_DD_Sync : if (vText) *vText = "DD"; return Can_Id::eChlid_UI_DD; // FP is not designed to directly communicate with UI //case eChlid_FP_UI : // has duplicate value as eChlid_FP_Sync case eChlid_FP_Alarm: case eChlid_FP_Sync : if (vText) *vText = "FP"; return Can_Id::eChlid_UI_Sync; case eDialin_TD : case eTD_Dialin : case eDialin_DD : case eDD_Dialin : case eDialin_FP : case eFP_Dialin : case eDialin_UI : case eUI_Dialin : if (vText) *vText = "DI"; return Can_Id::eChlid_UI_Sync; default: if (vText) *vText = "XX"; return Can_Id::eChlid_UI_Sync; } } /*! * \brief MessageInterpreter::interpretMessage * \details This method will call appropriate message interpreter * for received messages from HD or DG regarding the Can_Id. * This function checks to identify the source of the message. * if it is from HD or DG then checks the standard handled messages with strongly typed models. * we still have a chance in each HD/DG interpreter to log the unhandled messages. * if the source is none of the HD or DG it doesn't go to the individual interpreters, * and the message will identified as unhandled immediately. * \param vCan_Id - The Channel Id of the CANBus frame. * \param vMessage - The complete message of type Message which needs to be interpreted. * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. * \param vData - The values of QVariantList which is understandable for UI * and has been extracted from hex values of the CANBus Message Payload * regarding each Message Id definition. * \return true if the message channel is in the range which can be interpreted, false otherwise. * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not */ bool MessageInterpreter::interpretMessage(const Message &vMessage, QVariantList &vData) { bool ok = false; if ( ! gLogUnhandledOnly ) { switch (identifySource(vMessage.can_id)) { case Can_Source::eCan_TD: ok = interpretMessage_TD(vMessage, vData); break; case Can_Source::eCan_DD: ok = interpretMessage_DD(vMessage, vData); break; case Can_Source::eCan_FP: ok = interpretMessage_FP(vMessage, vData); break; default : printUnhandled (vMessage ); break; // ok is false, the individual interpreters for ?HD/DG should not be called, and it should be done here. } } else { Q_UNUSED (vData ); printUnhandled (vMessage ); } return ok; } /*! * \brief MessageInterpreter::interpretMessage_TD * \details This method will be called * for received messages from TD to interpret the vMessage of type Message * to vData of type QVariantList which UI understands regarding the Can_Id. * \param vMessage - The complete message of type Message which needs to be interpreted. * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. * \param vData - The values of QVariantList which is understandable for UI * and has been extracted from hex values of the CANBus Message Payload * in vMessage of type Message regarding each Message Id definition. * \return true if the message CANBus channel is in the range which can be interpreted, false otherwise. * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not */ bool MessageInterpreter::interpretMessage_TD(const Message &vMessage, QVariantList &vData) { bool ok = false; vData.clear(); switch (vMessage.actionId) { // notice we are in receive mode // ----- Debug case Gui::GuiActionType::ID_CANBusFaultCount : ok = canbusFaultCountData (vMessage, vData); /* TODO : implement notify<>() */ break; case Gui::GuiActionType::ID_TDDebugText : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDDebugText ); break; case Gui::GuiActionType::ID_HDGeneralEvent : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDGeneralEvent ); break; // ----- Events case Gui::GuiActionType::ID_Acknow : ok = true; /* TODO : implement notify<>() */ break; case Gui::GuiActionType::ID_PowerOff : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PowerOff ); break; case Gui::GuiActionType::ID_ShuttingDown : ok = true; LOG_APPED("HD,ShuttingDown"); /* TODO : implement notify<>() */ break; case Gui::GuiActionType::ID_DuetConfirmHDi : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DuetConfirmHDi ); break; // ----- POST case Gui::GuiActionType::ID_HDPostSingleResultData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDPostSingleResultData ); break; case Gui::GuiActionType::ID_HDPostFinalResultData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDPostFinalResultData ); break; case Gui::GuiActionType::ID_UIPostFinalResultHDReq : ok = notify(vMessage, vData, Gui::GuiActionType::ID_UIPostFinalResultHDReq ); break; case Gui::GuiActionType::ID_HDRTCEpochData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDRTCEpochData ); break; // ----- Settings case Gui::GuiActionType::ID_AdjustServiceModeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustServiceModeRsp ); break; case Gui::GuiActionType::ID_AdjustVersionsTDReq : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsTDReq ); break; case Gui::GuiActionType::ID_AdjustVersionsTDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsTDRsp ); break; case Gui::GuiActionType::ID_AdjustSerialTDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustSerialTDRsp ); break; case Gui::GuiActionType::ID_AdjustServiceDatesHDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustServiceDatesHDRsp ); break; case Gui::GuiActionType::ID_AdjustHDDateTimeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustHDDateTimeRsp ); break; case Gui::GuiActionType::ID_HDUsageInfoRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDUsageInfoRsp ); break; case Gui::GuiActionType::ID_AdjustInstitutionalRecordRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustInstitutionalRecordRsp ); break; // ----- States case Gui::GuiActionType::ID_TDOpModeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDOpModeData ); break; case Gui::GuiActionType::ID_PreTreatmentStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PreTreatmentStates ); break; case Gui::GuiActionType::ID_TreatmentStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentStates ); break; case Gui::GuiActionType::ID_PostTreatmentStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PostTreatmentStates ); break; // ----- Datum case Gui::GuiActionType::ID_HDAccelerometerData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDAccelerometerData ); break; case Gui::GuiActionType::ID_HDSyringePumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDSyringePumpData ); break; case Gui::GuiActionType::ID_TDVoltageData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDVoltageData ); break; case Gui::GuiActionType::ID_TDAirBubbleData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDAirBubbleData ); break; case Gui::GuiActionType::ID_TDAirPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDAirPumpData ); break; case Gui::GuiActionType::ID_TDAirTrapData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDAirTrapData ); break; case Gui::GuiActionType::ID_TDValvesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDValvesData ); break; case Gui::GuiActionType::ID_TDBatteryData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDBatteryData ); break; case Gui::GuiActionType::ID_TDSwitchesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDSwitchesData ); break; case Gui::GuiActionType::ID_TDEjectorData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDEjectorData ); break; case Gui::GuiActionType::ID_TDTemperatureData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TDTemperatureData ); break; case Gui::GuiActionType::ID_HDBloodLeakData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDBloodLeakData ); break; // ----- Datum - Treatment case Gui::GuiActionType::ID_TreatmentRanges : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentRanges ); break; // ----- Pre-Treatment - Datum - Progress case Gui::GuiActionType::ID_SelfTestNoCartridgeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_SelfTestNoCartridgeData ); break; case Gui::GuiActionType::ID_SelfTestDryData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_SelfTestDryData ); break; case Gui::GuiActionType::ID_DisposablesPrimeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DisposablesPrimeData ); break; // ----- Pre-Treatment - Adjust case Gui::GuiActionType::ID_AdjustInitTreatmentRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustInitTreatmentRsp ); break; case Gui::GuiActionType::ID_AdjustParametersValidationRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustParametersValidationRsp ); break; case Gui::GuiActionType::ID_AdjustWaterSampleRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustWaterSampleRsp ); break; case Gui::GuiActionType::ID_AdjustDisposablesConfirmRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDisposablesConfirmRsp ); break; case Gui::GuiActionType::ID_AdjustDisposablesPrimeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDisposablesPrimeRsp ); break; case Gui::GuiActionType::ID_AdjustPatientConnectionBeginRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustPatientConnectionBeginRsp ); break; case Gui::GuiActionType::ID_AdjustUltrafiltrationInitRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustUltrafiltrationInitRsp ); break; case Gui::GuiActionType::ID_AdjustPatientConnectionConfirmRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustPatientConnectionConfirmRsp ); break; case Gui::GuiActionType::ID_AdjustStartTreatmentRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustStartTreatmentRsp ); break; // ----- In-Treatment - Datum case Gui::GuiActionType::ID_TreatmentTime : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentTime ); break; case Gui::GuiActionType::ID_BloodFlow : ok = notify(vMessage, vData, Gui::GuiActionType::ID_BloodFlow ); break; case Gui::GuiActionType::ID_DialysateInletFlow : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DialysateInletFlow ); break; case Gui::GuiActionType::ID_DialysateOutletFlow : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DialysateOutletFlow ); break; case Gui::GuiActionType::ID_PressureOcclusion : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PressureOcclusion ); break; case Gui::GuiActionType::ID_Saline : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Saline ); break; case Gui::GuiActionType::ID_Vitals : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Vitals ); break; case Gui::GuiActionType::ID_Heparin : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Heparin ); break; case Gui::GuiActionType::ID_Rinseback : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Rinseback ); break; case Gui::GuiActionType::ID_Recirculate : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Recirculate ); break; case Gui::GuiActionType::ID_BloodPrime : ok = notify(vMessage, vData, Gui::GuiActionType::ID_BloodPrime ); break; case Gui::GuiActionType::ID_TreatmentStop : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentStop ); break; case Gui::GuiActionType::ID_Ultrafiltration : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Ultrafiltration ); break; case Gui::GuiActionType::ID_TreatmentParametersSetPointData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentParametersSetPointData ); break; // ----- In-Treatment Adjust case Gui::GuiActionType::ID_AdjustDurationRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDurationRsp ); break; case Gui::GuiActionType::ID_AdjustBloodDialysateRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustBloodDialysateRsp ); break; case Gui::GuiActionType::ID_AdjustPressuresLimitsRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustPressuresLimitsRsp ); break; case Gui::GuiActionType::ID_AdjustSalineRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustSalineRsp ); break; case Gui::GuiActionType::ID_AdjustVitalsRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVitalsRsp ); break; case Gui::GuiActionType::ID_AdjustUltrafiltrationStateRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustUltrafiltrationStateRsp ); break; case Gui::GuiActionType::ID_AdjustHeparinRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustHeparinRsp ); break; case Gui::GuiActionType::ID_AdjustRinsebackRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustRinsebackRsp ); break; case Gui::GuiActionType::ID_AdjustRecirculateRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustRecirculateRsp ); break; case Gui::GuiActionType::ID_AdjustTreatmentEndRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustTreatmentEndRsp ); break; // ----- Post-Treatment Adjust case Gui::GuiActionType::ID_AdjustPatientDisconnectConfirmRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustPatientDisconnectConfirmRsp ); break; case Gui::GuiActionType::ID_AdjustDisposablesRemovalConfirmRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDisposablesRemovalConfirmRsp); break; case Gui::GuiActionType::ID_AdjustTreatmentLogRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustTreatmentLogRsp ); break; // ----- Treatment Log case Gui::GuiActionType::ID_TreatmentLogAvrgeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentLogAvrgeData ); break; case Gui::GuiActionType::ID_TreatmentLogAlarmData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentLogAlarmData ); break; case Gui::GuiActionType::ID_TreatmentLogEventData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentLogEventData ); break; // ----- Disinfection - Adjust case Gui::GuiActionType::ID_AdjustDisinfectModeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDisinfectModeRsp ); break; case Gui::GuiActionType::ID_AdjustDisinfectStartRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDisinfectStartRsp ); break; // these need to be standard and use notify as well case Gui::GuiActionType::ID_AdjustUltrafiltrationEditRsp : ok = adjustUltrafiltrationEdit (vMessage, vData); /* TODO : implement notify<>() */ break; case Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmRsp : ok = adjustUltrafiltrationConfirm (vMessage, vData); /* TODO : implement notify<>() */ break; // ----- Alarms case Gui::GuiActionType::ID_AlarmStatus : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AlarmStatus ); break; case Gui::GuiActionType::ID_AlarmTriggered : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AlarmTriggered ); break; case Gui::GuiActionType::ID_AlarmCleared : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AlarmCleared ); break; case Gui::GuiActionType::ID_AlarmVolumeSetRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AlarmVolumeSetRsp ); break; // This model class is a placeholder for the message 63(0x3F00) and there is no use case for this now. case Gui::GuiActionType::ID_AlarmActiveListRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AlarmActiveListRsp ); break; // unhandled messages: these will only be logged as received message // there has nothing been defined for these messages. default : printUnhandled (vMessage ); break; } return ok; } /*! * \brief MessageInterpreter::interpretMessage_DD * \details This method will be called * for received messages from DD to interpret the vMessage of type Message * to vData of type QVariantList which UI understands regarding the Can_Id. * \param vMessage - The complete message of type Message which needs to be interpreted. * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. * \param vData - The values of QVariantList which is understandable for UI * and has been extracted from hex values of the CANBus Message Payload * in vMessage of type Message regarding each Message Id definition. * \return true if the message CANBus channel is in the range which can be interpreted, false otherwise. * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not */ bool MessageInterpreter::interpretMessage_DD(const Message &vMessage, QVariantList &vData) { bool ok = false; vData.clear(); switch (vMessage.actionId) { // notice we are in receive mode case Gui::GuiActionType::ID_Acknow : ok = true; /* TODO : implement notify<>() */ break; LOG_APPED(QString("DD,CheckIn," + QVariant(vData).toStringList().join(','))); break; // ----- POST case Gui::GuiActionType::ID_DGPostSingleResultData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGPostSingleResultData ); break; case Gui::GuiActionType::ID_DGPostFinalResultData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGPostFinalResultData ); break; // DG data messages case Gui::GuiActionType::ID_DGROPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGROPumpData ); break; case Gui::GuiActionType::ID_DDPressuresData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDPressuresData ); break; case Gui::GuiActionType::ID_DGDrainPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGDrainPumpData ); break; case Gui::GuiActionType::ID_DGOperationModeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGOperationModeData ); break; case Gui::GuiActionType::ID_DGReservoirData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGReservoirData ); break; case Gui::GuiActionType::ID_DDValvesStatesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDValvesStatesData ); break; case Gui::GuiActionType::ID_DDHeatersData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDHeatersData ); break; case Gui::GuiActionType::ID_DGLoadCellReadingsData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGLoadCellReadingsData ); break; case Gui::GuiActionType::ID_DDConcentratePumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDConcentratePumpData ); break; case Gui::GuiActionType::ID_DDTemperaturesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDTemperaturesData ); break; case Gui::GuiActionType::ID_DDDialysatePumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDDialysatePumpData ); break; case Gui::GuiActionType::ID_DDDebugText : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDDebugText ); break; case Gui::GuiActionType::ID_DGGeneralEvent : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGGeneralEvent ); break; case Gui::GuiActionType::ID_DGAccelerometerData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGAccelerometerData ); break; case Gui::GuiActionType::ID_DDConductivityData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDConductivityData ); break; case Gui::GuiActionType::ID_DDGenDialysateData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDGenDialysateData ); break; case Gui::GuiActionType::ID_DDLevelData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDLevelData ); break; case Gui::GuiActionType::ID_DDBloodLeakData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DDBloodLeakData ); break; // ----- Datum - Pre-Treatment progress case Gui::GuiActionType::ID_DGFilterFlushData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGFilterFlushData ); break; // DG Response Messages case Gui::GuiActionType::ID_AdjustVersionsDDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsDDRsp ); break; case Gui::GuiActionType::ID_AdjustSerialDDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustSerialDDRsp ); break; case Gui::GuiActionType::ID_AdjustServiceDatesDGRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustServiceDatesDGRsp ); break; case Gui::GuiActionType::ID_AdjustDGDateTimeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDGDateTimeRsp ); break; case Gui::GuiActionType::ID_AdjustDGCleaningUsageRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDGCleaningUsageRsp ); break; // RO Water case Gui::GuiActionType::ID_DuetRoWaterStatDGq : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DuetRoWaterStatDGq ); break; case Gui::GuiActionType::ID_DuetRoWaterModeDGr : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DuetRoWaterModeDGr ); break; // unhandled messages: these will only be logged as received message // there has nothing been defined for these messages. default : printUnhandled (vMessage ); break; } return ok; } /*! * \brief MessageInterpreter::interpretMessage_FP * \details This method will be called * for received messages from FP to interpret the vMessage of type Message * to vData of type QVariantList which UI understands regarding the Can_Id. * \param vMessage - The complete message of type Message which needs to be interpreted. * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. * \param vData - The values of QVariantList which is understandable for UI * and has been extracted from hex values of the CANBus Message Payload * in vMessage of type Message regarding each Message Id definition. * \return true if the message CANBus channel is in the range which can be interpreted, false otherwise. * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not */ bool MessageInterpreter::interpretMessage_FP(const Message &vMessage, QVariantList &vData) { bool ok = false; vData.clear(); switch (vMessage.actionId) { // notice we are in receive mode case Gui::GuiActionType::ID_Acknow : ok = true; /* TODO : implement notify<>() */ break; LOG_APPED(QString("FP,CheckIn," + QVariant(vData).toStringList().join(','))); break; // FP data messages case Gui::GuiActionType::ID_FPValvesStatesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPValvesStatesData ); break; case Gui::GuiActionType::ID_FPROPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPROPumpData ); break; case Gui::GuiActionType::ID_FPPressuresData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPPressuresData ); break; case Gui::GuiActionType::ID_FPLevelData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPLevelData ); break; case Gui::GuiActionType::ID_FPFlowSensorData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPFlowSensorData ); break; case Gui::GuiActionType::ID_FPConductivityData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPConductivityData ); break; case Gui::GuiActionType::ID_FPTemperaturesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPTemperaturesData ); break; case Gui::GuiActionType::ID_FPROBoosterPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_FPROBoosterPumpData ); break; // FP Response Messages case Gui::GuiActionType::ID_AdjustVersionsFPRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsFPRsp ); break; // unhandled messages: these will only be logged as received message // there has nothing been defined for these messages. default : printUnhandled (vMessage ); break; } return ok; } // ---------- ---------- Message handlers ---------- ---------- // // ---------- ---------- ---------- ---------- ---------- Debug ---------- ---------- ---------- ---------- ---------- // /*! * \brief MessageInterpreter::canbusFaultCountData * \details This method interprets Fault Count message data * in vMessage of type Message. This message is only used for debugging purposes. * \param vMessage - The vMessage of type Message which contains all the data, * require to be interpreted. * \param vData - Fault Count data * \return true if the data can be extracted as defined for Fault Count Message ID */ bool MessageInterpreter::canbusFaultCountData(const Message &vMessage, QVariantList &vData) { // TODO : review other methods bool ok = false; if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_CANBusFaultCount) ) return ok; QVariantList mData; int index = 0; Types::U32 mCanBUSFaultCount; ok = GetValue(vMessage.data, index, mCanBUSFaultCount); // developer safety if for any reason length of CanBUSFaultCount set to 0 if (ok) { vData += mCanBUSFaultCount.value; } return ok; } // ---------- ---------- ---------- ---------- ---------- Adjustments ---------- ---------- ---------- ---------- ---------- // /*! * \brief MessageInterpreter::adjustUltrafiltrationEditData * \details This method interprets Treatment Ultrafiltration Volume Adjustment Response message data * in vMessage of type Message. * \param vMessage - The vMessage of type Message which contains all the data, * require to be interpreted. * \param vData - Treatment Ultrafiltration Volume Adjustment Response data * \return true if the data can be extracted as defined for Treatment Ultrafiltration Volume Adjustment Response Message ID */ bool MessageInterpreter::adjustUltrafiltrationEdit(const Message &vMessage, QVariantList &vData) { bool ok = false; if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AdjustUltrafiltrationEditRsp) ) return ok; Model::MAdjustUltrafiltrationEditResponse mData; ok = mData.fromByteArray(vMessage.data); LOG_APPED("HD," + mData.toString()); // TODO : Not Standard mData.toVariantList(vData); emit didActionReceive(mData.data()); return ok; } /*! * \brief MessageInterpreter::adjustUltrafiltrationConfirmData * \details This method interprets Treatment Ultrafiltration Volume Adjustment Confirm Response message data * in vMessage of type Message. * \param vMessage - The vMessage of type Message which contains all the data, * require to be interpreted. * \param vData - Treatment Ultrafiltration Volume Adjustment Confirm Response data * \return true if the data can be extracted as defined for Treatment Ultrafiltration Volume Adjustment Confirm Response Message ID */ bool MessageInterpreter::adjustUltrafiltrationConfirm(const Message &vMessage, QVariantList &vData) { bool ok = false; if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmRsp) ) return ok; Model::MAdjustUltrafiltrationConfirmResponse mData; ok = mData.fromByteArray(vMessage.data); LOG_APPED("HD," + mData.toString()); // TODO : Not Standard mData.toVariantList(vData); emit didActionReceive(mData.data()); return ok; } /*! * \brief MessageInterpreter::updateUnhandledMessages * \return this method is converting the general settings messages/unhandled (Storage::Settings_Category_MessagesUnhandled) group of settings to the message interpreter specific map structure. * it is done for performance to keep the lookup table shorter and faster. * This method is called by the chain of events when Application controller is done reading the settings and emits it didSettingsDone, * which Message dispatcher is listening to will call this function in its signal handler slot. */ void MessageInterpreter::updateUnhandledMessages() { QString category = Storage::Settings_Category_MessagesUnhandled; QStringList groups = _Settings.groups(category); // DEBUG: qDebug() << groups; for(const auto &group: qAsConst(groups)) { bool ok; quint16 id = QString(group).toUInt(&ok,16); if (!ok) continue; _messageList[ id ] = _Settings.keys(category, group); // DEBUG: qDebug() << _Settings.keys(group); } } /*! * \brief MessageInterpreter::logUnhandledMessage * \details Search in the list of the unhandled messages and tries to extract the data and log it. * \param vMessage - the received message. * \return true if the message data can be extracted and logged. */ bool MessageInterpreter::logUnhandledMessage(const Message &vMessage) const { bool ok = false; quint16 msg_id = vMessage.actionId; QString logString = QString("%1,").arg(msg_id,4,16); QString can_id; QString item = ""; identifySource(vMessage.can_id, &can_id); // Message Can Channel. logString += can_id + ","; // qDebug() << __FUNCTION__ << logString; if (_messageList.contains(msg_id)) { ok = true; QStringList items = _messageList[msg_id]; int index = 0; for ( int i = 0; i < items.count(); i++ ) { item = items[i]; if (i == 0) { // Message Name/Identifier logString += "~" + item; } else { // Message payload data if ( item == "F32" ) { Types::F32 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "S32" ) { Types::S32 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "U32" ) { Types::U32 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "S16" ) { Types::S16 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "U16" ) { Types::U16 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "S08" ) { Types::S08 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "U08" ) { Types::U08 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } else if ( item == "BOOL" ) { Types::U32 param; if (! GetValue(vMessage.data, index, param )) logString += ",?"; else logString += "," + QString::number(param.value); } } } } else { if ( gDisableUnhandledReport ) { // if the unhandled message error has been disabled, return. LOG_DEBUG(QString("Undefined unhandled message [%1]").arg(msg_id, 0, 16)); } } LOG_APPED(logString + item); return ok; }