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,431 @@
1
+ """
2
+ Coordinate subsystem detection and updates.
3
+ """
4
+
5
+ import asyncio
6
+ from contextlib import contextmanager, ExitStack
7
+ from dataclasses import dataclass
8
+ import logging
9
+ from typing import (
10
+ Optional,
11
+ Set,
12
+ Dict,
13
+ Iterator,
14
+ Callable,
15
+ AsyncIterator,
16
+ Union,
17
+ List,
18
+ )
19
+
20
+ from opentrons_hardware.hardware_control import network, tools
21
+ from opentrons_hardware.drivers import can_bus, binary_usb
22
+ from opentrons_hardware.firmware_bindings.constants import (
23
+ NodeId,
24
+ USBTarget,
25
+ FirmwareTarget,
26
+ ToolType,
27
+ )
28
+ from opentrons_hardware.firmware_update import FirmwareUpdate
29
+
30
+ from ..types import SubSystem, SubSystemState, UpdateStatus, UpdateState
31
+ from .ot3utils import subsystem_to_target, target_to_subsystem
32
+ from .errors import SubsystemUpdating
33
+
34
+
35
+ log = logging.getLogger(__name__)
36
+
37
+
38
+ @dataclass
39
+ class FirmwareUpdateRequirements:
40
+ target_version: int
41
+ filepath: str
42
+
43
+
44
+ class SubsystemManager:
45
+ """Control tracking and updating attached subsystems to the machine.
46
+
47
+ Call start() before trying to run the system (or build with build()).
48
+
49
+ This object has an always-up-to-date cache of attached subsystems driven by
50
+ asynchronous notifications from hardware and explicitly updatable with refresh().
51
+ """
52
+
53
+ _can_messenger: can_bus.CanMessenger
54
+ _usb_messenger: Optional[binary_usb.BinaryMessenger]
55
+ _tool_detector: tools.detector.ToolDetector
56
+ _network_info: network.NetworkInfo
57
+ _tool_detection_task: "Optional[asyncio.Task[None]]"
58
+ _expected_core_targets: Set[FirmwareTarget]
59
+ _present_tools: tools.types.ToolSummary
60
+ _tool_task_condition: asyncio.Condition
61
+ _tool_task_state: Union[bool, BaseException]
62
+ _updates_required: Dict[FirmwareTarget, FirmwareUpdateRequirements]
63
+ _updates_ongoing: Dict[SubSystem, UpdateStatus]
64
+ _update_bag: FirmwareUpdate
65
+
66
+ def __init__(
67
+ self,
68
+ can_messenger: can_bus.CanMessenger,
69
+ usb_messenger: Optional[binary_usb.BinaryMessenger],
70
+ tool_detector: tools.detector.ToolDetector,
71
+ network_info: network.NetworkInfo,
72
+ update_bag: FirmwareUpdate,
73
+ ) -> None:
74
+ self._can_messenger = can_messenger
75
+ self._usb_messenger = usb_messenger
76
+ self._tool_detector = tool_detector
77
+ self._network_info = network_info
78
+ self._tool_detection_task = None
79
+ self._expected_core_targets: Set[FirmwareTarget] = {
80
+ NodeId.gantry_x,
81
+ NodeId.gantry_y,
82
+ NodeId.head,
83
+ }
84
+ self._tool_task_condition = asyncio.Condition()
85
+ self._tool_task_state = False
86
+ self._updates_required = {}
87
+ self._updates_ongoing = {}
88
+ self._update_bag = update_bag
89
+ if self._usb_messenger:
90
+ self._expected_core_targets.add(USBTarget.rear_panel)
91
+ self._present_tools = tools.types.ToolSummary(
92
+ left=None, right=None, gripper=None
93
+ )
94
+
95
+ @property
96
+ def ok(self) -> bool:
97
+ """True if required subsystems are present and all present subsystems are ok."""
98
+ if not self._expected_core_targets.issubset(self.targets):
99
+ return False
100
+ return all(state.ok for state in self.subsystems.values())
101
+
102
+ @property
103
+ def device_info(self) -> Dict[SubSystem, network.DeviceInfoCache]:
104
+ return {
105
+ target_to_subsystem(target): info
106
+ for target, info in self._network_info.device_info.items()
107
+ }
108
+
109
+ @property
110
+ def targets(self) -> Set[FirmwareTarget]:
111
+ return self._network_info.targets
112
+
113
+ @property
114
+ def tools(self) -> tools.types.ToolSummary:
115
+ return self._present_tools
116
+
117
+ @property
118
+ def subsystems(self) -> Dict[SubSystem, SubSystemState]:
119
+ def _state_or(maybe_status: Optional[UpdateStatus]) -> Optional[UpdateState]:
120
+ if maybe_status is not None:
121
+ return maybe_status.state
122
+ return None
123
+
124
+ def _next_version(target: FirmwareTarget, current: int) -> int:
125
+ try:
126
+ return self._updates_required[target].target_version
127
+ except KeyError:
128
+ return current
129
+
130
+ return {
131
+ target_to_subsystem(target): SubSystemState(
132
+ ok=info.ok,
133
+ current_fw_version=info.version,
134
+ next_fw_version=_next_version(target, info.version),
135
+ fw_update_needed=target in self._updates_required,
136
+ current_fw_sha=info.shortsha,
137
+ pcba_revision=str(info.revision),
138
+ update_state=_state_or(
139
+ self._updates_ongoing.get(target_to_subsystem(target))
140
+ ),
141
+ )
142
+ for target, info in self._network_info.device_info.items()
143
+ }
144
+
145
+ @property
146
+ def update_required(self) -> bool:
147
+ return bool(self._updates_required)
148
+
149
+ @property
150
+ def subsystems_to_update(self) -> List[SubSystem]:
151
+ return [target_to_subsystem(t) for t in self._updates_required.keys()]
152
+
153
+ async def start(self) -> None:
154
+ await self._probe_network_and_cache_fw_updates(
155
+ self._expected_core_targets, True
156
+ )
157
+ self._tool_detection_task = asyncio.create_task(
158
+ self._tool_detection_task_main()
159
+ )
160
+ await self.refresh()
161
+ log.info(f"Subsystem manager started with devices {self.device_info}")
162
+
163
+ async def refresh(self) -> None:
164
+ """Explicitly refresh the state of the system.
165
+
166
+ This will not return until the information is up to date.
167
+ """
168
+ async with self._tool_task_condition:
169
+ if isinstance(self._tool_task_state, Exception):
170
+ raise self._tool_task_state
171
+ await self._tool_detector.check_once()
172
+ await self._tool_task_condition.wait()
173
+ if isinstance(self._tool_task_state, Exception):
174
+ raise self._tool_task_state
175
+ self._tool_task_state = False
176
+
177
+ async def is_new(self) -> bool:
178
+ """Returns True if there is data unread since the last call to is_new."""
179
+ async with self._tool_task_condition:
180
+ state = self._tool_task_state
181
+ if isinstance(state, Exception):
182
+ raise state
183
+ return self._tool_task_state is True
184
+
185
+ async def _check_devices_after_update(
186
+ self, devices: Set[SubSystem], timeout_sec: float = 10.0
187
+ ) -> None:
188
+ try:
189
+ await asyncio.wait_for(
190
+ self._do_check_devices_after_update(devices), timeout=timeout_sec
191
+ )
192
+ except asyncio.TimeoutError:
193
+ raise RuntimeError("Device failed to come back after firmware update")
194
+
195
+ async def _do_check_devices_after_update(self, devices: Set[SubSystem]) -> None:
196
+ # refresh the device_info cache and reset internal states
197
+ log.info(f"Checking {devices} after update")
198
+ attempts = 1
199
+ while True:
200
+ await self._probe_network_and_cache_fw_updates(
201
+ {subsystem_to_target(subsystem) for subsystem in devices},
202
+ False,
203
+ )
204
+ await asyncio.sleep(0.1)
205
+ # make sure the update actually succeeded
206
+ device_info = self.device_info
207
+ if devices.issubset(device_info.keys()) and all(
208
+ info.ok for subsys, info in device_info.items() if subsys in devices
209
+ ):
210
+ log.info(f"Found all devices after {attempts} tries")
211
+ return
212
+ log.info(f"Failed to find all of {devices}: found {device_info}")
213
+ attempts += 1
214
+
215
+ def get_update_progress(self) -> Dict[SubSystem, UpdateStatus]:
216
+ """Returns a set of UpdateStatus of the updates."""
217
+ return {k: v for k, v in self._updates_ongoing.items()}
218
+
219
+ async def update_firmware(
220
+ self,
221
+ subsystems: Optional[Set[SubSystem]] = None,
222
+ force: bool = False,
223
+ ) -> AsyncIterator[UpdateStatus]:
224
+ """Updates the firmware on the OT3."""
225
+ # Check that there arent updates already running for given nodes
226
+ current_subsystems = self.subsystems
227
+
228
+ subsystems_to_check = subsystems or set(current_subsystems)
229
+ subsystems_updating = set(self._updates_ongoing)
230
+ subsystems_to_update = subsystems_to_check - subsystems_updating
231
+ if not subsystems_to_update:
232
+ if subsystems:
233
+ raise SubsystemUpdating(f"Ongoing update for {subsystems}")
234
+ else:
235
+ log.info("No viable subsystem to update.")
236
+ return
237
+
238
+ # Check if devices need an update, only checks nodes if given
239
+ firmware_updates = self._get_required_fw_updates(
240
+ {subsystem_to_target(subsystem) for subsystem in subsystems_to_update},
241
+ force=force,
242
+ )
243
+
244
+ subsystems_updatable = set(
245
+ target_to_subsystem(target) for target in firmware_updates.keys()
246
+ )
247
+ updating_subsystems = subsystems_to_update.intersection(subsystems_updatable)
248
+
249
+ if not updating_subsystems:
250
+ log.info("No firmware updates required for specified subsystems.")
251
+ return
252
+
253
+ log.info(f"Updating firmware on {updating_subsystems}")
254
+
255
+ update_details = {
256
+ target: firmware_updates[target].filepath
257
+ for target in (
258
+ subsystem_to_target(subsystem) for subsystem in updating_subsystems
259
+ )
260
+ }
261
+
262
+ with ExitStack() as update_tracker_stack:
263
+ status_callbacks: Dict[SubSystem, Callable[[UpdateStatus], None]] = {
264
+ subsystem: update_tracker_stack.enter_context(
265
+ self._update_ongoing_for(subsystem)
266
+ )
267
+ for subsystem in updating_subsystems
268
+ }
269
+
270
+ updater = self._update_bag.update_runner(
271
+ can_messenger=self._can_messenger,
272
+ usb_messenger=self._usb_messenger,
273
+ update_details=update_details,
274
+ retry_count=3,
275
+ timeout_seconds=5,
276
+ erase=True,
277
+ )
278
+
279
+ # start the updates and yield progress to caller
280
+ async for target, status_element in updater.run_updates():
281
+ subsystem = target_to_subsystem(target)
282
+ upstream_status = UpdateStatus(
283
+ subsystem=subsystem,
284
+ state=UpdateState[status_element[0].name],
285
+ progress=int(status_element[1] * 100),
286
+ )
287
+ status_callbacks[subsystem](upstream_status)
288
+ yield upstream_status
289
+
290
+ await self._check_devices_after_update(updating_subsystems)
291
+
292
+ def _get_required_fw_updates(
293
+ self, targets: Set[FirmwareTarget], force: bool
294
+ ) -> Dict[FirmwareTarget, FirmwareUpdateRequirements]:
295
+ to_check = (targets or self.targets).intersection(self.targets)
296
+ updates_required: Dict[FirmwareTarget, FirmwareUpdateRequirements] = {}
297
+ bad_targets = {
298
+ target
299
+ for target in to_check
300
+ if not self.device_info[target_to_subsystem(target)].ok
301
+ }
302
+ good_targets = to_check - bad_targets
303
+ device_info_by_target = {
304
+ subsystem_to_target(subsystem): info
305
+ for subsystem, info in self.device_info.items()
306
+ }
307
+ good_updates = self._update_bag.update_checker(
308
+ device_info_by_target, good_targets, force
309
+ )
310
+ bad_updates = self._update_bag.update_checker(
311
+ device_info_by_target, bad_targets, True
312
+ )
313
+
314
+ for target, (next_version, filepath) in good_updates.items():
315
+ updates_required[target] = FirmwareUpdateRequirements(
316
+ target_version=next_version,
317
+ filepath=filepath,
318
+ )
319
+
320
+ for target, (next_version, filepath) in bad_updates.items():
321
+ updates_required[target] = FirmwareUpdateRequirements(
322
+ target_version=next_version,
323
+ filepath=filepath,
324
+ )
325
+
326
+ return updates_required
327
+
328
+ def _update_fw_update_requirements(self) -> None:
329
+ """Update the local cache of extra information required for subsystem state."""
330
+ # this runs in a separate task from where it will be queried, so we'll build a replacement
331
+ # for the _updates_required dict locally and then swap it over async-atomically
332
+
333
+ self._updates_required = self._get_required_fw_updates(set(), False)
334
+
335
+ async def _probe_network_and_cache_fw_updates(
336
+ self, targets: Set[FirmwareTarget], broadcast: bool = True
337
+ ) -> None:
338
+ checked_targets = {
339
+ target
340
+ for target in targets
341
+ if target_to_subsystem(target) not in self._updates_ongoing
342
+ }
343
+ if broadcast:
344
+ await self._network_info.probe(checked_targets)
345
+ else:
346
+ await self._network_info.probe_specific(checked_targets)
347
+ self._update_fw_update_requirements()
348
+
349
+ @contextmanager
350
+ def _update_ongoing_for(
351
+ self, subsystem: SubSystem
352
+ ) -> Iterator[Callable[[UpdateStatus], None]]:
353
+ if subsystem in self._updates_ongoing:
354
+ raise RuntimeError(f"Update already ongoing for {subsystem}")
355
+
356
+ def update_state(status: UpdateStatus) -> None:
357
+ self._updates_ongoing[subsystem] = status
358
+
359
+ self._updates_ongoing[subsystem] = UpdateStatus(
360
+ subsystem=subsystem, state=UpdateState.queued, progress=0
361
+ )
362
+ try:
363
+ yield update_state
364
+ except Exception:
365
+ log.exception(f"Update failed for subsystem {subsystem}")
366
+ raise
367
+ finally:
368
+ self._updates_ongoing.pop(subsystem)
369
+
370
+ async def _tool_detection_task_main(self) -> None:
371
+ try:
372
+ await self._tool_detection_task_protected()
373
+ except BaseException as e:
374
+ log.exception("Tool reader task failed")
375
+ async with self._tool_task_condition:
376
+ self._tool_task_state = e
377
+ self._tool_task_condition.notify_all()
378
+ raise
379
+
380
+ async def _tool_detection_task_protected(self) -> None:
381
+ """Main function of an asyncio task that responds to async notifications that tool states have changed."""
382
+ async with self._tool_task_condition:
383
+ self._tool_task_state = True
384
+ self._tool_task_condition.notify_all()
385
+ async for update in self._tool_detector.detect():
386
+ # We got a notification from the head that something changed. Let's check whether the currently
387
+ # attached tools are okay by getting their device info
388
+ tool_nodes: Set[NodeId] = set()
389
+ if update.left != ToolType.nothing_attached:
390
+ tool_nodes.add(NodeId.pipette_left)
391
+ if update.right != ToolType.nothing_attached:
392
+ tool_nodes.add(NodeId.pipette_right)
393
+ if update.gripper != ToolType.nothing_attached:
394
+ tool_nodes.add(NodeId.gripper)
395
+ base_can_nodes: List[NodeId] = [
396
+ NodeId.pipette_left,
397
+ NodeId.pipette_right,
398
+ NodeId.gripper,
399
+ ]
400
+ base_nodes: Set[FirmwareTarget] = {n for n in base_can_nodes}
401
+ try:
402
+ self._network_info.mark_absent(base_nodes - tool_nodes)
403
+ await self._probe_network_and_cache_fw_updates(
404
+ self._expected_core_targets.union(tool_nodes), False
405
+ )
406
+ except TimeoutError:
407
+ log.exception("Problem in internal network probe")
408
+ continue
409
+
410
+ # Once we know which are okay, we can ask only those for their subsystems
411
+ to_resolve = tools.types.ToolDetectionResult(
412
+ left=self._tool_if_ok(update.left, NodeId.pipette_left),
413
+ right=self._tool_if_ok(update.right, NodeId.pipette_right),
414
+ gripper=self._tool_if_ok(update.gripper, NodeId.gripper),
415
+ )
416
+ self._present_tools = await self._tool_detector.resolve(to_resolve, 10.0)
417
+ log.info(f"Present tools are now {self._present_tools}")
418
+ await network.log_motor_usage_data(self._can_messenger)
419
+ async with self._tool_task_condition:
420
+ self._tool_task_state = True
421
+ self._tool_task_condition.notify_all()
422
+
423
+ def _tool_if_ok(self, tool: ToolType, node: NodeId) -> ToolType:
424
+ if tool is ToolType.nothing_attached:
425
+ return tool
426
+ device_info = self._network_info.device_info
427
+ if node not in device_info:
428
+ return ToolType.nothing_attached
429
+ if not device_info[node].ok:
430
+ return ToolType.nothing_attached
431
+ return tool
@@ -0,0 +1,173 @@
1
+ import logging
2
+ from functools import partial
3
+ from typing import cast, Callable, Optional, List, Set
4
+ from typing_extensions import TypedDict, Literal
5
+
6
+ from opentrons.hardware_control.types import TipStateType, OT3Mount, InstrumentProbeType
7
+
8
+ from opentrons_hardware.drivers.can_bus import CanMessenger
9
+ from opentrons_hardware.firmware_bindings.constants import NodeId
10
+ from opentrons_hardware.hardware_control.tip_presence import (
11
+ TipDetector,
12
+ types as tip_types,
13
+ )
14
+ from opentrons_shared_data.errors.exceptions import (
15
+ TipDetectorNotFound,
16
+ UnmatchedTipPresenceStates,
17
+ GeneralError,
18
+ )
19
+
20
+ from .ot3utils import sensor_id_for_instrument
21
+
22
+ log = logging.getLogger(__name__)
23
+
24
+ TipListener = Callable[[OT3Mount, bool], None]
25
+ PipetteMountKeys = Literal["left", "right"]
26
+
27
+
28
+ class TipDetectorByMount(TypedDict):
29
+ left: Optional[TipDetector]
30
+ right: Optional[TipDetector]
31
+
32
+
33
+ class UnsubMethodByMount(TypedDict):
34
+ left: Optional[Callable[[], None]]
35
+ right: Optional[Callable[[], None]]
36
+
37
+
38
+ class TipUpdateByMount(TypedDict):
39
+ left: Optional[bool]
40
+ right: Optional[bool]
41
+
42
+
43
+ def _mount_to_node(mount: OT3Mount) -> NodeId:
44
+ return {
45
+ OT3Mount.LEFT: NodeId.pipette_left,
46
+ OT3Mount.RIGHT: NodeId.pipette_right,
47
+ }[mount]
48
+
49
+
50
+ class TipPresenceManager:
51
+ """Handle tip change notification coming from CAN."""
52
+
53
+ _listeners: Set[TipListener]
54
+ _detectors: TipDetectorByMount
55
+ _unsub_methods: UnsubMethodByMount
56
+ _last_state: TipUpdateByMount
57
+
58
+ def __init__(
59
+ self,
60
+ can_messenger: CanMessenger,
61
+ listeners: Set[TipListener] = set(),
62
+ ) -> None:
63
+ self._messenger = can_messenger
64
+ self._listeners = listeners
65
+ self._detectors = TipDetectorByMount(left=None, right=None)
66
+ self._unsub_methods = UnsubMethodByMount(left=None, right=None)
67
+ self._last_state = TipUpdateByMount(left=None, right=None)
68
+
69
+ @staticmethod
70
+ def _get_key(mount: OT3Mount) -> PipetteMountKeys:
71
+ assert mount != OT3Mount.GRIPPER
72
+ return cast(PipetteMountKeys, mount.name.lower())
73
+
74
+ async def clear_detector(self, mount: OT3Mount) -> None:
75
+ """Clean up and remove tip detector."""
76
+
77
+ def _unsubscribe() -> None:
78
+ """Unsubscribe from detector."""
79
+ unsub = self._unsub_methods[self._get_key(mount)]
80
+ if unsub:
81
+ unsub()
82
+ self.set_unsub(mount, None)
83
+
84
+ try:
85
+ detector = self.get_detector(mount)
86
+ detector.cleanup()
87
+ except TipDetectorNotFound:
88
+ pass
89
+ finally:
90
+ _unsubscribe()
91
+ self.set_detector(mount, None)
92
+
93
+ async def build_detector(self, mount: OT3Mount, sensor_count: int) -> None:
94
+ assert self._detectors.get(self._get_key(mount), None) is None
95
+ # set up and subscribe to the detector
96
+ d = TipDetector(self._messenger, _mount_to_node(mount), sensor_count)
97
+ # listens to the detector so we can immediately notify listeners
98
+ # the most up-to-date tip state
99
+ unsub = d.add_subscriber(partial(self._handle_tip_update, mount))
100
+ self.set_unsub(mount, unsub)
101
+ self.set_detector(mount, d)
102
+
103
+ def _handle_tip_update(
104
+ self, mount: OT3Mount, update: tip_types.TipNotification
105
+ ) -> None:
106
+ """Callback for detector."""
107
+ self._last_state[self._get_key(mount)] = update.presence
108
+
109
+ for listener in self._listeners:
110
+ listener(mount, update.presence)
111
+
112
+ def current_tip_state(self, mount: OT3Mount) -> Optional[bool]:
113
+ state = self._last_state[self._get_key(mount)]
114
+ return state
115
+
116
+ @staticmethod
117
+ def _get_tip_presence(
118
+ results: List[tip_types.TipNotification],
119
+ follow_singular_sensor: Optional[InstrumentProbeType] = None,
120
+ ) -> TipStateType:
121
+ """
122
+ We can use follow_singular_sensor used to specify that we only care
123
+ about the status of one tip presence sensor on a high throughput
124
+ pipette, and the other is allowed to be different.
125
+ """
126
+ if follow_singular_sensor:
127
+ target_sensor_id = sensor_id_for_instrument(follow_singular_sensor)
128
+ for r in results:
129
+ if r.sensor == target_sensor_id:
130
+ return TipStateType(r.presence)
131
+ # raise an error if requested sensor response isn't found
132
+ raise GeneralError(
133
+ message=f"Requested status for sensor {follow_singular_sensor} not found."
134
+ )
135
+ # more than one sensor reported, we have to check if their states match
136
+ if len(set(r.presence for r in results)) > 1:
137
+ raise UnmatchedTipPresenceStates(
138
+ {int(r.sensor): int(r.presence) for r in results}
139
+ )
140
+ return TipStateType(results[0].presence)
141
+
142
+ async def get_tip_status(
143
+ self,
144
+ mount: OT3Mount,
145
+ follow_singular_sensor: Optional[InstrumentProbeType] = None,
146
+ ) -> TipStateType:
147
+ detector = self.get_detector(mount)
148
+ return self._get_tip_presence(
149
+ await detector.request_tip_status(), follow_singular_sensor
150
+ )
151
+
152
+ def get_detector(self, mount: OT3Mount) -> TipDetector:
153
+ detector = self._detectors[self._get_key(mount)]
154
+ if not detector:
155
+ raise TipDetectorNotFound(
156
+ message=f"Tip detector not set up for {mount} mount",
157
+ detail={"mount": str(mount)},
158
+ )
159
+ return detector
160
+
161
+ def set_detector(self, mount: OT3Mount, detector: Optional[TipDetector]) -> None:
162
+ self._detectors[self._get_key(mount)] = detector
163
+
164
+ def set_unsub(self, mount: OT3Mount, unsub: Optional[Callable[[], None]]) -> None:
165
+ self._unsub_methods[self._get_key(mount)] = unsub
166
+
167
+ def add_listener(self, listener: TipListener) -> Callable[[], None]:
168
+ self._listeners.add(listener)
169
+
170
+ def remove() -> None:
171
+ self._listeners.discard(listener)
172
+
173
+ return remove
@@ -0,0 +1,14 @@
1
+ """backends.types - wrapper types for api/backend interaction"""
2
+
3
+ from enum import Enum, auto
4
+
5
+
6
+ class HWStopCondition(Enum):
7
+ none = auto()
8
+ limit_switch = auto()
9
+ sync_line = auto()
10
+ encoder_position = auto()
11
+ gripper_force = auto()
12
+ stall = auto()
13
+ ignore_stalls = auto()
14
+ limit_switch_backoff = auto()
@@ -0,0 +1,6 @@
1
+ """ Constants for the :py:class:`.hardware_control.API` instances.
2
+ """
3
+ SHAKE_OFF_TIPS_SPEED = 50 # mm/s
4
+ SHAKE_OFF_TIPS_DROP_DISTANCE = 2.25 # mm
5
+ SHAKE_OFF_TIPS_PICKUP_DISTANCE = 0.3 # mm
6
+ DROP_TIP_RELEASE_DISTANCE = 20 # mm