Skip to content

Commit 1dd49da

Browse files
ardupilot_manager: use new numeric --serialN ports instead of confusing --uartX
1 parent 605ab4c commit 1dd49da

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

core/services/ardupilot_manager/autopilot_manager.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,10 @@ def get_serials(self) -> List[Serial]:
192192
logger.error(e)
193193
return serials
194194

195-
def get_serial_cmdline(self) -> str:
196-
return " ".join([f"-{entry.port} {entry.endpoint}" for entry in self.get_serials()])
195+
def get_serial_cmdline(self, supports_new_serial_mapping: bool) -> str:
196+
if supports_new_serial_mapping:
197+
return " ".join([f"--serial{entry.port} {entry.endpoint}" for entry in self.get_serials()])
198+
return " ".join([f"-{entry.port_as_letter} {entry.endpoint}" for entry in self.get_serials()])
197199

198200
def get_default_params_cmdline(self, platform: Platform) -> str:
199201
# check if file exists and return it's path as --defaults parameter
@@ -202,6 +204,17 @@ def get_default_params_cmdline(self, platform: Platform) -> str:
202204
return f"--defaults {default_params_path}"
203205
return ""
204206

207+
def check_supports_new_serial_mapping(self, firmware: pathlib.Path) -> bool:
208+
"""
209+
check if the firmware supports --serialN instead of --uartX by checking the output of --help
210+
"""
211+
try:
212+
output = subprocess.check_output([firmware, "--help"], encoding="utf-8")
213+
return "--serial" in output
214+
except Exception as e:
215+
logger.warning(f"Failed to check if firmware supports new serial mapping: {e}")
216+
return False
217+
205218
async def start_linux_board(self, board: LinuxFlightController) -> None:
206219
self._current_board = board
207220
if not self.firmware_manager.is_firmware_installed(self._current_board):
@@ -248,12 +261,20 @@ async def start_linux_board(self, board: LinuxFlightController) -> None:
248261
#
249262
# The first column comes from https://ardupilot.org/dev/docs/sitl-serial-mapping.html
250263

264+
supports_new_serial_mapping = self.check_supports_new_serial_mapping(firmware_path)
265+
266+
master_endpoint_str = (
267+
f" --serial0 udp:{master_endpoint.place}:{master_endpoint.argument}"
268+
if supports_new_serial_mapping
269+
else f" -A udp:{master_endpoint.place}:{master_endpoint.argument}"
270+
)
271+
251272
command_line = (
252273
f"{firmware_path}"
253-
f" -A udp:{master_endpoint.place}:{master_endpoint.argument}"
274+
f"{master_endpoint_str}"
254275
f" --log-directory {self.settings.firmware_folder}/logs/"
255276
f" --storage-directory {self.settings.firmware_folder}/storage/"
256-
f" {self.get_serial_cmdline()}"
277+
f" {self.get_serial_cmdline(supports_new_serial_mapping)}"
257278
f" {self.get_default_params_cmdline(board.platform)}"
258279
)
259280

core/services/ardupilot_manager/flight_controller_detector/linux/navigator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ class NavigatorPi5(Navigator):
4747

4848
def get_serials(self) -> List[Serial]:
4949
return [
50-
Serial(port="C", endpoint="/dev/ttyAMA0"),
51-
Serial(port="B", endpoint="/dev/ttyAMA2"),
52-
Serial(port="E", endpoint="/dev/ttyAMA3"),
53-
Serial(port="F", endpoint="/dev/ttyAMA4"),
50+
Serial(port=1, endpoint="/dev/ttyAMA0"),
51+
Serial(port=3, endpoint="/dev/ttyAMA2"),
52+
Serial(port=4, endpoint="/dev/ttyAMA3"),
53+
Serial(port=5, endpoint="/dev/ttyAMA4"),
5454
]
5555

5656
def detect(self) -> bool:

core/services/ardupilot_manager/typedefs.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from enum import Enum, auto
44
from pathlib import Path
55
from platform import machine
6-
from typing import Any, Dict, List, Optional
6+
from typing import Any, Dict, List, Optional, Union
77

88
from pydantic import BaseModel, validator
99

@@ -177,15 +177,22 @@ class Serial(BaseModel):
177177
--serial5 /dev/ttyAMA3
178178
"""
179179

180-
port: str
180+
port: int
181181
endpoint: str
182182

183183
@validator("port")
184184
@classmethod
185-
def valid_letter(cls: Any, value: str) -> str:
186-
if value in "BCDEFGH" and len(value) == 1:
187-
return value
188-
raise ValueError(f"Invalid serial port: {value}. These must be between B and H. A is reserved.")
185+
def valid_letter(cls: Any, value: Union[str, int]) -> int:
186+
letters = ["A", "C", "D", "B", "E", "F", "G", "H", "I", "J"]
187+
if isinstance(value, str) and value in letters and len(value) == 1:
188+
return letters.index(value)
189+
try:
190+
port = int(value)
191+
if port in range(1, 10):
192+
return port
193+
except (ValueError, TypeError):
194+
pass
195+
raise ValueError(f"Invalid serial port: {value}. These must be between B(1) and J(9). A(0) is reserved.")
189196

190197
@validator("endpoint")
191198
@classmethod
@@ -202,4 +209,9 @@ def valid_endpoint(cls: Any, value: str) -> str:
202209
raise ValueError(f"Invalid endpoint configuration: {value}")
203210

204211
def __hash__(self) -> int: # make hashable BaseModel subclass
205-
return hash(self.port + self.endpoint)
212+
return hash(str(self.port) + self.endpoint)
213+
214+
@property
215+
def port_as_letter(self) -> str:
216+
letters = ["A", "C", "D", "B", "E", "F", "G", "H", "I", "J"]
217+
return letters[self.port]

0 commit comments

Comments
 (0)