Commit bdf4adf1 authored by Constantin's avatar Constantin
Browse files

added fallback mode, TODO: test&debug

mode for when some of the sensors don't work, just using one state in the statemachine and using only the space switch sensor
in this mode the red LED blinks, use this mode only if it is really necessary,
use it with parameter --fallback
parent f1430a05
from libtuer import ThreadFunction, logger, fire_and_forget from libtuer import ThreadFunction, logger, fire_and_forget
from actor import Actor from actor import Actor
import os, random, time import os, random, time, threading
# logger.{debug,info,warning,error,critical} # logger.{debug,info,warning,error,critical}
...@@ -22,6 +22,10 @@ OPEN_REPEAT_NUMBER = 3 ...@@ -22,6 +22,10 @@ OPEN_REPEAT_NUMBER = 3
CLOSE_REPEAT_TIMEOUT = 7 CLOSE_REPEAT_TIMEOUT = 7
CLOSE_REPEAT_NUMBER = 3 CLOSE_REPEAT_NUMBER = 3
# StateFallback constants
FALLBACK_BLINK_SPEED = 0.5 # seconds
FALLBACK_LEAVE_DELAY_LOCK = 5 # seconds
# StateAboutToOpen constants # 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")),\ 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")),\ (10, lambda:play_sound("flipswitch")), (10, lambda:play_sound("flipswitch")), (0, lambda:logger.error("Space open but switch not flipped for 30 seconds")),\
...@@ -133,16 +137,63 @@ class StateMachine(): ...@@ -133,16 +137,63 @@ class StateMachine():
return super().handle_pins_event() return super().handle_pins_event()
class StateStart(State): class StateStart(State):
def __init__(self, sm, nervlist = None, fallback=False):
super().__init__(self, sm, nervlist)
self.fallback = fallback
def handle_pins_event(self): def handle_pins_event(self):
pins = self.pins() 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): 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") 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: if pins.door_locked:
return StateMachine.StateZu(self.state_machine) return StateMachine.StateZu(self.state_machine)
else: else:
return StateMachine.StateAboutToOpen(self.state_machine) return StateMachine.StateAboutToOpen(self.state_machine)
return super().handle_pins_event() return 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()
# without return because we want to stay in fallback mode
super().handle_pins_event()
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): class StateZu(AbstractLockedState):
def handle_cmd_unlock_event(self,callback): def handle_cmd_unlock_event(self,callback):
return StateMachine.StateUnlocking(self.state_machine, callback) return StateMachine.StateUnlocking(self.state_machine, callback)
...@@ -254,10 +305,10 @@ class StateMachine(): ...@@ -254,10 +305,10 @@ class StateMachine():
return StateMachine.StateAuf(self.state_machine) return StateMachine.StateAuf(self.state_machine)
return super().handle_pins_event() return super().handle_pins_event()
def __init__(self, actor): def __init__(self, actor, fallback = False):
self.actor = actor self.actor = actor
self.callback = ThreadFunction(self._callback, name="StateMachine") self.callback = ThreadFunction(self._callback, name="StateMachine")
self.current_state = StateMachine.StateStart(self) self.current_state = StateMachine.StateStart(self, fallback)
self.pins = None self.pins = None
self.old_pins = None self.old_pins = None
......
...@@ -9,17 +9,25 @@ parser = argparse.ArgumentParser(description='Run a door') ...@@ -9,17 +9,25 @@ parser = argparse.ArgumentParser(description='Run a door')
parser.add_argument("-d", "--debug", parser.add_argument("-d", "--debug",
action="store_true", dest="debug", action="store_true", dest="debug",
help="Don't send emails") 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() args = parser.parse_args()
if args.debug: if args.debug:
import libtuer import libtuer
libtuer.mailAddress = [] libtuer.mailAddress = []
if args.fallback:
logger.info("Starting in fallback mode")
else:
# to avoid exceptions or getting None
args.fallback = False
# initialize GPIO stuff # initialize GPIO stuff
GPIO.setmode(GPIO.BOARD) GPIO.setmode(GPIO.BOARD)
# bring 'em all up # bring 'em all up
the_actor = actor.Actor() 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_socket = tysock.TySocket(the_machine)
the_pins = pins.PinsWatcher(the_machine) the_pins = pins.PinsWatcher(the_machine)
the_waker = waker.Waker(the_machine) the_waker = waker.Waker(the_machine)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment