@startuml Class_Overview title Leahi Real-time CDT — Class Overview skinparam classAttributeIconSize 0 skinparam class { BackgroundColor<> LightYellow BackgroundColor<> LightCyan } package "LeahiRt (process)" { class LeahiRtController { -_settings: QSettings -_canInterface: Can::CanInterface -_canThread: QThread -_dispatcher: Can::MessageDispatcher -_msgHandling: QHash -_msgCache: QMap> -_agentInterface: AgentInterface -_agentThread: QThread -_txSequence: quint16 __ +LeahiRtController(configPath, msgHandlingPath) +connectToAgent() -loadMsgHandling(msgHandlingPath) __ -onFrameReceive(QCanBusFrame) -onMessageReceive(Can::Message) -onAgentDisconnect() } } package "Comms (lib)" { class "Can::CanInterface" as CanInterface { -_canDevice: QSharedPointer -_rxFrameCount: FrameCount -_txFrameCount: FrameCount -_erFrameCount: FrameCount __ +init(thread: QThread&): bool +quitDevice() +enableConsoleOut(bool) +status(): QString __ +didFrameReceive(QCanBusFrame) <> +didFrameTransmit(bool) <> +didFrameError(QString) <> +didFrameWritten(qint64) <> __ -onFrameReceive() <> -onFrameTransmit(QCanBusFrame) <> -onFrameError(CanBusError) <> -onFrameWritten(qint64) <> } class AgentInterface { -_socket: QLocalSocket -_reconnectTimer: QTimer -_socketPath: QString -_rxBuf: QByteArray -_rxMsg: AgentMessage __ +init(socketPath, reconnectIntervalMs, thread): bool +send(msgId, sequence, payload): bool +quit() <> __ +didMessageReceive(MsgId, seq, payload) <> +didConnect() <> +didDisconnect() <> __ -onConnected() <> -onDisconnected() <> -onError(LocalSocketError) <> -onReadyRead() <> -onReconnectTimer() <> } } package "MsgUtils (lib)" { class "Can::MessageDispatcher" as MessageDispatcher { -_messageList: QHash -_rxSequence: Sequence -_builder: Can::MessageBuilder __ +didActionReceive(Can::Message) <> __ +onFrameReceive(CanId, payload) <> -buildMessage(CanId, payload): bool -rxCount(): Sequence } class "Can::MessageBuilder" as MessageBuilder { __ +buildFrames(MsgId, data, frameList, sequence): bool +buildMessage(payload, message, canId): bool +enableConsoleOut(bool) } class AgentMessage { -_headerBuf: QByteArray -_rxMsgId: MsgId -_rxSequence: quint16 -_rxPayloadLen: quint32 -_rxPayload: QByteArray __ +{static} build(msgId, sequence, payload): QByteArray +feed(bytes: QByteArray&): FeedResult +msgId(): MsgId +sequence(): quint16 +payload(): QByteArray +reset() } enum "AgentMessage::MsgId" as AgentMsgId { ClinicalData = 0x0001 Diagnostic = 0x0002 Ack = 0x0003 Alarms = 0x0004 Audit = 0x0005 DeviceLogFile = 0x0006 TreatmentLogFile = 0x0007 CloudSyncLogFile = 0x0008 } enum "AgentMessage::FeedResult" as FeedResult { Incomplete Complete HeaderError PayloadError } } package "AgentSim (process)" { class AgentSimController <> { -_settings: QSettings -_server: QLocalServer -_client: QLocalSocket* -_rxBuf: QByteArray -_rxMsg: AgentMessage __ +listen(): bool -handleMessage(AgentMessage) -logMessage(MsgId, seq, payload) __ -onNewConnection() <> -onDisconnected() <> -onReadyRead() <> } } package "CANDumpPlayer (process)" { class "CANDumpPlayer\n(main)" <> { +can_interface: string +candump_file: string +--speed: double +--test: bool __ Parses candump log and replays\nframes onto SocketCAN at a\nconfigurable speed multiplier } } ' --- composition --- LeahiRtController *-- CanInterface LeahiRtController *-- AgentInterface LeahiRtController *-- MessageDispatcher ' --- internal composition --- MessageDispatcher *-- MessageBuilder ' --- usage --- AgentInterface ..> AgentMessage : uses AgentSimController ..> AgentMessage : uses ' --- enum nesting --- AgentMessage +-- AgentMsgId AgentMessage +-- FeedResult ' --- layout hints --- CanInterface -[hidden]- AgentInterface @enduml