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,442 @@
1
+ from __future__ import annotations
2
+ import asyncio
3
+ import copy
4
+ import logging
5
+ from threading import Event
6
+ from typing import Dict, Optional, List, Tuple, TYPE_CHECKING, Sequence, Iterator, cast
7
+ from contextlib import contextmanager
8
+
9
+ from opentrons_shared_data.pipette import (
10
+ pipette_load_name_conversions as pipette_load_name,
11
+ mutable_configurations,
12
+ pipette_definition,
13
+ )
14
+
15
+ from opentrons import types
16
+ from opentrons.config.types import RobotConfig
17
+ from opentrons.config import get_opentrons_path
18
+ from opentrons.drivers.smoothie_drivers import SimulatingDriver
19
+
20
+ from opentrons.drivers.rpi_drivers.gpio_simulator import SimulatingGPIOCharDev
21
+ from opentrons.util.async_helpers import ensure_yield
22
+
23
+ from .. import modules
24
+ from ..types import BoardRevision, Axis
25
+ from ..module_control import AttachedModulesControl
26
+ from ..util import ot2_axis_to_string
27
+
28
+ if TYPE_CHECKING:
29
+ from opentrons_shared_data.pipette.types import PipetteName, PipetteModel
30
+ from ..dev_types import (
31
+ AttachedPipette,
32
+ AttachedInstruments,
33
+ PipetteSpec,
34
+ InstrumentHardwareConfigs,
35
+ )
36
+ from opentrons.drivers.rpi_drivers.dev_types import GPIODriverLike
37
+
38
+
39
+ MODULE_LOG = logging.getLogger(__name__)
40
+
41
+
42
+ class Simulator:
43
+ """This is a subclass of hardware_control that only simulates the
44
+ hardware actions. It is suitable for use on a dev machine or on
45
+ a robot with no smoothie connected.
46
+ """
47
+
48
+ @classmethod
49
+ async def build(
50
+ cls,
51
+ attached_instruments: Dict[types.Mount, Dict[str, Optional[str]]],
52
+ attached_modules: Dict[str, List[modules.SimulatingModule]],
53
+ config: RobotConfig,
54
+ loop: asyncio.AbstractEventLoop,
55
+ strict_attached_instruments: bool = True,
56
+ ) -> Simulator:
57
+ """Build the simulator.
58
+
59
+ Use this factory method rather than the initializer to handle proper GPIO
60
+ initialization.
61
+
62
+ :param attached_instruments: A dictionary describing the instruments
63
+ the simulator should consider attached.
64
+ If this argument is specified and
65
+ :py:meth:`get_attached_instruments` is
66
+ called with expectations that do not
67
+ match, the call fails. This is useful for
68
+ making the simulator match the real
69
+ hardware, for instance to check if a
70
+ protocol asks for the right instruments.
71
+ This dict should map mounts to either
72
+ empty dicts or to dicts containing
73
+ 'model' and 'id' keys.
74
+ :param attached_modules: A map of module type names (e.g.
75
+ `'tempdeck'` or `'magdeck'`) to lists of SimulatingModel
76
+ dataclasses representing
77
+ modules the simulator should assume are
78
+ attached. Like `attached_instruments`, used
79
+ to make the simulator match the setup of the
80
+ real hardware.
81
+ :param config: The robot config to use
82
+ :param loop: The asyncio event loop to use.
83
+ :param strict_attached_instruments: This param changes the behavior of
84
+ the instrument cache. If ``True``,
85
+ (default), ``cache_instrument``
86
+ calls requesting instruments not
87
+ in ``attached_instruments`` will
88
+ fail as if the instrument was not
89
+ present. If ``False``, those calls
90
+ will still pass but give a response
91
+ version of 1, while calls
92
+ requesting instruments that _are_
93
+ present get the full number.
94
+ """
95
+ gpio = SimulatingGPIOCharDev("gpiochip0")
96
+ await gpio.setup()
97
+ return cls(
98
+ attached_instruments,
99
+ attached_modules,
100
+ config,
101
+ loop,
102
+ gpio,
103
+ strict_attached_instruments,
104
+ )
105
+
106
+ def __init__(
107
+ self,
108
+ attached_instruments: Dict[types.Mount, Dict[str, Optional[str]]],
109
+ attached_modules: Dict[str, List[modules.SimulatingModule]],
110
+ config: RobotConfig,
111
+ loop: asyncio.AbstractEventLoop,
112
+ gpio_chardev: GPIODriverLike,
113
+ strict_attached_instruments: bool = True,
114
+ ) -> None:
115
+ """Initialize the simulator.
116
+
117
+ Always prefer using :py:meth:`.build` to create an instance of this class. For
118
+ more information on arguments, see that method. If you want to use this
119
+ directly, you must pass in an initialized _and set up_ GPIO driver instance.
120
+ """
121
+ self.config = config
122
+ self._loop = loop
123
+ self._smoothie_driver = SimulatingDriver()
124
+ self._gpio_chardev = gpio_chardev
125
+
126
+ def _sanitize_attached_instrument(
127
+ passed_ai: Optional[PipetteSpec] = None,
128
+ ) -> PipetteSpec:
129
+ if not passed_ai or not passed_ai.get("model"):
130
+ return {"model": None, "id": None}
131
+ if pipette_load_name.supported_pipette(
132
+ cast("PipetteName", passed_ai["model"])
133
+ ):
134
+ if pipette_load_name.is_model(passed_ai["model"]):
135
+ return passed_ai
136
+ else:
137
+ get_pip_model = pipette_load_name.convert_pipette_name(
138
+ cast("PipetteName", passed_ai["model"])
139
+ )
140
+ return {
141
+ "model": PipetteModel(str(get_pip_model)),
142
+ "id": passed_ai.get("id"),
143
+ }
144
+ raise KeyError(
145
+ "If you specify attached_instruments, the model "
146
+ "should be pipette names or pipette models, but "
147
+ f'{passed_ai["model"]} is not'
148
+ )
149
+
150
+ self._attached_instruments = {
151
+ m: _sanitize_attached_instrument(attached_instruments.get(m)) # type: ignore
152
+ for m in types.Mount.ot2_mounts()
153
+ }
154
+ self._stubbed_attached_modules = attached_modules
155
+ self._position = copy.copy(self._smoothie_driver.homed_position)
156
+ # Engaged axes start all true in smoothie for some reason so we
157
+ # imitate that here
158
+ # TODO(LC2642019) Create a simulating driver for smoothie instead of
159
+ # using a flag
160
+
161
+ self._engaged_axes = {ax: True for ax in self._smoothie_driver.homed_position}
162
+ self._lights = {"button": False, "rails": False}
163
+ self._run_flag = Event()
164
+ self._run_flag.set()
165
+ self._log = MODULE_LOG.getChild(repr(self))
166
+ self._strict_attached = bool(strict_attached_instruments)
167
+ self._board_revision = BoardRevision.OG
168
+ # TODO (lc 05-12-2021) In a follow-up refactor that pulls the execution
169
+ # manager responsbility into the controller/backend itself as opposed
170
+ # to the hardware api controller.
171
+ self._module_controls: Optional[AttachedModulesControl] = None
172
+
173
+ async def get_serial_number(self) -> Optional[str]:
174
+ return "simulator"
175
+
176
+ @property
177
+ def gpio_chardev(self) -> GPIODriverLike:
178
+ return self._gpio_chardev
179
+
180
+ @property
181
+ def module_controls(self) -> AttachedModulesControl:
182
+ if not self._module_controls:
183
+ raise AttributeError("Module controls not found.")
184
+ return self._module_controls
185
+
186
+ @module_controls.setter
187
+ def module_controls(self, module_controls: AttachedModulesControl) -> None:
188
+ self._module_controls = module_controls
189
+
190
+ @ensure_yield
191
+ async def update_position(self) -> Dict[str, float]:
192
+ return self._position
193
+
194
+ def _unhomed_axes(self, axes: Sequence[str]) -> List[str]:
195
+ return list(
196
+ axis
197
+ for axis in axes
198
+ if not self._smoothie_driver.homed_flags.get(axis, False)
199
+ )
200
+
201
+ def is_homed(self, axes: Sequence[str]) -> bool:
202
+ return not any(self._unhomed_axes(axes))
203
+
204
+ @ensure_yield
205
+ async def move(
206
+ self,
207
+ target_position: Dict[str, float],
208
+ home_flagged_axes: bool = True,
209
+ speed: Optional[float] = None,
210
+ axis_max_speeds: Optional[Dict[str, float]] = None,
211
+ ) -> None:
212
+ self._position.update(target_position)
213
+ self._engaged_axes.update({ax: True for ax in target_position})
214
+
215
+ @ensure_yield
216
+ async def home(self, axes: Optional[List[str]] = None) -> Dict[str, float]:
217
+ # driver_3_0-> HOMED_POSITION
218
+ checked_axes = "".join(axes) if axes else "XYZABC"
219
+ self._position.update(
220
+ {ax: self._smoothie_driver.homed_position[ax] for ax in checked_axes}
221
+ )
222
+ self._engaged_axes.update({ax: True for ax in checked_axes})
223
+ await self._smoothie_driver.home(axis=checked_axes)
224
+ return self._position
225
+
226
+ @ensure_yield
227
+ async def fast_home(self, axis: Sequence[str], margin: float) -> Dict[str, float]:
228
+ for ax in axis:
229
+ self._position[ax] = self._smoothie_driver.homed_position[ax]
230
+ self._engaged_axes[ax] = True
231
+ return self._position
232
+
233
+ def _attached_to_mount(
234
+ self, mount: types.Mount, expected_instr: Optional["PipetteName"]
235
+ ) -> AttachedPipette:
236
+ init_instr = self._attached_instruments.get(mount, {"model": None, "id": None})
237
+ found_model = init_instr["model"]
238
+ back_compat: List["PipetteName"] = []
239
+
240
+ path_to_overrides = get_opentrons_path("pipette_config_overrides_dir")
241
+ found_model_configs: Optional[pipette_definition.PipetteConfigurations] = None
242
+
243
+ converted_found_name: Optional[pipette_definition.PipetteNameType] = None
244
+ if found_model:
245
+ converted_found_model = pipette_load_name.convert_pipette_model(found_model)
246
+ converted_found_name = pipette_load_name.convert_to_pipette_name_type(
247
+ found_model
248
+ )
249
+ found_model_configs = (
250
+ mutable_configurations.load_with_mutable_configurations(
251
+ converted_found_model, path_to_overrides, init_instr["id"]
252
+ )
253
+ )
254
+ back_compat = found_model_configs.pipette_backcompat_names
255
+ if (
256
+ expected_instr
257
+ and found_model
258
+ and found_model_configs
259
+ and (
260
+ str(converted_found_name) != expected_instr
261
+ and expected_instr not in back_compat
262
+ )
263
+ ):
264
+ if self._strict_attached:
265
+ raise RuntimeError(
266
+ "mount {}: expected instrument {} but got {}".format(
267
+ mount.name, expected_instr, found_model
268
+ )
269
+ )
270
+ else:
271
+ converted_expected_model = pipette_load_name.convert_pipette_name(
272
+ expected_instr
273
+ )
274
+ return {
275
+ "config": mutable_configurations.load_with_mutable_configurations(
276
+ converted_expected_model, path_to_overrides
277
+ ),
278
+ "id": None,
279
+ }
280
+ elif found_model and found_model_configs:
281
+ # Instrument detected matches instrument expected (note:
282
+ # "instrument detected" means passed as an argument to the
283
+ # constructor of this class) OR,
284
+ # Instrument detected and no expected instrument specified
285
+ return {
286
+ "config": found_model_configs,
287
+ "id": init_instr["id"],
288
+ }
289
+ elif expected_instr:
290
+ # Expected instrument specified and no instrument detected
291
+ converted_expected_model = pipette_load_name.convert_pipette_name(
292
+ expected_instr
293
+ )
294
+ return {
295
+ "config": mutable_configurations.load_with_mutable_configurations(
296
+ converted_expected_model, path_to_overrides
297
+ ),
298
+ "id": None,
299
+ }
300
+ else:
301
+ # No instrument detected or expected
302
+ return {"config": None, "id": None}
303
+
304
+ @ensure_yield
305
+ async def get_attached_instruments(
306
+ self, expected: Dict[types.Mount, "PipetteName"]
307
+ ) -> AttachedInstruments:
308
+ """Update the internal cache of attached instruments.
309
+
310
+ This method allows after-init-time specification of attached simulated
311
+ instruments. The method will return
312
+ - the instruments specified at init-time, or if those do not exists,
313
+ - the instruments specified in expected, or if that is not passed,
314
+ - nothing
315
+
316
+ :param expected: A mapping of mount to instrument model prefixes. When
317
+ loading instruments from a prefix, we return the
318
+ lexically-first model that matches the prefix. If the
319
+ models specified in expected do not match the models
320
+ specified in the `attached_instruments` argument of
321
+ :py:meth:`__init__`, :py:attr:`RuntimeError` is
322
+ raised.
323
+ :raises RuntimeError: If an instrument is expected but not found.
324
+ :returns: A dict of mount to either instrument model names or `None`.
325
+ """
326
+ return {
327
+ mount: self._attached_to_mount(mount, expected.get(mount))
328
+ for mount in types.Mount.ot2_mounts()
329
+ }
330
+
331
+ def set_active_current(self, axis_currents: Dict[Axis, float]) -> None:
332
+ pass
333
+
334
+ @ensure_yield
335
+ async def watch(self) -> None:
336
+ new_mods_at_ports = []
337
+ for mod_name, list_of_modules in self._stubbed_attached_modules.items():
338
+ for module_details in list_of_modules:
339
+ new_mods_at_ports.append(
340
+ modules.SimulatingModuleAtPort(
341
+ port=f"/dev/ot_module_sim_{mod_name}{str(module_details.serial_number)}",
342
+ name=mod_name,
343
+ serial_number=module_details.serial_number,
344
+ model=module_details.model,
345
+ )
346
+ )
347
+ await self.module_controls.register_modules(new_mods_at_ports=new_mods_at_ports)
348
+
349
+ @contextmanager
350
+ def save_current(self) -> Iterator[None]:
351
+ yield
352
+
353
+ @property
354
+ def axis_bounds(self) -> Dict[Axis, Tuple[float, float]]:
355
+ """The (minimum, maximum) bounds for each axis."""
356
+ return {
357
+ Axis[ax]: (0, pos)
358
+ for ax, pos in self._smoothie_driver.axis_bounds.items()
359
+ if ax not in "BC"
360
+ }
361
+
362
+ @property
363
+ def fw_version(self) -> Optional[str]:
364
+ return "Virtual Smoothie"
365
+
366
+ @ensure_yield
367
+ async def update_fw_version(self) -> None:
368
+ pass
369
+
370
+ @property
371
+ def board_revision(self) -> BoardRevision:
372
+ return self._board_revision
373
+
374
+ @ensure_yield
375
+ async def update_firmware(
376
+ self, filename: str, loop: asyncio.AbstractEventLoop, modeset: bool
377
+ ) -> str:
378
+ return "Did nothing (simulating)"
379
+
380
+ def engaged_axes(self) -> Dict[str, bool]:
381
+ return self._engaged_axes
382
+
383
+ @ensure_yield
384
+ async def disengage_axes(self, axes: List[str]) -> None:
385
+ self._engaged_axes.update({ax: False for ax in axes})
386
+
387
+ def set_lights(self, button: Optional[bool], rails: Optional[bool]) -> None:
388
+ if button is not None:
389
+ self._lights["button"] = button
390
+ if rails is not None:
391
+ self._lights["rails"] = rails
392
+
393
+ def get_lights(self) -> Dict[str, bool]:
394
+ return self._lights
395
+
396
+ def pause(self) -> None:
397
+ self._run_flag.clear()
398
+
399
+ def resume(self) -> None:
400
+ self._run_flag.set()
401
+
402
+ @ensure_yield
403
+ async def halt(self) -> None:
404
+ self._run_flag.set()
405
+
406
+ @ensure_yield
407
+ async def hard_halt(self) -> None:
408
+ self._run_flag.set()
409
+
410
+ @ensure_yield
411
+ async def probe(self, axis: str, distance: float) -> Dict[str, float]:
412
+ self._position[axis.upper()] = self._position[axis.upper()] + distance
413
+ return self._position
414
+
415
+ @ensure_yield
416
+ async def clean_up(self) -> None:
417
+ pass
418
+
419
+ @ensure_yield
420
+ async def configure_mount(
421
+ self, mount: types.Mount, config: InstrumentHardwareConfigs
422
+ ) -> None:
423
+ mount_axis = Axis.by_mount(mount)
424
+ plunger_axis = Axis.of_plunger(mount)
425
+
426
+ await self._smoothie_driver.update_steps_per_mm(
427
+ {ot2_axis_to_string(plunger_axis): config["steps_per_mm"]}
428
+ )
429
+ await self._smoothie_driver.update_pipette_config(
430
+ ot2_axis_to_string(mount_axis), {"home": config["home_pos"]}
431
+ )
432
+ await self._smoothie_driver.update_pipette_config(
433
+ ot2_axis_to_string(plunger_axis), {"max_travel": config["max_travel"]}
434
+ )
435
+ self._smoothie_driver.set_dwelling_current(
436
+ {ot2_axis_to_string(plunger_axis): config["idle_current"]}
437
+ )
438
+ ms = config["splits"]
439
+ if ms:
440
+ self._smoothie_driver.configure_splits_for(
441
+ {ot2_axis_to_string(plunger_axis): ms}
442
+ )
@@ -0,0 +1,240 @@
1
+ from opentrons.hardware_control.types import (
2
+ StatusBarState,
3
+ StatusBarUpdateEvent,
4
+ StatusBarUpdateListener,
5
+ StatusBarUpdateUnsubscriber,
6
+ )
7
+ from opentrons_hardware.hardware_control import status_bar
8
+ from opentrons_hardware.firmware_bindings.binary_constants import (
9
+ LightAnimationType,
10
+ LightTransitionType,
11
+ )
12
+
13
+ from typing import List
14
+
15
+
16
+ class StatusBarStateController:
17
+ """Stateful control of the status bar.
18
+
19
+ Note that the controller can be enabled/disabled at any time. If the controller
20
+ is ever disabled, the lights are set to OFF and future state changes will not
21
+ write to the rear panel board. However, the proper `StatusBarState` will still
22
+ be cached, so if the controller becomes enabled/disabled in the future it will
23
+ be able to resume the correct animation based on the current system state."""
24
+
25
+ def __init__(self, controller: status_bar.StatusBar) -> None:
26
+ """Create a StatusBarStateController."""
27
+ self._status_bar_state = StatusBarState.IDLE
28
+ self._controller = controller
29
+ self._enabled = True
30
+ self._listeners: List[StatusBarUpdateListener] = []
31
+
32
+ def add_listener(
33
+ self, listener: StatusBarUpdateListener
34
+ ) -> StatusBarUpdateUnsubscriber:
35
+ """Add a listener to the status bar state."""
36
+ if listener not in self._listeners:
37
+ self._listeners.append(listener)
38
+
39
+ def _remove_listener() -> None:
40
+ self._listeners.remove(listener)
41
+
42
+ return _remove_listener
43
+
44
+ def emit_event(self) -> None:
45
+ """Emit an event to all listeners."""
46
+ for listener in self._listeners:
47
+ listener(StatusBarUpdateEvent(self._status_bar_state, self._enabled))
48
+
49
+ async def _status_bar_idle(self) -> None:
50
+ self._status_bar_state = StatusBarState.IDLE
51
+ if self._enabled:
52
+ await self._controller.static_color(status_bar.WHITE)
53
+
54
+ async def _status_bar_running(self) -> None:
55
+ self._status_bar_state = StatusBarState.RUNNING
56
+ if self._enabled:
57
+ await self._controller.static_color(status_bar.GREEN)
58
+
59
+ async def _status_bar_paused(self) -> None:
60
+ self._status_bar_state = StatusBarState.PAUSED
61
+ if self._enabled:
62
+ await self._controller.pulse_color(status_bar.BLUE)
63
+
64
+ async def _status_bar_hardware_error(self) -> None:
65
+ self._status_bar_state = StatusBarState.HARDWARE_ERROR
66
+ if self._enabled:
67
+ await self._controller.flash_color(status_bar.RED)
68
+
69
+ async def _status_bar_software_error(self) -> None:
70
+ self._status_bar_state = StatusBarState.SOFTWARE_ERROR
71
+ if self._enabled:
72
+ await self._controller.static_color(status_bar.YELLOW)
73
+
74
+ async def _status_bar_error_recovery(self) -> None:
75
+ self._status_bar_state = StatusBarState.ERROR_RECOVERY
76
+ if self._enabled:
77
+ await self._controller.pulse_color(status_bar.YELLOW)
78
+
79
+ async def _status_bar_confirm(self) -> None:
80
+ # Confirm should revert to IDLE
81
+ self._status_bar_state = StatusBarState.IDLE
82
+ if self._enabled:
83
+ await self._controller.blink_once(status_bar.GREEN, status_bar.WHITE)
84
+
85
+ async def _status_bar_run_complete(self) -> None:
86
+ self._status_bar_state = StatusBarState.RUN_COMPLETED
87
+ if self._enabled:
88
+ await self._controller.pulse_color(status_bar.GREEN)
89
+
90
+ async def _status_bar_updating(self) -> None:
91
+ self._status_bar_state = StatusBarState.UPDATING
92
+ if self._enabled:
93
+ await self._controller.pulse_color(status_bar.WHITE)
94
+
95
+ async def _status_bar_activation(self) -> None:
96
+ # Activation should revert to IDLE
97
+ self._status_bar_state = StatusBarState.IDLE
98
+
99
+ # This animation uses an intermediate color between the blue and the white.
100
+ # This results in a sort of light-blue effect.
101
+ steps: List[status_bar.ColorStep] = [
102
+ status_bar.ColorStep(LightTransitionType.linear, 250, status_bar.OFF),
103
+ status_bar.ColorStep(LightTransitionType.linear, 750, status_bar.OFF),
104
+ status_bar.ColorStep(LightTransitionType.linear, 1000, status_bar.BLUE),
105
+ status_bar.ColorStep(
106
+ LightTransitionType.linear,
107
+ 250,
108
+ status_bar.Color(
109
+ r=0,
110
+ g=int(status_bar.BLUE.g * 0.75),
111
+ b=int(status_bar.BLUE.b * 0.75),
112
+ w=50,
113
+ ),
114
+ ),
115
+ status_bar.ColorStep(LightTransitionType.linear, 250, status_bar.WHITE),
116
+ ]
117
+
118
+ if self._enabled:
119
+ await self._controller.start_animation(
120
+ steps=steps, type=LightAnimationType.single_shot
121
+ )
122
+
123
+ async def _status_bar_disco(self) -> None:
124
+ # TODO - update implementation
125
+ colors = [
126
+ status_bar.GREEN,
127
+ status_bar.YELLOW,
128
+ status_bar.PURPLE,
129
+ status_bar.ORANGE,
130
+ status_bar.GREEN,
131
+ status_bar.YELLOW,
132
+ status_bar.PURPLE,
133
+ status_bar.ORANGE,
134
+ status_bar.WHITE,
135
+ ]
136
+ steps: List[status_bar.ColorStep] = [
137
+ status_bar.ColorStep(LightTransitionType.linear, 300, color)
138
+ for color in colors
139
+ ]
140
+ steps.append(
141
+ status_bar.ColorStep(LightTransitionType.linear, 500, status_bar.OFF)
142
+ )
143
+ steps.append(
144
+ status_bar.ColorStep(LightTransitionType.linear, 75, status_bar.BLUE)
145
+ )
146
+ steps.append(
147
+ status_bar.ColorStep(
148
+ LightTransitionType.instant,
149
+ transition_time_ms=150,
150
+ color=status_bar.GREEN,
151
+ )
152
+ )
153
+ steps.append(
154
+ status_bar.ColorStep(
155
+ LightTransitionType.instant,
156
+ transition_time_ms=150,
157
+ color=status_bar.OFF,
158
+ )
159
+ )
160
+ steps.append(
161
+ status_bar.ColorStep(
162
+ LightTransitionType.instant,
163
+ transition_time_ms=150,
164
+ color=status_bar.GREEN,
165
+ )
166
+ )
167
+ steps.append(
168
+ status_bar.ColorStep(
169
+ LightTransitionType.linear,
170
+ transition_time_ms=1000,
171
+ color=status_bar.WHITE,
172
+ )
173
+ )
174
+
175
+ self._status_bar_state = StatusBarState.IDLE
176
+ if self._enabled:
177
+ await self._controller.start_animation(
178
+ steps=steps, type=LightAnimationType.single_shot
179
+ )
180
+
181
+ async def _status_bar_off(self) -> None:
182
+ self._status_bar_state = StatusBarState.OFF
183
+ if self._enabled:
184
+ await self._controller.static_color(status_bar.OFF)
185
+
186
+ async def set_status_bar_state(self, state: StatusBarState) -> None:
187
+ """Main interface to set a new state."""
188
+ callbacks = {
189
+ StatusBarState.IDLE: self._status_bar_idle,
190
+ StatusBarState.RUNNING: self._status_bar_running,
191
+ StatusBarState.PAUSED: self._status_bar_paused,
192
+ StatusBarState.HARDWARE_ERROR: self._status_bar_hardware_error,
193
+ StatusBarState.SOFTWARE_ERROR: self._status_bar_software_error,
194
+ StatusBarState.ERROR_RECOVERY: self._status_bar_error_recovery,
195
+ StatusBarState.CONFIRMATION: self._status_bar_confirm,
196
+ StatusBarState.RUN_COMPLETED: self._status_bar_run_complete,
197
+ StatusBarState.UPDATING: self._status_bar_updating,
198
+ StatusBarState.ACTIVATION: self._status_bar_activation,
199
+ StatusBarState.DISCO: self._status_bar_disco,
200
+ StatusBarState.OFF: self._status_bar_off,
201
+ }
202
+ await callbacks[state]()
203
+ self.emit_event()
204
+
205
+ def get_current_state(self) -> StatusBarState:
206
+ """Get the current state."""
207
+ return self._status_bar_state
208
+
209
+ async def set_enabled(self, enabled: bool) -> None:
210
+ """Enable or disable the status bar.
211
+
212
+ If the status bar is newly disabled, the lights are set OFF
213
+ and the old status is cached so it can later be restored.
214
+
215
+ If the status bar is newly enabled, the last-set animation
216
+ will be sent to the rear panel.
217
+
218
+ NOTE When the status bar is disabled, `set_status_bar_state` will
219
+ still update the internal status bar setting as if the bar is on!
220
+ This means that, when the status bar is reenabled, it will look
221
+ correct for the current robot status."""
222
+ if enabled == self._enabled:
223
+ return
224
+
225
+ if enabled:
226
+ # Need to turn Enabled true *first* so that we can actually write
227
+ # the setting to the rear panel
228
+ self._enabled = True
229
+ await self.set_status_bar_state(self._status_bar_state)
230
+ else:
231
+ cached_state = self.get_current_state()
232
+ await self.set_status_bar_state(StatusBarState.OFF)
233
+ self._enabled = False
234
+ # This ensures that the status bar will be set to the correct state
235
+ # if it's reactivated before the state gets set again.
236
+ self._status_bar_state = cached_state
237
+
238
+ def get_enabled(self) -> bool:
239
+ """Check whether the status bar is enabled."""
240
+ return self._enabled