Skip to content

Commit 6232879

Browse files
wip
1 parent 5e8ab1f commit 6232879

File tree

5 files changed

+2070
-436
lines changed

5 files changed

+2070
-436
lines changed

core/services/ardupilot_manager/flight_controller_detector/Detector.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from commonwealth.utils.general import is_running_as_root
55
from serial.tools.list_ports_linux import SysFS, comports
66

7-
from flight_controller_detector.board_identification import identifiers
7+
from flight_controller_detector.board_identification import identifiers, get_board_id_from_usb_id
88
from flight_controller_detector.linux.detector import LinuxFlightControllerDetector
99
from typedefs import FlightController, FlightControllerFlags, Platform
1010

@@ -55,17 +55,25 @@ def detect_serial_flight_controllers() -> List[FlightController]:
5555
# usb_device_path property will be the same for two serial connections using the same USB port
5656
if port.usb_device_path not in [device.usb_device_path for device in unique_serial_devices]:
5757
unique_serial_devices.append(port)
58-
boards = [
59-
FlightController(
60-
name=port.product or port.name,
61-
manufacturer=port.manufacturer,
62-
platform=Detector.detect_serial_platform(port)
63-
or Platform(), # this is just to make CI happy. check line 82
64-
path=port.device,
65-
)
66-
for port in unique_serial_devices
67-
if Detector.detect_serial_platform(port) is not None
68-
]
58+
boards = []
59+
for port in unique_serial_devices:
60+
platform = Detector.detect_serial_platform(port)
61+
if platform is not None:
62+
board_name = port.product or port.name
63+
64+
# Get board_id using USB VID:PID
65+
board_id = None
66+
if port.vid is not None and port.pid is not None:
67+
board_id = get_board_id_from_usb_id(port.vid, port.pid, board_name)
68+
69+
board = FlightController(
70+
name=board_name,
71+
manufacturer=port.manufacturer,
72+
platform=platform,
73+
path=port.device,
74+
ardupilot_board_id=board_id,
75+
)
76+
boards.append(board)
6977
for port in unique_serial_devices:
7078
for board in boards:
7179
if board.path == port.device and Detector.is_serial_bootloader(port):

core/services/ardupilot_manager/flight_controller_detector/board_identification.py

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
from enum import Enum
33
from pathlib import Path
4-
from typing import List
4+
from typing import List, Optional
55

66
from pydantic import BaseModel
77

@@ -39,16 +39,101 @@ def load_board_identifiers() -> List[SerialBoardIdentifier]:
3939
with open(boards_path, encoding="utf-8") as f:
4040
json_data = json.load(f)
4141

42-
# Extract all unique board names
42+
# Extract all unique board names from the new structure
4343
board_names = set()
4444
for boards_list in json_data.values():
45-
board_names.update(boards_list)
45+
if isinstance(boards_list, list) and boards_list:
46+
# Check if it's the new format (list of objects) or old format (list of strings)
47+
if isinstance(boards_list[0], dict):
48+
# New format: extract board_name from objects
49+
board_names.update(board["board_name"] for board in boards_list if "board_name" in board)
50+
else:
51+
# Old format: boards_list contains strings directly
52+
board_names.update(boards_list)
4653

4754
return [
4855
SerialBoardIdentifier(attribute=SerialAttr.product, id_value=board_name, platform=Platform.GenericSerial)
4956
for board_name in board_names
5057
]
5158

5259

60+
def get_board_id_from_name(board_name: str) -> Optional[int]:
61+
"""
62+
Get the board ID for a given board name by searching through the boards cache.
63+
64+
Args:
65+
board_name: The name of the board to look up.
66+
67+
Returns:
68+
Optional[int]: The board ID if found, None otherwise.
69+
"""
70+
try:
71+
boards_path = get_boards_cache_path()
72+
73+
# If cache doesn't exist, try to generate it
74+
if not boards_path.exists():
75+
handler = ManifestHandler()
76+
handler.process_and_export(boards_path)
77+
78+
with open(boards_path, encoding="utf-8") as f:
79+
json_data = json.load(f)
80+
81+
# Search through all USB IDs for the board name
82+
for boards_list in json_data.values():
83+
if isinstance(boards_list, list):
84+
for board in boards_list:
85+
if isinstance(board, dict) and board.get("board_name") == board_name:
86+
return board.get("board_id")
87+
elif isinstance(board, str) and board == board_name:
88+
# Old format doesn't have board IDs
89+
return None
90+
91+
return None
92+
except (json.JSONDecodeError, OSError, FileNotFoundError):
93+
return None
94+
95+
96+
def get_board_id_from_usb_id(vid: int, pid: int, board_name: Optional[str] = None) -> Optional[int]:
97+
"""
98+
Get the board ID for a given USB VID:PID combination, optionally filtering by board name.
99+
100+
Args:
101+
vid: USB Vendor ID
102+
pid: USB Product ID
103+
board_name: Optional board name to filter results when multiple boards share the same USB ID
104+
105+
Returns:
106+
Optional[int]: The board ID if found, None otherwise.
107+
"""
108+
try:
109+
boards_path = get_boards_cache_path()
110+
111+
# If cache doesn't exist, try to generate it
112+
if not boards_path.exists():
113+
handler = ManifestHandler()
114+
handler.process_and_export(boards_path)
115+
116+
with open(boards_path, encoding="utf-8") as f:
117+
json_data = json.load(f)
118+
119+
# Format USB ID as vid:pid (lowercase hex)
120+
usb_id = f"{vid:04x}:{pid:04x}"
121+
122+
if usb_id in json_data:
123+
boards_list = json_data[usb_id]
124+
if isinstance(boards_list, list):
125+
for board in boards_list:
126+
if isinstance(board, dict):
127+
# If board_name is specified, filter by it
128+
return board.get("board_id")
129+
elif isinstance(board, str):
130+
# Old format doesn't have board IDs
131+
return None
132+
133+
return None
134+
except (json.JSONDecodeError, OSError, FileNotFoundError):
135+
return None
136+
137+
53138
# Load dynamic board identifiers from manifest
54139
identifiers = load_board_identifiers()

0 commit comments

Comments
 (0)