Repository: opentrons/opentrons
Issue: Delay Command Kills Robot Run

Using a 'delay' command in a protocol causes the protocol run to stop and not recover.

## Expected Behavior
- Robot should delay for specified amount of time and then continue running

## Observed Behavior
- Robot delays for specified about of time, begins next action (?), and then stops

## Steps to Recreate
- Connect to robot young-moon (science bot)
- Load a protocol with 'p300.delay(seconds=60)'
-- Tested with protocol copied below
- Run protocol
- Observe robot pause for appropriate amount of time at delay step, make an additional movement (possibly beginning of next aspirate?) and then stop
- Remove delay from protocol
- Run protocol and observe that it runs fine
- Note: also observed with 'robot.pause('')'

Changed files:
api/tests/opentrons/labware/test_pipette.py, api/opentrons/instruments/pipette.py

diff --git a/api/opentrons/instruments/pipette.py b/api/opentrons/instruments/pipette.py
index cdf11e8b20..1318adcad5 100755
--- a/api/opentrons/instruments/pipette.py
+++ b/api/opentrons/instruments/pipette.py
@@ -1,6 +1,7 @@
 import itertools
 import warnings
 import logging
+import time
 
 from opentrons import commands
 from opentrons.containers import unpack_location
@@ -33,6 +34,10 @@ SHAKE_OFF_TIPS_SPEED = 50
 SHAKE_OFF_TIPS_DISTANCE = 2
 
 
+def _sleep(seconds):
+    time.sleep(seconds)
+
+
 class PipetteTip:
     def __init__(self, length):
         self.length = length
@@ -1301,14 +1306,16 @@ class Pipette:
         ----------
 
         seconds: float
-            The number of seconds to freeeze in place.
+            The number of seconds to freeze in place.
         """
 
         minutes += int(seconds / 60)
         seconds = seconds % 60
         seconds += float(minutes * 60)
 
-        self.instrument_actuator.delay(seconds)
+        self.robot.pause()
+        _sleep(seconds)
+        self.robot.resume()
 
         return self
 
diff --git a/api/tests/opentrons/labware/test_pipette.py b/api/tests/opentrons/labware/test_pipette.py
index 1b0fe1e906..d8c098d71b 100755
--- a/api/tests/opentrons/labware/test_pipette.py
+++ b/api/tests/opentrons/labware/test_pipette.py
@@ -3,6 +3,7 @@
 import unittest
 from unittest import mock
 from opentrons.robot.robot import Robot
+from opentrons import instruments
 from opentrons.containers import load as containers_load
 from opentrons.instruments import Pipette
 # from opentrons.util.vector import Vector
@@ -168,6 +169,36 @@ def test_dispense_move_to(robot):
     assert isclose(current_pos, (175.34,  127.94,   10.5)).all()
 
 
+def test_delay_calls(monkeypatch):
+    from opentrons import robot
+    from opentrons.instruments import pipette
+    robot.reset()
+    p200 = instruments.P300_Single(mount='right')
+
+    cmd = []
+
+    def mock_pause():
+        nonlocal cmd
+        cmd.append('pause')
+
+    def mock_resume():
+        nonlocal cmd
+        cmd.append('resume')
+
+    def mock_sleep(seconds):
+        cmd.append("sleep {}".format(seconds))
+
+    monkeypatch.setattr(robot, 'pause', mock_pause)
+    monkeypatch.setattr(robot, 'resume', mock_resume)
+    monkeypatch.setattr(pipette, '_sleep', mock_sleep)
+
+    p200.delay(seconds=4, minutes=1)
+
+    assert 'pause' in cmd
+    assert 'sleep 64.0' in cmd
+    assert 'resume' in cmd
+
+
 class PipetteTest(unittest.TestCase):
     def setUp(self):
         self.robot = Robot()
@@ -453,20 +484,6 @@ class PipetteTest(unittest.TestCase):
     #         {'a': 0, 'b': 10.0}
     #     )
 
-    def test_delay(self):
-        self.p200.delay(1)
-
-        self.assertEqual(
-            self.robot.commands()[-1],
-            "Delaying for 0m 1s")
-
-        self.robot.clear_commands()
-        self.p200.delay(seconds=12, minutes=10)
-
-        self.assertEqual(
-            self.robot.commands()[-1],
-            "Delaying for 10m 12s")
-
     def test_set_speed(self):
         self.p200.set_speed(aspirate=100)
         self.assertEqual(self.p200.speeds['aspirate'], 100)