opentrons 8.6.0__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 (601) 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 +557 -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 +187 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +557 -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/scripts/update_module_fw.py +274 -0
  200. opentrons/hardware_control/simulator_setup.py +260 -0
  201. opentrons/hardware_control/thread_manager.py +431 -0
  202. opentrons/hardware_control/threaded_async_lock.py +97 -0
  203. opentrons/hardware_control/types.py +792 -0
  204. opentrons/hardware_control/util.py +234 -0
  205. opentrons/legacy_broker.py +53 -0
  206. opentrons/legacy_commands/__init__.py +1 -0
  207. opentrons/legacy_commands/commands.py +483 -0
  208. opentrons/legacy_commands/helpers.py +153 -0
  209. opentrons/legacy_commands/module_commands.py +276 -0
  210. opentrons/legacy_commands/protocol_commands.py +54 -0
  211. opentrons/legacy_commands/publisher.py +155 -0
  212. opentrons/legacy_commands/robot_commands.py +51 -0
  213. opentrons/legacy_commands/types.py +1186 -0
  214. opentrons/motion_planning/__init__.py +32 -0
  215. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  216. opentrons/motion_planning/deck_conflict.py +501 -0
  217. opentrons/motion_planning/errors.py +35 -0
  218. opentrons/motion_planning/types.py +42 -0
  219. opentrons/motion_planning/waypoints.py +218 -0
  220. opentrons/ordered_set.py +138 -0
  221. opentrons/protocol_api/__init__.py +105 -0
  222. opentrons/protocol_api/_liquid.py +157 -0
  223. opentrons/protocol_api/_liquid_properties.py +814 -0
  224. opentrons/protocol_api/_nozzle_layout.py +31 -0
  225. opentrons/protocol_api/_parameter_context.py +300 -0
  226. opentrons/protocol_api/_parameters.py +31 -0
  227. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  228. opentrons/protocol_api/_types.py +43 -0
  229. opentrons/protocol_api/config.py +23 -0
  230. opentrons/protocol_api/core/__init__.py +23 -0
  231. opentrons/protocol_api/core/common.py +33 -0
  232. opentrons/protocol_api/core/core_map.py +74 -0
  233. opentrons/protocol_api/core/engine/__init__.py +22 -0
  234. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  235. opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
  236. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  237. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  238. opentrons/protocol_api/core/engine/labware.py +238 -0
  239. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  240. opentrons/protocol_api/core/engine/module_core.py +1027 -0
  241. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  242. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  243. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  244. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  245. opentrons/protocol_api/core/engine/robot.py +139 -0
  246. opentrons/protocol_api/core/engine/stringify.py +74 -0
  247. opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
  248. opentrons/protocol_api/core/engine/well.py +241 -0
  249. opentrons/protocol_api/core/instrument.py +459 -0
  250. opentrons/protocol_api/core/labware.py +151 -0
  251. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  252. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  253. opentrons/protocol_api/core/legacy/deck.py +369 -0
  254. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  255. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  256. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  257. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  258. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  259. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  260. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  261. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  262. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  263. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  265. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  266. opentrons/protocol_api/core/module.py +484 -0
  267. opentrons/protocol_api/core/protocol.py +311 -0
  268. opentrons/protocol_api/core/robot.py +51 -0
  269. opentrons/protocol_api/core/well.py +116 -0
  270. opentrons/protocol_api/core/well_grid.py +45 -0
  271. opentrons/protocol_api/create_protocol_context.py +177 -0
  272. opentrons/protocol_api/deck.py +223 -0
  273. opentrons/protocol_api/disposal_locations.py +244 -0
  274. opentrons/protocol_api/instrument_context.py +3272 -0
  275. opentrons/protocol_api/labware.py +1579 -0
  276. opentrons/protocol_api/module_contexts.py +1447 -0
  277. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  278. opentrons/protocol_api/protocol_context.py +1688 -0
  279. opentrons/protocol_api/robot_context.py +303 -0
  280. opentrons/protocol_api/validation.py +761 -0
  281. opentrons/protocol_engine/__init__.py +155 -0
  282. opentrons/protocol_engine/actions/__init__.py +65 -0
  283. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  284. opentrons/protocol_engine/actions/action_handler.py +13 -0
  285. opentrons/protocol_engine/actions/actions.py +302 -0
  286. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  287. opentrons/protocol_engine/clients/__init__.py +5 -0
  288. opentrons/protocol_engine/clients/sync_client.py +174 -0
  289. opentrons/protocol_engine/clients/transports.py +197 -0
  290. opentrons/protocol_engine/commands/__init__.py +757 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  296. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  297. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  298. opentrons/protocol_engine/commands/aspirate.py +244 -0
  299. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  300. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  301. opentrons/protocol_engine/commands/blow_out.py +146 -0
  302. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  303. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  306. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  307. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  308. opentrons/protocol_engine/commands/command.py +308 -0
  309. opentrons/protocol_engine/commands/command_unions.py +974 -0
  310. opentrons/protocol_engine/commands/comment.py +57 -0
  311. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  312. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  313. opentrons/protocol_engine/commands/custom.py +67 -0
  314. opentrons/protocol_engine/commands/dispense.py +194 -0
  315. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  316. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  317. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  318. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  319. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  320. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  321. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  322. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  323. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  324. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  325. opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
  326. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  327. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  328. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  329. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  330. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  331. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  333. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  334. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  336. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  337. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  338. opentrons/protocol_engine/commands/home.py +100 -0
  339. opentrons/protocol_engine/commands/identify_module.py +86 -0
  340. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  341. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  342. opentrons/protocol_engine/commands/load_labware.py +210 -0
  343. opentrons/protocol_engine/commands/load_lid.py +154 -0
  344. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  345. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  346. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  347. opentrons/protocol_engine/commands/load_module.py +223 -0
  348. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  349. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  350. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  351. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  352. opentrons/protocol_engine/commands/move_labware.py +546 -0
  353. opentrons/protocol_engine/commands/move_relative.py +102 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  355. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  356. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  357. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  358. opentrons/protocol_engine/commands/movement_common.py +338 -0
  359. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  360. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  361. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  362. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  363. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  364. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  365. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  366. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  367. opentrons/protocol_engine/commands/robot/common.py +18 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  369. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  370. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  371. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  372. opentrons/protocol_engine/commands/save_position.py +109 -0
  373. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  374. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  375. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  376. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  377. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  378. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  379. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  380. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  381. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  384. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  386. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  388. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  390. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  391. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  392. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  401. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  402. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  403. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  404. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  405. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  406. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  407. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  408. opentrons/protocol_engine/engine_support.py +28 -0
  409. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  410. opentrons/protocol_engine/errors/__init__.py +191 -0
  411. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  412. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  413. opentrons/protocol_engine/execution/__init__.py +50 -0
  414. opentrons/protocol_engine/execution/command_executor.py +216 -0
  415. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  416. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  417. opentrons/protocol_engine/execution/equipment.py +819 -0
  418. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  419. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  420. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  421. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  422. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  423. opentrons/protocol_engine/execution/movement.py +350 -0
  424. opentrons/protocol_engine/execution/pipetting.py +607 -0
  425. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  426. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  427. opentrons/protocol_engine/execution/run_control.py +33 -0
  428. opentrons/protocol_engine/execution/status_bar.py +34 -0
  429. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  430. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  431. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  432. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  433. opentrons/protocol_engine/notes/__init__.py +17 -0
  434. opentrons/protocol_engine/notes/notes.py +59 -0
  435. opentrons/protocol_engine/plugins.py +104 -0
  436. opentrons/protocol_engine/protocol_engine.py +683 -0
  437. opentrons/protocol_engine/resources/__init__.py +26 -0
  438. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  439. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  440. opentrons/protocol_engine/resources/file_provider.py +161 -0
  441. opentrons/protocol_engine/resources/fixture_validation.py +68 -0
  442. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  443. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  444. opentrons/protocol_engine/resources/model_utils.py +32 -0
  445. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  446. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  447. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  448. opentrons/protocol_engine/slot_standardization.py +128 -0
  449. opentrons/protocol_engine/state/__init__.py +1 -0
  450. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  451. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  452. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  453. opentrons/protocol_engine/state/_move_types.py +83 -0
  454. opentrons/protocol_engine/state/_well_math.py +193 -0
  455. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  456. opentrons/protocol_engine/state/command_history.py +309 -0
  457. opentrons/protocol_engine/state/commands.py +1164 -0
  458. opentrons/protocol_engine/state/config.py +39 -0
  459. opentrons/protocol_engine/state/files.py +57 -0
  460. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  461. opentrons/protocol_engine/state/geometry.py +2408 -0
  462. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  463. opentrons/protocol_engine/state/labware.py +1432 -0
  464. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  465. opentrons/protocol_engine/state/liquids.py +73 -0
  466. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  467. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  468. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  469. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  471. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  472. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  473. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  474. opentrons/protocol_engine/state/modules.py +1515 -0
  475. opentrons/protocol_engine/state/motion.py +373 -0
  476. opentrons/protocol_engine/state/pipettes.py +905 -0
  477. opentrons/protocol_engine/state/state.py +421 -0
  478. opentrons/protocol_engine/state/state_summary.py +36 -0
  479. opentrons/protocol_engine/state/tips.py +420 -0
  480. opentrons/protocol_engine/state/update_types.py +904 -0
  481. opentrons/protocol_engine/state/wells.py +290 -0
  482. opentrons/protocol_engine/types/__init__.py +310 -0
  483. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  484. opentrons/protocol_engine/types/command_annotations.py +53 -0
  485. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  486. opentrons/protocol_engine/types/execution.py +96 -0
  487. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  488. opentrons/protocol_engine/types/instrument.py +47 -0
  489. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  490. opentrons/protocol_engine/types/labware.py +131 -0
  491. opentrons/protocol_engine/types/labware_movement.py +22 -0
  492. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  493. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  494. opentrons/protocol_engine/types/liquid.py +40 -0
  495. opentrons/protocol_engine/types/liquid_class.py +59 -0
  496. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  497. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  498. opentrons/protocol_engine/types/location.py +194 -0
  499. opentrons/protocol_engine/types/module.py +310 -0
  500. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  501. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  502. opentrons/protocol_engine/types/tip.py +18 -0
  503. opentrons/protocol_engine/types/util.py +21 -0
  504. opentrons/protocol_engine/types/well_position.py +124 -0
  505. opentrons/protocol_reader/__init__.py +37 -0
  506. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  507. opentrons/protocol_reader/file_format_validator.py +152 -0
  508. opentrons/protocol_reader/file_hasher.py +27 -0
  509. opentrons/protocol_reader/file_identifier.py +284 -0
  510. opentrons/protocol_reader/file_reader_writer.py +90 -0
  511. opentrons/protocol_reader/input_file.py +16 -0
  512. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  513. opentrons/protocol_reader/protocol_reader.py +188 -0
  514. opentrons/protocol_reader/protocol_source.py +124 -0
  515. opentrons/protocol_reader/role_analyzer.py +86 -0
  516. opentrons/protocol_runner/__init__.py +26 -0
  517. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  518. opentrons/protocol_runner/json_file_reader.py +55 -0
  519. opentrons/protocol_runner/json_translator.py +314 -0
  520. opentrons/protocol_runner/legacy_command_mapper.py +852 -0
  521. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  522. opentrons/protocol_runner/protocol_runner.py +530 -0
  523. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  524. opentrons/protocol_runner/run_orchestrator.py +496 -0
  525. opentrons/protocol_runner/task_queue.py +95 -0
  526. opentrons/protocols/__init__.py +6 -0
  527. opentrons/protocols/advanced_control/__init__.py +0 -0
  528. opentrons/protocols/advanced_control/common.py +38 -0
  529. opentrons/protocols/advanced_control/mix.py +60 -0
  530. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  531. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  532. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  533. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  534. opentrons/protocols/api_support/__init__.py +0 -0
  535. opentrons/protocols/api_support/constants.py +8 -0
  536. opentrons/protocols/api_support/deck_type.py +110 -0
  537. opentrons/protocols/api_support/definitions.py +18 -0
  538. opentrons/protocols/api_support/instrument.py +151 -0
  539. opentrons/protocols/api_support/labware_like.py +233 -0
  540. opentrons/protocols/api_support/tip_tracker.py +175 -0
  541. opentrons/protocols/api_support/types.py +32 -0
  542. opentrons/protocols/api_support/util.py +403 -0
  543. opentrons/protocols/bundle.py +89 -0
  544. opentrons/protocols/duration/__init__.py +4 -0
  545. opentrons/protocols/duration/errors.py +5 -0
  546. opentrons/protocols/duration/estimator.py +628 -0
  547. opentrons/protocols/execution/__init__.py +0 -0
  548. opentrons/protocols/execution/dev_types.py +181 -0
  549. opentrons/protocols/execution/errors.py +40 -0
  550. opentrons/protocols/execution/execute.py +84 -0
  551. opentrons/protocols/execution/execute_json_v3.py +275 -0
  552. opentrons/protocols/execution/execute_json_v4.py +359 -0
  553. opentrons/protocols/execution/execute_json_v5.py +28 -0
  554. opentrons/protocols/execution/execute_python.py +169 -0
  555. opentrons/protocols/execution/json_dispatchers.py +87 -0
  556. opentrons/protocols/execution/types.py +7 -0
  557. opentrons/protocols/geometry/__init__.py +0 -0
  558. opentrons/protocols/geometry/planning.py +297 -0
  559. opentrons/protocols/labware.py +312 -0
  560. opentrons/protocols/models/__init__.py +0 -0
  561. opentrons/protocols/models/json_protocol.py +679 -0
  562. opentrons/protocols/parameters/__init__.py +0 -0
  563. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  564. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  565. opentrons/protocols/parameters/exceptions.py +34 -0
  566. opentrons/protocols/parameters/parameter_definition.py +272 -0
  567. opentrons/protocols/parameters/types.py +17 -0
  568. opentrons/protocols/parameters/validation.py +267 -0
  569. opentrons/protocols/parse.py +671 -0
  570. opentrons/protocols/types.py +159 -0
  571. opentrons/py.typed +0 -0
  572. opentrons/resources/scripts/lpc21isp +0 -0
  573. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  574. opentrons/simulate.py +1065 -0
  575. opentrons/system/__init__.py +6 -0
  576. opentrons/system/camera.py +51 -0
  577. opentrons/system/log_control.py +59 -0
  578. opentrons/system/nmcli.py +856 -0
  579. opentrons/system/resin.py +24 -0
  580. opentrons/system/smoothie_update.py +15 -0
  581. opentrons/system/wifi.py +204 -0
  582. opentrons/tools/__init__.py +0 -0
  583. opentrons/tools/args_handler.py +22 -0
  584. opentrons/tools/write_pipette_memory.py +157 -0
  585. opentrons/types.py +618 -0
  586. opentrons/util/__init__.py +1 -0
  587. opentrons/util/async_helpers.py +166 -0
  588. opentrons/util/broker.py +84 -0
  589. opentrons/util/change_notifier.py +47 -0
  590. opentrons/util/entrypoint_util.py +278 -0
  591. opentrons/util/get_union_elements.py +26 -0
  592. opentrons/util/helpers.py +6 -0
  593. opentrons/util/linal.py +178 -0
  594. opentrons/util/logging_config.py +265 -0
  595. opentrons/util/logging_queue_handler.py +61 -0
  596. opentrons/util/performance_helpers.py +157 -0
  597. opentrons-8.6.0.dist-info/METADATA +37 -0
  598. opentrons-8.6.0.dist-info/RECORD +601 -0
  599. opentrons-8.6.0.dist-info/WHEEL +4 -0
  600. opentrons-8.6.0.dist-info/entry_points.txt +3 -0
  601. opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,426 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ from typing import Optional, Mapping
6
+ from typing_extensions import Final
7
+
8
+ from opentrons.drivers.rpi_drivers.types import USBPort
9
+ from opentrons.drivers.heater_shaker.driver import HeaterShakerDriver
10
+ from opentrons.drivers.heater_shaker.abstract import AbstractHeaterShakerDriver
11
+ from opentrons.drivers.heater_shaker.simulator import SimulatingDriver
12
+ from opentrons.drivers.types import Temperature, RPM, HeaterShakerLabwareLatchStatus
13
+ from opentrons.hardware_control.execution_manager import ExecutionManager
14
+ from opentrons.hardware_control.poller import Reader, Poller
15
+ from opentrons.hardware_control.modules import mod_abc, update
16
+ from opentrons.hardware_control.modules.types import (
17
+ ModuleDisconnectedCallback,
18
+ ModuleType,
19
+ TemperatureStatus,
20
+ SpeedStatus,
21
+ HeaterShakerStatus,
22
+ UploadFunction,
23
+ LiveData,
24
+ HeaterShakerData,
25
+ )
26
+
27
+ log = logging.getLogger(__name__)
28
+
29
+ POLL_PERIOD = 1.0
30
+
31
+ # TODO(mc, 2022-06-14): this techinque copied from temperature module
32
+ # to speed up simulation of heater-shaker protocols, but it's pretty silly
33
+ # module simulation in PAPIv2 needs to be seriously rethought
34
+ SIMULATING_POLL_PERIOD = POLL_PERIOD / 20.0
35
+
36
+ DFU_PID = "df11"
37
+
38
+
39
+ class HeaterShaker(mod_abc.AbstractModule):
40
+ """Hardware control interface for an attached Heater-Shaker module."""
41
+
42
+ MODULE_TYPE = ModuleType.HEATER_SHAKER
43
+
44
+ @classmethod
45
+ async def build(
46
+ cls,
47
+ port: str,
48
+ usb_port: USBPort,
49
+ hw_control_loop: asyncio.AbstractEventLoop,
50
+ execution_manager: Optional[ExecutionManager] = None,
51
+ poll_interval_seconds: Optional[float] = None,
52
+ simulating: bool = False,
53
+ sim_model: Optional[str] = None,
54
+ sim_serial_number: Optional[str] = None,
55
+ disconnected_callback: ModuleDisconnectedCallback = None,
56
+ ) -> "HeaterShaker":
57
+ """
58
+ Build a HeaterShaker
59
+
60
+ Args:
61
+ port: The port to connect to
62
+ usb_port: USB Port
63
+ hw_control_loop: The event loop running in the hardware control thread.
64
+ execution_manager: Execution manager.
65
+ poll_interval_seconds: Poll interval override.
66
+ simulating: whether to build a simulating driver
67
+ loop: Loop
68
+ sim_model: The model name used by simulator
69
+ disconnected_callback: Callback to inform the module controller that the device was disconnected
70
+
71
+ Returns:
72
+ HeaterShaker instance
73
+ """
74
+ driver: AbstractHeaterShakerDriver
75
+ if not simulating:
76
+ driver = await HeaterShakerDriver.create(port=port, loop=hw_control_loop)
77
+ poll_interval_seconds = poll_interval_seconds or POLL_PERIOD
78
+ else:
79
+ driver = SimulatingDriver(serial_number=sim_serial_number)
80
+ poll_interval_seconds = poll_interval_seconds or SIMULATING_POLL_PERIOD
81
+
82
+ reader = HeaterShakerReader(driver=driver)
83
+ poller = Poller(reader=reader, interval=poll_interval_seconds)
84
+ module = cls(
85
+ port=port,
86
+ usb_port=usb_port,
87
+ driver=driver,
88
+ reader=reader,
89
+ poller=poller,
90
+ device_info=await driver.get_device_info(),
91
+ hw_control_loop=hw_control_loop,
92
+ execution_manager=execution_manager,
93
+ disconnected_callback=disconnected_callback,
94
+ )
95
+
96
+ try:
97
+ await poller.start()
98
+ except Exception:
99
+ log.exception(f"First read of Heater-Shaker on port {port} failed")
100
+
101
+ return module
102
+
103
+ def __init__(
104
+ self,
105
+ port: str,
106
+ usb_port: USBPort,
107
+ driver: AbstractHeaterShakerDriver,
108
+ reader: HeaterShakerReader,
109
+ poller: Poller,
110
+ device_info: Mapping[str, str],
111
+ hw_control_loop: asyncio.AbstractEventLoop,
112
+ execution_manager: Optional[ExecutionManager] = None,
113
+ disconnected_callback: ModuleDisconnectedCallback = None,
114
+ ):
115
+ super().__init__(
116
+ port=port,
117
+ usb_port=usb_port,
118
+ hw_control_loop=hw_control_loop,
119
+ execution_manager=execution_manager,
120
+ disconnected_callback=disconnected_callback,
121
+ )
122
+ self._device_info = device_info
123
+ self._driver = driver
124
+ self._reader = reader
125
+ self._poller = poller
126
+
127
+ async def cleanup(self) -> None:
128
+ """Stop the poller task"""
129
+ await self._poller.stop()
130
+ await self._driver.disconnect()
131
+
132
+ @classmethod
133
+ def name(cls) -> str:
134
+ """Used for picking up serial port symlinks"""
135
+ return "heatershaker"
136
+
137
+ def firmware_prefix(self) -> str:
138
+ """The prefix used for looking up firmware"""
139
+ return "heater-shaker"
140
+
141
+ @staticmethod
142
+ def _model_from_revision(revision: Optional[str]) -> str:
143
+ """Defines the revision -> model mapping"""
144
+ return "heaterShakerModuleV1"
145
+
146
+ @staticmethod
147
+ def _get_temperature_status(temperature: Temperature) -> TemperatureStatus:
148
+ """
149
+ Determine the status from the temperature.
150
+
151
+ Args:
152
+ temperature: A Temperature instance
153
+
154
+ Returns:
155
+ The status
156
+ """
157
+ DELTA: Final = 0.7
158
+ status = TemperatureStatus.IDLE
159
+ if temperature.target is not None:
160
+ diff = temperature.target - temperature.current
161
+ if abs(diff) < DELTA: # To avoid status fluctuation near target
162
+ status = TemperatureStatus.HOLDING
163
+ elif diff < 0:
164
+ status = TemperatureStatus.COOLING
165
+ else:
166
+ status = TemperatureStatus.HEATING
167
+ return status
168
+
169
+ @staticmethod
170
+ def _get_speed_status(speed: RPM) -> SpeedStatus:
171
+ """
172
+ Determine the status from the speed.
173
+
174
+ Args:
175
+ speed: An RPM instance
176
+
177
+ Returns:
178
+ The status
179
+ """
180
+ DELTA: Final = 40
181
+ status = SpeedStatus.IDLE
182
+ if speed.target is not None:
183
+ diff = speed.target - speed.current
184
+ if abs(diff) < DELTA: # To avoid status fluctuation near target
185
+ status = SpeedStatus.HOLDING
186
+ elif diff < 0:
187
+ status = SpeedStatus.DECELERATING
188
+ else:
189
+ status = SpeedStatus.ACCELERATING
190
+ return status
191
+
192
+ def model(self) -> str:
193
+ return self._model_from_revision(self._device_info.get("model"))
194
+
195
+ def bootloader(self) -> UploadFunction:
196
+ return update.upload_via_dfu
197
+
198
+ @property
199
+ def device_info(self) -> Mapping[str, str]:
200
+ return self._device_info
201
+
202
+ @property
203
+ def live_data(self) -> LiveData:
204
+ data: HeaterShakerData = {
205
+ "temperatureStatus": self.temperature_status,
206
+ "speedStatus": self.speed_status,
207
+ "labwareLatchStatus": self.labware_latch_status,
208
+ "currentTemp": self.temperature,
209
+ "targetTemp": self.target_temperature,
210
+ "currentSpeed": self.speed,
211
+ "targetSpeed": self.target_speed,
212
+ "errorDetails": self._reader.error,
213
+ }
214
+ return {
215
+ "status": self.status.value,
216
+ "data": data,
217
+ }
218
+
219
+ @property
220
+ def temperature(self) -> float:
221
+ return self._reader.temperature.current
222
+
223
+ @property
224
+ def target_temperature(self) -> Optional[float]:
225
+ return self._reader.temperature.target
226
+
227
+ @property
228
+ def speed(self) -> int:
229
+ return self._reader.rpm.current
230
+
231
+ @property
232
+ def target_speed(self) -> Optional[int]:
233
+ return self._reader.rpm.target
234
+
235
+ @property
236
+ def temperature_status(self) -> TemperatureStatus:
237
+ return self._get_temperature_status(self._reader.temperature)
238
+
239
+ @property
240
+ def speed_status(self) -> SpeedStatus:
241
+ return self._get_speed_status(self._reader.rpm)
242
+
243
+ @property
244
+ def labware_latch_status(self) -> HeaterShakerLabwareLatchStatus:
245
+ return self._reader.labware_latch
246
+
247
+ @property
248
+ def status(self) -> HeaterShakerStatus:
249
+ """Module status or error state details."""
250
+ # TODO (spp, 2022-2-22): Does this make sense as the overarching 'status'?
251
+ # Or maybe consolidate the above 3 statuses into this one?
252
+ if self._reader.error:
253
+ return HeaterShakerStatus.ERROR
254
+ elif (
255
+ self.temperature_status == TemperatureStatus.IDLE
256
+ and self.speed_status == SpeedStatus.IDLE
257
+ ):
258
+ return HeaterShakerStatus.IDLE
259
+ else:
260
+ return HeaterShakerStatus.RUNNING
261
+
262
+ @property
263
+ def is_simulated(self) -> bool:
264
+ return isinstance(self._driver, SimulatingDriver)
265
+
266
+ async def start_set_temperature(self, celsius: float) -> None:
267
+ """
268
+ Set temperature in degrees Celsius
269
+
270
+ Range: Room temperature to 90 degree Celsius
271
+ Any temperature above the value will be clipped to
272
+ the nearest limit. This is a resistive heater, not
273
+ a Peltier TEC, so a temperature that is too low
274
+ may be unattainable but we do not limit input on the
275
+ low side in case the user has this in a freezer.
276
+
277
+ This function will complete as soon as heating begins, and
278
+ will not wait until the temperature is achieved. To then wait
279
+ until heating is complete, use await_temperature. To start
280
+ heating and wait until heating is complete in one call, use
281
+ set_temperature.
282
+
283
+ """
284
+ await self.wait_for_is_running()
285
+ await self._driver.set_temperature(celsius)
286
+ await self._reader.read_temperature()
287
+
288
+ # TODO(mc, 2022-10-10): remove `awaiting_temperature` argument,
289
+ # and instead, wait until status is holding
290
+ async def await_temperature(self, awaiting_temperature: float) -> None:
291
+ """Await temperature in degrees Celsius.
292
+
293
+ Polls the Heater-Shaker's current temperature until
294
+ the specified temperature is reached. If `awaiting_temperature`
295
+ is different than the current target temperature,
296
+ the resulting behavior may be unpredictable.
297
+ """
298
+ if self.is_simulated:
299
+ return
300
+
301
+ await self.wait_for_is_running()
302
+ await self._reader.read_temperature()
303
+
304
+ async def _await_temperature() -> None:
305
+ if self.temperature_status == TemperatureStatus.HEATING:
306
+ while self.temperature < awaiting_temperature:
307
+ await self._poller.wait_next_poll()
308
+ elif self.temperature_status == TemperatureStatus.COOLING:
309
+ while self.temperature > awaiting_temperature:
310
+ await self._poller.wait_next_poll()
311
+
312
+ t = self._loop.create_task(_await_temperature())
313
+ self.make_cancellable(t)
314
+ await t
315
+
316
+ async def set_speed(self, rpm: int) -> None:
317
+ """
318
+ Set shake speed in RPM
319
+
320
+ Range: 0-3000 RPM
321
+ Any speed above or below these values will cause an error.
322
+
323
+ This function will not complete until the heater-shaker is at
324
+ the speed or an error occurs. To start spinning but not wait
325
+ until the final speed is reached, see start_set_speed.
326
+ """
327
+ await self.wait_for_is_running()
328
+ await self._driver.set_rpm(rpm)
329
+ await self._reader.read_rpm()
330
+
331
+ async def _wait() -> None:
332
+ # Wait until we reach the target speed.
333
+ while self.speed_status != SpeedStatus.HOLDING:
334
+ await self._poller.wait_next_poll()
335
+
336
+ task = self._loop.create_task(_wait())
337
+ self.make_cancellable(task)
338
+ await task
339
+
340
+ async def _wait_for_labware_latch(
341
+ self, status: HeaterShakerLabwareLatchStatus
342
+ ) -> None:
343
+ """Wait until the hardware reports the labware latch status matches."""
344
+ while self.labware_latch_status != status:
345
+ await self._poller.wait_next_poll()
346
+
347
+ async def _wait_for_shake_deactivation(self) -> None:
348
+ """Wait until hardware reports that module has stopped shaking and has homed."""
349
+ while self.speed_status != SpeedStatus.IDLE:
350
+ await self._poller.wait_next_poll()
351
+
352
+ async def deactivate(self, must_be_running: bool = True) -> None:
353
+ """Stop heating/cooling; stop shaking and home the plate"""
354
+ await self.deactivate_heater(must_be_running=must_be_running)
355
+ await self.deactivate_shaker(must_be_running=must_be_running)
356
+
357
+ async def deactivate_heater(self, must_be_running: bool = True) -> None:
358
+ """Stop heating/cooling"""
359
+ if must_be_running:
360
+ await self.wait_for_is_running()
361
+ await self._driver.deactivate_heater()
362
+ await self._reader.read_temperature()
363
+
364
+ async def deactivate_shaker(self, must_be_running: bool = True) -> None:
365
+ """Stop shaking and home the plate"""
366
+ if must_be_running:
367
+ await self.wait_for_is_running()
368
+ await self._driver.home()
369
+ await self._wait_for_shake_deactivation()
370
+
371
+ async def open_labware_latch(self) -> None:
372
+ await self.wait_for_is_running()
373
+ await self._driver.open_labware_latch()
374
+ await self._wait_for_labware_latch(HeaterShakerLabwareLatchStatus.IDLE_OPEN)
375
+
376
+ async def close_labware_latch(self) -> None:
377
+ await self.wait_for_is_running()
378
+ await self._driver.close_labware_latch()
379
+ await self._wait_for_labware_latch(HeaterShakerLabwareLatchStatus.IDLE_CLOSED)
380
+
381
+ async def prep_for_update(self) -> str:
382
+ await self._poller.stop()
383
+ await self._driver.enter_programming_mode()
384
+ dfu_info = await update.find_dfu_device(pid=DFU_PID, expected_device_count=2)
385
+ return dfu_info
386
+
387
+
388
+ class HeaterShakerReader(Reader):
389
+ temperature: Temperature
390
+ rpm: RPM
391
+ labware_latch: HeaterShakerLabwareLatchStatus
392
+ error: Optional[str]
393
+
394
+ def __init__(self, driver: AbstractHeaterShakerDriver) -> None:
395
+ self.temperature = Temperature(current=25, target=None)
396
+ self.rpm = RPM(current=0, target=None)
397
+ self.labware_latch = HeaterShakerLabwareLatchStatus.IDLE_UNKNOWN
398
+ self.error: Optional[str] = None
399
+ self._driver = driver
400
+
401
+ async def read(self) -> None:
402
+ await self.read_temperature()
403
+ await self.read_rpm()
404
+ await self.read_labware_latch()
405
+ self._set_error(None)
406
+
407
+ def on_error(self, exception: Exception) -> None:
408
+ self._set_error(exception)
409
+
410
+ async def read_temperature(self) -> None:
411
+ self.temperature = await self._driver.get_temperature()
412
+
413
+ async def read_rpm(self) -> None:
414
+ self.rpm = await self._driver.get_rpm()
415
+
416
+ async def read_labware_latch(self) -> None:
417
+ self.labware_latch = await self._driver.get_labware_latch_status()
418
+
419
+ def _set_error(self, exception: Optional[Exception]) -> None:
420
+ if exception is None:
421
+ self.error = None
422
+ else:
423
+ try:
424
+ self.error = str(exception.args[0])
425
+ except Exception:
426
+ self.error = repr(exception)
@@ -0,0 +1,35 @@
1
+ from opentrons.drivers.types import Temperature
2
+ from opentrons.hardware_control.modules.types import TemperatureStatus
3
+
4
+
5
+ class LidTemperatureStatus:
6
+ """A wrapper for the lid temperature status."""
7
+
8
+ TEMP_THRESHOLD = 0.3
9
+ """The threshold under which the difference between target and temperature
10
+ is considered `holding`."""
11
+
12
+ def __init__(self) -> None:
13
+ """Construct."""
14
+ self._status = TemperatureStatus.ERROR
15
+
16
+ @property
17
+ def status(self) -> TemperatureStatus:
18
+ """Return the current status."""
19
+ return self._status
20
+
21
+ def update(self, temperature: Temperature) -> TemperatureStatus:
22
+ """Update the status based on the temperature."""
23
+ if temperature.target is None:
24
+ status = TemperatureStatus.IDLE
25
+ else:
26
+ diff = temperature.target - temperature.current
27
+ if abs(diff) < self.TEMP_THRESHOLD:
28
+ status = TemperatureStatus.HOLDING
29
+ elif diff < 0:
30
+ # TC lid can't actively cool
31
+ status = TemperatureStatus.IDLE
32
+ else:
33
+ status = TemperatureStatus.HEATING
34
+ self._status = status
35
+ return self._status
@@ -0,0 +1,233 @@
1
+ import asyncio
2
+ import logging
3
+ from typing import Dict, Optional
4
+ from opentrons.drivers.mag_deck import (
5
+ SimulatingDriver,
6
+ MagDeckDriver,
7
+ AbstractMagDeckDriver,
8
+ )
9
+ from opentrons.drivers.rpi_drivers.types import USBPort
10
+ from ..execution_manager import ExecutionManager
11
+ from . import update, mod_abc, types
12
+
13
+ log = logging.getLogger(__name__)
14
+
15
+ MAX_ENGAGE_HEIGHT = {
16
+ # Distance from home position.
17
+ # Measured in model-specific units (half-mm for GEN1, mm for GEN2).
18
+ "magneticModuleV1": 45,
19
+ "magneticModuleV2": 25,
20
+ }
21
+
22
+ # Measured in model-specific units (half-mm for GEN1, mm for GEN2).
23
+ # TODO(mc, 2022-06-13): the value for gen1 is off by ~1.5 mm
24
+ # The correct value is ~8.0 half-mm (4.0 mm)
25
+ # https://opentrons.atlassian.net/browse/RET-1242
26
+ OFFSET_TO_LABWARE_BOTTOM = {"magneticModuleV1": 5, "magneticModuleV2": 2.5}
27
+
28
+
29
+ def engage_height_is_in_range(model: str, height: float) -> bool:
30
+ """Return whether or not a height would be valid to pass to `MagDeck.engage()`.
31
+
32
+ Args:
33
+ model: The model of Magnetic Module for which you want to check
34
+ the engage height.
35
+ height: A height that you would provide to `MagDeck.engage()`.
36
+ """
37
+ return 0 <= height <= MAX_ENGAGE_HEIGHT[model]
38
+
39
+
40
+ class MagDeck(mod_abc.AbstractModule):
41
+ """Hardware control interface for an attached Temperature Module."""
42
+
43
+ MODULE_TYPE = types.ModuleType.MAGNETIC
44
+ FIRST_GEN2_REVISION = 20
45
+
46
+ @classmethod
47
+ async def build(
48
+ cls,
49
+ port: str,
50
+ usb_port: USBPort,
51
+ hw_control_loop: asyncio.AbstractEventLoop,
52
+ execution_manager: Optional[ExecutionManager] = None,
53
+ poll_interval_seconds: Optional[float] = None,
54
+ simulating: bool = False,
55
+ sim_model: Optional[str] = None,
56
+ sim_serial_number: Optional[str] = None,
57
+ disconnected_callback: types.ModuleDisconnectedCallback = None,
58
+ ) -> "MagDeck":
59
+ """Factory function."""
60
+ driver: AbstractMagDeckDriver
61
+ if not simulating:
62
+ driver = await MagDeckDriver.create(port=port, loop=hw_control_loop)
63
+ else:
64
+ driver = SimulatingDriver(
65
+ sim_model=sim_model, serial_number=sim_serial_number
66
+ )
67
+
68
+ mod = cls(
69
+ port=port,
70
+ usb_port=usb_port,
71
+ execution_manager=execution_manager,
72
+ hw_control_loop=hw_control_loop,
73
+ device_info=await driver.get_device_info(),
74
+ driver=driver,
75
+ disconnected_callback=disconnected_callback,
76
+ )
77
+ return mod
78
+
79
+ def __init__(
80
+ self,
81
+ port: str,
82
+ usb_port: USBPort,
83
+ hw_control_loop: asyncio.AbstractEventLoop,
84
+ driver: AbstractMagDeckDriver,
85
+ device_info: Dict[str, str],
86
+ execution_manager: Optional[ExecutionManager] = None,
87
+ disconnected_callback: types.ModuleDisconnectedCallback = None,
88
+ ) -> None:
89
+ """Constructor"""
90
+ super().__init__(
91
+ port=port,
92
+ usb_port=usb_port,
93
+ hw_control_loop=hw_control_loop,
94
+ execution_manager=execution_manager,
95
+ disconnected_callback=disconnected_callback,
96
+ )
97
+ self._device_info = device_info
98
+ self._driver = driver
99
+ self._current_height = 0.0
100
+
101
+ async def cleanup(self) -> None:
102
+ await self._driver.disconnect()
103
+
104
+ @classmethod
105
+ def name(cls) -> str:
106
+ """Get the module name."""
107
+ return "magdeck"
108
+
109
+ def firmware_prefix(self) -> str:
110
+ """The prefix used for looking up firmware"""
111
+ return "magnetic-module"
112
+
113
+ def model(self) -> str:
114
+ """Get the model."""
115
+ return self._model_from_revision(self._device_info.get("model"))
116
+
117
+ def bootloader(self) -> types.UploadFunction:
118
+ """Get the bootloating method."""
119
+ return update.upload_via_avrdude
120
+
121
+ async def calibrate(self) -> None:
122
+ """Calibration involves probing for top plate to get the plate height."""
123
+ await self.wait_for_is_running()
124
+ await self._driver.probe_plate()
125
+ # return if successful or not?
126
+
127
+ # TODO(mc, 2022-09-23): refactor this method to take real mm,
128
+ # hardware API should abstract away the idea of "short millimeters"
129
+ # https://opentrons.atlassian.net/browse/RET-1242
130
+ async def engage(
131
+ self,
132
+ height: Optional[float] = None,
133
+ height_from_base: Optional[float] = None,
134
+ must_be_running: bool = True,
135
+ ) -> None:
136
+ """Move the magnet to a specific height, measured from home position.
137
+
138
+ The units of position depend on the module model.
139
+ For GEN1, it's half millimeters ("short millimeters").
140
+ For GEN2, it's millimeters.
141
+ """
142
+ if height is None:
143
+ assert height_from_base is not None, "An engage height must be specified"
144
+ height = height_from_base + OFFSET_TO_LABWARE_BOTTOM[self.model()]
145
+
146
+ if must_be_running:
147
+ await self.wait_for_is_running()
148
+ if not engage_height_is_in_range(self.model(), height):
149
+ raise ValueError(
150
+ f"Invalid engage height for {self.model()}: {height}. "
151
+ f"Must be 0 - {MAX_ENGAGE_HEIGHT[self.model()]}."
152
+ )
153
+ await self._driver.move(height)
154
+ self._current_height = await self._driver.get_mag_position()
155
+
156
+ async def deactivate(self, must_be_running: bool = True) -> None:
157
+ """Home the magnet."""
158
+ if must_be_running:
159
+ await self.wait_for_is_running()
160
+ await self._driver.home()
161
+ await self.engage(0.0, must_be_running=must_be_running)
162
+
163
+ @property
164
+ def current_height(self) -> float:
165
+ """Get the current height."""
166
+ return self._current_height
167
+
168
+ @property
169
+ def device_info(self) -> Dict[str, str]:
170
+ """
171
+
172
+ Returns: a dict
173
+ { 'serial': 'abc123', 'model': '8675309', 'version': '9001' }
174
+
175
+ """
176
+ return self._device_info
177
+
178
+ @property
179
+ def serial_number(self) -> Optional[str]:
180
+ """The usb serial number of this device"""
181
+ return self._device_info.get("serial")
182
+
183
+ @property
184
+ def status(self) -> types.MagneticStatus:
185
+ if self.current_height > 0:
186
+ return types.MagneticStatus.ENGAGED
187
+ else:
188
+ return types.MagneticStatus.DISENGAGED
189
+
190
+ @property
191
+ def engaged(self) -> bool:
192
+ if self.current_height > 0:
193
+ return True
194
+ else:
195
+ return False
196
+
197
+ @property
198
+ def live_data(self) -> types.LiveData:
199
+ data: types.MagneticModuleData = {
200
+ "engaged": self.engaged,
201
+ "height": self.current_height,
202
+ }
203
+ return {
204
+ "status": self.status,
205
+ "data": data,
206
+ }
207
+
208
+ @property
209
+ def is_simulated(self) -> bool:
210
+ return isinstance(self._driver, SimulatingDriver)
211
+
212
+ # Internal Methods
213
+
214
+ async def prep_for_update(self) -> str:
215
+ await self._driver.enter_programming_mode()
216
+ new_port = await update.find_bootloader_port()
217
+ return new_port or self.port
218
+
219
+ @staticmethod
220
+ def _model_from_revision(revision: Optional[str]) -> str:
221
+ """Defines the revision -> model mapping"""
222
+ if not revision or "v" not in revision:
223
+ log.error(f"bad revision: {revision}")
224
+ return "magneticModuleV1"
225
+ try:
226
+ revision_num = float(revision.split("v")[-1])
227
+ except (ValueError, TypeError):
228
+ log.exception("bad revision: {revision}")
229
+ return "magneticModuleV1"
230
+ if revision_num < MagDeck.FIRST_GEN2_REVISION:
231
+ return "magneticModuleV1"
232
+ else:
233
+ return "magneticModuleV2"