diff --git a/mycroft/client/enclosure/__init__.py b/mycroft/client/enclosure/__init__.py
index cb59143831..6e3464f773 100644
--- a/mycroft/client/enclosure/__init__.py
+++ b/mycroft/client/enclosure/__init__.py
@@ -16,4 +16,261 @@
# along with Mycroft Core. If not, see .
-__author__ = 'seanfitz'
+import subprocess
+import time
+from Queue import Queue
+from alsaaudio import Mixer
+from threading import Thread
+
+import serial
+
+from mycroft.client.enclosure.arduino import EnclosureArduino
+from mycroft.client.enclosure.eyes import EnclosureEyes
+from mycroft.client.enclosure.mouth import EnclosureMouth
+from mycroft.client.enclosure.weather import EnclosureWeather
+from mycroft.configuration import ConfigurationManager
+from mycroft.messagebus.client.ws import WebsocketClient
+from mycroft.messagebus.message import Message
+from mycroft.util import play_wav, create_signal
+from mycroft.util.audio_test import record
+from mycroft.util.log import getLogger
+
+__author__ = 'aatchison', 'jdorleans', 'iward'
+
+LOGGER = getLogger("EnclosureClient")
+
+
+class EnclosureReader(Thread):
+ """
+ Reads data from Serial port.
+
+ Listens to all commands sent by Arduino that must be be performed on
+ Mycroft Core.
+
+ E.g. Mycroft Stop Feature
+ #. Arduino sends a Stop command after a button press on a Mycroft unit
+ #. ``EnclosureReader`` captures the Stop command
+ #. Notify all Mycroft Core processes (e.g. skills) to be stopped
+
+ Note: A command is identified by a line break
+ """
+
+ def __init__(self, serial, client):
+ super(EnclosureReader, self).__init__(target=self.read)
+ self.alive = True
+ self.daemon = True
+ self.serial = serial
+ self.client = client
+ self.start()
+
+ def read(self):
+ while self.alive:
+ try:
+ data = self.serial.readline()[:-2]
+ if data:
+ self.process(data)
+ LOGGER.info("Reading: " + data)
+ except Exception as e:
+ LOGGER.error("Reading error: {0}".format(e))
+
+ def process(self, data):
+ self.client.emit(Message(data))
+
+ if "mycroft.stop" in data:
+ create_signal('buttonPress')
+ self.client.emit(Message("mycroft.stop"))
+
+ if "volume.up" in data:
+ self.client.emit(
+ Message("IncreaseVolumeIntent", {'play_sound': True}))
+
+ if "volume.down" in data:
+ self.client.emit(
+ Message("DecreaseVolumeIntent", {'play_sound': True}))
+
+ if "system.test.begin" in data:
+ self.client.emit(Message('recognizer_loop:sleep'))
+
+ if "system.test.end" in data:
+ self.client.emit(Message('recognizer_loop:wake_up'))
+
+ if "mic.test" in data:
+ mixer = Mixer()
+ prev_vol = mixer.getvolume()[0]
+ mixer.setvolume(35)
+ self.client.emit(Message("speak", {
+ 'utterance': "I am testing one two three"}))
+
+ time.sleep(0.5) # Prevents recording the loud button press
+ record("/tmp/test.wav", 3.0)
+ mixer.setvolume(prev_vol)
+ play_wav("/tmp/test.wav").communicate()
+
+ # Test audio muting on arduino
+ subprocess.call('speaker-test -P 10 -l 0 -s 1', shell=True)
+
+ if "unit.shutdown" in data:
+ self.client.emit(
+ Message("enclosure.eyes.timedspin",
+ {'length': 12000}))
+ self.client.emit(Message("enclosure.mouth.reset"))
+ subprocess.call('systemctl poweroff -i', shell=True)
+
+ if "unit.reboot" in data:
+ self.client.emit(
+ Message("enclosure.eyes.spin"))
+ self.client.emit(Message("enclosure.mouth.reset"))
+ subprocess.call('systemctl reboot -i', shell=True)
+
+ if "unit.setwifi" in data:
+ self.client.emit(Message("wifisetup.start"))
+
+ if "unit.factory-reset" in data:
+ subprocess.call(
+ 'rm ~/.mycroft/identity/identity.json',
+ shell=True)
+ self.client.emit(
+ Message("enclosure.eyes.spin"))
+ self.client.emit(Message("enclosure.mouth.reset"))
+ subprocess.call('systemctl reboot -i', shell=True)
+
+ def stop(self):
+ self.alive = False
+
+
+class EnclosureWriter(Thread):
+ """
+ Writes data to Serial port.
+ #. Enqueues all commands received from Mycroft enclosures
+ implementation
+ #. Process them on the received order by writing on the Serial port
+
+ E.g. Displaying a text on Mycroft's Mouth
+ #. ``EnclosureMouth`` sends a text command
+ #. ``EnclosureWriter`` captures and enqueue the command
+ #. ``EnclosureWriter`` removes the next command from the queue
+ #. ``EnclosureWriter`` writes the command to Serial port
+
+ Note: A command has to end with a line break
+ """
+
+ def __init__(self, serial, client, size=16):
+ super(EnclosureWriter, self).__init__(target=self.flush)
+ self.alive = True
+ self.daemon = True
+ self.serial = serial
+ self.client = client
+ self.commands = Queue(size)
+ self.start()
+
+ def flush(self):
+ while self.alive:
+ try:
+ cmd = self.commands.get()
+ self.serial.write(cmd + '\n')
+ LOGGER.info("Writing: " + cmd)
+ self.commands.task_done()
+ except Exception as e:
+ LOGGER.error("Writing error: {0}".format(e))
+
+ def write(self, command):
+ self.commands.put(str(command))
+
+ def stop(self):
+ self.alive = False
+
+
+class Enclosure(object):
+ """
+ Serves as a communication interface between Arduino and Mycroft Core.
+
+ ``Enclosure`` initializes and aggregates all enclosures implementation.
+
+ E.g. ``EnclosureEyes``, ``EnclosureMouth`` and ``EnclosureArduino``
+
+ It also listens to the basis events in order to perform those core actions
+ on the unit.
+
+ E.g. Start and Stop talk animation
+ """
+
+ def __init__(self):
+ self.config = ConfigurationManager.get().get("enclosure")
+ self.__init_serial()
+ self.client = WebsocketClient()
+ self.reader = EnclosureReader(self.serial, self.client)
+ self.writer = EnclosureWriter(self.serial, self.client)
+ self.eyes = EnclosureEyes(self.client, self.writer)
+ self.mouth = EnclosureMouth(self.client, self.writer)
+ self.system = EnclosureArduino(self.client, self.writer)
+ self.weather = EnclosureWeather(self.client, self.writer)
+ self.__register_events()
+ self.update()
+ self.test()
+
+ def update(self):
+ if self.config.get('update'):
+ try:
+ self.speak("I am upgrading my enclosure version")
+ subprocess.check_call('/opt/enclosure/upload.sh')
+ self.speak("Enclosure upgrade completed")
+ time.sleep(5)
+ except:
+ self.speak("I cannot upgrade right now, I'll try later")
+
+ def test(self):
+ if self.config.get('test'):
+ self.speak("Beginning hardware self test")
+ self.writer.write("test.begin")
+
+ def __init_serial(self):
+ try:
+ self.port = self.config.get("port")
+ self.rate = self.config.get("rate")
+ self.timeout = self.config.get("timeout")
+ self.serial = serial.serial_for_url(
+ url=self.port, baudrate=self.rate, timeout=self.timeout)
+ LOGGER.info(
+ "Connected to: " + self.port + " rate: " + str(self.rate) +
+ " timeout: " + str(self.timeout))
+ except:
+ LOGGER.error(
+ "It is not possible to connect to serial port: " + self.port)
+ raise
+
+ def __register_events(self):
+ self.client.on('enclosure.mouth.events.activate',
+ self.__register_mouth_events)
+ self.client.on('enclosure.mouth.events.deactivate',
+ self.__remove_mouth_events)
+ self.__register_mouth_events()
+
+ def __register_mouth_events(self, event=None):
+ self.client.on('recognizer_loop:record_begin', self.mouth.listen)
+ self.client.on('recognizer_loop:record_end', self.mouth.reset)
+ self.client.on('recognizer_loop:audio_output_start', self.mouth.talk)
+ self.client.on('recognizer_loop:audio_output_end', self.mouth.reset)
+
+ def __remove_mouth_events(self, event=None):
+ self.client.remove('recognizer_loop:record_begin', self.mouth.listen)
+ self.client.remove('recognizer_loop:record_end', self.mouth.reset)
+ self.client.remove('recognizer_loop:audio_output_start',
+ self.mouth.talk)
+ self.client.remove('recognizer_loop:audio_output_end',
+ self.mouth.reset)
+
+ def speak(self, text):
+ self.client.emit(Message("speak", {'utterance': text}))
+
+ def run(self):
+ try:
+ self.client.run_forever()
+ except Exception as e:
+ LOGGER.error("Client error: {0}".format(e))
+ self.stop()
+
+ def stop(self):
+ self.writer.stop()
+ self.reader.stop()
+ self.serial.close()
+ self.client.close()
diff --git a/mycroft/client/enclosure/main.py b/mycroft/client/enclosure/main.py
index b71e174906..3425b5b84d 100644
--- a/mycroft/client/enclosure/main.py
+++ b/mycroft/client/enclosure/main.py
@@ -14,266 +14,11 @@
#
# You should have received a copy of the GNU General Public License
# along with Mycroft Core. If not, see .
-import subprocess
+
+
import sys
-import time
-from Queue import Queue
-from alsaaudio import Mixer
-from threading import Thread
-import serial
-
-from mycroft.client.enclosure.arduino import EnclosureArduino
-from mycroft.client.enclosure.eyes import EnclosureEyes
-from mycroft.client.enclosure.mouth import EnclosureMouth
-from mycroft.client.enclosure.weather import EnclosureWeather
-from mycroft.configuration import ConfigurationManager
-from mycroft.messagebus.client.ws import WebsocketClient
-from mycroft.messagebus.message import Message
-from mycroft.util import play_wav
-from mycroft.util import create_signal
-from mycroft.util.audio_test import record
-from mycroft.util.log import getLogger
-
-__author__ = 'aatchison + jdorleans + iward'
-
-LOGGER = getLogger("EnclosureClient")
-
-
-class EnclosureReader(Thread):
- """
- Reads data from Serial port.
-
- Listens to all commands sent by Arduino that must be be performed on
- Mycroft Core.
-
- E.g. Mycroft Stop Feature
- #. Arduino sends a Stop command after a button press on a Mycroft unit
- #. ``EnclosureReader`` captures the Stop command
- #. Notify all Mycroft Core processes (e.g. skills) to be stopped
-
- Note: A command is identified by a line break
- """
-
- def __init__(self, serial, client):
- super(EnclosureReader, self).__init__(target=self.read)
- self.alive = True
- self.daemon = True
- self.serial = serial
- self.client = client
- self.start()
-
- def read(self):
- while self.alive:
- try:
- data = self.serial.readline()[:-2]
- if data:
- self.process(data)
- LOGGER.info("Reading: " + data)
- except Exception as e:
- LOGGER.error("Reading error: {0}".format(e))
-
- def process(self, data):
- self.client.emit(Message(data))
-
- if "mycroft.stop" in data:
- create_signal('buttonPress')
- self.client.emit(Message("mycroft.stop"))
-
- if "volume.up" in data:
- self.client.emit(
- Message("IncreaseVolumeIntent", {'play_sound': True}))
-
- if "volume.down" in data:
- self.client.emit(
- Message("DecreaseVolumeIntent", {'play_sound': True}))
-
- if "system.test.begin" in data:
- self.client.emit(Message('recognizer_loop:sleep'))
-
- if "system.test.end" in data:
- self.client.emit(Message('recognizer_loop:wake_up'))
-
- if "mic.test" in data:
- mixer = Mixer()
- prev_vol = mixer.getvolume()[0]
- mixer.setvolume(35)
- self.client.emit(Message("speak", {
- 'utterance': "I am testing one two three"}))
-
- time.sleep(0.5) # Prevents recording the loud button press
- record("/tmp/test.wav", 3.0)
- mixer.setvolume(prev_vol)
- play_wav("/tmp/test.wav").communicate()
-
- # Test audio muting on arduino
- subprocess.call('speaker-test -P 10 -l 0 -s 1', shell=True)
-
- if "unit.shutdown" in data:
- self.client.emit(
- Message("enclosure.eyes.timedspin",
- {'length': 12000}))
- self.client.emit(Message("enclosure.mouth.reset"))
- subprocess.call('systemctl poweroff -i', shell=True)
-
- if "unit.reboot" in data:
- self.client.emit(
- Message("enclosure.eyes.spin"))
- self.client.emit(Message("enclosure.mouth.reset"))
- subprocess.call('systemctl reboot -i', shell=True)
-
- if "unit.setwifi" in data:
- self.client.emit(Message("mycroft.wifi.start"))
-
- if "unit.factory-reset" in data:
- subprocess.call(
- 'rm ~/.mycroft/identity/identity.json',
- shell=True)
- self.client.emit(
- Message("enclosure.eyes.spin"))
- self.client.emit(Message("enclosure.mouth.reset"))
- subprocess.call('systemctl reboot -i', shell=True)
-
- def stop(self):
- self.alive = False
-
-
-class EnclosureWriter(Thread):
- """
- Writes data to Serial port.
- #. Enqueues all commands received from Mycroft enclosures
- implementation
- #. Process them on the received order by writing on the Serial port
-
- E.g. Displaying a text on Mycroft's Mouth
- #. ``EnclosureMouth`` sends a text command
- #. ``EnclosureWriter`` captures and enqueue the command
- #. ``EnclosureWriter`` removes the next command from the queue
- #. ``EnclosureWriter`` writes the command to Serial port
-
- Note: A command has to end with a line break
- """
-
- def __init__(self, serial, client, size=16):
- super(EnclosureWriter, self).__init__(target=self.flush)
- self.alive = True
- self.daemon = True
- self.serial = serial
- self.client = client
- self.commands = Queue(size)
- self.start()
-
- def flush(self):
- while self.alive:
- try:
- cmd = self.commands.get()
- self.serial.write(cmd + '\n')
- LOGGER.info("Writing: " + cmd)
- self.commands.task_done()
- except Exception as e:
- LOGGER.error("Writing error: {0}".format(e))
-
- def write(self, command):
- self.commands.put(str(command))
-
- def stop(self):
- self.alive = False
-
-
-class Enclosure(object):
- """
- Serves as a communication interface between Arduino and Mycroft Core.
-
- ``Enclosure`` initializes and aggregates all enclosures implementation.
-
- E.g. ``EnclosureEyes``, ``EnclosureMouth`` and ``EnclosureArduino``
-
- It also listens to the basis events in order to perform those core actions
- on the unit.
-
- E.g. Start and Stop talk animation
- """
-
- def __init__(self):
- self.config = ConfigurationManager.get().get("enclosure")
- self.__init_serial()
- self.client = WebsocketClient()
- self.reader = EnclosureReader(self.serial, self.client)
- self.writer = EnclosureWriter(self.serial, self.client)
- self.eyes = EnclosureEyes(self.client, self.writer)
- self.mouth = EnclosureMouth(self.client, self.writer)
- self.system = EnclosureArduino(self.client, self.writer)
- self.weather = EnclosureWeather(self.client, self.writer)
- self.__register_events()
- self.update()
- self.test()
-
- def update(self):
- if self.config.get('update'):
- try:
- self.speak("I am upgrading my enclosure version")
- subprocess.check_call('/opt/enclosure/upload.sh')
- self.speak("Enclosure upgrade completed")
- time.sleep(5)
- except:
- self.speak("I cannot upgrade right now, I'll try later")
-
- def test(self):
- if self.config.get('test'):
- self.speak("Beginning hardware self test")
- self.writer.write("test.begin")
-
- def __init_serial(self):
- try:
- self.port = self.config.get("port")
- self.rate = self.config.get("rate")
- self.timeout = self.config.get("timeout")
- self.serial = serial.serial_for_url(
- url=self.port, baudrate=self.rate, timeout=self.timeout)
- LOGGER.info(
- "Connected to: " + self.port + " rate: " + str(self.rate) +
- " timeout: " + str(self.timeout))
- except:
- LOGGER.error(
- "It is not possible to connect to serial port: " + self.port)
- raise
-
- def __register_events(self):
- self.client.on('enclosure.mouth.events.activate',
- self.__register_mouth_events)
- self.client.on('enclosure.mouth.events.deactivate',
- self.__remove_mouth_events)
- self.__register_mouth_events()
-
- def __register_mouth_events(self, event=None):
- self.client.on('recognizer_loop:record_begin', self.mouth.listen)
- self.client.on('recognizer_loop:record_end', self.mouth.reset)
- self.client.on('recognizer_loop:audio_output_start', self.mouth.talk)
- self.client.on('recognizer_loop:audio_output_end', self.mouth.reset)
-
- def __remove_mouth_events(self, event=None):
- self.client.remove('recognizer_loop:record_begin', self.mouth.listen)
- self.client.remove('recognizer_loop:record_end', self.mouth.reset)
- self.client.remove('recognizer_loop:audio_output_start',
- self.mouth.talk)
- self.client.remove('recognizer_loop:audio_output_end',
- self.mouth.reset)
-
- def speak(self, text):
- self.client.emit(Message("speak", {'utterance': text}))
-
- def run(self):
- try:
- self.client.run_forever()
- except Exception as e:
- LOGGER.error("Client error: {0}".format(e))
- self.stop()
-
- def stop(self):
- self.writer.stop()
- self.reader.stop()
- self.serial.close()
- self.client.close()
+from mycroft.client.enclosure import Enclosure
def main():