@@ -88,13 +88,20 @@ class QueueStatus(enum.Enum):
88
88
New fixup commands may be enqueued and will execute immediately.
89
89
"""
90
90
91
+ AWAITING_RECOVERY_PAUSED = enum .auto ()
92
+ """Execution of fixit commands has been paused.
91
93
92
- class RunResult (str , enum .Enum ):
94
+ New protocol and fixit commands may be enqueued, but will wait to execute.
95
+ New setup commands may not be enqueued.
96
+ """
97
+
98
+
99
+ class RunResult (enum .Enum ):
93
100
"""Result of the run."""
94
101
95
- SUCCEEDED = "succeeded"
96
- FAILED = "failed"
97
- STOPPED = "stopped"
102
+ SUCCEEDED = enum . auto ()
103
+ FAILED = enum . auto ()
104
+ STOPPED = enum . auto ()
98
105
99
106
100
107
@dataclass (frozen = True )
@@ -348,11 +355,20 @@ def handle_action(self, action: Action) -> None: # noqa: C901
348
355
self ._state .run_started_at = (
349
356
self ._state .run_started_at or action .requested_at
350
357
)
351
- if self ._state .is_door_blocking :
352
- # Always inactivate queue when door is blocking
353
- self ._state .queue_status = QueueStatus .PAUSED
354
- else :
355
- self ._state .queue_status = QueueStatus .RUNNING
358
+ match self ._state .queue_status :
359
+ case QueueStatus .SETUP :
360
+ self ._state .queue_status = (
361
+ QueueStatus .PAUSED
362
+ if self ._state .is_door_blocking
363
+ else QueueStatus .RUNNING
364
+ )
365
+ case QueueStatus .AWAITING_RECOVERY_PAUSED :
366
+ self ._state .queue_status = QueueStatus .AWAITING_RECOVERY
367
+ case QueueStatus .PAUSED :
368
+ self ._state .queue_status = QueueStatus .RUNNING
369
+ case QueueStatus .RUNNING | QueueStatus .AWAITING_RECOVERY :
370
+ # Nothing for the play action to do. No-op.
371
+ pass
356
372
357
373
elif isinstance (action , PauseAction ):
358
374
self ._state .queue_status = QueueStatus .PAUSED
@@ -364,8 +380,7 @@ def handle_action(self, action: Action) -> None: # noqa: C901
364
380
365
381
elif isinstance (action , StopAction ):
366
382
if not self ._state .run_result :
367
- if self ._state .queue_status == QueueStatus .AWAITING_RECOVERY :
368
- self ._state .recovery_target_command_id = None
383
+ self ._state .recovery_target_command_id = None
369
384
370
385
self ._state .queue_status = QueueStatus .PAUSED
371
386
if action .from_estop :
@@ -422,10 +437,15 @@ def handle_action(self, action: Action) -> None: # noqa: C901
422
437
if self ._config .block_on_door_open :
423
438
if action .door_state == DoorState .OPEN :
424
439
self ._state .is_door_blocking = True
425
- # todo(mm, 2024-03-19): It's unclear how the door should interact
426
- # with error recovery (QueueStatus.AWAITING_RECOVERY).
427
- if self ._state .queue_status != QueueStatus .SETUP :
428
- self ._state .queue_status = QueueStatus .PAUSED
440
+ match self ._state .queue_status :
441
+ case QueueStatus .SETUP :
442
+ pass
443
+ case QueueStatus .RUNNING | QueueStatus .PAUSED :
444
+ self ._state .queue_status = QueueStatus .PAUSED
445
+ case QueueStatus .AWAITING_RECOVERY | QueueStatus .AWAITING_RECOVERY_PAUSED :
446
+ self ._state .queue_status = (
447
+ QueueStatus .AWAITING_RECOVERY_PAUSED
448
+ )
429
449
elif action .door_state == DoorState .CLOSED :
430
450
self ._state .is_door_blocking = False
431
451
@@ -847,18 +867,19 @@ def validate_action_allowed( # noqa: C901
847
867
raise RunStoppedError ("The run has already stopped." )
848
868
849
869
elif isinstance (action , PlayAction ):
850
- if self .get_status () == EngineStatus .BLOCKED_BY_OPEN_DOOR :
870
+ if self .get_status () in (
871
+ EngineStatus .BLOCKED_BY_OPEN_DOOR ,
872
+ EngineStatus .AWAITING_RECOVERY_BLOCKED_BY_OPEN_DOOR ,
873
+ ):
851
874
raise RobotDoorOpenError ("Front door or top window is currently open." )
852
- elif self .get_status () == EngineStatus .AWAITING_RECOVERY :
853
- raise NotImplementedError ()
854
875
else :
855
876
return action
856
877
857
878
elif isinstance (action , PauseAction ):
858
879
if not self .get_is_running ():
859
880
raise PauseNotAllowedError ("Cannot pause a run that is not running." )
860
881
elif self .get_status () == EngineStatus .AWAITING_RECOVERY :
861
- raise NotImplementedError ( )
882
+ raise PauseNotAllowedError ( "Cannot pause a run in recovery mode." )
862
883
else :
863
884
return action
864
885
@@ -901,7 +922,7 @@ def validate_action_allowed( # noqa: C901
901
922
else :
902
923
assert_never (action )
903
924
904
- def get_status (self ) -> EngineStatus :
925
+ def get_status (self ) -> EngineStatus : # noqa: C901
905
926
"""Get the current execution status of the engine."""
906
927
if self ._state .run_result :
907
928
# The main part of the run is over, or will be over soon.
@@ -936,6 +957,12 @@ def get_status(self) -> EngineStatus:
936
957
else :
937
958
return EngineStatus .PAUSED
938
959
960
+ elif self ._state .queue_status == QueueStatus .AWAITING_RECOVERY_PAUSED :
961
+ if self ._state .is_door_blocking :
962
+ return EngineStatus .AWAITING_RECOVERY_BLOCKED_BY_OPEN_DOOR
963
+ else :
964
+ return EngineStatus .AWAITING_RECOVERY_PAUSED
965
+
939
966
elif self ._state .queue_status == QueueStatus .AWAITING_RECOVERY :
940
967
return EngineStatus .AWAITING_RECOVERY
941
968
0 commit comments