@startuml CodeGenPipeline title Build-time Code Generation Pipeline skinparam activityShape octagon skinparam defaultTextAlignment center |Input| start :LeahiUnhandled.conf\n(CAN message definitions); |Build system| if (build system) then (qmake) :extra-compilers "proto", "msgdefs", "canrouting"\nin MsgUtils.pro / CloudConnect.pro; else (cmake) :generate_protobuf(),\ngenerate_msg_defs_cpp(),\ngenerate_can_routing_ini()\nin lib/MsgUtils/cmake; endif :invoke the generator scripts\n(GenerateProtobuf.py, GenerateMsgDefsCpp.py,\nGenerateCanRoutingIni.py)\nusing the shared Python venv; |MsgUtils Python| :MsgData.loadConf() parses .conf —\nmessage names, IDs,\nfield names and types; fork ' ── Pipeline A: Protobuf schema ────────────────────────────── |Jinja2 Templates| :MsgDefs_proto.jinja\nrenders LeahiMsgDefs.proto; |protoc| :protoc --cpp_out compiles .proto\ninto C++ stubs\n(LeahiMsgDefs.pb.h / .pb.cc); |Build| :pb.h/cpp files compiled\ninto MsgUtils library; fork again ' ── Pipeline B: C++ message structs ───────────────────────── |Jinja2 Templates| :MsgDefs_h.jinja renders\nLeahiMsgDefs.h\n(msg structs with fromQByteArray /\ntoQByteArray); :MsgDefs_cpp.jinja renders\nLeahiMsgDefs.cpp; :MsgProtoUtils_h.jinja renders\nLeahiMsgProtoUtils.h; :MsgProtoUtils_cpp.jinja renders\nLeahiMsgProtoUtils.cpp\n(canMessageToProtobufByteArray()); |Build| :MsgDefs + MsgProtoUtils compiled\ninto MsgUtils library; fork again ' ── Pipeline C: CAN routing INI ───────────────────────────── |MsgUtils Python| :CanRoutingIni.loadConf() extends it —\nto add CAN message handling; :loadIni() merges the existing\nLeahiCanRouting.ini —\nto preserve changes to original file; |Jinja2 Templates| :CanRoutingIni.jinja renders\nLeahiCanRouting.ini\n(msg_id, action, topic); end fork |Runtime| :**CloudConnectController** ==== * loadConfig(): reads CloudConnect.ini * loadCanRouting(): reads LeahiCanRouting.ini * onCanMessageReceive(): CAN msg → protobuf and routes msg * canMessageToProtobufByteArray(): converts CAN → protobuf; stop @enduml