Merge branch 'master' of ralfj.de:saartuer
authorRalf Jung <post@ralfj.de>
Thu, 24 Oct 2013 17:45:26 +0000 (19:45 +0200)
committerRalf Jung <post@ralfj.de>
Thu, 24 Oct 2013 17:45:26 +0000 (19:45 +0200)
Conflicts:
statemachine.py

1  2 
statemachine.py
tuerd

diff --combined statemachine.py
index c73bea0321c0f42dd99350fc09f10e45e2c4e057,3a27adaf8c58a5cd384c417283bf82236450e706..a3c4affb860ed23733d41fbef7f4868f22c9889e
@@@ -1,6 -1,6 +1,6 @@@
  from libtuer import ThreadFunction, logger, fire_and_forget
  from actor import Actor
- import os, random, time
+ import os, random, time, threading
  
  # logger.{debug,info,warning,error,critical}
  
@@@ -22,6 -22,10 +22,10 @@@ OPEN_REPEAT_NUMBER = 
  CLOSE_REPEAT_TIMEOUT = 7
  CLOSE_REPEAT_NUMBER = 3
  
+ # StateFallback constants
+ FALLBACK_BLINK_SPEED = 0.5 # seconds
+ FALLBACK_LEAVE_DELAY_LOCK = 5 # seconds
  # StateAboutToOpen constants
  ABOUTOPEN_NERVLIST = [(5, lambda : play_sound("flipswitch")), (5, lambda:play_sound("flipswitch")), (0, lambda:logger.warning("Space open but switch not flipped for 10 seconds")),\
        (10, lambda:play_sound("flipswitch")), (10, lambda:play_sound("flipswitch")), (0, lambda:logger.error("Space open but switch not flipped for 30 seconds")),\
@@@ -133,17 -137,63 +137,63 @@@ class StateMachine()
                        return super().handle_pins_event()
        
        class StateStart(State):
+               def __init__(self, sm, nervlist = None, fallback=False):
+                       super().__init__(self, sm, nervlist)
+                       self.fallback = fallback
                def handle_pins_event(self):
                        pins = self.pins()
                        if not (pins.door_locked is None or pins.door_closed is None or pins.space_active is None or pins.bell_ringing is None):
 -                              logger.info("All sensors got a value, switching to a proper state")
+                               if self.fallback:
+                                       logger.info("Going to StateFallback because running in fallback mode")
+                                       return StateMachine.StateFallback(self.state_machine)
                                if pins.door_locked:
 +                                      logger.info("All sensors got a value, switching to a proper state: Space is closed")
                                        return StateMachine.StateZu(self.state_machine)
                                else:
 +                                      logger.info("All sensors got a value, switching to a proper state: Space is (about to) open")
                                        return StateMachine.StateAboutToOpen(self.state_machine)
                        return super().handle_pins_event()
        
 -                      # without return because we want to stay in fallback mode
 -                      super().handle_pins_event()
+       class StateFallback(State):
+               def __init__(self, sm, nervlist = None):
+                       super().__init__(self, sm, nervlist)
+                       self._last_blink_time = time.time()
+                       self._red_state = False
+               def handle_pins_event(self):
+                       pins = self.pins()
+                       # buzz if open and bell rang
+                       if pins.space_active and pins.bell_ringing and not self.old_pins().bell_ringing:
+                               logger.info("StateFallback: Space switch on and door bell rung => buzzing")
+                               self.actor().act(Actor.CMD_BUZZ)
+                       # set green LED according to space switch
+                       if pins.space_active:
+                               self.actor().act(Actor.CMD_GREEN_ON)
+                       else:
+                               self.actor().act(Actor.CMD_GREEN_OFF)
+                       # primitive leaving procedure if space switch turned off
+                       if not pins.space_active and self.old_pins().space_active:
+                               def _close_after_time():
+                                       time.sleep(FALLBACK_LEAVE_DELAY_LOCK)
+                                       self.actor().act(Actor.CMD_LOCK)
+                               t = threading.Thread(target=_close_after_time)
+                               t.start()
++                      # not calling superclass because we want to stay in fallback mode
+               def handle_wakeup_event(self):
+                       # blink red LED
+                       now = time.time()
+                       if now - self._last_blink_time < FALLBACK_BLINK_SPEED:
+                               if self._red_state:
+                                       self.actor().act(Actor.CMD_RED_OFF)
+                                       self._red_state = False
+                               else:
+                                       self.actor().act(Actor.CMD_RED_ON)
+                                       self._red_state = True
+                               self._last_blink_time = now
+               def handle_cmd_unlock_event(self,arg):
+                       if arg is not None:
+                               arg("298 Fallback Okay: Trying to unlock the door. The System is in fallback mode, success information is not available.")
+                       self.actor().act(Actor.CMD_UNLOCK)
+       
        class StateZu(AbstractLockedState):
                def handle_cmd_unlock_event(self,callback):
                        return StateMachine.StateUnlocking(self.state_machine, callback)
                                return StateMachine.StateAuf(self.state_machine)
                        return super().handle_pins_event()
        
-       def __init__(self, actor):
+       def __init__(self, actor, fallback = False):
                self.actor = actor
                self.callback = ThreadFunction(self._callback, name="StateMachine")
-               self.current_state = StateMachine.StateStart(self)
+               self.current_state = StateMachine.StateStart(self, fallback)
                self.pins = None
                self.old_pins = None
        
diff --combined tuerd
index ec51c94ee15fb65645a4190820e584ed40e2051d,50fe03f8b08a8e058c1fc093a1aa826d8d4791d9..92c4122c2cf0678e8f0fc20f875a3bf6ae481e6b
--- 1/tuerd
--- 2/tuerd
+++ b/tuerd
@@@ -9,20 -9,25 +9,28 @@@ parser = argparse.ArgumentParser(descri
  parser.add_argument("-d", "--debug",
                                        action="store_true", dest="debug",
                                        help="Don't send emails")
+ parser.add_argument("-f", "--fallback",
+                                       action="store_true", dest="fallback",
+                                       help="Fallback mode for unfunctional hardware: Depend on less sensor input")
  args = parser.parse_args()
  if args.debug:
        import libtuer
        libtuer.mailAddress = []
+ if args.fallback:
+       logger.info("Starting in fallback mode")
+ else:
+       # to avoid exceptions or getting None
+       args.fallback = False
  
 +# Not let's go!
 +logger.info("Starting up...")
 +
  # initialize GPIO stuff
  GPIO.setmode(GPIO.BOARD)
  
  # bring 'em all up
  the_actor = actor.Actor()
- the_machine = statemachine.StateMachine(the_actor)
+ the_machine = statemachine.StateMachine(the_actor, args.fallback)
  the_socket = tysock.TySocket(the_machine)
  the_pins = pins.PinsWatcher(the_machine)
  the_waker = waker.Waker(the_machine)