def tweak_power_led(self, enable): """ Tweak raspberry pi power led Note: Infos from https://www.jeffgeerling.com/blogs/jeff-geerling/controlling-pwr-act-leds-raspberry-pi Args: enable (bool): True to turn on led """ if not os.path.exists('/sys/class/leds/led1'): self.logger.info('Power led not found on this device') return raspi = Tools.raspberry_pi_infos() off_value = '0' if raspi['model'].lower().find('zero') else '1' on_value = '1' if raspi['model'].lower().find('zero') else '0' echo_value = on_value if enable else off_value console = Console() resp = console.command('echo %s > /sys/class/leds/led1/brightness' % echo_value) if resp['returncode'] != 0: raise CommandError('Error tweaking power led') # store led status self._set_config_field('enablepowerled', enable)
def _on_audio_registered(self): """ Audio driver registered """ self.asoundconf = EtcAsoundConf(self.cleep_filesystem) self.configtxt = ConfigTxt(self.cleep_filesystem) self.console = Console()
def download_documentation(self, module_name): """ Download documentation (html as archive tar.gz) Args: module_name (string): module name Returns: dict: archive infos:: { data: filepath filename: new filename } Raises: CommandError: command failed error """ self.logger.info('Download documentation html archive') cmd = self.CLI_DOCS_ZIP_PATH_CMD % (self.CLI, module_name) self.logger.debug('Doc zip path cmd: %s' % cmd) console = Console() res = console.command(cmd) if res['returncode'] != 0: raise CommandError(''.join(res['stdout'])) zip_path = res['stdout'][0].split('=')[1] self.logger.debug('Module "%s" docs path "%s"' % (module_name, zip_path)) return {'filepath': zip_path, 'filename': os.path.basename(zip_path)}
def build_application(self, module_name): """ Build application archive (zip format) Archive is not protected by password Args: module_name (string): module name Raises: Exception: if build failed """ cmd = self.CLI_BUILD_APP_CMD % (self.CLI, module_name) self.logger.debug('Build app cmd: %s' % cmd) console = Console() res = console.command(cmd, 60.0) self.logger.info('Build app result: %s | %s' % (res['stdout'], res['stderr'])) if res['returncode'] != 0: raise CommandError('Error building application. Check Cleep logs.') try: self.__last_application_build = json.loads(res['stdout'][0]) except Exception as error: self.logger.exception( 'Error parsing app build command "%s" output' % cmd) raise CommandError( 'Error building application. Check Cleep logs.') from error
def __cli_check(self, command, timeout=15.0): """ Execute cleep-cli check specified by command Args: command (string): cli command to execute Returns: dict: command output """ console = Console() res = console.command(command, timeout) self.logger.debug('Cli command "%s" output: %s | %s' % (command, res['stdout'], res['stderr'])) if res['returncode'] != 0: self.logger.exception('Command "%s"', command) raise CommandError('Command failed') try: return json.loads(''.join(res['stdout'])) except Exception as error: self.logger.exception('Error parsing command "%s" output' % command) raise CommandError( 'Error parsing check result. Check Cleep logs') from error
def create_application(self, module_name): """ Create new application skel Args: module_name (string): module name Raises: CommandError: if command failed """ self.__stop_watcher() cmd = self.CLI_NEW_APPLICATION_CMD % (self.CLI, module_name) self.logger.debug('Create app cmd: %s' % cmd) try: console = Console() res = console.command(cmd, 10.0) self.logger.info('Create app cmd result: %s %s' % (res['stdout'], res['stderr'])) if res['returncode'] != 0: raise CommandError( 'Error during application creation. Check Cleep logs.') # sync new app content console.command(self.CLI_SYNC_MODULE_CMD % module_name) finally: self.__start_watcher()
def restart_cleep(self, delay=3.0): """ Restart Cleep """ # backup configuration self.backup_cleep_config() # send event self.cleep_restart_event.send({'delay': delay}) # and restart cleep console = Console() console.command_delayed('/etc/cleep/cleephelper.sh restart', delay)
def poweroff_device(self, delay=5.0): """ Poweroff device """ # backup configuration self.backup_cleep_config() # send event self.device_poweroff_event.send({'delay': delay}) # and reboot system console = Console() console.command_delayed('poweroff', delay)
def reboot_device(self, delay=5.0): """ Reboot device """ # backup configuration self.backup_cleep_config() # send event self.device_reboot_event.send({'delay': delay}) # and reboot system console = Console() console.command_delayed('reboot', delay)
def _execute_command(self, sensor): # pragma: no cover """ Execute dht22 binary command Useful for unit testing """ console = Console() cmd = self.DHT22_CMD % sensor["gpios"][0]["pin"] self.logger.debug('Read DHT22 sensor values from command "%s"' % cmd) resp = console.command(cmd, timeout=11) self.logger.debug("Read DHT command response: %s" % resp) if resp['error'] or resp['killed']: self.logger.error("DHT22 command failed: %s" % resp) return json.loads(resp['stdout'][0])
def sync_time(): """ Synchronize device time using NTP server Note: This command may lasts some seconds Returns: bool: True if NTP sync succeed, False otherwise """ console = Console() resp = console.command("/usr/sbin/ntpdate-debian", timeout=60.0) return resp["returncode"] == 0
def tweak_activity_led(self, enable): """ Tweak raspberry pi activity led Args: enable (bool): True to turn on led """ if not os.path.exists('/sys/class/leds/led0'): self.logger.info('Activity led not found on this device') return raspi = Tools.raspberry_pi_infos() off_value = '0' if raspi['model'].lower().find('zero') else '1' on_value = '1' if raspi['model'].lower().find('zero') else '0' echo_value = on_value if enable else off_value console = Console() resp = console.command('echo %s > /sys/class/leds/led0/brightness' % echo_value) if resp['returncode'] != 0: raise CommandError('Error tweaking activity led') # store led status self._set_config_field('enableactivityled', enable)
def set_timezone(self): """ Set timezone according to coordinates Returns: bool: True if function succeed, False otherwise Raises: CommandError: if unable to save timezone """ # get position position = self._get_config_field("position") if not position["latitude"] and not position["longitude"]: self.logger.warning( "Unable to set timezone from unspecified position (%s)" % position) return False # compute timezone current_timezone = None try: # try to find timezone at position current_timezone = self.timezonefinder.timezone_at( lat=position["latitude"], lng=position["longitude"]) if current_timezone is None: # extend search to closest position # TODO increase delta_degree to extend research, careful it use more CPU ! current_timezone = self.timezonefinder.closest_timezone_at( lat=position["latitude"], lng=position["longitude"]) except ValueError: # the coordinates were out of bounds self.logger.exception("Coordinates out of bounds") except Exception: self.logger.exception( "Error occured searching timezone at position") if not current_timezone: self.logger.warning( "Unable to set device timezone because it was not found") return False # save timezone value self.logger.debug("Save new timezone: %s" % current_timezone) if not self._set_config_field("timezone", current_timezone): raise CommandError("Unable to save timezone") # configure system timezone zoneinfo = os.path.join(self.SYSTEM_ZONEINFO_DIR, current_timezone) self.logger.debug("Checking zoneinfo file: %s" % zoneinfo) if not os.path.exists(zoneinfo): raise CommandError('No system file found for "%s" timezone' % current_timezone) self.logger.debug('zoneinfo file "%s" exists' % zoneinfo) self.cleep_filesystem.rm(self.SYSTEM_LOCALTIME) self.logger.debug('Writing timezone "%s" in "%s"' % (current_timezone, self.SYSTEM_TIMEZONE)) if not self.cleep_filesystem.write_data(self.SYSTEM_TIMEZONE, "%s" % current_timezone): self.logger.error( 'Unable to write timezone data on "%s". System timezone is not configured!' % self.SYSTEM_TIMEZONE) return False # launch timezone update in background self.logger.debug("Updating system timezone") command = Console() res = command.command( "/usr/sbin/dpkg-reconfigure -f noninteractive tzdata", timeout=15.0) self.logger.debug("Timezone update command result: %s" % res) if res["returncode"] != 0: self.logger.error("Error reconfiguring system timezone: %s" % res["stderr"]) return False # TODO configure all wpa_supplicant.conf country code # propagate changes to cleep self.timezone = timezone(current_timezone) self._time_task() return True
def __kill_watchers(self): """ Kill all watchers instances """ console = Console() console.command('/usr/bin/pkill -9 -f "cleep-cli watch"')