-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathrobot.py
385 lines (314 loc) · 10.8 KB
/
robot.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# project: pRodriguezAssistant
import subprocess
import time
import threading
import sys
import getopt
import pathlib
import psutil
from common import power
from common.speech_recognizer import PsLiveRecognizer
from profiles.bender import bender as profile
from common import server
main_thread_is_running = True
SLEEP_TASK_ENABLED = profile.SLEEP_TASK_ENABLED
IDLE_TIME = 60 # in minutes, 2 - minimum
sleep_enabled = False
is_sleeping = False
sleep_counter = 0
sleep_counter_lock = threading.Lock()
UPS_TASK_ENABLED = profile.UPS_TASK_ENABLED
UPS_TASK_INTERVAL = 2
if UPS_TASK_ENABLED: from common import ups_lite
SERVER_TASK_ENABLED = profile.SERVER_TASK_ENABLED
fsm_state = 1
fsm_transition = {
'repeated keyphrase': 2,
'exit': 3,
'reboot': 4,
'shutdown': 5,
'rss start': 6,
'rss end': 1
}
speech_recognizer = None
def sleep_enable_set(val):
global sleep_enabled
sleep_enabled = val
def main(argv):
global main_thread_is_running
global fsm_state
global sleep_enabled
global speech_recognizer
profile.vol_ctrl.set_speaker_volume(profile.vol_ctrl.speaker_volume)
kill_pocketsphinx()
profile.m_player.send_command('stop')
if profile.eyes_bl:
profile.eyes_bl.exec_cmd('OFF')
time.sleep(0.15)
if UPS_TASK_ENABLED:
ups_thread = threading.Thread(target=ups_task)
ups_thread.start()
if SLEEP_TASK_ENABLED:
sleep_enabled = True
profile.sleep_enable_set = sleep_enable_set
sleep_thread = threading.Thread(target=sleep_task)
sleep_thread.daemon = True
sleep_thread.start()
if SERVER_TASK_ENABLED:
server._RequestHandler.POST_callback = profile.POST_handler
server_thread = threading.Thread(target=server.run_server)
server_thread.daemon = True
server_thread.start()
speech_recognizer = PsLiveRecognizer(str(pathlib.Path().absolute()) + '/common/resources/',
str(pathlib.Path().absolute()) + '/profiles/' + profile.name + '/resources/',
profile.recognize_lang, profile.name)
sphinx_proc = subprocess.Popen(["%s" % speech_recognizer.cmd_line], shell=True, stdout=subprocess.PIPE)
print(["%s" % speech_recognizer.cmd_line])
time.sleep(10)
expected_sphinx_pid = sphinx_proc.pid + 1
if psutil.pid_exists(expected_sphinx_pid) == True:
sphinx_pids = [process.pid for process in psutil.process_iter() if 'pocketsphinx_co' in str(process.name)]
if sphinx_pids == None:
print('No pocketsphinx_continuous processes!')
sys.exit(1)
if len(sphinx_pids) > 1:
print('More than one pocketsphinx_continuous processes!')
sys.exit(1)
if len(sphinx_pids) == 1 and (expected_sphinx_pid in sphinx_pids):
print('pocketsphinx_continuous successfully started')
else:
print('Error while starting pocketsphinx_continuous!')
sys.exit(1)
if profile.eyes_bl:
profile.eyes_bl.exec_cmd('ON')
while True:
if (fsm_state == 1):
if find_keyphrase(sphinx_proc):
conversation_mode(sphinx_proc)
elif (fsm_state == 2):
conversation_mode(sphinx_proc)
elif (fsm_state == 3):
break
elif (fsm_state == 4):
break
elif (fsm_state == 5):
break
elif (fsm_state == 6):
rss_read_mode(sphinx_proc)
else:
continue
main_thread_is_running = False
kill_pocketsphinx()
profile.m_player.send_command('stop')
if profile.eyes_bl:
profile.eyes_bl.exec_cmd('OFF')
time.sleep(3)
if (fsm_state == 4):
power.reboot()
if (fsm_state == 5):
power.shutdown()
sys.exit(0)
def ups_task():
global main_thread_is_running
prev_voltage = ups_lite.read_voltage()
prev_capacity = ups_lite.read_capacity()
while main_thread_is_running:
time.sleep(UPS_TASK_INTERVAL)
voltage = ups_lite.read_voltage()
capacity = ups_lite.read_capacity()
if voltage >= 4.20:
if prev_voltage <= 4.15:
profile.a_player.play_answer('electricity')
else:
if capacity < 20 and (prev_capacity > capacity):
power.shutdown()
prev_voltage = voltage
prev_capacity = capacity
def sleep_task():
global is_sleeping
global sleep_enabled
global sleep_counter
global speech_recognizer
while main_thread_is_running:
time.sleep(60)
if sleep_enabled:
sleep_counter_inc()
if sleep_counter >= IDLE_TIME:
if not is_sleeping:
if not profile.m_player.musicIsPlaying:
if profile.eyes_bl:
profile.eyes_bl.exec_cmd('OFF')
profile.a_player.play_answer('fall asleep')
is_sleeping = True
def sleep_counter_inc():
global sleep_counter
sleep_counter_lock.acquire()
sleep_counter += 1
sleep_counter_lock.release()
def sleep_counter_reset():
global sleep_counter
sleep_counter_lock.acquire()
sleep_counter = 0
sleep_counter_lock.release()
def wake_up():
global is_sleeping
if profile.eyes_bl:
profile.eyes_bl.exec_cmd('ON')
profile.a_player.play_answer('wake up')
is_sleeping = False
def get_utterance(sphinx_proc):
retcode = sphinx_proc.returncode
utt = sphinx_proc.stdout.readline().decode('utf8').rstrip().lower()
print('utterance = ' + utt)
return utt
def find_keyphrase(sphinx_proc):
global sleep_enabled
global is_sleeping
global aplayer
global fsm_state
keyphrase_found = False
print('Start mode:')
utt = get_utterance(sphinx_proc)
if speech_recognizer.lang == 'ru':
try:
utt = profile.STTTranslatorRU.tr_start_ru_en[utt]
except KeyError as e:
utt = 'unrecognized'
#raise ValueError('Undefined key to translate: {}'.format(e.args[0]))
if (profile.name in utt):
if sleep_enabled:
sleep_counter_reset()
if profile.m_player.musicIsPlaying:
if('pause' in utt or 'stop' in utt or profile.vol_ctrl.speaker_volume == 0):
profile.m_player.send_command('pause')
keyphrase_found = True
else:
if (('hi' in utt) or ('hey' in utt) or ('hello' in utt)) and not is_sleeping:
answer = 'hey ' + profile.name
profile.a_player.play_answer(answer)
if is_sleeping:
wake_up()
keyphrase_found = True
return keyphrase_found
def conversation_mode(sphinx_proc):
global sleep_enabled
global is_sleeping
global fsm_state
global speech_recognizer
print ('Conversation mode:')
utt = get_utterance(sphinx_proc)
if speech_recognizer.lang == 'ru':
try:
utt = profile.STTTranslatorRU.tr_conversation_ru_en[utt]
except KeyError as e:
utt = 'unrecognized'
#raise ValueError('Undefined key to translate: {}'.format(e.args[0]))
if is_sleeping:
wake_up()
else:
before_action = None
after_action = None
try:
action = profile.actions[utt]
answer = action[0]
before_action = action[1]
after_action = action[2]
except KeyError as e:
answer = 'unrecognized'
print ("answer = " + answer)
try:
fsm_state = fsm_transition[answer]
except:
fsm_state = 1
confirmation_needed = None
if before_action:
confirmation_needed = before_action()
if confirmation_needed:
profile.a_player.play_answer('confirmation')
if not get_confirmation(sphinx_proc):
answer = 'no audio'
after_action = None
else:
answer = 'confirmed'
if answer != 'no audio' and answer != 'rss next' and answer != 'rss next':
profile.a_player.play_answer(answer)
if after_action:
after_action()
if answer != 'shutdown' or answer != 'reboot':
if profile.m_player.musicIsPlaying:
profile.m_player.send_command('resume')
if sleep_enabled:
sleep_counter_reset()
def rss_read_mode(sphinx_proc):
global sleep_enabled
global is_sleeping
global fsm_state
global speech_recognizer
print ('RSS reader mode:')
utt = get_utterance(sphinx_proc)
if speech_recognizer.lang == 'ru':
try:
utt = profile.STTTranslatorRU.tr_conversation_ru_en[utt]
except KeyError as e:
utt = 'unrecognized'
#raise ValueError('Undefined key to translate: {}'.format(e.args[0]))
if (profile.name in utt):
if sleep_enabled:
sleep_counter_reset()
fsm_state = 2
if (('hi' in utt) or ('hey' in utt) or ('hello' in utt)) and not is_sleeping:
answer = 'hey ' + profile.name
profile.a_player.play_answer(answer)
if is_sleeping:
wake_up()
return
if is_sleeping:
wake_up()
else:
after_action = None
try:
action = profile.actions[utt]
answer = action[0]
after_action = action[2]
except KeyError as e:
answer = 'unrecognized'
print ("answer = " + answer)
if ('rss' in answer) and (not 'start' in answer):
try:
fsm_state = fsm_transition[answer]
except:
fsm_state = 6
profile.a_player.play_answer(answer)
if after_action:
after_action()
if sleep_enabled:
sleep_counter_reset()
def get_confirmation(sphinx_proc):
print ('Get confirmation mode:')
utt = get_utterance(sphinx_proc)
if speech_recognizer.lang == 'ru':
try:
utt = profile.STTTranslatorRU.tr_conversation_ru_en[utt]
except KeyError as e:
utt = 'unrecognized'
#raise ValueError('Undefined key to translate: {}'.format(e.args[0]))
if utt == profile.confirmation_phrase:
return True
else:
return False
def stop_pocketsphinx():
stop_exe = 'killall -s STOP pocketsphinx_co'
p = subprocess.Popen(["%s" % stop_exe], shell=True, stdout=subprocess.PIPE)
code = p.wait()
def cont_pocketsphinx():
cont_exe = 'killall -s CONT pocketsphinx_co'
p = subprocess.Popen(["%s" % cont_exe], shell=True, stdout=subprocess.PIPE)
code = p.wait()
def kill_pocketsphinx():
kill_exe = 'killall -s SIGKILL pocketsphinx_co'
p = subprocess.Popen(["%s" % kill_exe], shell=True, stdout=subprocess.PIPE)
code = p.wait()
if __name__ == "__main__":
main(sys.argv[1:])