opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/cli/analyze.py +71 -7
- opentrons/config/__init__.py +9 -0
- opentrons/config/advanced_settings.py +22 -0
- opentrons/config/defaults_ot3.py +14 -36
- opentrons/config/feature_flags.py +4 -0
- opentrons/config/types.py +6 -17
- opentrons/drivers/absorbance_reader/abstract.py +27 -3
- opentrons/drivers/absorbance_reader/async_byonoy.py +207 -154
- opentrons/drivers/absorbance_reader/driver.py +24 -15
- opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
- opentrons/drivers/absorbance_reader/simulator.py +32 -6
- opentrons/drivers/types.py +23 -1
- opentrons/execute.py +2 -2
- opentrons/hardware_control/api.py +18 -10
- opentrons/hardware_control/backends/controller.py +3 -2
- opentrons/hardware_control/backends/flex_protocol.py +11 -5
- opentrons/hardware_control/backends/ot3controller.py +18 -50
- opentrons/hardware_control/backends/ot3simulator.py +7 -6
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
- opentrons/hardware_control/module_control.py +43 -2
- opentrons/hardware_control/modules/__init__.py +7 -1
- opentrons/hardware_control/modules/absorbance_reader.py +230 -83
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/heater_shaker.py +8 -3
- opentrons/hardware_control/modules/magdeck.py +12 -3
- opentrons/hardware_control/modules/mod_abc.py +27 -2
- opentrons/hardware_control/modules/tempdeck.py +15 -7
- opentrons/hardware_control/modules/thermocycler.py +69 -3
- opentrons/hardware_control/modules/types.py +11 -5
- opentrons/hardware_control/modules/update.py +11 -5
- opentrons/hardware_control/modules/utils.py +3 -1
- opentrons/hardware_control/ot3_calibration.py +6 -6
- opentrons/hardware_control/ot3api.py +126 -89
- opentrons/hardware_control/poller.py +15 -11
- opentrons/hardware_control/protocols/__init__.py +1 -7
- opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
- opentrons/hardware_control/protocols/liquid_handler.py +5 -0
- opentrons/motion_planning/__init__.py +2 -0
- opentrons/motion_planning/waypoints.py +32 -0
- opentrons/protocol_api/__init__.py +2 -1
- opentrons/protocol_api/_liquid.py +87 -1
- opentrons/protocol_api/_parameter_context.py +10 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
- opentrons/protocol_api/core/engine/instrument.py +29 -25
- opentrons/protocol_api/core/engine/labware.py +10 -2
- opentrons/protocol_api/core/engine/module_core.py +129 -17
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
- opentrons/protocol_api/core/engine/protocol.py +55 -2
- opentrons/protocol_api/core/instrument.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/module.py +22 -4
- opentrons/protocol_api/core/protocol.py +5 -2
- opentrons/protocol_api/instrument_context.py +52 -20
- opentrons/protocol_api/labware.py +13 -1
- opentrons/protocol_api/module_contexts.py +68 -13
- opentrons/protocol_api/protocol_context.py +38 -4
- opentrons/protocol_api/validation.py +5 -3
- opentrons/protocol_engine/__init__.py +10 -9
- opentrons/protocol_engine/actions/__init__.py +5 -0
- opentrons/protocol_engine/actions/actions.py +42 -25
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/sync_client.py +7 -1
- opentrons/protocol_engine/clients/transports.py +1 -1
- opentrons/protocol_engine/commands/__init__.py +0 -4
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +161 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
- opentrons/protocol_engine/commands/aspirate.py +29 -16
- opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
- opentrons/protocol_engine/commands/blow_out.py +63 -14
- opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
- opentrons/protocol_engine/commands/command.py +28 -17
- opentrons/protocol_engine/commands/command_unions.py +37 -24
- opentrons/protocol_engine/commands/comment.py +5 -3
- opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
- opentrons/protocol_engine/commands/custom.py +5 -3
- opentrons/protocol_engine/commands/dispense.py +42 -20
- opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
- opentrons/protocol_engine/commands/drop_tip.py +68 -15
- opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
- opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/home.py +11 -5
- opentrons/protocol_engine/commands/liquid_probe.py +146 -88
- opentrons/protocol_engine/commands/load_labware.py +19 -5
- opentrons/protocol_engine/commands/load_liquid.py +18 -7
- opentrons/protocol_engine/commands/load_module.py +43 -6
- opentrons/protocol_engine/commands/load_pipette.py +18 -17
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
- opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
- opentrons/protocol_engine/commands/move_labware.py +106 -19
- opentrons/protocol_engine/commands/move_relative.py +15 -3
- opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
- opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
- opentrons/protocol_engine/commands/move_to_well.py +37 -10
- opentrons/protocol_engine/commands/pick_up_tip.py +50 -29
- opentrons/protocol_engine/commands/pipetting_common.py +39 -15
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
- opentrons/protocol_engine/commands/reload_labware.py +13 -4
- opentrons/protocol_engine/commands/retract_axis.py +6 -3
- opentrons/protocol_engine/commands/save_position.py +2 -3
- opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
- opentrons/protocol_engine/commands/set_status_bar.py +5 -3
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
- opentrons/protocol_engine/commands/touch_tip.py +19 -7
- opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +194 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
- opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
- opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
- opentrons/protocol_engine/create_protocol_engine.py +41 -8
- opentrons/protocol_engine/engine_support.py +2 -1
- opentrons/protocol_engine/error_recovery_policy.py +14 -3
- opentrons/protocol_engine/errors/__init__.py +18 -0
- opentrons/protocol_engine/errors/exceptions.py +114 -2
- opentrons/protocol_engine/execution/__init__.py +2 -0
- opentrons/protocol_engine/execution/command_executor.py +22 -13
- opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
- opentrons/protocol_engine/execution/door_watcher.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +2 -1
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +4 -2
- opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
- opentrons/protocol_engine/execution/labware_movement.py +6 -3
- opentrons/protocol_engine/execution/movement.py +8 -3
- opentrons/protocol_engine/execution/pipetting.py +7 -4
- opentrons/protocol_engine/execution/queue_worker.py +6 -2
- opentrons/protocol_engine/execution/run_control.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
- opentrons/protocol_engine/execution/tip_handler.py +77 -43
- opentrons/protocol_engine/notes/__init__.py +14 -2
- opentrons/protocol_engine/notes/notes.py +18 -1
- opentrons/protocol_engine/plugins.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +54 -31
- opentrons/protocol_engine/resources/__init__.py +2 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
- opentrons/protocol_engine/resources/file_provider.py +157 -0
- opentrons/protocol_engine/resources/fixture_validation.py +5 -0
- opentrons/protocol_engine/resources/labware_validation.py +10 -0
- opentrons/protocol_engine/state/__init__.py +0 -70
- opentrons/protocol_engine/state/addressable_areas.py +1 -1
- opentrons/protocol_engine/state/command_history.py +21 -2
- opentrons/protocol_engine/state/commands.py +110 -31
- opentrons/protocol_engine/state/files.py +59 -0
- opentrons/protocol_engine/state/frustum_helpers.py +440 -0
- opentrons/protocol_engine/state/geometry.py +359 -15
- opentrons/protocol_engine/state/labware.py +166 -63
- opentrons/protocol_engine/state/liquids.py +1 -1
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
- opentrons/protocol_engine/state/modules.py +167 -85
- opentrons/protocol_engine/state/motion.py +16 -9
- opentrons/protocol_engine/state/pipettes.py +157 -317
- opentrons/protocol_engine/state/state.py +30 -1
- opentrons/protocol_engine/state/state_summary.py +3 -0
- opentrons/protocol_engine/state/tips.py +69 -114
- opentrons/protocol_engine/state/update_types.py +408 -0
- opentrons/protocol_engine/state/wells.py +236 -0
- opentrons/protocol_engine/types.py +90 -0
- opentrons/protocol_reader/file_format_validator.py +83 -15
- opentrons/protocol_runner/json_translator.py +21 -5
- opentrons/protocol_runner/legacy_command_mapper.py +27 -6
- opentrons/protocol_runner/legacy_context_plugin.py +27 -71
- opentrons/protocol_runner/protocol_runner.py +6 -3
- opentrons/protocol_runner/run_orchestrator.py +26 -6
- opentrons/protocols/advanced_control/mix.py +3 -5
- opentrons/protocols/advanced_control/transfers.py +125 -56
- opentrons/protocols/api_support/constants.py +1 -1
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/labware_like.py +4 -4
- opentrons/protocols/api_support/tip_tracker.py +2 -2
- opentrons/protocols/api_support/types.py +15 -2
- opentrons/protocols/api_support/util.py +30 -42
- opentrons/protocols/duration/errors.py +1 -1
- opentrons/protocols/duration/estimator.py +50 -29
- opentrons/protocols/execution/dev_types.py +2 -2
- opentrons/protocols/execution/execute_json_v4.py +15 -10
- opentrons/protocols/execution/execute_python.py +8 -3
- opentrons/protocols/geometry/planning.py +12 -12
- opentrons/protocols/labware.py +17 -33
- opentrons/simulate.py +3 -3
- opentrons/types.py +30 -3
- opentrons/util/logging_config.py +34 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
- opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
- opentrons/protocol_engine/commands/configuring_common.py +0 -26
- opentrons/protocol_runner/thread_async_queue.py +0 -174
- /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
- /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
|
@@ -7,7 +7,7 @@ from typing_extensions import Literal
|
|
|
7
7
|
from .pipetting_common import PipetteIdMixin
|
|
8
8
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
9
9
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
10
|
-
from .
|
|
10
|
+
from ..state.update_types import StateUpdate
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from ..execution import EquipmentHandler
|
|
@@ -34,12 +34,6 @@ class ConfigureForVolumeParams(PipetteIdMixin):
|
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
class ConfigureForVolumePrivateResult(PipetteConfigUpdateResultMixin):
|
|
38
|
-
"""Result sent to the store but not serialized."""
|
|
39
|
-
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
|
|
43
37
|
class ConfigureForVolumeResult(BaseModel):
|
|
44
38
|
"""Result data from execution of an ConfigureForVolume command."""
|
|
45
39
|
|
|
@@ -49,7 +43,7 @@ class ConfigureForVolumeResult(BaseModel):
|
|
|
49
43
|
class ConfigureForVolumeImplementation(
|
|
50
44
|
AbstractCommandImpl[
|
|
51
45
|
ConfigureForVolumeParams,
|
|
52
|
-
SuccessData[ConfigureForVolumeResult
|
|
46
|
+
SuccessData[ConfigureForVolumeResult],
|
|
53
47
|
]
|
|
54
48
|
):
|
|
55
49
|
"""Configure for volume command implementation."""
|
|
@@ -59,7 +53,7 @@ class ConfigureForVolumeImplementation(
|
|
|
59
53
|
|
|
60
54
|
async def execute(
|
|
61
55
|
self, params: ConfigureForVolumeParams
|
|
62
|
-
) -> SuccessData[ConfigureForVolumeResult
|
|
56
|
+
) -> SuccessData[ConfigureForVolumeResult]:
|
|
63
57
|
"""Check that requested pipette can be configured for the given volume."""
|
|
64
58
|
pipette_result = await self._equipment.configure_for_volume(
|
|
65
59
|
pipette_id=params.pipetteId,
|
|
@@ -67,13 +61,16 @@ class ConfigureForVolumeImplementation(
|
|
|
67
61
|
tip_overlap_version=params.tipOverlapNotAfterVersion,
|
|
68
62
|
)
|
|
69
63
|
|
|
64
|
+
state_update = StateUpdate()
|
|
65
|
+
state_update.update_pipette_config(
|
|
66
|
+
pipette_id=pipette_result.pipette_id,
|
|
67
|
+
config=pipette_result.static_config,
|
|
68
|
+
serial_number=pipette_result.serial_number,
|
|
69
|
+
)
|
|
70
|
+
|
|
70
71
|
return SuccessData(
|
|
71
72
|
public=ConfigureForVolumeResult(),
|
|
72
|
-
|
|
73
|
-
pipette_id=pipette_result.pipette_id,
|
|
74
|
-
serial_number=pipette_result.serial_number,
|
|
75
|
-
config=pipette_result.static_config,
|
|
76
|
-
),
|
|
73
|
+
state_update=state_update,
|
|
77
74
|
)
|
|
78
75
|
|
|
79
76
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Configure nozzle layout command request, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
from opentrons.protocol_engine.state.update_types import StateUpdate
|
|
3
4
|
from pydantic import BaseModel
|
|
4
5
|
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
5
6
|
from typing_extensions import Literal
|
|
@@ -9,9 +10,6 @@ from .pipetting_common import (
|
|
|
9
10
|
)
|
|
10
11
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
11
12
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
12
|
-
from .configuring_common import (
|
|
13
|
-
PipetteNozzleLayoutResultMixin,
|
|
14
|
-
)
|
|
15
13
|
from ..types import (
|
|
16
14
|
AllNozzleLayoutConfiguration,
|
|
17
15
|
SingleNozzleLayoutConfiguration,
|
|
@@ -39,12 +37,6 @@ class ConfigureNozzleLayoutParams(PipetteIdMixin):
|
|
|
39
37
|
]
|
|
40
38
|
|
|
41
39
|
|
|
42
|
-
class ConfigureNozzleLayoutPrivateResult(PipetteNozzleLayoutResultMixin):
|
|
43
|
-
"""Result sent to the store but not serialized."""
|
|
44
|
-
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
|
|
48
40
|
class ConfigureNozzleLayoutResult(BaseModel):
|
|
49
41
|
"""Result data from execution of an configureNozzleLayout command."""
|
|
50
42
|
|
|
@@ -54,7 +46,7 @@ class ConfigureNozzleLayoutResult(BaseModel):
|
|
|
54
46
|
class ConfigureNozzleLayoutImplementation(
|
|
55
47
|
AbstractCommandImpl[
|
|
56
48
|
ConfigureNozzleLayoutParams,
|
|
57
|
-
SuccessData[ConfigureNozzleLayoutResult
|
|
49
|
+
SuccessData[ConfigureNozzleLayoutResult],
|
|
58
50
|
]
|
|
59
51
|
):
|
|
60
52
|
"""Configure nozzle layout command implementation."""
|
|
@@ -67,7 +59,7 @@ class ConfigureNozzleLayoutImplementation(
|
|
|
67
59
|
|
|
68
60
|
async def execute(
|
|
69
61
|
self, params: ConfigureNozzleLayoutParams
|
|
70
|
-
) -> SuccessData[ConfigureNozzleLayoutResult
|
|
62
|
+
) -> SuccessData[ConfigureNozzleLayoutResult]:
|
|
71
63
|
"""Check that requested pipette can support the requested nozzle layout."""
|
|
72
64
|
primary_nozzle = params.configurationParams.dict().get("primaryNozzle")
|
|
73
65
|
front_right_nozzle = params.configurationParams.dict().get("frontRightNozzle")
|
|
@@ -85,12 +77,14 @@ class ConfigureNozzleLayoutImplementation(
|
|
|
85
77
|
**nozzle_params,
|
|
86
78
|
)
|
|
87
79
|
|
|
80
|
+
update_state = StateUpdate()
|
|
81
|
+
update_state.update_pipette_nozzle(
|
|
82
|
+
pipette_id=params.pipetteId, nozzle_map=nozzle_map
|
|
83
|
+
)
|
|
84
|
+
|
|
88
85
|
return SuccessData(
|
|
89
86
|
public=ConfigureNozzleLayoutResult(),
|
|
90
|
-
|
|
91
|
-
pipette_id=params.pipetteId,
|
|
92
|
-
nozzle_map=nozzle_map,
|
|
93
|
-
),
|
|
87
|
+
state_update=update_state,
|
|
94
88
|
)
|
|
95
89
|
|
|
96
90
|
|
|
@@ -40,16 +40,18 @@ class CustomResult(BaseModel):
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class CustomImplementation(
|
|
43
|
-
AbstractCommandImpl[CustomParams, SuccessData[CustomResult
|
|
43
|
+
AbstractCommandImpl[CustomParams, SuccessData[CustomResult]]
|
|
44
44
|
):
|
|
45
45
|
"""Custom command implementation."""
|
|
46
46
|
|
|
47
47
|
# TODO(mm, 2022-11-09): figure out how a plugin can specify a custom command
|
|
48
48
|
# implementation. For now, always no-op, so we can use custom commands as containers
|
|
49
49
|
# for legacy RPC (pre-ProtocolEngine) payloads.
|
|
50
|
-
async def execute(self, params: CustomParams) -> SuccessData[CustomResult
|
|
50
|
+
async def execute(self, params: CustomParams) -> SuccessData[CustomResult]:
|
|
51
51
|
"""A custom command does nothing when executed directly."""
|
|
52
|
-
return SuccessData(
|
|
52
|
+
return SuccessData(
|
|
53
|
+
public=CustomResult.construct(),
|
|
54
|
+
)
|
|
53
55
|
|
|
54
56
|
|
|
55
57
|
class Custom(BaseCommand[CustomParams, CustomResult, ErrorOccurrence]):
|
|
@@ -8,15 +8,15 @@ from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
|
|
10
10
|
from ..types import DeckPoint
|
|
11
|
+
from ..state.update_types import StateUpdate, CLEAR
|
|
11
12
|
from .pipetting_common import (
|
|
12
13
|
PipetteIdMixin,
|
|
13
14
|
DispenseVolumeMixin,
|
|
14
15
|
FlowRateMixin,
|
|
15
|
-
|
|
16
|
+
LiquidHandlingWellLocationMixin,
|
|
16
17
|
BaseLiquidHandlingResult,
|
|
17
18
|
DestinationPositionResult,
|
|
18
19
|
OverpressureError,
|
|
19
|
-
OverpressureErrorInternalData,
|
|
20
20
|
)
|
|
21
21
|
from .command import (
|
|
22
22
|
AbstractCommandImpl,
|
|
@@ -30,13 +30,14 @@ from ..errors.error_occurrence import ErrorOccurrence
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
31
31
|
from ..execution import MovementHandler, PipettingHandler
|
|
32
32
|
from ..resources import ModelUtils
|
|
33
|
+
from ..state.state import StateView
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
DispenseCommandType = Literal["dispense"]
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
class DispenseParams(
|
|
39
|
-
PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin,
|
|
40
|
+
PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
|
|
40
41
|
):
|
|
41
42
|
"""Payload required to dispense to a specific well."""
|
|
42
43
|
|
|
@@ -53,8 +54,8 @@ class DispenseResult(BaseLiquidHandlingResult, DestinationPositionResult):
|
|
|
53
54
|
|
|
54
55
|
|
|
55
56
|
_ExecuteReturn = Union[
|
|
56
|
-
SuccessData[DispenseResult
|
|
57
|
-
DefinedErrorData[OverpressureError
|
|
57
|
+
SuccessData[DispenseResult],
|
|
58
|
+
DefinedErrorData[OverpressureError],
|
|
58
59
|
]
|
|
59
60
|
|
|
60
61
|
|
|
@@ -63,31 +64,54 @@ class DispenseImplementation(AbstractCommandImpl[DispenseParams, _ExecuteReturn]
|
|
|
63
64
|
|
|
64
65
|
def __init__(
|
|
65
66
|
self,
|
|
67
|
+
state_view: StateView,
|
|
66
68
|
movement: MovementHandler,
|
|
67
69
|
pipetting: PipettingHandler,
|
|
68
70
|
model_utils: ModelUtils,
|
|
69
71
|
**kwargs: object,
|
|
70
72
|
) -> None:
|
|
73
|
+
self._state_view = state_view
|
|
71
74
|
self._movement = movement
|
|
72
75
|
self._pipetting = pipetting
|
|
73
76
|
self._model_utils = model_utils
|
|
74
77
|
|
|
75
78
|
async def execute(self, params: DispenseParams) -> _ExecuteReturn:
|
|
76
79
|
"""Move to and dispense to the requested well."""
|
|
80
|
+
state_update = StateUpdate()
|
|
81
|
+
well_location = params.wellLocation
|
|
82
|
+
labware_id = params.labwareId
|
|
83
|
+
well_name = params.wellName
|
|
84
|
+
volume = params.volume
|
|
85
|
+
|
|
86
|
+
# TODO(pbm, 10-15-24): call self._state_view.geometry.validate_dispense_volume_into_well()
|
|
87
|
+
|
|
77
88
|
position = await self._movement.move_to_well(
|
|
78
89
|
pipette_id=params.pipetteId,
|
|
79
|
-
labware_id=
|
|
80
|
-
well_name=
|
|
81
|
-
well_location=
|
|
90
|
+
labware_id=labware_id,
|
|
91
|
+
well_name=well_name,
|
|
92
|
+
well_location=well_location,
|
|
82
93
|
)
|
|
94
|
+
deck_point = DeckPoint.construct(x=position.x, y=position.y, z=position.z)
|
|
95
|
+
state_update.set_pipette_location(
|
|
96
|
+
pipette_id=params.pipetteId,
|
|
97
|
+
new_labware_id=labware_id,
|
|
98
|
+
new_well_name=well_name,
|
|
99
|
+
new_deck_point=deck_point,
|
|
100
|
+
)
|
|
101
|
+
|
|
83
102
|
try:
|
|
84
103
|
volume = await self._pipetting.dispense_in_place(
|
|
85
104
|
pipette_id=params.pipetteId,
|
|
86
|
-
volume=
|
|
105
|
+
volume=volume,
|
|
87
106
|
flow_rate=params.flowRate,
|
|
88
107
|
push_out=params.pushOut,
|
|
89
108
|
)
|
|
90
109
|
except PipetteOverpressureError as e:
|
|
110
|
+
state_update.set_liquid_operated(
|
|
111
|
+
labware_id=labware_id,
|
|
112
|
+
well_name=well_name,
|
|
113
|
+
volume_added=CLEAR,
|
|
114
|
+
)
|
|
91
115
|
return DefinedErrorData(
|
|
92
116
|
public=OverpressureError(
|
|
93
117
|
id=self._model_utils.generate_id(),
|
|
@@ -101,23 +125,21 @@ class DispenseImplementation(AbstractCommandImpl[DispenseParams, _ExecuteReturn]
|
|
|
101
125
|
],
|
|
102
126
|
errorInfo={"retryLocation": (position.x, position.y, position.z)},
|
|
103
127
|
),
|
|
104
|
-
|
|
105
|
-
position=DeckPoint.construct(
|
|
106
|
-
x=position.x, y=position.y, z=position.z
|
|
107
|
-
)
|
|
108
|
-
),
|
|
128
|
+
state_update=state_update,
|
|
109
129
|
)
|
|
110
130
|
else:
|
|
131
|
+
state_update.set_liquid_operated(
|
|
132
|
+
labware_id=labware_id,
|
|
133
|
+
well_name=well_name,
|
|
134
|
+
volume_added=volume,
|
|
135
|
+
)
|
|
111
136
|
return SuccessData(
|
|
112
|
-
public=DispenseResult(
|
|
113
|
-
|
|
114
|
-
position=DeckPoint(x=position.x, y=position.y, z=position.z),
|
|
115
|
-
),
|
|
116
|
-
private=None,
|
|
137
|
+
public=DispenseResult(volume=volume, position=deck_point),
|
|
138
|
+
state_update=state_update,
|
|
117
139
|
)
|
|
118
140
|
|
|
119
141
|
|
|
120
|
-
class Dispense(BaseCommand[DispenseParams, DispenseResult,
|
|
142
|
+
class Dispense(BaseCommand[DispenseParams, DispenseResult, OverpressureError]):
|
|
121
143
|
"""Dispense command model."""
|
|
122
144
|
|
|
123
145
|
commandType: DispenseCommandType = "dispense"
|
|
@@ -12,7 +12,6 @@ from .pipetting_common import (
|
|
|
12
12
|
FlowRateMixin,
|
|
13
13
|
BaseLiquidHandlingResult,
|
|
14
14
|
OverpressureError,
|
|
15
|
-
OverpressureErrorInternalData,
|
|
16
15
|
)
|
|
17
16
|
from .command import (
|
|
18
17
|
AbstractCommandImpl,
|
|
@@ -22,11 +21,13 @@ from .command import (
|
|
|
22
21
|
DefinedErrorData,
|
|
23
22
|
)
|
|
24
23
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
25
|
-
from ..
|
|
24
|
+
from ..state.update_types import StateUpdate, CLEAR
|
|
25
|
+
from ..types import CurrentWell
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
28
28
|
from ..execution import PipettingHandler, GantryMover
|
|
29
29
|
from ..resources import ModelUtils
|
|
30
|
+
from ..state.state import StateView
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
DispenseInPlaceCommandType = Literal["dispenseInPlace"]
|
|
@@ -48,8 +49,8 @@ class DispenseInPlaceResult(BaseLiquidHandlingResult):
|
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
_ExecuteReturn = Union[
|
|
51
|
-
SuccessData[DispenseInPlaceResult
|
|
52
|
-
DefinedErrorData[OverpressureError
|
|
52
|
+
SuccessData[DispenseInPlaceResult],
|
|
53
|
+
DefinedErrorData[OverpressureError],
|
|
53
54
|
]
|
|
54
55
|
|
|
55
56
|
|
|
@@ -61,17 +62,22 @@ class DispenseInPlaceImplementation(
|
|
|
61
62
|
def __init__(
|
|
62
63
|
self,
|
|
63
64
|
pipetting: PipettingHandler,
|
|
65
|
+
state_view: StateView,
|
|
64
66
|
gantry_mover: GantryMover,
|
|
65
67
|
model_utils: ModelUtils,
|
|
66
68
|
**kwargs: object,
|
|
67
69
|
) -> None:
|
|
68
70
|
self._pipetting = pipetting
|
|
71
|
+
self._state_view = state_view
|
|
69
72
|
self._gantry_mover = gantry_mover
|
|
70
73
|
self._model_utils = model_utils
|
|
71
74
|
|
|
72
75
|
async def execute(self, params: DispenseInPlaceParams) -> _ExecuteReturn:
|
|
73
76
|
"""Dispense without moving the pipette."""
|
|
77
|
+
state_update = StateUpdate()
|
|
78
|
+
current_location = self._state_view.pipettes.get_current_location()
|
|
74
79
|
try:
|
|
80
|
+
current_position = await self._gantry_mover.get_position(params.pipetteId)
|
|
75
81
|
volume = await self._pipetting.dispense_in_place(
|
|
76
82
|
pipette_id=params.pipetteId,
|
|
77
83
|
volume=params.volume,
|
|
@@ -79,7 +85,15 @@ class DispenseInPlaceImplementation(
|
|
|
79
85
|
push_out=params.pushOut,
|
|
80
86
|
)
|
|
81
87
|
except PipetteOverpressureError as e:
|
|
82
|
-
|
|
88
|
+
if (
|
|
89
|
+
isinstance(current_location, CurrentWell)
|
|
90
|
+
and current_location.pipette_id == params.pipetteId
|
|
91
|
+
):
|
|
92
|
+
state_update.set_liquid_operated(
|
|
93
|
+
labware_id=current_location.labware_id,
|
|
94
|
+
well_name=current_location.well_name,
|
|
95
|
+
volume_added=CLEAR,
|
|
96
|
+
)
|
|
83
97
|
return DefinedErrorData(
|
|
84
98
|
public=OverpressureError(
|
|
85
99
|
id=self._model_utils.generate_id(),
|
|
@@ -101,22 +115,26 @@ class DispenseInPlaceImplementation(
|
|
|
101
115
|
}
|
|
102
116
|
),
|
|
103
117
|
),
|
|
104
|
-
|
|
105
|
-
position=DeckPoint(
|
|
106
|
-
x=current_position.x,
|
|
107
|
-
y=current_position.y,
|
|
108
|
-
z=current_position.z,
|
|
109
|
-
),
|
|
110
|
-
),
|
|
118
|
+
state_update=state_update,
|
|
111
119
|
)
|
|
112
120
|
else:
|
|
121
|
+
if (
|
|
122
|
+
isinstance(current_location, CurrentWell)
|
|
123
|
+
and current_location.pipette_id == params.pipetteId
|
|
124
|
+
):
|
|
125
|
+
state_update.set_liquid_operated(
|
|
126
|
+
labware_id=current_location.labware_id,
|
|
127
|
+
well_name=current_location.well_name,
|
|
128
|
+
volume_added=volume,
|
|
129
|
+
)
|
|
113
130
|
return SuccessData(
|
|
114
|
-
public=DispenseInPlaceResult(volume=volume),
|
|
131
|
+
public=DispenseInPlaceResult(volume=volume),
|
|
132
|
+
state_update=state_update,
|
|
115
133
|
)
|
|
116
134
|
|
|
117
135
|
|
|
118
136
|
class DispenseInPlace(
|
|
119
|
-
BaseCommand[DispenseInPlaceParams, DispenseInPlaceResult,
|
|
137
|
+
BaseCommand[DispenseInPlaceParams, DispenseInPlaceResult, OverpressureError]
|
|
120
138
|
):
|
|
121
139
|
"""DispenseInPlace command model."""
|
|
122
140
|
|
|
@@ -5,13 +5,27 @@ from pydantic import Field
|
|
|
5
5
|
from typing import TYPE_CHECKING, Optional, Type
|
|
6
6
|
from typing_extensions import Literal
|
|
7
7
|
|
|
8
|
+
from opentrons.protocol_engine.errors.exceptions import TipAttachedError
|
|
9
|
+
from opentrons.protocol_engine.resources.model_utils import ModelUtils
|
|
10
|
+
|
|
11
|
+
from ..state import update_types
|
|
8
12
|
from ..types import DropTipWellLocation, DeckPoint
|
|
9
|
-
from .pipetting_common import
|
|
10
|
-
|
|
13
|
+
from .pipetting_common import (
|
|
14
|
+
PipetteIdMixin,
|
|
15
|
+
DestinationPositionResult,
|
|
16
|
+
TipPhysicallyAttachedError,
|
|
17
|
+
)
|
|
18
|
+
from .command import (
|
|
19
|
+
AbstractCommandImpl,
|
|
20
|
+
BaseCommand,
|
|
21
|
+
BaseCommandCreate,
|
|
22
|
+
DefinedErrorData,
|
|
23
|
+
SuccessData,
|
|
24
|
+
)
|
|
11
25
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
12
26
|
|
|
13
27
|
if TYPE_CHECKING:
|
|
14
|
-
from ..state import StateView
|
|
28
|
+
from ..state.state import StateView
|
|
15
29
|
from ..execution import MovementHandler, TipHandler
|
|
16
30
|
|
|
17
31
|
|
|
@@ -53,9 +67,12 @@ class DropTipResult(DestinationPositionResult):
|
|
|
53
67
|
pass
|
|
54
68
|
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
)
|
|
70
|
+
_ExecuteReturn = (
|
|
71
|
+
SuccessData[DropTipResult] | DefinedErrorData[TipPhysicallyAttachedError]
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
59
76
|
"""Drop tip command implementation."""
|
|
60
77
|
|
|
61
78
|
def __init__(
|
|
@@ -63,19 +80,23 @@ class DropTipImplementation(
|
|
|
63
80
|
state_view: StateView,
|
|
64
81
|
tip_handler: TipHandler,
|
|
65
82
|
movement: MovementHandler,
|
|
83
|
+
model_utils: ModelUtils,
|
|
66
84
|
**kwargs: object,
|
|
67
85
|
) -> None:
|
|
68
86
|
self._state_view = state_view
|
|
69
87
|
self._tip_handler = tip_handler
|
|
70
88
|
self._movement_handler = movement
|
|
89
|
+
self._model_utils = model_utils
|
|
71
90
|
|
|
72
|
-
async def execute(self, params: DropTipParams) ->
|
|
91
|
+
async def execute(self, params: DropTipParams) -> _ExecuteReturn:
|
|
73
92
|
"""Move to and drop a tip using the requested pipette."""
|
|
74
93
|
pipette_id = params.pipetteId
|
|
75
94
|
labware_id = params.labwareId
|
|
76
95
|
well_name = params.wellName
|
|
77
96
|
home_after = params.homeAfter
|
|
78
97
|
|
|
98
|
+
state_update = update_types.StateUpdate()
|
|
99
|
+
|
|
79
100
|
if params.alternateDropLocation:
|
|
80
101
|
well_location = self._state_view.geometry.get_next_tip_drop_location(
|
|
81
102
|
labware_id=labware_id,
|
|
@@ -101,16 +122,48 @@ class DropTipImplementation(
|
|
|
101
122
|
well_name=well_name,
|
|
102
123
|
well_location=tip_drop_location,
|
|
103
124
|
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
),
|
|
111
|
-
private=None,
|
|
125
|
+
deck_point = DeckPoint.construct(x=position.x, y=position.y, z=position.z)
|
|
126
|
+
state_update.set_pipette_location(
|
|
127
|
+
pipette_id=pipette_id,
|
|
128
|
+
new_labware_id=labware_id,
|
|
129
|
+
new_well_name=well_name,
|
|
130
|
+
new_deck_point=deck_point,
|
|
112
131
|
)
|
|
113
132
|
|
|
133
|
+
try:
|
|
134
|
+
await self._tip_handler.drop_tip(
|
|
135
|
+
pipette_id=pipette_id, home_after=home_after
|
|
136
|
+
)
|
|
137
|
+
except TipAttachedError as exception:
|
|
138
|
+
error = TipPhysicallyAttachedError(
|
|
139
|
+
id=self._model_utils.generate_id(),
|
|
140
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
141
|
+
wrappedErrors=[
|
|
142
|
+
ErrorOccurrence.from_failed(
|
|
143
|
+
id=self._model_utils.generate_id(),
|
|
144
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
145
|
+
error=exception,
|
|
146
|
+
)
|
|
147
|
+
],
|
|
148
|
+
)
|
|
149
|
+
state_update_if_false_positive = update_types.StateUpdate()
|
|
150
|
+
state_update_if_false_positive.update_pipette_tip_state(
|
|
151
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
152
|
+
)
|
|
153
|
+
return DefinedErrorData(
|
|
154
|
+
public=error,
|
|
155
|
+
state_update=state_update,
|
|
156
|
+
state_update_if_false_positive=state_update_if_false_positive,
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
state_update.update_pipette_tip_state(
|
|
160
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
161
|
+
)
|
|
162
|
+
return SuccessData(
|
|
163
|
+
public=DropTipResult(position=deck_point),
|
|
164
|
+
state_update=state_update,
|
|
165
|
+
)
|
|
166
|
+
|
|
114
167
|
|
|
115
168
|
class DropTip(BaseCommand[DropTipParams, DropTipResult, ErrorOccurrence]):
|
|
116
169
|
"""Drop tip command model."""
|
|
@@ -4,9 +4,18 @@ from pydantic import Field, BaseModel
|
|
|
4
4
|
from typing import TYPE_CHECKING, Optional, Type
|
|
5
5
|
from typing_extensions import Literal
|
|
6
6
|
|
|
7
|
-
from .
|
|
8
|
-
|
|
7
|
+
from .command import (
|
|
8
|
+
AbstractCommandImpl,
|
|
9
|
+
BaseCommand,
|
|
10
|
+
BaseCommandCreate,
|
|
11
|
+
DefinedErrorData,
|
|
12
|
+
SuccessData,
|
|
13
|
+
)
|
|
14
|
+
from .pipetting_common import PipetteIdMixin, TipPhysicallyAttachedError
|
|
15
|
+
from ..errors.exceptions import TipAttachedError
|
|
9
16
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
17
|
+
from ..resources.model_utils import ModelUtils
|
|
18
|
+
from ..state import update_types
|
|
10
19
|
|
|
11
20
|
if TYPE_CHECKING:
|
|
12
21
|
from ..execution import TipHandler
|
|
@@ -34,27 +43,59 @@ class DropTipInPlaceResult(BaseModel):
|
|
|
34
43
|
pass
|
|
35
44
|
|
|
36
45
|
|
|
46
|
+
_ExecuteReturn = (
|
|
47
|
+
SuccessData[DropTipInPlaceResult] | DefinedErrorData[TipPhysicallyAttachedError]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
37
51
|
class DropTipInPlaceImplementation(
|
|
38
|
-
AbstractCommandImpl[DropTipInPlaceParams,
|
|
52
|
+
AbstractCommandImpl[DropTipInPlaceParams, _ExecuteReturn]
|
|
39
53
|
):
|
|
40
54
|
"""Drop tip in place command implementation."""
|
|
41
55
|
|
|
42
56
|
def __init__(
|
|
43
57
|
self,
|
|
44
58
|
tip_handler: TipHandler,
|
|
59
|
+
model_utils: ModelUtils,
|
|
45
60
|
**kwargs: object,
|
|
46
61
|
) -> None:
|
|
47
62
|
self._tip_handler = tip_handler
|
|
63
|
+
self._model_utils = model_utils
|
|
48
64
|
|
|
49
|
-
async def execute(
|
|
50
|
-
self, params: DropTipInPlaceParams
|
|
51
|
-
) -> SuccessData[DropTipInPlaceResult, None]:
|
|
65
|
+
async def execute(self, params: DropTipInPlaceParams) -> _ExecuteReturn:
|
|
52
66
|
"""Drop a tip using the requested pipette."""
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
state_update = update_types.StateUpdate()
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
await self._tip_handler.drop_tip(
|
|
71
|
+
pipette_id=params.pipetteId, home_after=params.homeAfter
|
|
72
|
+
)
|
|
73
|
+
except TipAttachedError as exception:
|
|
74
|
+
state_update_if_false_positive = update_types.StateUpdate()
|
|
75
|
+
state_update_if_false_positive.update_pipette_tip_state(
|
|
76
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
77
|
+
)
|
|
78
|
+
error = TipPhysicallyAttachedError(
|
|
79
|
+
id=self._model_utils.generate_id(),
|
|
80
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
81
|
+
wrappedErrors=[
|
|
82
|
+
ErrorOccurrence.from_failed(
|
|
83
|
+
id=self._model_utils.generate_id(),
|
|
84
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
85
|
+
error=exception,
|
|
86
|
+
)
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
return DefinedErrorData(
|
|
90
|
+
public=error,
|
|
91
|
+
state_update=state_update,
|
|
92
|
+
state_update_if_false_positive=state_update_if_false_positive,
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
state_update.update_pipette_tip_state(
|
|
96
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
97
|
+
)
|
|
98
|
+
return SuccessData(public=DropTipInPlaceResult(), state_update=state_update)
|
|
58
99
|
|
|
59
100
|
|
|
60
101
|
class DropTipInPlace(
|
|
@@ -38,7 +38,7 @@ class GetTipPresenceResult(BaseModel):
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class GetTipPresenceImplementation(
|
|
41
|
-
AbstractCommandImpl[GetTipPresenceParams, SuccessData[GetTipPresenceResult
|
|
41
|
+
AbstractCommandImpl[GetTipPresenceParams, SuccessData[GetTipPresenceResult]]
|
|
42
42
|
):
|
|
43
43
|
"""GetTipPresence command implementation."""
|
|
44
44
|
|
|
@@ -51,7 +51,7 @@ class GetTipPresenceImplementation(
|
|
|
51
51
|
|
|
52
52
|
async def execute(
|
|
53
53
|
self, params: GetTipPresenceParams
|
|
54
|
-
) -> SuccessData[GetTipPresenceResult
|
|
54
|
+
) -> SuccessData[GetTipPresenceResult]:
|
|
55
55
|
"""Verify if tip presence is as expected for the requested pipette."""
|
|
56
56
|
pipette_id = params.pipetteId
|
|
57
57
|
|
|
@@ -59,7 +59,9 @@ class GetTipPresenceImplementation(
|
|
|
59
59
|
pipette_id=pipette_id,
|
|
60
60
|
)
|
|
61
61
|
|
|
62
|
-
return SuccessData(
|
|
62
|
+
return SuccessData(
|
|
63
|
+
public=GetTipPresenceResult(status=result),
|
|
64
|
+
)
|
|
63
65
|
|
|
64
66
|
|
|
65
67
|
class GetTipPresence(
|
|
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
|
|
|
9
9
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
13
13
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
14
14
|
|
|
15
15
|
|
|
@@ -27,9 +27,7 @@ class CloseLabwareLatchResult(BaseModel):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class CloseLabwareLatchImpl(
|
|
30
|
-
AbstractCommandImpl[
|
|
31
|
-
CloseLabwareLatchParams, SuccessData[CloseLabwareLatchResult, None]
|
|
32
|
-
]
|
|
30
|
+
AbstractCommandImpl[CloseLabwareLatchParams, SuccessData[CloseLabwareLatchResult]]
|
|
33
31
|
):
|
|
34
32
|
"""Execution implementation of a Heater-Shaker's close labware latch command."""
|
|
35
33
|
|
|
@@ -44,7 +42,7 @@ class CloseLabwareLatchImpl(
|
|
|
44
42
|
|
|
45
43
|
async def execute(
|
|
46
44
|
self, params: CloseLabwareLatchParams
|
|
47
|
-
) -> SuccessData[CloseLabwareLatchResult
|
|
45
|
+
) -> SuccessData[CloseLabwareLatchResult]:
|
|
48
46
|
"""Close a Heater-Shaker's labware latch."""
|
|
49
47
|
# Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
|
|
50
48
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
@@ -59,7 +57,9 @@ class CloseLabwareLatchImpl(
|
|
|
59
57
|
if hs_hardware_module is not None:
|
|
60
58
|
await hs_hardware_module.close_labware_latch()
|
|
61
59
|
|
|
62
|
-
return SuccessData(
|
|
60
|
+
return SuccessData(
|
|
61
|
+
public=CloseLabwareLatchResult(),
|
|
62
|
+
)
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class CloseLabwareLatch(
|