timer.py (4992B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\actions\timer.py 2 import logging 3 import random 4 import uthread2 5 from behaviors import status 6 from behaviors.tasks import Task 7 from ccpProfile import TimedFunction 8 logger = logging.getLogger(__name__) 9 10 class TimeoutAction(Task): 11 12 def __init__(self, attributes): 13 super(TimeoutAction, self).__init__(attributes) 14 15 @TimedFunction('behaviors::actions::timer::TimeoutAction::OnEnter') 16 def OnEnter(self): 17 self.SetStatusToSuccess() 18 timeoutThread = uthread2.StartTasklet(self._TimeoutThread) 19 self.SetContextValue('timeoutThread', timeoutThread) 20 21 def CleanUp(self): 22 super(TimeoutAction, self).CleanUp() 23 timeoutThread = self.GetContextValue('timeoutThread') 24 if timeoutThread: 25 timeoutThread.kill() 26 27 def _TimeoutThread(self): 28 timeoutSeconds = self._GetTimeoutSeconds() 29 logger.debug('OnTimeout started timeoutSeconds %s', timeoutSeconds) 30 uthread2.SleepSim(timeoutSeconds) 31 logger.debug('OnTimeout waking up') 32 self._OnTimeout() 33 34 def _OnTimeout(self): 35 raise NotImplementedError 36 37 def _GetTimeoutSeconds(self): 38 if getattr(self.attributes, 'timeoutMilliSecondsAddress', None): 39 return self.GetLastBlackboardValue(self.attributes.timeoutMilliSecondsAddress) / 1000 40 return self.attributes.timeoutSeconds 41 42 43 class FailUntilTimeoutAction(Task): 44 45 @TimedFunction('behaviors::actions::timer::FailUntilTimeoutAction::OnEnter') 46 def OnEnter(self): 47 resetValue = self.GetLastBlackboardValue(self.attributes.triggerAddress) 48 if resetValue: 49 self.SetStatusToSuccess() 50 self.SendBlackboardValue(self.attributes.triggerAddress, False) 51 else: 52 self.SetStatusToFailed() 53 channel = self.GetChannelFromAddress(self.attributes.timerAddress) 54 timerValue = channel.GetLastMessageValue() 55 if timerValue is None: 56 self.SetStatusToFailed() 57 self.context.timerManager.StartTimer(self.attributes.timeoutSeconds, channel) 58 channel.AddObserver(self._OnTimeout) 59 60 def _OnTimeout(self, name, message): 61 if message.value is None and not self.IsInvalid(): 62 self.SendBlackboardValue(self.attributes.triggerAddress, True) 63 channel = self.GetChannelFromAddress(self.attributes.timerAddress) 64 self.context.timerManager.StartTimer(self.attributes.timeoutSeconds, channel) 65 self.behaviorTree.RequestReset(requestedBy=self) 66 67 def CleanUp(self): 68 if not self.IsInvalid(): 69 self.UnsubscribeToBlackboard(self.attributes.timerAddress, self._OnTimeout) 70 super(FailUntilTimeoutAction, self).CleanUp() 71 72 73 class SucceedAfterTimeoutAction(TimeoutAction): 74 75 @TimedFunction('behaviors::actions::timer::SucceedAfterTimeoutAction::OnEnter') 76 def OnEnter(self): 77 super(SucceedAfterTimeoutAction, self).OnEnter() 78 self.SetStatusToSuspended() 79 80 def _OnTimeout(self): 81 if not self.IsInvalid(): 82 self.SetStatusToSuccess() 83 self.status.OnUpdated(self) 84 self.behaviorTree.StartTaskNextTick(self) 85 86 87 class ClearValueAndResetAfterTimeout(TimeoutAction): 88 89 def _OnTimeout(self): 90 self.SendBlackboardValue(self.attributes.targetAddress, None) 91 self.behaviorTree.RequestReset(requestedBy=self) 92 93 94 class BlockWhileTimeout(Task): 95 96 @TimedFunction('behaviors::actions::timer::BlockWhileTimeout::OnEnter') 97 def OnEnter(self): 98 timerValue = self.GetLastBlackboardValue(self.attributes.timerAddress) 99 if self.attributes.maxRandomTimeoutSeconds: 100 secondsUntilReset = random.randint(self.attributes.timeoutSeconds, self.attributes.maxRandomTimeoutSeconds) 101 else: 102 secondsUntilReset = self.attributes.timeoutSeconds 103 if timerValue is None: 104 channel = self.GetChannelFromAddress(self.attributes.timerAddress) 105 self.context.timerManager.StartTimer(secondsUntilReset, channel) 106 self.status = status.TaskSuspendedStatus 107 self.SubscribeToBlackboard(self.attributes.timerAddress, self._OnTimeout) 108 109 def OnExit(self): 110 self.UnsubscribeToBlackboard(self.attributes.timerAddress, self._OnTimeout) 111 112 def _OnTimeout(self, name, message): 113 if self.IsInvalid(): 114 return 115 if message.value is None: 116 self.SetStatusToSuccess() 117 self.behaviorTree.StartTaskNextTick(self) 118 119 def CleanUp(self): 120 if not self.IsInvalid(): 121 self.UnsubscribeToBlackboard(self.attributes.timerAddress, self._OnTimeout) 122 super(BlockWhileTimeout, self).CleanUp() 123 124 125 class ClearTimer(Task): 126 127 def OnEnter(self): 128 timer_id = self.GetLastBlackboardValue(self.attributes.timerAddress) 129 if timer_id is not None: 130 self.context.timerManager.ClearTimer(timer_id) 131 self.SetStatusToSuccess()