Problem
MissionCommandTree::friendlyName() / rawName() fall back to MAV_CMD(<number>) for any command without UI info, producing unhelpful log output and UI text (e.g. MAV_CMD(42006) instead of MAV_CMD_ORBIT_YAW_ACQUIRE... etc). The natural fix — looking the name up via QMetaEnum on the generated MAVLinkEnums namespace — does not work today because of a silent moc limitation.
Root cause
tools/generators/mavlink_enums.py generates MAVLinkEnumsQml.h, which exposes every MAVLink enum to the Qt meta-object system / QML via using-imports:
namespace MAVLinkEnums {
Q_NAMESPACE
QML_NAMED_ELEMENT(MAVLinkEnums)
using ::MAV_CMD;
...
Q_ENUM_NS(MAV_CMD)
}
moc registers the enum type for a using-declared enum but produces an empty key table — it never parses the original C header where the enumerators are defined. So QMetaEnum::valueToKey() returns nullptr for every value, and QML-side lookups like MAVLinkEnums.MAV_RESULT_ACCEPTED are also silently broken for all 259 generated enums.
Fix (implemented and validated, then deferred)
Change the generator to parse each enum's keys/values out of the mavgen dialect headers and redefine the enums inside the namespace instead of using-importing them:
namespace MAVLinkEnums {
Q_NAMESPACE
QML_NAMED_ELEMENT(MAVLinkEnums)
enum MAV_CMD {
MAV_CMD_NAV_WAYPOINT = 16,
...
};
Q_ENUM_NS(MAV_CMD)
} // namespace MAVLinkEnums
Implementation notes from the validated prototype:
- New
extract_enum_defs() in the generator: walks each typedef enum X { ... } X; block, strips mavgen's /* ... | */ block comments (DOTALL — comments span lines and can contain decoy NAME=value text), extracts (key, value) pairs with a line-anchored regex.
- Fail-loud validation: every non-comment line of an enum body must match
NAME = <plain decimal or hex literal> exactly (re.fullmatch). Anything else (1 << 3, 1U, enumerator references, valueless entries) raises ValueError naming the enum and quoting the line, failing the build instead of silently emitting an enum with missing keys (which is the current failure mode, just one layer down). This deliberately encodes mavgen's output contract.
MissionCommandTree::_mavCmdEnumName() helper: MAVLinkEnums::staticMetaObject → indexOfEnumerator("MAV_CMD") (warn + numeric fallback if missing) → valueToKey() (numeric fallback if unknown value).
- Unit tests (
tools/tests/test_mavlink_enums.py): key/value parsing including multi-line comments with embedded =99 decoys and >INT_MAX values; assert generated header contains real definitions and no using ::; parametrized fail-loud tests for the four unparsable entry forms.
- Validated against all 19 dialect headers in the build tree: 259 enums, zero validation failures; full app build clean.
The work was backed out to keep the changeset minimal ahead of a stable backport of the initial-connect timeout fixes. Reapply on master when convenient.
Note
RetryableRequestMessageState / other MAVLink message-name logging could use the same populated meta-object once available.
Problem
MissionCommandTree::friendlyName()/rawName()fall back toMAV_CMD(<number>)for any command without UI info, producing unhelpful log output and UI text (e.g.MAV_CMD(42006)instead ofMAV_CMD_ORBIT_YAW_ACQUIRE... etc). The natural fix — looking the name up viaQMetaEnumon the generatedMAVLinkEnumsnamespace — does not work today because of a silent moc limitation.Root cause
tools/generators/mavlink_enums.pygeneratesMAVLinkEnumsQml.h, which exposes every MAVLink enum to the Qt meta-object system / QML via using-imports:moc registers the enum type for a using-declared enum but produces an empty key table — it never parses the original C header where the enumerators are defined. So
QMetaEnum::valueToKey()returnsnullptrfor every value, and QML-side lookups likeMAVLinkEnums.MAV_RESULT_ACCEPTEDare also silently broken for all 259 generated enums.Fix (implemented and validated, then deferred)
Change the generator to parse each enum's keys/values out of the mavgen dialect headers and redefine the enums inside the namespace instead of using-importing them:
Implementation notes from the validated prototype:
extract_enum_defs()in the generator: walks eachtypedef enum X { ... } X;block, strips mavgen's/* ... | */block comments (DOTALL — comments span lines and can contain decoyNAME=valuetext), extracts(key, value)pairs with a line-anchored regex.NAME = <plain decimal or hex literal>exactly (re.fullmatch). Anything else (1 << 3,1U, enumerator references, valueless entries) raisesValueErrornaming the enum and quoting the line, failing the build instead of silently emitting an enum with missing keys (which is the current failure mode, just one layer down). This deliberately encodes mavgen's output contract.MissionCommandTree::_mavCmdEnumName()helper:MAVLinkEnums::staticMetaObject→indexOfEnumerator("MAV_CMD")(warn + numeric fallback if missing) →valueToKey()(numeric fallback if unknown value).tools/tests/test_mavlink_enums.py): key/value parsing including multi-line comments with embedded=99decoys and >INT_MAX values; assert generated header contains real definitions and nousing ::; parametrized fail-loud tests for the four unparsable entry forms.The work was backed out to keep the changeset minimal ahead of a stable backport of the initial-connect timeout fixes. Reapply on master when convenient.
Note
RetryableRequestMessageState/ other MAVLink message-name logging could use the same populated meta-object once available.