opentrons 8.7.0a2__py3-none-any.whl → 8.7.0a4__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.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/_version.py +2 -2
- opentrons/drivers/thermocycler/abstract.py +0 -1
- opentrons/drivers/thermocycler/driver.py +4 -33
- opentrons/drivers/thermocycler/simulator.py +0 -2
- opentrons/hardware_control/api.py +5 -24
- opentrons/hardware_control/backends/controller.py +2 -8
- opentrons/hardware_control/backends/ot3controller.py +0 -3
- opentrons/hardware_control/backends/ot3simulator.py +1 -2
- opentrons/hardware_control/backends/simulator.py +1 -2
- opentrons/hardware_control/backends/subsystem_manager.py +2 -5
- opentrons/hardware_control/module_control.py +8 -82
- opentrons/hardware_control/modules/__init__.py +0 -3
- opentrons/hardware_control/modules/absorbance_reader.py +4 -11
- opentrons/hardware_control/modules/flex_stacker.py +9 -38
- opentrons/hardware_control/modules/heater_shaker.py +5 -30
- opentrons/hardware_control/modules/magdeck.py +4 -8
- opentrons/hardware_control/modules/mod_abc.py +5 -13
- opentrons/hardware_control/modules/tempdeck.py +5 -25
- opentrons/hardware_control/modules/thermocycler.py +10 -56
- opentrons/hardware_control/modules/types.py +1 -20
- opentrons/hardware_control/modules/utils.py +4 -11
- opentrons/hardware_control/nozzle_manager.py +0 -3
- opentrons/hardware_control/ot3api.py +5 -26
- opentrons/hardware_control/scripts/update_module_fw.py +0 -5
- opentrons/hardware_control/types.py +2 -31
- opentrons/legacy_commands/protocol_commands.py +0 -20
- opentrons/legacy_commands/types.py +0 -42
- opentrons/motion_planning/waypoints.py +29 -15
- opentrons/protocol_api/__init__.py +0 -5
- opentrons/protocol_api/_types.py +1 -6
- opentrons/protocol_api/core/common.py +1 -3
- opentrons/protocol_api/core/engine/_default_labware_versions.py +11 -32
- opentrons/protocol_api/core/engine/labware.py +1 -8
- opentrons/protocol_api/core/engine/module_core.py +0 -4
- opentrons/protocol_api/core/engine/protocol.py +43 -23
- opentrons/protocol_api/core/legacy/legacy_module_core.py +0 -2
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -11
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +2 -14
- opentrons/protocol_api/core/module.py +0 -1
- opentrons/protocol_api/core/protocol.py +2 -11
- opentrons/protocol_api/module_contexts.py +0 -1
- opentrons/protocol_api/protocol_context.py +4 -26
- opentrons/protocol_api/robot_context.py +21 -38
- opentrons/protocol_api/validation.py +1 -6
- opentrons/protocol_engine/actions/__init__.py +2 -4
- opentrons/protocol_engine/actions/actions.py +9 -22
- opentrons/protocol_engine/clients/sync_client.py +7 -6
- opentrons/protocol_engine/commands/__init__.py +0 -42
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +15 -2
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +15 -2
- opentrons/protocol_engine/commands/aspirate.py +0 -1
- opentrons/protocol_engine/commands/command.py +0 -1
- opentrons/protocol_engine/commands/command_unions.py +0 -39
- opentrons/protocol_engine/commands/dispense.py +0 -1
- opentrons/protocol_engine/commands/drop_tip.py +8 -32
- opentrons/protocol_engine/commands/movement_common.py +0 -2
- opentrons/protocol_engine/commands/pick_up_tip.py +11 -21
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +0 -6
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +0 -8
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +1 -17
- opentrons/protocol_engine/commands/touch_tip.py +1 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +22 -6
- opentrons/protocol_engine/errors/__init__.py +0 -4
- opentrons/protocol_engine/errors/exceptions.py +0 -55
- opentrons/protocol_engine/execution/__init__.py +0 -2
- opentrons/protocol_engine/execution/command_executor.py +0 -8
- opentrons/protocol_engine/execution/create_queue_worker.py +1 -5
- opentrons/protocol_engine/execution/labware_movement.py +12 -9
- opentrons/protocol_engine/execution/movement.py +0 -2
- opentrons/protocol_engine/execution/queue_worker.py +0 -4
- opentrons/protocol_engine/execution/run_control.py +0 -8
- opentrons/protocol_engine/protocol_engine.py +33 -67
- opentrons/protocol_engine/resources/__init__.py +0 -2
- opentrons/protocol_engine/resources/deck_configuration_provider.py +0 -7
- opentrons/protocol_engine/resources/labware_validation.py +6 -10
- opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
- opentrons/protocol_engine/state/_well_math.py +18 -60
- opentrons/protocol_engine/state/addressable_areas.py +0 -2
- opentrons/protocol_engine/state/commands.py +7 -7
- opentrons/protocol_engine/state/geometry.py +374 -204
- opentrons/protocol_engine/state/labware.py +102 -52
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +0 -37
- opentrons/protocol_engine/state/modules.py +8 -21
- opentrons/protocol_engine/state/motion.py +0 -44
- opentrons/protocol_engine/state/state.py +0 -14
- opentrons/protocol_engine/state/state_summary.py +0 -2
- opentrons/protocol_engine/state/tips.py +258 -177
- opentrons/protocol_engine/state/update_types.py +9 -16
- opentrons/protocol_engine/types/__init__.py +3 -9
- opentrons/protocol_engine/types/deck_configuration.py +1 -5
- opentrons/protocol_engine/types/instrument.py +1 -8
- opentrons/protocol_engine/types/labware.py +13 -1
- opentrons/protocol_engine/types/module.py +0 -10
- opentrons/protocol_engine/types/tip.py +0 -9
- opentrons/protocol_runner/create_simulating_orchestrator.py +2 -29
- opentrons/protocol_runner/run_orchestrator.py +2 -18
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/types.py +1 -2
- opentrons/simulate.py +15 -48
- opentrons/system/camera.py +1 -1
- {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/METADATA +4 -4
- {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/RECORD +105 -118
- opentrons/protocol_api/core/engine/tasks.py +0 -35
- opentrons/protocol_api/core/legacy/tasks.py +0 -19
- opentrons/protocol_api/core/legacy_simulator/tasks.py +0 -19
- opentrons/protocol_api/core/tasks.py +0 -31
- opentrons/protocol_api/tasks.py +0 -48
- opentrons/protocol_engine/commands/create_timer.py +0 -83
- opentrons/protocol_engine/commands/set_tip_state.py +0 -97
- opentrons/protocol_engine/commands/wait_for_tasks.py +0 -98
- opentrons/protocol_engine/execution/task_handler.py +0 -157
- opentrons/protocol_engine/resources/concurrency_provider.py +0 -27
- opentrons/protocol_engine/state/labware_origin_math/errors.py +0 -94
- opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +0 -1331
- opentrons/protocol_engine/state/tasks.py +0 -139
- opentrons/protocol_engine/types/tasks.py +0 -38
- {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/WHEEL +0 -0
- {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/entry_points.txt +0 -0
- {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/licenses/LICENSE +0 -0
opentrons/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '8.7.
|
|
32
|
-
__version_tuple__ = version_tuple = (8, 7, 0, '
|
|
31
|
+
__version__ = version = '8.7.0a4'
|
|
32
|
+
__version_tuple__ = version_tuple = (8, 7, 0, 'a4')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -226,7 +226,6 @@ class ThermocyclerDriver(AbstractThermocyclerDriver):
|
|
|
226
226
|
temp: float,
|
|
227
227
|
hold_time: Optional[float] = None,
|
|
228
228
|
volume: Optional[float] = None,
|
|
229
|
-
ramp_rate: Optional[float] = None,
|
|
230
229
|
) -> None:
|
|
231
230
|
"""Send set plate temperature command"""
|
|
232
231
|
temp = min(BLOCK_TARGET_MAX, max(BLOCK_TARGET_MIN, temp))
|
|
@@ -344,38 +343,10 @@ class ThermocyclerDriverV2(ThermocyclerDriver):
|
|
|
344
343
|
"""
|
|
345
344
|
super().__init__(connection)
|
|
346
345
|
|
|
347
|
-
async def
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
volume: Optional[float] = None,
|
|
352
|
-
ramp_rate: Optional[float] = None,
|
|
353
|
-
) -> None:
|
|
354
|
-
"""Send set plate temperature command"""
|
|
355
|
-
temp = min(BLOCK_TARGET_MAX, max(BLOCK_TARGET_MIN, temp))
|
|
356
|
-
|
|
357
|
-
c = (
|
|
358
|
-
CommandBuilder(terminator=TC_COMMAND_TERMINATOR)
|
|
359
|
-
.add_gcode(gcode=GCODE.SET_PLATE_TEMP)
|
|
360
|
-
.add_float(
|
|
361
|
-
prefix="S", value=temp, precision=utils.TC_GCODE_ROUNDING_PRECISION
|
|
362
|
-
)
|
|
363
|
-
)
|
|
364
|
-
if hold_time is not None:
|
|
365
|
-
c = c.add_float(
|
|
366
|
-
prefix="H", value=hold_time, precision=utils.TC_GCODE_ROUNDING_PRECISION
|
|
367
|
-
)
|
|
368
|
-
if volume is not None:
|
|
369
|
-
c = c.add_float(
|
|
370
|
-
prefix="V", value=volume, precision=utils.TC_GCODE_ROUNDING_PRECISION
|
|
371
|
-
)
|
|
372
|
-
|
|
373
|
-
if ramp_rate is not None:
|
|
374
|
-
c = c.add_float(
|
|
375
|
-
prefix="R", value=ramp_rate, precision=utils.TC_GCODE_ROUNDING_PRECISION
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
await self._connection.send_command(command=c, retries=DEFAULT_COMMAND_RETRIES)
|
|
346
|
+
async def set_ramp_rate(self, ramp_rate: float) -> None:
|
|
347
|
+
"""Send a set ramp rate command"""
|
|
348
|
+
# This command is fully unsupported on TC Gen2
|
|
349
|
+
return None
|
|
379
350
|
|
|
380
351
|
async def get_device_info(self) -> Dict[str, str]:
|
|
381
352
|
"""Send get device info command"""
|
|
@@ -67,12 +67,10 @@ class SimulatingDriver(AbstractThermocyclerDriver):
|
|
|
67
67
|
temp: float,
|
|
68
68
|
hold_time: Optional[float] = None,
|
|
69
69
|
volume: Optional[float] = None,
|
|
70
|
-
ramp_rate: Optional[float] = None,
|
|
71
70
|
) -> None:
|
|
72
71
|
self._plate_temperature.target = temp
|
|
73
72
|
self._plate_temperature.current = temp
|
|
74
73
|
self._plate_temperature.hold = 0
|
|
75
|
-
self._ramp_rate = ramp_rate
|
|
76
74
|
|
|
77
75
|
@ensure_yield
|
|
78
76
|
async def get_plate_temperature(self) -> PlateTemperature:
|
|
@@ -44,7 +44,6 @@ from .execution_manager import ExecutionManagerProvider
|
|
|
44
44
|
from .pause_manager import PauseManager
|
|
45
45
|
from .module_control import AttachedModulesControl
|
|
46
46
|
from .types import (
|
|
47
|
-
AsynchronousModuleErrorNotification,
|
|
48
47
|
Axis,
|
|
49
48
|
CriticalPoint,
|
|
50
49
|
DoorState,
|
|
@@ -52,7 +51,6 @@ from .types import (
|
|
|
52
51
|
ErrorMessageNotification,
|
|
53
52
|
HardwareEventHandler,
|
|
54
53
|
HardwareAction,
|
|
55
|
-
HardwareEvent,
|
|
56
54
|
MotionChecks,
|
|
57
55
|
PauseType,
|
|
58
56
|
StatusBarState,
|
|
@@ -169,18 +167,6 @@ class API(
|
|
|
169
167
|
except Exception:
|
|
170
168
|
mod_log.exception("Errored during door state event callback")
|
|
171
169
|
|
|
172
|
-
def _send_module_notification(self, event: HardwareEvent) -> None:
|
|
173
|
-
if not isinstance(event, AsynchronousModuleErrorNotification):
|
|
174
|
-
return
|
|
175
|
-
mod_log.info(
|
|
176
|
-
f"Forwarding module event {event.event} for {event.module_model} {event.module_serial} at {event.port}"
|
|
177
|
-
)
|
|
178
|
-
for cb in self._callbacks:
|
|
179
|
-
try:
|
|
180
|
-
cb(event)
|
|
181
|
-
except Exception:
|
|
182
|
-
mod_log.exception("Errored during module asynchronous callback")
|
|
183
|
-
|
|
184
170
|
def _reset_last_mount(self) -> None:
|
|
185
171
|
self._last_moved_mount = None
|
|
186
172
|
|
|
@@ -261,9 +247,7 @@ class API(
|
|
|
261
247
|
)
|
|
262
248
|
await api_instance.cache_instruments()
|
|
263
249
|
module_controls = await AttachedModulesControl.build(
|
|
264
|
-
api_instance,
|
|
265
|
-
board_revision=backend.board_revision,
|
|
266
|
-
event_callback=api_instance._send_module_notification,
|
|
250
|
+
api_instance, board_revision=backend.board_revision
|
|
267
251
|
)
|
|
268
252
|
backend.module_controls = module_controls
|
|
269
253
|
checked_loop.create_task(backend.watch(loop=checked_loop))
|
|
@@ -322,9 +306,7 @@ class API(
|
|
|
322
306
|
)
|
|
323
307
|
await api_instance.cache_instruments()
|
|
324
308
|
module_controls = await AttachedModulesControl.build(
|
|
325
|
-
api_instance,
|
|
326
|
-
board_revision=backend.board_revision,
|
|
327
|
-
event_callback=api_instance._send_module_notification,
|
|
309
|
+
api_instance, board_revision=backend.board_revision
|
|
328
310
|
)
|
|
329
311
|
backend.module_controls = module_controls
|
|
330
312
|
await backend.watch()
|
|
@@ -1330,10 +1312,9 @@ class API(
|
|
|
1330
1312
|
self.is_simulator
|
|
1331
1313
|
), "Cannot build simulating module from non-simulating hardware control API"
|
|
1332
1314
|
|
|
1333
|
-
return await self._backend.module_controls.
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
),
|
|
1315
|
+
return await self._backend.module_controls.build_module(
|
|
1316
|
+
port="",
|
|
1317
|
+
usb_port=USBPort(name="", port_number=1, port_group=PortGroup.MAIN),
|
|
1337
1318
|
type=modules.ModuleType.from_model(model),
|
|
1338
1319
|
sim_model=model.value,
|
|
1339
1320
|
)
|
|
@@ -360,19 +360,13 @@ class Controller:
|
|
|
360
360
|
"""Run a probe and return the new position dict"""
|
|
361
361
|
return await self._smoothie_driver.probe_axis(axis, distance)
|
|
362
362
|
|
|
363
|
-
async def clean_up(self) -> None:
|
|
363
|
+
async def clean_up(self) -> None:
|
|
364
364
|
try:
|
|
365
365
|
loop = asyncio.get_event_loop()
|
|
366
366
|
except RuntimeError:
|
|
367
367
|
return
|
|
368
|
-
if hasattr(self, "_module_controls") and self._module_controls is not None:
|
|
369
|
-
await self._module_controls.clean_up()
|
|
370
368
|
if hasattr(self, "_event_watcher"):
|
|
371
|
-
if (
|
|
372
|
-
loop.is_running()
|
|
373
|
-
and self._event_watcher
|
|
374
|
-
and not self._event_watcher.closed
|
|
375
|
-
):
|
|
369
|
+
if loop.is_running() and self._event_watcher:
|
|
376
370
|
self._event_watcher.close()
|
|
377
371
|
if hasattr(self, "gpio_chardev"):
|
|
378
372
|
try:
|
|
@@ -1398,9 +1398,6 @@ class OT3Controller(FlexBackend):
|
|
|
1398
1398
|
except RuntimeError:
|
|
1399
1399
|
return
|
|
1400
1400
|
|
|
1401
|
-
if hasattr(self, "_module_controls") and self._module_controls is not None:
|
|
1402
|
-
await self._module_controls.clean_up()
|
|
1403
|
-
|
|
1404
1401
|
if hasattr(self, "_event_watcher"):
|
|
1405
1402
|
if (
|
|
1406
1403
|
loop.is_running()
|
|
@@ -728,8 +728,7 @@ class OT3Simulator(FlexBackend):
|
|
|
728
728
|
@ensure_yield
|
|
729
729
|
async def clean_up(self) -> None:
|
|
730
730
|
"""Clean up."""
|
|
731
|
-
|
|
732
|
-
await self._module_controls.clean_up()
|
|
731
|
+
pass
|
|
733
732
|
|
|
734
733
|
@staticmethod
|
|
735
734
|
def _get_home_position() -> Dict[Axis, float]:
|
|
@@ -414,8 +414,7 @@ class Simulator:
|
|
|
414
414
|
|
|
415
415
|
@ensure_yield
|
|
416
416
|
async def clean_up(self) -> None:
|
|
417
|
-
|
|
418
|
-
await self._module_controls.clean_up()
|
|
417
|
+
pass
|
|
419
418
|
|
|
420
419
|
@ensure_yield
|
|
421
420
|
async def configure_mount(
|
|
@@ -91,8 +91,6 @@ class SubsystemManager:
|
|
|
91
91
|
self._present_tools = tools.types.ToolSummary(
|
|
92
92
|
left=None, right=None, gripper=None
|
|
93
93
|
)
|
|
94
|
-
# This is intended to be an internal variable but is modified in unit tests to avoid long timeouts
|
|
95
|
-
self._check_device_update_timeout = 10.0
|
|
96
94
|
|
|
97
95
|
@property
|
|
98
96
|
def ok(self) -> bool:
|
|
@@ -185,12 +183,11 @@ class SubsystemManager:
|
|
|
185
183
|
return self._tool_task_state is True
|
|
186
184
|
|
|
187
185
|
async def _check_devices_after_update(
|
|
188
|
-
self, devices: Set[SubSystem], timeout_sec:
|
|
186
|
+
self, devices: Set[SubSystem], timeout_sec: float = 10.0
|
|
189
187
|
) -> None:
|
|
190
188
|
try:
|
|
191
189
|
await asyncio.wait_for(
|
|
192
|
-
self._do_check_devices_after_update(devices),
|
|
193
|
-
timeout=timeout_sec or self._check_device_update_timeout,
|
|
190
|
+
self._do_check_devices_after_update(devices), timeout=timeout_sec
|
|
194
191
|
)
|
|
195
192
|
except asyncio.TimeoutError:
|
|
196
193
|
raise RuntimeError("Device failed to come back after firmware update")
|
|
@@ -2,11 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
-
from typing import TYPE_CHECKING, List, Optional, Union
|
|
5
|
+
from typing import TYPE_CHECKING, List, Optional, Union
|
|
6
6
|
from glob import glob
|
|
7
7
|
|
|
8
|
-
from opentrons_shared_data.errors.exceptions import EnumeratedError
|
|
9
|
-
|
|
10
8
|
from opentrons.config import IS_ROBOT, IS_LINUX
|
|
11
9
|
from opentrons.drivers.rpi_drivers import types, interfaces, usb, usb_simulator
|
|
12
10
|
from opentrons.hardware_control.emulation.module_server.helpers import (
|
|
@@ -21,16 +19,8 @@ from opentrons.hardware_control.modules.module_calibration import (
|
|
|
21
19
|
from opentrons.hardware_control.modules.types import ModuleAtPort, ModuleType
|
|
22
20
|
from opentrons.hardware_control.modules import SimulatingModuleAtPort
|
|
23
21
|
|
|
24
|
-
|
|
25
22
|
from opentrons.types import Point
|
|
26
|
-
from .types import
|
|
27
|
-
AionotifyEvent,
|
|
28
|
-
BoardRevision,
|
|
29
|
-
OT3Mount,
|
|
30
|
-
StatusBarUpdateEvent,
|
|
31
|
-
HardwareEvent,
|
|
32
|
-
AsynchronousModuleErrorNotification,
|
|
33
|
-
)
|
|
23
|
+
from .types import AionotifyEvent, BoardRevision, OT3Mount, StatusBarUpdateEvent
|
|
34
24
|
from . import modules
|
|
35
25
|
|
|
36
26
|
if TYPE_CHECKING:
|
|
@@ -61,21 +51,10 @@ class AttachedModulesControl:
|
|
|
61
51
|
self,
|
|
62
52
|
api: Union["API", "OT3API"],
|
|
63
53
|
usb: interfaces.USBDriverInterface,
|
|
64
|
-
event_callback: Callable[[HardwareEvent], None],
|
|
65
54
|
) -> None:
|
|
66
55
|
self._available_modules: List[modules.AbstractModule] = []
|
|
67
56
|
self._api = api
|
|
68
57
|
self._usb = usb
|
|
69
|
-
self._event_callback = event_callback
|
|
70
|
-
if not IS_ROBOT and not api.is_simulator:
|
|
71
|
-
# Start task that registers emulated modules.
|
|
72
|
-
self._emulation_listen_task: asyncio.Task[
|
|
73
|
-
None
|
|
74
|
-
] | None = api.loop.create_task(
|
|
75
|
-
listen_module_connection(self.register_modules)
|
|
76
|
-
)
|
|
77
|
-
else:
|
|
78
|
-
self._emulation_listen_task = None
|
|
79
58
|
|
|
80
59
|
def subscribe_to_api_event(self, module: modules.AbstractModule) -> None:
|
|
81
60
|
self._api.add_status_bar_listener(module.event_listener)
|
|
@@ -85,20 +64,22 @@ class AttachedModulesControl:
|
|
|
85
64
|
cls,
|
|
86
65
|
api_instance: Union["API", "OT3API"],
|
|
87
66
|
board_revision: BoardRevision,
|
|
88
|
-
event_callback: Callable[[HardwareEvent], None],
|
|
89
67
|
) -> AttachedModulesControl:
|
|
90
68
|
usb_instance = (
|
|
91
69
|
usb.USBBus(board_revision)
|
|
92
70
|
if not api_instance.is_simulator and IS_ROBOT
|
|
93
71
|
else usb_simulator.USBBusSimulator()
|
|
94
72
|
)
|
|
95
|
-
mc_instance = cls(
|
|
96
|
-
api=api_instance, usb=usb_instance, event_callback=event_callback
|
|
97
|
-
)
|
|
73
|
+
mc_instance = cls(api=api_instance, usb=usb_instance)
|
|
98
74
|
|
|
99
75
|
if not api_instance.is_simulator:
|
|
100
76
|
# Do an initial scan of modules.
|
|
101
77
|
await mc_instance.register_modules(mc_instance.scan())
|
|
78
|
+
if not IS_ROBOT:
|
|
79
|
+
# Start task that registers emulated modules.
|
|
80
|
+
api_instance.loop.create_task(
|
|
81
|
+
listen_module_connection(mc_instance.register_modules)
|
|
82
|
+
)
|
|
102
83
|
|
|
103
84
|
return mc_instance
|
|
104
85
|
|
|
@@ -106,37 +87,6 @@ class AttachedModulesControl:
|
|
|
106
87
|
def available_modules(self) -> List[modules.AbstractModule]:
|
|
107
88
|
return self._available_modules
|
|
108
89
|
|
|
109
|
-
async def clean_up(self) -> None:
|
|
110
|
-
"""Clean up all registered modules and emulator scanning tasks (if any)."""
|
|
111
|
-
for module in self._available_modules:
|
|
112
|
-
await module.cleanup()
|
|
113
|
-
if self._emulation_listen_task is not None:
|
|
114
|
-
self._emulation_listen_task.cancel("cleanup")
|
|
115
|
-
try:
|
|
116
|
-
await self._emulation_listen_task
|
|
117
|
-
except asyncio.CancelledError:
|
|
118
|
-
pass
|
|
119
|
-
except Exception:
|
|
120
|
-
log.exception("Exception cleaning up emulation listen task")
|
|
121
|
-
finally:
|
|
122
|
-
self._emulation_listen_task = None
|
|
123
|
-
|
|
124
|
-
async def register_simulated_module(
|
|
125
|
-
self,
|
|
126
|
-
simulated_usb_port: types.USBPort,
|
|
127
|
-
type: modules.ModuleType,
|
|
128
|
-
sim_model: str,
|
|
129
|
-
) -> modules.AbstractModule:
|
|
130
|
-
"""Register a simulated module."""
|
|
131
|
-
module = await self.build_module(
|
|
132
|
-
"", simulated_usb_port, type, sim_model, sim_serial_number=None
|
|
133
|
-
)
|
|
134
|
-
self._available_modules.append(module)
|
|
135
|
-
self._available_modules = sorted(
|
|
136
|
-
self._available_modules, key=modules.AbstractModule.sort_key
|
|
137
|
-
)
|
|
138
|
-
return module
|
|
139
|
-
|
|
140
90
|
async def build_module(
|
|
141
91
|
self,
|
|
142
92
|
port: str,
|
|
@@ -155,7 +105,6 @@ class AttachedModulesControl:
|
|
|
155
105
|
sim_model=sim_model,
|
|
156
106
|
sim_serial_number=sim_serial_number,
|
|
157
107
|
disconnected_callback=self._disconnected_callback,
|
|
158
|
-
error_callback=self._async_error_callback,
|
|
159
108
|
)
|
|
160
109
|
last_event = StatusBarUpdateEvent(
|
|
161
110
|
self._api.get_status_bar_state(), self._api.get_status_bar_enabled()
|
|
@@ -172,29 +121,6 @@ class AttachedModulesControl:
|
|
|
172
121
|
self._api.loop,
|
|
173
122
|
)
|
|
174
123
|
|
|
175
|
-
def _async_error_callback(
|
|
176
|
-
self,
|
|
177
|
-
exc: Exception,
|
|
178
|
-
model: str,
|
|
179
|
-
port: str,
|
|
180
|
-
serial: str | None,
|
|
181
|
-
) -> None:
|
|
182
|
-
"""Used by the module to indicate it saw an error from its data poller."""
|
|
183
|
-
try:
|
|
184
|
-
self._api.loop.call_soon(
|
|
185
|
-
self._event_callback,
|
|
186
|
-
AsynchronousModuleErrorNotification(
|
|
187
|
-
exception=EnumeratedError.ensure(exc),
|
|
188
|
-
module_serial=serial,
|
|
189
|
-
module_model=modules.module_model_from_string(model),
|
|
190
|
-
port=port,
|
|
191
|
-
),
|
|
192
|
-
)
|
|
193
|
-
except Exception:
|
|
194
|
-
log.exception(
|
|
195
|
-
f"Async error callback for module {model} {serial} at {port} for exc {exc} failed"
|
|
196
|
-
)
|
|
197
|
-
|
|
198
124
|
async def unregister_modules(
|
|
199
125
|
self,
|
|
200
126
|
mods_at_ports: Union[
|
|
@@ -27,9 +27,7 @@ from .types import (
|
|
|
27
27
|
LiveData,
|
|
28
28
|
ModuleData,
|
|
29
29
|
ModuleDataValidator,
|
|
30
|
-
module_model_from_string,
|
|
31
30
|
)
|
|
32
|
-
|
|
33
31
|
from .errors import (
|
|
34
32
|
UpdateError,
|
|
35
33
|
AbsorbanceReaderDisconnectedError,
|
|
@@ -68,5 +66,4 @@ __all__ = [
|
|
|
68
66
|
"FlexStackerStatus",
|
|
69
67
|
"PlatformState",
|
|
70
68
|
"StackerAxisState",
|
|
71
|
-
"module_model_from_string",
|
|
72
69
|
]
|
|
@@ -21,7 +21,6 @@ from opentrons.hardware_control.poller import Poller, Reader
|
|
|
21
21
|
from opentrons.hardware_control.modules import mod_abc
|
|
22
22
|
from opentrons.hardware_control.modules.types import (
|
|
23
23
|
ModuleDisconnectedCallback,
|
|
24
|
-
ModuleErrorCallback,
|
|
25
24
|
ModuleType,
|
|
26
25
|
AbsorbanceReaderStatus,
|
|
27
26
|
LiveData,
|
|
@@ -105,13 +104,12 @@ class AbsorbanceReader(mod_abc.AbstractModule):
|
|
|
105
104
|
port: str,
|
|
106
105
|
usb_port: USBPort,
|
|
107
106
|
hw_control_loop: asyncio.AbstractEventLoop,
|
|
108
|
-
execution_manager: ExecutionManager,
|
|
109
|
-
disconnected_callback: ModuleDisconnectedCallback,
|
|
110
|
-
error_callback: ModuleErrorCallback,
|
|
107
|
+
execution_manager: Optional[ExecutionManager] = None,
|
|
111
108
|
poll_interval_seconds: Optional[float] = None,
|
|
112
109
|
simulating: bool = False,
|
|
113
110
|
sim_model: Optional[str] = None,
|
|
114
111
|
sim_serial_number: Optional[str] = None,
|
|
112
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
115
113
|
) -> "AbsorbanceReader":
|
|
116
114
|
"""
|
|
117
115
|
Build and connect to an AbsorbanceReader
|
|
@@ -154,7 +152,6 @@ class AbsorbanceReader(mod_abc.AbstractModule):
|
|
|
154
152
|
hw_control_loop=hw_control_loop,
|
|
155
153
|
execution_manager=execution_manager,
|
|
156
154
|
disconnected_callback=disconnected_callback,
|
|
157
|
-
error_callback=error_callback,
|
|
158
155
|
)
|
|
159
156
|
|
|
160
157
|
try:
|
|
@@ -173,9 +170,8 @@ class AbsorbanceReader(mod_abc.AbstractModule):
|
|
|
173
170
|
poller: Poller,
|
|
174
171
|
device_info: Mapping[str, str],
|
|
175
172
|
hw_control_loop: asyncio.AbstractEventLoop,
|
|
176
|
-
execution_manager: ExecutionManager,
|
|
177
|
-
disconnected_callback: ModuleDisconnectedCallback,
|
|
178
|
-
error_callback: ModuleErrorCallback,
|
|
173
|
+
execution_manager: Optional[ExecutionManager] = None,
|
|
174
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
179
175
|
) -> None:
|
|
180
176
|
"""
|
|
181
177
|
Constructor
|
|
@@ -197,7 +193,6 @@ class AbsorbanceReader(mod_abc.AbstractModule):
|
|
|
197
193
|
hw_control_loop=hw_control_loop,
|
|
198
194
|
execution_manager=execution_manager,
|
|
199
195
|
disconnected_callback=disconnected_callback,
|
|
200
|
-
error_callback=error_callback,
|
|
201
196
|
)
|
|
202
197
|
self._device_info = device_info
|
|
203
198
|
self._reader = reader
|
|
@@ -376,5 +371,3 @@ class AbsorbanceReader(mod_abc.AbstractModule):
|
|
|
376
371
|
self._error = str(error)
|
|
377
372
|
if isinstance(error, AbsorbanceReaderDisconnectedError):
|
|
378
373
|
self.disconnected_callback()
|
|
379
|
-
else:
|
|
380
|
-
self.error_callback(error)
|
|
@@ -44,7 +44,6 @@ from opentrons.hardware_control.modules.types import (
|
|
|
44
44
|
FlexStackerStatus,
|
|
45
45
|
HopperDoorState,
|
|
46
46
|
LatchState,
|
|
47
|
-
ModuleErrorCallback,
|
|
48
47
|
ModuleDisconnectedCallback,
|
|
49
48
|
ModuleType,
|
|
50
49
|
PlatformState,
|
|
@@ -216,13 +215,12 @@ class FlexStacker(mod_abc.AbstractModule):
|
|
|
216
215
|
port: str,
|
|
217
216
|
usb_port: USBPort,
|
|
218
217
|
hw_control_loop: asyncio.AbstractEventLoop,
|
|
219
|
-
execution_manager: ExecutionManager,
|
|
220
|
-
|
|
221
|
-
error_callback: ModuleErrorCallback,
|
|
222
|
-
poll_interval_seconds: float | None = None,
|
|
218
|
+
execution_manager: Optional[ExecutionManager] = None,
|
|
219
|
+
poll_interval_seconds: Optional[float] = None,
|
|
223
220
|
simulating: bool = False,
|
|
224
221
|
sim_model: Optional[str] = None,
|
|
225
222
|
sim_serial_number: Optional[str] = None,
|
|
223
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
226
224
|
) -> "FlexStacker":
|
|
227
225
|
"""
|
|
228
226
|
Build a FlexStacker
|
|
@@ -261,9 +259,11 @@ class FlexStacker(mod_abc.AbstractModule):
|
|
|
261
259
|
hw_control_loop=hw_control_loop,
|
|
262
260
|
execution_manager=execution_manager,
|
|
263
261
|
disconnected_callback=disconnected_callback,
|
|
264
|
-
error_callback=error_callback,
|
|
265
262
|
)
|
|
266
263
|
|
|
264
|
+
# Set initialized callback
|
|
265
|
+
reader.set_initialized_callback(module._initialized_callback)
|
|
266
|
+
|
|
267
267
|
# Enable stallguard
|
|
268
268
|
for axis, config in STALLGUARD_CONFIG.items():
|
|
269
269
|
await driver.set_stallguard_threshold(
|
|
@@ -286,9 +286,8 @@ class FlexStacker(mod_abc.AbstractModule):
|
|
|
286
286
|
poller: Poller,
|
|
287
287
|
device_info: Mapping[str, str],
|
|
288
288
|
hw_control_loop: asyncio.AbstractEventLoop,
|
|
289
|
-
execution_manager: ExecutionManager,
|
|
290
|
-
disconnected_callback: ModuleDisconnectedCallback,
|
|
291
|
-
error_callback: ModuleErrorCallback,
|
|
289
|
+
execution_manager: Optional[ExecutionManager] = None,
|
|
290
|
+
disconnected_callback: ModuleDisconnectedCallback = None,
|
|
292
291
|
):
|
|
293
292
|
super().__init__(
|
|
294
293
|
port=port,
|
|
@@ -296,7 +295,6 @@ class FlexStacker(mod_abc.AbstractModule):
|
|
|
296
295
|
hw_control_loop=hw_control_loop,
|
|
297
296
|
execution_manager=execution_manager,
|
|
298
297
|
disconnected_callback=disconnected_callback,
|
|
299
|
-
error_callback=error_callback,
|
|
300
298
|
)
|
|
301
299
|
self._device_info = device_info
|
|
302
300
|
self._driver = driver
|
|
@@ -306,20 +304,12 @@ class FlexStacker(mod_abc.AbstractModule):
|
|
|
306
304
|
self._stacker_status = FlexStackerStatus.IDLE
|
|
307
305
|
self._last_status_bar_event: Optional[StatusBarUpdateEvent] = None
|
|
308
306
|
self._should_identify = False
|
|
309
|
-
# Set initialized callback
|
|
310
|
-
self._unsubscribe_init = reader.set_initialized_callback(
|
|
311
|
-
self._initialized_callback
|
|
312
|
-
)
|
|
313
|
-
self._unsubscribe_error = reader.set_error_callback(self._async_error_callback)
|
|
314
307
|
|
|
315
308
|
async def _initialized_callback(self) -> None:
|
|
316
309
|
"""Called by the reader once the module is initialized."""
|
|
317
310
|
if self._last_status_bar_event:
|
|
318
311
|
await self._handle_status_bar_event(self._last_status_bar_event)
|
|
319
312
|
|
|
320
|
-
def _async_error_callback(self, exception: Exception) -> None:
|
|
321
|
-
self.error_callback(exception)
|
|
322
|
-
|
|
323
313
|
async def cleanup(self) -> None:
|
|
324
314
|
"""Stop the poller task"""
|
|
325
315
|
await self._poller.stop()
|
|
@@ -874,27 +864,10 @@ class FlexStackerReader(Reader):
|
|
|
874
864
|
self.installation_detected = False
|
|
875
865
|
self._refresh_state = False
|
|
876
866
|
self._initialized_callback: Optional[Callable[[], Awaitable[None]]] = None
|
|
877
|
-
self._error_callback: Optional[Callable[[Exception], None]] = None
|
|
878
867
|
|
|
879
|
-
def set_initialized_callback(
|
|
880
|
-
self, callback: Callable[[], Awaitable[None]]
|
|
881
|
-
) -> Callable[[], None]:
|
|
868
|
+
def set_initialized_callback(self, callback: Callable[[], Awaitable[None]]) -> None:
|
|
882
869
|
"""Sets the callback used when done initializing the module."""
|
|
883
870
|
self._initialized_callback = callback
|
|
884
|
-
return self._remove_init_callback
|
|
885
|
-
|
|
886
|
-
def _remove_init_callback(self) -> None:
|
|
887
|
-
self._initialized_callback = None
|
|
888
|
-
|
|
889
|
-
def set_error_callback(
|
|
890
|
-
self, error_callback: Callable[[Exception], None]
|
|
891
|
-
) -> Callable[[], None]:
|
|
892
|
-
"""Register a handler for asynchronous hardware errors."""
|
|
893
|
-
self._error_callback = error_callback
|
|
894
|
-
return self._remove_error_callback
|
|
895
|
-
|
|
896
|
-
def _remove_error_callback(self) -> None:
|
|
897
|
-
self._error_callback = None
|
|
898
871
|
|
|
899
872
|
async def read(self) -> None:
|
|
900
873
|
await self.get_door_closed()
|
|
@@ -969,8 +942,6 @@ class FlexStackerReader(Reader):
|
|
|
969
942
|
if exception is None:
|
|
970
943
|
self.error = None
|
|
971
944
|
else:
|
|
972
|
-
if self._error_callback:
|
|
973
|
-
self._error_callback(exception)
|
|
974
945
|
try:
|
|
975
946
|
self.error = str(exception.args[0])
|
|
976
947
|
except Exception:
|