opentrons 8.6.0a1__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/__init__.py +150 -0
- opentrons/_version.py +34 -0
- opentrons/calibration_storage/__init__.py +54 -0
- opentrons/calibration_storage/deck_configuration.py +62 -0
- opentrons/calibration_storage/encoder_decoder.py +31 -0
- opentrons/calibration_storage/file_operators.py +142 -0
- opentrons/calibration_storage/helpers.py +103 -0
- opentrons/calibration_storage/ot2/__init__.py +34 -0
- opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
- opentrons/calibration_storage/ot2/models/__init__.py +0 -0
- opentrons/calibration_storage/ot2/models/v1.py +149 -0
- opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
- opentrons/calibration_storage/ot2/tip_length.py +281 -0
- opentrons/calibration_storage/ot3/__init__.py +31 -0
- opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
- opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
- opentrons/calibration_storage/ot3/models/__init__.py +0 -0
- opentrons/calibration_storage/ot3/models/v1.py +122 -0
- opentrons/calibration_storage/ot3/module_offset.py +138 -0
- opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
- opentrons/calibration_storage/types.py +45 -0
- opentrons/cli/__init__.py +21 -0
- opentrons/cli/__main__.py +5 -0
- opentrons/cli/analyze.py +501 -0
- opentrons/config/__init__.py +631 -0
- opentrons/config/advanced_settings.py +871 -0
- opentrons/config/defaults_ot2.py +214 -0
- opentrons/config/defaults_ot3.py +499 -0
- opentrons/config/feature_flags.py +86 -0
- opentrons/config/gripper_config.py +55 -0
- opentrons/config/reset.py +203 -0
- opentrons/config/robot_configs.py +187 -0
- opentrons/config/types.py +183 -0
- opentrons/drivers/__init__.py +0 -0
- opentrons/drivers/absorbance_reader/__init__.py +11 -0
- opentrons/drivers/absorbance_reader/abstract.py +72 -0
- opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
- opentrons/drivers/absorbance_reader/driver.py +81 -0
- opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
- opentrons/drivers/absorbance_reader/simulator.py +84 -0
- opentrons/drivers/asyncio/__init__.py +0 -0
- opentrons/drivers/asyncio/communication/__init__.py +22 -0
- opentrons/drivers/asyncio/communication/async_serial.py +183 -0
- opentrons/drivers/asyncio/communication/errors.py +88 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +552 -0
- opentrons/drivers/command_builder.py +102 -0
- opentrons/drivers/flex_stacker/__init__.py +13 -0
- opentrons/drivers/flex_stacker/abstract.py +214 -0
- opentrons/drivers/flex_stacker/driver.py +768 -0
- opentrons/drivers/flex_stacker/errors.py +68 -0
- opentrons/drivers/flex_stacker/simulator.py +309 -0
- opentrons/drivers/flex_stacker/types.py +367 -0
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/drivers/heater_shaker/__init__.py +5 -0
- opentrons/drivers/heater_shaker/abstract.py +76 -0
- opentrons/drivers/heater_shaker/driver.py +204 -0
- opentrons/drivers/heater_shaker/simulator.py +94 -0
- opentrons/drivers/mag_deck/__init__.py +6 -0
- opentrons/drivers/mag_deck/abstract.py +44 -0
- opentrons/drivers/mag_deck/driver.py +208 -0
- opentrons/drivers/mag_deck/simulator.py +63 -0
- opentrons/drivers/rpi_drivers/__init__.py +33 -0
- opentrons/drivers/rpi_drivers/dev_types.py +94 -0
- opentrons/drivers/rpi_drivers/gpio.py +282 -0
- opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
- opentrons/drivers/rpi_drivers/interfaces.py +15 -0
- opentrons/drivers/rpi_drivers/types.py +364 -0
- opentrons/drivers/rpi_drivers/usb.py +102 -0
- opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
- opentrons/drivers/serial_communication.py +151 -0
- opentrons/drivers/smoothie_drivers/__init__.py +4 -0
- opentrons/drivers/smoothie_drivers/connection.py +51 -0
- opentrons/drivers/smoothie_drivers/constants.py +121 -0
- opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
- opentrons/drivers/smoothie_drivers/errors.py +49 -0
- opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
- opentrons/drivers/smoothie_drivers/simulator.py +99 -0
- opentrons/drivers/smoothie_drivers/types.py +16 -0
- opentrons/drivers/temp_deck/__init__.py +10 -0
- opentrons/drivers/temp_deck/abstract.py +54 -0
- opentrons/drivers/temp_deck/driver.py +197 -0
- opentrons/drivers/temp_deck/simulator.py +57 -0
- opentrons/drivers/thermocycler/__init__.py +12 -0
- opentrons/drivers/thermocycler/abstract.py +99 -0
- opentrons/drivers/thermocycler/driver.py +395 -0
- opentrons/drivers/thermocycler/simulator.py +126 -0
- opentrons/drivers/types.py +107 -0
- opentrons/drivers/utils.py +222 -0
- opentrons/execute.py +742 -0
- opentrons/hardware_control/__init__.py +65 -0
- opentrons/hardware_control/__main__.py +77 -0
- opentrons/hardware_control/adapters.py +98 -0
- opentrons/hardware_control/api.py +1347 -0
- opentrons/hardware_control/backends/__init__.py +7 -0
- opentrons/hardware_control/backends/controller.py +400 -0
- opentrons/hardware_control/backends/errors.py +9 -0
- opentrons/hardware_control/backends/estop_state.py +164 -0
- opentrons/hardware_control/backends/flex_protocol.py +497 -0
- opentrons/hardware_control/backends/ot3controller.py +1930 -0
- opentrons/hardware_control/backends/ot3simulator.py +900 -0
- opentrons/hardware_control/backends/ot3utils.py +664 -0
- opentrons/hardware_control/backends/simulator.py +442 -0
- opentrons/hardware_control/backends/status_bar_state.py +240 -0
- opentrons/hardware_control/backends/subsystem_manager.py +431 -0
- opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
- opentrons/hardware_control/backends/types.py +14 -0
- opentrons/hardware_control/constants.py +6 -0
- opentrons/hardware_control/dev_types.py +125 -0
- opentrons/hardware_control/emulation/__init__.py +0 -0
- opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
- opentrons/hardware_control/emulation/app.py +56 -0
- opentrons/hardware_control/emulation/connection_handler.py +38 -0
- opentrons/hardware_control/emulation/heater_shaker.py +150 -0
- opentrons/hardware_control/emulation/magdeck.py +60 -0
- opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
- opentrons/hardware_control/emulation/module_server/client.py +78 -0
- opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
- opentrons/hardware_control/emulation/module_server/models.py +31 -0
- opentrons/hardware_control/emulation/module_server/server.py +110 -0
- opentrons/hardware_control/emulation/parser.py +74 -0
- opentrons/hardware_control/emulation/proxy.py +241 -0
- opentrons/hardware_control/emulation/run_emulator.py +68 -0
- opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
- opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
- opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
- opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
- opentrons/hardware_control/emulation/settings.py +119 -0
- opentrons/hardware_control/emulation/simulations.py +133 -0
- opentrons/hardware_control/emulation/smoothie.py +192 -0
- opentrons/hardware_control/emulation/tempdeck.py +69 -0
- opentrons/hardware_control/emulation/thermocycler.py +128 -0
- opentrons/hardware_control/emulation/types.py +10 -0
- opentrons/hardware_control/emulation/util.py +38 -0
- opentrons/hardware_control/errors.py +43 -0
- opentrons/hardware_control/execution_manager.py +164 -0
- opentrons/hardware_control/instruments/__init__.py +5 -0
- opentrons/hardware_control/instruments/instrument_abc.py +39 -0
- opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
- opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
- opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
- opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
- opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
- opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
- opentrons/hardware_control/module_control.py +332 -0
- opentrons/hardware_control/modules/__init__.py +69 -0
- opentrons/hardware_control/modules/absorbance_reader.py +373 -0
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/flex_stacker.py +948 -0
- opentrons/hardware_control/modules/heater_shaker.py +426 -0
- opentrons/hardware_control/modules/lid_temp_status.py +35 -0
- opentrons/hardware_control/modules/magdeck.py +233 -0
- opentrons/hardware_control/modules/mod_abc.py +245 -0
- opentrons/hardware_control/modules/module_calibration.py +93 -0
- opentrons/hardware_control/modules/plate_temp_status.py +61 -0
- opentrons/hardware_control/modules/tempdeck.py +299 -0
- opentrons/hardware_control/modules/thermocycler.py +731 -0
- opentrons/hardware_control/modules/types.py +417 -0
- opentrons/hardware_control/modules/update.py +255 -0
- opentrons/hardware_control/modules/utils.py +73 -0
- opentrons/hardware_control/motion_utilities.py +318 -0
- opentrons/hardware_control/nozzle_manager.py +422 -0
- opentrons/hardware_control/ot3_calibration.py +1171 -0
- opentrons/hardware_control/ot3api.py +3227 -0
- opentrons/hardware_control/pause_manager.py +31 -0
- opentrons/hardware_control/poller.py +112 -0
- opentrons/hardware_control/protocols/__init__.py +106 -0
- opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
- opentrons/hardware_control/protocols/calibratable.py +45 -0
- opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
- opentrons/hardware_control/protocols/configurable.py +48 -0
- opentrons/hardware_control/protocols/event_sourcer.py +18 -0
- opentrons/hardware_control/protocols/execution_controllable.py +33 -0
- opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
- opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
- opentrons/hardware_control/protocols/gripper_controller.py +55 -0
- opentrons/hardware_control/protocols/hardware_manager.py +51 -0
- opentrons/hardware_control/protocols/identifiable.py +16 -0
- opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
- opentrons/hardware_control/protocols/liquid_handler.py +266 -0
- opentrons/hardware_control/protocols/module_provider.py +16 -0
- opentrons/hardware_control/protocols/motion_controller.py +243 -0
- opentrons/hardware_control/protocols/position_estimator.py +45 -0
- opentrons/hardware_control/protocols/simulatable.py +10 -0
- opentrons/hardware_control/protocols/stoppable.py +9 -0
- opentrons/hardware_control/protocols/types.py +27 -0
- opentrons/hardware_control/robot_calibration.py +224 -0
- opentrons/hardware_control/scripts/README.md +28 -0
- opentrons/hardware_control/scripts/__init__.py +1 -0
- opentrons/hardware_control/scripts/gripper_control.py +208 -0
- opentrons/hardware_control/scripts/ot3gripper +7 -0
- opentrons/hardware_control/scripts/ot3repl +7 -0
- opentrons/hardware_control/scripts/repl.py +187 -0
- opentrons/hardware_control/scripts/tc_control.py +97 -0
- opentrons/hardware_control/simulator_setup.py +260 -0
- opentrons/hardware_control/thread_manager.py +431 -0
- opentrons/hardware_control/threaded_async_lock.py +97 -0
- opentrons/hardware_control/types.py +792 -0
- opentrons/hardware_control/util.py +234 -0
- opentrons/legacy_broker.py +53 -0
- opentrons/legacy_commands/__init__.py +1 -0
- opentrons/legacy_commands/commands.py +483 -0
- opentrons/legacy_commands/helpers.py +153 -0
- opentrons/legacy_commands/module_commands.py +215 -0
- opentrons/legacy_commands/protocol_commands.py +54 -0
- opentrons/legacy_commands/publisher.py +155 -0
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +1115 -0
- opentrons/motion_planning/__init__.py +32 -0
- opentrons/motion_planning/adjacent_slots_getters.py +168 -0
- opentrons/motion_planning/deck_conflict.py +396 -0
- opentrons/motion_planning/errors.py +35 -0
- opentrons/motion_planning/types.py +42 -0
- opentrons/motion_planning/waypoints.py +218 -0
- opentrons/ordered_set.py +138 -0
- opentrons/protocol_api/__init__.py +105 -0
- opentrons/protocol_api/_liquid.py +157 -0
- opentrons/protocol_api/_liquid_properties.py +814 -0
- opentrons/protocol_api/_nozzle_layout.py +31 -0
- opentrons/protocol_api/_parameter_context.py +300 -0
- opentrons/protocol_api/_parameters.py +31 -0
- opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
- opentrons/protocol_api/_types.py +43 -0
- opentrons/protocol_api/config.py +23 -0
- opentrons/protocol_api/core/__init__.py +23 -0
- opentrons/protocol_api/core/common.py +33 -0
- opentrons/protocol_api/core/core_map.py +74 -0
- opentrons/protocol_api/core/engine/__init__.py +22 -0
- opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
- opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
- opentrons/protocol_api/core/engine/exceptions.py +19 -0
- opentrons/protocol_api/core/engine/instrument.py +2391 -0
- opentrons/protocol_api/core/engine/labware.py +238 -0
- opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
- opentrons/protocol_api/core/engine/module_core.py +1025 -0
- opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
- opentrons/protocol_api/core/engine/point_calculations.py +64 -0
- opentrons/protocol_api/core/engine/protocol.py +1153 -0
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/stringify.py +74 -0
- opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
- opentrons/protocol_api/core/engine/well.py +241 -0
- opentrons/protocol_api/core/instrument.py +459 -0
- opentrons/protocol_api/core/labware.py +151 -0
- opentrons/protocol_api/core/legacy/__init__.py +11 -0
- opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
- opentrons/protocol_api/core/legacy/deck.py +369 -0
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
- opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
- opentrons/protocol_api/core/legacy/load_info.py +67 -0
- opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
- opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
- opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
- opentrons/protocol_api/core/module.py +484 -0
- opentrons/protocol_api/core/protocol.py +311 -0
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/core/well.py +116 -0
- opentrons/protocol_api/core/well_grid.py +45 -0
- opentrons/protocol_api/create_protocol_context.py +177 -0
- opentrons/protocol_api/deck.py +223 -0
- opentrons/protocol_api/disposal_locations.py +244 -0
- opentrons/protocol_api/instrument_context.py +3212 -0
- opentrons/protocol_api/labware.py +1579 -0
- opentrons/protocol_api/module_contexts.py +1425 -0
- opentrons/protocol_api/module_validation_and_errors.py +61 -0
- opentrons/protocol_api/protocol_context.py +1688 -0
- opentrons/protocol_api/robot_context.py +303 -0
- opentrons/protocol_api/validation.py +761 -0
- opentrons/protocol_engine/__init__.py +155 -0
- opentrons/protocol_engine/actions/__init__.py +65 -0
- opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
- opentrons/protocol_engine/actions/action_handler.py +13 -0
- opentrons/protocol_engine/actions/actions.py +302 -0
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/__init__.py +5 -0
- opentrons/protocol_engine/clients/sync_client.py +174 -0
- opentrons/protocol_engine/clients/transports.py +197 -0
- opentrons/protocol_engine/commands/__init__.py +757 -0
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
- opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
- opentrons/protocol_engine/commands/aspirate.py +244 -0
- opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
- opentrons/protocol_engine/commands/blow_out.py +146 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
- opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
- opentrons/protocol_engine/commands/command.py +308 -0
- opentrons/protocol_engine/commands/command_unions.py +974 -0
- opentrons/protocol_engine/commands/comment.py +57 -0
- opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
- opentrons/protocol_engine/commands/custom.py +67 -0
- opentrons/protocol_engine/commands/dispense.py +194 -0
- opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +232 -0
- opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
- opentrons/protocol_engine/commands/hash_command_params.py +38 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
- opentrons/protocol_engine/commands/home.py +100 -0
- opentrons/protocol_engine/commands/identify_module.py +86 -0
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +464 -0
- opentrons/protocol_engine/commands/load_labware.py +210 -0
- opentrons/protocol_engine/commands/load_lid.py +154 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
- opentrons/protocol_engine/commands/load_liquid.py +95 -0
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +223 -0
- opentrons/protocol_engine/commands/load_pipette.py +167 -0
- opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
- opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
- opentrons/protocol_engine/commands/move_labware.py +546 -0
- opentrons/protocol_engine/commands/move_relative.py +102 -0
- opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
- opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
- opentrons/protocol_engine/commands/move_to_well.py +119 -0
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
- opentrons/protocol_engine/commands/pipetting_common.py +443 -0
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
- opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
- opentrons/protocol_engine/commands/reload_labware.py +90 -0
- opentrons/protocol_engine/commands/retract_axis.py +75 -0
- opentrons/protocol_engine/commands/robot/__init__.py +70 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/save_position.py +109 -0
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
- opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
- opentrons/protocol_engine/commands/set_status_bar.py +89 -0
- opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
- opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
- opentrons/protocol_engine/commands/touch_tip.py +189 -0
- opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
- opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
- opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
- opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
- opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
- opentrons/protocol_engine/create_protocol_engine.py +193 -0
- opentrons/protocol_engine/engine_support.py +28 -0
- opentrons/protocol_engine/error_recovery_policy.py +81 -0
- opentrons/protocol_engine/errors/__init__.py +191 -0
- opentrons/protocol_engine/errors/error_occurrence.py +182 -0
- opentrons/protocol_engine/errors/exceptions.py +1308 -0
- opentrons/protocol_engine/execution/__init__.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +216 -0
- opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
- opentrons/protocol_engine/execution/door_watcher.py +119 -0
- opentrons/protocol_engine/execution/equipment.py +819 -0
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +686 -0
- opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
- opentrons/protocol_engine/execution/labware_movement.py +297 -0
- opentrons/protocol_engine/execution/movement.py +349 -0
- opentrons/protocol_engine/execution/pipetting.py +607 -0
- opentrons/protocol_engine/execution/queue_worker.py +86 -0
- opentrons/protocol_engine/execution/rail_lights.py +25 -0
- opentrons/protocol_engine/execution/run_control.py +33 -0
- opentrons/protocol_engine/execution/status_bar.py +34 -0
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
- opentrons/protocol_engine/execution/tip_handler.py +550 -0
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/notes/__init__.py +17 -0
- opentrons/protocol_engine/notes/notes.py +59 -0
- opentrons/protocol_engine/plugins.py +104 -0
- opentrons/protocol_engine/protocol_engine.py +683 -0
- opentrons/protocol_engine/resources/__init__.py +26 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +58 -0
- opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
- opentrons/protocol_engine/resources/labware_validation.py +73 -0
- opentrons/protocol_engine/resources/model_utils.py +32 -0
- opentrons/protocol_engine/resources/module_data_provider.py +44 -0
- opentrons/protocol_engine/resources/ot3_validation.py +21 -0
- opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
- opentrons/protocol_engine/slot_standardization.py +128 -0
- opentrons/protocol_engine/state/__init__.py +1 -0
- opentrons/protocol_engine/state/_abstract_store.py +27 -0
- opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
- opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
- opentrons/protocol_engine/state/_move_types.py +83 -0
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +699 -0
- opentrons/protocol_engine/state/command_history.py +309 -0
- opentrons/protocol_engine/state/commands.py +1158 -0
- opentrons/protocol_engine/state/config.py +39 -0
- opentrons/protocol_engine/state/files.py +57 -0
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/geometry.py +2359 -0
- opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
- opentrons/protocol_engine/state/labware.py +1459 -0
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +73 -0
- opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
- opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
- opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
- opentrons/protocol_engine/state/modules.py +1500 -0
- opentrons/protocol_engine/state/motion.py +373 -0
- opentrons/protocol_engine/state/pipettes.py +905 -0
- opentrons/protocol_engine/state/state.py +421 -0
- opentrons/protocol_engine/state/state_summary.py +36 -0
- opentrons/protocol_engine/state/tips.py +420 -0
- opentrons/protocol_engine/state/update_types.py +904 -0
- opentrons/protocol_engine/state/wells.py +290 -0
- opentrons/protocol_engine/types/__init__.py +308 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +81 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +131 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +303 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/__init__.py +37 -0
- opentrons/protocol_reader/extract_labware_definitions.py +66 -0
- opentrons/protocol_reader/file_format_validator.py +152 -0
- opentrons/protocol_reader/file_hasher.py +27 -0
- opentrons/protocol_reader/file_identifier.py +284 -0
- opentrons/protocol_reader/file_reader_writer.py +90 -0
- opentrons/protocol_reader/input_file.py +16 -0
- opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
- opentrons/protocol_reader/protocol_reader.py +188 -0
- opentrons/protocol_reader/protocol_source.py +124 -0
- opentrons/protocol_reader/role_analyzer.py +86 -0
- opentrons/protocol_runner/__init__.py +26 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
- opentrons/protocol_runner/json_file_reader.py +55 -0
- opentrons/protocol_runner/json_translator.py +314 -0
- opentrons/protocol_runner/legacy_command_mapper.py +848 -0
- opentrons/protocol_runner/legacy_context_plugin.py +116 -0
- opentrons/protocol_runner/protocol_runner.py +530 -0
- opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
- opentrons/protocol_runner/run_orchestrator.py +496 -0
- opentrons/protocol_runner/task_queue.py +95 -0
- opentrons/protocols/__init__.py +6 -0
- opentrons/protocols/advanced_control/__init__.py +0 -0
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +60 -0
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +180 -0
- opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
- opentrons/protocols/api_support/__init__.py +0 -0
- opentrons/protocols/api_support/constants.py +8 -0
- opentrons/protocols/api_support/deck_type.py +110 -0
- opentrons/protocols/api_support/definitions.py +18 -0
- opentrons/protocols/api_support/instrument.py +151 -0
- opentrons/protocols/api_support/labware_like.py +233 -0
- opentrons/protocols/api_support/tip_tracker.py +175 -0
- opentrons/protocols/api_support/types.py +32 -0
- opentrons/protocols/api_support/util.py +403 -0
- opentrons/protocols/bundle.py +89 -0
- opentrons/protocols/duration/__init__.py +4 -0
- opentrons/protocols/duration/errors.py +5 -0
- opentrons/protocols/duration/estimator.py +628 -0
- opentrons/protocols/execution/__init__.py +0 -0
- opentrons/protocols/execution/dev_types.py +181 -0
- opentrons/protocols/execution/errors.py +40 -0
- opentrons/protocols/execution/execute.py +84 -0
- opentrons/protocols/execution/execute_json_v3.py +275 -0
- opentrons/protocols/execution/execute_json_v4.py +359 -0
- opentrons/protocols/execution/execute_json_v5.py +28 -0
- opentrons/protocols/execution/execute_python.py +169 -0
- opentrons/protocols/execution/json_dispatchers.py +87 -0
- opentrons/protocols/execution/types.py +7 -0
- opentrons/protocols/geometry/__init__.py +0 -0
- opentrons/protocols/geometry/planning.py +297 -0
- opentrons/protocols/labware.py +312 -0
- opentrons/protocols/models/__init__.py +0 -0
- opentrons/protocols/models/json_protocol.py +679 -0
- opentrons/protocols/parameters/__init__.py +0 -0
- opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
- opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
- opentrons/protocols/parameters/exceptions.py +34 -0
- opentrons/protocols/parameters/parameter_definition.py +272 -0
- opentrons/protocols/parameters/types.py +17 -0
- opentrons/protocols/parameters/validation.py +267 -0
- opentrons/protocols/parse.py +671 -0
- opentrons/protocols/types.py +159 -0
- opentrons/py.typed +0 -0
- opentrons/resources/scripts/lpc21isp +0 -0
- opentrons/resources/smoothie-edge-8414642.hex +23010 -0
- opentrons/simulate.py +1065 -0
- opentrons/system/__init__.py +6 -0
- opentrons/system/camera.py +51 -0
- opentrons/system/log_control.py +59 -0
- opentrons/system/nmcli.py +856 -0
- opentrons/system/resin.py +24 -0
- opentrons/system/smoothie_update.py +15 -0
- opentrons/system/wifi.py +204 -0
- opentrons/tools/__init__.py +0 -0
- opentrons/tools/args_handler.py +22 -0
- opentrons/tools/write_pipette_memory.py +157 -0
- opentrons/types.py +618 -0
- opentrons/util/__init__.py +1 -0
- opentrons/util/async_helpers.py +166 -0
- opentrons/util/broker.py +84 -0
- opentrons/util/change_notifier.py +47 -0
- opentrons/util/entrypoint_util.py +278 -0
- opentrons/util/get_union_elements.py +26 -0
- opentrons/util/helpers.py +6 -0
- opentrons/util/linal.py +178 -0
- opentrons/util/logging_config.py +265 -0
- opentrons/util/logging_queue_handler.py +61 -0
- opentrons/util/performance_helpers.py +157 -0
- opentrons-8.6.0a1.dist-info/METADATA +37 -0
- opentrons-8.6.0a1.dist-info/RECORD +600 -0
- opentrons-8.6.0a1.dist-info/WHEEL +4 -0
- opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
- opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Coordinate subsystem detection and updates.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from contextlib import contextmanager, ExitStack
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
import logging
|
|
9
|
+
from typing import (
|
|
10
|
+
Optional,
|
|
11
|
+
Set,
|
|
12
|
+
Dict,
|
|
13
|
+
Iterator,
|
|
14
|
+
Callable,
|
|
15
|
+
AsyncIterator,
|
|
16
|
+
Union,
|
|
17
|
+
List,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from opentrons_hardware.hardware_control import network, tools
|
|
21
|
+
from opentrons_hardware.drivers import can_bus, binary_usb
|
|
22
|
+
from opentrons_hardware.firmware_bindings.constants import (
|
|
23
|
+
NodeId,
|
|
24
|
+
USBTarget,
|
|
25
|
+
FirmwareTarget,
|
|
26
|
+
ToolType,
|
|
27
|
+
)
|
|
28
|
+
from opentrons_hardware.firmware_update import FirmwareUpdate
|
|
29
|
+
|
|
30
|
+
from ..types import SubSystem, SubSystemState, UpdateStatus, UpdateState
|
|
31
|
+
from .ot3utils import subsystem_to_target, target_to_subsystem
|
|
32
|
+
from .errors import SubsystemUpdating
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
log = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class FirmwareUpdateRequirements:
|
|
40
|
+
target_version: int
|
|
41
|
+
filepath: str
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class SubsystemManager:
|
|
45
|
+
"""Control tracking and updating attached subsystems to the machine.
|
|
46
|
+
|
|
47
|
+
Call start() before trying to run the system (or build with build()).
|
|
48
|
+
|
|
49
|
+
This object has an always-up-to-date cache of attached subsystems driven by
|
|
50
|
+
asynchronous notifications from hardware and explicitly updatable with refresh().
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
_can_messenger: can_bus.CanMessenger
|
|
54
|
+
_usb_messenger: Optional[binary_usb.BinaryMessenger]
|
|
55
|
+
_tool_detector: tools.detector.ToolDetector
|
|
56
|
+
_network_info: network.NetworkInfo
|
|
57
|
+
_tool_detection_task: "Optional[asyncio.Task[None]]"
|
|
58
|
+
_expected_core_targets: Set[FirmwareTarget]
|
|
59
|
+
_present_tools: tools.types.ToolSummary
|
|
60
|
+
_tool_task_condition: asyncio.Condition
|
|
61
|
+
_tool_task_state: Union[bool, BaseException]
|
|
62
|
+
_updates_required: Dict[FirmwareTarget, FirmwareUpdateRequirements]
|
|
63
|
+
_updates_ongoing: Dict[SubSystem, UpdateStatus]
|
|
64
|
+
_update_bag: FirmwareUpdate
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
can_messenger: can_bus.CanMessenger,
|
|
69
|
+
usb_messenger: Optional[binary_usb.BinaryMessenger],
|
|
70
|
+
tool_detector: tools.detector.ToolDetector,
|
|
71
|
+
network_info: network.NetworkInfo,
|
|
72
|
+
update_bag: FirmwareUpdate,
|
|
73
|
+
) -> None:
|
|
74
|
+
self._can_messenger = can_messenger
|
|
75
|
+
self._usb_messenger = usb_messenger
|
|
76
|
+
self._tool_detector = tool_detector
|
|
77
|
+
self._network_info = network_info
|
|
78
|
+
self._tool_detection_task = None
|
|
79
|
+
self._expected_core_targets: Set[FirmwareTarget] = {
|
|
80
|
+
NodeId.gantry_x,
|
|
81
|
+
NodeId.gantry_y,
|
|
82
|
+
NodeId.head,
|
|
83
|
+
}
|
|
84
|
+
self._tool_task_condition = asyncio.Condition()
|
|
85
|
+
self._tool_task_state = False
|
|
86
|
+
self._updates_required = {}
|
|
87
|
+
self._updates_ongoing = {}
|
|
88
|
+
self._update_bag = update_bag
|
|
89
|
+
if self._usb_messenger:
|
|
90
|
+
self._expected_core_targets.add(USBTarget.rear_panel)
|
|
91
|
+
self._present_tools = tools.types.ToolSummary(
|
|
92
|
+
left=None, right=None, gripper=None
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def ok(self) -> bool:
|
|
97
|
+
"""True if required subsystems are present and all present subsystems are ok."""
|
|
98
|
+
if not self._expected_core_targets.issubset(self.targets):
|
|
99
|
+
return False
|
|
100
|
+
return all(state.ok for state in self.subsystems.values())
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def device_info(self) -> Dict[SubSystem, network.DeviceInfoCache]:
|
|
104
|
+
return {
|
|
105
|
+
target_to_subsystem(target): info
|
|
106
|
+
for target, info in self._network_info.device_info.items()
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def targets(self) -> Set[FirmwareTarget]:
|
|
111
|
+
return self._network_info.targets
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def tools(self) -> tools.types.ToolSummary:
|
|
115
|
+
return self._present_tools
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def subsystems(self) -> Dict[SubSystem, SubSystemState]:
|
|
119
|
+
def _state_or(maybe_status: Optional[UpdateStatus]) -> Optional[UpdateState]:
|
|
120
|
+
if maybe_status is not None:
|
|
121
|
+
return maybe_status.state
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
def _next_version(target: FirmwareTarget, current: int) -> int:
|
|
125
|
+
try:
|
|
126
|
+
return self._updates_required[target].target_version
|
|
127
|
+
except KeyError:
|
|
128
|
+
return current
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
target_to_subsystem(target): SubSystemState(
|
|
132
|
+
ok=info.ok,
|
|
133
|
+
current_fw_version=info.version,
|
|
134
|
+
next_fw_version=_next_version(target, info.version),
|
|
135
|
+
fw_update_needed=target in self._updates_required,
|
|
136
|
+
current_fw_sha=info.shortsha,
|
|
137
|
+
pcba_revision=str(info.revision),
|
|
138
|
+
update_state=_state_or(
|
|
139
|
+
self._updates_ongoing.get(target_to_subsystem(target))
|
|
140
|
+
),
|
|
141
|
+
)
|
|
142
|
+
for target, info in self._network_info.device_info.items()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def update_required(self) -> bool:
|
|
147
|
+
return bool(self._updates_required)
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def subsystems_to_update(self) -> List[SubSystem]:
|
|
151
|
+
return [target_to_subsystem(t) for t in self._updates_required.keys()]
|
|
152
|
+
|
|
153
|
+
async def start(self) -> None:
|
|
154
|
+
await self._probe_network_and_cache_fw_updates(
|
|
155
|
+
self._expected_core_targets, True
|
|
156
|
+
)
|
|
157
|
+
self._tool_detection_task = asyncio.create_task(
|
|
158
|
+
self._tool_detection_task_main()
|
|
159
|
+
)
|
|
160
|
+
await self.refresh()
|
|
161
|
+
log.info(f"Subsystem manager started with devices {self.device_info}")
|
|
162
|
+
|
|
163
|
+
async def refresh(self) -> None:
|
|
164
|
+
"""Explicitly refresh the state of the system.
|
|
165
|
+
|
|
166
|
+
This will not return until the information is up to date.
|
|
167
|
+
"""
|
|
168
|
+
async with self._tool_task_condition:
|
|
169
|
+
if isinstance(self._tool_task_state, Exception):
|
|
170
|
+
raise self._tool_task_state
|
|
171
|
+
await self._tool_detector.check_once()
|
|
172
|
+
await self._tool_task_condition.wait()
|
|
173
|
+
if isinstance(self._tool_task_state, Exception):
|
|
174
|
+
raise self._tool_task_state
|
|
175
|
+
self._tool_task_state = False
|
|
176
|
+
|
|
177
|
+
async def is_new(self) -> bool:
|
|
178
|
+
"""Returns True if there is data unread since the last call to is_new."""
|
|
179
|
+
async with self._tool_task_condition:
|
|
180
|
+
state = self._tool_task_state
|
|
181
|
+
if isinstance(state, Exception):
|
|
182
|
+
raise state
|
|
183
|
+
return self._tool_task_state is True
|
|
184
|
+
|
|
185
|
+
async def _check_devices_after_update(
|
|
186
|
+
self, devices: Set[SubSystem], timeout_sec: float = 10.0
|
|
187
|
+
) -> None:
|
|
188
|
+
try:
|
|
189
|
+
await asyncio.wait_for(
|
|
190
|
+
self._do_check_devices_after_update(devices), timeout=timeout_sec
|
|
191
|
+
)
|
|
192
|
+
except asyncio.TimeoutError:
|
|
193
|
+
raise RuntimeError("Device failed to come back after firmware update")
|
|
194
|
+
|
|
195
|
+
async def _do_check_devices_after_update(self, devices: Set[SubSystem]) -> None:
|
|
196
|
+
# refresh the device_info cache and reset internal states
|
|
197
|
+
log.info(f"Checking {devices} after update")
|
|
198
|
+
attempts = 1
|
|
199
|
+
while True:
|
|
200
|
+
await self._probe_network_and_cache_fw_updates(
|
|
201
|
+
{subsystem_to_target(subsystem) for subsystem in devices},
|
|
202
|
+
False,
|
|
203
|
+
)
|
|
204
|
+
await asyncio.sleep(0.1)
|
|
205
|
+
# make sure the update actually succeeded
|
|
206
|
+
device_info = self.device_info
|
|
207
|
+
if devices.issubset(device_info.keys()) and all(
|
|
208
|
+
info.ok for subsys, info in device_info.items() if subsys in devices
|
|
209
|
+
):
|
|
210
|
+
log.info(f"Found all devices after {attempts} tries")
|
|
211
|
+
return
|
|
212
|
+
log.info(f"Failed to find all of {devices}: found {device_info}")
|
|
213
|
+
attempts += 1
|
|
214
|
+
|
|
215
|
+
def get_update_progress(self) -> Dict[SubSystem, UpdateStatus]:
|
|
216
|
+
"""Returns a set of UpdateStatus of the updates."""
|
|
217
|
+
return {k: v for k, v in self._updates_ongoing.items()}
|
|
218
|
+
|
|
219
|
+
async def update_firmware(
|
|
220
|
+
self,
|
|
221
|
+
subsystems: Optional[Set[SubSystem]] = None,
|
|
222
|
+
force: bool = False,
|
|
223
|
+
) -> AsyncIterator[UpdateStatus]:
|
|
224
|
+
"""Updates the firmware on the OT3."""
|
|
225
|
+
# Check that there arent updates already running for given nodes
|
|
226
|
+
current_subsystems = self.subsystems
|
|
227
|
+
|
|
228
|
+
subsystems_to_check = subsystems or set(current_subsystems)
|
|
229
|
+
subsystems_updating = set(self._updates_ongoing)
|
|
230
|
+
subsystems_to_update = subsystems_to_check - subsystems_updating
|
|
231
|
+
if not subsystems_to_update:
|
|
232
|
+
if subsystems:
|
|
233
|
+
raise SubsystemUpdating(f"Ongoing update for {subsystems}")
|
|
234
|
+
else:
|
|
235
|
+
log.info("No viable subsystem to update.")
|
|
236
|
+
return
|
|
237
|
+
|
|
238
|
+
# Check if devices need an update, only checks nodes if given
|
|
239
|
+
firmware_updates = self._get_required_fw_updates(
|
|
240
|
+
{subsystem_to_target(subsystem) for subsystem in subsystems_to_update},
|
|
241
|
+
force=force,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
subsystems_updatable = set(
|
|
245
|
+
target_to_subsystem(target) for target in firmware_updates.keys()
|
|
246
|
+
)
|
|
247
|
+
updating_subsystems = subsystems_to_update.intersection(subsystems_updatable)
|
|
248
|
+
|
|
249
|
+
if not updating_subsystems:
|
|
250
|
+
log.info("No firmware updates required for specified subsystems.")
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
log.info(f"Updating firmware on {updating_subsystems}")
|
|
254
|
+
|
|
255
|
+
update_details = {
|
|
256
|
+
target: firmware_updates[target].filepath
|
|
257
|
+
for target in (
|
|
258
|
+
subsystem_to_target(subsystem) for subsystem in updating_subsystems
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
with ExitStack() as update_tracker_stack:
|
|
263
|
+
status_callbacks: Dict[SubSystem, Callable[[UpdateStatus], None]] = {
|
|
264
|
+
subsystem: update_tracker_stack.enter_context(
|
|
265
|
+
self._update_ongoing_for(subsystem)
|
|
266
|
+
)
|
|
267
|
+
for subsystem in updating_subsystems
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
updater = self._update_bag.update_runner(
|
|
271
|
+
can_messenger=self._can_messenger,
|
|
272
|
+
usb_messenger=self._usb_messenger,
|
|
273
|
+
update_details=update_details,
|
|
274
|
+
retry_count=3,
|
|
275
|
+
timeout_seconds=5,
|
|
276
|
+
erase=True,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# start the updates and yield progress to caller
|
|
280
|
+
async for target, status_element in updater.run_updates():
|
|
281
|
+
subsystem = target_to_subsystem(target)
|
|
282
|
+
upstream_status = UpdateStatus(
|
|
283
|
+
subsystem=subsystem,
|
|
284
|
+
state=UpdateState[status_element[0].name],
|
|
285
|
+
progress=int(status_element[1] * 100),
|
|
286
|
+
)
|
|
287
|
+
status_callbacks[subsystem](upstream_status)
|
|
288
|
+
yield upstream_status
|
|
289
|
+
|
|
290
|
+
await self._check_devices_after_update(updating_subsystems)
|
|
291
|
+
|
|
292
|
+
def _get_required_fw_updates(
|
|
293
|
+
self, targets: Set[FirmwareTarget], force: bool
|
|
294
|
+
) -> Dict[FirmwareTarget, FirmwareUpdateRequirements]:
|
|
295
|
+
to_check = (targets or self.targets).intersection(self.targets)
|
|
296
|
+
updates_required: Dict[FirmwareTarget, FirmwareUpdateRequirements] = {}
|
|
297
|
+
bad_targets = {
|
|
298
|
+
target
|
|
299
|
+
for target in to_check
|
|
300
|
+
if not self.device_info[target_to_subsystem(target)].ok
|
|
301
|
+
}
|
|
302
|
+
good_targets = to_check - bad_targets
|
|
303
|
+
device_info_by_target = {
|
|
304
|
+
subsystem_to_target(subsystem): info
|
|
305
|
+
for subsystem, info in self.device_info.items()
|
|
306
|
+
}
|
|
307
|
+
good_updates = self._update_bag.update_checker(
|
|
308
|
+
device_info_by_target, good_targets, force
|
|
309
|
+
)
|
|
310
|
+
bad_updates = self._update_bag.update_checker(
|
|
311
|
+
device_info_by_target, bad_targets, True
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
for target, (next_version, filepath) in good_updates.items():
|
|
315
|
+
updates_required[target] = FirmwareUpdateRequirements(
|
|
316
|
+
target_version=next_version,
|
|
317
|
+
filepath=filepath,
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
for target, (next_version, filepath) in bad_updates.items():
|
|
321
|
+
updates_required[target] = FirmwareUpdateRequirements(
|
|
322
|
+
target_version=next_version,
|
|
323
|
+
filepath=filepath,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
return updates_required
|
|
327
|
+
|
|
328
|
+
def _update_fw_update_requirements(self) -> None:
|
|
329
|
+
"""Update the local cache of extra information required for subsystem state."""
|
|
330
|
+
# this runs in a separate task from where it will be queried, so we'll build a replacement
|
|
331
|
+
# for the _updates_required dict locally and then swap it over async-atomically
|
|
332
|
+
|
|
333
|
+
self._updates_required = self._get_required_fw_updates(set(), False)
|
|
334
|
+
|
|
335
|
+
async def _probe_network_and_cache_fw_updates(
|
|
336
|
+
self, targets: Set[FirmwareTarget], broadcast: bool = True
|
|
337
|
+
) -> None:
|
|
338
|
+
checked_targets = {
|
|
339
|
+
target
|
|
340
|
+
for target in targets
|
|
341
|
+
if target_to_subsystem(target) not in self._updates_ongoing
|
|
342
|
+
}
|
|
343
|
+
if broadcast:
|
|
344
|
+
await self._network_info.probe(checked_targets)
|
|
345
|
+
else:
|
|
346
|
+
await self._network_info.probe_specific(checked_targets)
|
|
347
|
+
self._update_fw_update_requirements()
|
|
348
|
+
|
|
349
|
+
@contextmanager
|
|
350
|
+
def _update_ongoing_for(
|
|
351
|
+
self, subsystem: SubSystem
|
|
352
|
+
) -> Iterator[Callable[[UpdateStatus], None]]:
|
|
353
|
+
if subsystem in self._updates_ongoing:
|
|
354
|
+
raise RuntimeError(f"Update already ongoing for {subsystem}")
|
|
355
|
+
|
|
356
|
+
def update_state(status: UpdateStatus) -> None:
|
|
357
|
+
self._updates_ongoing[subsystem] = status
|
|
358
|
+
|
|
359
|
+
self._updates_ongoing[subsystem] = UpdateStatus(
|
|
360
|
+
subsystem=subsystem, state=UpdateState.queued, progress=0
|
|
361
|
+
)
|
|
362
|
+
try:
|
|
363
|
+
yield update_state
|
|
364
|
+
except Exception:
|
|
365
|
+
log.exception(f"Update failed for subsystem {subsystem}")
|
|
366
|
+
raise
|
|
367
|
+
finally:
|
|
368
|
+
self._updates_ongoing.pop(subsystem)
|
|
369
|
+
|
|
370
|
+
async def _tool_detection_task_main(self) -> None:
|
|
371
|
+
try:
|
|
372
|
+
await self._tool_detection_task_protected()
|
|
373
|
+
except BaseException as e:
|
|
374
|
+
log.exception("Tool reader task failed")
|
|
375
|
+
async with self._tool_task_condition:
|
|
376
|
+
self._tool_task_state = e
|
|
377
|
+
self._tool_task_condition.notify_all()
|
|
378
|
+
raise
|
|
379
|
+
|
|
380
|
+
async def _tool_detection_task_protected(self) -> None:
|
|
381
|
+
"""Main function of an asyncio task that responds to async notifications that tool states have changed."""
|
|
382
|
+
async with self._tool_task_condition:
|
|
383
|
+
self._tool_task_state = True
|
|
384
|
+
self._tool_task_condition.notify_all()
|
|
385
|
+
async for update in self._tool_detector.detect():
|
|
386
|
+
# We got a notification from the head that something changed. Let's check whether the currently
|
|
387
|
+
# attached tools are okay by getting their device info
|
|
388
|
+
tool_nodes: Set[NodeId] = set()
|
|
389
|
+
if update.left != ToolType.nothing_attached:
|
|
390
|
+
tool_nodes.add(NodeId.pipette_left)
|
|
391
|
+
if update.right != ToolType.nothing_attached:
|
|
392
|
+
tool_nodes.add(NodeId.pipette_right)
|
|
393
|
+
if update.gripper != ToolType.nothing_attached:
|
|
394
|
+
tool_nodes.add(NodeId.gripper)
|
|
395
|
+
base_can_nodes: List[NodeId] = [
|
|
396
|
+
NodeId.pipette_left,
|
|
397
|
+
NodeId.pipette_right,
|
|
398
|
+
NodeId.gripper,
|
|
399
|
+
]
|
|
400
|
+
base_nodes: Set[FirmwareTarget] = {n for n in base_can_nodes}
|
|
401
|
+
try:
|
|
402
|
+
self._network_info.mark_absent(base_nodes - tool_nodes)
|
|
403
|
+
await self._probe_network_and_cache_fw_updates(
|
|
404
|
+
self._expected_core_targets.union(tool_nodes), False
|
|
405
|
+
)
|
|
406
|
+
except TimeoutError:
|
|
407
|
+
log.exception("Problem in internal network probe")
|
|
408
|
+
continue
|
|
409
|
+
|
|
410
|
+
# Once we know which are okay, we can ask only those for their subsystems
|
|
411
|
+
to_resolve = tools.types.ToolDetectionResult(
|
|
412
|
+
left=self._tool_if_ok(update.left, NodeId.pipette_left),
|
|
413
|
+
right=self._tool_if_ok(update.right, NodeId.pipette_right),
|
|
414
|
+
gripper=self._tool_if_ok(update.gripper, NodeId.gripper),
|
|
415
|
+
)
|
|
416
|
+
self._present_tools = await self._tool_detector.resolve(to_resolve, 10.0)
|
|
417
|
+
log.info(f"Present tools are now {self._present_tools}")
|
|
418
|
+
await network.log_motor_usage_data(self._can_messenger)
|
|
419
|
+
async with self._tool_task_condition:
|
|
420
|
+
self._tool_task_state = True
|
|
421
|
+
self._tool_task_condition.notify_all()
|
|
422
|
+
|
|
423
|
+
def _tool_if_ok(self, tool: ToolType, node: NodeId) -> ToolType:
|
|
424
|
+
if tool is ToolType.nothing_attached:
|
|
425
|
+
return tool
|
|
426
|
+
device_info = self._network_info.device_info
|
|
427
|
+
if node not in device_info:
|
|
428
|
+
return ToolType.nothing_attached
|
|
429
|
+
if not device_info[node].ok:
|
|
430
|
+
return ToolType.nothing_attached
|
|
431
|
+
return tool
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from functools import partial
|
|
3
|
+
from typing import cast, Callable, Optional, List, Set
|
|
4
|
+
from typing_extensions import TypedDict, Literal
|
|
5
|
+
|
|
6
|
+
from opentrons.hardware_control.types import TipStateType, OT3Mount, InstrumentProbeType
|
|
7
|
+
|
|
8
|
+
from opentrons_hardware.drivers.can_bus import CanMessenger
|
|
9
|
+
from opentrons_hardware.firmware_bindings.constants import NodeId
|
|
10
|
+
from opentrons_hardware.hardware_control.tip_presence import (
|
|
11
|
+
TipDetector,
|
|
12
|
+
types as tip_types,
|
|
13
|
+
)
|
|
14
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
15
|
+
TipDetectorNotFound,
|
|
16
|
+
UnmatchedTipPresenceStates,
|
|
17
|
+
GeneralError,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .ot3utils import sensor_id_for_instrument
|
|
21
|
+
|
|
22
|
+
log = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
TipListener = Callable[[OT3Mount, bool], None]
|
|
25
|
+
PipetteMountKeys = Literal["left", "right"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TipDetectorByMount(TypedDict):
|
|
29
|
+
left: Optional[TipDetector]
|
|
30
|
+
right: Optional[TipDetector]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class UnsubMethodByMount(TypedDict):
|
|
34
|
+
left: Optional[Callable[[], None]]
|
|
35
|
+
right: Optional[Callable[[], None]]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TipUpdateByMount(TypedDict):
|
|
39
|
+
left: Optional[bool]
|
|
40
|
+
right: Optional[bool]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _mount_to_node(mount: OT3Mount) -> NodeId:
|
|
44
|
+
return {
|
|
45
|
+
OT3Mount.LEFT: NodeId.pipette_left,
|
|
46
|
+
OT3Mount.RIGHT: NodeId.pipette_right,
|
|
47
|
+
}[mount]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class TipPresenceManager:
|
|
51
|
+
"""Handle tip change notification coming from CAN."""
|
|
52
|
+
|
|
53
|
+
_listeners: Set[TipListener]
|
|
54
|
+
_detectors: TipDetectorByMount
|
|
55
|
+
_unsub_methods: UnsubMethodByMount
|
|
56
|
+
_last_state: TipUpdateByMount
|
|
57
|
+
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
can_messenger: CanMessenger,
|
|
61
|
+
listeners: Set[TipListener] = set(),
|
|
62
|
+
) -> None:
|
|
63
|
+
self._messenger = can_messenger
|
|
64
|
+
self._listeners = listeners
|
|
65
|
+
self._detectors = TipDetectorByMount(left=None, right=None)
|
|
66
|
+
self._unsub_methods = UnsubMethodByMount(left=None, right=None)
|
|
67
|
+
self._last_state = TipUpdateByMount(left=None, right=None)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def _get_key(mount: OT3Mount) -> PipetteMountKeys:
|
|
71
|
+
assert mount != OT3Mount.GRIPPER
|
|
72
|
+
return cast(PipetteMountKeys, mount.name.lower())
|
|
73
|
+
|
|
74
|
+
async def clear_detector(self, mount: OT3Mount) -> None:
|
|
75
|
+
"""Clean up and remove tip detector."""
|
|
76
|
+
|
|
77
|
+
def _unsubscribe() -> None:
|
|
78
|
+
"""Unsubscribe from detector."""
|
|
79
|
+
unsub = self._unsub_methods[self._get_key(mount)]
|
|
80
|
+
if unsub:
|
|
81
|
+
unsub()
|
|
82
|
+
self.set_unsub(mount, None)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
detector = self.get_detector(mount)
|
|
86
|
+
detector.cleanup()
|
|
87
|
+
except TipDetectorNotFound:
|
|
88
|
+
pass
|
|
89
|
+
finally:
|
|
90
|
+
_unsubscribe()
|
|
91
|
+
self.set_detector(mount, None)
|
|
92
|
+
|
|
93
|
+
async def build_detector(self, mount: OT3Mount, sensor_count: int) -> None:
|
|
94
|
+
assert self._detectors.get(self._get_key(mount), None) is None
|
|
95
|
+
# set up and subscribe to the detector
|
|
96
|
+
d = TipDetector(self._messenger, _mount_to_node(mount), sensor_count)
|
|
97
|
+
# listens to the detector so we can immediately notify listeners
|
|
98
|
+
# the most up-to-date tip state
|
|
99
|
+
unsub = d.add_subscriber(partial(self._handle_tip_update, mount))
|
|
100
|
+
self.set_unsub(mount, unsub)
|
|
101
|
+
self.set_detector(mount, d)
|
|
102
|
+
|
|
103
|
+
def _handle_tip_update(
|
|
104
|
+
self, mount: OT3Mount, update: tip_types.TipNotification
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Callback for detector."""
|
|
107
|
+
self._last_state[self._get_key(mount)] = update.presence
|
|
108
|
+
|
|
109
|
+
for listener in self._listeners:
|
|
110
|
+
listener(mount, update.presence)
|
|
111
|
+
|
|
112
|
+
def current_tip_state(self, mount: OT3Mount) -> Optional[bool]:
|
|
113
|
+
state = self._last_state[self._get_key(mount)]
|
|
114
|
+
return state
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def _get_tip_presence(
|
|
118
|
+
results: List[tip_types.TipNotification],
|
|
119
|
+
follow_singular_sensor: Optional[InstrumentProbeType] = None,
|
|
120
|
+
) -> TipStateType:
|
|
121
|
+
"""
|
|
122
|
+
We can use follow_singular_sensor used to specify that we only care
|
|
123
|
+
about the status of one tip presence sensor on a high throughput
|
|
124
|
+
pipette, and the other is allowed to be different.
|
|
125
|
+
"""
|
|
126
|
+
if follow_singular_sensor:
|
|
127
|
+
target_sensor_id = sensor_id_for_instrument(follow_singular_sensor)
|
|
128
|
+
for r in results:
|
|
129
|
+
if r.sensor == target_sensor_id:
|
|
130
|
+
return TipStateType(r.presence)
|
|
131
|
+
# raise an error if requested sensor response isn't found
|
|
132
|
+
raise GeneralError(
|
|
133
|
+
message=f"Requested status for sensor {follow_singular_sensor} not found."
|
|
134
|
+
)
|
|
135
|
+
# more than one sensor reported, we have to check if their states match
|
|
136
|
+
if len(set(r.presence for r in results)) > 1:
|
|
137
|
+
raise UnmatchedTipPresenceStates(
|
|
138
|
+
{int(r.sensor): int(r.presence) for r in results}
|
|
139
|
+
)
|
|
140
|
+
return TipStateType(results[0].presence)
|
|
141
|
+
|
|
142
|
+
async def get_tip_status(
|
|
143
|
+
self,
|
|
144
|
+
mount: OT3Mount,
|
|
145
|
+
follow_singular_sensor: Optional[InstrumentProbeType] = None,
|
|
146
|
+
) -> TipStateType:
|
|
147
|
+
detector = self.get_detector(mount)
|
|
148
|
+
return self._get_tip_presence(
|
|
149
|
+
await detector.request_tip_status(), follow_singular_sensor
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def get_detector(self, mount: OT3Mount) -> TipDetector:
|
|
153
|
+
detector = self._detectors[self._get_key(mount)]
|
|
154
|
+
if not detector:
|
|
155
|
+
raise TipDetectorNotFound(
|
|
156
|
+
message=f"Tip detector not set up for {mount} mount",
|
|
157
|
+
detail={"mount": str(mount)},
|
|
158
|
+
)
|
|
159
|
+
return detector
|
|
160
|
+
|
|
161
|
+
def set_detector(self, mount: OT3Mount, detector: Optional[TipDetector]) -> None:
|
|
162
|
+
self._detectors[self._get_key(mount)] = detector
|
|
163
|
+
|
|
164
|
+
def set_unsub(self, mount: OT3Mount, unsub: Optional[Callable[[], None]]) -> None:
|
|
165
|
+
self._unsub_methods[self._get_key(mount)] = unsub
|
|
166
|
+
|
|
167
|
+
def add_listener(self, listener: TipListener) -> Callable[[], None]:
|
|
168
|
+
self._listeners.add(listener)
|
|
169
|
+
|
|
170
|
+
def remove() -> None:
|
|
171
|
+
self._listeners.discard(listener)
|
|
172
|
+
|
|
173
|
+
return remove
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""backends.types - wrapper types for api/backend interaction"""
|
|
2
|
+
|
|
3
|
+
from enum import Enum, auto
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HWStopCondition(Enum):
|
|
7
|
+
none = auto()
|
|
8
|
+
limit_switch = auto()
|
|
9
|
+
sync_line = auto()
|
|
10
|
+
encoder_position = auto()
|
|
11
|
+
gripper_force = auto()
|
|
12
|
+
stall = auto()
|
|
13
|
+
ignore_stalls = auto()
|
|
14
|
+
limit_switch_backoff = auto()
|