def listener(): rospy.init_node('mycroft_skills') rospy.loginfo(rospy.get_caller_id() + " started") rospy.Subscriber("mycroft/utterance", String, handle_utterance) rospy.Subscriber("mycroft/remove_skill", String, handle_remove_skill) s = rospy.Service('mycroft/register_skill', MycroftService, handle_register_skill) global bus reset_sigint_handler() # Create PID file, prevent multiple instancesof this service mycroft.lock.Lock('skills') # Connect this Skill management process to the Mycroft Messagebus bus = WebsocketClient() Configuration.init(bus) config = Configuration.get() # Set the active lang to match the configured one set_active_lang(config.get('lang', 'en-us')) bus.on('skill.manager.initialised', initialise_response_server) bus.on('message', create_echo_function('SKILLS')) # Startup will be called after the connection with the Messagebus is done bus.once('open', _starting_up) bus.on('skill.converse.request', check_working) create_daemon(bus.run_forever) wait_for_exit_signal() shutdown() rospy.spin()
def main(): global ws lock = Lock('skills') # prevent multiple instances of this service # Connect this Skill management process to the websocket ws = WebsocketClient() ConfigurationManager.init(ws) ignore_logs = ConfigurationManager.instance().get("ignore_logs") # Listen for messages and echo them for logging def _echo(message): try: _message = json.loads(message) if _message.get("type") in ignore_logs: return if _message.get("type") == "registration": # do not log tokens from registration messages _message["data"]["token"] = None message = json.dumps(_message) except: pass logger.debug(message) ws.on('message', _echo) # Startup will be called after websocket is full live ws.once('open', _starting_up) ws.run_forever()
def main(): global ws global config ws = WebsocketClient() Configuration.init(ws) config = Configuration.get() speech.init(ws) # Setup control of pulse audio setup_pulseaudio_handlers(config.get('Audio').get('pulseaudio')) def echo(message): try: _message = json.loads(message) if 'mycroft.audio.service' not in _message.get('type'): return message = json.dumps(_message) except: pass LOG.debug(message) LOG.info("Staring Audio Services") ws.on('message', echo) ws.once('open', load_services_callback) try: ws.run_forever() except KeyboardInterrupt, e: LOG.exception(e) speech.shutdown() sys.exit()
def main(): global ws lock = Lock('skills') # prevent multiple instances of this service # Connect this Skill management process to the websocket ws = WebsocketClient() ConfigurationManager.init(ws) ignore_logs = ConfigurationManager.instance().get("ignore_logs") # Listen for messages and echo them for logging def _echo(message): try: _message = json.loads(message) if _message.get("type") in ignore_logs: return if _message.get("type") == "registration": # do not log tokens from registration messages _message["data"]["token"] = None message = json.dumps(_message) except: pass logger.debug(message) ws.on('message', _echo) # Kick off loading of skills ws.once('open', _load_skills) ws.run_forever()
def main(): global ws global config global pulse ws = WebsocketClient() ConfigurationManager.init(ws) config = ConfigurationManager.get() speech.init(ws) # Setup control of pulse audio if pulsectl and config.get('Audio').get('pulseaudio') == 'mute': pulse = pulsectl.Pulse('Mycroft-audio-service') else: pulse = None def echo(message): try: _message = json.loads(message) if 'mycroft.audio.service' in _message.get('type'): return message = json.dumps(_message) except: pass logger.debug(message) logger.info("Staring Audio Services") ws.on('message', echo) ws.once('open', load_services_callback) try: ws.run_forever() except KeyboardInterrupt, e: logger.exception(e) speech.shutdown() sys.exit()
def main(): global ws lock = Lock('skills') # prevent multiple instances of this service # Connect this Skill management process to the websocket ws = WebsocketClient() ConfigurationManager.init(ws) ignore_logs = ConfigurationManager.instance().get("ignore_logs") # Listen for messages and echo them for logging def _echo(message): try: _message = json.loads(message) if _message.get("type") in ignore_logs: return if _message.get("type") == "registration": # do not log tokens from registration messages _message["data"]["token"] = None message = json.dumps(_message) except: pass LOG('SKILLS').debug(message) ws.on('message', _echo) ws.on('skill.converse.request', handle_converse_request) # Startup will be called after websocket is full live ws.once('open', _starting_up) ws.run_forever()
def main(): global ws global config ws = WebsocketClient() ConfigurationManager.init(ws) config = ConfigurationManager.get() speech.init(ws) # Setup control of pulse audio setup_pulseaudio_handlers(config.get('Audio').get('pulseaudio')) def echo(message): try: _message = json.loads(message) if 'mycroft.audio.service' not in _message.get('type'): return message = json.dumps(_message) except: pass LOG.debug(message) LOG.info("Staring Audio Services") ws.on('message', echo) ws.once('open', load_services_callback) try: ws.run_forever() except KeyboardInterrupt, e: LOG.exception(e) speech.shutdown() sys.exit()
def main(): global bus reset_sigint_handler() # Create PID file, prevent multiple instancesof this service mycroft.lock.Lock('skills') # Connect this Skill management process to the Mycroft Messagebus bus = WebsocketClient() Configuration.init(bus) bus.on('message', create_echo_function('SKILLS')) # Startup will be called after the connection with the Messagebus is done bus.once('open', _starting_up) create_daemon(bus.run_forever) wait_for_exit_signal() shutdown()
def main(): global client client = WebsocketClient() def echo(message): try: _message = json.loads(message) if _message.get("message_type") == "registration": # do not log tokens from registration messages _message["metadata"]["token"] = None message = json.dumps(_message) except: pass logger.debug(message) client.on('message', echo) client.once('open', load_skills_callback) client.run_forever()
def main(): global ws ws = WebsocketClient() ConfigurationManager.init(ws) def echo(message): try: _message = json.loads(message) if _message.get("type") == "registration": # do not log tokens from registration messages _message["data"]["token"] = None message = json.dumps(_message) except: pass logger.debug(message) ws.on('message', echo) ws.once('open', load_skills_callback) ws.run_forever()
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 """ _last_internet_notification = 0 def __init__(self): self.ws = WebsocketClient() self.ws.on("open", self.on_ws_open) Configuration.init(self.ws) global_config = Configuration.get() self.lang = global_config['lang'] self.config = global_config.get("enclosure") self.__init_serial() self.reader = EnclosureReader(self.serial, self.ws, self.lang) self.writer = EnclosureWriter(self.serial, self.ws) # initiates the web sockets on display manager # NOTE: this is a temporary place to initiate display manager sockets initiate_display_manager_ws() def on_ws_open(self, event=None): # Mark 1 auto-detection: # # Prepare to receive message when the Arduino responds to the # following "system.version" self.ws.on("enclosure.started", self.on_arduino_responded) self.arduino_responded = False # Send a message to the Arduino across the serial line asking # for a reply with version info. self.writer.write("system.version") # Start a 5 second timer. If the serial port hasn't received # any acknowledgement of the "system.version" within those # 5 seconds, assume there is nothing on the other end (e.g. # we aren't running a Mark 1 with an Arduino) Timer(5, self.check_for_response).start() # Notifications from mycroft-core self.ws.on("enclosure.notify.no_internet", self.on_no_internet) def on_arduino_responded(self, event=None): self.eyes = EnclosureEyes(self.ws, self.writer) self.mouth = EnclosureMouth(self.ws, self.writer) self.system = EnclosureArduino(self.ws, self.writer) self.weather = EnclosureWeather(self.ws, self.writer) self.__register_events() self.__reset() self.arduino_responded = True # verify internet connection and prompt user on bootup if needed if not connected(): # We delay this for several seconds to ensure that the other # clients are up and connected to the messagebus in order to # receive the "speak". This was sometimes happening too # quickly and the user wasn't notified what to do. Timer(5, self._do_net_check).start() Timer(60, self._hack_check_for_duplicates).start() def on_no_internet(self, event=None): if connected(): # One last check to see if connection was established return if time.time() - Enclosure._last_internet_notification < 30: # don't bother the user with multiple notifications with 30 secs return Enclosure._last_internet_notification = time.time() # TODO: This should go into EnclosureMark1 subclass of Enclosure. if has_been_paired(): # Handle the translation within that code. self.ws.emit( Message( "speak", { 'utterance': "This device is not connected to the Internet. " "Either plug in a network cable or hold the " "button on top for two seconds, then select " "wifi from the menu" })) else: # enter wifi-setup mode automatically self.ws.emit(Message('system.wifi.setup', {'lang': self.lang})) 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) LOG.info("Connected to: %s rate: %s timeout: %s" % (self.port, self.rate, self.timeout)) except: LOG.error("Impossible to connect to serial port: " + str(self.port)) raise def __register_events(self): self.ws.on('enclosure.mouth.events.activate', self.__register_mouth_events) self.ws.on('enclosure.mouth.events.deactivate', self.__remove_mouth_events) self.ws.on('enclosure.reset', self.__reset) self.__register_mouth_events() def __register_mouth_events(self, event=None): self.ws.on('recognizer_loop:record_begin', self.mouth.listen) self.ws.on('recognizer_loop:record_end', self.mouth.reset) self.ws.on('recognizer_loop:audio_output_start', self.mouth.talk) self.ws.on('recognizer_loop:audio_output_end', self.mouth.reset) def __remove_mouth_events(self, event=None): self.ws.remove('recognizer_loop:record_begin', self.mouth.listen) self.ws.remove('recognizer_loop:record_end', self.mouth.reset) self.ws.remove('recognizer_loop:audio_output_start', self.mouth.talk) self.ws.remove('recognizer_loop:audio_output_end', self.mouth.reset) def __reset(self, event=None): # Reset both the mouth and the eye elements to indicate the unit is # ready for input. self.writer.write("eyes.reset") self.writer.write("mouth.reset") def speak(self, text): self.ws.emit(Message("speak", {'utterance': text})) def run(self): try: self.ws.run_forever() except Exception as e: LOG.error("Error: {0}".format(e)) self.stop() def check_for_response(self): if not self.arduino_responded: # There is nothing on the other end of the serial port # close these serial-port readers and this process self.writer.stop() self.reader.stop() self.serial.close() self.ws.close() def _handle_pairing_complete(self, Message): """ Handler for 'mycroft.paired', unmutes the mic after the pairing is complete. """ self.ws.emit(Message("mycroft.mic.unmute")) def _do_net_check(self): # TODO: This should live in the derived Enclosure, e.g. Enclosure_Mark1 LOG.info("Checking internet connection") if not connected(): # and self.conn_monitor is None: if has_been_paired(): # TODO: Enclosure/localization self.speak("This unit is not connected to the Internet. " "Either plug in a network cable or hold the " "button on top for two seconds, then select " "wifi from the menu") else: # Begin the unit startup process, this is the first time it # is being run with factory defaults. # TODO: This logic should be in Enclosure_Mark1 # TODO: Enclosure/localization # Don't listen to mic during this out-of-box experience self.ws.emit(Message("mycroft.mic.mute")) # Setup handler to unmute mic at the end of on boarding # i.e. after pairing is complete self.ws.once('mycroft.paired', self._handle_pairing_complete) self.speak(mycroft.dialog.get('mycroft.intro')) wait_while_speaking() time.sleep(2) # a pause sounds better than just jumping in # Kick off wifi-setup automatically data = {'allow_timeout': False, 'lang': self.lang} self.ws.emit(Message('system.wifi.setup', data)) def _hack_check_for_duplicates(self): # TEMPORARY HACK: Look for multiple instance of the # mycroft-speech-client and/or mycroft-skills services, which could # happen when upgrading a shipping Mark 1 from release 0.8.17 or # before. When found, force the unit to reboot. import psutil LOG.info("Hack to check for duplicate service instances") count_instances = 0 needs_reboot = False for process in psutil.process_iter(): if process.cmdline() == [ 'python2.7', '/usr/local/bin/mycroft-speech-client' ]: count_instances += 1 if (count_instances > 1): LOG.info("Duplicate mycroft-speech-client found") needs_reboot = True count_instances = 0 for process in psutil.process_iter(): if process.cmdline() == [ 'python2.7', '/usr/local/bin/mycroft-skills' ]: count_instances += 1 if (count_instances > 1): LOG.info("Duplicate mycroft-skills found") needs_reboot = True if needs_reboot: LOG.info("Hack reboot...") self.reader.process("unit.reboot") self.ws.emit(Message("enclosure.eyes.spin")) self.ws.emit(Message("enclosure.mouth.reset"))
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 """ _last_internet_notification = 0 def __init__(self): self.ws = WebsocketClient() self.ws.on("open", self.on_ws_open) Configuration.init(self.ws) global_config = Configuration.get() self.lang = global_config['lang'] self.config = global_config.get("enclosure") self.__init_serial() self.reader = EnclosureReader(self.serial, self.ws, self.lang) self.writer = EnclosureWriter(self.serial, self.ws) # initiates the web sockets on display manager # NOTE: this is a temporary place to initiate display manager sockets initiate_display_manager_ws() def on_ws_open(self, event=None): # Mark 1 auto-detection: # # Prepare to receive message when the Arduino responds to the # following "system.version" self.ws.on("enclosure.started", self.on_arduino_responded) self.arduino_responded = False # Send a message to the Arduino across the serial line asking # for a reply with version info. self.writer.write("system.version") # Start a 5 second timer. If the serial port hasn't received # any acknowledgement of the "system.version" within those # 5 seconds, assume there is nothing on the other end (e.g. # we aren't running a Mark 1 with an Arduino) Timer(5, self.check_for_response).start() # Notifications from mycroft-core self.ws.on("enclosure.notify.no_internet", self.on_no_internet) def on_arduino_responded(self, event=None): self.eyes = EnclosureEyes(self.ws, self.writer) self.mouth = EnclosureMouth(self.ws, self.writer) self.system = EnclosureArduino(self.ws, self.writer) self.weather = EnclosureWeather(self.ws, self.writer) self.__register_events() self.__reset() self.arduino_responded = True # verify internet connection and prompt user on bootup if needed if not connected(): # We delay this for several seconds to ensure that the other # clients are up and connected to the messagebus in order to # receive the "speak". This was sometimes happening too # quickly and the user wasn't notified what to do. Timer(5, self._do_net_check).start() Timer(60, self._hack_check_for_duplicates).start() def on_no_internet(self, event=None): if connected(): # One last check to see if connection was established return if time.time() - Enclosure._last_internet_notification < 30: # don't bother the user with multiple notifications with 30 secs return Enclosure._last_internet_notification = time.time() # TODO: This should go into EnclosureMark1 subclass of Enclosure. if has_been_paired(): # Handle the translation within that code. self.ws.emit(Message("speak", { 'utterance': "This device is not connected to the Internet. " "Either plug in a network cable or hold the " "button on top for two seconds, then select " "wifi from the menu"})) else: # enter wifi-setup mode automatically self.ws.emit(Message('system.wifi.setup', {'lang': self.lang})) 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) LOG.info("Connected to: %s rate: %s timeout: %s" % (self.port, self.rate, self.timeout)) except: LOG.error("Impossible to connect to serial port: "+str(self.port)) raise def __register_events(self): self.ws.on('enclosure.mouth.events.activate', self.__register_mouth_events) self.ws.on('enclosure.mouth.events.deactivate', self.__remove_mouth_events) self.ws.on('enclosure.reset', self.__reset) self.__register_mouth_events() def __register_mouth_events(self, event=None): self.ws.on('recognizer_loop:record_begin', self.mouth.listen) self.ws.on('recognizer_loop:record_end', self.mouth.reset) self.ws.on('recognizer_loop:audio_output_start', self.mouth.talk) self.ws.on('recognizer_loop:audio_output_end', self.mouth.reset) def __remove_mouth_events(self, event=None): self.ws.remove('recognizer_loop:record_begin', self.mouth.listen) self.ws.remove('recognizer_loop:record_end', self.mouth.reset) self.ws.remove('recognizer_loop:audio_output_start', self.mouth.talk) self.ws.remove('recognizer_loop:audio_output_end', self.mouth.reset) def __reset(self, event=None): # Reset both the mouth and the eye elements to indicate the unit is # ready for input. self.writer.write("eyes.reset") self.writer.write("mouth.reset") def speak(self, text): self.ws.emit(Message("speak", {'utterance': text})) def run(self): try: self.ws.run_forever() except Exception as e: LOG.error("Error: {0}".format(e)) self.stop() def check_for_response(self): if not self.arduino_responded: # There is nothing on the other end of the serial port # close these serial-port readers and this process self.writer.stop() self.reader.stop() self.serial.close() self.ws.close() def _handle_pairing_complete(self, Message): """ Handler for 'mycroft.paired', unmutes the mic after the pairing is complete. """ self.ws.emit(Message("mycroft.mic.unmute")) def _do_net_check(self): # TODO: This should live in the derived Enclosure, e.g. Enclosure_Mark1 LOG.info("Checking internet connection") if not connected(): # and self.conn_monitor is None: if has_been_paired(): # TODO: Enclosure/localization self.speak("This unit is not connected to the Internet. " "Either plug in a network cable or hold the " "button on top for two seconds, then select " "wifi from the menu") else: # Begin the unit startup process, this is the first time it # is being run with factory defaults. # TODO: This logic should be in Enclosure_Mark1 # TODO: Enclosure/localization # Don't listen to mic during this out-of-box experience self.ws.emit(Message("mycroft.mic.mute")) # Setup handler to unmute mic at the end of on boarding # i.e. after pairing is complete self.ws.once('mycroft.paired', self._handle_pairing_complete) self.speak(mycroft.dialog.get('mycroft.intro')) wait_while_speaking() time.sleep(2) # a pause sounds better than just jumping in # Kick off wifi-setup automatically data = {'allow_timeout': False, 'lang': self.lang} self.ws.emit(Message('system.wifi.setup', data)) def _hack_check_for_duplicates(self): # TEMPORARY HACK: Look for multiple instance of the # mycroft-speech-client and/or mycroft-skills services, which could # happen when upgrading a shipping Mark 1 from release 0.8.17 or # before. When found, force the unit to reboot. import psutil LOG.info("Hack to check for duplicate service instances") count_instances = 0 needs_reboot = False for process in psutil.process_iter(): if process.cmdline() == ['python2.7', '/usr/local/bin/mycroft-speech-client']: count_instances += 1 if (count_instances > 1): LOG.info("Duplicate mycroft-speech-client found") needs_reboot = True count_instances = 0 for process in psutil.process_iter(): if process.cmdline() == ['python2.7', '/usr/local/bin/mycroft-skills']: count_instances += 1 if (count_instances > 1): LOG.info("Duplicate mycroft-skills found") needs_reboot = True if needs_reboot: LOG.info("Hack reboot...") self.reader.process("unit.reboot") self.ws.emit(Message("enclosure.eyes.spin")) self.ws.emit(Message("enclosure.mouth.reset"))