-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
167 lines (126 loc) · 5.89 KB
/
main.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
import os
from functools import partial
import yaml
import grpc
import speech_recognition as sr
from prompt_toolkit.application import Application
from prompt_toolkit.application.current import get_app
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.layout import Layout
from prompt_toolkit.layout.containers import HSplit, VSplit, FloatContainer
from prompt_toolkit.styles import Style
from prompt_toolkit.widgets import Button, Box, TextArea, Label, Frame
from prompt_toolkit.eventloop import ensure_future, From
import home_assistant.vlviapb_pb2 as vl
import home_assistant.vlviapb_pb2_grpc as vl_grpc
from home_assistant.view_utils import (show_dialog, ChoiceDialog,
MessageDialog, ListeningDialog)
from home_assistant.home import Home
LOGO = r"""
[]
_ _ ____ __ __ ______ _____ _____ _____ _____ _______ _ _ _______ /^~^~^~^~^~^~\
| | | |/ __ \| \/ | ____| /\ / ____/ ____|_ _|/ ____|__ __|/\ | \ | |__ __| /^ ^ ^ ^ ^ ^ ^\
| |__| | | | | \ / | |__ / \ | (___| (___ | | | (___ | | / \ | \| | | | /_^_^_^^_^_^_^_^_\
| __ | | | | |\/| | __| / /\ \ \___ \\___ \ | | \___ \ | | / /\ \ | . ` | | | | .--. |
| | | | |__| | | | | |____ / ____ \ ____) |___) |_| |_ ____) | | |/ ____ \| |\ | | | ^^^^| [}{] |[]| |^^^^^
|_| |_|\____/|_| |_|______| /_/ \_\_____/_____/|_____|_____/ |_/_/ \_\_| \_| |_| 88|________|__|__|888
====
"""
HELP = "Welcome to HOME ASSISTANT deluxe edition"
def help_handler():
def coroutine():
dialog = MessageDialog(HELP, 'HELP')
yield From(show_dialog(dialog))
ensure_future(coroutine())
def recognize(voice_lab, vl_metadata, audio_data):
wav_data = audio_data.get_wav_data(convert_rate=16000, convert_width=2)
text = []
stream = iter([vl.AudioFrames(frames=wav_data)])
for update in voice_lab.RecognizeStream(stream, metadata=vl_metadata):
shift = update.shift
words = update.words
words_to_rm = len(words) - shift
text[len(text) - words_to_rm:] = words
# filter prepositions
return [word for word in text if len(word) > 2]
def listen_handler(vl_stub, vl_metadata, mic, recognizer, home, text_area):
def handler():
def coroutine():
listening_dialog = ListeningDialog(mic, recognizer)
audio = yield From(show_dialog(listening_dialog))
tokens = recognize(vl_stub, vl_metadata, audio)
possible_commands = home.match_command(tokens)
text_area.text = ' '.join(tokens)
text_area.text = str(home)
if not possible_commands:
err_msg = 'Unrecognized command: {}'.format(' '.join(tokens))
err_msg_dialog = MessageDialog(err_msg, 'Error')
yield From(show_dialog(err_msg_dialog))
elif len(possible_commands) == 1 and possible_commands[0][0] == 0:
[(_, _, action)] = possible_commands
action()
else:
choice_dialog = ChoiceDialog([cmd for _, cmd, _ in possible_commands[:3]])
choice = yield From(show_dialog(choice_dialog))
if choice is not None:
_, _, action = possible_commands[choice]
action()
text_area.text = str(home)
ensure_future(coroutine())
return handler
def create_app(listen_handler, home):
# components
logo = Label(text=LOGO)
text_area = TextArea(text=str(home), read_only=True, scrollbar=True)
listen_btn = Button('Listen', handler=listen_handler(text_area=text_area))
help_btn = Button('Help', handler=help_handler)
exit_btn = Button('Exit', handler=lambda: get_app().exit())
buttons = HSplit(children=[Label(text=' MENU'),
Frame(listen_btn),
Frame(help_btn),
Frame(exit_btn)],
style='bg:#00aa00 #000000')
# root container
root_container = FloatContainer(HSplit([
Box(body=VSplit([buttons, logo], padding=12),
padding=0,
style='bg:#888800 #000000'),
text_area,
]), floats=[])
# key bindings
bindings = KeyBindings()
bindings.add('tab')(focus_next)
bindings.add('s-tab')(focus_previous)
@bindings.add('c-c')
@bindings.add('q')
def _(event):
event.app.exit()
# application
application = Application(layout=Layout(root_container,
focused_element=listen_btn),
key_bindings=bindings,
enable_page_navigation_bindings=True,
mouse_support=True,
full_screen=True)
return application
def main():
password = os.environ.get('VL_PASSWD')
if not password:
print('Missing password required to connect to Voice Lab service.\n'
'Please provider by setting environment variable "VL_PASSWD"')
exit(1)
channel = grpc.insecure_channel('demo.voicelab.pl:7722')
vl_stub = vl_grpc.VLVIAStub(channel)
vl_metadata = [
('pid', '8131'),
('password', password),
('contenttype', 'audio/L16;rate=16000')
]
with open('./home.yaml') as f:
home = Home(yaml.load(f))
app = create_app(partial(listen_handler, vl_stub, vl_metadata,
sr.Microphone(), sr.Recognizer(), home), home)
app.run()
if __name__ == '__main__':
main()