/*! * * 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.h * date 10/26/2019 * author Behrouz NematiPour * */ #pragma once // Qt #include #include #include // Project #include "main.h" #include "guiactions.h" // Define #define _MessageHandler MessageHandler::I() // forward declarations class unittests; // namespace using namespace Gui; namespace Can { #define CAN_FRAME_LENGTH 8 #define MAX_PAYLOAD_IN_HEADER_FRAME 3 /*! * * \brief The MessageHandler class * \details This class is handling the can message by building and striping it. * // -- CAN MESSAGE STRUCTURE -- * #0 #1 #2 #3 #4 #5 #6 #7 * +---+---+---+---+---+---+---+---+--.......--+ * | A5| MsgId |Len| Payload |CRC|..padding..| * +---+---+---+---+---+---+---+---+--.......--+ * Header Frame: * 1 - CRC is last after payload * Ex1 - If Len=0 then CRC is #4 * Ex2 - If Len=1 then CRC is #5 and payload is #4 * 2 - If CRC is not the last by in the frame * then there is padding 0x00 to make the frame 8 byte fix * Tail Frame: * 3 - Partial frames only have Payload and CRC ( and padded) * */ class MessageHandler : public QObject { Q_OBJECT // friends friend class ::unittests; const QHash payloadLen { {GuiActionType::PowerOff, 0x01}, {GuiActionType::Check_In, 0x00} }; // constants enum Payload_Data : quint8 { ePayload_None = 0x00, ePayload_Sync = 0xA5, }; enum Frame_Data : quint8 { eLenCanFrame = 8, eLenMaxHeaderData = 3, eLenSyncByte = 1, eLenActionId = 2, eLenLength = 1, }; enum Can_Id : quint16 { // Broadcasts //// Alarm eChlid_HD_Alarm = 0x001, ///< HD alarm broadcast eChlid_DG_Alarm = 0x002, ///< DG alarm broadcast eChlid_UI_Alarm = 0x004, ///< UI alarm broadcast [Out] //// Sync eChlid_HD_Sync = 0x040, ///< HD sync broadcast eChlid_DG_Sync = 0x080, ///< DG sync broadcast eChlid_UI_Sync = 0x200, ///< UI sync broadcast [Out] // UI not listening eChlid_HD_DG = 0x008, ///< HD => DG eChlid_DG_HD = 0x010, ///< DG => HD // UI is listening eChlid_HD = 0x020, ///< HD => UI eChlid_UI = 0x100, ///< UI => HD [Out] // UI lessens occasionally eChlid_DG_UI = eChlid_DG_Alarm, ///< No direct channel has been defined between DG&UI, May be required for logging eChlid_UI_DG = eChlid_UI_Sync , ///< No direct channel has been defined between DG&UI, May be required for logging }; struct Message { // Private Data Class quint8 length; GuiActionType actionId; QByteArray data; bool isComplete() { return data.length() == length; } bool isEmpty () { return data.length() == 0 ; } }; typedef QList MessageList; QHash messages; // Singleton SINGLETON_DECL(MessageHandler) public: void init(); private: void connection(); void checked_in(); // TODO : needs to be renamed and called from the main timer to tell HD, UI is alive // build message to be sent QByteArray buildMessage (GuiActionType vAction , GuiActionData vData = GuiActionData::NoData); void addSyncByte (QByteArray &vPayload ); void addActionId (QByteArray &vPayload , GuiActionType vAction); void addLegth (QByteArray &vPayload , GuiActionType vAction); void addData (QByteArray &vPayload , GuiActionData vData = GuiActionData::NoData); void addCRC (QByteArray &vPayload ); void addPadding (QByteArray &vPayload ); quint8 calcCRC (const QByteArray &vData ); bool checkCRC (const QByteArray &vData , quint8 vCRC); // strip message to its parts QByteArray stripMessage (const QCanBusFrame &vFrame ); bool hasSyncByte (QByteArray &vPayload ); GuiActionType getActionId (QByteArray &vPayload ); quint8 getLength (QByteArray &vPayload ); QByteArray getData (QByteArray &vPayload , quint8 vLen , bool *ok = nullptr ); // 0 - command definition // 0.0- Can ID // 0.1- command id // 0.2- command payload length // 1 - create, frame, schedule, send // 2 - read, categorize, buffer, act private slots: // Should be private for thread safety and is connected internally. void onActionRequest (GuiActionType vAction); // UI => HD/DG void onActionPerform (GuiActionType vAction, GuiActionData vData); // UI <= HD/DG void onRead (const QCanBusFrame &vFrame); protected: virtual void timerEvent(QTimerEvent *event) override; signals: void didActionConfirm(GuiActionType vAction, GuiActionData vData); // UI <= HD/DG void didActionCommand(GuiActionType vAction ); // UI <= HD/DG void didActionRequest(const QCanBusFrame &vFrame ); // UI => HD/DG void didActionPerform(const QCanBusFrame &vFrame ); // UI => HD/DG }; }