Skip to content

Commit c6f368a

Browse files
joaomariolagopatrickelectric
authored andcommitted
core:services:autopilot_manager: Error Handling
* Add `index_to_http_exception` to provide better error directing to frontend * Add better error handling conversion on `restore_default_firmware` allowing to convert the exception to appropriated error message for user
1 parent 7495d0e commit c6f368a

File tree

1 file changed

+37
-2
lines changed
  • core/services/ardupilot_manager/api/v1/routers

1 file changed

+37
-2
lines changed

core/services/ardupilot_manager/api/v1/routers/index.py

+37-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import os
22
import shutil
3+
from functools import wraps
34
from pathlib import Path
4-
from typing import Any, List, Optional
5+
from typing import Any, Callable, List, Optional, Tuple
56

67
from commonwealth.mavlink_comm.exceptions import (
78
FetchUpdatedMessageFail,
@@ -17,7 +18,7 @@
1718
from loguru import logger
1819

1920
from autopilot_manager import AutoPilotManager
20-
from exceptions import InvalidFirmwareFile
21+
from exceptions import InvalidFirmwareFile, NoDefaultFirmwareAvailable
2122
from typedefs import Firmware, FlightController, Parameters, Serial, SITLFrame, Vehicle
2223

2324
index_router_v1 = APIRouter(
@@ -29,6 +30,19 @@
2930
autopilot = AutoPilotManager()
3031

3132

33+
def index_to_http_exception(endpoint: Callable[..., Any]) -> Callable[..., Any]:
34+
@wraps(endpoint)
35+
async def wrapper(*args: Tuple[Any], **kwargs: dict[str, Any]) -> Any:
36+
try:
37+
return await endpoint(*args, **kwargs)
38+
except HTTPException as error:
39+
raise error
40+
except Exception as error:
41+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(error)) from error
42+
43+
return wrapper
44+
45+
3246
# By default, all REST resources should have its own router, but as some of them does not implement
3347
# all the CRUD operations, we gonna keep ones that have less than 2 endpoints in the index router.
3448

@@ -63,16 +77,19 @@ def raise_lock(*raise_args: str, **kwargs: int) -> None:
6377

6478

6579
@index_router_v1.put("/serials", status_code=status.HTTP_200_OK)
80+
@index_to_http_exception
6681
def update_serials(serials: List[Serial] = Body(...)) -> Any:
6782
autopilot.update_serials(serials)
6883

6984

7085
@index_router_v1.get("/serials", response_model=List[Serial])
86+
@index_to_http_exception
7187
def get_serials() -> Any:
7288
return autopilot.get_serials()
7389

7490

7591
@index_router_v1.get("/firmware_info", response_model=FirmwareInfo, summary="Get version and type of current firmware.")
92+
@index_to_http_exception
7693
async def get_firmware_info() -> Any:
7794
if not autopilot.current_board:
7895
message = "No board running, firmware information is unavailable"
@@ -87,6 +104,7 @@ async def get_firmware_info() -> Any:
87104

88105

89106
@index_router_v1.get("/vehicle_type", response_model=MavlinkVehicleType, summary="Get mavlink vehicle type.")
107+
@index_to_http_exception
90108
async def get_vehicle_type() -> Any:
91109
if not autopilot.current_board:
92110
message = "No board running, vehicle type is unavailable"
@@ -101,11 +119,13 @@ async def get_vehicle_type() -> Any:
101119

102120

103121
@index_router_v1.post("/sitl_frame", summary="Set SITL Frame type.")
122+
@index_to_http_exception
104123
async def set_sitl_frame(frame: SITLFrame) -> Any:
105124
return autopilot.set_sitl_frame(frame)
106125

107126

108127
@index_router_v1.get("/firmware_vehicle_type", response_model=str, summary="Get firmware vehicle type.")
128+
@index_to_http_exception
109129
async def get_firmware_vehicle_type() -> Any:
110130
if not autopilot.current_board:
111131
raise RuntimeError("Cannot fetch vehicle type info as there's no board running.")
@@ -117,11 +137,13 @@ async def get_firmware_vehicle_type() -> Any:
117137
response_model=List[Firmware],
118138
summary="Retrieve dictionary of available firmwares versions with their respective URL.",
119139
)
140+
@index_to_http_exception
120141
async def get_available_firmwares(vehicle: Vehicle, board_name: Optional[str] = None) -> Any:
121142
return autopilot.get_available_firmwares(vehicle, (await target_board(board_name)).platform)
122143

123144

124145
@index_router_v1.post("/install_firmware_from_url", summary="Install firmware for given URL.")
146+
@index_to_http_exception
125147
@single_threaded(callback=raise_lock)
126148
async def install_firmware_from_url(
127149
url: str,
@@ -145,6 +167,7 @@ async def install_firmware_from_url(
145167

146168

147169
@index_router_v1.post("/install_firmware_from_file", summary="Install firmware from user file.")
170+
@index_to_http_exception
148171
@single_threaded(callback=raise_lock)
149172
async def install_firmware_from_file(
150173
binary: UploadFile = File(...),
@@ -171,65 +194,77 @@ async def install_firmware_from_file(
171194
@index_router_v1.get(
172195
"/board", response_model=Optional[FlightController], summary="Check what is the current running board."
173196
)
197+
@index_to_http_exception
174198
def get_board() -> Any:
175199
return autopilot.current_board
176200

177201

178202
@index_router_v1.post("/board", summary="Set board to be used.")
203+
@index_to_http_exception
179204
async def set_board(board: FlightController, sitl_frame: SITLFrame = SITLFrame.VECTORED) -> Any:
180205
autopilot.current_sitl_frame = sitl_frame
181206
await autopilot.change_board(board)
182207

183208

184209
@index_router_v1.post("/restart", summary="Restart the autopilot with current set options.")
210+
@index_to_http_exception
185211
async def restart() -> Any:
186212
logger.debug("Restarting ardupilot...")
187213
await autopilot.restart_ardupilot()
188214
logger.debug("Ardupilot successfully restarted.")
189215

190216

191217
@index_router_v1.post("/start", summary="Start the autopilot.")
218+
@index_to_http_exception
192219
async def start() -> Any:
193220
logger.debug("Starting ardupilot...")
194221
await autopilot.start_ardupilot()
195222
logger.debug("Ardupilot successfully started.")
196223

197224

198225
@index_router_v1.post("/preferred_router", summary="Set the preferred MAVLink router.")
226+
@index_to_http_exception
199227
async def set_preferred_router(router: str) -> Any:
200228
logger.debug("Setting preferred Router")
201229
await autopilot.set_preferred_router(router)
202230
logger.debug(f"Preferred Router successfully set to {router}")
203231

204232

205233
@index_router_v1.get("/preferred_router", summary="Retrieve preferred router")
234+
@index_to_http_exception
206235
def preferred_router() -> Any:
207236
return autopilot.load_preferred_router()
208237

209238

210239
@index_router_v1.get("/available_routers", summary="Retrieve preferred router")
240+
@index_to_http_exception
211241
def available_routers() -> Any:
212242
return autopilot.get_available_routers()
213243

214244

215245
@index_router_v1.post("/stop", summary="Stop the autopilot.")
246+
@index_to_http_exception
216247
async def stop() -> Any:
217248
logger.debug("Stopping ardupilot...")
218249
await autopilot.kill_ardupilot()
219250
logger.debug("Ardupilot successfully stopped.")
220251

221252

222253
@index_router_v1.post("/restore_default_firmware", summary="Restore default firmware.")
254+
@index_to_http_exception
223255
async def restore_default_firmware(board_name: Optional[str] = None) -> Any:
224256
try:
225257
await autopilot.kill_ardupilot()
226258
autopilot.restore_default_firmware(await target_board(board_name))
259+
except (NoDefaultFirmwareAvailable, ValueError) as error:
260+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(error)) from error
227261
finally:
228262
await autopilot.start_ardupilot()
229263

230264

231265
@index_router_v1.get(
232266
"/available_boards", response_model=List[FlightController], summary="Retrieve list of connected boards."
233267
)
268+
@index_to_http_exception
234269
async def available_boards() -> Any:
235270
return await autopilot.available_boards(True)

0 commit comments

Comments
 (0)