/*! * * 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 messagepartitioner.cpp * date 12/6/2019 * author Behrouz NematiPour * */ #include "messagepartitioner.h" // Qt #include // Project // namespace using namespace Can; MessagePartitioner::MessagePartitioner(QObject *parent) : QObject(parent) { } QList MessagePartitioner::buildMessage(GuiActionType vAction, const QByteArray &vData) { QList mFrames; QByteArray mPayload ; addSyncByte (mPayload); // SyncByte addActionId (mPayload, vAction); // Message ID addData (mPayload, vAction, vData); // Regarding Payload Length, Adding required Data addCRC (mPayload); // CRC quint16 len = mPayload.length(); if (len > Message::eLenCanFrame) { quint8 frameCount = len / Message::eLenCanFrame; for (quint8 i = 0; i <= frameCount; i++) { mFrames += mPayload.mid(i * Message::eLenCanFrame, Message::eLenCanFrame); } } else { mFrames += mPayload; } addPadding (mFrames.last()); // Padded to 8 byte frame return mFrames; } void MessagePartitioner::addSyncByte(QByteArray &vPayload) { vPayload.append(Message::ePayload_Sync); // Sync byte } void MessagePartitioner::addActionId(QByteArray &vPayload, GuiActionType vAction) { if (vAction != GuiActions::Unknown) { vPayload += (vAction >> 8) & 0xFF;//high byte vPayload += vAction & 0xFF;// low byte } } void MessagePartitioner::addData(QByteArray &vPayload, GuiActionType vAction, const QByteArray &vData) { quint8 len = Message::payloadLen[vAction]; // if len has been set to max(255) // it means it has no limit and can be as long as 255 bytes if (len == Message::eLenMaxData) { len = vData.length(); if (vData.length() > Message::eLenMaxData) { len = Message::eLenMaxData ; } } vPayload += len; vPayload += vData.mid(0, len); // Adding required Data } void MessagePartitioner::addCRC(QByteArray &vPayload) { vPayload += calcCRC(vPayload); } void MessagePartitioner::addPadding(QByteArray &vPayload) { vPayload = vPayload.leftJustified(Message::eLenCanFrame, '\0'); } quint8 MessagePartitioner::calcCRC(const QByteArray &vData) { // TODO : calcCRC has not been used yet Q_UNUSED(vData) return '\0'; } bool MessagePartitioner::checkCRC(const QByteArray &vData, quint8 vCRC) { //TODO : enable when the calcCRC implemented Q_UNUSED(vData) Q_UNUSED(vCRC ) return true;//calcCRC(vData) == vCRC; } bool MessagePartitioner::stripMessage(const QByteArray &vPayload, Packet &vMessage) { QByteArray mPayload = vPayload; //Can_Id mCanId = static_cast(vFrame.frameId()); //if (messages[mCanId].isEmpty()) { // messages[mCanId].append(Message()); //} else { // if (messages[mCanId].last().isComplete()) { // messages[mCanId].append(Message()); // } //} // //Message message = messages[mCanId].last(); // when we are here the message is new or partial. bool ok = false; if (hasSyncByte(mPayload)) { vMessage.actionId = getActionId(mPayload); vMessage.length = getLength (mPayload); vMessage.data = getData (mPayload, vMessage.length, &ok); if (!ok) { qDebug() << "ERROR : CRC error"; return false; } } else { qDebug() << "ERROR : incomplete message or corrupted without sync byte (without header)"; return false; } //messages[mCanId].append(message); return true; } bool MessagePartitioner::hasSyncByte(QByteArray &vPayload) { quint8 mSyncByte = vPayload[0]; if (mSyncByte == Message::ePayload_Sync) { vPayload = vPayload.mid(Message::eLenSyncByte); return true; } return false; } GuiActionType MessagePartitioner::getActionId(QByteArray &vPayload) { quint16 mActionId; mActionId = (vPayload[0] << 8) | vPayload[1]; //TODO : It needs to be checked that the Action ID is Correct. //return GuiActionType::Unknown; vPayload = vPayload.mid(Message::eLenActionId); return static_cast(mActionId); } quint8 MessagePartitioner::getLength(QByteArray &vPayload) { quint8 mlen = vPayload[0]; vPayload = vPayload.mid(Message::eLenLength); return mlen; } QByteArray MessagePartitioner::getData(QByteArray &vPayload, quint8 vLen, bool *ok) { QByteArray mData; if (vLen <= Message::eLenMaxHeaderData) { mData = vPayload.mid(0,vLen); if (ok) { *ok = checkCRC(mData,vPayload[vLen+1]); // CRC is always next byte after Data } } else { mData = vPayload; } return mData; }