You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
4.0 KiB
200 lines
4.0 KiB
#!/usr/bin/env python3 |
|
|
|
import threading |
|
import queue |
|
|
|
class IllegalEventError(Exception): |
|
pass |
|
|
|
|
|
class AbstractState(object): |
|
def __init__(self, controller): |
|
pass |
|
|
|
def on_gabelschalter_up(self): |
|
raise IllegalEventError() |
|
|
|
def on_gabelschalter_down(self): |
|
raise IllegalEventError() |
|
|
|
def on_incoming_call(self): |
|
raise IllegalEventError() |
|
|
|
def on_call_ended(self): |
|
raise IllegalEventError() |
|
|
|
def on_call_accepted(self): |
|
raise IllegalEventError() |
|
|
|
def on_call_ringing(self): |
|
raise IllegalEventError() |
|
|
|
def on_nummernschalter_input(self, num): |
|
raise IllegalEventError() |
|
|
|
def on_timeout(self): |
|
raise IllegalEventError() |
|
|
|
|
|
|
|
class IdleState(AbstractState): |
|
def on_incoming_call(self): |
|
print('incomfing call') |
|
|
|
def on_gabelschalter_up(self): |
|
print('gabel up') |
|
return DailingState |
|
|
|
def on_gabelschalter_down(self): |
|
pass |
|
|
|
def on_nummernschalter_input(self, x): |
|
pass |
|
|
|
|
|
class SchelltState(AbstractState): |
|
def on_gabelschalter_up(self): |
|
return AcceptingState |
|
|
|
def on_call_ended(self): |
|
return IdleState |
|
|
|
class AcceptingState(AbstractState): |
|
def on_call_accepted(self): |
|
return CallRunningState |
|
|
|
class CallTerminatingState(AbstractState): |
|
def on_call_ended(self): |
|
return IdleState |
|
|
|
def on_call_accepted(self): |
|
return None |
|
|
|
class ForgottenState(AbstractState): |
|
def on_gabelschalter_down(self): |
|
return IdleState |
|
|
|
class BusyBeepingState(AbstractState): |
|
def on_timeout(self): |
|
return ForgottenState |
|
|
|
def on_gabelschalter_down(self): |
|
return IdleState |
|
|
|
class CallRunningState(AbstractState): |
|
def on_gabelschalter_down(self): |
|
return CallTerminatingState |
|
|
|
def on_call_ended(self): |
|
return BusyBeepingState |
|
|
|
class WecktState(AbstractState): |
|
def on_gabelschalter_down(self): |
|
return CallTerminatingState |
|
|
|
def on_call_ended(self): |
|
return BusyBeepingState |
|
|
|
def on_call_accepted(self): |
|
return CallRunningState |
|
|
|
class ConnectingState(AbstractState): |
|
def on_gabelschalter_down(self): |
|
return CallTerminatingState |
|
|
|
def on_call_ringing(self): |
|
return WecktState |
|
|
|
class DailingState(AbstractState): |
|
def on_gabelschalter_down(self): |
|
return IdleState |
|
|
|
def on_nummernschalter_input(self, num): |
|
print('nummernschalter: %d' % (num)) |
|
|
|
def on_timeout(self): |
|
return ConnectingState |
|
|
|
|
|
|
|
class TelefonapparatUserInterface(object): |
|
def __init__(self): |
|
pass |
|
|
|
def add_gabelschalter_callback(self, cb): |
|
pass |
|
|
|
def add_nummernschalter_callback(self, cb): |
|
pass |
|
|
|
def set_wecker(self, enabled): |
|
pass |
|
|
|
def set_schauzeichen(self, enabled): |
|
pass |
|
|
|
|
|
class StateMachineController(object): |
|
def __init__(self): |
|
self.__state = IdleState(self) |
|
|
|
self.__running = True |
|
self.__evqueue = queue.Queue() |
|
self.__evthread = threading.Thread(target=self.__event_dispatcher) |
|
self.__evthread.start() |
|
|
|
def __event_dispatcher(self): |
|
while self.__running: |
|
(evname, evargs, evkwargs) = self.__evqueue.get() |
|
if not evname: |
|
return |
|
|
|
print('!!! event: %s' % (evname)) |
|
handler = getattr(self.__state, 'on_%s' % (evname)) |
|
try: |
|
newstate = handler(*evargs, **evkwargs) |
|
except IllegalEventError: |
|
print('illegal event occured!!!!!!!!!!!!!!!!!!!!') |
|
if not newstate: |
|
continue |
|
|
|
oldstate = self.__state.__class__ |
|
print('%s -> %s' % (oldstate.__name__, newstate.__name__)) |
|
self.__state = newstate(self) |
|
|
|
|
|
def queue_event(self, evname, *evargs, **evkwargs): |
|
if not hasattr(AbstractState, 'on_%s' % (evname)): |
|
raise ValueError('Illegal event name: %s' % (evname)) |
|
self.__evqueue.put((evname, evargs, evkwargs)) |
|
|
|
def stop(self, hard=False): |
|
if hard: |
|
self.__running = False |
|
self.__evqueue.put((None, None, None)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
c = StateMachineController() |
|
|
|
c.queue_event('gabelschalter_up') |
|
c.queue_event('nummernschalter_input', 4) |
|
c.queue_event('nummernschalter_input', 2) |
|
#c.queue_event('gabelschalter_down') |
|
#c.queue_event('call_accepted') |
|
c.queue_event('timeout') |
|
c.queue_event('call_ringing') |
|
#c.queue_event('gabelschalter_down') |
|
c.queue_event('call_accepted') |
|
c.queue_event('call_ended') |
|
c.queue_event('timeout') |
|
c.queue_event('gabelschalter_down') |
|
|
|
c.stop() |
|
|
|
|
|
|
|
|