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 actor import Actor
import os, random, time
import os, random, time, threading
# logger.{debug,info,warning,error,critical}
......@@ -22,6 +22,10 @@ OPEN_REPEAT_NUMBER = 3
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,16 +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:
return StateMachine.StateZu(self.state_machine)
else:
return StateMachine.StateAboutToOpen(self.state_machine)
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):
def handle_cmd_unlock_event(self,callback):
return StateMachine.StateUnlocking(self.state_machine, callback)
......@@ -254,10 +305,10 @@ class StateMachine():
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
......
......@@ -9,17 +9,25 @@ parser = argparse.ArgumentParser(description='Run a door')
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
# 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)
......
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