Index: LeahiRt/LeahiRtController.h =================================================================== diff -u -r6f9f24886c73d92b380e4c3afd82c0b19559d42d -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- LeahiRt/LeahiRtController.h (.../LeahiRtController.h) (revision 6f9f24886c73d92b380e4c3afd82c0b19559d42d) +++ LeahiRt/LeahiRtController.h (.../LeahiRtController.h) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -1,41 +1,116 @@ +/*! + * + * Copyright (c) 2024-2026 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 LeahiRtController.h + * \author (original) Stephen Quong + * \date (original) 24-May-2026 + * + */ #pragma once #include #include +#include #include #include +#include +#include #include -#include +#include +#include "AgentInterface.h" +#include "AgentMessage.h" #include "CanInterface.h" #include "CanMessage.h" -#include "MessageBuilder.h" -// SQ #include "ProtoInterface.h" +#include "MessageDispatcher.h" using namespace Can; +/*! + * \brief Real-time CAN to cloud controller + * \details Owns the CAN→cloud pipeline. CanInterface receives frames, the + * MessageDispatcher reassembles them per CAN id, and completed messages + * are converted to protobuf and forwarded to the Connectivity Agent + * over the AgentInterface. + */ class LeahiRtController : public QObject { Q_OBJECT public: - explicit LeahiRtController(QObject *parent = nullptr); + explicit LeahiRtController(const QString &configPath, const QString &msgHandlingPath, QObject *parent = nullptr); ~LeahiRtController(); - void openSocket(const QString host, const unsigned int port=80); + /*! + * \brief connectToAgent + * \details Initialises the AgentInterface using the socket path and reconnect + * interval from the settings file. + */ + void connectToAgent(); private: + /*! + * \brief Send message handling policy for a CAN message. + */ + enum class MsgAction { + Drop, ///< Discard the message; do not forward to the Agent. + SendAlways, ///< Forward unconditionally. + SendDelta, ///< Forward only when the payload has changed since the last send. + }; + + /*! + * \brief Message handling entry loaded from message handling INI. + */ + struct MsgHandling { + MsgAction action = MsgAction::Drop; + AgentMessage::MsgId topic = AgentMessage::MsgId::ClinicalData; + }; + + void loadMsgHandling(const QString &msgHandlingPath); + + QSettings _settings; Can::CanInterface _canInterface; QThread _canThread; - QWebSocket _clientSocket; - Can::MessageBuilder _msgBuilder; - QMap _messages; - // SQ proto::ProtoInterface _protoInterface; - // SQ QThread _protoThread; + Can::MessageDispatcher _dispatcher; + QMap> _msgCache; + QHash _msgHandling; + AgentInterface _agentInterface; + QThread _agentThread; + quint16 _txSequence = 0; Q_SIGNALS: + /*! + * \brief didCanMessageReceive + * \details Emitted when a complete CAN message has been reassembled. + * \param timestamp - time the message was completed + * \param msg - the completed message + */ void didCanMessageReceive(const QDateTime timestamp, const Can::Message msg); private Q_SLOTS: + /*! + * \brief onFrameReceive + * \details Unpacks a CAN frame and feeds it to the dispatcher for reassembly. + * \param frame - the received CAN frame + */ void onFrameReceive(const QCanBusFrame frame); + + /*! + * \brief onMessageReceive + * \details Applies the message handling policy: drops, forwards unconditionally, + * or forwards only on payload change, using the INI-configured topic. + * \param msg - the reassembled message + */ + void onMessageReceive(const Can::Message &msg); + + /*! + * \brief onAgentDisconnect + * \details Resets the received flag on all cache entries so that send_delta + * messages are treated as new on the next connection. + */ + void onAgentDisconnect(); };