21 Listens to enclosure commands for Mycroft's Mouth. 23 Performs the associated command on Arduino by writing on the Serial port. 34 self.bus.on(
'enclosure.mouth.reset', self.
reset)
35 self.bus.on(
'enclosure.mouth.talk', self.
talk)
36 self.bus.on(
'enclosure.mouth.think', self.
think)
37 self.bus.on(
'enclosure.mouth.listen', self.
listen)
38 self.bus.on(
'enclosure.mouth.smile', self.
smile)
39 self.bus.on(
'enclosure.mouth.viseme_list', self.
viseme_list)
40 self.bus.on(
'enclosure.mouth.text', self.
text)
41 self.bus.on(
'enclosure.mouth.display', self.
display)
42 self.bus.on(
'enclosure.mouth.display_image', self.
display_image)
45 self.bus.on(
'enclosure.mouth.events.activate',
47 self.bus.on(
'enclosure.mouth.events.deactivate',
51 self.bus.on(
'enclosure.mouth.viseme_list', self.
viseme_list)
54 self.bus.remove(
'enclosure.mouth.viseme_list', self.
viseme_list)
57 self.writer.write(
"mouth.reset")
59 def talk(self, event=None):
60 self.writer.write(
"mouth.talk")
63 self.writer.write(
"mouth.think")
66 self.writer.write(
"mouth.listen")
69 self.writer.write(
"mouth.smile")
72 if event
and event.data:
73 start = event.data[
'start']
74 visemes = event.data[
'visemes']
76 for code, end
in visemes:
79 if time.time() < start + end:
80 self.writer.write(
'mouth.viseme=' + code)
81 time.sleep(start + end - time.time())
87 def text(self, event=None):
89 if event
and event.data:
90 text = event.data.get(
"text", text)
91 self.writer.write(
"mouth.text=" + text)
93 def __display(self, code, clear_previous, x_offset, y_offset):
94 """ Write the encoded image to enclosure screen. 97 code (str): encoded image to display 98 clean_previous (str): if "True" will clear the screen before 100 x_offset (int): x direction offset 101 y_offset (int): y direction offset 103 clear_previous = int(str(clear_previous) ==
"True")
104 clear_previous =
"cP=" + str(clear_previous) +
"," 105 x_offset =
"x=" + str(x_offset) +
"," 106 y_offset =
"y=" + str(y_offset) +
"," 108 message =
"mouth.icon=" + x_offset + y_offset + clear_previous + code
110 if len(message) > 60:
111 message1 = message[:31]
112 message2 = message[31:]
115 message2 =
"mouth.icon=" + message2
116 self.writer.write(message1)
118 self.writer.write(message2)
121 self.writer.write(message)
124 """ Display a Mark-1 specific code. 126 event (Message): messagebus message with data to display 132 if event
and event.data:
133 code = event.data.get(
"img_code", code)
134 x_offset = int(event.data.get(
"xOffset", x_offset))
135 y_offset = int(event.data.get(
"yOffset", y_offset))
136 clear_previous = event.data.get(
"clearPrev", clear_previous)
137 self.
__display(code, clear_previous, x_offset, y_offset)
140 """ Display an image on the enclosure. 142 The method uses PIL to convert the image supplied into a code 143 suitable for the Mark-1 display. 146 event (Message): messagebus message with data to display 151 image_absolute_path = event.data[
'img_path']
152 refresh = event.data[
'clearPrev']
153 invert = event.data[
'invert']
154 x_offset = event.data[
'xOffset']
155 y_offset = event.data[
'yOffset']
156 threshold = event.data.get(
'threshold', 70)
159 img = Image.open(image_absolute_path).convert(
"RGBA")
160 img2 = Image.new(
'RGBA', img.size, (255, 255, 255))
165 img = Image.alpha_composite(img2, img)
166 img = img.convert(
"L")
170 img = img.crop((0, 0, 32, height))
176 img = img.crop((0, 0, width, 8))
184 width_codes = [
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
185 'M',
'N',
'O',
'P',
'Q',
'R', 'S', 'T', '
U', 'V', 'W',
186 'X',
'Y',
'Z',
'[',
'\\',
']',
'^',
'_',
'`',
'a']
188 height_codes = [
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I']
190 encode += width_codes[width - 1]
191 encode += height_codes[height - 1]
196 for i
in range(width):
197 for j
in range(height):
198 if img.getpixel((i, j)) < threshold:
200 binary_values.append(
'1')
202 binary_values.append(
'0')
205 binary_values.append(
'0')
207 binary_values.append(
'1')
211 number_of_top_pixel = 0
212 number_of_bottom_pixel = 0
215 number_of_top_pixel = 4
216 number_of_bottom_pixel = height - 4
218 number_of_top_pixel = height
226 for val
in binary_values:
229 if increment == number_of_top_pixel
and alternate
is False:
231 binary_list.append(binary_code[::-1])
235 elif increment == number_of_bottom_pixel
and alternate
is True:
236 binary_list.append(binary_code[::-1])
243 pixel_codes = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
244 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P']
246 for binary_values
in binary_list:
247 number = int(binary_values, 2)
248 pixel_code = pixel_codes[number]
251 self.
__display(encode, refresh, x_offset, y_offset)
254 if event
and event.data:
256 img_code = event.data.get(
"img_code",
None)
260 icon =
"IICEIBMDNLMDIBCEAA" 263 icon =
"IIEEGBGDHLHDHBGEEA" 266 icon =
"IIIBMDMDODODODMDIB" 269 icon =
"IIMAOJOFPBPJPFOBMA" 272 icon =
"IIMIOFOBPFPDPJOFMA" 275 icon =
"IIAAIIMEODLBJAAAAA" 278 icon =
"IIJEKCMBPHMBKCJEAA" 281 icon =
"IIABIBIBIJIJJGJAGA" 283 temp = event.data.get(
"temp",
None)
284 if icon
is not None and temp
is not None:
286 msg =
"weather.display=" + str(temp) +
"," + str(icon)
287 self.writer.write(msg)
def _deactivate_visemes(self, event=None)
def __display(self, code, clear_previous, x_offset, y_offset)
def listen(self, event=None)
def _activate_visemes(self, event=None)
def viseme_list(self, event=None)
def talk(self, event=None)
def display_image(self, event=None)
def text(self, event=None)
def smile(self, event=None)
def reset(self, event=None)
def __init__(self, bus, writer)
def clear_visemes(self, event=None)
def display_weather(self, event=None)
def think(self, event=None)
def display(self, event=None)