/*! * * Copyright (c) 2019-2020 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 messagehandler.cpp * date 10/26/2019 * author Behrouz NematiPour * */ #include "messagehandler.h" // Qt #include #include // Project #include "applicationcontroller.h" // namespace using namespace Can; // Singleton SINGLETON_INIT(MessageHandler) /*! * \brief MessageHandler Constructor * \param parent */ MessageHandler::MessageHandler(QObject *parent) : QObject(parent) { } /*! * \brief Message Handler initializer */ void MessageHandler::init() { connection(); checked_in(); //startTimer(1000); } /*! * \brief Message Handler connections definition * \details Initializes the required signal/slot connection between this class and other objects\n * to be able to communicate. */ void MessageHandler::connection() { // From GUI connect(_ApplicationController, SIGNAL(didActionRequest(GuiActionType)), this , SLOT( onActionRequest(GuiActionType))); // From GUI connect(_ApplicationController, SIGNAL(didActionPerform(GuiActionType,GuiActionData)), this , SLOT( onActionPerform(GuiActionType, GuiActionData))); // From HD/DG connect(_CanInterface , SIGNAL(didRead(QCanBusFrame)), this , SLOT( onRead(QCanBusFrame))); } void MessageHandler::checked_in() { QCanBusFrame mFrame; mFrame.setFrameId(eChlid_UI); mFrame.setPayload(buildMessage(GuiActions::Check_In)); emit didActionPerform(mFrame); } QByteArray MessageHandler::buildMessage(GuiActionType vAction, GuiActionData vData) { QByteArray mPayload ; addSyncByte (mPayload); addActionId (mPayload, vAction ); // Message ID addLegth (mPayload, vAction ); // Payload Length addPayload (mPayload); // Adding required Data addChecksum (mPayload); // Checksum addPadding (mPayload); // Padded to 8 byte frame return mPayload ; } void MessageHandler::addSyncByte(QByteArray &vPayload) { vPayload.append(ePayload_Sync); // Sync byte } void MessageHandler::addActionId(QByteArray &vPayload, GuiActionType vAction) { if (vAction != GuiActions::Unknown) { vPayload += (vAction >> 8) & 0xFF;//high byte vPayload += vAction & 0xFF;// low byte } } void MessageHandler::addLegth(QByteArray &vPayload, GuiActionType vAction) { vPayload.append( payloadLen[vAction]); } void MessageHandler::addPayload(QByteArray &vPayload, GuiActionData vData) { // if the payload is more than a remaining frame empty bytes // then it requires to be chopped. vPayload.append(vData); // Adding required Data } void MessageHandler::addPadding(QByteArray &vPayload) { vPayload.rightJustified(eCanFrameLen,'\0'); } quint8 MessageHandler::checksum(QByteArray &vBytes) { // TODO : has not been used yet return '\0'; } bool MessageHandler::hasSyncByte(QByteArray &vPayload) { if (vPayload.left(eLenSync) == ePayload_Sync) { vPayload = vPayload.right(eLenSync); return true; } return false; } GuiActionType MessageHandler::getActionId(QByteArray &vPayload) { GuiActionType mActionId = vPayload.left(eLenActionId); vPayload = vPayload.right(eLenActionId); return mActionId; } quint8 MessageHandler::getLength(QByteArray &vPayload) { quint8 mPayloadLength = vPayload.left(eLenPayload); vPayload = vPayload.right(eLenPayload); return mPayloadLength; } void MessageHandler::addChecksum(QByteArray &vPayload) { vPayload += checksum(vPayload); } /*! * \brief Process the requested action * \details Processes the requested action * \param vAction - User requested Action */ void MessageHandler::onActionRequest(GuiActionType vAction) { // TODO : Test Code QCanBusFrame mFrame; mFrame.setFrameId(eChlid_UI); mFrame.setPayload(buildMessage(vAction)); emit didActionRequest(mFrame); } /*! * \brief Process the performed action * \details An action which has been commanded by HD has been performed by GUI.\n * GUI notifies that the action has been performed * \param vAction * \param vData */ void MessageHandler::onActionPerform(GuiActionType vAction, GuiActionData vData) { // TODO : Test Code QCanBusFrame mFrame; mFrame.setFrameId(eChlid_UI); mFrame.setPayload(buildMessage(vAction, vData)); emit didActionPerform(mFrame); } /*! * \brief MessageHandler::onRead * \param vFrame */ void MessageHandler::onRead(const QCanBusFrame &vFrame) { // TODO : Test Code bool isCommand = true ; bool isUnknown = false; bool isIgnored = false; //// TODO : For test //QString cmd = " 020 [8] A5 01"; //if (vFrame.toString().left(cmd.length()) != cmd) { // isUnknown = true; //} Can_Id mCanId = vFrame.frameId(); switch (mCanId) { case eChlid_HD_DG: case eChlid_DG_HD: isIgnored = true; break; case eChlid_HD: break; default: break; } QByteArray mPayload = vFrame.payload(); Message message; if (messages[mCanId].isEmpty()) { // there is no message in the message list for this channel // so we expect to have a new message which starts with Sync // and we are striping out the payload and add to the list if (hasSyncByte(mPayload)) { message.actionId = getActionId(mPayload); message.length = getLength(mPayload); if (message.length <= eMaxHeaderData) { // payload can be fitted in one frame so we have all the payload message.data = getPayload(mPayload); } else { } if (checksum(message.data) != getChecksum(mPayload)) { // ERROR : Checksum error } messages[mCanId].append(message); } else { // ERROR : incomplete message or corrupted without sync byte (without header) } } else { if (!messages[mCanId].last().isFull()) { } } if (isUnknown || isIgnored) return; if (isCommand) { emit didActionCommand(GuiActions::PowerOff); } else { emit didActionConfirm(GuiActions::PowerOff,GuiActions::Accepted); } } void MessageHandler::timerEvent(QTimerEvent *event) { QObject::timerEvent(event); }