def test_set_players(self): new_player = Player(name="totoplayer", parameters={}) with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_players(new_player) self.assertIn(new_player, self.sl.settings.players)
def set_deaf(self): """ Set the trigger status (deaf or not) Curl test: curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"deaf": "True"}' http://127.0.0.1:5000/deaf """ if not request.get_json() or 'deaf' not in request.get_json(): data = {"Error": "Wrong parameters, 'deaf' not set"} return jsonify(error=data), 400 # get deaf if present deaf = self.get_value_flag_from_request(http_request=request, flag_to_find="deaf", is_boolean=True) signal_order = SignalLauncher.get_order_instance() if signal_order is not None and deaf is not None and self.settings.options.deaf is not None: SettingEditor.set_deaf_status(signal_order.trigger_instance, deaf) data = {"deaf": self.settings.options.deaf} return jsonify(data), 200 data = {"error": "Cannot switch deaf status"} return jsonify(error=data), 400
def set_adjust_for_ambient_noise_second(self): """ Set the Brain.ai Core ambient_noise_second value Curl test: curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"energy_threshold": "6666"}' http://127.0.0.1:5000/settings/ambient_noise_second """ if not request.get_json( ) or 'ambient_noise_second' not in request.get_json(): data = { "Error": "Wrong parameters, 'ambient_noise_second' not set" } return jsonify(error=data), 400 # get if present ambient_noise_second = self.get_value_flag_from_request( http_request=request, flag_to_find="ambient_noise_second", is_boolean=False) SettingEditor.set_adjust_for_ambient_noise_second( adjust_for_ambient_noise_second=ambient_noise_second) data = {"ambient_noise_second": ambient_noise_second} return jsonify(data), 200
def test_set_variabless(self): default_variables = {"coucou": "hello"} with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_variables(default_variables) self.assertEqual("hello", self.sl.settings.variables["coucou"])
def test_set_ttss(self): new_tts = Tts(name="totoTss", parameters={}) with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_ttss(new_tts) self.assertIn(new_tts, self.sl.settings.ttss)
def test_set_adjust_for_ambient_noise_second(self): with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_adjust_for_ambient_noise_second( adjust_for_ambient_noise_second=600) self.assertEqual( 600, self.sl.settings.options.adjust_for_ambient_noise_second)
def test_set_hooks(self): default_hooks = {"on_deaf": "randomSynapse"} with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_hooks(default_hooks) self.assertEqual("randomSynapse", self.sl.settings.hooks["on_deaf"])
def test_set_default_tts(self): default_name = "NameTts" with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_default_tts(default_name) self.assertEqual("pico2wave", self.sl.settings.default_tts_name) default_name = "googletts" SettingEditor.set_default_tts(default_name) self.assertEqual(default_name, self.sl.settings.default_tts_name)
def test_set_default_trigger(self): default_name = "NameTrigger" with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_default_trigger(default_name) self.assertEqual("snowboy", self.sl.settings.default_trigger_name ) # not existing in the list, not updated ! default_name = "snowboy" SettingEditor.set_default_trigger(default_name) self.assertEqual(default_name, self.sl.settings.default_trigger_name)
def test_set_default_stt(self): default_name = "NameStt" with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_default_stt(default_name) self.assertEqual("google", self.sl.settings.default_stt_name ) # not updated because not in the list default_name = "google" SettingEditor.set_default_stt(default_name) self.assertEqual(default_name, self.sl.settings.default_stt_name) # updated
def set_mute(self): """ Set the Brain.ai Core mute status (mute or not) Curl test: curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"mute": "True"}' http://127.0.0.1:5000/mute """ if not request.get_json() or 'mute' not in request.get_json(): data = {"Error": "Wrong parameters, 'mute' not set"} return jsonify(error=data), 400 # get mute if present mute = self.get_value_flag_from_request(http_request=request, flag_to_find="mute", is_boolean=True) SettingEditor.set_mute_status(mute=mute) data = {"mute": mute} return jsonify(data), 200
def run_synapse_by_audio(self): """ Give an order to Brain.ai 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
def set_default_player(self): """ Set the Brain.ai Core default_player value Curl test: curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"default_player": "myPlayer"}' http://127.0.0.1:5000/settings/default_player """ if not request.get_json() or 'default_player' not in request.get_json( ): data = {"Error": "Wrong parameters, 'default_player' not set"} return jsonify(error=data), 400 # get if present value = self.get_value_flag_from_request(http_request=request, flag_to_find="default_player", is_boolean=False) SettingEditor.set_default_player(default_player_name=value) data = {"default_player": self.settings.default_player_name} return jsonify(data), 200
def set_variables(self): """ Set the Brain.ai Core variables value. Can be used with a dictionary of variables : curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"variable1":"variables_value","variables_name2":"variables_value2"}' http://127.0.0.1:5000/settings/varaibles """ if not request.get_json(): data = {"Error": "No Parameters provided"} return jsonify(error=data), 400 # get if present value = request.get_json() if not isinstance(value, dict): data = {"Error": "Variables must be a dictionary"} return jsonify(error=data), 400 SettingEditor.set_variables(variables=value) data = {"variables": self.settings.variables} return jsonify(data), 200
def set_hooks(self): """ Set the Brain.ai Core hooks value Curl test: curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"hook_name":"hook_value","hooke_name2":"hook_value2"}' http://127.0.0.1:5000/settings/hooks """ if not request.get_json(): data = {"Error": "No Parameters not"} return jsonify(error=data), 400 # get if present value = request.get_json() if not isinstance(value, dict): data = {"Error": "Hooks must be a dictionary"} return jsonify(error=data), 400 SettingEditor.set_hooks(hooks=value) data = {"hooks": self.settings.hooks} return jsonify(data), 200
def run_synapse_by_name(self, synapse_name): """ Run a synapse by its name test with curl: curl -i --user admin:secret -X POST http://127.0.0.1:5000/synapses/start/id/say-hello-fr run a synapse without making brain speaking curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"mute":"true"}' http://127.0.0.1:5000/synapses/start/id/say-hello-fr Run a synapse by its name and pass order's parameters curl -i -H "Content-Type: application/json" --user admin:secret -X POST \ -d '{"mute":"true", "parameters": {"parameter1": "value1" }}' \ http://127.0.0.1:5000/synapses/start/id/say-hello-fr :param synapse_name: name(id) of the synapse to execute :return: """ # get a synapse object from the name logger.debug("[FlaskAPI] run_synapse_by_name: synapse name -> %s" % synapse_name) synapse_target = BrainLoader().brain.get_synapse_by_name( synapse_name=synapse_name) # Store the mute value, then apply depending of the request parameters old_mute_value = self.settings.options.mute mute = self.get_value_flag_from_request(http_request=request, flag_to_find="mute", is_boolean=True) if mute is not None: SettingEditor.set_mute_status(mute=mute) # get parameters parameters = self.get_parameters_from_request(request) if synapse_target is None: data = {"synapse name not found": "%s" % synapse_name} if mute is not None: SettingEditor.set_mute_status(mute=old_mute_value) return jsonify(error=data), 404 else: # generate a MatchedSynapse from the synapse matched_synapse = MatchedSynapse(matched_synapse=synapse_target, overriding_parameter=parameters) # get the current LIFO buffer from the singleton lifo_buffer = LifoManager.get_singleton_lifo() lifo_buffer.add_synapse_list_to_lifo([matched_synapse]) response = lifo_buffer.execute(is_api_call=True) data = jsonify(response) if mute is not None: SettingEditor.set_mute_status(mute=old_mute_value) return data, 201
def run_synapse_by_order(self): """ Give an order to Brain.ai via API like it was from a spoken one Test with curl curl -i --user admin:secret -H "Content-Type: application/json" -X POST \ -d '{"order":"my order"}' http://localhost:5000/synapses/start/order In case of quotes in the order or accents, use a file cat post.json: {"order":"j'aime"} curl -i --user admin:secret -H "Content-Type: application/json" -X POST \ --data @post.json http://localhost:5000/order/ Can be used with mute flag curl -i --user admin:secret -H "Content-Type: application/json" -X POST \ -d '{"order":"my order", "mute":"true"}' http://localhost:5000/synapses/start/order :return: """ if not request.get_json() or 'order' not in request.get_json(): data = {"Error": "Wrong parameters, 'order' not set"} return jsonify(error=data), 400 order = request.get_json('order') # Store the mute value, then apply depending of the request parameters old_mute_value = self.settings.options.mute mute = self.get_value_flag_from_request(http_request=request, flag_to_find="mute", is_boolean=True) if mute is not None: SettingEditor.set_mute_status(mute=mute) if order is not None: # get the order order_to_run = order["order"] logger.debug( "[FlaskAPI] run_synapse_by_order: order to run -> %s" % order_to_run) api_response = SynapseLauncher.run_matching_synapse_from_order( order_to_run, self.brain, self.settings, is_api_call=True) data = jsonify(api_response) if mute is not None: SettingEditor.set_mute_status(mute=old_mute_value) return data, 201 else: data = {"error": "order cannot be null"} if mute is not None: SettingEditor.set_mute_status(mute=old_mute_value) return jsonify(error=data), 400
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 test_set_mute_status(self): with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_mute_status(mute=True) self.assertTrue(self.sl.settings.options.mute)
def test_set_deaf_status(self): with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_deaf_status(mock.Mock(), deaf=False) self.assertFalse(self.sl.settings.options.deaf)
def test_set_energy_threshold(self): with mock.patch("brain.core.ConfigurationManager.SettingLoader" ) as mock_setting_loader: mock_setting_loader.return_value(self.sl) SettingEditor.set_energy_threshold(600) self.assertEqual(600, self.sl.settings.options.energy_threshold)