From 03d705fd86d40e52e2922071c907385b4ce6ace6 Mon Sep 17 00:00:00 2001 From: j-w9 <295470691+j-w9@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:42:41 -0400 Subject: [PATCH] HardwareReport: show vehicle, frame and configured outputs --- HardwareReport/HardwareReport.js | 179 +++++++++- HardwareReport/index.html | 6 + HardwareReport/param_values.json | 550 +++++++++++++++++++++++++++++++ 3 files changed, 734 insertions(+), 1 deletion(-) create mode 100644 HardwareReport/param_values.json diff --git a/HardwareReport/HardwareReport.js b/HardwareReport/HardwareReport.js index 0f2116a4..15cb1585 100644 --- a/HardwareReport/HardwareReport.js +++ b/HardwareReport/HardwareReport.js @@ -1701,6 +1701,168 @@ function load_params(log) { } +// Names for build types used in param_values.json and for display +const vehicle_build_types = { + 1: { key: "ArduRover", name: "Rover" }, + 2: { key: "ArduCopter", name: "Copter" }, + 3: { key: "ArduPlane", name: "Plane" }, + 4: { key: "AntennaTracker", name: "Antenna Tracker" }, + 7: { key: "ArduSub", name: "Sub" }, + 12: { key: "Blimp", name: "Blimp" }, +} + +// Get the name of a param value from param_values.json, or the value if no name is found +function get_param_value_name(vehicle_key, list, value) { + if ((vehicle_key in param_values) && (list in param_values[vehicle_key]) && (value in param_values[vehicle_key][list])) { + return param_values[vehicle_key][list][value] + } + return value.toString() +} + +// Show vehicle and frame type +function show_vehicle(build_type) { + if (!(build_type in vehicle_build_types)) { + return + } + const vehicle = vehicle_build_types[build_type] + + let section = document.getElementById("VEHICLE") + section.hidden = false + section.previousElementSibling.hidden = false + + let name = vehicle.name + let frame_params = [] + switch (vehicle.key) { + case "ArduCopter": + case "ArduRover": + frame_params = ["FRAME_CLASS", "FRAME_TYPE"] + break + + case "ArduPlane": + if (("Q_ENABLE" in params) && (params.Q_ENABLE > 0)) { + name = "QuadPlane" + if (("Q_TILT_ENABLE" in params) && (params.Q_TILT_ENABLE > 0)) { + name += ", tilt-rotor" + } + if (("Q_TAILSIT_ENABLE" in params) && (params.Q_TAILSIT_ENABLE > 0)) { + name += ", tailsitter" + } + frame_params = ["Q_FRAME_CLASS", "Q_FRAME_TYPE"] + } + break + + case "ArduSub": + frame_params = ["FRAME_CONFIG"] + break + } + + section.appendChild(document.createTextNode(name)) + for (const param of frame_params) { + if (!(param in params)) { + continue + } + section.appendChild(document.createElement("br")) + section.appendChild(document.createTextNode(param + ": " + get_param_value_name(vehicle.key, param, params[param]))) + } +} + +// Show configured output functions +function show_outputs(build_type) { + + // Use the names for this vehicle, if unknown use the first name found + let function_names = {} + if (build_type in vehicle_build_types) { + const key = vehicle_build_types[build_type].key + if (key in param_values) { + function_names = param_values[key].SERVO_FUNCTION + } + } else { + for (const values of Object.values(param_values)) { + function_names = Object.assign({}, values.SERVO_FUNCTION, function_names) + } + } + + // DroneCAN drivers, check that the driver is assigned to a port and that it uses DroneCAN + let can_drivers = [] + for (let driver = 1; driver <= 3; driver++) { + let assigned = false + for (let port = 1; port <= 3; port++) { + const name = "CAN_P" + port + "_DRIVER" + if ((name in params) && (params[name] == driver)) { + assigned = true + } + } + const prefix = "CAN_D" + driver + "_" + if (!assigned || !((prefix + "PROTOCOL") in params) || (params[prefix + "PROTOCOL"] != 1)) { + continue + } + can_drivers.push({ prefix, esc: params[prefix + "UC_ESC_BM"] || 0, servo: params[prefix + "UC_SRV_BM"] || 0 }) + } + + let outputs = [] + for (let i = 1; i <= 32; i++) { + const name = "SERVO" + i + "_FUNCTION" + if (!(name in params) || (params[name] == 0)) { + continue + } + const value = params[name] + let func = (value in function_names) ? function_names[value] : "Unknown" + func += " (" + value + ")" + + let can = [] + for (const driver of can_drivers) { + const bit = 1 << (i - 1) + if (driver.esc & bit) { + can.push("DroneCAN ESC (" + driver.prefix + "UC_ESC_BM)") + } + if (driver.servo & bit) { + can.push("DroneCAN servo (" + driver.prefix + "UC_SRV_BM)") + } + } + outputs.push({ output: i, func, can: can.join(", ") }) + } + + if (outputs.length == 0) { + return + } + + let section = document.getElementById("OUTPUTS") + section.hidden = false + section.previousElementSibling.hidden = false + + const show_can = outputs.some((output) => output.can.length > 0) + + let table = document.createElement("table") + table.style.borderCollapse = "collapse" + section.appendChild(table) + + function add_cell(row, type, text) { + let cell = document.createElement(type) + cell.style.border = "1px solid #000" + cell.style.padding = "4px 8px" + cell.appendChild(document.createTextNode(text)) + row.appendChild(cell) + } + + let header = document.createElement("tr") + table.appendChild(header) + add_cell(header, "th", "Output") + add_cell(header, "th", "Function") + if (show_can) { + add_cell(header, "th", "Also sent over CAN") + } + + for (const output of outputs) { + let row = document.createElement("tr") + table.appendChild(row) + add_cell(row, "td", output.output) + add_cell(row, "td", output.func) + if (show_can) { + add_cell(row, "td", output.can) + } + } +} + function load_param_file(text) { var lines = text.split('\n') params = {} @@ -1716,6 +1878,9 @@ function load_param_file(text) { load_params() + // Vehicle type is unknown from a param file + show_outputs(null) + } let can @@ -2635,6 +2800,9 @@ async function load_log(log_file) { } } + show_vehicle(version.build_type) + show_outputs(version.build_type) + // Look for watchdog show_watchdog(log) @@ -3179,6 +3347,7 @@ function reset() { setup_section(document.getElementById("warnings")) setup_section(document.getElementById("VER")) setup_section(document.getElementById("FC")) + setup_section(document.getElementById("VEHICLE")) setup_section(document.getElementById("WDOG")) setup_section(document.getElementById("InternalError")) setup_section(document.getElementById("IOMCU")) @@ -3187,6 +3356,7 @@ function reset() { setup_section(document.getElementById("BARO")) setup_section(document.getElementById("ARSPD")) setup_section(document.getElementById("DroneCAN")) + setup_section(document.getElementById("OUTPUTS")) setup_section(document.getElementById("WAYPOINTS")) setup_section(document.getElementById("FILES")) setup_section(document.getElementById("GPS")) @@ -3646,6 +3816,7 @@ function reset() { } let board_types = {} +let param_values = {} async function initial_load() { function load_board_types(text) { @@ -3667,7 +3838,11 @@ async function initial_load() { } } - return new Promise((resolve) => { + const param_values_loaded = fetch("param_values.json") + .then((res) => res.json()) + .then((data) => { param_values = data }) + + const board_types_loaded = new Promise((resolve) => { fetch("board_types.txt") .then((res) => { return res.text() @@ -3676,6 +3851,8 @@ async function initial_load() { resolve() }); }) + + return Promise.all([board_types_loaded, param_values_loaded]) } function save_text(text, file_postfix) { diff --git a/HardwareReport/index.html b/HardwareReport/index.html index b2cce456..9d9e1bc5 100644 --- a/HardwareReport/index.html +++ b/HardwareReport/index.html @@ -48,6 +48,9 @@
diff --git a/HardwareReport/param_values.json b/HardwareReport/param_values.json new file mode 100644 index 00000000..49bba546 --- /dev/null +++ b/HardwareReport/param_values.json @@ -0,0 +1,550 @@ +{ + "ArduCopter": { + "SERVO_FUNCTION": { + "-1": "GPIO", + "0": "Disabled", + "1": "RCPassThru", + "6": "Mount1Yaw", + "7": "Mount1Pitch", + "8": "Mount1Roll", + "9": "Mount1Retract", + "10": "CameraTrigger", + "12": "Mount2Yaw", + "13": "Mount2Pitch", + "14": "Mount2Roll", + "15": "Mount2Retract", + "22": "SprayerPump", + "23": "SprayerSpinner", + "27": "Parachute", + "28": "Gripper", + "29": "LandingGear", + "30": "EngineRunEnable", + "31": "HeliRSC", + "32": "HeliTailRSC", + "33": "Motor1", + "34": "Motor2", + "35": "Motor3", + "36": "Motor4", + "37": "Motor5", + "38": "Motor6", + "39": "Motor7", + "40": "Motor8", + "51": "RCIN1", + "52": "RCIN2", + "53": "RCIN3", + "54": "RCIN4", + "55": "RCIN5", + "56": "RCIN6", + "57": "RCIN7", + "58": "RCIN8", + "59": "RCIN9", + "60": "RCIN10", + "61": "RCIN11", + "62": "RCIN12", + "63": "RCIN13", + "64": "RCIN14", + "65": "RCIN15", + "66": "RCIN16", + "73": "ThrottleLeft", + "74": "ThrottleRight", + "75": "TiltMotorFrontLeft", + "76": "TiltMotorFrontRight", + "81": "BoostThrottle", + "82": "Motor9", + "83": "Motor10", + "84": "Motor11", + "85": "Motor12", + "88": "Winch", + "90": "CameraISO", + "91": "CameraAperture", + "92": "CameraFocus", + "93": "CameraShutterSpeed", + "94": "Script1", + "95": "Script2", + "96": "Script3", + "97": "Script4", + "98": "Script5", + "99": "Script6", + "100": "Script7", + "101": "Script8", + "102": "Script9", + "103": "Script10", + "104": "Script11", + "105": "Script12", + "106": "Script13", + "107": "Script14", + "108": "Script15", + "109": "Script16", + "120": "NeoPixel1", + "121": "NeoPixel2", + "122": "NeoPixel3", + "123": "NeoPixel4", + "124": "RateRoll", + "125": "RatePitch", + "126": "RateThrust", + "127": "RateYaw", + "129": "ProfiLED1", + "130": "ProfiLED2", + "131": "ProfiLED3", + "132": "ProfiLEDClock", + "133": "Winch Clutch", + "134": "SERVOn_MIN", + "135": "SERVOn_TRIM", + "136": "SERVOn_MAX", + "138": "Alarm", + "139": "Alarm Inverted", + "140": "RCIN1Scaled", + "141": "RCIN2Scaled", + "142": "RCIN3Scaled", + "143": "RCIN4Scaled", + "144": "RCIN5Scaled", + "145": "RCIN6Scaled", + "146": "RCIN7Scaled", + "147": "RCIN8Scaled", + "148": "RCIN9Scaled", + "149": "RCIN10Scaled", + "150": "RCIN11Scaled", + "151": "RCIN12Scaled", + "152": "RCIN13Scaled", + "153": "RCIN14Scaled", + "154": "RCIN15Scaled", + "155": "RCIN16Scaled", + "160": "Motor13", + "161": "Motor14", + "162": "Motor15", + "163": "Motor16", + "164": "Motor17", + "165": "Motor18", + "166": "Motor19", + "167": "Motor20", + "168": "Motor21", + "169": "Motor22", + "170": "Motor23", + "171": "Motor24", + "172": "Motor25", + "173": "Motor26", + "174": "Motor27", + "175": "Motor28", + "176": "Motor29", + "177": "Motor30", + "178": "Motor31", + "179": "Motor32" + }, + "FRAME_CLASS": { + "0": "Undefined", + "1": "Quad", + "2": "Hexa", + "3": "Octa", + "4": "OctaQuad", + "5": "Y6", + "6": "Heli", + "7": "Tri", + "8": "SingleCopter", + "9": "CoaxCopter", + "10": "BiCopter", + "11": "Heli_Dual", + "12": "DodecaHexa", + "13": "HeliQuad", + "14": "Deca", + "15": "Scripting Matrix", + "16": "6DoF Scripting", + "17": "Dynamic Scripting Matrix" + }, + "FRAME_TYPE": { + "0": "Plus", + "1": "X", + "2": "V", + "3": "H", + "4": "V-Tail", + "5": "A-Tail", + "10": "Y6B", + "11": "Y6F", + "12": "BetaFlightX", + "13": "DJIX", + "14": "ClockwiseX", + "15": "I", + "18": "BetaFlightXReversed", + "19": "Y4" + } + }, + "ArduPlane": { + "SERVO_FUNCTION": { + "-1": "GPIO", + "0": "Disabled", + "1": "RCPassThru", + "2": "Flap", + "3": "FlapAuto", + "4": "Aileron", + "6": "Mount1Yaw", + "7": "Mount1Pitch", + "8": "Mount1Roll", + "9": "Mount1Retract", + "10": "CameraTrigger", + "12": "Mount2Yaw", + "13": "Mount2Pitch", + "14": "Mount2Roll", + "15": "Mount2Retract", + "16": "DifferentialSpoilerLeft1", + "17": "DifferentialSpoilerRight1", + "19": "Elevator", + "21": "Rudder", + "22": "SprayerPump", + "23": "SprayerSpinner", + "24": "FlaperonLeft", + "25": "FlaperonRight", + "26": "GroundSteering", + "27": "Parachute", + "28": "Gripper", + "29": "LandingGear", + "30": "EngineRunEnable", + "33": "Motor1", + "34": "Motor2", + "35": "Motor3", + "36": "Motor4", + "37": "Motor5", + "38": "Motor6", + "39": "Motor7/TailTiltServo", + "40": "Motor8", + "41": "TiltMotorsFront", + "45": "TiltMotorsRear", + "46": "TiltMotorRearLeft", + "47": "TiltMotorRearRight", + "51": "RCIN1", + "52": "RCIN2", + "53": "RCIN3", + "54": "RCIN4", + "55": "RCIN5", + "56": "RCIN6", + "57": "RCIN7", + "58": "RCIN8", + "59": "RCIN9", + "60": "RCIN10", + "61": "RCIN11", + "62": "RCIN12", + "63": "RCIN13", + "64": "RCIN14", + "65": "RCIN15", + "66": "RCIN16", + "67": "Ignition", + "69": "Starter", + "70": "Throttle", + "73": "ThrottleLeft", + "74": "ThrottleRight", + "75": "TiltMotorFrontLeft", + "76": "TiltMotorFrontRight", + "77": "ElevonLeft", + "78": "ElevonRight", + "79": "VTailLeft", + "80": "VTailRight", + "82": "Motor9", + "83": "Motor10", + "84": "Motor11", + "85": "Motor12", + "86": "DifferentialSpoilerLeft2", + "87": "DifferentialSpoilerRight2", + "90": "CameraISO", + "91": "CameraAperture", + "92": "CameraFocus", + "93": "CameraShutterSpeed", + "94": "Script1", + "95": "Script2", + "96": "Script3", + "97": "Script4", + "98": "Script5", + "99": "Script6", + "100": "Script7", + "101": "Script8", + "102": "Script9", + "103": "Script10", + "104": "Script11", + "105": "Script12", + "106": "Script13", + "107": "Script14", + "108": "Script15", + "109": "Script16", + "110": "Airbrakes", + "120": "NeoPixel1", + "121": "NeoPixel2", + "122": "NeoPixel3", + "123": "NeoPixel4", + "124": "RateRoll", + "125": "RatePitch", + "126": "RateThrust", + "127": "RateYaw", + "129": "ProfiLED1", + "130": "ProfiLED2", + "131": "ProfiLED3", + "132": "ProfiLEDClock", + "134": "SERVOn_MIN", + "135": "SERVOn_TRIM", + "136": "SERVOn_MAX", + "138": "Alarm", + "139": "Alarm Inverted", + "140": "RCIN1Scaled", + "141": "RCIN2Scaled", + "142": "RCIN3Scaled", + "143": "RCIN4Scaled", + "144": "RCIN5Scaled", + "145": "RCIN6Scaled", + "146": "RCIN7Scaled", + "147": "RCIN8Scaled", + "148": "RCIN9Scaled", + "149": "RCIN10Scaled", + "150": "RCIN11Scaled", + "151": "RCIN12Scaled", + "152": "RCIN13Scaled", + "153": "RCIN14Scaled", + "154": "RCIN15Scaled", + "155": "RCIN16Scaled", + "160": "Motor13", + "161": "Motor14", + "162": "Motor15", + "163": "Motor16", + "164": "Motor17", + "165": "Motor18", + "166": "Motor19", + "167": "Motor20", + "168": "Motor21", + "169": "Motor22", + "170": "Motor23", + "171": "Motor24", + "172": "Motor25", + "173": "Motor26", + "174": "Motor27", + "175": "Motor28", + "176": "Motor29", + "177": "Motor30", + "178": "Motor31", + "179": "Motor32" + }, + "Q_FRAME_CLASS": { + "0": "Undefined", + "1": "Quad", + "2": "Hexa", + "3": "Octa", + "4": "OctaQuad", + "5": "Y6", + "7": "Tri", + "10": "Single/Dual", + "12": "DodecaHexa", + "14": "Deca", + "15": "Scripting Matrix", + "17": "Dynamic Scripting Matrix" + }, + "Q_FRAME_TYPE": { + "0": "Plus", + "1": "X", + "2": "V", + "3": "H", + "4": "V-Tail", + "5": "A-Tail", + "10": "Y6B", + "11": "Y6F", + "12": "BetaFlightX", + "13": "DJIX", + "14": "ClockwiseX", + "15": "I", + "16": "MOTOR_FRAME_TYPE_NYT_PLUS", + "17": "MOTOR_FRAME_TYPE_NYT_X", + "18": "BetaFlightXReversed", + "19": "Y4" + } + }, + "ArduRover": { + "SERVO_FUNCTION": { + "-1": "GPIO", + "0": "Disabled", + "1": "RCPassThru", + "6": "Mount1Yaw", + "7": "Mount1Pitch", + "8": "Mount1Roll", + "9": "Mount1Retract", + "10": "CameraTrigger", + "12": "Mount2Yaw", + "13": "Mount2Pitch", + "14": "Mount2Roll", + "15": "Mount2Retract", + "22": "SprayerPump", + "23": "SprayerSpinner", + "26": "GroundSteering", + "28": "Gripper", + "33": "Motor1", + "34": "Motor2", + "35": "Motor3", + "36": "Motor4", + "51": "RCIN1", + "52": "RCIN2", + "53": "RCIN3", + "54": "RCIN4", + "55": "RCIN5", + "56": "RCIN6", + "57": "RCIN7", + "58": "RCIN8", + "59": "RCIN9", + "60": "RCIN10", + "61": "RCIN11", + "62": "RCIN12", + "63": "RCIN13", + "64": "RCIN14", + "65": "RCIN15", + "66": "RCIN16", + "70": "Throttle", + "73": "ThrottleLeft", + "74": "ThrottleRight", + "88": "Winch", + "89": "Main Sail", + "90": "CameraISO", + "91": "CameraAperture", + "92": "CameraFocus", + "93": "CameraShutterSpeed", + "94": "Script1", + "95": "Script2", + "96": "Script3", + "97": "Script4", + "98": "Script5", + "99": "Script6", + "100": "Script7", + "101": "Script8", + "102": "Script9", + "103": "Script10", + "104": "Script11", + "105": "Script12", + "106": "Script13", + "107": "Script14", + "108": "Script15", + "109": "Script16", + "120": "NeoPixel1", + "121": "NeoPixel2", + "122": "NeoPixel3", + "123": "NeoPixel4", + "128": "WingSailElevator", + "129": "ProfiLED1", + "130": "ProfiLED2", + "131": "ProfiLED3", + "132": "ProfiLEDClock", + "133": "Winch Clutch", + "134": "SERVOn_MIN", + "135": "SERVOn_TRIM", + "136": "SERVOn_MAX", + "137": "SailMastRotation", + "138": "Alarm", + "139": "Alarm Inverted", + "140": "RCIN1Scaled", + "141": "RCIN2Scaled", + "142": "RCIN3Scaled", + "143": "RCIN4Scaled", + "144": "RCIN5Scaled", + "145": "RCIN6Scaled", + "146": "RCIN7Scaled", + "147": "RCIN8Scaled", + "148": "RCIN9Scaled", + "149": "RCIN10Scaled", + "150": "RCIN11Scaled", + "151": "RCIN12Scaled", + "152": "RCIN13Scaled", + "153": "RCIN14Scaled", + "154": "RCIN15Scaled", + "155": "RCIN16Scaled" + }, + "FRAME_CLASS": { + "0": "Undefined", + "1": "Rover", + "2": "Boat", + "3": "BalanceBot" + }, + "FRAME_TYPE": { + "0": "Default", + "1": "Omni3", + "2": "OmniX", + "3": "OmniPlus", + "4": "Omni3Mecanum" + } + }, + "ArduSub": { + "SERVO_FUNCTION": { + "-1": "GPIO", + "0": "Disabled", + "1": "RCPassThru", + "6": "Mount1Yaw", + "7": "Mount1Pitch", + "8": "Mount1Roll", + "9": "Mount1Retract", + "28": "Gripper", + "33": "Motor1", + "34": "Motor2", + "35": "Motor3", + "36": "Motor4", + "37": "Motor5", + "38": "Motor6", + "39": "Motor7", + "40": "Motor8", + "51": "RCIN1/Pitch", + "52": "RCIN2/Roll", + "53": "RCIN3/HeaveVertical", + "54": "RCIN4/YawTurn", + "55": "RCIN5/SurgeForward", + "56": "RCIN6/SwayLateral", + "57": "RCIN7/CameraPan", + "58": "RCIN8/CameraTilt", + "59": "RCIN9", + "60": "RCIN10", + "61": "RCIN11", + "62": "RCIN12", + "63": "RCIN13", + "64": "RCIN14", + "65": "RCIN15", + "66": "RCIN16", + "82": "Motor9", + "83": "Motor10", + "84": "Motor11", + "85": "Motor12", + "88": "Winch", + "90": "CameraISO", + "91": "CameraAperture", + "92": "CameraFocus", + "93": "CameraShutterSpeed", + "94": "Script1", + "95": "Script2", + "96": "Script3", + "97": "Script4", + "98": "Script5", + "99": "Script6", + "100": "Script7", + "101": "Script8", + "102": "Script9", + "103": "Script10", + "104": "Script11", + "105": "Script12", + "106": "Script13", + "107": "Script14", + "108": "Script15", + "109": "Script16", + "120": "NeoPixel1", + "121": "NeoPixel2", + "122": "NeoPixel3", + "123": "NeoPixel4", + "134": "SERVOn_MIN", + "135": "SERVOn_TRIM", + "136": "SERVOn_MAX", + "181": "Lights1", + "182": "Lights2", + "183": "VideoSwitch", + "184": "Actuator1", + "185": "Actuator2", + "186": "Actuator3", + "187": "Actuator4", + "188": "Actuator5", + "189": "Actuator6" + }, + "FRAME_CONFIG": { + "0": "BlueROV1", + "1": "Vectored", + "2": "Vectored_6DOF", + "3": "Vectored_6DOF_90", + "4": "SimpleROV-3", + "5": "SimpleROV-4", + "6": "SimpleROV-5", + "7": "Custom" + } + } +}