Skip to content

Commit

Permalink
ardupilot_manager: use new numeric --serialN ports instead of confusi…
Browse files Browse the repository at this point in the history
…ng --uartX
  • Loading branch information
Williangalvani committed Jan 20, 2025
1 parent 605ab4c commit 1dd49da
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
29 changes: 25 additions & 4 deletions core/services/ardupilot_manager/autopilot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,10 @@ def get_serials(self) -> List[Serial]:
logger.error(e)
return serials

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

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

def check_supports_new_serial_mapping(self, firmware: pathlib.Path) -> bool:
"""
check if the firmware supports --serialN instead of --uartX by checking the output of --help
"""
try:
output = subprocess.check_output([firmware, "--help"], encoding="utf-8")
return "--serial" in output
except Exception as e:
logger.warning(f"Failed to check if firmware supports new serial mapping: {e}")
return False

async def start_linux_board(self, board: LinuxFlightController) -> None:
self._current_board = board
if not self.firmware_manager.is_firmware_installed(self._current_board):
Expand Down Expand Up @@ -248,12 +261,20 @@ async def start_linux_board(self, board: LinuxFlightController) -> None:
#
# The first column comes from https://ardupilot.org/dev/docs/sitl-serial-mapping.html

supports_new_serial_mapping = self.check_supports_new_serial_mapping(firmware_path)

master_endpoint_str = (
f" --serial0 udp:{master_endpoint.place}:{master_endpoint.argument}"
if supports_new_serial_mapping
else f" -A udp:{master_endpoint.place}:{master_endpoint.argument}"
)

command_line = (
f"{firmware_path}"
f" -A udp:{master_endpoint.place}:{master_endpoint.argument}"
f"{master_endpoint_str}"
f" --log-directory {self.settings.firmware_folder}/logs/"
f" --storage-directory {self.settings.firmware_folder}/storage/"
f" {self.get_serial_cmdline()}"
f" {self.get_serial_cmdline(supports_new_serial_mapping)}"
f" {self.get_default_params_cmdline(board.platform)}"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class NavigatorPi5(Navigator):

def get_serials(self) -> List[Serial]:
return [
Serial(port="C", endpoint="/dev/ttyAMA0"),
Serial(port="B", endpoint="/dev/ttyAMA2"),
Serial(port="E", endpoint="/dev/ttyAMA3"),
Serial(port="F", endpoint="/dev/ttyAMA4"),
Serial(port=1, endpoint="/dev/ttyAMA0"),
Serial(port=3, endpoint="/dev/ttyAMA2"),
Serial(port=4, endpoint="/dev/ttyAMA3"),
Serial(port=5, endpoint="/dev/ttyAMA4"),
]

def detect(self) -> bool:
Expand Down
26 changes: 19 additions & 7 deletions core/services/ardupilot_manager/typedefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from enum import Enum, auto
from pathlib import Path
from platform import machine
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel, validator

Expand Down Expand Up @@ -177,15 +177,22 @@ class Serial(BaseModel):
--serial5 /dev/ttyAMA3
"""

port: str
port: int
endpoint: str

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

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

def __hash__(self) -> int: # make hashable BaseModel subclass
return hash(self.port + self.endpoint)
return hash(str(self.port) + self.endpoint)

@property
def port_as_letter(self) -> str:
letters = ["A", "C", "D", "B", "E", "F", "G", "H", "I", "J"]
return letters[self.port]

0 comments on commit 1dd49da

Please sign in to comment.