1 from libtuer import ThreadFunction, logger
2 from actor import Actor
4 # logger.{debug,info,warning,error,critical}
6 # StateOpening constants
7 OPEN_REPEAT_TIMEOUT = 8
10 def play_sound (what):
11 print ("I would now play the sound %s... IF I HAD SOUNDS!" % what)
13 # StateAboutToOpen constants
14 ABOUTOPEN_NERVLIST = [(5, lambda : play_sound("heydrückdenknopf.mp3")), (10, lambda:play_sound("alterichmeinsernst.mp3"))]
15 # TODO: erzeuge mehr nerv
18 # commands you can send
26 def __init__(self, state_machine):
27 self.state_machine = state_machine
28 self.time_entered = time.time()
30 def handle_pins_event(self):
31 pass # one needn't implement this
32 def handle_buzz_event(self,arg): # this shouldn't be overwritten
33 self.actor.act(Actor.CMD_BUZZ)
34 arg("200 okay: buzz executed")
35 def handle_open_event(self,arg):
37 arg("412 Precondition Failed: The current state (%s) cannot handle the OPEN event" % self.__class__.__name__)
38 def handle_wakeup_event(self):
39 pass # one needn't implement this
41 return self.state_machine.pins
43 return self.state_machine.actor
44 def handle_event(self,ev,arg):
46 self.handle_pins_event()
48 self.handle_buzz_event(arg)
50 self.handle_open_event(arg)
51 elif arg is CMD_WAKEUP:
52 self.handle_wakeup_event()
54 raise Exception("Unknown command number: %d" % ev)
56 class StateStart(State):
57 def __init__(self, sm):
58 State.__init__(self,sm)
59 def handle_pins_event(self):
64 if thepins.door_locked:
70 def __init__(self,sm):
71 State.__init__(self,sm)
72 def handle_pins_event(self):
74 if not pins.door_locked:
75 return StateAboutToOpen(self.state_machine)
76 def handle_open_event(self,callback):
77 return StateOpening(callback,self.state_machine)
79 class StateOpening(State):
80 def __init__(self,callback,sm):
81 State.__init__(self,sm)
82 self.callbacks=[callback]
84 self.actor().act(Actor.CMD_OPEN)
85 def notify(self, did_it_work):
86 s = "200 okay: door open" if did_it_work else ("500 internal server error: Couldn't open door with %d tries à %f seconds" % (OPEN_REPEAT_NUMBER,OPEN_REPEAT_TIMEOUT))
87 for cb in self.callbacks:
90 def handle_pins_event(self):
92 if not pins.door_locked:
94 return StateAboutToOpen(self.state_machine)
95 def handle_open_event(self,callback):
96 self.callbacks.append(callback)
97 def handle_wakeup_event(self):
98 over = time.time() - self.time_entered
99 nexttry = (self.tries+1) * OPEN_REPEAT_TIMEOUT
101 if self.tries < OPEN_REPEAT_NUMBER:
102 self.actor().act(Actor.CMD_OPEN)
105 #TODO: LOG ERROR und EMAIL an Admins
107 return StateZu(self.state_machine)
109 class StateAboutToOpen(State):
110 def __init__(self, sm):
112 def handle_pins_event(self):
115 return StateZu(self.state_machine)
116 elif pins.space_active:
117 return StateAuf(self.state_machine)
119 over = time.time() - self.time_entered
121 logger.debug("AboutToOpen since %f seconds. TODO: nerv the user" % over)
124 class StateAuf(State):
128 class StateClosing(State):
132 class StateAboutToLeave(State):
136 class StateLeaving(State):
140 def __init__(self, actor):
142 self.callback = ThreadFunction(self._callback)
143 self.current_state = None
149 def _callback(self, cmd, arg=None):
151 if cmd == StateMachine.CMD_PINS:
154 newstate = self.current_state.handle_event(cmd,arg) # returns None or an instance of the new state
155 while newstate is not None:
156 logger.info("StateMachine: new state = %s" % newstate.__class__.__name__)
157 self.current_state = newstate
158 newstate = self.current_state.handle_event(StateMachine.CMD_PINS, self.pins)