/*! * * 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 messagepacker.h * \date 12/9/2019 * \author Behrouz NematiPour * */ #pragma once // Qt #include // Project #include "main.h" #include "messagebuilder.h" #include "messageinterpreter.h" // define #define _MessageDispatcher Can::MessageDispatcher::I() // forward declarations class tst_canbus; class tst_acknow; class tst_messaging; // since this class is the interface between GUI and Can // it needs to use Gui namespace otherwise it makes code hard to read. using namespace Gui; namespace Can { /*! * \brief The MessageDispatcher class \n * \details Message Dispatcher is the class which is the mediator between CanBus Frames \n * and Application Messages. \n * The massages and frames need to be interpreted form/to hex \n * and also need to be split into frames or constructor from frames to be a message. \n * ---------------------------------------------------------------------------------------- \n * \n * Interpreter : message [ toHex , fromHex] \n * \n * Builder : message [ toFrame , fromFrame ] \n * \n * Dispatcher : signal->Handler( .. frame .. ) \n * \n * Handler : signal->Dispatcher( .. frame .. ) \n * \n * ---------------------------------------------------------------------------------------- \n * \n * *** UI <-> AppController <-> Dispatcher <-> Handler <-> HD *** \n * \n * ---------------------------------------------------------------------------------------- \n * \n * UI -> message -> \n * AppController { \n * signal->Dispatcher ( .. message .. ) \n * } \n * \n * Dispatcher { \n * .. \n * messageList[ch][frameList] += Builder.toFrame ( Interpreter.toHex ( message ) ) \n * .. \n * signal->Handler( .. frame .. ) \n * } \n * \n * ---------------------------------------------------------------------------------------- \n * \n * HD -> frame -> \n * Handler { \n * signal->Dispatcher ( .. frame .. ) \n * } \n * \n * Dispatcher { \n * messageList[ch][frameList] += Interpreter.fromHex( frame ) \n * isComplete => Builder.fromFrame( frameList ) : signal->AppController \n * } \n * \n * ---------------------------------------------------------------------------------------- \n */ class MessageDispatcher : public QObject { Q_OBJECT // friends friend class ::tst_canbus; friend class ::tst_acknow; friend class ::tst_messaging; QHash _messageList; Sequence _txSequence = 0; Sequence _rxSequence = 0; MessageBuilder _builder; MessageInterpreter _interpreter; QThread *_thread = nullptr; bool _init = false; QList _needsAcknow { GuiActionType::ID_AdjustBloodDialysateReq , GuiActionType::ID_AdjustDurationReq , GuiActionType::ID_AdjustUltrafiltrationStateReq , GuiActionType::ID_AdjustUltrafiltrationEditReq , GuiActionType::ID_AdjustUltrafiltrationConfirmReq , }; // Singleton SINGLETON(MessageDispatcher) public slots: bool init(); bool init(QThread &vThread); private slots: void quit(); public: void enableConsoleOut(bool vEnable) { _builder.enableConsoleOut(vEnable); } private: void initConnections(); void initThread(QThread &vThread); void quitThread(); void actionTransmit (GuiActionType vActionId, const QVariantList &vData, Sequence vSequence = 0); void framesTransmit (Can_Id vCan_Id, const FrameList &vFrameList); bool needsAcknow (GuiActionType vActionId); bool buildMessage (Can_Id vCan_Id, const QByteArray &vPayload); bool interpretMessage(const Message &vMessage); Sequence txCount(); Sequence rxCount(); signals: /*! * \brief didActionReceive * \details When a message received over the CANBUS this signal is emitted * on successful collecting all required payloads from different frames if any * and successfully has been built into a message and can be interpreted * \param vAction - The action has been extracted from CANBUS message header to be done * \param vData - The data has been collected from CANBUS frame(s) */ void didActionReceive (GuiActionType vAction , const QVariantList &vData); /*! * \brief didActionReceive * \details Emits when a message requires * \param vData */ void didActionReceive (const Message &vMessage); /*! * \brief didAcknowReceive * \details if the type the received message id is and Acknow this signal will be emitted * \param vData - the data of the Acknow message which is the message Sequence * which we got the Ack for. */ void didAcknowReceive (Sequence vSequence); /*! * \brief didAcknowTransmit * \details this signal will be emitted when the message which has been sent * needs Acknowledge back. * \param vFrameList - the frames which has been send * and will be used to be send on retries. */ void didAcknowTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); /*! * \brief didFrameTransmit * \details When a message is requested to be transmitted this signal is emitted * on successful interpretation and building the message into frames * \param vCan_Id - Target channel of the CANBUS message * \param vPayload - The payload of the message to be sent */ void didFrameTransmit (Can_Id vCan_Id, const QByteArray &vPayload); private slots: // A Frame has been received from CanInterface void onFrameReceive (Can_Id vCan_Id, const QByteArray &vPayload); // void onFramesTransmit (Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); void onFailedTransmit ( Sequence vSequence); // An Action has been requested to be transmitted. void onActionTransmit (GuiActionType vActionId, const QVariantList &vData); // ---- Signal/Slots ADJUST_TRANSMT_MODEL_BRIDGE_DEFINITIONS_NOEMIT ACTION_RECEIVE_MODEL_BRIDGE_DEFINITIONS }; }