Make nervlists relative
[saartuer.git] / statemachine.py
index 6a3e88961c2749d567ff7b406896f6d9fffc42da..f2cac47d8df7d2462aaf8222b48816d4bd0a35e0 100644 (file)
@@ -44,13 +44,17 @@ class Nerver():
        # If f returns something, that's also returned by nerv.
        def __init__(self, nervlist):
                self.nervlist = list(nervlist)
+               self.last_event_time = time.time()
        
-       def nerv(self, total_time):
+       def nerv(self):
                if len(self.nervlist):
                        (time, f) = self.nervlist[0]
+                       now = time.time()
+                       time_gone = now-self.last_event_time
                        # check if the first element is to be triggered
-                       if time >= total_time:
+                       if time_gone >= time:
                                self.nervlist = self.nervlist[1:] # "pop" the first element, but do not modify original list
+                               self.last_event_time = now
                                return f()
 
 
@@ -65,7 +69,6 @@ class StateMachine():
        class State():
                def __init__(self, state_machine, nervlist = None):
                        self.state_machine = state_machine
-                       self.time_entered = time.time()
                        self._nerver = None if nervlist is None else Nerver(nervlist)
                def handle_pins_event(self):
                        pass # one needn't implement this
@@ -77,7 +80,7 @@ class StateMachine():
                                arg("412 Precondition Failed: The current state (%s) cannot handle the OPEN event" % self.__class__.__name__)
                def handle_wakeup_event(self):
                        if self._nerver is not None:
-                               return self._nerver.nerv(time.time() - self.time_entered)
+                               return self._nerver.nerv()
                def pins(self):
                        return self.state_machine.pins
                def actor(self):
@@ -119,8 +122,8 @@ class StateMachine():
        class StateUnlocking(State):
                def __init__(self,callback,sm):
                        # construct a nervlist
-                       nervlist = [(t*OPEN_REPEAT_TIMEOUT, lambda: self.actor().act(Actor.CMD_UNLOCK)) for t in xrange(1, OPEN_REPEAT_NUMBER+1)]
-                       nervlist += [((OPEN_REPEAT_NUMBER+1)*OPEN_REPEAT_TIMEOUT, self.could_not_open)]
+                       nervlist = [(OPEN_REPEAT_TIMEOUT, lambda: self.actor().act(Actor.CMD_UNLOCK)) for t in xrange(OPEN_REPEAT_NUMBER)]
+                       nervlist += [(OPEN_REPEAT_TIMEOUT, self.could_not_open)]
                        super().__init__(sm,nervlist)
                        self.callbacks=[callback]
                        # FIXME: can we send "202 processing: Trying to open the door" here? Are the callbacks multi-use?
@@ -183,14 +186,13 @@ class StateMachine():
                                logger.error("door manually locked, but space switch on - going to StateZu")
                                play_sound("manual_lock")
                                return StateZu(self.state_machine)
-               # handle_wakeup_event intentionally not overwritten
        
        class StateLocking(State):
                # FIXME: Why does this even have callbacks?
                # TODO: share code with StateUnlocking
                def __init__(self,sm):
                        # construct a nervlist
-                       nervlist = [(t*CLOSE_REPEAT_TIMEOUT, lambda: self.actor().act(Actor.CMD_LOCK)) for t in xrange(1, CLOSE_REPEAT_NUMBER+1)]
+                       nervlist = [(t*CLOSE_REPEAT_TIMEOUT, lambda: self.actor().act(Actor.CMD_LOCK)) for t in range(1, CLOSE_REPEAT_NUMBER+1)]
                        nervlist += [((CLOSE_REPEAT_NUMBER+1)*CLOSE_REPEAT_TIMEOUT, self.could_not_close)]
                        super().__init__(sm, nervlist)
                        self.callbacks=[]
@@ -219,26 +221,24 @@ class StateMachine():
                        return StateAboutToOpen(self.state_machine)
        
        class StateAboutToLeave(State):
+               def __init__(self, sm):
+                       nervlist = [(LEAVE_TIMEOUT, lambda: StateLocking(self.state_machine))]
+                       super().__init__(sm, nervlist)
                def handle_pins_event(self):
                        if not self.pins().door_closed:
                                return StateLeaving(self.state_machine)
                        if self.pins().door_locked:
                                return StateZu(self.state_machine)
-               def handle_wakeup_event(self):
-                       over = time.time() - self.time_entered
-                       if over >= LEAVE_TIMEOUT:
-                               return StateLocking(self.state_machine)
        
        class StateLeaving(State):
+               def __init__(self, sm):
+                       nervlist = [(LEAVE_TIMEOUT, lambda: StateAboutToOpen(self.state_machine))]
+                       super().__init__(sm, nervlist)
                def handle_pins_event(self):
                        if self.pins().door_closed:
                                return StateLocking(self.state_machine)
                        if self.pins().door_locked:
                                return StateZu(self.state_machine)
-               def handle_wakeup_event(self):
-                       over = time.time() - self.time_entered
-                       if over >= LEAVE_TIMEOUT:
-                               return StateAboutToOpen(self.state_machine)
        
        def __init__(self, actor):
                self.actor = actor