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,274 @@
1
+ """Module Firmware update script."""
2
+ import argparse
3
+ import asyncio
4
+ from glob import glob
5
+ import os
6
+ import re
7
+ import subprocess
8
+ import sys
9
+ from typing import Dict, Final, List, Optional
10
+
11
+ from opentrons.drivers.rpi_drivers import usb
12
+ from opentrons.hardware_control.module_control import MODULE_PORT_REGEX
13
+ from opentrons.hardware_control import modules
14
+ from opentrons.hardware_control.modules.mod_abc import AbstractModule
15
+ from opentrons.hardware_control.modules.update import update_firmware
16
+ from opentrons.hardware_control.types import BoardRevision
17
+
18
+
19
+ # Constants for checking if module is back online
20
+ ONLINE_RETRIES = 3
21
+ DELAY_S = 5
22
+
23
+
24
+ MODULES: Final[Dict[str, str]] = {
25
+ "temp-deck": "tempdeck",
26
+ "mag-deck": "magdeck",
27
+ "thermocycler": "thermocycler",
28
+ "heater-shaker": "heatershaker",
29
+ "absorbance-reader": "absorbancereader",
30
+ "flex-stacker": "flexstacker",
31
+ }
32
+
33
+
34
+ def parse_version(filepath: str) -> str:
35
+ """Parse the version string from the filename."""
36
+ _, ext = os.path.splitext(os.path.basename(filepath))
37
+ ext_pattern = re.escape(ext.lstrip("."))
38
+ pattern = rf"@(v\d+(?:\.\d+)*)\.{ext_pattern}"
39
+ match = re.search(pattern, os.path.basename(filepath))
40
+ return match.group(1) if match else ""
41
+
42
+
43
+ def scan_connected_modules() -> List[modules.ModuleAtPort]:
44
+ """Scan for connected modules and return list of
45
+ tuples of serial ports and device names
46
+ """
47
+ discovered_modules = []
48
+ devices = glob("/dev/ot_module*")
49
+ for port in devices:
50
+ symlink_port = port.split("dev/")[1]
51
+ module_at_port = get_module_at_port(symlink_port)
52
+ if module_at_port:
53
+ discovered_modules.append(module_at_port)
54
+ return discovered_modules
55
+
56
+
57
+ def get_module_at_port(port: str) -> Optional[modules.ModuleAtPort]:
58
+ """Given a port, returns either a ModuleAtPort
59
+ if it is a recognized module, or None if not recognized.
60
+ """
61
+ match = MODULE_PORT_REGEX.search(port)
62
+ if match:
63
+ name = match.group(1).lower()
64
+ if name not in modules.MODULE_TYPE_BY_NAME:
65
+ print(f"Unexpected module connected: {name} on {port}")
66
+ return None
67
+ return modules.ModuleAtPort(port=f"/dev/{port}", name=name)
68
+ return None
69
+
70
+
71
+ async def build_module(
72
+ mod: modules.ModuleAtPort, loop: asyncio.AbstractEventLoop
73
+ ) -> Optional[AbstractModule]:
74
+ try:
75
+ # Get the device path and
76
+ port = subprocess.check_output(["readlink", "-f", mod.port]).decode().strip()
77
+ # remove the symlink for the device, so its freed by the robot-server
78
+ print(f"Removing symlink {mod.port}")
79
+ subprocess.check_call(["unlink", mod.port])
80
+ # wwait some time to let the device teardown
81
+ await asyncio.sleep(2)
82
+ # create an instance of the module using the device path
83
+ return await modules.build(
84
+ port=port,
85
+ usb_port=mod.usb_port,
86
+ type=modules.MODULE_TYPE_BY_NAME[mod.name],
87
+ simulating=False,
88
+ hw_control_loop=loop,
89
+ )
90
+ except Exception:
91
+ return None
92
+
93
+
94
+ async def teardown_module(module: AbstractModule) -> None:
95
+ """Tearsdown the module so it can be used again by the robot-server.."""
96
+ name = module.name()
97
+ serial = module.device_info["serial"]
98
+ port_name = module.usb_port.name
99
+ command = f"echo '{port_name}' | tee /sys/bus/usb/drivers/usb"
100
+ print(f"Removing module: {name} {serial}")
101
+ try:
102
+ # stop the poller and disconnect serial
103
+ await module._poller.stop() # type: ignore
104
+ await module._driver.disconnect() # type: ignore
105
+ # unbind the device from usb and re-bind to simulate unplug
106
+ subprocess.run(f"{command}/unbind", shell=True, capture_output=True)
107
+ await asyncio.sleep(2)
108
+ subprocess.run(f"{command}/bind", shell=True, capture_output=True)
109
+ except Exception:
110
+ pass
111
+
112
+
113
+ def enable_udev_rules(enable: bool) -> None:
114
+ """Enable/Disable creation of opentrons modules by the hardware controller.
115
+
116
+ This is done so the module is not automatically picked up by the server
117
+ while we are updating it.
118
+ """
119
+ rule = "95-opentrons-modules.rules"
120
+ original = f"/etc/udev/rules.d/{rule}"
121
+ destination = f"/var/lib/{rule}"
122
+ src = original if not enable else destination
123
+ dst = destination if not enable else original
124
+ msg = "Disabl" if not enable else "Enabl"
125
+ if not os.path.exists(src):
126
+ sys.exit(f"ERROR: Rule file not found: {src}")
127
+
128
+ try:
129
+ print(f"{msg}ing udev: Moving rule {src} -> {dst}")
130
+ subprocess.check_call(["mount", "-o", "remount,rw", "/"])
131
+ subprocess.check_call(["mv", src, dst])
132
+ except Exception as e:
133
+ sys.exit(
134
+ f"ERROR: Could not {msg}e udev rule: {rule}\n{e}",
135
+ )
136
+ finally:
137
+ subprocess.check_call(["mount", "-o", "remount,ro", "/"])
138
+ subprocess.check_call(["udevadm", "control", "--reload-rules"])
139
+
140
+
141
+ def check_dev_exist(port: str) -> bool:
142
+ """True if the device with the given port exists in /dev."""
143
+ try:
144
+ return subprocess.run(["ls", port], capture_output=True).returncode == 0
145
+ except Exception:
146
+ return False
147
+
148
+
149
+ async def main(args: argparse.Namespace) -> None: # noqa: C901
150
+ """Entry point for script."""
151
+ mod_name = MODULES[args.module]
152
+ target_version = parse_version(args.file)
153
+ if not os.path.exists(args.file):
154
+ sys.exit(f"Invalid filepath: {args.file}")
155
+ if not target_version:
156
+ sys.exit(f"Target version could not be parsed from file: {args.file}")
157
+
158
+ print("Setting up...")
159
+ loop = asyncio.get_running_loop()
160
+ usb_bus = usb.USBBus(BoardRevision.FLEX_B2) # todo: get this from the robot
161
+ print(f"Searching for {mod_name} modules in /dev/")
162
+ mods = scan_connected_modules()
163
+ mods = usb_bus.match_virtual_ports(mods) # type: ignore
164
+ if not mods:
165
+ print("No modules found")
166
+ return
167
+
168
+ # Disable udev rules so modules aren't re-created by the server when they update
169
+ teardown_modules: List[AbstractModule] = []
170
+ enable_udev_rules(False)
171
+ print("\n------------------------------------------")
172
+ for mod in mods:
173
+ if mod_name not in mod.name:
174
+ continue
175
+
176
+ # Create an instance of the opentrons module
177
+ print(f"Found mod: {mod.name} at {mod.port}")
178
+ module = await build_module(mod, loop)
179
+ if module is None:
180
+ continue
181
+
182
+ name = module.name()
183
+ version = module.device_info["version"]
184
+ serial = module.device_info["serial"]
185
+ model = module.device_info["model"]
186
+ teardown_modules.append(module)
187
+ print(f"Created module: {module.name()} {model} {serial} {version}")
188
+
189
+ # Check that the update file is for this module
190
+ file_prefix = module.firmware_prefix()
191
+ if file_prefix not in args.file:
192
+ print(f"ERROR: Target module does not match file: {mod_name} {args.file}")
193
+ continue
194
+
195
+ # Check if the module is one we care about
196
+ if args.serial and serial not in args.serial:
197
+ continue
198
+
199
+ # Check if the module needs an update
200
+ if version == target_version and not args.force:
201
+ print(f"Module {name} {serial} is up-to-date.")
202
+ continue
203
+
204
+ print(f"Updating {name} {model} {serial}: {version} -> {target_version}")
205
+ await update_firmware(module, args.file)
206
+
207
+ # wait for the device to come online
208
+ for retry in range(ONLINE_RETRIES):
209
+ if retry >= ONLINE_RETRIES:
210
+ print(f"Module {serial} failed to come back online.")
211
+ break
212
+
213
+ print(f"Checking if {name} at {module.port} is online...")
214
+ await asyncio.sleep(DELAY_S)
215
+ if not check_dev_exist(module.port):
216
+ print("Not online")
217
+ continue
218
+
219
+ # re-open serial connection
220
+ if not await module._driver.is_connected(): # type: ignore
221
+ await module._driver.connect() # type: ignore
222
+
223
+ # refresh the device info
224
+ print(f"Device {module.port} is back online, refreshing device info.")
225
+ device_info = (await module._driver.get_device_info()).to_dict() # type: ignore
226
+ success = device_info["version"] == target_version
227
+ msg = "updated successfully!" if success else "failed to update"
228
+ print(f"Device {name} {serial} {msg}")
229
+ break
230
+
231
+ print("------------------------------------------\n")
232
+ print("Tearing down")
233
+ # Enable udev rules and teardown the module so they can be pick-up by the robot-server
234
+ enable_udev_rules(True)
235
+ for module in teardown_modules:
236
+ await teardown_module(module)
237
+ print("Done")
238
+
239
+
240
+ if __name__ == "__main__":
241
+ parser = argparse.ArgumentParser(description="Module FW Update.")
242
+ parser.add_argument(
243
+ "--module",
244
+ help="The module target to be updated.",
245
+ type=str,
246
+ required=True,
247
+ choices=MODULES.keys(),
248
+ )
249
+ parser.add_argument(
250
+ "--file",
251
+ help="""Path to binary file containing the FW executable"""
252
+ """Must have format `module-name@vx.x.x.bin/hex`, ex, flex-stacker@v0.0.1.bin""",
253
+ type=str,
254
+ required=True,
255
+ )
256
+ parser.add_argument(
257
+ "--serial",
258
+ help="The specific serial numbers of the devices to update.",
259
+ type=str,
260
+ nargs="+",
261
+ )
262
+ parser.add_argument(
263
+ "--force",
264
+ help="Force install the update, even if the versions are the same.",
265
+ action="store_true",
266
+ default=False,
267
+ )
268
+ args = parser.parse_args()
269
+ try:
270
+ asyncio.run(main(args))
271
+ except Exception as e:
272
+ print("ERROR: Unhandled Exception: ", e)
273
+ # Re-enable udev rules
274
+ enable_udev_rules(True)
@@ -0,0 +1,260 @@
1
+ import asyncio
2
+ from typing import Dict, Optional, Any, List, Union
3
+ from typing_extensions import Literal
4
+ from dataclasses import dataclass, asdict, field, replace
5
+ import json
6
+ from pathlib import Path
7
+ from warnings import warn
8
+
9
+ from opentrons.config import robot_configs
10
+ from opentrons.config.types import RobotConfig, OT3Config
11
+ from opentrons.types import Mount
12
+ from opentrons.hardware_control import API, HardwareControlAPI, ThreadManager
13
+ from opentrons.hardware_control.types import OT3Mount, HardwareFeatureFlags
14
+ from opentrons.hardware_control.modules import SimulatingModule
15
+
16
+
17
+ # Name and kwargs for a module function
18
+ @dataclass(frozen=True)
19
+ class ModuleCall:
20
+ function_name: str
21
+ args: List[Any] = field(default_factory=list)
22
+ kwargs: Dict[str, Any] = field(default_factory=dict)
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class ModuleItem:
27
+ serial_number: str
28
+ model: str
29
+ calls: List[ModuleCall] = field(default_factory=list)
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class OT2SimulatorSetup:
34
+ machine: Literal["OT-2 Standard"] = "OT-2 Standard"
35
+ attached_instruments: Dict[Mount, Dict[str, Optional[str]]] = field(
36
+ default_factory=dict
37
+ )
38
+ attached_modules: Dict[str, List[ModuleItem]] = field(default_factory=dict)
39
+ config: Optional[RobotConfig] = None
40
+ strict_attached_instruments: bool = True
41
+
42
+
43
+ @dataclass(frozen=True)
44
+ class OT3SimulatorSetup:
45
+ machine: Literal["OT-3 Standard"] = "OT-3 Standard"
46
+ attached_instruments: Dict[OT3Mount, Dict[str, Optional[str]]] = field(
47
+ default_factory=dict
48
+ )
49
+ attached_modules: Dict[str, List[ModuleItem]] = field(default_factory=dict)
50
+ config: Optional[OT3Config] = None
51
+ strict_attached_instruments: bool = True
52
+
53
+
54
+ SimulatorSetup = Union[OT2SimulatorSetup, OT3SimulatorSetup]
55
+
56
+
57
+ async def _simulator_for_setup(
58
+ setup: SimulatorSetup, loop: Optional[asyncio.AbstractEventLoop]
59
+ ) -> HardwareControlAPI:
60
+ if setup.machine == "OT-2 Standard":
61
+ return await API.build_hardware_simulator(
62
+ attached_instruments=setup.attached_instruments,
63
+ attached_modules={
64
+ k: [
65
+ SimulatingModule(serial_number=m.serial_number, model=m.model)
66
+ for m in v
67
+ ]
68
+ for k, v in setup.attached_modules.items()
69
+ },
70
+ config=setup.config,
71
+ strict_attached_instruments=setup.strict_attached_instruments,
72
+ loop=loop,
73
+ feature_flags=HardwareFeatureFlags.build_from_ff(),
74
+ )
75
+ else:
76
+ from opentrons.hardware_control.ot3api import OT3API
77
+
78
+ return await OT3API.build_hardware_simulator(
79
+ attached_instruments=setup.attached_instruments,
80
+ attached_modules={
81
+ k: [
82
+ SimulatingModule(serial_number=m.serial_number, model=m.model)
83
+ for m in v
84
+ ]
85
+ for k, v in setup.attached_modules.items()
86
+ },
87
+ config=setup.config,
88
+ strict_attached_instruments=setup.strict_attached_instruments,
89
+ loop=loop,
90
+ feature_flags=HardwareFeatureFlags.build_from_ff(),
91
+ )
92
+
93
+
94
+ async def create_simulator(
95
+ setup: SimulatorSetup, loop: Optional[asyncio.AbstractEventLoop] = None
96
+ ) -> HardwareControlAPI:
97
+ """Create a simulator"""
98
+ simulator = await _simulator_for_setup(setup, loop)
99
+ for attached_module in simulator.attached_modules:
100
+ modules = setup.attached_modules[attached_module.name()]
101
+ for module in modules:
102
+ if module.serial_number == attached_module.device_info.get("serial"):
103
+ for call in module.calls:
104
+ f = getattr(attached_module, call.function_name)
105
+ await f(*call.args, **call.kwargs)
106
+
107
+ return simulator
108
+
109
+
110
+ async def load_simulator(
111
+ path: Path, loop: Optional[asyncio.AbstractEventLoop] = None
112
+ ) -> HardwareControlAPI:
113
+ """Create a simulator from a JSON file."""
114
+ return await create_simulator(setup=load_simulator_setup(path), loop=loop)
115
+
116
+
117
+ def _thread_manager_for_setup(
118
+ setup: SimulatorSetup,
119
+ ) -> ThreadManager[HardwareControlAPI]:
120
+ if setup.machine == "OT-2 Standard":
121
+ return ThreadManager(
122
+ API.build_hardware_simulator,
123
+ attached_instruments=setup.attached_instruments,
124
+ attached_modules={
125
+ k: [
126
+ SimulatingModule(serial_number=m.serial_number, model=m.model)
127
+ for m in v
128
+ ]
129
+ for k, v in setup.attached_modules.items()
130
+ },
131
+ config=setup.config,
132
+ strict_attached_instruments=setup.strict_attached_instruments,
133
+ feature_flags=HardwareFeatureFlags.build_from_ff(),
134
+ )
135
+ else:
136
+ from opentrons.hardware_control.ot3api import OT3API
137
+
138
+ return ThreadManager(
139
+ OT3API.build_hardware_simulator,
140
+ attached_instruments=setup.attached_instruments,
141
+ attached_modules={
142
+ k: [
143
+ SimulatingModule(serial_number=m.serial_number, model=m.model)
144
+ for m in v
145
+ ]
146
+ for k, v in setup.attached_modules.items()
147
+ },
148
+ config=setup.config,
149
+ strict_attached_instruments=setup.strict_attached_instruments,
150
+ feature_flags=HardwareFeatureFlags.build_from_ff(),
151
+ )
152
+
153
+
154
+ async def create_simulator_thread_manager(
155
+ setup: SimulatorSetup,
156
+ ) -> ThreadManager[HardwareControlAPI]:
157
+ """Create a simulator thread manager from a loaded config."""
158
+ thread_manager = _thread_manager_for_setup(setup)
159
+ await thread_manager.managed_thread_ready_async()
160
+
161
+ for attached_module in thread_manager.wrapped().attached_modules:
162
+ modules = setup.attached_modules[attached_module.name()]
163
+ for module in modules:
164
+ for call in module.calls:
165
+ f = getattr(attached_module, call.function_name)
166
+ await f(*call.args, **call.kwargs)
167
+
168
+ return thread_manager
169
+
170
+
171
+ async def load_simulator_thread_manager(
172
+ path: Path,
173
+ ) -> ThreadManager[HardwareControlAPI]:
174
+ """Create a simulator wrapped in a ThreadManager from a JSON file."""
175
+ return await create_simulator_thread_manager(load_simulator_setup(path))
176
+
177
+
178
+ def save_simulator_setup(simulator_setup: SimulatorSetup, path: Path) -> None:
179
+ """Write a simulator setup to a file."""
180
+ no_config = replace(simulator_setup, config=None)
181
+ as_dict = asdict(no_config)
182
+
183
+ as_dict["config"] = (
184
+ robot_configs.config_to_save(simulator_setup.config)
185
+ if simulator_setup.config
186
+ else None
187
+ )
188
+
189
+ if as_dict.get("attached_instruments", None):
190
+ as_dict["attached_instruments"] = {
191
+ mount.name.lower(): data
192
+ for mount, data in as_dict["attached_instruments"].items()
193
+ }
194
+
195
+ with path.open("w") as f:
196
+ json.dump(as_dict, f)
197
+
198
+
199
+ def load_simulator_setup(path: Path) -> SimulatorSetup:
200
+ """Load a simulator setup from a file."""
201
+ with path.open() as f:
202
+ obj = json.load(f)
203
+
204
+ if "machine" not in obj:
205
+ warn(
206
+ "Simulator configuration does not name a machine, defaulting to OT-2 Standard"
207
+ )
208
+ machine_type = obj.get("machine", "OT-2 Standard")
209
+ if machine_type == "OT-2 Standard":
210
+ return OT2SimulatorSetup(
211
+ **{k: _prepare_for_simulator_setup(k, v) for (k, v) in obj.items()}
212
+ )
213
+ else:
214
+ return OT3SimulatorSetup(
215
+ **{k: _prepare_for_ot3_simulator_setup(k, v) for (k, v) in obj.items()}
216
+ )
217
+
218
+
219
+ def _prepare_for_simulator_setup(key: str, value: Dict[str, Any]) -> Any:
220
+ """Convert value to a SimulatorSetup"""
221
+ if key == "attached_instruments" and value:
222
+ return {Mount[mount.upper()]: data for (mount, data) in value.items()}
223
+ if key == "config" and value:
224
+ return robot_configs.build_config_ot2(value)
225
+ if key == "attached_modules" and value:
226
+ attached_modules: Dict[str, List[ModuleItem]] = {}
227
+ for key, item in value.items():
228
+ for obj in item:
229
+ attached_modules.setdefault(key, []).append(
230
+ ModuleItem(
231
+ serial_number=obj["serial_number"],
232
+ model=obj["model"],
233
+ calls=[ModuleCall(**data) for data in obj["calls"]],
234
+ )
235
+ )
236
+
237
+ return attached_modules
238
+
239
+ return value
240
+
241
+
242
+ def _prepare_for_ot3_simulator_setup(key: str, value: Dict[str, Any]) -> Any:
243
+ if key == "attached_instruments" and value:
244
+ return {OT3Mount[mount.upper()]: data for (mount, data) in value.items()}
245
+ if key == "config" and value:
246
+ return robot_configs.build_config_ot3(value)
247
+ if key == "attached_modules" and value:
248
+ attached_modules: Dict[str, List[ModuleItem]] = {}
249
+ for key, item in value.items():
250
+ for obj in item:
251
+ attached_modules.setdefault(key, []).append(
252
+ ModuleItem(
253
+ serial_number=obj["serial_number"],
254
+ model=obj["model"],
255
+ calls=[ModuleCall(**data) for data in obj["calls"]],
256
+ )
257
+ )
258
+
259
+ return attached_modules
260
+ return value