Browse Source

Reindented files to consistenlty use 4 spaces and removed trailing whitespaces

master
klonfish 8 years ago
parent
commit
60c899edcc
  1. 279
      apparatinterface.py
  2. 245
      configreader.py
  3. 602
      fetapd.py
  4. 284
      statemachinetest.py

279
apparatinterface.py

@ -5,149 +5,146 @@ import threading
class FeApPinConfiguration(object): class FeApPinConfiguration(object):
def __init__(self, gpio_numbering, pin_nsa, pin_nsi, pin_gabelschalter, def __init__(self, gpio_numbering, pin_nsa, pin_nsi, pin_gabelschalter,
pin_schauzeichen, pin_wecker_enable, pin_wecker_a, pin_schauzeichen, pin_wecker_enable, pin_wecker_a,
pin_wecker_b, invert_gs): pin_wecker_b, invert_gs):
if gpio_numbering == 'BOARD': if gpio_numbering == 'BOARD':
gpio_numbering = gpio.BOARD gpio_numbering = gpio.BOARD
elif gpio_numbering == 'BCM': elif gpio_numbering == 'BCM':
gpio_numbering = gpio.BCM gpio_numbering = gpio.BCM
else: else:
raise ValueError('Illegal gpio numbering: %s' % (gpio_numbering)) raise ValueError('Illegal gpio numbering: %s' % (gpio_numbering))
self.gpio_numbering = gpio_numbering self.gpio_numbering = gpio_numbering
self.pin_nsa = pin_nsa self.pin_nsa = pin_nsa
self.pin_nsi = pin_nsi self.pin_nsi = pin_nsi
self.pin_gabelschalter = pin_gabelschalter self.pin_gabelschalter = pin_gabelschalter
self.pin_schauzeichen = pin_schauzeichen self.pin_schauzeichen = pin_schauzeichen
self.pin_wecker_enable = pin_wecker_enable self.pin_wecker_enable = pin_wecker_enable
self.pin_wecker_a = pin_wecker_a self.pin_wecker_a = pin_wecker_a
self.pin_wecker_b = pin_wecker_b self.pin_wecker_b = pin_wecker_b
self.invert_gs = invert_gs self.invert_gs = invert_gs
class FeApUserInterface(object): class FeApUserInterface(object):
def __init__(self, pinconfig): def __init__(self, pinconfig):
self.__pinconfig = pinconfig self.__pinconfig = pinconfig
gpio.setmode(self.__pinconfig.gpio_numbering) gpio.setmode(self.__pinconfig.gpio_numbering)
gpio.setup(self.__pinconfig.pin_nsa, gpio.IN, gpio.PUD_UP) gpio.setup(self.__pinconfig.pin_nsa, gpio.IN, gpio.PUD_UP)
gpio.setup(self.__pinconfig.pin_nsi, gpio.IN, gpio.PUD_UP) gpio.setup(self.__pinconfig.pin_nsi, gpio.IN, gpio.PUD_UP)
gpio.setup(self.__pinconfig.pin_gabelschalter, gpio.IN, gpio.PUD_UP) gpio.setup(self.__pinconfig.pin_gabelschalter, gpio.IN, gpio.PUD_UP)
gpio.setup(self.__pinconfig.pin_schauzeichen, gpio.OUT) gpio.setup(self.__pinconfig.pin_schauzeichen, gpio.OUT)
gpio.setup(self.__pinconfig.pin_wecker_enable, gpio.OUT) gpio.setup(self.__pinconfig.pin_wecker_enable, gpio.OUT)
gpio.setup(self.__pinconfig.pin_wecker_a, gpio.OUT) gpio.setup(self.__pinconfig.pin_wecker_a, gpio.OUT)
gpio.setup(self.__pinconfig.pin_wecker_b, gpio.OUT) gpio.setup(self.__pinconfig.pin_wecker_b, gpio.OUT)
gpio.add_event_detect(self.__pinconfig.pin_nsa, gpio.BOTH, gpio.add_event_detect(self.__pinconfig.pin_nsa, gpio.BOTH,
self.__on_nsa_change, 20) self.__on_nsa_change, 20)
gpio.add_event_detect(self.__pinconfig.pin_nsi, gpio.FALLING, gpio.add_event_detect(self.__pinconfig.pin_nsi, gpio.FALLING,
self.__on_nsi_falling, 20) self.__on_nsi_falling, 20)
gpio.add_event_detect(self.__pinconfig.pin_gabelschalter, gpio.BOTH, gpio.add_event_detect(self.__pinconfig.pin_gabelschalter, gpio.BOTH,
self.__on_gabelschalter_change, 20) self.__on_gabelschalter_change, 20)
#self.__nsa_up_time = 0 #self.__nsa_up_time = 0
self.__nsi_cnt = 0 self.__nsi_cnt = 0
self.__weckt = False self.__weckt = False
self.__nummernschalter_active_callbacks = [] self.__nummernschalter_active_callbacks = []
self.__nummernschalter_done_callbacks = [] self.__nummernschalter_done_callbacks = []
self.__gabelschalter_callbacks = [] self.__gabelschalter_callbacks = []
def __on_nsa_change(self, pin): def __on_nsa_change(self, pin):
nsastate = gpio.input(self.__pinconfig.pin_nsa) nsastate = gpio.input(self.__pinconfig.pin_nsa)
if nsastate == 0: if nsastate == 0:
#self.__nsa_up_time = time.time() #self.__nsa_up_time = time.time()
self.__nsi_cnt = 0 self.__nsi_cnt = 0
for cb in self.__nummernschalter_active_callbacks: for cb in self.__nummernschalter_active_callbacks:
cb() cb()
else: else:
for cb in self.__nummernschalter_done_callbacks: for cb in self.__nummernschalter_done_callbacks:
cb(self.__nsi_cnt % 10) cb(self.__nsi_cnt % 10)
def __on_nsi_falling(self, pin): def __on_nsi_falling(self, pin):
#print 'nsi' #print 'nsi'
self.__nsi_cnt += 1 self.__nsi_cnt += 1
def __on_gabelschalter_change(self, pin): def __on_gabelschalter_change(self, pin):
gbstate = gpio.input(self.__pinconfig.pin_gabelschalter) gbstate = gpio.input(self.__pinconfig.pin_gabelschalter)
if self.__pinconfig.invert_gs: if self.__pinconfig.invert_gs:
gbstate = 1 - gbstate gbstate = 1 - gbstate
print 'gabelschalter:', gbstate print 'gabelschalter:', gbstate
for cb in self.__gabelschalter_callbacks: for cb in self.__gabelschalter_callbacks:
cb(gbstate) cb(gbstate)
def __wecker_thread(self): def __wecker_thread(self):
while self.__weckt: while self.__weckt:
c = 0 c = 0
gpio.output(self.__pinconfig.pin_wecker_enable, 1) gpio.output(self.__pinconfig.pin_wecker_enable, 1)
while c < 1000: while c < 1000:
gpio.output(self.__pinconfig.pin_wecker_a, 1) gpio.output(self.__pinconfig.pin_wecker_a, 1)
gpio.output(self.__pinconfig.pin_wecker_b, 0) gpio.output(self.__pinconfig.pin_wecker_b, 0)
time.sleep(0.02) time.sleep(0.02)
gpio.output(self.__pinconfig.pin_wecker_a, 0) gpio.output(self.__pinconfig.pin_wecker_a, 0)
gpio.output(self.__pinconfig.pin_wecker_b, 1) gpio.output(self.__pinconfig.pin_wecker_b, 1)
time.sleep(0.02) time.sleep(0.02)
c += 40 c += 40
print 'ring' print 'ring'
gpio.output(self.__pinconfig.pin_wecker_enable, 0) gpio.output(self.__pinconfig.pin_wecker_enable, 0)
print '' print ''
time.sleep(4) time.sleep(4)
def add_gabelschalter_callback(self, cb): def add_gabelschalter_callback(self, cb):
self.__gabelschalter_callbacks.append(cb) self.__gabelschalter_callbacks.append(cb)
def add_nummernschalter_active_callback(self, cb): def add_nummernschalter_active_callback(self, cb):
self.__nummernschalter_active_callbacks.append(cb) self.__nummernschalter_active_callbacks.append(cb)
def add_nummernschalter_done_callback(self, cb): def add_nummernschalter_done_callback(self, cb):
self.__nummernschalter_done_callbacks.append(cb) self.__nummernschalter_done_callbacks.append(cb)
def set_wecker(self, enabled): def set_wecker(self, enabled):
if enabled and not self.__weckt: if enabled and not self.__weckt:
self.__weckt = True self.__weckt = True
t = threading.Thread(target=self.__wecker_thread) t = threading.Thread(target=self.__wecker_thread)
t.start() t.start()
elif not enabled: elif not enabled:
self.__weckt = False self.__weckt = False
def set_schauzeichen(self, enabled): def set_schauzeichen(self, enabled):
gpio.output(self.__pinconfig.pin_schauzeichen, 1 if enabled else 0) gpio.output(self.__pinconfig.pin_schauzeichen, 1 if enabled else 0)
if __name__ == '__main__': if __name__ == '__main__':
gpio.setmode(gpio.BOARD) gpio.setmode(gpio.BOARD)
pinconfig = FeApPinConfiguration() pinconfig = FeApPinConfiguration()
t = FeApUserInterface(pinconfig) t = FeApUserInterface(pinconfig)
def dailed(num): def dailed(num):
print num print num
t.add_nummernschalter_callback(dailed) t.add_nummernschalter_callback(dailed)
t.set_schauzeichen(True) t.set_schauzeichen(True)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(False) t.set_schauzeichen(False)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(True) t.set_schauzeichen(True)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(False) t.set_schauzeichen(False)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(True) t.set_schauzeichen(True)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(False) t.set_schauzeichen(False)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(True) t.set_schauzeichen(True)
time.sleep(0.5) time.sleep(0.5)
t.set_schauzeichen(False) t.set_schauzeichen(False)
time.sleep(0.5) time.sleep(0.5)
t.set_wecker(True) t.set_wecker(True)
time.sleep(20) time.sleep(20)
t.set_wecker(False) t.set_wecker(False)
while True: while True:
time.sleep(1) time.sleep(1)

245
configreader.py

@ -6,129 +6,124 @@ import phoneinterface
import fetapd import fetapd
class ConfigurationReader(object): class ConfigurationReader(object):
DEFAULTS = { DEFAULTS = {
'gpio_numbering': 'BOARD', 'gpio_numbering': 'BOARD',
'pin_nsa': '11', 'pin_nsa': '11',
'pin_nsi': '13', 'pin_nsi': '13',
'pin_gabelschalter': '15', 'pin_gabelschalter': '15',
'pin_schauzeichen': '12', 'pin_schauzeichen': '12',
'pin_wecker_enable': '16', 'pin_wecker_enable': '16',
'pin_wecker_a': '18', 'pin_wecker_a': '18',
'pin_wecker_b': '19', 'pin_wecker_b': '19',
'invert_gs' : 'false', 'invert_gs' : 'false',
'default_proxy': '' 'default_proxy': ''
} }
def __init__(self): def __init__(self):
self.__cp = ConfigParser.ConfigParser(defaults=ConfigurationReader.DEFAULTS) self.__cp = ConfigParser.ConfigParser(defaults=ConfigurationReader.DEFAULTS)
self.__pinconfig = None self.__pinconfig = None
self.__dialconfig = None self.__dialconfig = None
self.__proxyconfigs = None self.__proxyconfigs = None
self.__phoneconfig = None self.__phoneconfig = None
def __get_global_val(self, option): def __get_global_val(self, option):
return self.__cp.get('fetapd', option) return self.__cp.get('fetapd', option)
def __get_global_val_int(self, option): def __get_global_val_int(self, option):
return int(self.__cp.get('fetapd', option)) return int(self.__cp.get('fetapd', option))
def __get_global_val_bool(self, option): def __get_global_val_bool(self, option):
return self.__cp.get('fetapd', option).lower() in ['true', 'yes', '1'] return self.__cp.get('fetapd', option).lower() in ['true', 'yes', '1']
def __get_proxy_val(self, proxyname, option): def __get_proxy_val(self, proxyname, option):
return self.__cp.get('proxy_'+proxyname, option) return self.__cp.get('proxy_'+proxyname, option)
def __get_proxy_val_int(self, proxyname, option): def __get_proxy_val_int(self, proxyname, option):
return self.__cp.getint('proxy_'+proxyname, option) return self.__cp.getint('proxy_'+proxyname, option)
def __read_shortcuts(self): def __read_shortcuts(self):
fname = self.__get_global_val('shortcuts_file') fname = self.__get_global_val('shortcuts_file')
shortcuts = {} shortcuts = {}
with open(fname, 'r') as csvfile: with open(fname, 'r') as csvfile:
for row in csv.DictReader(csvfile): for row in csv.DictReader(csvfile):
print 'row', row print 'row', row
shortcuts[row['shortcut']] = row['number'] shortcuts[row['shortcut']] = row['number']
print 'shortcuts:', shortcuts print 'shortcuts:', shortcuts
return shortcuts return shortcuts
def __read_blacklist(self): def __read_blacklist(self):
fname = self.__get_global_val('blacklist_file') fname = self.__get_global_val('blacklist_file')
blacklist = [] blacklist = []
with open(fname, 'r') as csvfile: with open(fname, 'r') as csvfile:
for row in csv.DictReader(csvfile): for row in csv.DictReader(csvfile):
blacklist.append(row['number']) blacklist.append(row['number'])
return blacklist return blacklist
def read(self, f): def read(self, f):
self.__cp.read(f) self.__cp.read(f)
print 'pin_nsa:', self.__get_global_val_int('pin_nsa'), print 'pin_nsa:', self.__get_global_val_int('pin_nsa'),
self.__pinconfig = apparatinterface.FeApPinConfiguration( self.__pinconfig = apparatinterface.FeApPinConfiguration(
gpio_numbering = self.__get_global_val('gpio_numbering'), gpio_numbering = self.__get_global_val('gpio_numbering'),
pin_nsa = self.__get_global_val_int('pin_nsa'), pin_nsa = self.__get_global_val_int('pin_nsa'),
pin_nsi = self.__get_global_val_int('pin_nsi'), pin_nsi = self.__get_global_val_int('pin_nsi'),
pin_gabelschalter = self.__get_global_val_int('pin_gabelschalter'), pin_gabelschalter = self.__get_global_val_int('pin_gabelschalter'),
pin_schauzeichen = self.__get_global_val_int('pin_schauzeichen'), pin_schauzeichen = self.__get_global_val_int('pin_schauzeichen'),
pin_wecker_enable = self.__get_global_val_int('pin_wecker_enable'), pin_wecker_enable = self.__get_global_val_int('pin_wecker_enable'),
pin_wecker_a = self.__get_global_val_int('pin_wecker_a'), pin_wecker_a = self.__get_global_val_int('pin_wecker_a'),
pin_wecker_b = self.__get_global_val_int('pin_wecker_b'), pin_wecker_b = self.__get_global_val_int('pin_wecker_b'),
invert_gs = self.__get_global_val_bool('invert_gs'), invert_gs = self.__get_global_val_bool('invert_gs'),
) )
self.__dialconfig = fetapd.DialConfiguration( self.__dialconfig = fetapd.DialConfiguration(
self.__get_global_val_int('dial_timeout'), self.__get_global_val_int('dial_timeout'),
self.__read_shortcuts(), self.__read_shortcuts(),
self.__read_blacklist(), self.__read_blacklist(),
) )
proxyconfigs = [] proxyconfigs = []
for secname in self.__cp.sections(): for secname in self.__cp.sections():
if secname.startswith('proxy_'): if secname.startswith('proxy_'):
proxyname = secname[6:] proxyname = secname[6:]
proxyconfig = phoneinterface.PhoneProxyConfiguration( proxyconfig = phoneinterface.PhoneProxyConfiguration(
name = proxyname, name = proxyname,
proxy = self.__get_proxy_val(proxyname, 'proxy'), proxy = self.__get_proxy_val(proxyname, 'proxy'),
identity = self.__get_proxy_val(proxyname, 'identity'), identity = self.__get_proxy_val(proxyname, 'identity'),
username = self.__get_proxy_val(proxyname, 'username'), username = self.__get_proxy_val(proxyname, 'username'),
password = self.__get_proxy_val(proxyname, 'password'), password = self.__get_proxy_val(proxyname, 'password'),
realm = self.__get_proxy_val(proxyname, 'realm'), realm = self.__get_proxy_val(proxyname, 'realm'),
prefix = self.__get_proxy_val(proxyname, 'prefix') prefix = self.__get_proxy_val(proxyname, 'prefix')
) )
proxyconfigs.append(proxyconfig) proxyconfigs.append(proxyconfig)
self.__phoneconfig = phoneinterface.PhoneConfiguration( self.__phoneconfig = phoneinterface.PhoneConfiguration(
sound_device = self.__get_global_val('sound_device'), sound_device = self.__get_global_val('sound_device'),
incoming_timeout = self.__get_global_val_int('incoming_timeout'), incoming_timeout = self.__get_global_val_int('incoming_timeout'),
linphone_config = self.__get_global_val('linphone_config'), linphone_config = self.__get_global_val('linphone_config'),
default_proxy = self.__get_global_val('default_proxy'), default_proxy = self.__get_global_val('default_proxy'),
stun_server = self.__get_global_val('stun_server'), stun_server = self.__get_global_val('stun_server'),
proxies = proxyconfigs proxies = proxyconfigs
) )
@property @property
def pinconfig(self): def pinconfig(self):
return self.__pinconfig return self.__pinconfig
@property @property
def dialconfig(self): def dialconfig(self):
return self.__dialconfig return self.__dialconfig
@property @property
def phoneconfig(self): def phoneconfig(self):
return self.__phoneconfig return self.__phoneconfig

602
fetapd.py

@ -7,13 +7,13 @@ import configreader
class DialConfiguration(object): class DialConfiguration(object):
def __init__(self, dial_timeout, shortcuts, blacklist): def __init__(self, dial_timeout, shortcuts, blacklist):
self.dial_timeout = dial_timeout self.dial_timeout = dial_timeout
self.shortcuts = shortcuts self.shortcuts = shortcuts
self.blacklist = blacklist self.blacklist = blacklist
class IllegalEventError(Exception): class IllegalEventError(Exception):
pass pass
""" """
@ -21,47 +21,47 @@ An abstract state, needed to define all possible events.
""" """
class AbstractState(object): class AbstractState(object):
def on_registration_in_progress(self): def on_registration_in_progress(self):
raise IllegalEventError() raise IllegalEventError()
def on_registration_successful(self): def on_registration_successful(self):
raise IllegalEventError() raise IllegalEventError()
def on_registration_lost(self): def on_registration_lost(self):
raise IllegalEventError() raise IllegalEventError()
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
raise IllegalEventError() raise IllegalEventError()
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
raise IllegalEventError() raise IllegalEventError()
def on_incoming_call(self): def on_incoming_call(self):
raise IllegalEventError() raise IllegalEventError()
def on_call_ended(self): def on_call_ended(self):
raise IllegalEventError() raise IllegalEventError()
def on_call_accepted(self): def on_call_accepted(self):
raise IllegalEventError() raise IllegalEventError()
def on_call_ringing(self): def on_call_ringing(self):
raise IllegalEventError() raise IllegalEventError()
def on_invalid_number(self): def on_invalid_number(self):
raise IllegalEventError() raise IllegalEventError()
def on_nummernschalter_active(self): def on_nummernschalter_active(self):
raise IllegalEventError() raise IllegalEventError()
def on_nummernschalter_input(self, num): def on_nummernschalter_input(self, num):
raise IllegalEventError() raise IllegalEventError()
def on_timeout(self): def on_timeout(self):
raise IllegalEventError() raise IllegalEventError()
def leave(self): def leave(self):
return None return None
""" """
@ -70,338 +70,338 @@ behaviour for some events (overriden if necessary).
""" """
class BaseState(AbstractState): class BaseState(AbstractState):
def __init__(self, controller): def __init__(self, controller):
self._controller = controller self._controller = controller
def on_registration_lost(self): def on_registration_lost(self):
return InitState return InitState
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
return None return None
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return None return None
def on_incoming_call(self): def on_incoming_call(self):
self._controller.phone.decline_call() self._controller.phone.decline_call()
def on_call_ended(self): def on_call_ended(self):
# When an incoming call is declined, a call_ended event occurs, which # When an incoming call is declined, a call_ended event occurs, which
# needs to be ignored, here. # needs to be ignored, here.
return None return None
def on_nummernschalter_active(self): def on_nummernschalter_active(self):
return None return None
def on_nummernschalter_input(self, num): def on_nummernschalter_input(self, num):
return None return None
class InitState(BaseState): class InitState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(InitState, self).__init__(controller) super(InitState, self).__init__(controller)
self._controller.feap.set_schauzeichen(True) self._controller.feap.set_schauzeichen(True)
def on_registration_in_progress(self): def on_registration_in_progress(self):
print('registration in progress') print('registration in progress')
return RegisteringState return RegisteringState
class RegisteringState(BaseState): class RegisteringState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(RegisteringState, self).__init__(controller) super(RegisteringState, self).__init__(controller)
def on_registration_successful(self): def on_registration_successful(self):
print('registration successful') print('registration successful')
self._controller.feap.set_schauzeichen(False) self._controller.feap.set_schauzeichen(False)
return IdleState return IdleState
class IdleState(BaseState): class IdleState(BaseState):
def on_incoming_call(self): def on_incoming_call(self):
print('incomfing call') print('incomfing call')
caller = self._controller.phone.get_remote_number() caller = self._controller.phone.get_remote_number()
print('From: %s' % caller) print('From: %s' % caller)
if caller in self._controller.dialconfig.blacklist: if caller in self._controller.dialconfig.blacklist:
print('Caller on blacklist - declining') print('Caller on blacklist - declining')
self._controller.phone.decline_call() self._controller.phone.decline_call()
return CallTerminatingState return CallTerminatingState
else: else:
return SchelltState return SchelltState
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
print('gabel up') print('gabel up')
return DialingState return DialingState
class SchelltState(BaseState): class SchelltState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(SchelltState, self).__init__(controller) super(SchelltState, self).__init__(controller)
self._controller.feap.set_wecker(True) self._controller.feap.set_wecker(True)
def leave(self): def leave(self):
self._controller.feap.set_wecker(False) self._controller.feap.set_wecker(False)
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
return AcceptingState return AcceptingState
def on_call_ended(self): def on_call_ended(self):
return IdleState return IdleState
class AcceptingState(BaseState): class AcceptingState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(AcceptingState, self).__init__(controller) super(AcceptingState, self).__init__(controller)
self._controller.phone.accept_call() self._controller.phone.accept_call()
def on_call_accepted(self): def on_call_accepted(self):
return CallRunningState return CallRunningState
class CallTerminatingState(BaseState): class CallTerminatingState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(CallTerminatingState, self).__init__(controller) super(CallTerminatingState, self).__init__(controller)
self._controller.phone.end_call() self._controller.phone.end_call()
def on_call_ended(self): def on_call_ended(self):
return IdleState return IdleState
def on_call_accepted(self): def on_call_accepted(self):
return None return None
class ForgottenState(BaseState): class ForgottenState(BaseState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return IdleState return IdleState
class BusyBeepingState(BaseState): class BusyBeepingState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(BusyBeepingState, self).__init__(controller) super(BusyBeepingState, self).__init__(controller)
self._controller.phone.play_busy_tone() self._controller.phone.play_busy_tone()
def leave(self): def leave(self):
self._controller.phone.stop_playing() self._controller.phone.stop_playing()
def on_timeout(self): def on_timeout(self):
return ForgottenState return ForgottenState
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return IdleState return IdleState
class CallRunningState(BaseState): class CallRunningState(BaseState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return CallTerminatingState return CallTerminatingState
def on_call_ended(self): def on_call_ended(self):
return BusyBeepingState return BusyBeepingState
class WecktState(BaseState): class WecktState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(WecktState, self).__init__(controller) super(WecktState, self).__init__(controller)
self._controller.phone.play_ringback_tone() self._controller.phone.play_ringback_tone()
def leave(self): def leave(self):
self._controller.phone.stop_playing() self._controller.phone.stop_playing()
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return CallTerminatingState return CallTerminatingState
def on_call_ended(self): def on_call_ended(self):
return BusyBeepingState return BusyBeepingState
def on_call_accepted(self): def on_call_accepted(self):
return CallRunningState return CallRunningState
class ConnectingState(BaseState): class ConnectingState(BaseState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return CallTerminatingState return CallTerminatingState
def on_call_ringing(self): def on_call_ringing(self):
return WecktState return WecktState
def on_call_accepted(self): def on_call_accepted(self):
return CallRunningState return CallRunningState
def on_invalid_number(self): def on_invalid_number(self):
# TODO: play sound # TODO: play sound
return BusyBeepingState return BusyBeepingState
def on_call_ended(self): def on_call_ended(self):
return BusyBeepingState return BusyBeepingState
class DialingState(BaseState): class DialingState(BaseState):
def __init__(self, controller): def __init__(self, controller):
super(DialingState, self).__init__(controller) super(DialingState, self).__init__(controller)
self._controller.phone.play_dial_tone() self._controller.phone.play_dial_tone()
self.__dial_tone = True self.__dial_tone = True
self.__number = '' self.__number = ''
def leave(self): def leave(self):
if self.__dial_tone: if self.__dial_tone:
self._controller.phone.stop_playing() self._controller.phone.stop_playing()
self._controller.abort_timeout() self._controller.abort_timeout()
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return IdleState return IdleState
def on_nummernschalter_active(self): def on_nummernschalter_active(self):
self._controller.abort_timeout() self._controller.abort_timeout()
if self.__dial_tone: if self.__dial_tone:
self._controller.phone.stop_playing() self._controller.phone.stop_playing()
def on_nummernschalter_input(self, num): def on_nummernschalter_input(self, num):
print('nummernschalter: %d' % (num)) print('nummernschalter: %d' % (num))
if self.__dial_tone: if self.__dial_tone:
self._controller.phone.stop_playing() self._controller.phone.stop_playing()
self.__number += str(num) self.__number += str(num)
self._controller.abort_timeout() self._controller.abort_timeout()
self._controller.set_timeout(self._controller.dialconfig.dial_timeout * 1000) self._controller.set_timeout(self._controller.dialconfig.dial_timeout * 1000)
self._controller.phone.read_text(str(num)) self._controller.phone.read_text(str(num))
def on_timeout(self): def on_timeout(self):
number = self.__number number = self.__number
print 'Dialing number:', number print 'Dialing number:', number
if number in self._controller.dialconfig.shortcuts: if number in self._controller.dialconfig.shortcuts:
number = self._controller.dialconfig.shortcuts[number] number = self._controller.dialconfig.shortcuts[number]
print 'shortcut resolved:', number print 'shortcut resolved:', number
self._controller.phone.call(number) self._controller.phone.call(number)
return ConnectingState return ConnectingState
class StateMachineController(object): class StateMachineController(object):
def __init__(self, phone, feap, dialconfig): def __init__(self, phone, feap, dialconfig):
self.__phone = phone self.__phone = phone
self.__feap = feap self.__feap = feap
self.__dialconfig = dialconfig self.__dialconfig = dialconfig
self.__state = InitState(self) self.__state = InitState(self)
self.__timeout = None self.__timeout = None
self.__running = True self.__running = True
self.__evqueue = queue.Queue() self.__evqueue = queue.Queue()
self.__evthread = threading.Thread(target=self.__event_dispatcher) self.__evthread = threading.Thread(target=self.__event_dispatcher)
self.__evthread.start() self.__evthread.start()
def __event_dispatcher(self): def __event_dispatcher(self):
while self.__running: while self.__running:
(evname, evargs, evkwargs) = self.__evqueue.get() (evname, evargs, evkwargs) = self.__evqueue.get()
if not evname: if not evname:
return return
print('!!! event: %s' % (evname)) print('!!! event: %s' % (evname))
handler = getattr(self.__state, 'on_%s' % (evname)) handler = getattr(self.__state, 'on_%s' % (evname))
try: try:
newstate = handler(*evargs, **evkwargs) newstate = handler(*evargs, **evkwargs)
except IllegalEventError: except IllegalEventError:
print('illegal event occured!!!!!!!!!!!!!!!!!!!!', self.__state.__class__.__name__) print('illegal event occured!!!!!!!!!!!!!!!!!!!!', self.__state.__class__.__name__)
if not newstate: if not newstate:
continue continue
self.__state.leave() self.__state.leave()
self.abort_timeout() self.abort_timeout()
oldstate = self.__state.__class__ oldstate = self.__state.__class__
print('%s -> %s' % (oldstate.__name__, newstate.__name__)) print('%s -> %s' % (oldstate.__name__, newstate.__name__))
self.__state = newstate(self) self.__state = newstate(self)
def queue_event(self, evname, *evargs, **evkwargs): def queue_event(self, evname, *evargs, **evkwargs):
if not hasattr(AbstractState, 'on_%s' % (evname)): if not hasattr(AbstractState, 'on_%s' % (evname)):
raise ValueError('Illegal event name: %s' % (evname)) raise ValueError('Illegal event name: %s' % (evname))
self.__evqueue.put((evname, evargs, evkwargs)) self.__evqueue.put((evname, evargs, evkwargs))
def set_timeout(self, timeout): def set_timeout(self, timeout):
self.__timeout = threading.Timer(timeout/1000, self.queue_event, args=['timeout']) self.__timeout = threading.Timer(timeout/1000, self.queue_event, args=['timeout'])
self.__timeout.start() self.__timeout.start()
def abort_timeout(self): def abort_timeout(self):
if self.__timeout: if self.__timeout:
self.__timeout.cancel() self.__timeout.cancel()
self.__timeout = None self.__timeout = None
@property @property
def phone(self): def phone(self):
return self.__phone return self.__phone
@property @property
def feap(self): def feap(self):
return self.__feap return self.__feap
@property @property
def dialconfig(self): def dialconfig(self):
return self.__dialconfig return self.__dialconfig
def stop(self, hard=False): def stop(self, hard=False):
if hard: if hard:
self.__running = False self.__running = False
self.__evqueue.put((None, None, None)) self.__evqueue.put((None, None, None))
c = None c = None
def gabelschalter_cb(state): def gabelschalter_cb(state):
global c global c
if state == 1: if state == 1:
c.queue_event('gabelschalter_up') c.queue_event('gabelschalter_up')
else: else:
c.queue_event('gabelschalter_down') c.queue_event('gabelschalter_down')
def nummernschalter_active_cb(): def nummernschalter_active_cb():
global c global c
c.queue_event('nummernschalter_active') c.queue_event('nummernschalter_active')
def nummernschalter_done_cb(digit): def nummernschalter_done_cb(digit):
global c global c
c.queue_event('nummernschalter_input', digit) c.queue_event('nummernschalter_input', digit)
def phone_cb(event): def phone_cb(event):
if event == PhoneEvent.RegInProgress: if event == PhoneEvent.RegInProgress:
c.queue_event('registration_in_progress') c.queue_event('registration_in_progress')
elif event == PhoneEvent.RegSuccessfull: elif event == PhoneEvent.RegSuccessfull:
c.queue_event('registration_successful') c.queue_event('registration_successful')
elif event == PhoneEvent.RegLost: elif event == PhoneEvent.RegLost:
c.queue_event('registration_lost') c.queue_event('registration_lost')
elif event == PhoneEvent.CallIncoming: elif event == PhoneEvent.CallIncoming:
c.queue_event('incoming_call') c.queue_event('incoming_call')
elif event == PhoneEvent.CallAccepted: elif event == PhoneEvent.CallAccepted:
c.queue_event('call_accepted') c.queue_event('call_accepted')
elif event == PhoneEvent.CallEnded: elif event == PhoneEvent.CallEnded:
c.queue_event('call_ended') c.queue_event('call_ended')
elif event == PhoneEvent.CallRinging: elif event == PhoneEvent.CallRinging:
c.queue_event('call_ringing') c.queue_event('call_ringing')
elif event == PhoneEvent.CallBusy: elif event == PhoneEvent.CallBusy:
c.queue_event('call_ended') c.queue_event('call_ended')
elif event == PhoneEvent.CallInvalidNumber: elif event == PhoneEvent.CallInvalidNumber:
c.queue_event('invalid_number') c.queue_event('invalid_number')
if __name__ == '__main__': if __name__ == '__main__':
cfg = configreader.ConfigurationReader() cfg = configreader.ConfigurationReader()
cfg.read('fetap.ini') cfg.read('fetap.ini')
phone = PhoneInterface(cfg.phoneconfig) phone = PhoneInterface(cfg.phoneconfig)
feap = FeApUserInterface(cfg.pinconfig) feap = FeApUserInterface(cfg.pinconfig)
c = StateMachineController(phone, feap, cfg.dialconfig) c = StateMachineController(phone, feap, cfg.dialconfig)
feap.add_gabelschalter_callback(gabelschalter_cb) feap.add_gabelschalter_callback(gabelschalter_cb)
feap.add_nummernschalter_active_callback(nummernschalter_active_cb) feap.add_nummernschalter_active_callback(nummernschalter_active_cb)
feap.add_nummernschalter_done_callback(nummernschalter_done_cb) feap.add_nummernschalter_done_callback(nummernschalter_done_cb)
phone.add_event_cb(phone_cb) phone.add_event_cb(phone_cb)
phone.start() phone.start()
try: try:
while True: while True:
time.sleep(1) time.sleep(1)
''' '''
c.queue_event('gabelschalter_up') c.queue_event('gabelschalter_up')
c.queue_event('nummernschalter_input', 4) c.queue_event('nummernschalter_input', 4)
c.queue_event('nummernschalter_input', 2) c.queue_event('nummernschalter_input', 2)
#c.queue_event('gabelschalter_down') #c.queue_event('gabelschalter_down')
#c.queue_event('call_accepted') #c.queue_event('call_accepted')
c.queue_event('timeout') c.queue_event('timeout')
c.queue_event('call_ringing') c.queue_event('call_ringing')
#c.queue_event('gabelschalter_down') #c.queue_event('gabelschalter_down')
c.queue_event('call_accepted') c.queue_event('call_accepted')
c.queue_event('call_ended') c.queue_event('call_ended')
c.queue_event('timeout') c.queue_event('timeout')
c.queue_event('gabelschalter_down') c.queue_event('gabelschalter_down')
''' '''
except KeyboardInterrupt: except KeyboardInterrupt:
phone.stop() phone.stop()
feap.set_wecker(False) feap.set_wecker(False)
c.stop() c.stop()

284
statemachinetest.py

@ -2,213 +2,205 @@ import threading
import Queue as queue import Queue as queue
class IllegalEventError(Exception): class IllegalEventError(Exception):
pass pass
class AbstractState(object): class AbstractState(object):
def __init__(self, controller): def __init__(self, controller):
pass pass
def on_registration_in_progress(self): def on_registration_in_progress(self):
raise IllegalEventError() raise IllegalEventError()
def on_registration_successful(self): def on_registration_successful(self):
raise IllegalEventError() raise IllegalEventError()
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
raise IllegalEventError() raise IllegalEventError()
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
raise IllegalEventError() raise IllegalEventError()
def on_incoming_call(self): def on_incoming_call(self):
raise IllegalEventError() raise IllegalEventError()
def on_call_ended(self): def on_call_ended(self):
raise IllegalEventError() raise IllegalEventError()
def on_call_accepted(self): def on_call_accepted(self):
raise IllegalEventError() raise IllegalEventError()
def on_call_ringing(self): def on_call_ringing(self):
raise IllegalEventError() raise IllegalEventError()
def on_nummernschalter_input(self, num): def on_nummernschalter_input(self, num):
raise IllegalEventError() raise IllegalEventError()
def on_timeout(self): def on_timeout(self):
raise IllegalEventError() raise IllegalEventError()
class InitState(AbstractState): class InitState(AbstractState):
def on_registration_in_progress(self): def on_registration_in_progress(self):
print('registration in progress') print('registration in progress')
return RegisteringState return RegisteringState
class RegisteringState(AbstractState): class RegisteringState(AbstractState):
def on_registration_successful(self): def on_registration_successful(self):
print('registration successfull') print('registration successfull')
return IdleState return IdleState
class IdleState(AbstractState): class IdleState(AbstractState):
def on_incoming_call(self): def on_incoming_call(self):
print('incomfing call') print('incomfing call')
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
print('gabel up') print('gabel up')
return DialingState return DialingState
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
pass pass
def on_nummernschalter_input(self, x): def on_nummernschalter_input(self, x):
pass pass
class SchelltState(AbstractState): class SchelltState(AbstractState):
def on_gabelschalter_up(self): def on_gabelschalter_up(self):
return AcceptingState return AcceptingState
def on_call_ended(self): def on_call_ended(self):
return IdleState return IdleState
class AcceptingState(AbstractState): class AcceptingState(AbstractState):
def on_call_accepted(self): def on_call_accepted(self):
return CallRunningState return CallRunningState
class CallTerminatingState(AbstractState): class CallTerminatingState(AbstractState):
def on_call_ended(self): def on_call_ended(self):
return IdleState return IdleState
def on_call_accepted(self): def on_call_accepted(self):
return None return None
class ForgottenState(AbstractState): class ForgottenState(AbstractState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return IdleState return IdleState
class BusyBeepingState(AbstractState): class BusyBeepingState(AbstractState):
def on_timeout(self): def on_timeout(self):
return ForgottenState return ForgottenState
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return IdleState return IdleState
class CallRunningState(AbstractState): class CallRunningState(AbstractState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return CallTerminatingState return CallTerminatingState
def on_call_ended(self): def on_call_ended(self):
return BusyBeepingState return BusyBeepingState
class WecktState(AbstractState): class WecktState(AbstractState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return CallTerminatingState return CallTerminatingState
def on_call_ended(self): def on_call_ended(self):
return BusyBeepingState return BusyBeepingState
def on_call_accepted(self): def on_call_accepted(self):
return CallRunningState return CallRunningState
class ConnectingState(AbstractState): class ConnectingState(AbstractState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return CallTerminatingState return CallTerminatingState
def on_call_ringing(self): def on_call_ringing(self):
return WecktState return WecktState
class DialingState(AbstractState): class DialingState(AbstractState):
def on_gabelschalter_down(self): def on_gabelschalter_down(self):
return IdleState return IdleState
def on_nummernschalter_input(self, num): def on_nummernschalter_input(self, num):
print('nummernschalter: %d' % (num)) print('nummernschalter: %d' % (num))
def on_timeout(self):
return ConnectingState
def on_timeout(self):
return ConnectingState
class TelefonapparatUserInterface(object): class TelefonapparatUserInterface(object):
def __init__(self): def __init__(self):
pass pass
def add_gabelschalter_callback(self, cb): def add_gabelschalter_callback(self, cb):
pass pass
def add_nummernschalter_callback(self, cb): def add_nummernschalter_callback(self, cb):
pass pass
def set_wecker(self, enabled): def set_wecker(self, enabled):
pass pass
def set_schauzeichen(self, enabled): def set_schauzeichen(self, enabled):
pass pass
class StateMachineController(object): class StateMachineController(object):
def __init__(self): def __init__(self):
self.__state = InitState(self) self.__state = InitState(self)
self.__running = True self.__running = True
self.__evqueue = queue.Queue() self.__evqueue = queue.Queue()
self.__evthread = threading.Thread(target=self.__event_dispatcher) self.__evthread = threading.Thread(target=self.__event_dispatcher)
self.__evthread.start() self.__evthread.start()
def __event_dispatcher(self): def __event_dispatcher(self):
while self.__running: while self.__running:
(evname, evargs, evkwargs) = self.__evqueue.get() (evname, evargs, evkwargs) = self.__evqueue.get()
if not evname: if not evname:
return return
print('!!! event: %s' % (evname)) print('!!! event: %s' % (evname))
handler = getattr(self.__state, 'on_%s' % (evname)) handler = getattr(self.__state, 'on_%s' % (evname))
try: try:
newstate = handler(*evargs, **evkwargs) newstate = handler(*evargs, **evkwargs)
except IllegalEventError: except IllegalEventError:
print('illegal event occured!!!!!!!!!!!!!!!!!!!!') print('illegal event occured!!!!!!!!!!!!!!!!!!!!')
if not newstate: if not newstate:
continue continue
oldstate = self.__state.__class__ oldstate = self.__state.__class__
print('%s -> %s' % (oldstate.__name__, newstate.__name__)) print('%s -> %s' % (oldstate.__name__, newstate.__name__))
self.__state = newstate(self) self.__state = newstate(self)
def queue_event(self, evname, *evargs, **evkwargs):
def queue_event(self, evname, *evargs, **evkwargs): if not hasattr(AbstractState, 'on_%s' % (evname)):
if not hasattr(AbstractState, 'on_%s' % (evname)): raise ValueError('Illegal event name: %s' % (evname))
raise ValueError('Illegal event name: %s' % (evname)) self.__evqueue.put((evname, evargs, evkwargs))
self.__evqueue.put((evname, evargs, evkwargs))
def stop(self, hard=False):
def stop(self, hard=False): if hard:
if hard: self.__running = False
self.__running = False self.__evqueue.put((None, None, None))
self.__evqueue.put((None, None, None))
if __name__ == '__main__': if __name__ == '__main__':
c = StateMachineController() c = StateMachineController()
c.queue_event('registration_in_progress') c.queue_event('registration_in_progress')
c.queue_event('registration_successful') c.queue_event('registration_successful')
c.queue_event('gabelschalter_up') c.queue_event('gabelschalter_up')
c.queue_event('nummernschalter_input', 4) c.queue_event('nummernschalter_input', 4)
c.queue_event('nummernschalter_input', 2) c.queue_event('nummernschalter_input', 2)
#c.queue_event('gabelschalter_down') #c.queue_event('gabelschalter_down')
#c.queue_event('call_accepted') #c.queue_event('call_accepted')
c.queue_event('timeout') c.queue_event('timeout')
c.queue_event('call_ringing') c.queue_event('call_ringing')
#c.queue_event('gabelschalter_down') #c.queue_event('gabelschalter_down')
c.queue_event('call_accepted') c.queue_event('call_accepted')
c.queue_event('call_ended') c.queue_event('call_ended')
c.queue_event('timeout') c.queue_event('timeout')
c.queue_event('gabelschalter_down') c.queue_event('gabelschalter_down')
c.stop() c.stop()

Loading…
Cancel
Save