diff --git a/api/src/opentrons/protocols/api_support/definitions.py b/api/src/opentrons/protocols/api_support/definitions.py index 08230959672..067200e7864 100644 --- a/api/src/opentrons/protocols/api_support/definitions.py +++ b/api/src/opentrons/protocols/api_support/definitions.py @@ -1,6 +1,6 @@ from .types import APIVersion -MAX_SUPPORTED_VERSION = APIVersion(2, 9) +MAX_SUPPORTED_VERSION = APIVersion(2, 10) #: The maximum supported protocol API version in this release V2_MODULE_DEF_VERSION = APIVersion(2, 3) diff --git a/api/src/opentrons/protocols/context/engine/protocol_context.py b/api/src/opentrons/protocols/context/engine/protocol_context.py index ad66feab76a..3f48540b930 100644 --- a/api/src/opentrons/protocols/context/engine/protocol_context.py +++ b/api/src/opentrons/protocols/context/engine/protocol_context.py @@ -132,8 +132,15 @@ def get_rail_lights_on(self) -> bool: def door_closed(self) -> bool: raise NotImplementedError() - def get_last_location(self) -> Optional[types.Location]: + def get_last_location( + self, + mount: Optional[types.Mount] = None, + ) -> Optional[types.Location]: raise NotImplementedError() - def set_last_location(self, location: Optional[types.Location]) -> None: + def set_last_location( + self, + location: Optional[types.Location], + mount: Optional[types.Mount] = None, + ) -> None: raise NotImplementedError() diff --git a/api/src/opentrons/protocols/context/protocol.py b/api/src/opentrons/protocols/context/protocol.py index 1b0e6746caa..2de36dee39b 100644 --- a/api/src/opentrons/protocols/context/protocol.py +++ b/api/src/opentrons/protocols/context/protocol.py @@ -160,9 +160,16 @@ def door_closed(self) -> bool: ... @abstractmethod - def get_last_location(self) -> Optional[types.Location]: + def get_last_location( + self, + mount: Optional[types.Mount] = None, + ) -> Optional[types.Location]: ... @abstractmethod - def set_last_location(self, location: Optional[types.Location]) -> None: + def set_last_location( + self, + location: Optional[types.Location], + mount: Optional[types.Mount] = None, + ) -> None: ... diff --git a/api/src/opentrons/protocols/context/protocol_api/instrument_context.py b/api/src/opentrons/protocols/context/protocol_api/instrument_context.py index 07cadfe589a..157a25f535a 100644 --- a/api/src/opentrons/protocols/context/protocol_api/instrument_context.py +++ b/api/src/opentrons/protocols/context/protocol_api/instrument_context.py @@ -154,7 +154,17 @@ def move_to(self, minimum_z_height: Optional[float], speed: Optional[float]) -> None: """Move the instrument.""" - last_location = self._protocol_interface.get_last_location() + # prevent direct movement bugs in PAPI version >= 2.10 + location_cache_mount = ( + self._mount + if self._api_version >= APIVersion(2, 10) else + None + ) + + last_location = self._protocol_interface.get_last_location( + mount=location_cache_mount + ) + if last_location: from_lw = last_location.labware else: @@ -190,7 +200,10 @@ def move_to(self, self._protocol_interface.set_last_location(None) raise else: - self._protocol_interface.set_last_location(location) + self._protocol_interface.set_last_location( + location=location, + mount=location_cache_mount + ) def get_mount(self) -> types.Mount: """Get the mount this pipette is attached to.""" diff --git a/api/src/opentrons/protocols/context/protocol_api/protocol_context.py b/api/src/opentrons/protocols/context/protocol_api/protocol_context.py index 31de2108a35..a1fb1e5a29e 100644 --- a/api/src/opentrons/protocols/context/protocol_api/protocol_context.py +++ b/api/src/opentrons/protocols/context/protocol_api/protocol_context.py @@ -86,6 +86,7 @@ def __init__(self, self._bundled_data: Dict[str, bytes] = bundled_data or {} self._default_max_speeds = AxisMaxSpeeds() self._last_location: Optional[types.Location] = None + self._last_mount: Optional[types.Mount] = None self._loaded_modules: Set['AbstractModule'] = set() @classmethod @@ -195,8 +196,8 @@ def load_module( hc_mod_instance = None for mod in available_modules: compatible = module_geometry.models_compatible( - module_geometry.module_model_from_string(mod.model()), - resolved_model) + module_geometry.module_model_from_string(mod.model()), + resolved_model) if compatible and mod not in self._loaded_modules: self._loaded_modules.add(mod) hc_mod_instance = SynchronousAdapter(mod) @@ -295,10 +296,21 @@ def door_closed(self) -> bool: """Check if door is closed.""" return DoorState.CLOSED == self._hw_manager.hardware.door_state - def get_last_location(self) -> Optional[types.Location]: + def get_last_location( + self, + mount: Optional[types.Mount] = None, + ) -> Optional[types.Location]: """Get the most recent moved to location.""" - return self._last_location + if mount is None or mount == self._last_mount: + return self._last_location - def set_last_location(self, location: Optional[types.Location]) -> None: + return None + + def set_last_location( + self, + location: Optional[types.Location], + mount: Optional[types.Mount] = None, + ) -> None: """Set the most recent moved to location.""" self._last_location = location + self._last_mount = mount