-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
304 lines (235 loc) · 8.63 KB
/
server.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
# Required libraries
import cv2
import os
import unidecode
import _thread
import pygame
import reverse_geocode as rg
from flask import Flask, jsonify, request
import threading
import atexit
# Helper functions for database and image operations
from database import *
from image_operations import *
# Helper script for socket communication
import de1_sockets as de1sock
# Microsoft API calls
import azure_api_calls as api
streaming_thread = None
pygame.mixer.init()
db = connect_db()
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
latest_bmp = None
latest_palette = None
language_codes ={
'english': 'en-us',
'french': 'fr-fr',
'german': 'de-de',
'spanish': 'es-es',
'italian': 'it-it'
}
voice_codes = {
'english': 'en-US-BenjaminRUS',
'french': 'fr-FR-Paul-Apollo',
'german': 'de-DE-Hedda',
'spanish': 'es-ES-Laura-Apollo',
'italian': 'it-IT-LuciaRUS'
}
'''
Simple test endpoint to make sure that our
server is able to send responses
'''
@app.route('/', methods=['GET'])
def hello():
return 'Hello World'
'''
Main end point for the application.
@param target_language the string identifying the language to translate to
@param native_language the string identifying the selected native language
- Receives user native language and target language.
- Fetches image from Pi camera
- Sends and receives data from REST api calls for Azure API
- Sends response to De1Soc, image over socket thread and
response message over HTTP
'''
@app.route('/translate', methods=['GET'])
def translate():
target_language = (request.args.get('target_language')).lower()
native_language = (request.args.get('native_language')).lower()
# get codes for text to speech playback and for HTTP response
target_language_code = language_codes[target_language]
target_voice_code = voice_codes[target_language]
native_language_code = language_codes[native_language]
frame = get_frame()
filename = "Images/test_output_translate.bmp"
cv2.imwrite(filename, frame)
image_data = open(filename, "rb").read()
# detect the objects in the image
analysisJson = api.detect_objects(image_data)
# draw bounding boxes on all the images
objects = analysisJson['objects']
returnJson = {
"objects":[],
"targetLanguage": target_language,
"nativeLanguage": native_language
}
# find translation of detected objects for target language
translations = []
for detectedObject in objects:
translation_object_target = api.translate(detectedObject['object'],
target_language_code)['translations'][0]['text']
translations.append(unidecode.unidecode(translation_object_target))
translation_object_native = detectedObject['object'] if native_language is "english" else api.translate(detectedObject['object'],
native_language_code)['translations'][0]['text']
returnJson["objects"].append({
"native" : unidecode.unidecode(translation_object_native),
"translated" : unidecode.unidecode(translation_object_target)
})
boxed_filename = boundingBoxes(frame, objects, translations)
global latest_bmp
global latest_palette
latest_bmp, latest_palette = palettize(boxed_filename)
return jsonify(returnJson)
'''
Opens a socket to send the bmp image to the De1
- return OK if the image was sent successfully
'''
@app.route('/open_bmp_sock', methods=['GET'])
def open_bmp_sock():
global latest_bmp
global latest_palette
_thread.start_new_thread(de1sock.send_image_data, (latest_bmp, latest_palette))
return '\"OK\"'
@app.route('/get_location', methods=['GET'])
def get_location():
latitude = float(request.args.get('latitude'))
longitude = float(request.args.get('longitude'))
coordinates = [(latitude, longitude)]
output = rg.search(coordinates)
return '\"' + output[0]['country'].lower() + '\"'
'''
Plays audio from RPi audio output over a speaker or headset using the pygame library
@param word the word that the user wishes to hear the audio for
@param language the target language for the audio
- returns a .wav audio file with the given word spoken in the target language
'''
@app.route('/play_audio', methods=['GET'])
def play_audio():
word = (request.args.get('word')).lower()
language = (request.args.get('language')).lower()
api.text_to_speech(word, language_codes[language], voice_codes[language])
pygame.mixer.music.load('Sound/response' + str(0) + '.wav')
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
continue
return '\"OK\"'
'''
End point for registering a new user
@param name the new user's username
@param password the new user's password
- Returns the user's unique user_id if successful
- create_user method takes care of instance where user already exists in the db
'''
@app.route('/register_user', methods=['GET'])
def register_user():
global db
name = (request.args.get('name'))
password = (request.args.get('password'))
if db is not None:
return create_user(db, name, password)
else:
return '\"NO_DB\"'
''''
End point for authenticating a user
@param name the existing user's username
@param password the existing user's password
- Returns the user's unique user_id if successful
- find_user method takes care of incorrect username/password scenarios
'''
@app.route('/authenticate_user', methods=['GET'])
def authenticate_user():
global db
name = (request.args.get('name'))
password = (request.args.get('password'))
if db is not None:
return find_user(db, name, password)
else:
return '\"NO_DB\"'
'''
End point for deleting an existing user
@param name the existing user's username
@param password the existing user's password
- Returns the user's unique user_id if successful
- delete_user method takes care of incorrect username/password scenarios
'''
@app.route('/delete_user', methods=['GET'])
def delete_user():
global db
name = (request.args.get('name'))
password = (request.args.get('password'))
if db is not None:
return remove_user(db, name, password)
else:
return '\"NO_DB\"'
'''
End point for adding a word to a user's history
@param name the user's username
- Returns the user's ADD_OK if successful
- add_history method takes care of incorrect username/password and invalid word scenarios
'''
@app.route('/add_to_history', methods=['GET'])
def add_to_history():
global db
name = (request.args.get('name'))
native_language = (request.args.get('native_language'))
target_language = (request.args.get('target_language'))
native_word = (request.args.get('native_word'))
target_word = (request.args.get('target_word'))
if db is not None:
return add_history(db, name, native_language, target_language, native_word, target_word)
else:
return '\"NO_DB\"'
'''
End point for removing a word from a user's history
@param name the user's username
- Returns the user's DELETE_OK if successful
- add_history method takes care of incorrect username/password and invalid word scenarios
'''
@app.route('/remove_from_history', methods=['GET'])
def remove_from_history():
global db
name = (request.args.get('name'))
native_language = (request.args.get('native_language'))
target_language = (request.args.get('target_language'))
native_word = (request.args.get('native_word'))
target_word = (request.args.get('target_word'))
if db is not None:
return remove_history(db, name, native_language, target_language, native_word, target_word)
else:
return '\"NO_DB\"'
'''
End point for adding a word to a user's history
@param name the user's username
- Returns a user's entire history of words
- add_history method takes care of incorrect username/password and invalid word scenarios
'''
@app.route('/get_user_history', methods=['GET'])
def get_user_history():
global db
name = (request.args.get('name'))
if db is not None:
return jsonify(get_history(db, name))
else:
return '\"NO_DB\"'
def stop_streaming_thread():
global streaming_thread
stop_stream()
if streaming_thread is not None:
streaming_thread.join()
if __name__ == '__main__':
db = connect_db()
streaming_thread = threading.Thread(target = start_stream, args = ())
streaming_thread.start()
atexit.register(stop_streaming_thread)
app.run(host='0.0.0.0', debug=False)