opentrons 8.6.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of opentrons might be problematic. Click here for more details.

Files changed (600) hide show
  1. opentrons/__init__.py +150 -0
  2. opentrons/_version.py +34 -0
  3. opentrons/calibration_storage/__init__.py +54 -0
  4. opentrons/calibration_storage/deck_configuration.py +62 -0
  5. opentrons/calibration_storage/encoder_decoder.py +31 -0
  6. opentrons/calibration_storage/file_operators.py +142 -0
  7. opentrons/calibration_storage/helpers.py +103 -0
  8. opentrons/calibration_storage/ot2/__init__.py +34 -0
  9. opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
  10. opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
  11. opentrons/calibration_storage/ot2/models/__init__.py +0 -0
  12. opentrons/calibration_storage/ot2/models/v1.py +149 -0
  13. opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
  14. opentrons/calibration_storage/ot2/tip_length.py +281 -0
  15. opentrons/calibration_storage/ot3/__init__.py +31 -0
  16. opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
  17. opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
  18. opentrons/calibration_storage/ot3/models/__init__.py +0 -0
  19. opentrons/calibration_storage/ot3/models/v1.py +122 -0
  20. opentrons/calibration_storage/ot3/module_offset.py +138 -0
  21. opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
  22. opentrons/calibration_storage/types.py +45 -0
  23. opentrons/cli/__init__.py +21 -0
  24. opentrons/cli/__main__.py +5 -0
  25. opentrons/cli/analyze.py +501 -0
  26. opentrons/config/__init__.py +631 -0
  27. opentrons/config/advanced_settings.py +871 -0
  28. opentrons/config/defaults_ot2.py +214 -0
  29. opentrons/config/defaults_ot3.py +499 -0
  30. opentrons/config/feature_flags.py +86 -0
  31. opentrons/config/gripper_config.py +55 -0
  32. opentrons/config/reset.py +203 -0
  33. opentrons/config/robot_configs.py +187 -0
  34. opentrons/config/types.py +183 -0
  35. opentrons/drivers/__init__.py +0 -0
  36. opentrons/drivers/absorbance_reader/__init__.py +11 -0
  37. opentrons/drivers/absorbance_reader/abstract.py +72 -0
  38. opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
  39. opentrons/drivers/absorbance_reader/driver.py +81 -0
  40. opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
  41. opentrons/drivers/absorbance_reader/simulator.py +84 -0
  42. opentrons/drivers/asyncio/__init__.py +0 -0
  43. opentrons/drivers/asyncio/communication/__init__.py +22 -0
  44. opentrons/drivers/asyncio/communication/async_serial.py +183 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +552 -0
  47. opentrons/drivers/command_builder.py +102 -0
  48. opentrons/drivers/flex_stacker/__init__.py +13 -0
  49. opentrons/drivers/flex_stacker/abstract.py +214 -0
  50. opentrons/drivers/flex_stacker/driver.py +768 -0
  51. opentrons/drivers/flex_stacker/errors.py +68 -0
  52. opentrons/drivers/flex_stacker/simulator.py +309 -0
  53. opentrons/drivers/flex_stacker/types.py +367 -0
  54. opentrons/drivers/flex_stacker/utils.py +19 -0
  55. opentrons/drivers/heater_shaker/__init__.py +5 -0
  56. opentrons/drivers/heater_shaker/abstract.py +76 -0
  57. opentrons/drivers/heater_shaker/driver.py +204 -0
  58. opentrons/drivers/heater_shaker/simulator.py +94 -0
  59. opentrons/drivers/mag_deck/__init__.py +6 -0
  60. opentrons/drivers/mag_deck/abstract.py +44 -0
  61. opentrons/drivers/mag_deck/driver.py +208 -0
  62. opentrons/drivers/mag_deck/simulator.py +63 -0
  63. opentrons/drivers/rpi_drivers/__init__.py +33 -0
  64. opentrons/drivers/rpi_drivers/dev_types.py +94 -0
  65. opentrons/drivers/rpi_drivers/gpio.py +282 -0
  66. opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
  67. opentrons/drivers/rpi_drivers/interfaces.py +15 -0
  68. opentrons/drivers/rpi_drivers/types.py +364 -0
  69. opentrons/drivers/rpi_drivers/usb.py +102 -0
  70. opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
  71. opentrons/drivers/serial_communication.py +151 -0
  72. opentrons/drivers/smoothie_drivers/__init__.py +4 -0
  73. opentrons/drivers/smoothie_drivers/connection.py +51 -0
  74. opentrons/drivers/smoothie_drivers/constants.py +121 -0
  75. opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
  76. opentrons/drivers/smoothie_drivers/errors.py +49 -0
  77. opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
  78. opentrons/drivers/smoothie_drivers/simulator.py +99 -0
  79. opentrons/drivers/smoothie_drivers/types.py +16 -0
  80. opentrons/drivers/temp_deck/__init__.py +10 -0
  81. opentrons/drivers/temp_deck/abstract.py +54 -0
  82. opentrons/drivers/temp_deck/driver.py +197 -0
  83. opentrons/drivers/temp_deck/simulator.py +57 -0
  84. opentrons/drivers/thermocycler/__init__.py +12 -0
  85. opentrons/drivers/thermocycler/abstract.py +99 -0
  86. opentrons/drivers/thermocycler/driver.py +395 -0
  87. opentrons/drivers/thermocycler/simulator.py +126 -0
  88. opentrons/drivers/types.py +107 -0
  89. opentrons/drivers/utils.py +222 -0
  90. opentrons/execute.py +742 -0
  91. opentrons/hardware_control/__init__.py +65 -0
  92. opentrons/hardware_control/__main__.py +77 -0
  93. opentrons/hardware_control/adapters.py +98 -0
  94. opentrons/hardware_control/api.py +1347 -0
  95. opentrons/hardware_control/backends/__init__.py +7 -0
  96. opentrons/hardware_control/backends/controller.py +400 -0
  97. opentrons/hardware_control/backends/errors.py +9 -0
  98. opentrons/hardware_control/backends/estop_state.py +164 -0
  99. opentrons/hardware_control/backends/flex_protocol.py +497 -0
  100. opentrons/hardware_control/backends/ot3controller.py +1930 -0
  101. opentrons/hardware_control/backends/ot3simulator.py +900 -0
  102. opentrons/hardware_control/backends/ot3utils.py +664 -0
  103. opentrons/hardware_control/backends/simulator.py +442 -0
  104. opentrons/hardware_control/backends/status_bar_state.py +240 -0
  105. opentrons/hardware_control/backends/subsystem_manager.py +431 -0
  106. opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
  107. opentrons/hardware_control/backends/types.py +14 -0
  108. opentrons/hardware_control/constants.py +6 -0
  109. opentrons/hardware_control/dev_types.py +125 -0
  110. opentrons/hardware_control/emulation/__init__.py +0 -0
  111. opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
  112. opentrons/hardware_control/emulation/app.py +56 -0
  113. opentrons/hardware_control/emulation/connection_handler.py +38 -0
  114. opentrons/hardware_control/emulation/heater_shaker.py +150 -0
  115. opentrons/hardware_control/emulation/magdeck.py +60 -0
  116. opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
  117. opentrons/hardware_control/emulation/module_server/client.py +78 -0
  118. opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
  119. opentrons/hardware_control/emulation/module_server/models.py +31 -0
  120. opentrons/hardware_control/emulation/module_server/server.py +110 -0
  121. opentrons/hardware_control/emulation/parser.py +74 -0
  122. opentrons/hardware_control/emulation/proxy.py +241 -0
  123. opentrons/hardware_control/emulation/run_emulator.py +68 -0
  124. opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
  125. opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
  126. opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
  127. opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
  128. opentrons/hardware_control/emulation/settings.py +119 -0
  129. opentrons/hardware_control/emulation/simulations.py +133 -0
  130. opentrons/hardware_control/emulation/smoothie.py +192 -0
  131. opentrons/hardware_control/emulation/tempdeck.py +69 -0
  132. opentrons/hardware_control/emulation/thermocycler.py +128 -0
  133. opentrons/hardware_control/emulation/types.py +10 -0
  134. opentrons/hardware_control/emulation/util.py +38 -0
  135. opentrons/hardware_control/errors.py +43 -0
  136. opentrons/hardware_control/execution_manager.py +164 -0
  137. opentrons/hardware_control/instruments/__init__.py +5 -0
  138. opentrons/hardware_control/instruments/instrument_abc.py +39 -0
  139. opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
  140. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
  141. opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
  142. opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
  143. opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
  144. opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
  145. opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
  146. opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
  147. opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
  148. opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
  149. opentrons/hardware_control/module_control.py +332 -0
  150. opentrons/hardware_control/modules/__init__.py +69 -0
  151. opentrons/hardware_control/modules/absorbance_reader.py +373 -0
  152. opentrons/hardware_control/modules/errors.py +7 -0
  153. opentrons/hardware_control/modules/flex_stacker.py +948 -0
  154. opentrons/hardware_control/modules/heater_shaker.py +426 -0
  155. opentrons/hardware_control/modules/lid_temp_status.py +35 -0
  156. opentrons/hardware_control/modules/magdeck.py +233 -0
  157. opentrons/hardware_control/modules/mod_abc.py +245 -0
  158. opentrons/hardware_control/modules/module_calibration.py +93 -0
  159. opentrons/hardware_control/modules/plate_temp_status.py +61 -0
  160. opentrons/hardware_control/modules/tempdeck.py +299 -0
  161. opentrons/hardware_control/modules/thermocycler.py +731 -0
  162. opentrons/hardware_control/modules/types.py +417 -0
  163. opentrons/hardware_control/modules/update.py +255 -0
  164. opentrons/hardware_control/modules/utils.py +73 -0
  165. opentrons/hardware_control/motion_utilities.py +318 -0
  166. opentrons/hardware_control/nozzle_manager.py +422 -0
  167. opentrons/hardware_control/ot3_calibration.py +1171 -0
  168. opentrons/hardware_control/ot3api.py +3227 -0
  169. opentrons/hardware_control/pause_manager.py +31 -0
  170. opentrons/hardware_control/poller.py +112 -0
  171. opentrons/hardware_control/protocols/__init__.py +106 -0
  172. opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
  173. opentrons/hardware_control/protocols/calibratable.py +45 -0
  174. opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
  175. opentrons/hardware_control/protocols/configurable.py +48 -0
  176. opentrons/hardware_control/protocols/event_sourcer.py +18 -0
  177. opentrons/hardware_control/protocols/execution_controllable.py +33 -0
  178. opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
  179. opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
  180. opentrons/hardware_control/protocols/gripper_controller.py +55 -0
  181. opentrons/hardware_control/protocols/hardware_manager.py +51 -0
  182. opentrons/hardware_control/protocols/identifiable.py +16 -0
  183. opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
  184. opentrons/hardware_control/protocols/liquid_handler.py +266 -0
  185. opentrons/hardware_control/protocols/module_provider.py +16 -0
  186. opentrons/hardware_control/protocols/motion_controller.py +243 -0
  187. opentrons/hardware_control/protocols/position_estimator.py +45 -0
  188. opentrons/hardware_control/protocols/simulatable.py +10 -0
  189. opentrons/hardware_control/protocols/stoppable.py +9 -0
  190. opentrons/hardware_control/protocols/types.py +27 -0
  191. opentrons/hardware_control/robot_calibration.py +224 -0
  192. opentrons/hardware_control/scripts/README.md +28 -0
  193. opentrons/hardware_control/scripts/__init__.py +1 -0
  194. opentrons/hardware_control/scripts/gripper_control.py +208 -0
  195. opentrons/hardware_control/scripts/ot3gripper +7 -0
  196. opentrons/hardware_control/scripts/ot3repl +7 -0
  197. opentrons/hardware_control/scripts/repl.py +187 -0
  198. opentrons/hardware_control/scripts/tc_control.py +97 -0
  199. opentrons/hardware_control/simulator_setup.py +260 -0
  200. opentrons/hardware_control/thread_manager.py +431 -0
  201. opentrons/hardware_control/threaded_async_lock.py +97 -0
  202. opentrons/hardware_control/types.py +792 -0
  203. opentrons/hardware_control/util.py +234 -0
  204. opentrons/legacy_broker.py +53 -0
  205. opentrons/legacy_commands/__init__.py +1 -0
  206. opentrons/legacy_commands/commands.py +483 -0
  207. opentrons/legacy_commands/helpers.py +153 -0
  208. opentrons/legacy_commands/module_commands.py +215 -0
  209. opentrons/legacy_commands/protocol_commands.py +54 -0
  210. opentrons/legacy_commands/publisher.py +155 -0
  211. opentrons/legacy_commands/robot_commands.py +51 -0
  212. opentrons/legacy_commands/types.py +1115 -0
  213. opentrons/motion_planning/__init__.py +32 -0
  214. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  215. opentrons/motion_planning/deck_conflict.py +396 -0
  216. opentrons/motion_planning/errors.py +35 -0
  217. opentrons/motion_planning/types.py +42 -0
  218. opentrons/motion_planning/waypoints.py +218 -0
  219. opentrons/ordered_set.py +138 -0
  220. opentrons/protocol_api/__init__.py +105 -0
  221. opentrons/protocol_api/_liquid.py +157 -0
  222. opentrons/protocol_api/_liquid_properties.py +814 -0
  223. opentrons/protocol_api/_nozzle_layout.py +31 -0
  224. opentrons/protocol_api/_parameter_context.py +300 -0
  225. opentrons/protocol_api/_parameters.py +31 -0
  226. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  227. opentrons/protocol_api/_types.py +43 -0
  228. opentrons/protocol_api/config.py +23 -0
  229. opentrons/protocol_api/core/__init__.py +23 -0
  230. opentrons/protocol_api/core/common.py +33 -0
  231. opentrons/protocol_api/core/core_map.py +74 -0
  232. opentrons/protocol_api/core/engine/__init__.py +22 -0
  233. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  234. opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
  235. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  236. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  237. opentrons/protocol_api/core/engine/labware.py +238 -0
  238. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  239. opentrons/protocol_api/core/engine/module_core.py +1025 -0
  240. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  241. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  242. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  243. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  244. opentrons/protocol_api/core/engine/robot.py +139 -0
  245. opentrons/protocol_api/core/engine/stringify.py +74 -0
  246. opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
  247. opentrons/protocol_api/core/engine/well.py +241 -0
  248. opentrons/protocol_api/core/instrument.py +459 -0
  249. opentrons/protocol_api/core/labware.py +151 -0
  250. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  251. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  252. opentrons/protocol_api/core/legacy/deck.py +369 -0
  253. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  254. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  255. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  256. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  257. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  258. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  259. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  260. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  261. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  262. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  263. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  265. opentrons/protocol_api/core/module.py +484 -0
  266. opentrons/protocol_api/core/protocol.py +311 -0
  267. opentrons/protocol_api/core/robot.py +51 -0
  268. opentrons/protocol_api/core/well.py +116 -0
  269. opentrons/protocol_api/core/well_grid.py +45 -0
  270. opentrons/protocol_api/create_protocol_context.py +177 -0
  271. opentrons/protocol_api/deck.py +223 -0
  272. opentrons/protocol_api/disposal_locations.py +244 -0
  273. opentrons/protocol_api/instrument_context.py +3212 -0
  274. opentrons/protocol_api/labware.py +1579 -0
  275. opentrons/protocol_api/module_contexts.py +1425 -0
  276. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  277. opentrons/protocol_api/protocol_context.py +1688 -0
  278. opentrons/protocol_api/robot_context.py +303 -0
  279. opentrons/protocol_api/validation.py +761 -0
  280. opentrons/protocol_engine/__init__.py +155 -0
  281. opentrons/protocol_engine/actions/__init__.py +65 -0
  282. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  283. opentrons/protocol_engine/actions/action_handler.py +13 -0
  284. opentrons/protocol_engine/actions/actions.py +302 -0
  285. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  286. opentrons/protocol_engine/clients/__init__.py +5 -0
  287. opentrons/protocol_engine/clients/sync_client.py +174 -0
  288. opentrons/protocol_engine/clients/transports.py +197 -0
  289. opentrons/protocol_engine/commands/__init__.py +757 -0
  290. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  296. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  297. opentrons/protocol_engine/commands/aspirate.py +244 -0
  298. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  299. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  300. opentrons/protocol_engine/commands/blow_out.py +146 -0
  301. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  302. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  303. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  306. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  307. opentrons/protocol_engine/commands/command.py +308 -0
  308. opentrons/protocol_engine/commands/command_unions.py +974 -0
  309. opentrons/protocol_engine/commands/comment.py +57 -0
  310. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  311. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  312. opentrons/protocol_engine/commands/custom.py +67 -0
  313. opentrons/protocol_engine/commands/dispense.py +194 -0
  314. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  315. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  316. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  317. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  318. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  319. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  320. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  321. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  322. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  323. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  324. opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
  325. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  326. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  327. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  328. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  329. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  330. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  331. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  333. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  334. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  336. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  337. opentrons/protocol_engine/commands/home.py +100 -0
  338. opentrons/protocol_engine/commands/identify_module.py +86 -0
  339. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  340. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  341. opentrons/protocol_engine/commands/load_labware.py +210 -0
  342. opentrons/protocol_engine/commands/load_lid.py +154 -0
  343. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  344. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  345. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  346. opentrons/protocol_engine/commands/load_module.py +223 -0
  347. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  348. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  349. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  350. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  351. opentrons/protocol_engine/commands/move_labware.py +546 -0
  352. opentrons/protocol_engine/commands/move_relative.py +102 -0
  353. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  355. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  356. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  357. opentrons/protocol_engine/commands/movement_common.py +338 -0
  358. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  359. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  360. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  361. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  362. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  363. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  364. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  365. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  366. opentrons/protocol_engine/commands/robot/common.py +18 -0
  367. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  369. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  370. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  371. opentrons/protocol_engine/commands/save_position.py +109 -0
  372. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  373. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  374. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  375. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  376. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  377. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  378. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  379. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  380. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  381. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  384. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  386. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  388. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  390. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  391. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  392. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  401. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  402. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  403. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  404. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  405. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  406. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  407. opentrons/protocol_engine/engine_support.py +28 -0
  408. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  409. opentrons/protocol_engine/errors/__init__.py +191 -0
  410. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  411. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  412. opentrons/protocol_engine/execution/__init__.py +50 -0
  413. opentrons/protocol_engine/execution/command_executor.py +216 -0
  414. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  415. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  416. opentrons/protocol_engine/execution/equipment.py +819 -0
  417. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  418. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  419. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  420. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  421. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  422. opentrons/protocol_engine/execution/movement.py +349 -0
  423. opentrons/protocol_engine/execution/pipetting.py +607 -0
  424. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  425. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  426. opentrons/protocol_engine/execution/run_control.py +33 -0
  427. opentrons/protocol_engine/execution/status_bar.py +34 -0
  428. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  429. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  430. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  431. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  432. opentrons/protocol_engine/notes/__init__.py +17 -0
  433. opentrons/protocol_engine/notes/notes.py +59 -0
  434. opentrons/protocol_engine/plugins.py +104 -0
  435. opentrons/protocol_engine/protocol_engine.py +683 -0
  436. opentrons/protocol_engine/resources/__init__.py +26 -0
  437. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  438. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  439. opentrons/protocol_engine/resources/file_provider.py +161 -0
  440. opentrons/protocol_engine/resources/fixture_validation.py +58 -0
  441. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  442. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  443. opentrons/protocol_engine/resources/model_utils.py +32 -0
  444. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  445. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  446. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  447. opentrons/protocol_engine/slot_standardization.py +128 -0
  448. opentrons/protocol_engine/state/__init__.py +1 -0
  449. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  450. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  451. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  452. opentrons/protocol_engine/state/_move_types.py +83 -0
  453. opentrons/protocol_engine/state/_well_math.py +193 -0
  454. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  455. opentrons/protocol_engine/state/command_history.py +309 -0
  456. opentrons/protocol_engine/state/commands.py +1158 -0
  457. opentrons/protocol_engine/state/config.py +39 -0
  458. opentrons/protocol_engine/state/files.py +57 -0
  459. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  460. opentrons/protocol_engine/state/geometry.py +2359 -0
  461. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  462. opentrons/protocol_engine/state/labware.py +1459 -0
  463. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  464. opentrons/protocol_engine/state/liquids.py +73 -0
  465. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  466. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  467. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  468. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  469. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  471. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  472. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  473. opentrons/protocol_engine/state/modules.py +1500 -0
  474. opentrons/protocol_engine/state/motion.py +373 -0
  475. opentrons/protocol_engine/state/pipettes.py +905 -0
  476. opentrons/protocol_engine/state/state.py +421 -0
  477. opentrons/protocol_engine/state/state_summary.py +36 -0
  478. opentrons/protocol_engine/state/tips.py +420 -0
  479. opentrons/protocol_engine/state/update_types.py +904 -0
  480. opentrons/protocol_engine/state/wells.py +290 -0
  481. opentrons/protocol_engine/types/__init__.py +308 -0
  482. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  483. opentrons/protocol_engine/types/command_annotations.py +53 -0
  484. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  485. opentrons/protocol_engine/types/execution.py +96 -0
  486. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  487. opentrons/protocol_engine/types/instrument.py +47 -0
  488. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  489. opentrons/protocol_engine/types/labware.py +131 -0
  490. opentrons/protocol_engine/types/labware_movement.py +22 -0
  491. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  492. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  493. opentrons/protocol_engine/types/liquid.py +40 -0
  494. opentrons/protocol_engine/types/liquid_class.py +59 -0
  495. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  496. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  497. opentrons/protocol_engine/types/location.py +194 -0
  498. opentrons/protocol_engine/types/module.py +303 -0
  499. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  500. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  501. opentrons/protocol_engine/types/tip.py +18 -0
  502. opentrons/protocol_engine/types/util.py +21 -0
  503. opentrons/protocol_engine/types/well_position.py +124 -0
  504. opentrons/protocol_reader/__init__.py +37 -0
  505. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  506. opentrons/protocol_reader/file_format_validator.py +152 -0
  507. opentrons/protocol_reader/file_hasher.py +27 -0
  508. opentrons/protocol_reader/file_identifier.py +284 -0
  509. opentrons/protocol_reader/file_reader_writer.py +90 -0
  510. opentrons/protocol_reader/input_file.py +16 -0
  511. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  512. opentrons/protocol_reader/protocol_reader.py +188 -0
  513. opentrons/protocol_reader/protocol_source.py +124 -0
  514. opentrons/protocol_reader/role_analyzer.py +86 -0
  515. opentrons/protocol_runner/__init__.py +26 -0
  516. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  517. opentrons/protocol_runner/json_file_reader.py +55 -0
  518. opentrons/protocol_runner/json_translator.py +314 -0
  519. opentrons/protocol_runner/legacy_command_mapper.py +848 -0
  520. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  521. opentrons/protocol_runner/protocol_runner.py +530 -0
  522. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  523. opentrons/protocol_runner/run_orchestrator.py +496 -0
  524. opentrons/protocol_runner/task_queue.py +95 -0
  525. opentrons/protocols/__init__.py +6 -0
  526. opentrons/protocols/advanced_control/__init__.py +0 -0
  527. opentrons/protocols/advanced_control/common.py +38 -0
  528. opentrons/protocols/advanced_control/mix.py +60 -0
  529. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  530. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  531. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  532. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  533. opentrons/protocols/api_support/__init__.py +0 -0
  534. opentrons/protocols/api_support/constants.py +8 -0
  535. opentrons/protocols/api_support/deck_type.py +110 -0
  536. opentrons/protocols/api_support/definitions.py +18 -0
  537. opentrons/protocols/api_support/instrument.py +151 -0
  538. opentrons/protocols/api_support/labware_like.py +233 -0
  539. opentrons/protocols/api_support/tip_tracker.py +175 -0
  540. opentrons/protocols/api_support/types.py +32 -0
  541. opentrons/protocols/api_support/util.py +403 -0
  542. opentrons/protocols/bundle.py +89 -0
  543. opentrons/protocols/duration/__init__.py +4 -0
  544. opentrons/protocols/duration/errors.py +5 -0
  545. opentrons/protocols/duration/estimator.py +628 -0
  546. opentrons/protocols/execution/__init__.py +0 -0
  547. opentrons/protocols/execution/dev_types.py +181 -0
  548. opentrons/protocols/execution/errors.py +40 -0
  549. opentrons/protocols/execution/execute.py +84 -0
  550. opentrons/protocols/execution/execute_json_v3.py +275 -0
  551. opentrons/protocols/execution/execute_json_v4.py +359 -0
  552. opentrons/protocols/execution/execute_json_v5.py +28 -0
  553. opentrons/protocols/execution/execute_python.py +169 -0
  554. opentrons/protocols/execution/json_dispatchers.py +87 -0
  555. opentrons/protocols/execution/types.py +7 -0
  556. opentrons/protocols/geometry/__init__.py +0 -0
  557. opentrons/protocols/geometry/planning.py +297 -0
  558. opentrons/protocols/labware.py +312 -0
  559. opentrons/protocols/models/__init__.py +0 -0
  560. opentrons/protocols/models/json_protocol.py +679 -0
  561. opentrons/protocols/parameters/__init__.py +0 -0
  562. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  563. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  564. opentrons/protocols/parameters/exceptions.py +34 -0
  565. opentrons/protocols/parameters/parameter_definition.py +272 -0
  566. opentrons/protocols/parameters/types.py +17 -0
  567. opentrons/protocols/parameters/validation.py +267 -0
  568. opentrons/protocols/parse.py +671 -0
  569. opentrons/protocols/types.py +159 -0
  570. opentrons/py.typed +0 -0
  571. opentrons/resources/scripts/lpc21isp +0 -0
  572. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  573. opentrons/simulate.py +1065 -0
  574. opentrons/system/__init__.py +6 -0
  575. opentrons/system/camera.py +51 -0
  576. opentrons/system/log_control.py +59 -0
  577. opentrons/system/nmcli.py +856 -0
  578. opentrons/system/resin.py +24 -0
  579. opentrons/system/smoothie_update.py +15 -0
  580. opentrons/system/wifi.py +204 -0
  581. opentrons/tools/__init__.py +0 -0
  582. opentrons/tools/args_handler.py +22 -0
  583. opentrons/tools/write_pipette_memory.py +157 -0
  584. opentrons/types.py +618 -0
  585. opentrons/util/__init__.py +1 -0
  586. opentrons/util/async_helpers.py +166 -0
  587. opentrons/util/broker.py +84 -0
  588. opentrons/util/change_notifier.py +47 -0
  589. opentrons/util/entrypoint_util.py +278 -0
  590. opentrons/util/get_union_elements.py +26 -0
  591. opentrons/util/helpers.py +6 -0
  592. opentrons/util/linal.py +178 -0
  593. opentrons/util/logging_config.py +265 -0
  594. opentrons/util/logging_queue_handler.py +61 -0
  595. opentrons/util/performance_helpers.py +157 -0
  596. opentrons-8.6.0a1.dist-info/METADATA +37 -0
  597. opentrons-8.6.0a1.dist-info/RECORD +600 -0
  598. opentrons-8.6.0a1.dist-info/WHEEL +4 -0
  599. opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
  600. opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,900 @@
1
+ """OT3 Hardware Controller Backend."""
2
+
3
+ from __future__ import annotations
4
+ import asyncio
5
+ from contextlib import asynccontextmanager
6
+ import logging
7
+ from typing import (
8
+ Dict,
9
+ List,
10
+ Optional,
11
+ Tuple,
12
+ Sequence,
13
+ AsyncIterator,
14
+ cast,
15
+ Set,
16
+ Union,
17
+ Mapping,
18
+ )
19
+
20
+ from opentrons.config.types import OT3Config, GantryLoad
21
+ from opentrons.config import gripper_config
22
+
23
+ from opentrons.hardware_control.module_control import AttachedModulesControl
24
+ from opentrons.hardware_control import modules
25
+ from opentrons.hardware_control.types import (
26
+ BoardRevision,
27
+ Axis,
28
+ HepaFanState,
29
+ HepaUVState,
30
+ OT3Mount,
31
+ OT3AxisMap,
32
+ CurrentConfig,
33
+ InstrumentProbeType,
34
+ MotorStatus,
35
+ UpdateStatus,
36
+ UpdateState,
37
+ SubSystem,
38
+ SubSystemState,
39
+ TipStateType,
40
+ GripperJawState,
41
+ HardwareFeatureFlags,
42
+ StatusBarState,
43
+ EstopOverallStatus,
44
+ EstopState,
45
+ EstopPhysicalStatus,
46
+ HardwareEventHandler,
47
+ HardwareEventUnsubscriber,
48
+ PipetteSensorResponseQueue,
49
+ )
50
+
51
+ from opentrons_shared_data.pipette.types import PipetteName, PipetteModel
52
+ from opentrons_shared_data.pipette import (
53
+ pipette_load_name_conversions as pipette_load_name,
54
+ load_data as load_pipette_data,
55
+ )
56
+ from opentrons_shared_data.gripper.gripper_definition import GripperModel
57
+ from opentrons.hardware_control.dev_types import (
58
+ PipetteSpec,
59
+ GripperSpec,
60
+ AttachedPipette,
61
+ AttachedGripper,
62
+ OT3AttachedInstruments,
63
+ )
64
+ from opentrons.util.async_helpers import ensure_yield
65
+ from .types import HWStopCondition
66
+ from .flex_protocol import (
67
+ FlexBackend,
68
+ )
69
+
70
+
71
+ log = logging.getLogger(__name__)
72
+
73
+ AXIS_TO_SUBSYSTEM = {
74
+ Axis.X: SubSystem.gantry_x,
75
+ Axis.Y: SubSystem.gantry_y,
76
+ Axis.Z_L: SubSystem.head,
77
+ Axis.Z_R: SubSystem.head,
78
+ Axis.Z_G: SubSystem.gripper,
79
+ Axis.G: SubSystem.gripper,
80
+ Axis.P_L: SubSystem.pipette_left,
81
+ Axis.P_R: SubSystem.pipette_right,
82
+ }
83
+
84
+
85
+ def coalesce_move_segments(
86
+ origin: Dict[Axis, float], targets: List[Dict[Axis, float]]
87
+ ) -> Dict[Axis, float]:
88
+ for target in targets:
89
+ for axis, increment in target.items():
90
+ origin[axis] += increment
91
+ return origin
92
+
93
+
94
+ def axis_pad(positions: Dict[Axis, float], default_value: float) -> Dict[Axis, float]:
95
+ return {ax: positions.get(ax, default_value) for ax in Axis.node_axes()}
96
+
97
+
98
+ class OT3Simulator(FlexBackend):
99
+ """OT3 Hardware Controller Backend."""
100
+
101
+ _position: Dict[Axis, float]
102
+ _encoder_position: Dict[Axis, float]
103
+ _motor_status: Dict[Axis, MotorStatus]
104
+ _engaged_axes: Dict[Axis, bool]
105
+
106
+ @classmethod
107
+ async def build(
108
+ cls,
109
+ attached_instruments: Dict[OT3Mount, Dict[str, Optional[str]]],
110
+ attached_modules: Dict[str, List[modules.SimulatingModule]],
111
+ config: OT3Config,
112
+ loop: asyncio.AbstractEventLoop,
113
+ strict_attached_instruments: bool = True,
114
+ feature_flags: Optional[HardwareFeatureFlags] = None,
115
+ ) -> OT3Simulator:
116
+ """Create the OT3Simulator instance.
117
+
118
+ Args:
119
+ config: Robot configuration
120
+
121
+ Returns:
122
+ Instance.
123
+ """
124
+ return cls(
125
+ attached_instruments,
126
+ attached_modules,
127
+ config,
128
+ loop,
129
+ strict_attached_instruments,
130
+ feature_flags,
131
+ )
132
+
133
+ def __init__(
134
+ self,
135
+ attached_instruments: Dict[OT3Mount, Dict[str, Optional[str]]],
136
+ attached_modules: Dict[str, List[modules.SimulatingModule]],
137
+ config: OT3Config,
138
+ loop: asyncio.AbstractEventLoop,
139
+ strict_attached_instruments: bool = True,
140
+ feature_flags: Optional[HardwareFeatureFlags] = None,
141
+ ) -> None:
142
+ """Construct.
143
+
144
+ Args:
145
+ config: Robot configuration
146
+ driver: The Can Driver
147
+ """
148
+ self._configuration = config
149
+ self._loop = loop
150
+ self._strict_attached = bool(strict_attached_instruments)
151
+ self._stubbed_attached_modules = attached_modules
152
+ self._update_required = False
153
+ self._initialized = False
154
+ self._lights = {"button": False, "rails": False}
155
+ self._gear_motor_position: Dict[Axis, float] = {}
156
+ self._engaged_axes: Dict[Axis, bool] = {}
157
+ self._feature_flags = feature_flags or HardwareFeatureFlags()
158
+
159
+ def _sanitize_attached_instrument(
160
+ mount: OT3Mount, passed_ai: Optional[Dict[str, Optional[str]]] = None
161
+ ) -> Union[PipetteSpec, GripperSpec]:
162
+ if mount is OT3Mount.GRIPPER:
163
+ gripper_spec: GripperSpec = {"model": None, "id": None}
164
+ if passed_ai and passed_ai.get("model"):
165
+ gripper_spec["model"] = GripperModel.v1
166
+ gripper_spec["id"] = passed_ai.get("id")
167
+ return gripper_spec
168
+
169
+ # TODO (lc 12-5-2022) need to not always pass in defaults here
170
+ # but doing it to satisfy linter errors for now.
171
+ pipette_spec: PipetteSpec = {"model": None, "id": None}
172
+ if not passed_ai or not passed_ai.get("model"):
173
+ return pipette_spec
174
+
175
+ if pipette_load_name.supported_pipette(
176
+ cast(PipetteModel, passed_ai["model"])
177
+ ):
178
+ pipette_spec["model"] = cast(PipetteModel, passed_ai.get("model"))
179
+ pipette_spec["id"] = passed_ai.get("id")
180
+ return pipette_spec
181
+ # TODO (lc 12-05-2022) When the time comes we should properly
182
+ # support backwards compatibility
183
+ raise KeyError(
184
+ "If you specify attached_instruments, the model "
185
+ "should be pipette names or pipette models, but "
186
+ f'{passed_ai["model"]} is not'
187
+ )
188
+
189
+ self._attached_instruments = {
190
+ m: _sanitize_attached_instrument(m, attached_instruments.get(m))
191
+ for m in OT3Mount
192
+ }
193
+ self._module_controls: Optional[AttachedModulesControl] = None
194
+ self._position = self._get_home_position()
195
+ self._encoder_position = self._get_home_position()
196
+ self._motor_status = {}
197
+ axes = set((Axis.Z_L, Axis.Z_R, Axis.X, Axis.Y))
198
+ if self._attached_instruments[OT3Mount.LEFT].get("model", None):
199
+ axes.add(Axis.P_L)
200
+ if self._attached_instruments[OT3Mount.RIGHT].get("model", None):
201
+ axes.add(Axis.P_L)
202
+ if self._attached_instruments.get(
203
+ OT3Mount.GRIPPER
204
+ ) and self._attached_instruments[OT3Mount.GRIPPER].get("model", None):
205
+ axes.update((Axis.G, Axis.Z_G))
206
+ self._present_axes = axes
207
+ self._current_settings: Optional[OT3AxisMap[CurrentConfig]] = None
208
+ self._sim_jaw_state = GripperJawState.HOMED_READY
209
+ self._sim_tip_state: Dict[OT3Mount, Optional[bool]] = {
210
+ mount: False if self._attached_instruments[mount] else None
211
+ for mount in [OT3Mount.LEFT, OT3Mount.RIGHT]
212
+ }
213
+ self._sim_gantry_load = GantryLoad.LOW_THROUGHPUT
214
+ self._sim_status_bar_state = StatusBarState.IDLE
215
+ self._sim_estop_state = EstopState.DISENGAGED
216
+ self._sim_estop_left_state = EstopPhysicalStatus.DISENGAGED
217
+ self._sim_estop_right_state = EstopPhysicalStatus.DISENGAGED
218
+
219
+ async def get_serial_number(self) -> Optional[str]:
220
+ return "simulator"
221
+
222
+ @asynccontextmanager
223
+ async def restore_system_constraints(self) -> AsyncIterator[None]:
224
+ log.debug("Simulating saving system constraints")
225
+ try:
226
+ yield
227
+ finally:
228
+ log.debug("Simulating restoring system constraints")
229
+
230
+ def update_constraints_for_gantry_load(self, gantry_load: GantryLoad) -> None:
231
+ self._sim_gantry_load = gantry_load
232
+
233
+ def update_constraints_for_plunger_acceleration(
234
+ self,
235
+ mount: OT3Mount,
236
+ acceleration: float,
237
+ gantry_load: GantryLoad,
238
+ high_speed_pipette: bool = False,
239
+ ) -> None:
240
+ self._sim_gantry_load = gantry_load
241
+
242
+ @property
243
+ def initialized(self) -> bool:
244
+ """True when the hardware controller has initialized and is ready."""
245
+ return self._initialized
246
+
247
+ @initialized.setter
248
+ def initialized(self, value: bool) -> None:
249
+ self._initialized = value
250
+
251
+ @property
252
+ def gear_motor_position(self) -> Optional[float]:
253
+ return self._gear_motor_position.get(Axis.Q, None)
254
+
255
+ @property
256
+ def board_revision(self) -> BoardRevision:
257
+ """Get the board revision"""
258
+ return BoardRevision.UNKNOWN
259
+
260
+ @property
261
+ def module_controls(self) -> AttachedModulesControl:
262
+ """Get the module controls."""
263
+ if self._module_controls is None:
264
+ raise AttributeError("Module controls not found.")
265
+ return self._module_controls
266
+
267
+ @module_controls.setter
268
+ def module_controls(self, module_controls: AttachedModulesControl) -> None:
269
+ """Set the module controls"""
270
+ self._module_controls = module_controls
271
+
272
+ @ensure_yield
273
+ async def update_to_default_current_settings(self, gantry_load: GantryLoad) -> None:
274
+ self._gantry_load = gantry_load
275
+
276
+ def update_feature_flags(self, feature_flags: HardwareFeatureFlags) -> None:
277
+ """Update the hardware feature flags used by the hardware controller."""
278
+ self._feature_flags = feature_flags
279
+
280
+ def _handle_motor_status_update(self, response: Dict[Axis, float]) -> None:
281
+ self._position.update(response)
282
+ self._encoder_position.update(response)
283
+ self._motor_status.update(
284
+ (node, MotorStatus(True, True)) for node in response.keys()
285
+ )
286
+
287
+ @ensure_yield
288
+ async def update_motor_status(self) -> None:
289
+ """Retreieve motor and encoder status and position from all present devices"""
290
+ if not self._motor_status:
291
+ # Simulate condition at boot, status would not be ok
292
+ self._motor_status.update(
293
+ (axis, MotorStatus(False, False)) for axis in self._present_axes
294
+ )
295
+ else:
296
+ self._motor_status.update(
297
+ (axis, MotorStatus(True, True)) for axis in self._present_axes
298
+ )
299
+
300
+ @ensure_yield
301
+ async def update_motor_estimation(self, axes: Sequence[Axis]) -> None:
302
+ """Update motor position estimation for commanded axes, and update cache of data."""
303
+ # Simulate conditions as if there are no stalls, aka do nothing
304
+ return None
305
+
306
+ def _get_motor_status(
307
+ self, axes: Sequence[Axis]
308
+ ) -> Dict[Axis, Optional[MotorStatus]]:
309
+ return {ax: self._motor_status.get(ax) for ax in axes}
310
+
311
+ def get_invalid_motor_axes(self, axes: Sequence[Axis]) -> List[Axis]:
312
+ """Get axes that currently do not have the motor-ok flag."""
313
+ return [
314
+ ax
315
+ for ax, status in self._get_motor_status(axes).items()
316
+ if not status or not status.motor_ok
317
+ ]
318
+
319
+ def get_invalid_encoder_axes(self, axes: Sequence[Axis]) -> List[Axis]:
320
+ """Get axes that currently do not have the encoder-ok flag."""
321
+ return [
322
+ ax
323
+ for ax, status in self._get_motor_status(axes).items()
324
+ if not status or not status.encoder_ok
325
+ ]
326
+
327
+ def check_motor_status(self, axes: Sequence[Axis]) -> bool:
328
+ return len(self.get_invalid_motor_axes(axes)) == 0
329
+
330
+ def check_encoder_status(self, axes: Sequence[Axis]) -> bool:
331
+ return len(self.get_invalid_encoder_axes(axes)) == 0
332
+
333
+ async def update_position(self) -> OT3AxisMap[float]:
334
+ """Get the current position."""
335
+ return axis_pad(self._position, 0.0)
336
+
337
+ async def update_encoder_position(self) -> OT3AxisMap[float]:
338
+ """Get the encoder current position."""
339
+ return axis_pad(self._encoder_position, 0.0)
340
+
341
+ @ensure_yield
342
+ async def liquid_probe(
343
+ self,
344
+ mount: OT3Mount,
345
+ max_p_distance: float,
346
+ mount_speed: float,
347
+ plunger_speed: float,
348
+ threshold_pascals: float,
349
+ plunger_impulse_time: float,
350
+ num_baseline_reads: int,
351
+ z_offset_for_plunger_prep: float,
352
+ probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
353
+ force_both_sensors: bool = False,
354
+ response_queue: Optional[PipetteSensorResponseQueue] = None,
355
+ ) -> float:
356
+ z_axis = Axis.by_mount(mount)
357
+ pos = self._position
358
+ self._position.update(pos)
359
+ self._encoder_position.update(pos)
360
+ return self._position[z_axis]
361
+
362
+ @ensure_yield
363
+ async def move(
364
+ self,
365
+ origin: Dict[Axis, float],
366
+ target: Dict[Axis, float],
367
+ speed: Optional[float] = None,
368
+ stop_condition: HWStopCondition = HWStopCondition.none,
369
+ nodes_in_moves_only: bool = True,
370
+ ) -> None:
371
+ """Move to a position.
372
+
373
+ Args:
374
+ target_position: Map of axis to position.
375
+ home_flagged_axes: Whether to home afterwords.
376
+ speed: Optional speed
377
+ axis_max_speeds: Optional map of axis to speed.
378
+
379
+ Returns:
380
+ None
381
+ """
382
+ for ax in origin:
383
+ self._engaged_axes[ax] = True
384
+ self._position.update(target)
385
+ self._encoder_position.update(target)
386
+
387
+ @ensure_yield
388
+ async def home(
389
+ self, axes: Sequence[Axis], gantry_load: GantryLoad
390
+ ) -> OT3AxisMap[float]:
391
+ """Home axes.
392
+
393
+ Args:
394
+ axes: Optional list of axes.
395
+
396
+ Returns:
397
+ Homed position.
398
+ """
399
+ if axes:
400
+ homed = axes
401
+ else:
402
+ homed = list(iter(self._position.keys()))
403
+ for h in homed:
404
+ self._position[h] = self._get_home_position()[h]
405
+ self._motor_status[h] = MotorStatus(True, True)
406
+ self._engaged_axes[h] = True
407
+ return axis_pad(self._position, 0.0)
408
+
409
+ @ensure_yield
410
+ async def gripper_grip_jaw(
411
+ self,
412
+ duty_cycle: float,
413
+ expected_displacement: float,
414
+ stop_condition: HWStopCondition = HWStopCondition.none,
415
+ stay_engaged: bool = True,
416
+ ) -> None:
417
+ """Move gripper inward."""
418
+ self._sim_jaw_state = GripperJawState.GRIPPING
419
+ self._encoder_position[Axis.G] = expected_displacement
420
+
421
+ @ensure_yield
422
+ async def gripper_home_jaw(self, duty_cycle: float) -> None:
423
+ """Move gripper outward."""
424
+ self._motor_status[Axis.G] = MotorStatus(True, True)
425
+ self._encoder_position[Axis.G] = self._get_home_position()[Axis.G]
426
+ self._sim_jaw_state = GripperJawState.HOMED_READY
427
+
428
+ @ensure_yield
429
+ async def gripper_hold_jaw(
430
+ self,
431
+ encoder_position_um: int,
432
+ ) -> None:
433
+ self._encoder_position[Axis.G] = encoder_position_um / 1000.0
434
+ self._sim_jaw_state = GripperJawState.HOLDING
435
+
436
+ async def get_jaw_state(self) -> GripperJawState:
437
+ """Get the state of the gripper jaw."""
438
+ return self._sim_jaw_state
439
+
440
+ async def tip_action(
441
+ self, origin: float, targets: List[Tuple[float, float]]
442
+ ) -> None:
443
+ self._gear_motor_position.update(
444
+ coalesce_move_segments(
445
+ {Axis.Q: origin}, [{Axis.Q: target[0]} for target in targets]
446
+ )
447
+ )
448
+ await asyncio.sleep(0)
449
+
450
+ async def home_tip_motors(
451
+ self,
452
+ distance: float,
453
+ velocity: float,
454
+ back_off: bool = True,
455
+ ) -> None:
456
+ pass
457
+
458
+ def _attached_to_mount(
459
+ self, mount: OT3Mount, expected_instr: Optional[PipetteName]
460
+ ) -> OT3AttachedInstruments:
461
+ init_instr = self._attached_instruments.get(mount, {"model": None, "id": None})
462
+ if mount is OT3Mount.GRIPPER:
463
+ return self._attached_gripper_to_mount(cast(GripperSpec, init_instr))
464
+ return self._attached_pipette_to_mount(
465
+ mount, cast(PipetteSpec, init_instr), expected_instr
466
+ )
467
+
468
+ def _attached_gripper_to_mount(self, init_instr: GripperSpec) -> AttachedGripper:
469
+ found_model = init_instr["model"]
470
+ if found_model:
471
+ return {
472
+ "config": gripper_config.load(GripperModel.v1),
473
+ "id": init_instr["id"],
474
+ }
475
+ else:
476
+ return {"config": None, "id": None}
477
+
478
+ def _attached_pipette_to_mount(
479
+ self,
480
+ mount: OT3Mount,
481
+ init_instr: PipetteSpec,
482
+ expected_instr: Optional[PipetteName],
483
+ ) -> AttachedPipette:
484
+ found_model = init_instr["model"]
485
+
486
+ # TODO (lc 12-05-2022) When the time comes, we should think about supporting
487
+ # backwards compatability -- hopefully not relying on config keys only,
488
+ # but TBD.
489
+ if expected_instr and not pipette_load_name.supported_pipette(
490
+ cast(PipetteModel, expected_instr)
491
+ ):
492
+ raise RuntimeError(
493
+ f"mount {mount.name} requested a {expected_instr} which is not supported on the OT3"
494
+ )
495
+ if found_model and expected_instr and (expected_instr not in found_model):
496
+ if self._strict_attached:
497
+ raise RuntimeError(
498
+ "mount {}: expected instrument {} but got {}".format(
499
+ mount.name, expected_instr, found_model
500
+ )
501
+ )
502
+ else:
503
+ converted_name = pipette_load_name.convert_pipette_name(expected_instr)
504
+ return {
505
+ "config": load_pipette_data.load_definition(
506
+ converted_name.pipette_type,
507
+ converted_name.pipette_channels,
508
+ converted_name.pipette_version,
509
+ converted_name.oem_type,
510
+ ),
511
+ "id": None,
512
+ }
513
+ if found_model and init_instr["id"] is not None:
514
+ # Instrument detected matches instrument expected (note:
515
+ # "instrument detected" means passed as an argument to the
516
+ # constructor of this class)
517
+
518
+ # OR Instrument detected and no expected instrument specified
519
+
520
+ found_model_version = ""
521
+ if found_model.find("flex") > -1:
522
+ found_model = found_model.replace("_flex", "") # type: ignore
523
+ found_model_version = f"{init_instr['id'][4]}.{init_instr['id'][5]}"
524
+ converted_name = pipette_load_name.convert_pipette_model(
525
+ found_model, found_model_version
526
+ )
527
+ return {
528
+ "config": load_pipette_data.load_definition(
529
+ converted_name.pipette_type,
530
+ converted_name.pipette_channels,
531
+ converted_name.pipette_version,
532
+ converted_name.oem_type,
533
+ ),
534
+ "id": init_instr["id"],
535
+ }
536
+ elif expected_instr:
537
+ # Expected instrument specified and no instrument detected
538
+ converted_name = pipette_load_name.convert_pipette_name(expected_instr)
539
+ return {
540
+ "config": load_pipette_data.load_definition(
541
+ converted_name.pipette_type,
542
+ converted_name.pipette_channels,
543
+ converted_name.pipette_version,
544
+ converted_name.oem_type,
545
+ ),
546
+ "id": None,
547
+ }
548
+ else:
549
+ # No instrument detected or expected
550
+ return {"config": None, "id": None}
551
+
552
+ @ensure_yield
553
+ async def get_attached_instruments(
554
+ self, expected: Mapping[OT3Mount, Optional[PipetteName]]
555
+ ) -> Mapping[OT3Mount, OT3AttachedInstruments]:
556
+ """Get attached instruments.
557
+
558
+ Args:
559
+ expected: Which mounts are expected.
560
+
561
+ Returns:
562
+ A map of mount to pipette name.
563
+ """
564
+ return {
565
+ mount: self._attached_to_mount(mount, expected.get(mount))
566
+ for mount in OT3Mount
567
+ }
568
+
569
+ @ensure_yield
570
+ async def get_limit_switches(self) -> OT3AxisMap[bool]:
571
+ """Get the state of the gantry's limit switches on each axis."""
572
+ return {}
573
+
574
+ @ensure_yield
575
+ async def set_active_current(self, axis_currents: OT3AxisMap[float]) -> None:
576
+ """Set the active current.
577
+
578
+ Args:
579
+ axis_currents: Axes' currents
580
+
581
+ Returns:
582
+ None
583
+ """
584
+ return None
585
+
586
+ @asynccontextmanager
587
+ async def motor_current(
588
+ self,
589
+ run_currents: Optional[OT3AxisMap[float]] = None,
590
+ hold_currents: Optional[OT3AxisMap[float]] = None,
591
+ ) -> AsyncIterator[None]:
592
+ """Save the current."""
593
+ yield
594
+
595
+ @asynccontextmanager
596
+ async def restore_z_r_run_current(self) -> AsyncIterator[None]:
597
+ """
598
+ Temporarily restore the active current ONLY when homing or
599
+ retracting the Z_R axis while the 96-channel is attached.
600
+ """
601
+ yield
602
+
603
+ @asynccontextmanager
604
+ async def increase_z_l_hold_current(self) -> AsyncIterator[None]:
605
+ """
606
+ Temporarily increase the hold current when engaging the Z_L axis
607
+ while the 96-channel is attached
608
+ """
609
+ yield
610
+
611
+ @ensure_yield
612
+ async def watch(self, loop: asyncio.AbstractEventLoop) -> None:
613
+ new_mods_at_ports = []
614
+ for mod_name, list_of_modules in self._stubbed_attached_modules.items():
615
+ for module_details in list_of_modules:
616
+ new_mods_at_ports.append(
617
+ modules.SimulatingModuleAtPort(
618
+ port=f"/dev/ot_module_sim_{mod_name}{str(module_details.serial_number)}",
619
+ name=mod_name,
620
+ serial_number=module_details.serial_number,
621
+ model=module_details.model,
622
+ )
623
+ )
624
+ await self.module_controls.register_modules(new_mods_at_ports=new_mods_at_ports)
625
+
626
+ @property
627
+ def axis_bounds(self) -> OT3AxisMap[Tuple[float, float]]:
628
+ """Get the axis bounds."""
629
+ # TODO (AL, 2021-11-18): The bounds need to be defined
630
+ phony_bounds = (0, 10000)
631
+ return {
632
+ Axis.Z_R: phony_bounds,
633
+ Axis.Z_L: phony_bounds,
634
+ Axis.P_L: phony_bounds,
635
+ Axis.P_R: phony_bounds,
636
+ Axis.Y: phony_bounds,
637
+ Axis.X: phony_bounds,
638
+ Axis.Z_G: phony_bounds,
639
+ Axis.Q: phony_bounds,
640
+ }
641
+
642
+ @property
643
+ def fw_version(self) -> Dict[SubSystem, int]:
644
+ """Get the firmware version."""
645
+ return {AXIS_TO_SUBSYSTEM[axis]: 0 for axis in self._present_axes}
646
+
647
+ def axis_is_present(self, axis: Axis) -> bool:
648
+ return axis in self._present_axes
649
+
650
+ @property
651
+ def update_required(self) -> bool:
652
+ return self._update_required
653
+
654
+ @update_required.setter
655
+ def update_required(self, value: bool) -> None:
656
+ if value != self._update_required:
657
+ log.info(f"Firmware Update Flag set {self._update_required} -> {value}")
658
+ self._update_required = value
659
+
660
+ async def update_firmware(
661
+ self,
662
+ subsystems: Set[SubSystem],
663
+ force: bool = False,
664
+ ) -> AsyncIterator[UpdateStatus]:
665
+ """Updates the firmware on the OT3."""
666
+ for subsystem in subsystems:
667
+ yield UpdateStatus(
668
+ subsystem=subsystem, state=UpdateState.done, progress=100
669
+ )
670
+
671
+ def engaged_axes(self) -> OT3AxisMap[bool]:
672
+ """Get engaged axes."""
673
+ return self._engaged_axes
674
+
675
+ async def update_engaged_axes(self) -> None:
676
+ """Update engaged axes."""
677
+ return None
678
+
679
+ async def is_motor_engaged(self, axis: Axis) -> bool:
680
+ if axis not in self._engaged_axes.keys():
681
+ return False
682
+ return self._engaged_axes[axis]
683
+
684
+ @ensure_yield
685
+ async def disengage_axes(self, axes: List[Axis]) -> None:
686
+ """Disengage axes."""
687
+ for ax in axes:
688
+ self._engaged_axes.update({ax: False})
689
+ return None
690
+
691
+ @ensure_yield
692
+ async def engage_axes(self, axes: List[Axis]) -> None:
693
+ """Engage axes."""
694
+ for ax in axes:
695
+ self._engaged_axes.update({ax: True})
696
+ return None
697
+
698
+ @ensure_yield
699
+ async def set_lights(self, button: Optional[bool], rails: Optional[bool]) -> None:
700
+ """Set the light states."""
701
+ # Simulate how the real driver does this - there's no button so it's always false
702
+ if rails is not None:
703
+ self._lights["rails"] = rails
704
+
705
+ @ensure_yield
706
+ async def get_lights(self) -> Dict[str, bool]:
707
+ """Get the light state."""
708
+ return self._lights
709
+
710
+ def pause(self) -> None:
711
+ """Pause the controller activity."""
712
+ return None
713
+
714
+ def resume(self) -> None:
715
+ """Resume the controller activity."""
716
+ return None
717
+
718
+ @ensure_yield
719
+ async def halt(self) -> None:
720
+ """Halt the motors."""
721
+ return None
722
+
723
+ @ensure_yield
724
+ async def probe(self, axis: Axis, distance: float) -> OT3AxisMap[float]:
725
+ """Probe."""
726
+ return {}
727
+
728
+ @ensure_yield
729
+ async def clean_up(self) -> None:
730
+ """Clean up."""
731
+ pass
732
+
733
+ @staticmethod
734
+ def _get_home_position() -> Dict[Axis, float]:
735
+ return {
736
+ Axis.Z_L: 0,
737
+ Axis.Z_R: 0,
738
+ Axis.X: 0,
739
+ Axis.Y: 0,
740
+ Axis.P_L: 0,
741
+ Axis.P_R: 0,
742
+ Axis.Z_G: 0,
743
+ Axis.G: 0,
744
+ }
745
+
746
+ @staticmethod
747
+ def home_position() -> OT3AxisMap[float]:
748
+ return OT3Simulator._get_home_position()
749
+
750
+ @ensure_yield
751
+ async def capacitive_probe(
752
+ self,
753
+ mount: OT3Mount,
754
+ moving: Axis,
755
+ distance_mm: float,
756
+ speed_mm_per_s: float,
757
+ sensor_threshold_pf: float,
758
+ probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
759
+ ) -> bool:
760
+ self._position[moving] += distance_mm
761
+ return True
762
+
763
+ @ensure_yield
764
+ async def capacitive_pass(
765
+ self,
766
+ mount: OT3Mount,
767
+ moving: Axis,
768
+ distance_mm: float,
769
+ speed_mm_per_s: float,
770
+ probe: InstrumentProbeType,
771
+ ) -> List[float]:
772
+ self._position[moving] += distance_mm
773
+ return []
774
+
775
+ @property
776
+ def subsystems(self) -> Dict[SubSystem, SubSystemState]:
777
+ return {
778
+ AXIS_TO_SUBSYSTEM[axis]: SubSystemState(
779
+ ok=True,
780
+ current_fw_version=1,
781
+ next_fw_version=1,
782
+ fw_update_needed=False,
783
+ current_fw_sha="simulated",
784
+ pcba_revision="A1",
785
+ update_state=None,
786
+ )
787
+ for axis in self._present_axes
788
+ }
789
+
790
+ async def get_tip_status(
791
+ self,
792
+ mount: OT3Mount,
793
+ follow_singular_sensor: Optional[InstrumentProbeType] = None,
794
+ ) -> TipStateType:
795
+ return TipStateType(self._sim_tip_state[mount])
796
+
797
+ def current_tip_state(self, mount: OT3Mount) -> Optional[bool]:
798
+ return self._sim_tip_state[mount]
799
+
800
+ async def update_tip_detector(self, mount: OT3Mount, sensor_count: int) -> None:
801
+ pass
802
+
803
+ async def teardown_tip_detector(self, mount: OT3Mount) -> None:
804
+ pass
805
+
806
+ async def set_status_bar_state(self, state: StatusBarState) -> None:
807
+ self._sim_status_bar_state = state
808
+ await asyncio.sleep(0)
809
+
810
+ async def set_status_bar_enabled(self, enabled: bool) -> None:
811
+ await asyncio.sleep(0)
812
+
813
+ def get_status_bar_enabled(self) -> bool:
814
+ return True
815
+
816
+ def get_status_bar_state(self) -> StatusBarState:
817
+ return self._sim_status_bar_state
818
+
819
+ @property
820
+ def estop_status(self) -> EstopOverallStatus:
821
+ return EstopOverallStatus(
822
+ state=self._sim_estop_state,
823
+ left_physical_state=self._sim_estop_left_state,
824
+ right_physical_state=self._sim_estop_right_state,
825
+ )
826
+
827
+ def estop_acknowledge_and_clear(self) -> EstopOverallStatus:
828
+ """Attempt to acknowledge an Estop event and clear the status.
829
+
830
+ Returns the estop status after clearing the status."""
831
+ self._sim_estop_state = EstopState.DISENGAGED
832
+ self._sim_estop_left_state = EstopPhysicalStatus.DISENGAGED
833
+ self._sim_estop_right_state = EstopPhysicalStatus.DISENGAGED
834
+ return self.estop_status
835
+
836
+ def get_estop_state(self) -> EstopState:
837
+ return self._sim_estop_state
838
+
839
+ def add_estop_callback(self, cb: HardwareEventHandler) -> HardwareEventUnsubscriber:
840
+ return lambda: None
841
+
842
+ def check_gripper_position_within_bounds(
843
+ self,
844
+ expected_grip_width: float,
845
+ grip_width_uncertainty_wider: float,
846
+ grip_width_uncertainty_narrower: float,
847
+ jaw_width: float,
848
+ max_allowed_grip_error: float,
849
+ hard_limit_lower: float,
850
+ hard_limit_upper: float,
851
+ ) -> None:
852
+ # This is a (pretty bad) simulation of the gripper actually gripping something,
853
+ # but it should work.
854
+ self._encoder_position[Axis.G] = (hard_limit_upper - jaw_width) / 2
855
+
856
+ async def set_hepa_fan_state(self, fan_on: bool, duty_cycle: int) -> bool:
857
+ return False
858
+
859
+ async def get_hepa_fan_state(self) -> Optional[HepaFanState]:
860
+ return None
861
+
862
+ async def set_hepa_uv_state(self, light_on: bool, timeout_s: int) -> bool:
863
+ return False
864
+
865
+ async def get_hepa_uv_state(self) -> Optional[HepaUVState]:
866
+ return None
867
+
868
+ def _update_tip_state(self, mount: OT3Mount, status: bool) -> None:
869
+ """This is something we only use in the simulator.
870
+ It is required so that PE simulations using ot3api don't break."""
871
+ self._sim_tip_state[mount] = status
872
+
873
+ async def increase_evo_disp_count(self, mount: OT3Mount) -> None:
874
+ pass
875
+
876
+ async def read_env_temp_sensor(
877
+ self, mount: OT3Mount, primary: bool
878
+ ) -> Optional[float]:
879
+ """Read and return the current sensor information."""
880
+
881
+ return 0.0
882
+
883
+ async def read_env_hum_sensor(
884
+ self, mount: OT3Mount, primary: bool
885
+ ) -> Optional[float]:
886
+ """Read and return the current sensor information."""
887
+
888
+ return 0.0
889
+
890
+ async def read_pressure_sensor(
891
+ self, mount: OT3Mount, primary: bool
892
+ ) -> Optional[float]:
893
+ """Read and return the current sensor information."""
894
+ return 0.0
895
+
896
+ async def read_capacitive_sensor(
897
+ self, mount: OT3Mount, primary: bool
898
+ ) -> Optional[float]:
899
+ """Read and return the current sensor information."""
900
+ return 0.0