Index: sources/canbus/MessageInterpreter.cpp =================================================================== diff -u -r376859852f4d1a07263c44524aec347db29e0133 -r2d37cfe6593a90633a9db1fa5136f8fc43b56188 --- sources/canbus/MessageInterpreter.cpp (.../MessageInterpreter.cpp) (revision 376859852f4d1a07263c44524aec347db29e0133) +++ sources/canbus/MessageInterpreter.cpp (.../MessageInterpreter.cpp) (revision 2d37cfe6593a90633a9db1fa5136f8fc43b56188) @@ -1,15 +1,15 @@ /*! * - * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * Copyright (c) 2020-2022 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) Peter Lucia - * \date (last) 15-Oct-2020 - * \author (original) Behrouz NematiPour - * \date (original) 26-Aug-2020 + * \file MessageInterpreter.cpp + * \author (last) Behrouz NematiPour + * \date (last) 17-Dec-2021 + * \author (original) Behrouz NematiPour + * \date (original) 26-Aug-2020 * */ #include "MessageInterpreter.h" @@ -163,19 +163,20 @@ /*! * \brief MessageInterpreter::printUnhandled * \details Prints out the formatted string of the vMessage of type Message - * In case the Message ID of received CANBUS 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 ( gDisableUnhandledReport ) return; + if ( logUnhandledMessage(vMessage)) return; + if ( gDisableUnhandledReport ) return; QString mActionIdHexString = Format::toHexString(vMessage.actionId, false, eLenMessageIDDigits); QString logMessage = tr("Unhandled Message ID (HD)") + '\n' + - QString("%1 # %2 %3") + QString("%1 # %2 %3") .arg(int(vMessage.can_id), 3, 16, QChar('0')) .arg(mActionIdHexString) - .arg(QString(vMessage.data.toHex('.'))); + .arg(QString(vMessage.data.toHex('.'))).toUpper(); LOG_DEBUG(logMessage); } @@ -202,7 +203,7 @@ * 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 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. @@ -211,8 +212,8 @@ bool MessageInterpreter::interpretMessage(const Gui::GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload, Can_Id &vCanId) { bool ok = true; - QString mSenderID = "UI,"; - vCanId = Can::Can_Id::eChlid_UI_HD; + if (vCanId == Can::Can_Id::eChlid_NONE ) + vCanId = Can::Can_Id::eChlid_UI_HD ; vPayload.clear(); int length = vData.length(); @@ -225,21 +226,26 @@ if ( length ) { // this message has a variable length vPayload = Format::fromVariant(vData[0]); } - // LOG_EVENT(mSenderID + QString("CheckIn")); + // DEBUG: + LOG_EVENT_UI(QString("CheckIn")); break; case Gui::GuiActionType::ID_RawData: // len: 255, can have any len if ( length ) { // this message has a variable length vPayload = Format::fromVariant(vData[0]); } - LOG_EVENT(mSenderID + QString("RawData")); + LOG_EVENT_UI(QString("RawData")); break; 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_AdjustVersionsReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustVersionsRequestData ); 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_AdjustServiceReq : INTERPRET_TRSMT_MT_MESSAGE(AdjustServiceRequestData ); break; // Pre-Treatment case Gui::GuiActionType::ID_AdjustInitTreatmentReq : INTERPRET_TRANSMIT_MESSAGE(AdjustInitTreatmentRequestData ); break; case Gui::GuiActionType::ID_AdjustParametersValidationReq : INTERPRET_TRANSMIT_MESSAGE(AdjustParametersValidationRequestData ); break; @@ -281,10 +287,11 @@ // coco begin validated: Manually tested. This model class is a placeholder for the message 63(0x3F00) and there is no use case for this now. case Gui::GuiActionType::ID_AlarmClearedConditionReq : INTERPRET_TRANSMIT_MESSAGE(AlarmClearedConditionRequestData ); break; case Gui::GuiActionType::ID_AlarmActiveListReq : INTERPRET_TRSMT_MT_MESSAGE(AlarmActiveListRequestData ); break; + case Gui::GuiActionType::ID_AlarmTriggered : INTERPRET_TRANSMIT_MESSAGE(AlarmTriggeredRequestData ); break; // coco end default: QString mActionIdHexString = Format::toHexString(vActionId); - LOG_DEBUG(mSenderID + tr("Unknown transmit Message with ID '%1'").arg(mActionIdHexString)); + LOG_DEBUG(tr("Unknown transmit Message with ID '%1'").arg(mActionIdHexString)); ok = false; break; } @@ -293,39 +300,70 @@ /*! * \brief MessageInterpreter::identifySource - * \details Identifies the source of the message regarding the channgel id + * \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) +Can_Source MessageInterpreter::identifySource(Can_Id vCanId, QString *vText) { switch (vCanId) { case eChlid_HD_DG : // 0x008, ///< HD => DG case eChlid_HD_UI : // 0x020, ///< HD => UI case eChlid_HD_Alarm: // 0x001, ///< HD alarm broadcast case eChlid_HD_Sync : // 0x040, ///< HD sync broadcast + if (vText) *vText = "HD"; return Can_Source::eCan_HD; case eChlid_DG_HD : // 0x010, ///< DG => HD case eChlid_DG_UI : // 0x070, ///< DG => UI case eChlid_DG_Alarm: // 0x002, ///< DG alarm broadcast case eChlid_DG_Sync : // 0x080, ///< DG sync broadcast + if (vText) *vText = "DG"; return Can_Source::eCan_DG; 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) +{ + switch (vCanId) { + case eChlid_HD_UI : // 0x020, ///< HD => UI + case eChlid_HD_Alarm: // 0x001, ///< HD alarm broadcast + case eChlid_HD_Sync : // 0x040, ///< HD sync broadcast + if (vText) *vText = "HD"; + return Can_Id::eChlid_UI_HD; + + case eChlid_DG_UI : // 0x070, ///< DG => UI + case eChlid_DG_Alarm: // 0x002, ///< DG alarm broadcast + case eChlid_DG_Sync : // 0x080, ///< DG sync broadcast + if (vText) *vText = "DG"; + return Can_Id::eChlid_UI_DG; + + 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. - * \param vCan_Id - The Channel Id of the CANBUS frame. + * \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 + * 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 @@ -350,9 +388,9 @@ * \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 + * 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. + * \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_HD(const Message &vMessage, QVariantList &vData) @@ -363,16 +401,25 @@ // ----- Debug case Gui::GuiActionType::ID_CANBusFaultCount : ok = canbusFaultCountData (vMessage, vData); break; // TODO : implement notify<>() case Gui::GuiActionType::ID_HDDebugText : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDDebugText ); break; + case Gui::GuiActionType::ID_HDGeneralEvent : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDGeneralEvent ); break; // ----- Events case Gui::GuiActionType::ID_Acknow : ok = true; break; // TODO : implement notify<>() case Gui::GuiActionType::ID_PowerOff : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PowerOff ); break; case Gui::GuiActionType::ID_ShuttingDown : ok = true; LOG_EVENT("HD,ShuttingDown"); break; // TODO : implement notify<>() + // ----- 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; + // ----- Settings - case Gui::GuiActionType::ID_AdjustHDVersionsRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustHDVersionsRsp ); break; + case Gui::GuiActionType::ID_AdjustVersionsHDReq : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsHDReq ); break; + case Gui::GuiActionType::ID_AdjustVersionsHDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsHDRsp ); break; + case Gui::GuiActionType::ID_AdjustSerialHDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustSerialHDRsp ); break; + case Gui::GuiActionType::ID_AdjustServiceHDRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustServiceHDRsp ); break; case Gui::GuiActionType::ID_AdjustHDDateTimeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustHDDateTimeRsp ); break; + // ----- States case Gui::GuiActionType::ID_HDOperationModeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDOperationModeData ); break; case Gui::GuiActionType::ID_PreTreatmentStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PreTreatmentStates ); break; @@ -381,6 +428,10 @@ // ----- 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_HDAirBubbleData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDAirBubbleData ); break; + case Gui::GuiActionType::ID_HDAirTrapData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDAirTrapData ); 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; @@ -410,6 +461,7 @@ 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; // ----- 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; @@ -429,6 +481,8 @@ 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; + // ----- Disinfect - States + case Gui::GuiActionType::ID_DisinfectStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DisinfectStates ); break; // ----- Disinfection - Adjust case Gui::GuiActionType::ID_AdjustDisinfectRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDisinfectRsp ); break; case Gui::GuiActionType::ID_AdjustChemicalConfirmRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustChemicalConfirmRsp ); break; @@ -463,9 +517,9 @@ * \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 + * 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. + * \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_DG(const Message &vMessage, QVariantList &vData) @@ -478,6 +532,10 @@ ok = true; LOG_EVENT(QString("DG,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_DGPressuresData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGPressuresData ); break; @@ -489,26 +547,25 @@ case Gui::GuiActionType::ID_DGLoadCellReadingsData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGLoadCellReadingsData ); break; case Gui::GuiActionType::ID_DGTemperaturesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGTemperaturesData ); break; case Gui::GuiActionType::ID_DGDebugText : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGDebugText ); 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_DGConductivityData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGConductivityData ); break; // ----- Datum - Pre-Treatment progress case Gui::GuiActionType::ID_DGFilterFlushData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGFilterFlushData ); break; // ----- Datum - Disinfection case Gui::GuiActionType::ID_DisinfectDGFlushTimeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DisinfectDGFlushTimeData ); break; case Gui::GuiActionType::ID_DisinfectDGHeatTimeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DisinfectDGHeatTimeData ); break; case Gui::GuiActionType::ID_DisinfectDGChemicalTimeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DisinfectDGChemicalTimeData ); break; - // ----- Datum - Disinfect States - case Gui::GuiActionType::ID_DisinfectStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DisinfectStates ); break; // DG Response Messages - case Gui::GuiActionType::ID_AdjustDGVersionsRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDGVersionsRsp ); break; + case Gui::GuiActionType::ID_AdjustVersionsDGRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustVersionsDGRsp ); break; + case Gui::GuiActionType::ID_AdjustSerialDGRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustSerialDGRsp ); break; + case Gui::GuiActionType::ID_AdjustServiceDGRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustServiceDGRsp ); break; case Gui::GuiActionType::ID_AdjustDGDateTimeRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDGDateTimeRsp ); break; // unhandled messages: these will only be logged as received message // there has nothing been defined for these messages. - default: - printUnhandled (vMessage); - break; - + default : printUnhandled(vMessage); break; } return ok; @@ -592,3 +649,88 @@ return ok; } + +/*! + * \brief MessageInterpreter::updateUnhandledMessages + * \return this method is converting the general settings messages/unhandled 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() +{ + // DEBUG: qDebug() << _Settings.groups("messages/unhandled"); + for(const auto group: _Settings.groups("Messages/Unhandled")) { + // DEBUG: qDebug() << _Settings.keys(group); + bool ok; + quint16 id = QString(group).toUInt(&ok,16); + if (!ok) continue; + _messageList[ id ] = _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 id = vMessage.actionId; + if (_messageList.contains(id)) { + ok = true; + QStringList items = _messageList[id]; + QString logString; + int index = 0; + for ( int i = 0; i < items.count(); i++ ) { + QString item = items[i]; + if (i == 0) { + switch (identifySource(vMessage.can_id)) { + case Can_Source::eCan_HD: logString = "HD,~" + item; break; + case Can_Source::eCan_DG: logString = "DG,~" + item; break; + default : logString = "XX,~" + item; break; + } + } + else { + 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); + } + } + } + LOG_DATUM(logString); + } + return ok; +}