def __init__(self, **kwargs): super(RFIDReader, self).__init__(**kwargs) Thread.__init__(self, name=RFIDReader) Utils.print_info('[NFC_Reader] Starting manager ...') self.synapse_list = list(super(RFIDReader, self).get_list_synapse()) if self.synapse_list is None: self.synapse_list = list()
def __init__(self, **kwargs): super(Debug, self).__init__(**kwargs) self.message = kwargs.get('message', None) # check if parameters have been provided if self._is_parameters_ok(): Utils.print_warning("[Debug neuron, %s] %s\n" % (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), self.message))
def run(self): """ Start the thread that listen the microphone and then give the audio to the callback method """ Utils.print_info("Say something!") self.stop_thread = self.recognizer.listen_in_background(self.microphone, self.callback) while not self.kill_yourself: sleep(0.1) logger.debug("kill the speech recognition process") self.stop_thread()
def __init__(self, **kwargs): super(Snowboy, self).__init__() self._ignore_stderr() # pause listening boolean self.interrupted = False self.kill_received = False # get the sensitivity if set by the user self.sensitivity = kwargs.get('sensitivity', 0.5) # callback function to call when hotword caught self.callback = kwargs.get('callback', None) if self.callback is None: raise MissingParameterException("callback function is required with snowboy") # get the pmdl file to load self.pmdl = kwargs.get('pmdl_file', None) if self.pmdl is None: raise MissingParameterException("Pmdl file is required with snowboy") self.pmdl_path = Utils.get_real_file_path(self.pmdl) if not os.path.isfile(self.pmdl_path): raise SnowboyModelNotFounfd("The snowboy model file %s does not exist" % self.pmdl_path) self.detector = snowboydecoder.HotwordDetector(self.pmdl_path, sensitivity=self.sensitivity, detected_callback=self.callback, interrupt_check=self.interrupt_callback, sleep_time=0.03)
def run(self): """ Start the thread that listen the microphone and then give the audio to the callback method """ if self.audio_stream is None: Utils.print_info("Say something!") try: with self.microphone as source: logger.debug("[SpeechRecognition] STT timeout: %s" % self.settings.options.stt_timeout) self.audio_stream = self.recognizer.listen(source, timeout=self.settings.options.stt_timeout) except sr.WaitTimeoutError: logger.debug("[SpeechRecognition] timeout reached while waiting for audio input") self.audio_stream = None logger.debug("[SpeechRecognition] end of speech recognition process") self.callback(self.recognizer, self.audio_stream)
def waiting_for_trigger_callback_thread(self): """ Method to print in debug that the main process is waiting for a trigger detection """ logger.debug("[Order] Entering state: %s" % self.state) if self.settings.options.deaf: # the user asked to deaf inside the deaf neuron Utils.print_info("Kalliope is deaf") self.trigger_instance.pause() else: Utils.print_info("Waiting for trigger detection") # this loop is used to keep the main thread alive while not self.trigger_callback_called: sleep(0.1) # if here, then the trigger has been called HookManager.on_triggered() self.next_state()
def __init__(self, **kwargs): super(Precise, self).__init__() self._ignore_stderr() # pause listening boolean self.interrupted = False # callback function to call when hotword caught self.callback = kwargs.get('callback', None) if self.callback is None: raise MissingParameterException( "Callback function is required with precise") # get the sensitivity if set by the user self.sensitivity = kwargs.get('sensitivity', 0.5) # get the pmdl file to load self.pb_file = kwargs.get('pb_file', None) if self.pb_file is None: raise MissingParameterException( "Wake word file is required with precise") try: os.path.isfile(Utils.get_real_file_path(self.pb_file)) except TypeError: raise PreciseModelNotFound( "Precise wake word file %s does not exist" % self.pb_file) self.detector = HotwordDetector(keyword=self.pb_file, sensitivity=self.sensitivity, detected_callback=self.callback)
def __init__(self): super(SignalModule, self).__init__() Thread.__init__(self, name=Order) Utils.print_info('Starting order signal') # load settings and brain from singleton sl = SettingLoader() self.settings = sl.settings self.brain = BrainLoader().brain # keep in memory the order to process self.order_to_process = None # get the player instance self.player_instance = PlayerLauncher.get_player(settings=self.settings) # save an instance of the trigger self.trigger_instance = None self.trigger_callback_called = False self.skip_trigger = False # keep the status of the trigger, if true we can skip it in the statue machine # save the current order listener self.order_listener = None self.order_listener_callback_called = False # Initialize the state machine self.machine = Machine(model=self, states=Order.states, initial='init', queued=True) # define transitions self.machine.add_transition('start_trigger', ['init', 'analysing_order'], 'starting_trigger') self.machine.add_transition('wait_trigger_callback', 'starting_trigger', 'waiting_for_trigger_callback') self.machine.add_transition('stop_trigger', 'waiting_for_trigger_callback', 'stopping_trigger') self.machine.add_transition('wait_for_order', 'stopping_trigger', 'waiting_for_order_listener_callback') self.machine.add_transition('analyse_order', 'waiting_for_order_listener_callback', 'analysing_order') self.machine.add_transition('start_order_listener', 'analysing_order', 'start_order_listener') self.machine.add_ordered_transitions() # add method which are called when changing state self.machine.on_enter_starting_trigger('start_trigger_process') self.machine.on_enter_waiting_for_trigger_callback('waiting_for_trigger_callback_thread') self.machine.on_enter_stopping_trigger('stop_trigger_process') self.machine.on_enter_start_order_listener('start_order_listener_thread') self.machine.on_enter_waiting_for_order_listener_callback('waiting_for_order_listener_callback_thread') self.machine.on_enter_analysing_order('analysing_order_thread')
def __init__(self, audio_file=None): """ Thread used to caught n audio from the microphone and pass it to a callback method """ super(SpeechRecognition, self).__init__() self.recognizer = sr.Recognizer() self.microphone = sr.Microphone() self.callback = None self.stop_thread = None self.kill_yourself = False self.audio_stream = None # get global configuration sl = SettingLoader() self.settings = sl.settings if audio_file is None: # audio file not set, we need to capture a sample from the microphone with self.microphone as source: if self.settings.options.adjust_for_ambient_noise_second > 0: # threshold is calculated from capturing ambient sound logger.debug("[SpeechRecognition] threshold calculated by " "capturing ambient noise during %s seconds" % self.settings.options.adjust_for_ambient_noise_second) Utils.print_info("[SpeechRecognition] capturing ambient sound during %s seconds" % self.settings.options.adjust_for_ambient_noise_second) self.recognizer.adjust_for_ambient_noise(source, duration=self.settings. options.adjust_for_ambient_noise_second) else: # threshold is defined manually logger.debug("[SpeechRecognition] threshold defined by settings: %s" % self.settings.options.energy_threshold) self.recognizer.energy_threshold = self.settings.options.energy_threshold Utils.print_info("[SpeechRecognition] Threshold set to: %s" % self.recognizer.energy_threshold) else: # audio file provided with sr.AudioFile(audio_file) as source: self.audio_stream = self.recognizer.record(source) # read the entire audio file
def _is_parameters_ok(self): """ Check if received parameters are ok to perform operations in the neuron :return: true if parameters are ok, raise an exception otherwise .. raises:: MissingParameterException """ if self.synapse_name is None or self.synapse_name == "": raise MissingParameterException("[Brain neuron] You must specify a 'synapse_name'") if self.enabled is None or self.enabled == "": raise MissingParameterException("[Brain neuron] You must specify a 'enabled' boolean") self.enabled = Utils.str_to_bool(self.enabled) return True
def get_value_flag_from_request(self, http_request, flag_to_find, is_boolean=False): """ Get the value flag from the request if exist, None otherwise ! :param http_request: :param flag_to_find: json flag to find in the http_request :param is_boolean: True if the expected value is a boolean, False Otherwise. :return: the Value of the flag that has been found in the request """ flag_value = None try: received_json = http_request.get_json(force=True, silent=True, cache=True) if flag_to_find in received_json: flag_value = received_json[flag_to_find] if is_boolean: flag_value = Utils.str_to_bool(flag_value) except TypeError: # no json received pass logger.debug("[FlaskAPI] Value found for : type %s, %s : %s" % (flag_to_find, type(flag_value), flag_value)) return flag_value
def _is_parameters_ok(self): """ Check the validity for each parameter :return: True if all parameters are set correctly, False otherwise. """ # Players if self.default_player: if not SettingEditor._check_name_in_list_settings_entry(self.default_player, self.settings.players): logger.debug("[Settings] default_player %s is not defined in settings file ", self.default_player) return False if self.players: if not isinstance(self.players, list): logger.debug("[Settings] players current type: %s. players should be a list", type(self.players)) return False for player_el in self.players: if not isinstance(player_el, dict): logger.debug("[Settings] player current element type: %s. player element should be a dict", type(player_el)) return False # STT if self.default_stt: if not SettingEditor._check_name_in_list_settings_entry(self.default_stt, self.settings.stts): logger.debug("[Settings] default_stt %s is not defined in settings file ", self.default_stt) return False if self.speech_to_text: if not isinstance(self.speech_to_text, list): logger.debug("[Settings] speech_to_text current type: %s. speech_to_text should be a list", type(self.speech_to_text)) return False for stt_el in self.speech_to_text: if not isinstance(stt_el, dict): logger.debug( "[Settings] speech_to_text current element type: %s. speech_to_text element should be a dict", type(stt_el)) return False # TRIGGER if self.default_trigger: if not SettingEditor._check_name_in_list_settings_entry(self.default_trigger, self.settings.triggers): logger.debug("[Settings] default_trigger %s is not defined in settings file ", self.default_trigger) return False if self.triggers: if not isinstance(self.triggers, list): logger.debug("[Settings] triggers current type: %s. triggers should be a list", type(self.triggers)) return False for trigger_el in self.triggers: if not isinstance(trigger_el, dict): logger.debug("[Settings] triggers current element type: %s. triggers element should be a dict", type(trigger_el)) return False # TTS if self.default_tts: if not SettingEditor._check_name_in_list_settings_entry(self.default_tts, self.settings.ttss): logger.debug("[Settings] default_tts %s is not defined in settings file ", self.default_tts) return False if self.text_to_speech: if not isinstance(self.text_to_speech, list): logger.debug("[Settings] text_to_speech current type: %s. text_to_speech should be a list", type(self.text_to_speech)) return False for tts_el in self.text_to_speech: if not isinstance(tts_el, dict): logger.debug( "[Settings] text_to_speech element current type: %s. text_to_speech element should be a dict", type(tts_el)) return False # Options if self.deaf is not None: if not isinstance(self.deaf, bool): logger.debug("[Settings] deaf %s is not a correct value, you must define True or False", self.deaf) return False if self.mute is not None: if not isinstance(self.mute, bool): logger.debug("[Settings] mute %s is not a correct value, you must define True or False", self.mute) return False if self.energy_threshold is not None: if not isinstance(self.energy_threshold, int): logger.debug("[Settings] energy_threshold %s is not a correct integer, you must define a number", self.energy_threshold) return False if self.adjust_for_ambient_noise_second is not None: if not isinstance(self.adjust_for_ambient_noise_second, int): logger.debug( "[Settings] adjust_for_ambient_noise_second %s is not a correct integer, you must define a number", self.adjust_for_ambient_noise_second) return False # Hooks if self.hooks: if not isinstance(self.hooks, dict): logger.debug("[Settings] hooks property %s is not a dictionary as it should be.", type(self.hooks)) return False for hook_name, synap in self.hooks.items(): if not isinstance(synap, str) and not isinstance(synap, list): logger.debug( "[Settings] for hook element %s the type %s is nor a string nor a list as it should be.", hook_name, type(synap)) return False # Variables if self.var_files: if not isinstance(self.var_files, list): logger.debug("[Settings] var_files property %s is not a list as it should be.", type(self.var_files)) return False for file_name in self.var_files: var = Utils.get_real_file_path(file_name) if var is None: logger.debug("[Settings] Variables file %s not found", file_name) return False if self.variable: if not isinstance(self.variable, dict): logger.debug("[Settings] variable property %s is not a dict as it should be.", type(self.variable)) return False return True
def _set_settings(self): # PLAYERS if self.default_player: SettingEditor.set_default_player(self.default_player) if self.players: for player_el in self.players: if isinstance(player_el, dict): for player_name in player_el: name = player_name parameters = player_el[name] new_player = Player(name=name, parameters=parameters) SettingEditor.set_players(new_player) # STT if self.default_stt: SettingEditor.set_default_stt(self.default_stt) if self.speech_to_text: for stt_el in self.speech_to_text: if isinstance(stt_el, dict): for stt_name in stt_el: name = stt_name parameters = stt_el[name] new_stt = Stt(name=name, parameters=parameters) SettingEditor.set_stts(new_stt) # TRIGGER if self.default_trigger: SettingEditor.set_default_trigger(self.default_trigger) if self.triggers: for trigger_el in self.triggers: if isinstance(trigger_el, dict): for trigger_name in trigger_el: name = trigger_name parameters = trigger_el[name] new_trigger = Trigger(name=name, parameters=parameters) SettingEditor.set_trigger(new_trigger) # TTS if self.default_tts: SettingEditor.set_default_tts(self.default_tts) if self.text_to_speech: for tts_el in self.text_to_speech: if isinstance(tts_el, dict): for tts_name in tts_el: name = tts_name parameters = tts_el[name] new_tts = Tts(name=name, parameters=parameters) SettingEditor.set_ttss(new_tts) # Options if self.deaf is not None: signal_order = SignalLauncher.get_order_instance() if signal_order is not None: SettingEditor.set_deaf_status(signal_order.trigger_instance, self.deaf) if self.mute is not None: SettingEditor.set_mute_status(self.mute) if self.energy_threshold is not None: SettingEditor.set_energy_threshold(self.energy_threshold) if self.adjust_for_ambient_noise_second is not None: SettingEditor.set_adjust_for_ambient_noise_second(self.adjust_for_ambient_noise_second) # Hooks if self.hooks: SettingEditor.set_hooks(self.hooks) # Variables if self.var_files: variables = dict() for files in self.var_files: var = Utils.get_real_file_path(files) # var is None has been checked previously in _is_parameters_ok() method variables.update(YAMLLoader.get_config(var)) SettingEditor.set_variables(variables) if self.variable is not None: SettingEditor.set_variables(self.variable)
def run_synapse_by_audio(self): """ Give an order to Kalliope with an audio file Test with curl curl -i --user admin:secret -X POST http://localhost:5000/synapses/start/audio -F "file=@/path/to/input.wav" With mute flag curl -i --user admin:secret -X POST http://localhost:5000/synapses/start/audio -F "file=@path/to/file.wav" -F mute="true" :return: """ # check if the post request has the file part if 'file' not in request.files: data = { "error": "No file provided" } return jsonify(error=data), 400 uploaded_file = request.files['file'] # if user does not select file, browser also # submit a empty part without filename if uploaded_file.filename == '': data = { "error": "No file provided" } return jsonify(error=data), 400 # Store the mute value, then apply depending of the request parameters old_mute_value = self.settings.options.mute if request.form.get("mute"): SettingEditor.set_mute_status(mute=Utils.str_to_bool(request.form.get("mute"))) # save the file filename = secure_filename(uploaded_file.filename) base_path = os.path.join(self.app.config['UPLOAD_FOLDER']) uploaded_file.save(os.path.join(base_path, filename)) # now start analyse the audio with STT engine audio_path = base_path + os.sep + filename logger.debug("[FlaskAPI] run_synapse_by_audio: with file path %s" % audio_path) if not self.allowed_file(audio_path): audio_path = self._convert_to_wav(audio_file_path=audio_path) ol = OrderListener(callback=self.audio_analyser_callback, audio_file_path=audio_path) ol.start() ol.join() # wait the Order Analyser processing. We need to wait in this thread to keep the context while not self.order_analyser_return: time.sleep(0.1) self.order_analyser_return = False if self.api_response is not None and self.api_response: data = jsonify(self.api_response) self.api_response = None logger.debug("[FlaskAPI] run_synapse_by_audio: data %s" % data) if request.form.get("mute"): SettingEditor.set_mute_status(mute=old_mute_value) return data, 201 else: data = { "error": "The given order doesn't match any synapses" } if request.form.get("mute"): SettingEditor.set_mute_status(mute=old_mute_value) return jsonify(error=data), 400