vehicles.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. from typing import List, Optional
  2. from fastapi import APIRouter, Depends, HTTPException, Query, Path
  3. from schemas import (
  4. VehicleBase,
  5. VersionOut,
  6. BoardOut,
  7. FeatureOut,
  8. )
  9. from services.vehicles import get_vehicles_service, VehiclesService
  10. router = APIRouter(prefix="/vehicles", tags=["vehicles"])
  11. @router.get("", response_model=List[VehicleBase])
  12. async def list_vehicles(
  13. service: VehiclesService = Depends(get_vehicles_service)
  14. ):
  15. """
  16. Get list of all available vehicles.
  17. Returns:
  18. List of vehicles with their IDs and names.
  19. """
  20. return service.get_all_vehicles()
  21. @router.get(
  22. "/{vehicle_id}",
  23. response_model=VehicleBase,
  24. responses={
  25. 404: {"description": "Vehicle not found"}
  26. }
  27. )
  28. async def get_vehicle(
  29. vehicle_id: str = Path(..., description="Unique vehicle identifier"),
  30. service: VehiclesService = Depends(get_vehicles_service)
  31. ):
  32. """
  33. Get a specific vehicle by ID.
  34. Args:
  35. vehicle_id: The vehicle identifier (e.g., 'copter', 'plane')
  36. Returns:
  37. Vehicle details
  38. """
  39. vehicle = service.get_vehicle(vehicle_id)
  40. if not vehicle:
  41. raise HTTPException(
  42. status_code=404,
  43. detail=f"Vehicle with id '{vehicle_id}' not found"
  44. )
  45. return vehicle
  46. # --- Version Endpoints ---
  47. @router.get("/{vehicle_id}/versions", response_model=List[VersionOut])
  48. async def list_versions(
  49. vehicle_id: str = Path(..., description="Vehicle identifier"),
  50. type: Optional[str] = Query(
  51. None,
  52. description=(
  53. "Filter by version type "
  54. "(beta, stable, latest, tag)"
  55. )
  56. ),
  57. service: VehiclesService = Depends(get_vehicles_service)
  58. ):
  59. """
  60. Get all versions available for a specific vehicle.
  61. Args:
  62. vehicle_id: The vehicle identifier
  63. type: Optional filter by version type
  64. Returns:
  65. List of versions for the vehicle
  66. """
  67. return service.get_versions(vehicle_id, type_filter=type)
  68. @router.get(
  69. "/{vehicle_id}/versions/{version_id}",
  70. response_model=VersionOut,
  71. responses={
  72. 404: {"description": "Version not found for the vehicle"}
  73. }
  74. )
  75. async def get_version(
  76. vehicle_id: str = Path(..., description="Vehicle identifier"),
  77. version_id: str = Path(..., description="Version identifier"),
  78. service: VehiclesService = Depends(get_vehicles_service)
  79. ):
  80. """
  81. Get details of a specific version for a vehicle.
  82. Args:
  83. vehicle_id: The vehicle identifier
  84. version_id: The version identifier
  85. Returns:
  86. Version details
  87. """
  88. version = service.get_version(vehicle_id, version_id)
  89. if not version:
  90. raise HTTPException(
  91. status_code=404,
  92. detail=(
  93. f"Version '{version_id}' not found for "
  94. f"vehicle '{vehicle_id}'"
  95. )
  96. )
  97. return version
  98. # --- Board Endpoints ---
  99. @router.get(
  100. "/{vehicle_id}/versions/{version_id}/boards",
  101. response_model=List[BoardOut],
  102. responses={
  103. 404: {"description": "No boards found for the vehicle version"}
  104. }
  105. )
  106. async def list_boards(
  107. vehicle_id: str = Path(..., description="Vehicle identifier"),
  108. version_id: str = Path(..., description="Version identifier"),
  109. service: VehiclesService = Depends(get_vehicles_service)
  110. ):
  111. """
  112. Get all boards available for a specific vehicle version.
  113. Args:
  114. vehicle_id: The vehicle identifier
  115. version_id: The version identifier
  116. Returns:
  117. List of boards for the vehicle version
  118. """
  119. boards = service.get_boards(vehicle_id, version_id)
  120. if not boards:
  121. raise HTTPException(
  122. status_code=404,
  123. detail=(
  124. f"No boards found for vehicle '{vehicle_id}' and "
  125. f"version '{version_id}'"
  126. )
  127. )
  128. return boards
  129. @router.get(
  130. "/{vehicle_id}/versions/{version_id}/boards/{board_id}",
  131. response_model=BoardOut,
  132. responses={
  133. 404: {"description": "Board not found"}
  134. }
  135. )
  136. async def get_board(
  137. vehicle_id: str = Path(..., description="Vehicle identifier"),
  138. version_id: str = Path(..., description="Version identifier"),
  139. board_id: str = Path(..., description="Board identifier"),
  140. service: VehiclesService = Depends(get_vehicles_service)
  141. ):
  142. """
  143. Get details of a specific board for a vehicle version.
  144. Args:
  145. vehicle_id: The vehicle identifier
  146. version_id: The version identifier
  147. board_id: The board identifier
  148. Returns:
  149. Board details
  150. """
  151. board = service.get_board(vehicle_id, version_id, board_id)
  152. if not board:
  153. raise HTTPException(
  154. status_code=404,
  155. detail=f"Board '{board_id}' not found"
  156. )
  157. return board
  158. # --- Feature Endpoints ---
  159. @router.get(
  160. "/{vehicle_id}/versions/{version_id}/boards/{board_id}/features",
  161. response_model=List[FeatureOut]
  162. )
  163. async def list_features(
  164. vehicle_id: str = Path(..., description="Vehicle identifier"),
  165. version_id: str = Path(..., description="Version identifier"),
  166. board_id: str = Path(..., description="Board identifier"),
  167. category_id: Optional[str] = Query(
  168. None, description="Filter by category ID"
  169. ),
  170. service: VehiclesService = Depends(get_vehicles_service)
  171. ):
  172. """
  173. Get all features with defaults for a specific vehicle/version/board.
  174. Args:
  175. vehicle_id: The vehicle identifier
  176. version_id: The version identifier
  177. board_id: The board identifier
  178. category_id: Optional filter by category
  179. Returns:
  180. List of features with default settings for the board
  181. """
  182. features = service.get_features(
  183. vehicle_id, version_id, board_id, category_id
  184. )
  185. return features
  186. @router.get(
  187. "/{vehicle_id}/versions/{version_id}/boards/{board_id}/"
  188. "features/{feature_id}",
  189. response_model=FeatureOut,
  190. responses={
  191. 404: {"description": "Feature not found"}
  192. }
  193. )
  194. async def get_feature(
  195. vehicle_id: str = Path(..., description="Vehicle identifier"),
  196. version_id: str = Path(..., description="Version identifier"),
  197. board_id: str = Path(..., description="Board identifier"),
  198. feature_id: str = Path(..., description="Feature identifier"),
  199. service: VehiclesService = Depends(get_vehicles_service)
  200. ):
  201. """
  202. Get details of a specific feature for a vehicle/version/board.
  203. Args:
  204. vehicle_id: The vehicle identifier
  205. version_id: The version identifier
  206. board_id: The board identifier
  207. feature_id: The feature identifier
  208. Returns:
  209. Feature details with default settings
  210. """
  211. feature = service.get_feature(
  212. vehicle_id, version_id, board_id, feature_id
  213. )
  214. if not feature:
  215. raise HTTPException(
  216. status_code=404,
  217. detail=f"Feature '{feature_id}' not found"
  218. )
  219. return feature