def rename_script(self, old_script, new_script): """ Rename script Args: old_script (string): old script name new_script (string): new script name Raises: MissingParameter, InvalidParameter """ if old_script is None or len(old_script)==0: raise MissingParameter(u'Old_script parameter is missing') if new_script is None or len(new_script)==0: raise MissingParameter(u'New_script parameter is missing') if old_script==new_script: raise InvalidParameter(u'Script names must be differents') if not self.__scripts.has_key(old_script): raise InvalidParameter(u'Script "%s" does not exist' % old_script) if self.__scripts.has_key(new_script): raise InvalidParameter(u'Script "%s" already exists' % new_script) #rename script in filesystem self.cleep_filesystem.move(os.path.join(Actions.SCRIPTS_PATH, old_script), os.path.join(Actions.SCRIPTS_PATH, new_script)) time.sleep(0.5) #rename script in config scripts = self._get_config_field(u'scripts') old = scripts[old_script] scripts[new_script] = old del scripts[old_script] self._set_config_field(u'scripts', scripts) #reload scripts self.__load_scripts()
def __set_led(self, led_id, color, brightness=10): """ Configure led color and brightness Args: led_id (int): led identifier (0..2) color (list): RGB tuple (0,0,0) or RGB+brightness value (0,0,0,0) [0..255] brightness (int): brightness percentage (default 10%) [0..100] """ if self.leds_driver is None: raise InvalidParameter(u'Driver is not installed') if led_id < 0 or led_id > 2: raise InvalidParameter(u'Led_id must be 0..2') if brightness < 0 or brightness > 100: raise InvalidParameter(u'Brightness must be 0..100') if len(color) == 4 and (color[3] < 0 or color[3] > 100): raise InvalidParameter(u'Brightness must be 0..100') #handle brightness within color value if len(color) == 4: #force brightness brightness = color[3] #set led color #self.logger.debug(u'Set led%s color R=%s G=%s B=%s with Brightness=%s' % (led_id, color[0], color[1], color[2], brightness)) self.leds_driver.set_pixel(led_id, color[0], color[1], color[2], brightness)
def save_configuration(self, duration, speed): """ Save board configuration Args: duration (float): message duration (cycling time) speed (slow|normal|fast): message scrolling speed Raises: InvalidParameter, MissingParameter """ if duration is None: raise MissingParameter(u'Duration parameter is missing') if duration < 5 or duration > 60: raise InvalidParameter( u'Duration value must be between 5 and 60 seconds') if speed is None or len(speed) == 0: raise MissingParameter(u'Speed parameter is missing') if speed not in self.SPEEDS: raise InvalidParameter(u'Speed value is not valid') #save config self._update_config({u'duration': float(duration), u'speed': speed}) #update board configuration self.board.set_scroll_speed(self.SPEEDS[speed]) #stop current task if self.__display_task: self.__display_task.stop() #and restart new one self.__display_task = BackgroundTask(self.__display_message, self.logger, float(duration)) self.__display_task.start()
def add_leds_profile(self, name, repeat, actions): """ Add leds profile Args: name (string): profile name repeat (int): repeat value (see REPEAT_XXX) actions (list): list of actions (see ACTION_XXX) Returns: bool: True if led profile added successfully Raises: InvalidParameter: if invalid function parameter is specified MissingParameter: if function parameter is missing """ #check params if name is None or len(name) == 0: raise MissingParameter(u'Parameter name is missing') if repeat is None: raise MissingParameter(u'Parameter repeat is missing') if repeat not in (self.REPEAT_NONE, self.REPEAT_1, self.REPEAT_2, self.REPEAT_3, self.REPEAT_4, self.REPEAT_5, self.REPEAT_INF): raise InvalidParameter( u'Parameter repeat is not valid. See available values') if actions is None: raise MissingParameter(u'Parameter actions is missing') if len(actions) == 0: raise InvalidParameter( u'You must add at least one action in leds profile') #check name leds_profiles = self._get_config_field(u'leds_profiles') for profile in leds_profiles: if profile[u'name'] == name: raise InvalidParameter( u'Profile with same name already exists') #append new profile leds_profiles.append({ u'name': name, u'repeat': repeat, u'uuid': str(uuid.uuid4()), u'actions': actions, u'default': False }) #save config if not self._set_config_field(u'leds_profiles', leds_profiles): raise CommandError(u'Unable to save leds profile') return True
def get_script(self, script): """ Return a script Args: script (string): script name Returns: dict: script data:: { visual (string): visual editor used to edit file or None if no editor used code (string): source code header (string): source file header (can contains necessary infos for visual editor) } Raises: InvalidParameter: if script not found CommandError: if error occured processing script """ self.logger.debug(u'Config: %s' % self._get_config()) if not self.__scripts.has_key(script): raise InvalidParameter(u'Unknown script "%s"' % script) path = os.path.join(Actions.SCRIPTS_PATH, script) if not os.path.exists(path): raise InvalidParameter(u'Script "%s" does not exist' % script) output = { u'visual': None, u'code': None, u'header': None } #read file content self.logger.debug(u'Loading script: %s' % path) lines = self.cleep_filesystem.read_data(path, encoding='utf-8') self.logger.debug('Loaded lines: %s' % lines) content = u''.join(lines) #parse file groups = re.findall(u'# -\*- coding: utf-8 -\*-\n(?:\"\"\"\neditor:(\w+)\n(.*)\n\"\"\"\s)?(.*)', content, re.S | re.U) self.logger.debug(groups) if len(groups)==1: if len(groups[0])==3: output[u'editor'] = groups[0][0] output[u'header'] = groups[0][1] output[u'code'] = groups[0][2] else: raise CommandError(u'Unable to load script: invalid format') else: self.logger.warning(u'Unhandled source code: %s' % groups) return output
def set_credentials(self, username, password, phone_numbers): """ Set BulkSms credentials Args: username (string): username password (string): password phone_numbers (string): phone numbers (coma separated if many) Returns: bool: True if credentials saved successfully """ if username is None or len(username)==0: raise MissingParameter(u'Username parameter is missing') if password is None or len(password)==0: raise MissingParameter(u'Password parameter is missing') if phone_numbers is None or len(phone_numbers)==0: raise MissingParameter(u'Phone_numbers parameter is missing') if phone_numbers.strip().find(u' ')!=-1 or phone_numbers.strip().find(u';')!=-1: raise InvalidParameter(u'Phone numbers must be separated by coma (,)') #try to get credits credits = self.get_credits(username, password) return self._update_config({ u'username': username, u'password': password, u'phone_numbers': phone_numbers, u'credits': credits })
def add_music(self, filepath): """ Add new music Args: filepath (string): uploaded and local filepath Returns: bool: True if file uploaded successfully Raises: Exception, InvalidParameter """ #check parameters file_ext = os.path.splitext(filepath) self.logger.debug(u'Add music of extension: %s' % file_ext[1]) if file_ext[1][1:] not in Sounds.ALLOWED_MUSIC_EXTS: raise InvalidParameter( u'Invalid music file uploaded (only %s are supported)' % ','.join(Sounds.ALLOWED_MUSIC_EXTS)) #move file to valid dir if os.path.exists(filepath): name = os.path.basename(filepath) path = os.path.join(Sounds.MUSICS_PATH, name) self.logger.debug(u'Name=%s path=%s' % (name, path)) shutil.move(filepath, path) self.logger.info(u'File "%s" uploaded successfully' % name) else: #file doesn't exists self.logger.error(u'Music file "%s" doesn\'t exist' % filepath) raise Exception(u'Music file "%s" doesn\'t exists' % filepath) return True
def add_script(self, filepath): """ Add new script using rpc upload Args: filepath (string): script full path Raises: InvalidParameter: if invalid parameter is specified Exception: if error occured """ #check parameters file_ext = os.path.splitext(filepath) self.logger.info(u'uploaded file extension: %s - %s' % (unicode(file_ext), unicode(file_ext[1]))) if file_ext[1]!=u'.py': self.logger.info(u'uploaded file extension: %s' % unicode(file_ext[1][1:])) raise InvalidParameter(u'Invalid script file uploaded (only python script are supported)') #move file to valid dir if os.path.exists(filepath): name = os.path.basename(filepath) path = os.path.join(Actions.SCRIPTS_PATH, name) self.logger.info(u'Name=%s path=%s' % (name, path)) self.cleep_filesystem.move(filepath, path) self.logger.info(u'File "%s" uploaded successfully' % name) #reload scripts self.__load_scripts() else: #file doesn't exists self.logger.error(u'Script file "%s" doesn\'t exist' % filepath) raise Exception(u'Script file "%s" doesn\'t exists' % filepath)
def set_provider(self, provider_id, apikey): """ Set speechtotext provider Args: provider_id (int): provider id apikey (string): provider apikey Return: bool: True if action succeed """ if provider_id is None: raise MissingParameter(u'Parameter provider is missing') if not self.__check_provider(provider_id): raise InvalidParameter(u'Specified provider is not valid. Please check list of supported provider.') if apikey is None or len(apikey.strip())==0: raise MissingParameter(u'Parameter apikey is missing') #save config config = self._get_config() #need to convert provider id to string because json does not support int as map/dict key provider_id_str = str(provider_id) providersapikeys = self._get_config_field(u'providerapikeys') providersapikeys[provider_id_str] = apikey config = { u'providerid': provider_id_str, u'providerapikeys': providersapikeys } if not self._update_config(config): return False #restart speech recognition task self.__restart_speech_recognition_task() return True
def debug_script(self, script, event_name=None, event_values=None): """ Launch script debugging. Script output will be send to message bus as event Args: script (string): script name event_name (string): event name event_values (dict): event values Raises: InvalidParameter """ if not self.__scripts.has_key(script): raise InvalidParameter(u'Unknown script "%s"' % script) path = os.path.join(Actions.SCRIPTS_PATH, script) if not os.path.exists(path): raise InvalidParameter(u'Script "%s" does not exist' % script) #TODO handle event debug = Action(os.path.join(Actions.SCRIPTS_PATH, script), self.push, False, True) debug.start()
def set_volume(self, volume): """ Set volume Args: volume (int): volume value """ if volume is None: raise MissingParameter(u'Volume parameter is missing') if volume < 0 or volume > 100: raise InvalidParameter(u'Volume value must be 0..100') self.volume = volume
def save_script(self, script, editor, header, code): """ Save script content. If script name if not found, it will create new script Args: script (string): script name editor (string): editor name header (string): script header (header comments, may contains editor specific stuff) code (string): source code Returns: bool: True if script saved successfully Raises: MissingParameter: if parameter is missing CommandError: if error processing script """ if script is None or len(script)==0: raise InvalidParameter(u'Script parameter is missing') if editor is None or len(editor)==0: raise InvalidParameter(u'editor parameter is missing') if header is None: raise InvalidParameter(u'Header parameter is missing') if code is None: raise InvalidParameter(u'Code parameter is missing') #open script for writing path = os.path.join(Actions.SCRIPTS_PATH, script) self.logger.debug(u'Opening script: %s' % path) #fd = io.open(path, u'w', encoding=u'utf-8') content = u'# -*- coding: utf-8 -*-\n"""\neditor:%s\n%s\n"""\n%s' % (editor, header, code) #fd.write(content) #fd.close() self.cleep_filesystem.write_data(path, content, encoding='utf-8') #force script loading self.__load_scripts()
def set_lang(self, lang): """ Set tts lang Params: lang (string): tts lang (see TTS_LANGS) """ #check params if lang is None or len(lang) == 0: raise MissingParameter(u'Lang parameter is missing') if lang not in Sounds.TTS_LANGS.keys(): raise InvalidParameter(u'Specified lang "%s" is invalid' % lang) #save lang return self._set_config_field(u'lang', lang)
def disable_script(self, script, disabled): """ Enable/disable specified script Args: script (string): script name disable (bool): disable flag Raises: InvalidParameter: if parameter is invalid """ if not self.__scripts.has_key(script): raise InvalidParameter(u'Script not found') #enable/disable script scripts = self._get_config_field(u'scripts') scripts[script][u'disabled'] = disabled self._set_config_field(u'scripts', scripts) self.__scripts[script].set_disabled(disabled)
def add_sound(self, filepath): """ Add new sound Args: filepath (string): uploaded and local filepath Returns: bool: True if file uploaded successfully Raises: Exception, InvalidParameter """ #check parameters file_ext = os.path.splitext(filepath) self.logger.debug(u'Add sound of extension: %s' % file_ext[1]) if file_ext[1][1:] not in Sounds.ALLOWED_SOUND_EXTS: raise InvalidParameter( u'Invalid sound file uploaded (only %s are supported)' % ','.join(Sounds.ALLOWED_SOUND_EXTS)) #move file to valid dir if os.path.exists(filepath): name = os.path.basename(filepath) path = os.path.join(Sounds.MUSICS_PATH, name) self.logger.debug(u'Name=%s path=%s' % (name, path)) shutil.move(filepath, path) self.logger.info(u'Sound file "%s" uploaded successfully' % name) #once copied, try to bufferize file path = os.path.join(self.SOUNDS_PATH, sound[u'fullname']) if not self.__bufferize_sound(path): #invalid file, delete it self.delete_sound(sound[u'fullname']) raise Exception(u'Sound file format is not supported') else: #file doesn't exists self.logger.error(u'Sound file "%s" doesn\'t exist' % filepath) raise Exception(u'Sound file "%s" doesn\'t exists' % filepath) return True
def turn_off_leds(self, led1=True, led2=True, led3=True): """ Turn off leds Args: led1 (bool): True to turn off led1 led2 (bool): True to turn off led2 led3 (bool): True to turn off led3 """ if self.leds_driver is None: raise InvalidParameter(u'Driver is not installed') if led1: self.__set_led(0, self.LED_OFF) if led2: self.__set_led(1, self.LED_OFF) if led3: self.__set_led(2, self.LED_OFF) #show leds self.leds_driver.show()
def delete_music(self, fullname): """ Delete music Args: fullname (string): music file (with file extension) to delete Raises: InvalidParameter """ if fullname is None or len(fullname) == 0: raise MissingParameter(u'Fullname parameter is missing') #build filepath filepath = os.path.join(Sounds.MUSICS_PATH, fullname) #delete file if os.path.exists(filepath): os.remove(filepath) return True raise InvalidParameter(u'Invalid music file')
def turn_on_leds(self, led1=None, led2=None, led3=None): """ Turn on leds with specified color. None value does nothing on led Args: led1 (list): RGB<Brightness> list [0..255, 0..255, 0.255, <0..100>] led2 (list): RGB<Brightness> list [0..255, 0..255, 0.255, <0..100>] led3 (list): RGB<Brightness> list [0..255, 0..255, 0.255, <0..100>] """ if self.leds_driver is None: raise InvalidParameter(u'Driver is not installed') #led values checked in __set_led function if led1 is not None: self.__set_led(0, led1) if led2 is not None: self.__set_led(1, led2) if led3 is not None: self.__set_led(2, led3) #show leds self.leds_driver.show()
def remove_leds_profile(self, profile_uuid): """ Remove specified leds profile Args: profile_uuid (string): leds profile uuid """ #check parameters if self.__leds_profile_task is not None: raise CommandError( u'Leds profile is running. Please wait until end of it.') if profile_uuid is None or len(profile_uuid) == 0: raise MissingParameter(u'Parameter profile_uuid is missing') if profile_uuid.isdigit(): raise InvalidParameter(u'You can\'t delete default leds profiles') #get profile found = False leds_profiles = self._get_config_field(u'leds_profiles') for profile in leds_profiles: if profile[u'uuid'] == profile_uuid: #profile found, remove it found = True leds_profiles.remove(profile) break #check found if not found: self.logger.error(u'Unable to remove profile with uuid %s' % profile_uuid) raise CommandError(u'Unable to remove profile') #save config if not self._set_config_field(u'leds_profiles', leds_profiles): raise CommandError(u'Unable to save config') return True
def play_sound(self, fullname): """ Play sound. Multiple sound can be played simultaneously Args: fullname (string): sound file to play """ if fullname is None or len(fullname) == 0: raise MissingParameter(u'Parameter fullname is missing') #build filepath filepath = os.path.join(Sounds.SOUNDS_PATH, fullname) #check file validity if not os.path.exists(filepath): #invalid file specified raise InvalidParameter(u'Specified sound file "%s" is invalid' % fullname) if fullname not in self.sounds_buffer.keys(): raise CommandError(u'Unable to play sound: sound "%s" not found') #play sound self.sounds_buffer[fullname].set_volume(float(self.volume) / 100.0) self.sounds_buffer[fullname].play()
def play_music(self, fullname, force=False): """ Play specified file. Only one music can be played at once, use force to stop current playback Args: fullname (string): music file to play force (bool): force playing music and stop currently playing music Raises: Exception, InvalidParameter """ if fullname is None or len(fullname) == 0: raise MissingParameter(u'Parameter fullname is missing') #build filepath filepath = os.path.join(Sounds.MUSICS_PATH, fullname) #check file validity if not os.path.exists(filepath): #invalid file specified raise InvalidParameter(u'Specified music file "%s" is invalid' % fullname) #check if music is already playing if self.__music_thread != None and self.__music_thread.is_alive(): #music already is playing if not force: #rejct action raise Exception(u'Can\'t play 2 musics at the same time') else: #stop current music self.__music_thread.stop() #play music self.__music_thread = PlayMusic(filepath, self.volume) self.__music_thread.start()