/*! * * Copyright (c) 2019-2019 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 * date 12/11/2019 * author Behrouz NematiPour * */ #include "messageinterpreter.h" // Qt // Project #include "format.h" using namespace Can; /*! * \brief MessageInterpreter::MessageInterpreter * \param parent */ MessageInterpreter::MessageInterpreter(QObject *parent) : QObject(parent) { } /*! * \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 GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload) { bool ok = true; vPayload.clear(); int l = vData.length(); quint8 ix = 0; switch (vActionId) { // notice we are in transmit mode case GuiActionType::PowerOff: ix = static_cast(GuiActionIndx::PowerOff_Response); if (l >= ix + 1) { quint8 tmp = vData[ix].toUInt(); vPayload += tmp; } else { QString mActionIdHexString = Format::toHexString(vActionId); qDebug() << "ERROR :" << tr("Incorrect data for Message ID (UI) '%1'").arg(mActionIdHexString); ok = false; } break; case GuiActionType::KeepAlive: // Nothing needs to be done. // KeepAlive has No data. // Mentioned in the switch/case to be registered as a valid message. break; case GuiActionType::String: vPayload = Format::fromVariant(vData[0]); break; default: QString mActionIdHexString = Format::toHexString(vActionId); qDebug() << "ERROR :" << tr("Unknown Message ID (UI) '%1'").arg(mActionIdHexString); ok = false; break; } return ok; } /*! * \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 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 Can_Id vCan_Id, const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) { bool ok = false; switch (vCan_Id) { case eChlid_HD: case eChlid_HD_Alarm: case eChlid_HD_Sync: ok = interpretMessage_HD(vMessage, vActionId, vData); break; default: break; } return ok; } /*! * \brief MessageInterpreter::interpretMessage_HD * \details This method will be called * for received messages from HD 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_HD(const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) { bool ok = true; vActionId = vMessage.actionId; vData.clear(); switch (vActionId) { // notice we are in receive mode case GuiActionType::PowerOff: { quint8 mShowHide; ok = getPowerOffData(vMessage, mShowHide); if (ok) { vData += mShowHide; } break; } case GuiActionType::BloodFlow: { types::S32 mFlowSetPoint ; types::F32 mMeasuredFlow ; types::F32 mRotorSpeed ; types::F32 mMotorSpeed ; types::F32 mMotorCtlSpeed ; types::F32 mMotorCtlCurrent ; ok = getBloodFlowData(vMessage, mFlowSetPoint, mMeasuredFlow, mRotorSpeed, mMotorSpeed, mMotorCtlSpeed, mMotorCtlCurrent); if (ok) { vData += mFlowSetPoint .value; vData += mMeasuredFlow .value; vData += mRotorSpeed .value; vData += mMotorSpeed .value; vData += mMotorCtlSpeed .value; vData += mMotorCtlCurrent.value; } break; } case GuiActionType::AlarmStatus: printUnhandled(vMessage); break; case GuiActionType::AlarmTriggered: printUnhandled(vMessage); break; case GuiActionType::AlarmCleared: printUnhandled(vMessage); break; default: printUnhandled(vMessage); break; } return ok; } /*! * \brief MessageInterpreter::interpretMessage_DG * \details This method will be called * for received messages from DG 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_DG(const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) { Q_UNUSED(vMessage ); Q_UNUSED(vActionId); Q_UNUSED(vData ); // No data have been interpreted from DG yet return false; } /*! * \brief MessageInterpreter::getBloodFlowData * \details This is the method which interprets the Blood Flow message data in vMessage of type Message * to its elements of data. * \param vMessage - The vMessage of type Message which contains all the data, require to be interpreted. * \param vFlowSetPoint - Flow Set Point value of type signed int extracted out. * \param vMeasuredFlow - Measured Flow value of type float extracted out * \param vRotorSpeed - Rotor Speed value of type float extracted out * \param vMotorSpeed - Motor Speed value of type float extracted out * \param vMotorCtlSpeed - Motor Controller Speed value of type float extracted out * \param vMotorCtlCurrent - Motor Controller Current value of type float extracted out * \return true if the message can be successfully converted to the Blood Flow data elements. */ bool MessageInterpreter::getBloodFlowData( const Message &vMessage , types::S32 &vFlowSetPoint , types::F32 &vMeasuredFlow , types::F32 &vRotorSpeed , types::F32 &vMotorSpeed, types::F32 &vMotorCtlSpeed , types::F32 &vMotorCtlCurrent , types::F32 &vPWMDtCycle) { if ( vMessage.actionId != GuiActionType::BloodFlow ) { return false; } if ( vMessage.data.length() < payloadLen[GuiActionType::BloodFlow] ) { QString mActionIdHexString = Format::toHexString(vMessage.actionId); qDebug() << "ERROR :" << tr("Incorrect data for Message ID (HD) '%1'").arg(mActionIdHexString); return false; } int i = 0; int p = 0; int j = 0; p += 4; j = 0; while (i < p) { vFlowSetPoint.bytes[j] = vMessage.data[i]; j++; i++; } p += 4; j = 0; while (i < p) { vMeasuredFlow.bytes[j] = vMessage.data[i]; j++; i++; } p += 4; j = 0; while (i < p) { vRotorSpeed.bytes[j] = vMessage.data[i]; j++; i++; } p += 4; j = 0; while (i < p) { vMotorSpeed.bytes[j] = vMessage.data[i]; j++; i++; } p += 4; j = 0; while (i < p) { vMotorCtlSpeed.bytes[j] = vMessage.data[i]; j++; i++; } p += 4; j = 0; while (i < p) { vMotorCtlCurrent.bytes[j] = vMessage.data[i]; j++; i++; } return true; } /*! * \brief MessageInterpreter::getPowerOffData * \details This is the method which interprets the PowerOff message data * in vMessage of type Message. * to its elements of data. * \param vMessage - The vMessage of type Message which contains all the data, * require to be interpreted. * \param vShowHide - The return value of extracted fro * \return true if the data can be extracted as defined for PowerOff Message ID */ bool MessageInterpreter::getPowerOffData(const Message &vMessage, quint8 &vShowHide) { bool ok = true; int l = vMessage.data.length(); quint8 ix = static_cast(GuiActionIndx::PowerOff_ShowHide); if (l >= ix + 1) { quint8 tmp = vMessage.data[ix]; vShowHide = tmp; } else { QString mActionIdHexString = Format::toHexString(vMessage.actionId); qDebug() << "ERROR :" << tr("Incorrect data for Message ID (HD) '%1'").arg(mActionIdHexString); ok = false; } return ok; } /*! * \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) { QString mActionIdHexString = Format::toHexString(vMessage.actionId, false, eLenMessageIDDigits); qDebug() << "WARNG :" << tr("Unhandled Message ID (HD)"); qDebug().noquote() << QString(mActionIdHexString + " " + vMessage.data.toHex('.')).toLatin1(); qDebug() << ""; }