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,364 @@
1
+ from __future__ import annotations
2
+ import enum
3
+ import re
4
+ from itertools import groupby
5
+ from dataclasses import dataclass
6
+ from typing import List, Optional, Tuple
7
+ from opentrons.hardware_control.types import BoardRevision
8
+
9
+
10
+ class PinDir(enum.Enum):
11
+ rev_input = enum.auto()
12
+ input = enum.auto()
13
+ output = enum.auto()
14
+
15
+
16
+ class PortGroup:
17
+ MAIN = "main"
18
+ LEFT = "left"
19
+ RIGHT = "right"
20
+ FRONT = "front"
21
+ UNKNOWN = "unknown"
22
+
23
+
24
+ REV_OG_USB_PORTS = {"3": 1, "5": 2}
25
+ REV_A_USB_HUB = 3
26
+ FLEX_B2_USB_PORT_GROUP_LEFT = 4
27
+ FLEX_B2_USB_PORT_GROUP_RIGHT = 3
28
+ FLEX_B2_USB_PORT_GROUP_FRONT = 7
29
+ FLEX_B2_USB_PORTS = {"4": 1, "3": 2, "2": 3, "1": 4}
30
+
31
+ BUS_PATH = "/sys/bus/usb/devices/usb1/"
32
+
33
+ # Example usb path might look like:
34
+ # '/sys/bus/usb/devices/usb1/1-1/1-1.3/1-1.3:1.0/tty/ttyACM1/dev'.
35
+ # Example hid device path might look like:
36
+ # '/sys/bus/usb/devices/usb1/1-1/1-1.3/1-1.3:1.0/0003:16D0:1199.0002/hidraw/hidraw0/dev'
37
+ # There is only 1 bus that supports USB on the raspberry pi.
38
+ USB_PORT_INFO = re.compile(
39
+ r"""
40
+ (?P<port_path>(\d[\d]*-\d[\d\.]*[/]?)+):
41
+ (?P<device_path>
42
+ \d.\d/
43
+ (tty/tty(\w{4})/dev | [\w:\.]+?/hidraw/hidraw\d/dev)
44
+ )
45
+ """,
46
+ re.VERBOSE,
47
+ )
48
+
49
+ HUB_PATTERN = re.compile(r"(\d-[\d.]+\d?)[\/:]")
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ class USBPort:
54
+ name: str
55
+ port_number: int
56
+ port_group: str = PortGroup.UNKNOWN
57
+ hub: bool = False
58
+ hub_port: Optional[int] = None
59
+ device_path: str = ""
60
+
61
+ @classmethod
62
+ def build(
63
+ cls, full_path: str, board_revision: BoardRevision
64
+ ) -> Optional["USBPort"]:
65
+ """
66
+ Build a USBPort dataclass.
67
+
68
+ An example port path:
69
+ `1-1.3/1-1.3:1.0/tty/ttyACM1/dev`
70
+
71
+ Args:
72
+ port_path: Full path of a usb device
73
+ board_revision: Board revision
74
+
75
+ Returns:
76
+ Tuple of the port number, port group, hub, hub port, device path, and name
77
+ """
78
+ match = USB_PORT_INFO.search(full_path)
79
+ if not match:
80
+ return None
81
+
82
+ port_path = match.group("port_path")
83
+ device_path = match.group("device_path")
84
+ port_nodes = cls.get_unique_nodes(port_path)
85
+ hub, port, hub_port, name = cls.find_hub(port_nodes, board_revision)
86
+ hub, port_group, port, hub_port = cls.map_to_revision(
87
+ board_revision,
88
+ (
89
+ hub,
90
+ port,
91
+ hub_port,
92
+ ),
93
+ )
94
+ return cls(
95
+ name=name,
96
+ port_number=port,
97
+ port_group=port_group,
98
+ hub=hub,
99
+ hub_port=hub_port,
100
+ device_path=device_path,
101
+ )
102
+
103
+ @staticmethod
104
+ def find_hub(
105
+ port_nodes: List[str],
106
+ board_revision: BoardRevision,
107
+ ) -> Tuple[Optional[int], int, Optional[int], str]:
108
+ """
109
+ Find the hub, port, and hub_port data for a USB port from
110
+ the port nodes.
111
+
112
+ The last item of the port nodes list is parsed by splitting
113
+ the item at each period. It is parsed as follows:
114
+ 'bus.hub.port.hub_port'. The USB bus data is unused. The
115
+ hub_port data is only populated if a USB hub is connected
116
+ to that port. The Flex FRONT USB port is parsed as:
117
+ 'bus.hub.hub_port'.
118
+
119
+ :param port_nodes: A list of unique port id(s)
120
+ :returns: Tuple of the hub, port number, hub_port and name
121
+ """
122
+ if len(port_nodes) == 1 and "." not in port_nodes[0]:
123
+ # if no hub is attached, such as on a dev kit, the port
124
+ # nodes available will be 1-1
125
+ port = int(port_nodes[0].split("-")[1])
126
+ hub = None
127
+ hub_port = None
128
+ name = port_nodes[0]
129
+ else:
130
+ port_nodes = [node for node in port_nodes if "." in node]
131
+ if len(port_nodes) > 2:
132
+ port_info = port_nodes[2].split(".")
133
+ hub = int(port_info[1])
134
+ port = int(port_info[2])
135
+ hub_port = int(port_info[3])
136
+ name = port_nodes[2]
137
+ elif len(port_nodes) > 1:
138
+ if board_revision == BoardRevision.OG:
139
+ port_info = port_nodes[1].split(".")
140
+ hub = int(port_info[1])
141
+ port = int(port_info[1])
142
+ hub_port = int(port_info[2])
143
+ name = port_nodes[1]
144
+ else:
145
+ port_info = port_nodes[1].split(".")
146
+ hub = int(port_info[1])
147
+ name = port_nodes[1]
148
+ if (board_revision == BoardRevision.FLEX_B2) and (
149
+ hub == FLEX_B2_USB_PORT_GROUP_FRONT
150
+ ):
151
+ port = 9
152
+ hub_port = int(port_info[2])
153
+ else:
154
+ port = int(port_info[2])
155
+ hub_port = None
156
+ else:
157
+ if board_revision == BoardRevision.FLEX_B2:
158
+ port_info = port_nodes[0].split(".")
159
+ hub = int(port_info[1])
160
+ port = 9
161
+ hub_port = None
162
+ name = port_nodes[0]
163
+ else:
164
+ port = int(port_nodes[0].split(".")[1])
165
+ hub = None
166
+ hub_port = None
167
+ name = port_nodes[0]
168
+ return hub, port, hub_port, name
169
+
170
+ @staticmethod
171
+ def get_unique_nodes(full_name: str) -> List[str]:
172
+ """
173
+ Get unique port nodes for a USB port from the USB port path.
174
+
175
+ For a Flex or OT-2_R with a USB hub connected to a port,
176
+ the USB port path will look like:
177
+ `1-1.3/1-1.3.2/1-1.3.2.4/1-1.3.2.4`. This will become the
178
+ following 3 port nodes: ['1-1.3', '1-1.3.2', '1-1.3.2.4'].
179
+ The Flex FRONT USB port with a hub connected will look like:
180
+ `1-1.7/1-1.7.4/1-1.7.4` and become ['1-1.7', '1-1.7.4'].
181
+
182
+ For a Flex or OT-2_R without a USB hub connected to a port,
183
+ the USB port path will look like: `1-1.3/1-1.3.4/1-1.3.4`.
184
+ This will become the follwing 2 port nodes: ['1-1.3', '1-1.3.4'].
185
+ The Flex FRONT USB port without a hub connected will look like:
186
+ `1-1.7/1-1.7` and become ['1-1.7'].
187
+
188
+ For a OT-2_OG with a USB hub connected to a port, the USB
189
+ port path will look like: `1-1.3/1-1.3/1-1.3.3/1-1.3.3`. This will
190
+ become the following 2 port nodes: ['1-1.3', '1-1.3.3'].
191
+
192
+ For a OT-2_OG without a USB hub connected to a port, the USB
193
+ port path will look like: `1-1.3/1-1.3`. This will become the
194
+ following 1 port node: ['1-1.3'].
195
+
196
+ We only need one unique id here, so we will filter out duplicates.
197
+
198
+ :param full_name: Full path of the physical USB Path
199
+ :returns: List of separated USB port paths
200
+ """
201
+ all_match = HUB_PATTERN.findall(full_name)
202
+ match_set = []
203
+ for match in all_match:
204
+ if match not in match_set:
205
+ match_set.append(match)
206
+ return match_set
207
+
208
+ @staticmethod
209
+ def map_to_revision(
210
+ board_revision: BoardRevision,
211
+ port_info: Tuple[Optional[int], int, Optional[int]],
212
+ ) -> Tuple[bool, str, int, Optional[int]]:
213
+ """
214
+ Synthesize the hub, port_group, and hub_port data for a USB port
215
+ from the hub and hub_port data.
216
+
217
+ If a USB hub is connected to a port, the hub data field is True
218
+ and the hub_port data field is populated. Otherwise, the hub
219
+ data field is False and the hub_port data field is None.
220
+
221
+ For the OT-2, there is only one bank of USB ports, so the
222
+ port_group is always MAIN. For the Flex, there are LEFT, RIGHT,
223
+ and FRONT USB port banks, which map to specific hub values.
224
+
225
+ For the Flex, the RIGHT port values are increased by 4 to match
226
+ the physical hardware labeling (USB5 - USB8).
227
+
228
+ :param port_info: Tuple of the hub, port number, and hub port
229
+ :returns: Tuple of the hub, port group, port number, and hub port
230
+ """
231
+ hub, port, hub_port = port_info
232
+ if board_revision == BoardRevision.OG:
233
+ if hub:
234
+ return (
235
+ True,
236
+ PortGroup.MAIN,
237
+ REV_OG_USB_PORTS.get(str(port), port),
238
+ hub_port,
239
+ )
240
+ else:
241
+ return (
242
+ False,
243
+ PortGroup.MAIN,
244
+ REV_OG_USB_PORTS.get(str(port), port),
245
+ None,
246
+ )
247
+ elif board_revision == BoardRevision.FLEX_B2:
248
+ if hub == FLEX_B2_USB_PORT_GROUP_LEFT:
249
+ port_group = PortGroup.LEFT
250
+ port = FLEX_B2_USB_PORTS.get(str(port), port)
251
+ elif hub == FLEX_B2_USB_PORT_GROUP_RIGHT:
252
+ port_group = PortGroup.RIGHT
253
+ port = FLEX_B2_USB_PORTS.get(str(port), port)
254
+ port = port + 4
255
+ elif hub == FLEX_B2_USB_PORT_GROUP_FRONT:
256
+ port_group = PortGroup.FRONT
257
+ else:
258
+ port_group = PortGroup.UNKNOWN
259
+ if hub_port:
260
+ return True, port_group, port, hub_port
261
+ else:
262
+ return False, port_group, port, None
263
+ else: # any variant of OT2-Refresh
264
+ if hub_port:
265
+ return True, PortGroup.MAIN, port, hub_port
266
+ else:
267
+ return False, PortGroup.MAIN, port, None
268
+
269
+ def __hash__(self) -> int:
270
+ """
271
+ Hash function.
272
+
273
+ To have a unique set of nodes, they must
274
+ all have a unique hash. Lists are not
275
+ hashable which is why we need to unpack
276
+ the list here.
277
+ """
278
+ return hash(self.name)
279
+
280
+
281
+ class GPIOPin:
282
+ @classmethod
283
+ def build(cls, name: str, in_out: PinDir, pin: int) -> GPIOPin:
284
+ # use this method if the pin number is the same
285
+ # across all board revisions
286
+ return cls(name, in_out, rev_og=pin, rev_a=pin, rev_b=pin, rev_c=pin)
287
+
288
+ @classmethod
289
+ def build_with_rev(
290
+ cls, name: str, in_out: PinDir, **kwargs: Optional[int]
291
+ ) -> GPIOPin:
292
+ return cls(name, in_out, **kwargs)
293
+
294
+ def __init__(
295
+ self,
296
+ name: str,
297
+ in_out: PinDir,
298
+ rev_og: Optional[int] = None,
299
+ rev_a: Optional[int] = None,
300
+ rev_b: Optional[int] = None,
301
+ rev_c: Optional[int] = None,
302
+ ):
303
+ self.name = name
304
+ self.in_out = in_out
305
+ self.rev_og = rev_og
306
+ self.rev_a = rev_a
307
+ self.rev_b = rev_b
308
+ self.rev_c = rev_c
309
+
310
+ def by_board_rev(self, board_rev: BoardRevision) -> Optional[int]:
311
+ ref = {
312
+ BoardRevision.OG: self.rev_og,
313
+ BoardRevision.A: self.rev_a,
314
+ BoardRevision.B: self.rev_b,
315
+ BoardRevision.C: self.rev_c,
316
+ BoardRevision.UNKNOWN: self.rev_og,
317
+ }
318
+ return ref[board_rev]
319
+
320
+
321
+ class GPIOGroup:
322
+ def __init__(self, pins: List[GPIOPin]):
323
+ self.pins = pins
324
+
325
+ def __getattr__(self, item: str) -> GPIOPin:
326
+ res = next(filter(lambda x: x.name is item, self.pins), None)
327
+ assert res, f"Failed to find GPIOPin named: {item}"
328
+ return res
329
+
330
+ def by_type(self, pin_dir: PinDir) -> GPIOGroup:
331
+ return GPIOGroup(list(filter(lambda x: x.in_out is pin_dir, self.pins)))
332
+
333
+ def by_names(self, names: List[str]) -> GPIOGroup:
334
+ return GPIOGroup(list(filter(lambda x: x.name in names, self.pins)))
335
+
336
+ def group_by_pins(self, board_rev: BoardRevision) -> List[List[GPIOPin]]:
337
+ c = groupby(self.pins, key=lambda x: x.by_board_rev(board_rev))
338
+ l: List[List[GPIOPin]] = []
339
+ for k, v in c:
340
+ l.append(list(v))
341
+ return l
342
+
343
+
344
+ gpio_group = GPIOGroup(
345
+ [
346
+ # revision pins (input)
347
+ GPIOPin.build("rev_0", PinDir.rev_input, 17),
348
+ GPIOPin.build("rev_1", PinDir.rev_input, 27),
349
+ # output pins
350
+ GPIOPin.build("frame_leds", PinDir.output, 6),
351
+ GPIOPin.build("blue_button", PinDir.output, 13),
352
+ GPIOPin.build("halt", PinDir.output, 18),
353
+ GPIOPin.build("green_button", PinDir.output, 19),
354
+ GPIOPin.build("audio_enable", PinDir.output, 21),
355
+ GPIOPin.build("isp", PinDir.output, 23),
356
+ GPIOPin.build("reset", PinDir.output, 24),
357
+ GPIOPin.build("red_button", PinDir.output, 26),
358
+ # input pins
359
+ GPIOPin.build("button_input", PinDir.input, 5),
360
+ GPIOPin.build_with_rev("door_sw_filt", PinDir.input, rev_og=20, rev_a=12),
361
+ GPIOPin.build_with_rev("window_sw_filt", PinDir.input, rev_og=20, rev_a=16),
362
+ GPIOPin.build("window_door_sw", PinDir.input, 20),
363
+ ]
364
+ )
@@ -0,0 +1,102 @@
1
+ """
2
+ USB Driver.
3
+
4
+ A class to convert info from the usb bus into a
5
+ more readable format.
6
+ """
7
+
8
+ import subprocess
9
+ import os
10
+ from typing import List, Union
11
+
12
+ from opentrons.hardware_control.modules.types import (
13
+ ModuleAtPort,
14
+ SimulatingModuleAtPort,
15
+ )
16
+ from opentrons.hardware_control.types import BoardRevision
17
+
18
+ from .interfaces import USBDriverInterface
19
+ from .types import BUS_PATH, USBPort
20
+
21
+
22
+ class USBBus(USBDriverInterface):
23
+ def __init__(self, board_revision: BoardRevision):
24
+ self._board_revision = board_revision
25
+
26
+ @staticmethod
27
+ def _read_bus() -> List[str]:
28
+ """
29
+ Read the USB Bus information.
30
+
31
+ Use the sys bus path to find all of the USBs with
32
+ active devices connected to them.
33
+ """
34
+ read = [""]
35
+ try:
36
+ read = (
37
+ subprocess.check_output(["find", BUS_PATH, "-name", "dev"])
38
+ .decode()
39
+ .splitlines()
40
+ )
41
+ except Exception:
42
+ pass
43
+ return read
44
+
45
+ @staticmethod
46
+ def _read_symlink(virtual_port: str) -> str:
47
+ """ """
48
+ symlink = ""
49
+ try:
50
+ symlink = os.readlink(virtual_port)
51
+ except OSError:
52
+ pass
53
+ return symlink
54
+
55
+ def _read_usb_bus(self) -> List[USBPort]:
56
+ """
57
+ Read usb bus
58
+
59
+ Take the value returned from the USB bus and match
60
+ the paths to the expected port paths for modules.
61
+ :returns: A list of matching ports as dataclasses
62
+ """
63
+ active_ports = self._read_bus()
64
+ port_matches = []
65
+ for port in active_ports:
66
+ usb_port = USBPort.build(port.strip("/"), self._board_revision)
67
+ if usb_port:
68
+ port_matches.append(usb_port)
69
+ return port_matches
70
+
71
+ def match_virtual_ports(
72
+ self,
73
+ virtual_ports: Union[List[ModuleAtPort], List[SimulatingModuleAtPort]],
74
+ ) -> Union[List[ModuleAtPort], List[SimulatingModuleAtPort]]:
75
+ """
76
+ Match Virtual Ports
77
+
78
+ Given a list of virtual module ports, look up the
79
+ symlink to find the device path and link that to
80
+ the physical usb port information.
81
+ The virtual port path looks something like:
82
+ dev/ot_module_[MODULE NAME]
83
+ :param virtual_ports: A list of ModuleAtPort or SimulatingModuleAtPort objects
84
+ that hold the name and virtual port of each module
85
+ connected to the robot.
86
+
87
+ :returns: The updated list of ModuleAtPort
88
+ dataclasses with the physical usb port
89
+ information updated.
90
+ """
91
+ actual_ports = self._read_usb_bus()
92
+ sorted_virtual_ports = []
93
+
94
+ for p in actual_ports:
95
+ for vp in virtual_ports:
96
+ serial_port = self._read_symlink(vp.port)
97
+ if serial_port in p.device_path:
98
+ vp.usb_port = p
99
+ sorted_virtual_ports.append(vp)
100
+ break
101
+
102
+ return sorted_virtual_ports or virtual_ports
@@ -0,0 +1,22 @@
1
+ """
2
+ USB Simulating Driver.
3
+
4
+ A class to convert info from the usb bus into a
5
+ more readable format.
6
+ """
7
+ from typing import List, Union
8
+
9
+ from opentrons.hardware_control.modules.types import (
10
+ ModuleAtPort,
11
+ SimulatingModuleAtPort,
12
+ )
13
+
14
+ from .interfaces import USBDriverInterface
15
+
16
+
17
+ class USBBusSimulator(USBDriverInterface):
18
+ def match_virtual_ports(
19
+ self,
20
+ virtual_port: Union[List[ModuleAtPort], List[SimulatingModuleAtPort]],
21
+ ) -> Union[List[ModuleAtPort], List[SimulatingModuleAtPort]]:
22
+ return virtual_port
@@ -0,0 +1,151 @@
1
+ from typing import List, Optional, Iterator
2
+
3
+ import serial # type: ignore[import-untyped]
4
+ from serial import Serial
5
+ from serial.tools import list_ports # type: ignore[import-untyped]
6
+ import contextlib
7
+ import logging
8
+
9
+ from serial.tools.list_ports_common import ListPortInfo # type: ignore[import-untyped]
10
+
11
+ log = logging.getLogger(__name__)
12
+
13
+ RECOVERY_TIMEOUT = 10
14
+ DEFAULT_SERIAL_TIMEOUT = 5
15
+ DEFAULT_WRITE_TIMEOUT = 30
16
+
17
+
18
+ class SerialNoResponse(Exception):
19
+ pass
20
+
21
+
22
+ def get_ports_by_name(device_name: str) -> List[str]:
23
+ """Returns all serial devices with a given name"""
24
+ filtered_devices = filter(
25
+ lambda device: device_name in device[1], list_ports.comports()
26
+ )
27
+ device_ports = [device[0] for device in filtered_devices]
28
+ return device_ports
29
+
30
+
31
+ def get_port_by_VID(vid: str) -> Optional[ListPortInfo]:
32
+ """Returns first serial device with a given VID"""
33
+ for d in list_ports.comports():
34
+ if d.vid == vid:
35
+ return d[0]
36
+ return None
37
+
38
+
39
+ @contextlib.contextmanager
40
+ def serial_with_temp_timeout(
41
+ serial_connection: Serial, timeout: float
42
+ ) -> Iterator[Serial]:
43
+ """Implements a temporary timeout for a serial connection"""
44
+ saved_timeout = serial_connection.timeout
45
+ if timeout is not None:
46
+ serial_connection.timeout = timeout
47
+ try:
48
+ yield serial_connection
49
+ finally:
50
+ serial_connection.timeout = saved_timeout
51
+
52
+
53
+ def _parse_serial_response(response: bytes, ack: bytes) -> Optional[bytes]:
54
+ if ack in response:
55
+ parsed_response = response.split(ack)[0]
56
+ return parsed_response.strip()
57
+ else:
58
+ return None
59
+
60
+
61
+ def clear_buffer(serial_connection: Serial) -> None:
62
+ serial_connection.reset_input_buffer()
63
+
64
+
65
+ def _write_to_device_and_return(
66
+ cmd: str, ack: str, device_connection: Serial, tag: Optional[str] = None
67
+ ) -> str:
68
+ """Writes to a serial device.
69
+ - Formats command
70
+ - Wait for ack return
71
+ - return parsed response"""
72
+
73
+ if not tag:
74
+ tag = device_connection.port
75
+
76
+ encoded_write = cmd.encode()
77
+ encoded_ack = ack.encode()
78
+ log.debug(f"{tag}: Write -> {encoded_write!r}")
79
+ device_connection.write(encoded_write)
80
+ response = device_connection.read_until(encoded_ack)
81
+ log.debug(f"{tag}: Read <- {response}")
82
+ if encoded_ack not in response:
83
+ log.warning(f"{tag}: timed out after {device_connection.timeout}")
84
+ raise SerialNoResponse(
85
+ "No response from serial port after {} second(s)".format(
86
+ device_connection.timeout
87
+ )
88
+ )
89
+ clean_response = _parse_serial_response(response, encoded_ack)
90
+ if clean_response:
91
+ return clean_response.decode()
92
+ return ""
93
+
94
+
95
+ def _connect(port_name: str, baudrate: int) -> Serial:
96
+ ser = serial.serial_for_url(
97
+ url=port_name, baudrate=baudrate, timeout=DEFAULT_SERIAL_TIMEOUT
98
+ )
99
+ log.debug(ser)
100
+ return ser
101
+
102
+
103
+ def _attempt_command_recovery(
104
+ command: str, ack: str, serial_conn: Serial, tag: Optional[str] = None
105
+ ) -> str:
106
+ """Recovery after following a failed write_and_return() attempt"""
107
+ if not tag:
108
+ tag = serial_conn.port
109
+ with serial_with_temp_timeout(serial_conn, RECOVERY_TIMEOUT) as device:
110
+ response = _write_to_device_and_return(command, ack, device, tag=tag)
111
+ if response is None:
112
+ log.debug(f"{tag}: No valid response during _attempt_command_recovery")
113
+ raise RuntimeError(
114
+ "Recovery attempted - no valid serial response "
115
+ "for command: {} in {} seconds".format(command.encode(), RECOVERY_TIMEOUT)
116
+ )
117
+ return response
118
+
119
+
120
+ def write_and_return(
121
+ command: str,
122
+ ack: str,
123
+ serial_connection: Serial,
124
+ timeout: int = DEFAULT_WRITE_TIMEOUT,
125
+ tag: Optional[str] = None,
126
+ ) -> str:
127
+ """Write a command and return the response"""
128
+ clear_buffer(serial_connection)
129
+ with serial_with_temp_timeout(serial_connection, timeout) as device_connection:
130
+ response = _write_to_device_and_return(command, ack, device_connection, tag)
131
+ return response
132
+
133
+
134
+ def connect(
135
+ device_name: str, port: Optional[str] = None, baudrate: int = 115200
136
+ ) -> Serial:
137
+ """
138
+ Creates a serial connection.
139
+
140
+ Args:
141
+ device_name: defaults to 'Smoothieboard'
142
+ port: the optional port
143
+ baudrate: integer frequency for serial communication
144
+
145
+ Returns:
146
+ serial.Serial connection
147
+ """
148
+ if not port:
149
+ port = get_ports_by_name(device_name=device_name)[0]
150
+ log.debug("Device name: {}, Port: {}".format(device_name, port))
151
+ return _connect(port_name=port, baudrate=baudrate)
@@ -0,0 +1,4 @@
1
+ from .driver_3_0 import SmoothieDriver
2
+ from .simulator import SimulatingDriver
3
+
4
+ __all__ = ["SmoothieDriver", "SimulatingDriver"]
@@ -0,0 +1,51 @@
1
+ import logging
2
+
3
+ from opentrons.drivers.asyncio.communication import SerialConnection
4
+
5
+
6
+ log = logging.getLogger(__name__)
7
+
8
+
9
+ class RemoveUnwantedCharactersMixin:
10
+ """Mixin that removes echoed command and other unwanted characters
11
+ from the response."""
12
+
13
+ def process_raw_response(self, command: str, response: str) -> str:
14
+ """Process the raw response."""
15
+ return self._remove_unwanted_characters(command=command, response=response)
16
+
17
+ @staticmethod
18
+ def _remove_unwanted_characters(command: str, response: str) -> str:
19
+ # smoothieware can enter a weird state, where it repeats back
20
+ # the sent command at the beginning of its response.
21
+ # Check for this echo, and strips the command from the response
22
+ def _is_token_command(_s: str) -> bool:
23
+ """check if token is a command"""
24
+ # A single letter token cannot be assumed to be a command.
25
+ # For example: "M369 L" response is "L:2132121212".
26
+ return len(_s) > 1
27
+
28
+ # Split at spaces.
29
+ tokens = (c.strip() for c in command.strip().split(" "))
30
+ # A list of commands to remove from response. Including the entire
31
+ # command.
32
+ remove_from_response = [command] + [c for c in tokens if _is_token_command(c)]
33
+
34
+ # also removing any inadvertent newline/return characters
35
+ # this is ok because all data we need from Smoothie is returned on
36
+ # the first line in the response
37
+ remove_from_response += ["\r", "\n"]
38
+ modified_response = str(response)
39
+
40
+ for cmd in remove_from_response:
41
+ modified_response = modified_response.replace(cmd, "")
42
+
43
+ if modified_response != response:
44
+ log.debug(f"Removed characters from response: {response}")
45
+ log.debug(f"Newly formatted response: {modified_response}")
46
+
47
+ return modified_response.strip()
48
+
49
+
50
+ class SmoothieConnection(RemoveUnwantedCharactersMixin, SerialConnection):
51
+ pass