manifest: add label_pretty and firmware_category fields

Add human-readable labels and firmware classification to the build
manifest so ground stations like QGC can display friendly names and
filter builds by category.

New fields:
- label_pretty: human-readable variant name (e.g. "Multicopter")
- firmware_category: auto-detected classification
  - "vehicle" for multicopter, fixedwing, vtol, rover, uuv, spacecraft
  - "peripheral" for CAN sensor nodes (GPS, flow, mag, etc.)
  - "bootloader" for bootloader/canbootloader
  - "dev" for everything else (default, zenoh, mavlink-dev, etc.)

Peripheral detection uses ROMFSROOT="cannode" which is shared by all
~18 CAN sensor boards across ARK, Holybro, CUAV, Freefly, Matek, NXP.

A build-time warning fires when an unrecognized label falls through to
"dev", so new vehicle types are not silently hidden from end users.

Boards can override via CONFIG_BOARD_FIRMWARE_CATEGORY in .px4board.
CONFIG_BOARD_LABEL_PRETTY set on all px4/fmu-v6x variants as Phase 1.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
This commit is contained in:
Ramon Roche
2026-04-08 17:37:54 -07:00
parent 68c391328a
commit 63f059fd47
19 changed files with 231 additions and 0 deletions
@@ -2,6 +2,13 @@
import argparse, json, os, re, sys
from typing import Dict
_VEHICLE_LABELS = frozenset({
"multicopter", "fixedwing", "vtol", "rover", "uuv", "spacecraft",
})
_BOOTLOADER_LABELS = frozenset({
"bootloader", "canbootloader",
})
def parse_defconfig(path: str) -> Dict[str, str]:
d: Dict[str, str] = {}
if not path or not os.path.exists(path):
@@ -36,6 +43,38 @@ def detect_chip(defcfg: Dict[str,str]) -> str:
s = defcfg.get("CONFIG_ARCH_CHIP", "")
return s.lower().replace("_", "") if s else ""
def detect_firmware_category(target: str, defcfg: Dict[str, str]) -> str:
"""Infer firmware_category from the build label and defconfig.
Detection order:
1. bootloader / canbootloader labels → "bootloader"
2. Known vehicle labels → "vehicle"
3. ROMFSROOT == "cannode" (CAN peripheral boards) → "peripheral"
4. Everything else → "dev"
If you are adding a NEW vehicle type (e.g. "balloon"), you must EITHER:
1. Add the label to _VEHICLE_LABELS in this file, OR
2. Set CONFIG_BOARD_FIRMWARE_CATEGORY="vehicle" in the .px4board file
Otherwise the build will be classified as "dev" and hidden from
end-users in ground stations like QGroundControl.
"""
label = target.rsplit("_", 1)[-1].lower() if target else ""
if label in _BOOTLOADER_LABELS:
return "bootloader"
if label in _VEHICLE_LABELS:
return "vehicle"
# CAN peripheral boards (sensors, GPS, flow, etc.) use cannode ROMFS
romfsroot = defcfg.get("CONFIG_BOARD_ROMFSROOT", "")
if romfsroot == "cannode":
return "peripheral"
if label not in ("default", ""):
print(f"WARNING: label '{label}' (target '{target}') is not a known "
f"vehicle type — defaulting firmware_category to 'dev'. "
f"If this is a vehicle type, add it to _VEHICLE_LABELS in "
f"{__file__} or set CONFIG_BOARD_FIRMWARE_CATEGORY in the "
f".px4board file.", file=sys.stderr)
return "dev"
def pick(preferred: str, fallback_key: str, defcfg: Dict[str, str]) -> str:
return preferred if preferred else defcfg.get(fallback_key, "")
@@ -51,6 +90,8 @@ def main():
ap.add_argument("--chip", default="")
ap.add_argument("--vid", default="")
ap.add_argument("--pid", default="")
ap.add_argument("--label-pretty", default="")
ap.add_argument("--firmware-category", default="")
ap.add_argument("--out", help="Write to file instead of stdout")
args = ap.parse_args()
@@ -64,10 +105,16 @@ def main():
chip = args.chip or detect_chip(defcfg)
vid = norm_hex(pick(args.vid, "CONFIG_CDCACM_VENDORID", defcfg))
pid = norm_hex(pick(args.pid, "CONFIG_CDCACM_PRODUCTID", defcfg))
label_pretty = pick(args.label_pretty, "CONFIG_BOARD_LABEL_PRETTY", defcfg)
firmware_cat = pick(args.firmware_category,"CONFIG_BOARD_FIRMWARE_CATEGORY",defcfg)
if not firmware_cat:
firmware_cat = detect_firmware_category(target, defcfg)
manifest = {
"name": name,
"target": target,
"label_pretty": label_pretty,
"firmware_category": firmware_cat,
"manufacturer": manufacturer,
"hardware": {
"architecture": arch,