@startuml CodeGenPipeline title Build-time Code Generation Pipeline skinparam activityShape octagon skinparam defaultTextAlignment center |Input| start :LeahiUnhandled.conf\n(CAN message definitions); fork ' ── Pipeline A: Protobuf schema ────────────────────────────── |cmake| :generate_protobuf()\ninvokes GenerateProtobuf.py; |MsgUtils Python| :MsgData loads .conf —\nparses message names, IDs,\nfield names and types; |Jinja2 Templates| :MsgDefs_proto.jinja\nrenders LeahiMsgDefs.proto; |protoc| :protoc compiles .proto\ninto C++ stubs\n(LeahiMsgDefs.pb.h / .pb.cc); |CMake build| :pb stubs compiled\ninto MsgUtils library; fork again ' ── Pipeline B: C++ message structs ───────────────────────── |cmake| :generate_msg_defs_cpp()\ninvokes GenerateMsgDefsCpp.py; |MsgUtils Python| :MsgData loads .conf —\nparses message names, IDs,\nfield names and types; |Jinja2 Templates| :MsgDefs_h.jinja renders\nLeahiMsgDefs.h\n(typed structs + toProtobuf /\nfromQByteArray + msgIdString()); :MsgDefs_cpp.jinja renders\nLeahiMsgDefs.cpp\n(method implementations +\ncanMessageToProtobufByteArray() +\nmsgIdString() switch body); :MsgProtoUtils_h.jinja renders\nLeahiMsgProtoUtils.h; :MsgProtoUtils_cpp.jinja renders\nLeahiMsgProtoUtils.cpp; |CMake build| :MsgDefs + MsgProtoUtils compiled\ninto MsgUtils library; fork again ' ── Pipeline C: Message handling INI ──────────────────────── |cmake| :generate_msg_handling_ini()\ninvokes GenerateMsgHandlingIni.py; |MsgUtils Python| :MsgHandlingIni loads .conf —\nseeds each msgId with\naction=drop, topic=; :loadIni() merges existing\nLeahiRtMsgHandling.ini —\npreserves hand-edited\naction + topic values; |Jinja2 Templates| :MsgHandlingIni.jinja renders\nLeahiRtMsgHandling.ini\n(per-msgId: msg_id, action, topic); end fork |Runtime| :LeahiRtController::loadMsgHandling()\nreads LeahiRtMsgHandling.ini at startup; :onMessageReceive() looks up msgId\nin _msgHandling → drop / send_always /\nsend_delta policy, MQTT topic; :canMessageToProtobufByteArray()\nconverts CAN → protobuf bytes; :msgIdString() used in log output; stop note right Pipelines A and B are triggered by the MsgUtils library cmake target; Pipeline C is triggered by the LeahiRt executable cmake target. All three regenerate whenever the .conf file changes. end note @enduml