-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdriver.py
162 lines (148 loc) · 4.82 KB
/
driver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import rotaryhook
import linphone
import Queue
# Driving FSA
class PhoneMachine:
def __init__(self):
self.eventQueue = Queue.Queue()
self.linphone = linphone.Linphone(self.eventQueue)
self.linphone.start()
self.dialer = rotaryhook.RotaryHook(self.eventQueue)
self.dialer.start()
self.dialbuffer = ''
self.status = self.standby
while True:
# print(self.status)
self.status()
def get_event(self):
ret = self.eventQueue.get(True)
self.eventQueue.task_done()
# print ret
return ret
def get_event_timeout(self,timeout):
try:
ret = self.eventQueue.get(True,timeout)
self.eventQueue.task_done()
# print ret
return ret
except Queue.Empty:
return ['timeout', timeout]
# on-hook states
def standby(self):
# TODO: stop ringing and playing tones
self.dialbuffer = ''
self.linphone.hangup()
# TODO: check linphone status, maybe restart
while 1:
event = self.get_event()
if event[0] == 'incoming':
self.status = self.ringing
break
if event[0] == 'hook_up':
self.status = self.dialtone
break
if event[0] == 'dialed':
self.status = self.preCollect
self.dialbuffer = event[1]
break
def preCollect(self):
preCollectTimeout = 10 # forget collected digits after 10 seconds
while 1:
event = self.get_event_timeout(preCollectTimeout)
if event[0] == 'hook_up':
self.status = self.initiateCall
break
if event[0] == 'dialed':
self.dialbuffer += event[1]
break
def ringing(self):
# start ringing
while 1:
event = self.get_event()
if event[0] == 'disconnected':
self.status = self.standby
break
if event[0] == 'hook_up':
self.linphone.answer()
self.status = self.inCall
break
# stop ringing
# off-hook states
def dialtone(self):
# TODO: start playing dialtone
while 1:
event = self.get_event()
if event[0] == 'hook_down':
self.status = self.standby
break
if event[0] == 'dialed':
self.status = self.collectingNumber
self.dialbuffer = event[1]
break
# TODO: stop playing dialtone
def collectingNumber(self):
collectingNumberTimeout = 2.5
while 1:
event = self.get_event_timeout(collectingNumberTimeout)
if event[0] == 'dialed':
self.dialbuffer += event[1]
break
if event[0] == 'hook_down':
self.status = self.standby
break
if event[0] == 'timeout':
self.status = self.initiateCall
break
def initiateCall(self):
self.linphone.call(self.dialbuffer)
# TODO: ensure we have a dial tone
while 1:
event = self.get_event() # timeout?
if event[0] == 'error':
self.status = self.playError
break
if event[0] == 'busy':
self.status = self.playBusy
break
if event[0] == 'hook_down':
self.status = self.standby
break
if event[0] == 'connected':
self.status = self.inCall
break
# TODO: ensure we no longer play a dial tone
def playError(self):
# TODO: play some recorded file
while 1:
event = self.get_event()
if event[0] == 'hook_down':
self.status = self.standby
break
# TODO: terminate playing
def playBusy(self):
# TODO: play busy tone
while 1:
event = self.get_event()
if event[0] == 'hook_down':
self.status = self.standby
break
# TODO: terminate playing
def silence(self):
while 1:
event = self.get_event()
if event[0] == 'hook_down':
self.status = self.standby
break
def inCall(self):
while 1:
event = self.get_event()
if event[0] == 'hook_down':
self.linphone.hangup()
self.status = self.standby
break
if event[0] == 'disconnected':
self.status = self.silence
break
if event[0] == 'dialed':
self.linphone.sendDTMF(event[1])
pm = PhoneMachine()