Index: LeahiRt/CMakeLists.txt =================================================================== diff -u -r9d547159d805f3a0b0f2f6a11f4e34feb5117b65 -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- LeahiRt/CMakeLists.txt (.../CMakeLists.txt) (revision 9d547159d805f3a0b0f2f6a11f4e34feb5117b65) +++ LeahiRt/CMakeLists.txt (.../CMakeLists.txt) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -27,11 +27,11 @@ main.cpp ) -generate_message_ini(LEAHI_MSG_CONF ${CMAKE_CURRENT_SOURCE_DIR}/config/LeahiRtMessage.ini generate_message_ini) +generate_msg_handling_ini(LEAHI_MSG_CONF ${CMAKE_CURRENT_SOURCE_DIR}/config/LeahiRtMsgHandling.ini generate_msg_handling_ini) add_executable(${PROJECT_NAME}) -add_dependencies(${PROJECT_NAME} generate_message_ini) +add_dependencies(${PROJECT_NAME} generate_msg_handling_ini) target_sources(${PROJECT_NAME} PRIVATE ${INCLUDES} ${SRCS}) Index: LeahiRt/LeahiRtController.cpp =================================================================== diff -u -r402926738e7394ee2d3dc7add2e6d755f06a289d -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- LeahiRt/LeahiRtController.cpp (.../LeahiRtController.cpp) (revision 402926738e7394ee2d3dc7add2e6d755f06a289d) +++ LeahiRt/LeahiRtController.cpp (.../LeahiRtController.cpp) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -20,19 +20,23 @@ * \brief LeahiRtController::LeahiRtController * \details Constructor. Starts the CAN interface and wires the frame→dispatcher→ * completed-message pipeline. - * \param configPath - path to the settings file - * \param parent - optional QObject parent + * \param configPath - path to the settings file + * \param msgHandlingPath - path to the message handling INI + * \param parent - optional QObject parent */ -LeahiRtController::LeahiRtController(const QString &configPath, QObject *parent) : +LeahiRtController::LeahiRtController(const QString &configPath, const QString &msgHandlingPath, QObject *parent) : QObject(parent), _settings(configPath, QSettings::IniFormat), _canInterface(), _canThread(this), _dispatcher(this) { + loadMsgHandling(msgHandlingPath); + _canInterface.init(_canThread); connect(&_canInterface, &Can::CanInterface::didFrameReceive, this, &LeahiRtController::onFrameReceive); connect(&_dispatcher, &Can::MessageDispatcher::didActionReceive, this, &LeahiRtController::onMessageReceive); + connect(&_agentInterface, &AgentInterface::didDisconnect, this, &LeahiRtController::onAgentDisconnect); } /*! @@ -61,6 +65,64 @@ } /*! + * \brief LeahiRtController::loadMsgHandling + * \details Parses message handling INI and populates _msgHandling. + * \note Unknown msg action values default to Drop; unknown topic strings default to ClinicalData. + * \param msgHandlingPath - path to the message handling INI file + */ +void LeahiRtController::loadMsgHandling(const QString &msgHandlingPath) +{ + static const QHash actionMap = { + { QStringLiteral("send_always"), MsgAction::SendAlways }, + { QStringLiteral("send_delta"), MsgAction::SendDelta }, + { QStringLiteral("drop"), MsgAction::Drop }, + }; + static const QHash topicMap = { + { QStringLiteral("ClinicalData"), AgentMessage::MsgId::ClinicalData }, + { QStringLiteral("Diagnostic"), AgentMessage::MsgId::Diagnostic }, + { QStringLiteral("Ack"), AgentMessage::MsgId::Ack }, + { QStringLiteral("Alarms"), AgentMessage::MsgId::Alarms }, + { QStringLiteral("Audit"), AgentMessage::MsgId::Audit }, + { QStringLiteral("DeviceLogFile"), AgentMessage::MsgId::DeviceLogFile }, + { QStringLiteral("TreatmentLogFile"), AgentMessage::MsgId::TreatmentLogFile }, + { QStringLiteral("CloudSyncLogFile"), AgentMessage::MsgId::CloudSyncLogFile }, + }; + + QSettings msgHandlingIni(msgHandlingPath, QSettings::IniFormat); + if (msgHandlingIni.status() != QSettings::NoError) { + qWarning().noquote() << "LeahiRt: could not read message handling INI" << msgHandlingPath << "— all messages will be dropped"; + return; + } + + int loaded = 0; + for (const QString &group : msgHandlingIni.childGroups()) { + bool ok = false; + const Can::MsgId msgId = static_cast(group.toUInt(&ok, 16)); + if (!ok) { + continue; + } + + msgHandlingIni.beginGroup(group); + const QString actionStr = msgHandlingIni.value(QStringLiteral("action"), QStringLiteral("drop")).toString().trimmed(); + const QString topicStr = msgHandlingIni.value(QStringLiteral("topic")).toString().trimmed(); + msgHandlingIni.endGroup(); + + MsgHandling msgHandling; + msgHandling.action = actionMap.value(actionStr, MsgAction::Drop); + msgHandling.topic = topicMap.value(topicStr, AgentMessage::MsgId::ClinicalData); + + if (!actionMap.contains(actionStr)) { + qWarning().noquote() << QString("LeahiRt: unknown message action \"%1\" for msgId=0x%2 — defaulting to drop") + .arg(actionStr).arg(msgId, 4, 16, QChar('0')); + } + + _msgHandling.insert(msgId, msgHandling); + loaded++; + } + qInfo().noquote() << QString("LeahiRt: loaded message handling %1 (%2 entries)").arg(msgHandlingPath).arg(loaded); +} + +/*! * \brief LeahiRtController::onFrameReceive * \details Unpacks a CAN frame and feeds it to the dispatcher, which reassembles * multi-frame messages per CAN id. @@ -73,25 +135,51 @@ /*! * \brief LeahiRtController::onMessageReceive - * \details Converts a fully reassembled message to protobuf and forwards it to - * the Agent. + * \details Applies the message handling policy from LeahiRtMsgHandling.ini: drops, + * forwards unconditionally, or forwards only on payload change. Uses the + * section's topic to set the AgentMessage frame msg_id. * \param msg - the reassembled message */ void LeahiRtController::onMessageReceive(const Can::Message &msg) { - Can::Message &cachedMsg = _msgCache[msg.msgId]; - qDebug().noquote() << QString("Received message with MsgId=0x%1").arg(QString("%1").arg(msg.msgId, 4, 16, QChar('0')).toUpper()); + const auto it = _msgHandling.constFind(msg.msgId); + if (it == _msgHandling.constEnd()) { + qInfo().noquote() << QString("LeahiRt: no action defined for %1 (0x%2), dropping") + .arg(leahi::msgIdString(leahi::MsgId(msg.msgId))).arg(msg.msgId, 4, 16, QChar('0')); + return; + } - // only send the message if the data is different - // SQ if (cachedMsg.data != msg.data) { - // SQ if (msg.msgId == leahi::MSG_ID_TD_OP_MODE_DATA) { - const QByteArray payload = leahi::canMessageToProtobufByteArray( - QDateTime::currentDateTime(), - QStringLiteral("test_device"), - msg); - _agentInterface.send(AgentMessage::MsgId::ClinicalData, _txSequence++, payload); - // SQ } - // SQ } - cachedMsg = msg; - msg.dump(); + if (it->action == MsgAction::Drop) { + qInfo().noquote() << QString("LeahiRt: dropping message %1 (0x%2)") + .arg(leahi::msgIdString(leahi::MsgId(msg.msgId))).arg(msg.msgId, 4, 16, QChar('0')); + return; + } + + auto &[received, cachedMsg] = _msgCache[msg.msgId]; + if (it->action == MsgAction::SendDelta && received && + cachedMsg.data.chopped(1) == msg.data.chopped(1)) { + qInfo().noquote() << QString("LeahiRt: received message %1 (0x%2) did not changed from previous, dropping") + .arg(leahi::msgIdString(leahi::MsgId(msg.msgId))).arg(msg.msgId, 4, 16, QChar('0')); + return; + } + + const QByteArray payload = leahi::canMessageToProtobufByteArray( + QDateTime::currentDateTime(), + QStringLiteral("test_device"), + msg); + _agentInterface.send(it->topic, _txSequence++, payload); + received = true; + cachedMsg = msg; } + +/*! + * \brief LeahiRtController::onAgentDisconnect + * \details Resets the received flag on all cache entries so that send_delta + * messages are treated as new on the next connection. + */ +void LeahiRtController::onAgentDisconnect() +{ + for (auto &[received, msg] : _msgCache) { + received = false; + } +} Index: LeahiRt/LeahiRtController.h =================================================================== diff -u -r088513e6ea7bad08b4fb7862127c726eabad18fd -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- LeahiRt/LeahiRtController.h (.../LeahiRtController.h) (revision 088513e6ea7bad08b4fb7862127c726eabad18fd) +++ LeahiRt/LeahiRtController.h (.../LeahiRtController.h) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -14,11 +14,13 @@ #include #include +#include #include #include #include #include #include +#include #include "AgentInterface.h" #include "AgentMessage.h" @@ -40,7 +42,7 @@ Q_OBJECT public: - explicit LeahiRtController(const QString &configPath, QObject *parent = nullptr); + explicit LeahiRtController(const QString &configPath, const QString &msgHandlingPath, QObject *parent = nullptr); ~LeahiRtController(); /*! @@ -51,11 +53,31 @@ 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; Can::MessageDispatcher _dispatcher; - QMap _msgCache; + QMap> _msgCache; + QHash _msgHandling; AgentInterface _agentInterface; QThread _agentThread; quint16 _txSequence = 0; @@ -79,8 +101,16 @@ /*! * \brief onMessageReceive - * \details Converts a completed message to protobuf and forwards it to the Agent. + * \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(); }; Index: LeahiRt/main.cpp =================================================================== diff -u -r402926738e7394ee2d3dc7add2e6d755f06a289d -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- LeahiRt/main.cpp (.../main.cpp) (revision 402926738e7394ee2d3dc7add2e6d755f06a289d) +++ LeahiRt/main.cpp (.../main.cpp) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -54,10 +54,16 @@ {"c", "config"}, "Path to the configuration INI file.", "config", QDir(app.applicationDirPath()).filePath("config/LeahiRt.ini") ); + QCommandLineOption msgHandlingOption( + {"m", "msg_handling"}, "Path to the message handling INI file.", "msg_handling", + QDir(app.applicationDirPath()).filePath("config/LeahiRtMsgHandling.ini") + ); parser.addOption(configOption); + parser.addOption(msgHandlingOption); parser.process(app); - LeahiRtController rtController(parser.value(configOption)); + LeahiRtController rtController(parser.value(configOption), + parser.value(msgHandlingOption)); rtController.connectToAgent(); return app.exec(); Index: lib/Comms/src/AgentInterface.cpp =================================================================== diff -u -r402926738e7394ee2d3dc7add2e6d755f06a289d -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- lib/Comms/src/AgentInterface.cpp (.../AgentInterface.cpp) (revision 402926738e7394ee2d3dc7add2e6d755f06a289d) +++ lib/Comms/src/AgentInterface.cpp (.../AgentInterface.cpp) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -77,7 +77,7 @@ /*! * \brief AgentInterface::send * \details Builds an AgentMessage frame and writes it to the socket. - * \param msgId - message identifier for Agent MQTT routing + * \param msgId - message identifier for Agent MQTT topic * \param sequence - caller-managed sequence number * \param payload - message payload; pass empty for zero-length frames * \return true if written to the socket, false if not connected Index: lib/MsgUtils/cmake/MsgUtils.cmake =================================================================== diff -u -r9d547159d805f3a0b0f2f6a11f4e34feb5117b65 -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- lib/MsgUtils/cmake/MsgUtils.cmake (.../MsgUtils.cmake) (revision 9d547159d805f3a0b0f2f6a11f4e34feb5117b65) +++ lib/MsgUtils/cmake/MsgUtils.cmake (.../MsgUtils.cmake) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -61,7 +61,7 @@ # \param[in] _input_confs list of message conf files to use to generate the INI # \param[in] _output_ini path to the INI file to create or update # \param[in] _target_name name of the custom target to add -function(generate_message_ini _input_confs _output_ini _target_name) +function(generate_msg_handling_ini _input_confs _output_ini _target_name) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _output_ini) @@ -78,14 +78,14 @@ add_custom_command( DEPENDS ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgData.py - ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgIni.py - ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgIni.py - ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgIni.jinja + ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgHandlingIni.py + ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgHandlingIni.py + ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgHandlingIni.jinja ${${_input_confs}} OUTPUT ${_output_ini} COMMAND - ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgIni.py + ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgHandlingIni.py ${${_input_confs}} ${_output_ini} COMMENT "Generating/updating message INI ${_output_ini} from input ${_file_list}" Index: lib/MsgUtils/include/AgentMessage.h =================================================================== diff -u -r088513e6ea7bad08b4fb7862127c726eabad18fd -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- lib/MsgUtils/include/AgentMessage.h (.../AgentMessage.h) (revision 088513e6ea7bad08b4fb7862127c726eabad18fd) +++ lib/MsgUtils/include/AgentMessage.h (.../AgentMessage.h) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -41,7 +41,7 @@ { public: /*! - * \brief MQTT routing identifier carried in every frame header + * \brief MQTT topic identifier carried in every frame header * \details The Connectivity Agent uses this value to determine the MQTT topic. */ enum class MsgId : quint16 { Index: lib/MsgUtils/src/AgentMessage.cpp =================================================================== diff -u -r088513e6ea7bad08b4fb7862127c726eabad18fd -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- lib/MsgUtils/src/AgentMessage.cpp (.../AgentMessage.cpp) (revision 088513e6ea7bad08b4fb7862127c726eabad18fd) +++ lib/MsgUtils/src/AgentMessage.cpp (.../AgentMessage.cpp) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -21,7 +21,7 @@ /*! * \brief AgentMessage::build * \details Builds a complete wire-ready frame with header and optional payload CRCs. - * \param msgId - message identifier for Agent MQTT routing + * \param msgId - message identifier for Agent MQTT topic * \param sequence - caller-managed sequence number * \param payload - optional payload; pass empty for zero-length frames (e.g. Ack) * \return complete frame ready to write to the transport Index: scripts/MsgUtils/GenerateMsgHandlingIni.py =================================================================== diff -u --- scripts/MsgUtils/GenerateMsgHandlingIni.py (revision 0) +++ scripts/MsgUtils/GenerateMsgHandlingIni.py (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import argparse +import os +import sys +from msgutils import MsgHandlingIni + +def main(): + parser = argparse.ArgumentParser( + description='Tool for generating/updating the message handling INI from the inputted message conf file(s)' + ) + parser.add_argument('conf', nargs='+') + parser.add_argument('output', help='path to the message handling INI to create or update') + + args = parser.parse_args() + if len(sys.argv) < 3: + parser.print_help() + else: + msg_ini = MsgHandlingIni() + try: + for conf in args.conf: + msg_ini.loadConf(conf, clear=False) + msg_ini.loadIni(args.output) + output_dir = os.path.dirname(os.path.abspath(args.output)) + os.makedirs(output_dir, exist_ok=True) + msg_ini.write_ini(args.output) + except Exception as e: + print('Error: %s' % e) + sys.exit(1) + +if __name__ == "__main__": # calling main function + main() Fisheye: Tag ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f refers to a dead (removed) revision in file `scripts/MsgUtils/GenerateMsgIni.py'. Fisheye: No comparison available. Pass `N' to diff? Index: scripts/MsgUtils/msgutils/MsgHandlingIni.py =================================================================== diff -u --- scripts/MsgUtils/msgutils/MsgHandlingIni.py (revision 0) +++ scripts/MsgUtils/msgutils/MsgHandlingIni.py (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -0,0 +1,85 @@ +import configparser +import sys +from pathlib import Path +from jinja2 import Environment, FileSystemLoader +from .MsgData import MsgData + + +# \brief Generates and maintains the message handling INI from loaded message data. +# \details One section per message keyed by hex msgId (e.g. [0x0100]), carrying: +# msg_id - the MSG_ID_* reference name, regenerated from the conf on every run. +# action - send_always | send_delta | drop; defaults to drop, preserved across runs. +# topic - MQTT topic; empty by default, preserved across runs. +# Call loadConf() to load message definitions, then loadIni() to merge in existing +# action/topic values, then write_ini() to write the result. +class MsgHandlingIni(MsgData): + DEFAULT_ACTION = 'drop' + VALID_ACTIONS = ('send_always', 'send_delta', 'drop') + + # \brief Initializer + def __init__(self): + super().__init__() + + + # \brief Load a .conf file and cache the data, enriching each entry with default INI fields. + # \param[in] filename Filename of the .conf to load. + # \param[in] clear If true, clear any previously loaded data before processing. + # \return none + def loadConf(self, filename, clear=True): + super().loadConf(filename, clear) + for msg in self.data.values(): + msg['action'] = self.DEFAULT_ACTION + msg['topic'] = '' + + + # \brief Merge action/topic values from an existing INI into the loaded message data. + # \details Only action and topic are read; msg_id is always regenerated from the conf. + # Sections in the INI that are no longer in the conf are ignored (and warned if + # they carried non-default values). Unknown action values are reset to drop. + # \param[in] filename Path to the existing INI file; no-op if the file does not exist. + # \return none + def loadIni(self, filename): + path = Path(filename) + if not path.is_file(): + return + cfg = configparser.ConfigParser(inline_comment_prefixes=(';',)) + cfg.read(path, encoding='utf-8') + + # just use self.data.keys() + conf_keys = set(MsgData.value_to_hex_string(v) for v in self.data.keys()) + + for section in cfg.sections(): + try: + msg_id_value = int(section, 16) + except ValueError: + print(f"WARNING: could not convert section message ID {section} to valid message ID, skipping") + continue + if msg_id_value not in self.data.keys(): + action = cfg.get(section, 'action', fallback=self.DEFAULT_ACTION).strip() + topic = cfg.get(section, 'topic', fallback='').strip() + if action != self.DEFAULT_ACTION or topic: + print(f"WARNING: {MsgData.value_to_hex_string(msg_id_value)} no longer in Unhandled.conf, " + f"dropping section with action={action} topic={topic or ''}") + continue + + action = cfg.get(section, 'action', fallback=self.DEFAULT_ACTION).strip() + if action not in self.VALID_ACTIONS: + print(f"WARNING: {MsgData.value_to_hex_string(msg_id_value)} has invalid action \"{action}\", " + f"resetting to {self.DEFAULT_ACTION}") + action = self.DEFAULT_ACTION + + self.data[msg_id_value]['action'] = action + self.data[msg_id_value]['topic'] = cfg.get(section, 'topic', fallback='').strip() + + + # \brief Write the loaded message data to the INI file. + # \param[in] filename Path to the INI file to create or update. + # \return none + def write_ini(self, filename): + env = Environment(loader=FileSystemLoader(f'{Path(__file__).parent.absolute()}/templates'), + keep_trailing_newline=True) + template = env.get_template('MsgHandlingIni.jinja') + render = template.render({'msg_ini': self}) + with open(filename, mode='w', encoding='utf-8', newline='\n') as out_file: + out_file.write(render) + print(f"Wrote message INI {filename} with {len(self.data)} messages") Fisheye: Tag ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f refers to a dead (removed) revision in file `scripts/MsgUtils/msgutils/MsgIni.py'. Fisheye: No comparison available. Pass `N' to diff? Index: scripts/MsgUtils/msgutils/__init__.py =================================================================== diff -u -r8165b9eb5d23253e5d38b6ffde9d1a21cb1cbc52 -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- scripts/MsgUtils/msgutils/__init__.py (.../__init__.py) (revision 8165b9eb5d23253e5d38b6ffde9d1a21cb1cbc52) +++ scripts/MsgUtils/msgutils/__init__.py (.../__init__.py) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -1,4 +1,4 @@ from .MsgData import MsgData from .MsgCpp import MsgCpp from .MsgProtobuf import MsgProtobuf -from .MsgIni import MsgIni +from .MsgHandlingIni import MsgHandlingIni Index: scripts/MsgUtils/msgutils/templates/MsgDefs_cpp.jinja =================================================================== diff -u -r402926738e7394ee2d3dc7add2e6d755f06a289d -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- scripts/MsgUtils/msgutils/templates/MsgDefs_cpp.jinja (.../MsgDefs_cpp.jinja) (revision 402926738e7394ee2d3dc7add2e6d755f06a289d) +++ scripts/MsgUtils/msgutils/templates/MsgDefs_cpp.jinja (.../MsgDefs_cpp.jinja) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -1,12 +1,24 @@ {%- if msg_defs_header | length -%} #include "{{ msg_defs_header }}" {%- endif %} + +#include {%- if cpp_namespace is defined and cpp_namespace is not none %} namespace {{ cpp_namespace }} { {%- endif %} + +QString msgIdString(const MsgId msgId) +{ + switch (msgId) { {%- for (msg_id_value, msg) in msg_cpp.data.items() %} + case {{ msg['msg_id'] }}: return QStringLiteral("{{ msg['msg_id'] }}"); +{%- endfor %} + default: return QStringLiteral("0x%1").arg(static_cast(msgId), 4, 16, QChar('0')); + } +} +{%- for (msg_id_value, msg) in msg_cpp.data.items() %} // {{ msg['msg_id'] }} ({{ msg['msg_id_hex_string'] }}) // payload: {{ msg_cpp.field_list(msg_id_value) | join(", ") }} Index: scripts/MsgUtils/msgutils/templates/MsgDefs_h.jinja =================================================================== diff -u -r402926738e7394ee2d3dc7add2e6d755f06a289d -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- scripts/MsgUtils/msgutils/templates/MsgDefs_h.jinja (.../MsgDefs_h.jinja) (revision 402926738e7394ee2d3dc7add2e6d755f06a289d) +++ scripts/MsgUtils/msgutils/templates/MsgDefs_h.jinja (.../MsgDefs_h.jinja) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -23,6 +23,8 @@ {%- endfor %} }; +QString msgIdString(const MsgId msgId); + enum ParamType { {%- for type in msg_cpp.paramTypes %} {{ type }}, Index: scripts/MsgUtils/msgutils/templates/MsgHandlingIni.jinja =================================================================== diff -u --- scripts/MsgUtils/msgutils/templates/MsgHandlingIni.jinja (revision 0) +++ scripts/MsgUtils/msgutils/templates/MsgHandlingIni.jinja (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -0,0 +1,7 @@ +{%- for msg in msg_ini.data.values() -%} +[{{ msg.msg_id_hex_string }}] +msg_id = {{ msg.msg_id }} +action = {{ msg.action }} +topic = {{ msg.topic }} + +{% endfor -%} Fisheye: Tag ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f refers to a dead (removed) revision in file `scripts/MsgUtils/msgutils/templates/MsgIni.jinja'. Fisheye: No comparison available. Pass `N' to diff? Index: scripts/MsgUtils/pyproject.toml =================================================================== diff -u -r8165b9eb5d23253e5d38b6ffde9d1a21cb1cbc52 -rccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f --- scripts/MsgUtils/pyproject.toml (.../pyproject.toml) (revision 8165b9eb5d23253e5d38b6ffde9d1a21cb1cbc52) +++ scripts/MsgUtils/pyproject.toml (.../pyproject.toml) (revision ccc40a7e73e9ee5d2a5fb56f3f2bea4f8294900f) @@ -12,7 +12,7 @@ [project.scripts] GenerateMsgDefsCpp = "GenerateMsgDefsCpp:main" GenerateProtobuf = "GenerateProtobuf:main" -GenerateMsgIni = "GenerateMsgIni:main" +GenerateMsgHandlingIni = "GenerateMsgHandlingIni:main" [tool.setuptools.packages.find] exclude = ["test*"]