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.

Files changed (600) hide show
  1. opentrons/__init__.py +150 -0
  2. opentrons/_version.py +34 -0
  3. opentrons/calibration_storage/__init__.py +54 -0
  4. opentrons/calibration_storage/deck_configuration.py +62 -0
  5. opentrons/calibration_storage/encoder_decoder.py +31 -0
  6. opentrons/calibration_storage/file_operators.py +142 -0
  7. opentrons/calibration_storage/helpers.py +103 -0
  8. opentrons/calibration_storage/ot2/__init__.py +34 -0
  9. opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
  10. opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
  11. opentrons/calibration_storage/ot2/models/__init__.py +0 -0
  12. opentrons/calibration_storage/ot2/models/v1.py +149 -0
  13. opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
  14. opentrons/calibration_storage/ot2/tip_length.py +281 -0
  15. opentrons/calibration_storage/ot3/__init__.py +31 -0
  16. opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
  17. opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
  18. opentrons/calibration_storage/ot3/models/__init__.py +0 -0
  19. opentrons/calibration_storage/ot3/models/v1.py +122 -0
  20. opentrons/calibration_storage/ot3/module_offset.py +138 -0
  21. opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
  22. opentrons/calibration_storage/types.py +45 -0
  23. opentrons/cli/__init__.py +21 -0
  24. opentrons/cli/__main__.py +5 -0
  25. opentrons/cli/analyze.py +501 -0
  26. opentrons/config/__init__.py +631 -0
  27. opentrons/config/advanced_settings.py +871 -0
  28. opentrons/config/defaults_ot2.py +214 -0
  29. opentrons/config/defaults_ot3.py +499 -0
  30. opentrons/config/feature_flags.py +86 -0
  31. opentrons/config/gripper_config.py +55 -0
  32. opentrons/config/reset.py +203 -0
  33. opentrons/config/robot_configs.py +187 -0
  34. opentrons/config/types.py +183 -0
  35. opentrons/drivers/__init__.py +0 -0
  36. opentrons/drivers/absorbance_reader/__init__.py +11 -0
  37. opentrons/drivers/absorbance_reader/abstract.py +72 -0
  38. opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
  39. opentrons/drivers/absorbance_reader/driver.py +81 -0
  40. opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
  41. opentrons/drivers/absorbance_reader/simulator.py +84 -0
  42. opentrons/drivers/asyncio/__init__.py +0 -0
  43. opentrons/drivers/asyncio/communication/__init__.py +22 -0
  44. opentrons/drivers/asyncio/communication/async_serial.py +183 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +552 -0
  47. opentrons/drivers/command_builder.py +102 -0
  48. opentrons/drivers/flex_stacker/__init__.py +13 -0
  49. opentrons/drivers/flex_stacker/abstract.py +214 -0
  50. opentrons/drivers/flex_stacker/driver.py +768 -0
  51. opentrons/drivers/flex_stacker/errors.py +68 -0
  52. opentrons/drivers/flex_stacker/simulator.py +309 -0
  53. opentrons/drivers/flex_stacker/types.py +367 -0
  54. opentrons/drivers/flex_stacker/utils.py +19 -0
  55. opentrons/drivers/heater_shaker/__init__.py +5 -0
  56. opentrons/drivers/heater_shaker/abstract.py +76 -0
  57. opentrons/drivers/heater_shaker/driver.py +204 -0
  58. opentrons/drivers/heater_shaker/simulator.py +94 -0
  59. opentrons/drivers/mag_deck/__init__.py +6 -0
  60. opentrons/drivers/mag_deck/abstract.py +44 -0
  61. opentrons/drivers/mag_deck/driver.py +208 -0
  62. opentrons/drivers/mag_deck/simulator.py +63 -0
  63. opentrons/drivers/rpi_drivers/__init__.py +33 -0
  64. opentrons/drivers/rpi_drivers/dev_types.py +94 -0
  65. opentrons/drivers/rpi_drivers/gpio.py +282 -0
  66. opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
  67. opentrons/drivers/rpi_drivers/interfaces.py +15 -0
  68. opentrons/drivers/rpi_drivers/types.py +364 -0
  69. opentrons/drivers/rpi_drivers/usb.py +102 -0
  70. opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
  71. opentrons/drivers/serial_communication.py +151 -0
  72. opentrons/drivers/smoothie_drivers/__init__.py +4 -0
  73. opentrons/drivers/smoothie_drivers/connection.py +51 -0
  74. opentrons/drivers/smoothie_drivers/constants.py +121 -0
  75. opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
  76. opentrons/drivers/smoothie_drivers/errors.py +49 -0
  77. opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
  78. opentrons/drivers/smoothie_drivers/simulator.py +99 -0
  79. opentrons/drivers/smoothie_drivers/types.py +16 -0
  80. opentrons/drivers/temp_deck/__init__.py +10 -0
  81. opentrons/drivers/temp_deck/abstract.py +54 -0
  82. opentrons/drivers/temp_deck/driver.py +197 -0
  83. opentrons/drivers/temp_deck/simulator.py +57 -0
  84. opentrons/drivers/thermocycler/__init__.py +12 -0
  85. opentrons/drivers/thermocycler/abstract.py +99 -0
  86. opentrons/drivers/thermocycler/driver.py +395 -0
  87. opentrons/drivers/thermocycler/simulator.py +126 -0
  88. opentrons/drivers/types.py +107 -0
  89. opentrons/drivers/utils.py +222 -0
  90. opentrons/execute.py +742 -0
  91. opentrons/hardware_control/__init__.py +65 -0
  92. opentrons/hardware_control/__main__.py +77 -0
  93. opentrons/hardware_control/adapters.py +98 -0
  94. opentrons/hardware_control/api.py +1347 -0
  95. opentrons/hardware_control/backends/__init__.py +7 -0
  96. opentrons/hardware_control/backends/controller.py +400 -0
  97. opentrons/hardware_control/backends/errors.py +9 -0
  98. opentrons/hardware_control/backends/estop_state.py +164 -0
  99. opentrons/hardware_control/backends/flex_protocol.py +497 -0
  100. opentrons/hardware_control/backends/ot3controller.py +1930 -0
  101. opentrons/hardware_control/backends/ot3simulator.py +900 -0
  102. opentrons/hardware_control/backends/ot3utils.py +664 -0
  103. opentrons/hardware_control/backends/simulator.py +442 -0
  104. opentrons/hardware_control/backends/status_bar_state.py +240 -0
  105. opentrons/hardware_control/backends/subsystem_manager.py +431 -0
  106. opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
  107. opentrons/hardware_control/backends/types.py +14 -0
  108. opentrons/hardware_control/constants.py +6 -0
  109. opentrons/hardware_control/dev_types.py +125 -0
  110. opentrons/hardware_control/emulation/__init__.py +0 -0
  111. opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
  112. opentrons/hardware_control/emulation/app.py +56 -0
  113. opentrons/hardware_control/emulation/connection_handler.py +38 -0
  114. opentrons/hardware_control/emulation/heater_shaker.py +150 -0
  115. opentrons/hardware_control/emulation/magdeck.py +60 -0
  116. opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
  117. opentrons/hardware_control/emulation/module_server/client.py +78 -0
  118. opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
  119. opentrons/hardware_control/emulation/module_server/models.py +31 -0
  120. opentrons/hardware_control/emulation/module_server/server.py +110 -0
  121. opentrons/hardware_control/emulation/parser.py +74 -0
  122. opentrons/hardware_control/emulation/proxy.py +241 -0
  123. opentrons/hardware_control/emulation/run_emulator.py +68 -0
  124. opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
  125. opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
  126. opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
  127. opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
  128. opentrons/hardware_control/emulation/settings.py +119 -0
  129. opentrons/hardware_control/emulation/simulations.py +133 -0
  130. opentrons/hardware_control/emulation/smoothie.py +192 -0
  131. opentrons/hardware_control/emulation/tempdeck.py +69 -0
  132. opentrons/hardware_control/emulation/thermocycler.py +128 -0
  133. opentrons/hardware_control/emulation/types.py +10 -0
  134. opentrons/hardware_control/emulation/util.py +38 -0
  135. opentrons/hardware_control/errors.py +43 -0
  136. opentrons/hardware_control/execution_manager.py +164 -0
  137. opentrons/hardware_control/instruments/__init__.py +5 -0
  138. opentrons/hardware_control/instruments/instrument_abc.py +39 -0
  139. opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
  140. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
  141. opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
  142. opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
  143. opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
  144. opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
  145. opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
  146. opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
  147. opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
  148. opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
  149. opentrons/hardware_control/module_control.py +332 -0
  150. opentrons/hardware_control/modules/__init__.py +69 -0
  151. opentrons/hardware_control/modules/absorbance_reader.py +373 -0
  152. opentrons/hardware_control/modules/errors.py +7 -0
  153. opentrons/hardware_control/modules/flex_stacker.py +948 -0
  154. opentrons/hardware_control/modules/heater_shaker.py +426 -0
  155. opentrons/hardware_control/modules/lid_temp_status.py +35 -0
  156. opentrons/hardware_control/modules/magdeck.py +233 -0
  157. opentrons/hardware_control/modules/mod_abc.py +245 -0
  158. opentrons/hardware_control/modules/module_calibration.py +93 -0
  159. opentrons/hardware_control/modules/plate_temp_status.py +61 -0
  160. opentrons/hardware_control/modules/tempdeck.py +299 -0
  161. opentrons/hardware_control/modules/thermocycler.py +731 -0
  162. opentrons/hardware_control/modules/types.py +417 -0
  163. opentrons/hardware_control/modules/update.py +255 -0
  164. opentrons/hardware_control/modules/utils.py +73 -0
  165. opentrons/hardware_control/motion_utilities.py +318 -0
  166. opentrons/hardware_control/nozzle_manager.py +422 -0
  167. opentrons/hardware_control/ot3_calibration.py +1171 -0
  168. opentrons/hardware_control/ot3api.py +3227 -0
  169. opentrons/hardware_control/pause_manager.py +31 -0
  170. opentrons/hardware_control/poller.py +112 -0
  171. opentrons/hardware_control/protocols/__init__.py +106 -0
  172. opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
  173. opentrons/hardware_control/protocols/calibratable.py +45 -0
  174. opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
  175. opentrons/hardware_control/protocols/configurable.py +48 -0
  176. opentrons/hardware_control/protocols/event_sourcer.py +18 -0
  177. opentrons/hardware_control/protocols/execution_controllable.py +33 -0
  178. opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
  179. opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
  180. opentrons/hardware_control/protocols/gripper_controller.py +55 -0
  181. opentrons/hardware_control/protocols/hardware_manager.py +51 -0
  182. opentrons/hardware_control/protocols/identifiable.py +16 -0
  183. opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
  184. opentrons/hardware_control/protocols/liquid_handler.py +266 -0
  185. opentrons/hardware_control/protocols/module_provider.py +16 -0
  186. opentrons/hardware_control/protocols/motion_controller.py +243 -0
  187. opentrons/hardware_control/protocols/position_estimator.py +45 -0
  188. opentrons/hardware_control/protocols/simulatable.py +10 -0
  189. opentrons/hardware_control/protocols/stoppable.py +9 -0
  190. opentrons/hardware_control/protocols/types.py +27 -0
  191. opentrons/hardware_control/robot_calibration.py +224 -0
  192. opentrons/hardware_control/scripts/README.md +28 -0
  193. opentrons/hardware_control/scripts/__init__.py +1 -0
  194. opentrons/hardware_control/scripts/gripper_control.py +208 -0
  195. opentrons/hardware_control/scripts/ot3gripper +7 -0
  196. opentrons/hardware_control/scripts/ot3repl +7 -0
  197. opentrons/hardware_control/scripts/repl.py +187 -0
  198. opentrons/hardware_control/scripts/tc_control.py +97 -0
  199. opentrons/hardware_control/simulator_setup.py +260 -0
  200. opentrons/hardware_control/thread_manager.py +431 -0
  201. opentrons/hardware_control/threaded_async_lock.py +97 -0
  202. opentrons/hardware_control/types.py +792 -0
  203. opentrons/hardware_control/util.py +234 -0
  204. opentrons/legacy_broker.py +53 -0
  205. opentrons/legacy_commands/__init__.py +1 -0
  206. opentrons/legacy_commands/commands.py +483 -0
  207. opentrons/legacy_commands/helpers.py +153 -0
  208. opentrons/legacy_commands/module_commands.py +215 -0
  209. opentrons/legacy_commands/protocol_commands.py +54 -0
  210. opentrons/legacy_commands/publisher.py +155 -0
  211. opentrons/legacy_commands/robot_commands.py +51 -0
  212. opentrons/legacy_commands/types.py +1115 -0
  213. opentrons/motion_planning/__init__.py +32 -0
  214. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  215. opentrons/motion_planning/deck_conflict.py +396 -0
  216. opentrons/motion_planning/errors.py +35 -0
  217. opentrons/motion_planning/types.py +42 -0
  218. opentrons/motion_planning/waypoints.py +218 -0
  219. opentrons/ordered_set.py +138 -0
  220. opentrons/protocol_api/__init__.py +105 -0
  221. opentrons/protocol_api/_liquid.py +157 -0
  222. opentrons/protocol_api/_liquid_properties.py +814 -0
  223. opentrons/protocol_api/_nozzle_layout.py +31 -0
  224. opentrons/protocol_api/_parameter_context.py +300 -0
  225. opentrons/protocol_api/_parameters.py +31 -0
  226. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  227. opentrons/protocol_api/_types.py +43 -0
  228. opentrons/protocol_api/config.py +23 -0
  229. opentrons/protocol_api/core/__init__.py +23 -0
  230. opentrons/protocol_api/core/common.py +33 -0
  231. opentrons/protocol_api/core/core_map.py +74 -0
  232. opentrons/protocol_api/core/engine/__init__.py +22 -0
  233. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  234. opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
  235. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  236. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  237. opentrons/protocol_api/core/engine/labware.py +238 -0
  238. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  239. opentrons/protocol_api/core/engine/module_core.py +1025 -0
  240. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  241. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  242. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  243. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  244. opentrons/protocol_api/core/engine/robot.py +139 -0
  245. opentrons/protocol_api/core/engine/stringify.py +74 -0
  246. opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
  247. opentrons/protocol_api/core/engine/well.py +241 -0
  248. opentrons/protocol_api/core/instrument.py +459 -0
  249. opentrons/protocol_api/core/labware.py +151 -0
  250. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  251. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  252. opentrons/protocol_api/core/legacy/deck.py +369 -0
  253. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  254. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  255. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  256. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  257. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  258. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  259. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  260. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  261. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  262. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  263. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  265. opentrons/protocol_api/core/module.py +484 -0
  266. opentrons/protocol_api/core/protocol.py +311 -0
  267. opentrons/protocol_api/core/robot.py +51 -0
  268. opentrons/protocol_api/core/well.py +116 -0
  269. opentrons/protocol_api/core/well_grid.py +45 -0
  270. opentrons/protocol_api/create_protocol_context.py +177 -0
  271. opentrons/protocol_api/deck.py +223 -0
  272. opentrons/protocol_api/disposal_locations.py +244 -0
  273. opentrons/protocol_api/instrument_context.py +3212 -0
  274. opentrons/protocol_api/labware.py +1579 -0
  275. opentrons/protocol_api/module_contexts.py +1425 -0
  276. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  277. opentrons/protocol_api/protocol_context.py +1688 -0
  278. opentrons/protocol_api/robot_context.py +303 -0
  279. opentrons/protocol_api/validation.py +761 -0
  280. opentrons/protocol_engine/__init__.py +155 -0
  281. opentrons/protocol_engine/actions/__init__.py +65 -0
  282. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  283. opentrons/protocol_engine/actions/action_handler.py +13 -0
  284. opentrons/protocol_engine/actions/actions.py +302 -0
  285. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  286. opentrons/protocol_engine/clients/__init__.py +5 -0
  287. opentrons/protocol_engine/clients/sync_client.py +174 -0
  288. opentrons/protocol_engine/clients/transports.py +197 -0
  289. opentrons/protocol_engine/commands/__init__.py +757 -0
  290. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  296. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  297. opentrons/protocol_engine/commands/aspirate.py +244 -0
  298. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  299. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  300. opentrons/protocol_engine/commands/blow_out.py +146 -0
  301. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  302. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  303. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  306. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  307. opentrons/protocol_engine/commands/command.py +308 -0
  308. opentrons/protocol_engine/commands/command_unions.py +974 -0
  309. opentrons/protocol_engine/commands/comment.py +57 -0
  310. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  311. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  312. opentrons/protocol_engine/commands/custom.py +67 -0
  313. opentrons/protocol_engine/commands/dispense.py +194 -0
  314. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  315. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  316. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  317. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  318. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  319. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  320. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  321. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  322. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  323. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  324. opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
  325. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  326. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  327. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  328. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  329. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  330. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  331. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  333. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  334. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  336. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  337. opentrons/protocol_engine/commands/home.py +100 -0
  338. opentrons/protocol_engine/commands/identify_module.py +86 -0
  339. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  340. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  341. opentrons/protocol_engine/commands/load_labware.py +210 -0
  342. opentrons/protocol_engine/commands/load_lid.py +154 -0
  343. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  344. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  345. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  346. opentrons/protocol_engine/commands/load_module.py +223 -0
  347. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  348. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  349. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  350. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  351. opentrons/protocol_engine/commands/move_labware.py +546 -0
  352. opentrons/protocol_engine/commands/move_relative.py +102 -0
  353. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  355. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  356. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  357. opentrons/protocol_engine/commands/movement_common.py +338 -0
  358. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  359. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  360. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  361. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  362. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  363. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  364. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  365. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  366. opentrons/protocol_engine/commands/robot/common.py +18 -0
  367. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  369. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  370. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  371. opentrons/protocol_engine/commands/save_position.py +109 -0
  372. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  373. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  374. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  375. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  376. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  377. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  378. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  379. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  380. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  381. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  384. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  386. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  388. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  390. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  391. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  392. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  401. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  402. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  403. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  404. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  405. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  406. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  407. opentrons/protocol_engine/engine_support.py +28 -0
  408. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  409. opentrons/protocol_engine/errors/__init__.py +191 -0
  410. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  411. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  412. opentrons/protocol_engine/execution/__init__.py +50 -0
  413. opentrons/protocol_engine/execution/command_executor.py +216 -0
  414. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  415. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  416. opentrons/protocol_engine/execution/equipment.py +819 -0
  417. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  418. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  419. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  420. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  421. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  422. opentrons/protocol_engine/execution/movement.py +349 -0
  423. opentrons/protocol_engine/execution/pipetting.py +607 -0
  424. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  425. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  426. opentrons/protocol_engine/execution/run_control.py +33 -0
  427. opentrons/protocol_engine/execution/status_bar.py +34 -0
  428. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  429. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  430. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  431. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  432. opentrons/protocol_engine/notes/__init__.py +17 -0
  433. opentrons/protocol_engine/notes/notes.py +59 -0
  434. opentrons/protocol_engine/plugins.py +104 -0
  435. opentrons/protocol_engine/protocol_engine.py +683 -0
  436. opentrons/protocol_engine/resources/__init__.py +26 -0
  437. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  438. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  439. opentrons/protocol_engine/resources/file_provider.py +161 -0
  440. opentrons/protocol_engine/resources/fixture_validation.py +58 -0
  441. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  442. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  443. opentrons/protocol_engine/resources/model_utils.py +32 -0
  444. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  445. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  446. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  447. opentrons/protocol_engine/slot_standardization.py +128 -0
  448. opentrons/protocol_engine/state/__init__.py +1 -0
  449. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  450. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  451. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  452. opentrons/protocol_engine/state/_move_types.py +83 -0
  453. opentrons/protocol_engine/state/_well_math.py +193 -0
  454. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  455. opentrons/protocol_engine/state/command_history.py +309 -0
  456. opentrons/protocol_engine/state/commands.py +1158 -0
  457. opentrons/protocol_engine/state/config.py +39 -0
  458. opentrons/protocol_engine/state/files.py +57 -0
  459. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  460. opentrons/protocol_engine/state/geometry.py +2359 -0
  461. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  462. opentrons/protocol_engine/state/labware.py +1459 -0
  463. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  464. opentrons/protocol_engine/state/liquids.py +73 -0
  465. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  466. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  467. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  468. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  469. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  471. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  472. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  473. opentrons/protocol_engine/state/modules.py +1500 -0
  474. opentrons/protocol_engine/state/motion.py +373 -0
  475. opentrons/protocol_engine/state/pipettes.py +905 -0
  476. opentrons/protocol_engine/state/state.py +421 -0
  477. opentrons/protocol_engine/state/state_summary.py +36 -0
  478. opentrons/protocol_engine/state/tips.py +420 -0
  479. opentrons/protocol_engine/state/update_types.py +904 -0
  480. opentrons/protocol_engine/state/wells.py +290 -0
  481. opentrons/protocol_engine/types/__init__.py +308 -0
  482. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  483. opentrons/protocol_engine/types/command_annotations.py +53 -0
  484. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  485. opentrons/protocol_engine/types/execution.py +96 -0
  486. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  487. opentrons/protocol_engine/types/instrument.py +47 -0
  488. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  489. opentrons/protocol_engine/types/labware.py +131 -0
  490. opentrons/protocol_engine/types/labware_movement.py +22 -0
  491. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  492. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  493. opentrons/protocol_engine/types/liquid.py +40 -0
  494. opentrons/protocol_engine/types/liquid_class.py +59 -0
  495. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  496. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  497. opentrons/protocol_engine/types/location.py +194 -0
  498. opentrons/protocol_engine/types/module.py +303 -0
  499. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  500. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  501. opentrons/protocol_engine/types/tip.py +18 -0
  502. opentrons/protocol_engine/types/util.py +21 -0
  503. opentrons/protocol_engine/types/well_position.py +124 -0
  504. opentrons/protocol_reader/__init__.py +37 -0
  505. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  506. opentrons/protocol_reader/file_format_validator.py +152 -0
  507. opentrons/protocol_reader/file_hasher.py +27 -0
  508. opentrons/protocol_reader/file_identifier.py +284 -0
  509. opentrons/protocol_reader/file_reader_writer.py +90 -0
  510. opentrons/protocol_reader/input_file.py +16 -0
  511. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  512. opentrons/protocol_reader/protocol_reader.py +188 -0
  513. opentrons/protocol_reader/protocol_source.py +124 -0
  514. opentrons/protocol_reader/role_analyzer.py +86 -0
  515. opentrons/protocol_runner/__init__.py +26 -0
  516. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  517. opentrons/protocol_runner/json_file_reader.py +55 -0
  518. opentrons/protocol_runner/json_translator.py +314 -0
  519. opentrons/protocol_runner/legacy_command_mapper.py +848 -0
  520. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  521. opentrons/protocol_runner/protocol_runner.py +530 -0
  522. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  523. opentrons/protocol_runner/run_orchestrator.py +496 -0
  524. opentrons/protocol_runner/task_queue.py +95 -0
  525. opentrons/protocols/__init__.py +6 -0
  526. opentrons/protocols/advanced_control/__init__.py +0 -0
  527. opentrons/protocols/advanced_control/common.py +38 -0
  528. opentrons/protocols/advanced_control/mix.py +60 -0
  529. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  530. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  531. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  532. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  533. opentrons/protocols/api_support/__init__.py +0 -0
  534. opentrons/protocols/api_support/constants.py +8 -0
  535. opentrons/protocols/api_support/deck_type.py +110 -0
  536. opentrons/protocols/api_support/definitions.py +18 -0
  537. opentrons/protocols/api_support/instrument.py +151 -0
  538. opentrons/protocols/api_support/labware_like.py +233 -0
  539. opentrons/protocols/api_support/tip_tracker.py +175 -0
  540. opentrons/protocols/api_support/types.py +32 -0
  541. opentrons/protocols/api_support/util.py +403 -0
  542. opentrons/protocols/bundle.py +89 -0
  543. opentrons/protocols/duration/__init__.py +4 -0
  544. opentrons/protocols/duration/errors.py +5 -0
  545. opentrons/protocols/duration/estimator.py +628 -0
  546. opentrons/protocols/execution/__init__.py +0 -0
  547. opentrons/protocols/execution/dev_types.py +181 -0
  548. opentrons/protocols/execution/errors.py +40 -0
  549. opentrons/protocols/execution/execute.py +84 -0
  550. opentrons/protocols/execution/execute_json_v3.py +275 -0
  551. opentrons/protocols/execution/execute_json_v4.py +359 -0
  552. opentrons/protocols/execution/execute_json_v5.py +28 -0
  553. opentrons/protocols/execution/execute_python.py +169 -0
  554. opentrons/protocols/execution/json_dispatchers.py +87 -0
  555. opentrons/protocols/execution/types.py +7 -0
  556. opentrons/protocols/geometry/__init__.py +0 -0
  557. opentrons/protocols/geometry/planning.py +297 -0
  558. opentrons/protocols/labware.py +312 -0
  559. opentrons/protocols/models/__init__.py +0 -0
  560. opentrons/protocols/models/json_protocol.py +679 -0
  561. opentrons/protocols/parameters/__init__.py +0 -0
  562. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  563. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  564. opentrons/protocols/parameters/exceptions.py +34 -0
  565. opentrons/protocols/parameters/parameter_definition.py +272 -0
  566. opentrons/protocols/parameters/types.py +17 -0
  567. opentrons/protocols/parameters/validation.py +267 -0
  568. opentrons/protocols/parse.py +671 -0
  569. opentrons/protocols/types.py +159 -0
  570. opentrons/py.typed +0 -0
  571. opentrons/resources/scripts/lpc21isp +0 -0
  572. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  573. opentrons/simulate.py +1065 -0
  574. opentrons/system/__init__.py +6 -0
  575. opentrons/system/camera.py +51 -0
  576. opentrons/system/log_control.py +59 -0
  577. opentrons/system/nmcli.py +856 -0
  578. opentrons/system/resin.py +24 -0
  579. opentrons/system/smoothie_update.py +15 -0
  580. opentrons/system/wifi.py +204 -0
  581. opentrons/tools/__init__.py +0 -0
  582. opentrons/tools/args_handler.py +22 -0
  583. opentrons/tools/write_pipette_memory.py +157 -0
  584. opentrons/types.py +618 -0
  585. opentrons/util/__init__.py +1 -0
  586. opentrons/util/async_helpers.py +166 -0
  587. opentrons/util/broker.py +84 -0
  588. opentrons/util/change_notifier.py +47 -0
  589. opentrons/util/entrypoint_util.py +278 -0
  590. opentrons/util/get_union_elements.py +26 -0
  591. opentrons/util/helpers.py +6 -0
  592. opentrons/util/linal.py +178 -0
  593. opentrons/util/logging_config.py +265 -0
  594. opentrons/util/logging_queue_handler.py +61 -0
  595. opentrons/util/performance_helpers.py +157 -0
  596. opentrons-8.6.0a1.dist-info/METADATA +37 -0
  597. opentrons-8.6.0a1.dist-info/RECORD +600 -0
  598. opentrons-8.6.0a1.dist-info/WHEEL +4 -0
  599. opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
  600. opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,7 @@
1
+ from .controller import Controller
2
+ from .simulator import Simulator
3
+
4
+ # only expose the ot2 interfaces in __init__ so everything works if opentrons_hardware
5
+ # is not present
6
+
7
+ __all__ = ["Controller", "Simulator"]
@@ -0,0 +1,400 @@
1
+ from __future__ import annotations
2
+ import asyncio
3
+ from contextlib import contextmanager, AsyncExitStack
4
+ import logging
5
+ from typing import (
6
+ Callable,
7
+ Iterator,
8
+ Any,
9
+ Dict,
10
+ List,
11
+ Optional,
12
+ Tuple,
13
+ TYPE_CHECKING,
14
+ Union,
15
+ Sequence,
16
+ cast,
17
+ )
18
+ from typing_extensions import Final
19
+ from pathlib import Path
20
+
21
+ try:
22
+ import aionotify # type: ignore[import-untyped]
23
+ except (OSError, ModuleNotFoundError):
24
+ aionotify = None
25
+
26
+ from opentrons_shared_data.pipette import (
27
+ pipette_load_name_conversions as pipette_load_name,
28
+ mutable_configurations,
29
+ )
30
+ from opentrons_shared_data.pipette.types import PipetteName
31
+
32
+ from opentrons.drivers.smoothie_drivers import SmoothieDriver
33
+ from opentrons.drivers.rpi_drivers import build_gpio_chardev
34
+ import opentrons.config
35
+ from opentrons.config.types import RobotConfig
36
+ from opentrons.types import Mount
37
+
38
+ from ..module_control import AttachedModulesControl
39
+ from ..types import AionotifyEvent, BoardRevision, Axis, DoorState
40
+ from ..util import ot2_axis_to_string
41
+
42
+ if TYPE_CHECKING:
43
+ from opentrons_shared_data.pipette.types import PipetteModel
44
+ from ..dev_types import (
45
+ AttachedPipette,
46
+ AttachedInstruments,
47
+ InstrumentHardwareConfigs,
48
+ )
49
+ from opentrons.drivers.rpi_drivers.dev_types import GPIODriverLike
50
+
51
+ MODULE_LOG = logging.getLogger(__name__)
52
+
53
+
54
+ class Controller:
55
+ """The concrete instance of the controller for actually controlling
56
+ hardware.
57
+ """
58
+
59
+ @classmethod
60
+ async def build(cls, config: Optional[RobotConfig]) -> Controller:
61
+ """Build a Controller instance.
62
+
63
+ Use this factory method rather than the initializer to handle proper
64
+ GPIO initialization.
65
+
66
+ :param config: A loaded robot config.
67
+ """
68
+
69
+ gpio = build_gpio_chardev("gpiochip0")
70
+ gpio.config_by_board_rev()
71
+ await gpio.setup()
72
+ return cls(config, gpio)
73
+
74
+ def __init__(self, config: Optional[RobotConfig], gpio: GPIODriverLike):
75
+ """Build a Controller instance.
76
+
77
+ Always prefer using :py:meth:`.build` to create an instance of this class. For
78
+ more information on arguments, see that method. If you want to use this
79
+ directly, you must pass in an initialized _and set up_ GPIO driver instance.
80
+ """
81
+ if not opentrons.config.IS_ROBOT:
82
+ MODULE_LOG.warning(
83
+ "This is intended to run on a robot, and while it can connect "
84
+ "to a smoothie via a usb/serial adapter unexpected things "
85
+ "using gpios (such as smoothie reset or light management) "
86
+ "will fail. If you are seeing this message and you are "
87
+ "running on a robot, you need to set the RUNNING_ON_PI "
88
+ "environmental variable to 1."
89
+ )
90
+
91
+ self.config = config or opentrons.config.robot_configs.load_ot2()
92
+
93
+ self._gpio_chardev: Final = gpio
94
+ self._board_revision: Final = self.gpio_chardev.board_rev
95
+ # We handle our own locks in the hardware controller thank you
96
+ self._smoothie_driver = SmoothieDriver(
97
+ config=self.config, gpio_chardev=self._gpio_chardev
98
+ )
99
+ self._cached_fw_version: Optional[str] = None
100
+ self._module_controls: Optional[AttachedModulesControl] = None
101
+ try:
102
+ self._event_watcher = self._build_event_watcher()
103
+ except AttributeError:
104
+ MODULE_LOG.warning(
105
+ "Failed to initiate aionotify, cannot watch modules "
106
+ "or door, likely because not running on linux"
107
+ )
108
+
109
+ @staticmethod
110
+ def _build_event_watcher() -> aionotify.Watcher:
111
+ watcher = aionotify.Watcher()
112
+ watcher.watch(
113
+ alias="modules",
114
+ path="/dev",
115
+ flags=(
116
+ aionotify.Flags.CREATE
117
+ | aionotify.Flags.DELETE
118
+ | aionotify.Flags.MOVED_FROM
119
+ | aionotify.Flags.MOVED_TO
120
+ ),
121
+ )
122
+ return watcher
123
+
124
+ @property
125
+ def gpio_chardev(self) -> GPIODriverLike:
126
+ return self._gpio_chardev
127
+
128
+ @property
129
+ def board_revision(self) -> BoardRevision:
130
+ return self._board_revision
131
+
132
+ @property
133
+ def module_controls(self) -> AttachedModulesControl:
134
+ if not self._module_controls:
135
+ raise AttributeError("Module controls not found.")
136
+ return self._module_controls
137
+
138
+ @module_controls.setter
139
+ def module_controls(self, module_controls: AttachedModulesControl) -> None:
140
+ self._module_controls = module_controls
141
+
142
+ async def get_serial_number(self) -> Optional[str]:
143
+ try:
144
+ return Path("/var/serial").read_text().strip()
145
+ except OSError:
146
+ return None
147
+
148
+ def start_gpio_door_watcher(
149
+ self,
150
+ loop: asyncio.AbstractEventLoop,
151
+ update_door_state: Callable[[DoorState], None],
152
+ ) -> None:
153
+ self.gpio_chardev.start_door_switch_watcher(
154
+ loop=loop, update_door_state=update_door_state
155
+ )
156
+
157
+ async def update_position(self) -> Dict[str, float]:
158
+ await self._smoothie_driver.update_position()
159
+ return self._smoothie_driver.position
160
+
161
+ def _unhomed_axes(self, axes: Sequence[str]) -> List[str]:
162
+ return list(
163
+ axis
164
+ for axis in axes
165
+ if not self._smoothie_driver.homed_flags.get(axis, False)
166
+ )
167
+
168
+ def is_homed(self, axes: Sequence[str]) -> bool:
169
+ return not any(self._unhomed_axes(axes))
170
+
171
+ async def move(
172
+ self,
173
+ target_position: Dict[str, float],
174
+ home_flagged_axes: bool = True,
175
+ speed: Optional[float] = None,
176
+ axis_max_speeds: Optional[Dict[str, float]] = None,
177
+ ) -> None:
178
+ async with AsyncExitStack() as cmstack:
179
+ if axis_max_speeds:
180
+ await cmstack.enter_async_context(
181
+ self._smoothie_driver.restore_axis_max_speed(axis_max_speeds)
182
+ )
183
+ await self._smoothie_driver.move(
184
+ target_position, home_flagged_axes=home_flagged_axes, speed=speed
185
+ )
186
+
187
+ async def home(self, axes: Optional[List[str]] = None) -> Dict[str, float]:
188
+ if axes:
189
+ args: Tuple[Any, ...] = ("".join(axes),)
190
+ else:
191
+ args = tuple()
192
+ return await self._smoothie_driver.home(*args)
193
+
194
+ async def fast_home(self, axes: Sequence[str], margin: float) -> Dict[str, float]:
195
+ converted_axes = "".join(axes)
196
+ return await self._smoothie_driver.fast_home(converted_axes, margin)
197
+
198
+ async def _query_mount(
199
+ self, mount: Mount, expected: Union[PipetteModel, PipetteName, None]
200
+ ) -> AttachedPipette:
201
+ found_model: Optional[
202
+ PipetteModel
203
+ ] = await self._smoothie_driver.read_pipette_model( # type: ignore
204
+ mount.name.lower()
205
+ )
206
+ if found_model and not pipette_load_name.supported_pipette(found_model):
207
+ # TODO: Consider how to handle this error - it bubbles up now
208
+ # and will cause problems at higher levels
209
+ MODULE_LOG.error(f"Bad model on {mount.name}: {found_model}")
210
+ found_model = None
211
+ found_id = await self._smoothie_driver.read_pipette_id(mount.name.lower())
212
+
213
+ if found_model:
214
+ path_to_overrides = opentrons.config.get_opentrons_path(
215
+ "pipette_config_overrides_dir"
216
+ )
217
+ converted_found_model = pipette_load_name.convert_pipette_model(found_model)
218
+ converted_found_name = pipette_load_name.convert_to_pipette_name_type(
219
+ found_model
220
+ )
221
+ config = mutable_configurations.load_with_mutable_configurations(
222
+ converted_found_model, path_to_overrides, found_id
223
+ )
224
+ if expected:
225
+ acceptable = [
226
+ cast(PipetteName, str(converted_found_name))
227
+ ] + config.pipette_backcompat_names
228
+ if expected not in acceptable:
229
+ raise RuntimeError(
230
+ f"mount {mount}: instrument"
231
+ f" {expected} was requested"
232
+ f" but {converted_found_model} is present"
233
+ )
234
+ return {"config": config, "id": found_id}
235
+ else:
236
+ if expected:
237
+ raise RuntimeError(
238
+ f"mount {mount}: instrument {expected} was"
239
+ f" requested, but no instrument is present"
240
+ )
241
+ return {"config": None, "id": None}
242
+
243
+ async def get_attached_instruments(
244
+ self, expected: Dict[Mount, PipetteName]
245
+ ) -> AttachedInstruments:
246
+ """Find the instruments attached to our mounts.
247
+ :param expected: is ignored, it is just meant to enforce
248
+ the same interface as the simulator, where
249
+ required instruments can be manipulated.
250
+
251
+ :returns: A dict with mounts as the top-level keys. Each mount value is
252
+ a dict with keys 'model' (containing an instrument model name or
253
+ `None`) and 'id' (containing the serial number of the pipette
254
+ attached to that mount, or `None`). Both mounts will always be
255
+ specified.
256
+ """
257
+ return {
258
+ mount: await self._query_mount(mount, expected.get(mount))
259
+ for mount in Mount.ot2_mounts()
260
+ }
261
+
262
+ def set_active_current(self, axis_currents: Dict[Axis, float]) -> None:
263
+ """
264
+ This method sets only the 'active' current, i.e., the current for an
265
+ axis' movement. Smoothie driver automatically resets the current for
266
+ pipette axis to a low current (dwelling current) after each move
267
+ """
268
+ self._smoothie_driver.set_active_current(
269
+ {ot2_axis_to_string(axis): amp for axis, amp in axis_currents.items()}
270
+ )
271
+
272
+ @contextmanager
273
+ def save_current(self) -> Iterator[None]:
274
+ self._smoothie_driver.push_active_current()
275
+ try:
276
+ yield
277
+ finally:
278
+ self._smoothie_driver.pop_active_current()
279
+
280
+ async def _handle_watch_event(self) -> None:
281
+ try:
282
+ event = await self._event_watcher.get_event()
283
+ except asyncio.IncompleteReadError:
284
+ MODULE_LOG.debug("incomplete read error when quitting watcher")
285
+ return
286
+ if event is not None:
287
+ if "ot_module" in event.name:
288
+ event_name = event.name
289
+ flags = aionotify.Flags.parse(event.flags)
290
+ event_description = AionotifyEvent.build(event_name, flags)
291
+ await self.module_controls.handle_module_appearance(event_description)
292
+
293
+ async def watch(self, loop: asyncio.AbstractEventLoop) -> None:
294
+ can_watch = aionotify is not None
295
+ if can_watch:
296
+ await self._event_watcher.setup(loop)
297
+
298
+ while can_watch and (not self._event_watcher.closed):
299
+ await self._handle_watch_event()
300
+
301
+ async def connect(self, port: Optional[str] = None) -> None:
302
+ """Build driver and connect to it."""
303
+ await self._smoothie_driver.connect(port)
304
+ await self.update_fw_version()
305
+
306
+ @property
307
+ def axis_bounds(self) -> Dict[Axis, Tuple[float, float]]:
308
+ """The (minimum, maximum) bounds for each axis."""
309
+ return {
310
+ Axis[ax]: (0, pos)
311
+ for ax, pos in self._smoothie_driver.axis_bounds.items()
312
+ if ax not in "BC"
313
+ }
314
+
315
+ @property
316
+ def fw_version(self) -> Optional[str]:
317
+ return self._cached_fw_version
318
+
319
+ async def update_fw_version(self) -> None:
320
+ self._cached_fw_version = await self._smoothie_driver.get_fw_version()
321
+
322
+ async def update_firmware(
323
+ self, filename: str, loop: asyncio.AbstractEventLoop, modeset: bool
324
+ ) -> str:
325
+ msg = await self._smoothie_driver.update_firmware(filename, loop, modeset)
326
+ await self.update_fw_version()
327
+ return msg
328
+
329
+ def engaged_axes(self) -> Dict[str, bool]:
330
+ return self._smoothie_driver.engaged_axes
331
+
332
+ async def disengage_axes(self, axes: List[str]) -> None:
333
+ await self._smoothie_driver.disengage_axis("".join(axes))
334
+
335
+ def set_lights(self, button: Optional[bool], rails: Optional[bool]) -> None:
336
+ if button is not None:
337
+ self.gpio_chardev.set_button_light(blue=button)
338
+ if rails is not None:
339
+ self.gpio_chardev.set_rail_lights(rails)
340
+
341
+ def get_lights(self) -> Dict[str, bool]:
342
+ return {
343
+ "button": self.gpio_chardev.get_button_light()[2],
344
+ "rails": self.gpio_chardev.get_rail_lights(),
345
+ }
346
+
347
+ def pause(self) -> None:
348
+ self._smoothie_driver.pause()
349
+
350
+ def resume(self) -> None:
351
+ self._smoothie_driver.resume()
352
+
353
+ async def halt(self) -> None:
354
+ await self._smoothie_driver.kill()
355
+
356
+ async def hard_halt(self) -> None:
357
+ await self._smoothie_driver.hard_halt()
358
+
359
+ async def probe(self, axis: str, distance: float) -> Dict[str, float]:
360
+ """Run a probe and return the new position dict"""
361
+ return await self._smoothie_driver.probe_axis(axis, distance)
362
+
363
+ async def clean_up(self) -> None:
364
+ try:
365
+ loop = asyncio.get_event_loop()
366
+ except RuntimeError:
367
+ return
368
+ if hasattr(self, "_event_watcher"):
369
+ if loop.is_running() and self._event_watcher:
370
+ self._event_watcher.close()
371
+ if hasattr(self, "gpio_chardev"):
372
+ try:
373
+ if not loop.is_closed():
374
+ self.gpio_chardev.stop_door_switch_watcher(loop)
375
+ except RuntimeError:
376
+ pass
377
+
378
+ async def configure_mount(
379
+ self, mount: Mount, config: InstrumentHardwareConfigs
380
+ ) -> None:
381
+ mount_axis = Axis.by_mount(mount)
382
+ plunger_axis = Axis.of_plunger(mount)
383
+
384
+ await self._smoothie_driver.update_steps_per_mm(
385
+ {ot2_axis_to_string(plunger_axis): config["steps_per_mm"]}
386
+ )
387
+ await self._smoothie_driver.update_pipette_config(
388
+ ot2_axis_to_string(mount_axis), {"home": config["home_pos"]}
389
+ )
390
+ await self._smoothie_driver.update_pipette_config(
391
+ ot2_axis_to_string(plunger_axis), {"max_travel": config["max_travel"]}
392
+ )
393
+ self._smoothie_driver.set_dwelling_current(
394
+ {ot2_axis_to_string(plunger_axis): config["idle_current"]}
395
+ )
396
+ ms = config["splits"]
397
+ if ms:
398
+ self._smoothie_driver.configure_splits_for(
399
+ {ot2_axis_to_string(plunger_axis): ms}
400
+ )
@@ -0,0 +1,9 @@
1
+ class SubsystemUpdating(RuntimeError):
2
+ def __init__(self, msg: str) -> None:
3
+ self.msg = msg
4
+
5
+ def __repr__(self) -> str:
6
+ return f"<{self.__class__.__name__}: {self.msg}>"
7
+
8
+ def __str__(self) -> str:
9
+ return self.msg
@@ -0,0 +1,164 @@
1
+ """opentrons.hardware_control.estop_state: module to manage estop state machine on OT-3."""
2
+
3
+ from typing import List, Optional
4
+
5
+ from opentrons_hardware.hardware_control.estop.detector import (
6
+ EstopSummary,
7
+ EstopDetector,
8
+ )
9
+
10
+ from opentrons.hardware_control.types import (
11
+ EstopState,
12
+ EstopPhysicalStatus,
13
+ EstopAttachLocation,
14
+ EstopStateNotification,
15
+ HardwareEventHandler,
16
+ HardwareEventUnsubscriber,
17
+ )
18
+
19
+
20
+ class EstopStateMachine:
21
+ """Class to manage global Estop state."""
22
+
23
+ def __init__(self, detector: Optional[EstopDetector]) -> None:
24
+ """Create a new EstopStateMachine.
25
+
26
+ If detector is None, the state machine will be initialized in
27
+ a happy state (Disengaged, both estops detected) until it is
28
+ hooked up to a valid detector.
29
+ """
30
+ self._detector: Optional[EstopDetector] = None
31
+ self._state: EstopState = EstopState.DISENGAGED
32
+ # Start off in a happy state until a detector is added
33
+ self._summary = EstopSummary(
34
+ left_detected=True, right_detected=True, engaged=False
35
+ )
36
+ if detector is not None:
37
+ self.subscribe_to_detector(detector=detector)
38
+ self._listeners: List[HardwareEventHandler] = []
39
+
40
+ def subscribe_to_detector(self, detector: EstopDetector) -> None:
41
+ """Configure the estop state machine to listen to a detector.
42
+
43
+ This function will also transition the state based on the current
44
+ status of the detector."""
45
+ if self._detector is not None:
46
+ self._detector.remove_listener(self.detector_listener)
47
+ self._detector = detector
48
+ detector.add_listener(listener=self.detector_listener)
49
+ self._handle_state_transition(new_summary=detector.status)
50
+
51
+ def __del__(self) -> None:
52
+ if self._detector is not None:
53
+ self._detector.remove_listener(self.detector_listener)
54
+
55
+ def add_listener(self, listener: HardwareEventHandler) -> HardwareEventUnsubscriber:
56
+ """Add a hardware event listener for estop event changes."""
57
+ if listener not in self._listeners:
58
+ self._listeners.append(listener)
59
+ return lambda: self.remove_listener(listener)
60
+ return lambda: None
61
+
62
+ def remove_listener(self, listener: HardwareEventHandler) -> None:
63
+ """Remove an existing hardware event listener for estop detector changes."""
64
+ if listener in self._listeners:
65
+ self._listeners.remove(listener)
66
+
67
+ def detector_listener(self, summary: EstopSummary) -> None:
68
+ """Callback from the detector."""
69
+ self._handle_state_transition(new_summary=summary)
70
+
71
+ @staticmethod
72
+ def _transition_from_physically_engaged(summary: EstopSummary) -> EstopState:
73
+ if not summary.engaged:
74
+ # Estop disengaged, move to Logically Engaged
75
+ return EstopState.LOGICALLY_ENGAGED
76
+ return EstopState.PHYSICALLY_ENGAGED
77
+
78
+ @staticmethod
79
+ def _transition_from_disengaged(summary: EstopSummary) -> EstopState:
80
+ if summary.engaged:
81
+ # Estop engaged, move to physically engaged
82
+ return EstopState.PHYSICALLY_ENGAGED
83
+ if summary.left_detected or summary.right_detected:
84
+ # An estop is still plugged in, stay disengaged
85
+ return EstopState.DISENGAGED
86
+ # Everything unplugged, block all action
87
+ return EstopState.NOT_PRESENT
88
+
89
+ @staticmethod
90
+ def _transition_from_not_present(summary: EstopSummary) -> EstopState:
91
+ if summary.engaged:
92
+ # Estop plugged in and is ON, go to physically engaged
93
+ return EstopState.PHYSICALLY_ENGAGED
94
+ if summary.left_detected or summary.right_detected:
95
+ # Plugged in and NOT on, go to Disengaged
96
+ return EstopState.DISENGAGED
97
+ return EstopState.NOT_PRESENT
98
+
99
+ @staticmethod
100
+ def _transition_from_logically_engaged(summary: EstopSummary) -> EstopState:
101
+ if summary.engaged:
102
+ # Estop was turned on, go back to physically engaged
103
+ return EstopState.PHYSICALLY_ENGAGED
104
+ return EstopState.LOGICALLY_ENGAGED
105
+
106
+ def _emit_event(self, prev_state: EstopState) -> None:
107
+ """Broadcast a state change to all listeners."""
108
+ event = EstopStateNotification(old_state=prev_state, new_state=self._state)
109
+ for listener in self._listeners:
110
+ listener(event)
111
+
112
+ def _handle_state_transition(self, new_summary: EstopSummary) -> None:
113
+ """Caches the new state summary and changes the _state variable."""
114
+ self._summary = new_summary
115
+
116
+ prev_state = self._state
117
+
118
+ self._state = {
119
+ EstopState.PHYSICALLY_ENGAGED: self._transition_from_physically_engaged,
120
+ EstopState.DISENGAGED: self._transition_from_disengaged,
121
+ EstopState.NOT_PRESENT: self._transition_from_not_present,
122
+ EstopState.LOGICALLY_ENGAGED: self._transition_from_logically_engaged,
123
+ }[prev_state](new_summary)
124
+
125
+ if self._state != prev_state:
126
+ self._emit_event(prev_state=prev_state)
127
+
128
+ def get_physical_status(self, location: EstopAttachLocation) -> EstopPhysicalStatus:
129
+ """Get the physical status of an attach location"""
130
+ detected = (
131
+ self._summary.left_detected
132
+ if location == EstopAttachLocation.LEFT
133
+ else self._summary.right_detected
134
+ )
135
+
136
+ if not detected:
137
+ return EstopPhysicalStatus.NOT_PRESENT
138
+ # Note that we actually *don't* have a way to check if an individual
139
+ # estop is activated or not. But we can return Engaged or Disengaged
140
+ # based on the global state.
141
+ return (
142
+ EstopPhysicalStatus.ENGAGED
143
+ if self._summary.engaged
144
+ else EstopPhysicalStatus.DISENGAGED
145
+ )
146
+
147
+ @property
148
+ def state(self) -> EstopState:
149
+ return self._state
150
+
151
+ def acknowledge_and_clear(self) -> EstopState:
152
+ """Acknowledge a `logically_engaged` status if relevant.
153
+
154
+ If the current state is not LOGICALLY_ENGAGED, this does nothing.
155
+
156
+ If the current state *is* LOGICALLY_ENGAGED, this will move to the
157
+ correct return state (NOT_PRESENT or ENGAGED)"""
158
+ if self._state == EstopState.LOGICALLY_ENGAGED:
159
+ if self._summary.left_detected or self._summary.right_detected:
160
+ self._state = EstopState.DISENGAGED
161
+ else:
162
+ self._state = EstopState.NOT_PRESENT
163
+ self._emit_event(EstopState.LOGICALLY_ENGAGED)
164
+ return self._state