fetapi/fetapdtest.py

316 lines
7.6 KiB
Python
Raw Normal View History

2015-05-18 19:25:48 +02:00
import time
import threading
import Queue as queue
from phoneinterface import PhoneInterface, PhoneEvent
from tuitest import FeApPinConfiguration, FeApUserInterface
class IllegalEventError(Exception):
pass
class AbstractState(object):
def __init__(self, controller):
self._controller = controller
def on_registration_in_progress(self):
raise IllegalEventError()
def on_registration_successful(self):
raise IllegalEventError()
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_invalid_number(self):
raise IllegalEventError()
2015-05-18 19:25:48 +02:00
def on_nummernschalter_input(self, num):
raise IllegalEventError()
def on_timeout(self):
raise IllegalEventError()
class InitState(AbstractState):
def __init__(self, controller):
super(InitState, self).__init__(controller)
self._controller.get_feap().set_schauzeichen(True)
def on_registration_in_progress(self):
print('registration in progress')
return RegisteringState
class RegisteringState(AbstractState):
def __init__(self, controller):
super(RegisteringState, self).__init__(controller)
def on_registration_successful(self):
print('registration successful')
self._controller.get_feap().set_schauzeichen(False)
return IdleState
class IdleState(AbstractState):
def on_incoming_call(self):
print('incomfing call')
return SchelltState
def on_gabelschalter_up(self):
print('gabel up')
return DialingState
def on_gabelschalter_down(self):
pass
def on_nummernschalter_input(self, x):
pass
class SchelltState(AbstractState):
def __init__(self, controller):
super(SchelltState, self).__init__(controller)
self._controller.get_feap().set_wecker(True)
def __on_leave(self):
self._controller.get_feap().set_wecker(False)
def on_gabelschalter_up(self):
self.__on_leave()
return AcceptingState
def on_call_ended(self):
self.__on_leave()
return IdleState
class AcceptingState(AbstractState):
def __init__(self, controller):
super(AcceptingState, self).__init__(controller)
self._controller.get_phone().accept_call()
def on_call_accepted(self):
return CallRunningState
class CallTerminatingState(AbstractState):
def __init__(self, controller):
super(CallTerminatingState, self).__init__(controller)
self._controller.get_phone().end_call()
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 __init__(self, controller):
super(BusyBeepingState, self).__init__(controller)
self._controller.get_phone().play_busy_tone()
def __on_leave(self):
self._controller.get_phone().stop_playing()
def on_timeout(self):
return ForgottenState
def on_gabelschalter_down(self):
self.__on_leave()
2015-05-18 19:25:48 +02:00
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
def on_call_accepted(self):
return CallRunningState
def on_invalid_number(self):
# TODO: play sound
return BusyBeepingState
2015-05-18 19:25:48 +02:00
class DialingState(AbstractState):
def __init__(self, controller):
super(DialingState, self).__init__(controller)
self._controller.get_phone().play_dial_tone()
self.__dial_tone = True
2015-05-18 19:25:48 +02:00
self.__number = ''
def __on_leave(self):
if self.__dial_tone:
self._controller.get_phone().stop_playing()
2015-05-18 19:25:48 +02:00
self._controller.abort_timeout()
def on_gabelschalter_down(self):
self.__on_leave()
return IdleState
def on_nummernschalter_input(self, num):
print('nummernschalter: %d' % (num))
if self.__dial_tone:
self._controller.get_phone().stop_playing()
2015-05-18 19:25:48 +02:00
self.__number += str(num)
self._controller.abort_timeout()
self._controller.set_timeout(5000)
2015-05-18 19:25:48 +02:00
def on_timeout(self):
self.__on_leave()
print 'Dialing number:', self.__number
self._controller.get_phone().call(self.__number)
return ConnectingState
class StateMachineController(object):
def __init__(self, phone, feap):
self.__state = InitState(self)
self.__phone = phone
self.__feap = feap
self.__timeout = None
2015-05-18 19:25:48 +02:00
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!!!!!!!!!!!!!!!!!!!!', self.__state.__class__.__name__)
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 set_timeout(self, timeout):
2015-05-18 21:50:51 +02:00
self.__timeout = threading.Timer(timeout/1000, self.queue_event, args=['timeout'])
self.__timeout.start()
2015-05-18 19:25:48 +02:00
def abort_timeout(self):
if self.__timeout:
self.__timeout.cancel()
self.__timeout = None
2015-05-18 19:25:48 +02:00
def get_phone(self):
return phone
def get_feap(self):
return feap
def stop(self, hard=False):
if hard:
self.__running = False
self.__evqueue.put((None, None, None))
c = None
def gabelschalter_cb(state):
global c
if state == 1:
c.queue_event('gabelschalter_up')
else:
c.queue_event('gabelschalter_down')
def nummernschalter_cb(digit):
global c
c.queue_event('nummernschalter_input', digit)
def phone_cb(event):
if event == PhoneEvent.RegInProgress:
c.queue_event('registration_in_progress')
elif event == PhoneEvent.RegSuccessfull:
c.queue_event('registration_successful')
elif event == PhoneEvent.CallIncoming:
c.queue_event('incoming_call')
elif event == PhoneEvent.CallAccepted:
c.queue_event('call_accepted')
elif event == PhoneEvent.CallEnded:
c.queue_event('call_ended')
elif event == PhoneEvent.CallRinging:
c.queue_event('call_ringing')
elif event == PhoneEvent.CallInvalidNumber:
c.queue_event('invalid_number')
2015-05-18 19:25:48 +02:00
if __name__ == '__main__':
phone = PhoneInterface(None, '.linphonerc')
pinconf = FeApPinConfiguration()
feap = FeApUserInterface(pinconf)
c = StateMachineController(phone, feap)
feap.add_gabelschalter_callback(gabelschalter_cb)
feap.add_nummernschalter_callback(nummernschalter_cb)
phone.add_event_cb(phone_cb)
phone.start()
try:
while True:
time.sleep(1)
'''
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')
'''
except KeyboardInterrupt:
phone.stop()
feap.set_wecker(False)
c.stop()