Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(robot-server): Audit HTTP API documentation #14294

Merged
merged 34 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d516c41
Disable /docs to focus on /redoc.
SyntaxColoring Jan 5, 2024
0297204
Clarify /logs endpoint. Introduce an accursed xref mechanism.
SyntaxColoring Jan 5, 2024
cfaf767
Mark deprecated /modules endpoint as removed.
SyntaxColoring Jan 5, 2024
2259158
Minor formatting stuff.
SyntaxColoring Jan 5, 2024
c5e513b
Networking: Say JSON true/false, not Python True/False.
SyntaxColoring Jan 6, 2024
6f0a2a5
Networking: Remove redundancy.
SyntaxColoring Jan 6, 2024
ea64820
Networking: Minor formatting stuff.
SyntaxColoring Jan 5, 2024
9205f2b
Networking: Fix missing summaries.
SyntaxColoring Jan 6, 2024
ff71512
Lights and control: Add missing summaries.
SyntaxColoring Jan 6, 2024
d4ebc00
Deprecate /robot/move and /robot/positions.
SyntaxColoring Jan 5, 2024
f20ccef
Deprecate old_id.
SyntaxColoring Jan 5, 2024
b8bf11e
Missing summaries.
SyntaxColoring Jan 5, 2024
7c1f960
Flesh out POST /settings/reset.
SyntaxColoring Jan 5, 2024
c7a0ce2
Merge branch 'edge' into audit_openapi_docs
SyntaxColoring Feb 23, 2024
4716c79
Markdown formatting in Opentrons-Version.
SyntaxColoring Feb 23, 2024
05be780
Fix up /sessions/ endpoints.
SyntaxColoring Feb 23, 2024
820a303
Document protocol key.
SyntaxColoring Feb 23, 2024
85ef5f6
Merge branch 'edge' into audit_openapi_docs
SyntaxColoring Feb 26, 2024
aa82000
Revert accursed xref mechanism.
SyntaxColoring Feb 28, 2024
d6906cc
Format.
SyntaxColoring Feb 28, 2024
98bdb0c
Remove "factory"-reset terminology.
SyntaxColoring Feb 28, 2024
2e913b9
Mark /labware/calibrations endpoints as deprecated.
SyntaxColoring Feb 28, 2024
0aa91e3
Describe the /deck_configuration endpoints as Flex-only.
SyntaxColoring Feb 28, 2024
dc3e845
typo: colletion -> collection
SyntaxColoring Feb 28, 2024
ccf1e2c
Minor fixups to /subsystems endpoints.
SyntaxColoring Feb 28, 2024
e84ade7
Describe /pipettes as OT-2-only and /instruments as Flex-only.
SyntaxColoring Feb 28, 2024
aa662b8
Deprecate instrument offsets in `GET /calibration/status`.
SyntaxColoring Feb 28, 2024
5b4cfc6
Merge branch 'edge' into audit_openapi_docs
SyntaxColoring Mar 6, 2024
4318241
Tweak /instruments and /pipettes per discussion with Sarah and Laura.
SyntaxColoring Mar 6, 2024
b27b2aa
Arbitrary list order in deck config endpoints.
SyntaxColoring Mar 6, 2024
4d75231
Warn more firmly against `PUT`ing deck config on OT-2.
SyntaxColoring Mar 6, 2024
e074a87
Deprecate various labware hash fields.
SyntaxColoring Mar 6, 2024
7f712da
Deprecate labware hash query parameters.
SyntaxColoring Mar 6, 2024
f13baad
Readability improvement.
SyntaxColoring Mar 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions robot-server/robot_server/app_setup.py
Copy link
Contributor Author

@SyntaxColoring SyntaxColoring Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the sake of having some organized and self-contained discussions, I'm going to open a bunch of threads on this file, even though they're talking about code that lives elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should we do with GET /motors/engaged and POST /motors/disengage?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep em?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i mean they're not really necessary on the flex but they don't really hurt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to keep POST /camera/picture for the Flex? It does have a camera, right? Does that endpoint actually work on a Flex today?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has a camera, it should work, it may not

Copy link
Contributor Author

@SyntaxColoring SyntaxColoring Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to warn people away from using "intent": "setup" commands, or is that cat out of the bag?

Copy link
Contributor Author

@SyntaxColoring SyntaxColoring Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we sufficiently define how /runs coexist with /maintenance_runs/commands and /commands? We have not always done a great job on the server of enforcing mutual exclusion. I guess I'm worried if there's a danger of somebody POSTing to two of these things at once, the server accidentally allowing it, and them relying on the dangerous behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyone know if the GET /calibration/status deck calibration endpoint is meaningful on a Flex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyone know what the deal is with GET /settings/robot/? Should people be using it? Should we deprecate it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

people can use it for settings, there's nothing that special about it

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
),
version=__version__,
exception_handlers=exception_handlers,
# Disable documentation hosting via Swagger UI, normally at /docs.
# We instead focus on the docs hosted by ReDoc, at /redoc.
docs_url=None,
)

# cors
Expand Down
10 changes: 8 additions & 2 deletions robot-server/robot_server/deck_configuration/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,21 @@ class DeckConfigurationRequest(pydantic.BaseModel):
"""A request to set the robot's deck configuration."""

cutoutFixtures: List[CutoutFixture] = pydantic.Field(
description="A full list of all the cutout fixtures that are mounted onto the deck."
description=(
"A full list of all the cutout fixtures that are mounted onto the deck."
" The order is arbitrary."
)
)


class DeckConfigurationResponse(pydantic.BaseModel):
"""A response for the robot's current deck configuration."""

cutoutFixtures: List[CutoutFixture] = pydantic.Field(
description="A full list of all the cutout fixtures that are mounted onto the deck."
description=(
"A full list of all the cutout fixtures that are mounted onto the deck."
" The order is arbitrary."
)
)
lastModifiedAt: Optional[datetime] = pydantic.Field(
description=(
Expand Down
14 changes: 10 additions & 4 deletions robot-server/robot_server/deck_configuration/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@PydanticResponse.wrap_route(
router.put,
path="/deck_configuration",
summary="Set the deck configuration",
summary="Set the Flex deck configuration",
description=(
"Inform the robot how its deck is physically set up."
"\n\n"
Expand All @@ -38,15 +38,18 @@
" configuration, such as loading a labware into a staging area slot that this deck"
" configuration doesn't provide, the run command will fail with an error."
"\n\n"
"After you set the deck configuration, it will persist, even across reboots,"
" until you set it to something else."
"\n\n"
"**Warning:**"
" Currently, you can call this endpoint at any time, even while there is an active run."
" However, the robot can't adapt to deck configuration changes in the middle of a run."
" The robot will effectively take a snapshot of the deck configuration when the run is"
" first played. In the future, this endpoint may error if you try to call it in the middle"
" of an active run, so don't rely on being able to do that."
"\n\n"
"After you set the deck configuration, it will persist, even across reboots,"
" until you set it to something else."
"**Warning:** Only use this on Flex robots, never OT-2 robots. The behavior on"
" OT-2 robots is currently undefined and it may interfere with protocol execution."
),
responses={
fastapi.status.HTTP_200_OK: {
Expand Down Expand Up @@ -86,10 +89,13 @@ async def put_deck_configuration( # noqa: D103
@PydanticResponse.wrap_route(
router.get,
path="/deck_configuration",
summary="Get the deck configuration",
summary="Get the Flex deck configuration",
description=(
"Get the robot's current deck configuration."
" See `PUT /deck_configuration` for background information."
"\n\n"
"**Warning:** The behavior of this endpoint is currently only defined for Flex"
" robots, not OT-2 robots."
),
responses={
fastapi.status.HTTP_200_OK: {
Expand Down
11 changes: 8 additions & 3 deletions robot-server/robot_server/instruments/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,14 @@ async def _get_attached_instruments_ot2(
@PydanticResponse.wrap_route(
instruments_router.get,
path="/instruments",
summary="Get attached instruments.",
description="Get a list of all instruments (pipettes & gripper) currently attached"
" to the robot.",
summary="Get attached instruments",
description=(
"Get a list of all instruments (pipettes & gripper) currently attached"
" to the robot."
"\n\n"
"**Warning:** The behavior of this endpoint is currently only defined for Flex"
" robots. For OT-2 robots, use `/pipettes` instead."
),
responses={status.HTTP_200_OK: {"model": SimpleMultiBody[AttachedItem]}},
)
async def get_attached_instruments(
Expand Down
8 changes: 7 additions & 1 deletion robot-server/robot_server/protocols/protocol_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,10 @@ class Protocol(ResourceModel):
),
)

key: Optional[str] = None
key: Optional[str] = Field(
None,
description=(
"An arbitrary client-defined string, set when this protocol was uploaded."
" See `POST /protocols`."
),
)
12 changes: 11 additions & 1 deletion robot-server/robot_server/protocols/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
FileHasher,
)
from opentrons_shared_data.robot.dev_types import RobotType

from robot_server.errors.error_responses import ErrorDetails, ErrorBody
from robot_server.hardware import get_robot_type
from robot_server.service.task_runner import TaskRunner, get_task_runner
Expand Down Expand Up @@ -154,7 +155,16 @@ async def create_protocol(
files: List[UploadFile] = File(...),
# use Form because request is multipart/form-data
# https://fastapi.tiangolo.com/tutorial/request-forms-and-files/
key: Optional[str] = Form(None),
key: Optional[str] = Form(
default=None,
description=(
"An arbitrary client-defined string to attach to the new protocol resource."
" This should be no longer than ~100 characters or so."
" It's intended to store something like a UUID, to help clients that store"
" protocols locally keep track of which local files correspond to which"
" protocol resources on the robot."
),
),
protocol_directory: Path = Depends(get_protocol_directory),
protocol_store: ProtocolStore = Depends(get_protocol_store),
analysis_store: AnalysisStore = Depends(get_analysis_store),
Expand Down
6 changes: 3 additions & 3 deletions robot-server/robot_server/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@

router.include_router(
router=deck_configuration_router,
tags=["Deck Configuration"],
tags=["Flex Deck Configuration"],
dependencies=[Depends(check_version_header)],
)

Expand All @@ -90,7 +90,7 @@

router.include_router(
router=deprecated_session_router,
tags=["Session Management"],
tags=["OT-2 Calibration Sessions"],
dependencies=[Depends(check_version_header)],
)

Expand Down Expand Up @@ -120,7 +120,7 @@

router.include_router(
router=subsystems_router,
tags=["Subsystem Management"],
tags=["Flex Subsystem Management"],
dependencies=[Depends(check_version_header)],
)

Expand Down
4 changes: 2 additions & 2 deletions robot-server/robot_server/service/json_api/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class SimpleMultiBody(BaseResponseBody, GenericModel, Generic[ResponseDataT]):
# to be covariant is to make data the covariant Sequence protocol.
meta: MultiBodyMeta = Field(
...,
description="Metadata about the colletion response.",
description="Metadata about the collection response.",
)


Expand All @@ -125,7 +125,7 @@ class MultiBody(
links: ResponseLinksT = Field(..., description=DESCRIPTION_LINKS)
meta: MultiBodyMeta = Field(
...,
description="Metadata about the colletion response.",
description="Metadata about the collection response.",
)


Expand Down
3 changes: 3 additions & 0 deletions robot-server/robot_server/service/labware/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class LabwareCalibrationEndpointsRemoved(ErrorDetails):
"This endpoint has been removed."
" Use the `/runs` endpoints to manage labware offsets."
),
deprecated=True,
response_model=None,
responses={
status.HTTP_200_OK: {"model": lw_models.MultipleCalibrationsResponse},
Expand All @@ -62,6 +63,7 @@ async def get_all_labware_calibrations(
"This endpoint has been removed."
" Use the `/runs` endpoints to manage labware offsets."
),
deprecated=True,
response_model=None,
responses={
status.HTTP_404_NOT_FOUND: {"model": ErrorBody},
Expand Down Expand Up @@ -89,6 +91,7 @@ async def get_specific_labware_calibration(
"This endpoint has been removed."
" Use the `/runs` endpoints to manage labware offsets."
),
deprecated=True,
response_model=None,
responses={
status.HTTP_404_NOT_FOUND: {"model": ErrorBody},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,22 @@


class InstrumentOffset(BaseModel):
single: Offset
multi: Offset
single: Offset = Field(
...,
deprecated=True,
description=(
"This will always be `[0, 0, 0]`."
" Use the `GET /calibration/pipette_offset` endpoint instead."
),
)
multi: Offset = Field(
...,
deprecated=True,
description=(
"This will always be `[0, 0, 0]`."
" Use the `GET /calibration/pipette_offset` endpoint instead."
),
)


class InstrumentCalibrationStatus(BaseModel):
Expand Down Expand Up @@ -59,7 +73,12 @@ class DeckCalibrationData(BaseModel):
None, description="The ID of the pipette used in this calibration"
)
tiprack: typing.Optional[str] = Field(
None, description="The sha256 hash of the tiprack used in this calibration"
None,
description="A hash of the labware definition of the tip rack that"
" was used in this calibration."
" This is deprecated because it was prone to bugs where semantically identical"
" definitions had different hashes.",
deprecated=True,
)
source: typing.Optional[SourceType] = Field(
None, description="The calibration source"
Expand Down
30 changes: 15 additions & 15 deletions robot-server/robot_server/service/legacy/models/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ class WifiNetworkFull(WifiNetwork):

signal: int = Field(
...,
description="A unitless signal strength; a higher number is a " "better signal",
description="A unitless signal strength; a higher number is a better signal",
)
active: bool = Field(..., description="Whether there is a connection active")
security: str = Field(
..., description="The raw NetworkManager output about the wifi " "security"
..., description="The raw NetworkManager output about the Wi-Fi security"
)
securityType: NetworkingSecurityType

Expand Down Expand Up @@ -133,32 +133,32 @@ class WifiConfiguration(BaseModel):
...,
description="The SSID to connect to. If this isn't an SSID that "
"is being broadcast by a network, you "
"should also set hidden to true.",
"should also set `hidden` to `true`.",
)
hidden: typing.Optional[bool] = Field(
False,
description="True if the network is hidden (not broadcasting an "
"ssid). False (default if key is not "
"present) otherwise",
description="`true` if the network is hidden (not broadcasting an SSID). "
"`false` (default if key is not "
"present) otherwise.",
)
securityType: typing.Optional[NetworkingSecurityType]

psk: typing.Optional[SecretStr] = Field(
None,
description="If this is a PSK-secured network (securityType is "
"wpa-psk), the PSK",
description="If this is a PSK-secured network (`securityType` is "
'`"wpa-psk"`), the PSK',
)
eapConfig: typing.Optional[typing.Dict[str, str]] = Field(
None,
description="All options required to configure EAP access to the"
" wifi. All options should match one of the cases "
"described in /wifi/eap-options; for instance, "
" Wi-Fi. All options should match one of the cases "
"described in `/wifi/eap-options`; for instance, "
"configuring for peap/mschapv2 should have "
'"peap/mschapv2" as the eapType; it should have '
'"identity" and "password" props, both of which '
"are identified as mandatory in /wifi/eap-options; "
'and it may also have "anonymousIdentity" and '
'"caCert" properties, both of which are identified'
'`"peap/mschapv2"` as the `eapType`; it should have '
'`"identity"` and `"password"` props, both of which '
"are identified as mandatory in `/wifi/eap-options`; "
'and it may also have `"anonymousIdentity"` and '
'`"caCert"` properties, both of which are identified'
" as present but not required.",
required=["eapType"],
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class AdvancedSetting(BaseModel):
...,
description="The ID by which the property used to be known; not"
" useful now and may contain spaces or hyphens",
deprecated=True,
)
title: str = Field(
...,
Expand Down
27 changes: 22 additions & 5 deletions robot-server/robot_server/service/legacy/routers/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@

@router.post(
"/identify",
description="Blink the OT-2's gantry lights so you can pick it " "out of a crowd",
summary="Blink the lights",
description="Blink the gantry lights so you can pick it out of a crowd",
)
async def post_identify(
seconds: int = Query(..., description="Time to blink the lights for"),
Expand All @@ -37,8 +38,15 @@ async def post_identify(

@router.get(
"/robot/positions",
description="Get a list of useful positions",
summary="Get robot positions",
description=(
"Get a list of useful positions."
"\n\n"
"**Deprecated:** This data only makes sense for OT-2 robots, not Flex robots."
" There is currently no public way to get these positions for Flex robots."
),
response_model=control.RobotPositionsResponse,
deprecated=True,
)
async def get_robot_positions() -> control.RobotPositionsResponse:
"""
Expand All @@ -60,14 +68,20 @@ async def get_robot_positions() -> control.RobotPositionsResponse:

@router.post(
path="/robot/move",
summary="Move the robot",
description=(
"Move the robot's gantry to a position (usually to a "
"position retrieved from GET /robot/positions)"
"position retrieved from `GET /robot/positions`)."
"\n\n"
"**Deprecated:**"
" Run a `moveToCoordinates` command in a maintenance run instead."
" See the `/maintenance_runs` endpoints."
),
response_model=V1BasicResponse,
responses={
status.HTTP_403_FORBIDDEN: {"model": LegacyErrorResponse},
},
deprecated=True,
)
async def post_move_robot(
robot_move_target: control.RobotMoveTarget,
Expand All @@ -85,7 +99,8 @@ async def post_move_robot(

@router.post(
path="/robot/home",
description="Home the robot",
summary="Home the robot",
description="Home the robot.",
response_model=V1BasicResponse,
responses={
status.HTTP_400_BAD_REQUEST: {"model": LegacyErrorResponse},
Expand Down Expand Up @@ -126,7 +141,8 @@ async def post_home_robot(

@router.get(
"/robot/lights",
description="Get the current status of the OT-2's rail lights",
summary="Get whether the lights are on",
description="Get the current status of the robot's rail lights",
response_model=control.RobotLightState,
)
async def get_robot_light_state(
Expand All @@ -138,6 +154,7 @@ async def get_robot_light_state(

@router.post(
"/robot/lights",
summary="Turn the lights on or off",
description="Turn the rail lights on or off",
response_model=control.RobotLightState,
)
Expand Down
Loading
Loading