Merge branch 'master' of ralfj.de:saartuer
authorConstantin Berhard <constantin@exxxtremesys.lu>
Thu, 10 Oct 2013 14:54:04 +0000 (16:54 +0200)
committerConstantin Berhard <constantin@exxxtremesys.lu>
Thu, 10 Oct 2013 14:54:04 +0000 (16:54 +0200)
1  2 
statemachine.py

diff --combined statemachine.py
index 4b82def39c8859f66539fbadc64f6a75822fe3d3,dc00ca537f59d42f5e7f55f199e7663eaf32e691..1d75b2c1c53d2f12433a0d1a88fe73c01e3307be
@@@ -18,10 -18,6 +18,10 @@@ def play_sound (what)
  OPEN_REPEAT_TIMEOUT = 8
  OPEN_REPEAT_NUMBER = 3
  
 +# StateClosing constants
 +CLOSE_REPEAT_TIMEOUT = 8
 +CLOSE_REPEAT_NUMBER = 3
 +
  # StateAboutToOpen constants
  ABOUTOPEN_NERVLIST = [(5, lambda : play_sound("flipswitch")), (10, lambda:play_sound("flipswitch")), (10, lambda:Logger.warning("Space open but switch not flipped for 10 seconds")),\
        (20, lambda:play_sound("flipswitch")), (30, lambda:play_sound("flipswitch")), (30, lambda:Logger.error("Space open but switch not flipped for 30 seconds")),\
@@@ -77,9 -73,8 +77,8 @@@ class StateMachine()
                                raise Exception("Unknown command number: %d" % ev)
        
        class StateStart(State):
-               def __init__(self, sm):
-                       State.__init__(self,sm)
                def handle_pins_event(self):
+                       super().handle_pins_event()
                        thepins = self.pins()
                        for pin in thepins:
                                if pin is None:
                                return StateAuf
  
        class StateZu(State):
-               def __init__(self,sm):
-                       State.__init__(self,sm)
                def handle_pins_event(self):
+                       super().handle_pins_event()
                        pins = self.pins()
                        if not pins.door_locked:
                                return StateAboutToOpen(self.state_machine)
                def handle_open_event(self,callback):
+                       # intentionally not calling super() implementation
                        return StateOpening(callback,self.state_machine)
        
        class StateOpening(State):
                def __init__(self,callback,sm):
-                       State.__init__(self,sm)
+                       super().__init__(self,sm)
                        self.callbacks=[callback]
                        # FIXME: can we send "202 processing: Trying to open the door" here? Are the callbacks multi-use?
                        self.tries = 0
                                if cb is not None:
                                        cb(s)
                def handle_pins_event(self):
+                       super().handle_pins_event()
                        pins = self.pins()
                        if not pins.door_locked:
                                self.notify(True)
                                return StateAboutToOpen(self.state_machine)
                def handle_open_event(self,callback):
+                       # intentionally not calling super() implementation
                        # FIXME: 202 notification also here if possible
                        self.callbacks.append(callback)
                def handle_wakeup_event(self):
+                       super().handle_wakeup_event()
                        over = time.time() - self.time_entered
                        nexttry = (self.tries+1) * OPEN_REPEAT_TIMEOUT
                        if over > nexttry:
                                        return StateZu(self.state_machine)
        
        class AbstractStateWhereOpeningIsRedundant(State):
-               def __init__ (self,sm):
-                       State.__init__(sm):
                def handle_open_event(self, callback):
+                       # intentionally not calling super() implementation
+                       # FIXME contradicting original plan where open would be ignored in StateAboutToOpen?
                        callback("299 redundant: Space seems to be already open. Still processing your request tough.")
                        logger.warning("Received OPEN command in StateAboutToOpen. This should not be necessary.")
                        self.actor().act(Actor.CMD_OPEN)
        
        class StateAboutToOpen(AbstractStateWhereOpeningIsRedundant):
-               def __init__(self, sm):
-                       AbstractStateWhereOpeningIsRedundant.__init__(sm)
                def handle_pins_event(self):
+                       super().handle_pins_event()
                        pins = self.pins()
                        if pins.door_locked:
                                return StateZu(self.state_machine)
                        elif pins.space_active:
                                return StateAuf(self.state_machine)
                def handle_wakeup_event(self):
+                       super().handle_wakeup_event()
                        now = time.time()
                        lasttime = self.last_wakeup - self.time_entered
                        thistime = now - self.time_entered
        
        class StateAuf(AbstractStateWhereOpeningIsRedundant):
                def __init__(self,sm):
-                       AbstractStateWhereOpeningIsRedundant.__init__(sm)
+                       super().__init__(sm)
                        self.last_buzzed = None
                def handle_pins_event(self):
+                       super().handle_pins_event()
                        pins = self.pins()
                        if pins.bell_ringing:
                                now = time.time()
                # handle_wakeup_event intentionally not overwritten
        
        class StateClosing(State):
 -              #TODO Ralf/Conny
 -              pass
 +              # TODO: share code with StateOpening, and possibly also with the nerv-mechanism from StateAboutToOpen
 +              def __init__(self,callback,sm):
 +                      State.__init__(self,sm)
 +                      self.callbacks=[callback]
 +                      # FIXME: can we send "202 processing: Trying to close the door" here? Are the callbacks multi-use?
 +                      self.tries = 0
 +                      self.actor().act(Actor.CMD_CLOSE)
 +              def notify(self, did_it_work):
 +                      s = "200 okay: door closed" if did_it_work else ("500 internal server error: Couldn't close door with %d tries à %f seconds" % (CLOSE_REPEAT_NUMBER,CLOSE_REPEAT_TIMEOUT))
 +                      for cb in self.callbacks:
 +                              if cb is not None:
 +                                      cb(s)
 +              def handle_pins_event(self):
 +                      pins = self.pins()
 +                      if not pins.door_locked:
 +                              self.notify(True)
 +                              return StateAboutToOpen(self.state_machine)
 +              def handle_open_event(self,callback):
 +                      callback("409 conflict: The server is currently trying to close the door. Try again later.")
 +              def handle_wakeup_event(self):
 +                      over = time.time() - self.time_entered
 +                      nexttry = (self.tries+1) * CLOSE_REPEAT_TIMEOUT
 +                      if over > nexttry:
 +                              if self.tries < CLOSE_REPEAT_NUMBER:
 +                                      self.actor().act(Actor.CMD_CLOSE)
 +                                      self.tries += 1
 +                              else:
 +                                      logger.critical("Couldn't close door after %d tries. Going back to StateAboutToOpen." % CLOSE_REPEAT_NUMBER)
 +                                      self.notify(False)
 +                                      return StateAboutToOpen(self.state_machine)
        
        class StateAboutToLeave(State):
                #TODO Ralf
        def _callback(self, cmd, arg=None):
                # update pins
                if cmd == StateMachine.CMD_PINS:
-                       self.old_pins = self.pins
                        self.pins = arg
                # handle stuff
                newstate = self.current_state.handle_event(cmd,arg) # returns None or an instance of the new state
+               self.old_pins = self.pins # FIXME not used?
                while newstate is not None:
                        logger.info("StateMachine: new state = %s" % newstate.__class__.__name__)
                        self.current_state = newstate