def mark_completed(self): """ Mark a fulfilled quest complete to claim the reward. This will set the state of the quest to COMPLETED in the quest store. :raises QuestError: If the quest isn't ready to be marked complete. """ if self.is_completed(): return if self.is_fulfilled(): self._state = self.COMPLETED self._save_state() run_cmd('kdesk -a profile') for reward in self._rewards: n = reward.notification if n: display_generic_notification( n['title'], n['byline'], n['image'], n['command'] ) else: raise QuestError('Quest not ready to be completed.')
def copy_screenshot(filename): ''' Copies screenshot 'filename' into SCREENSHOT_PATH ''' ensure_dir(TMP_DIR) if os.path.isfile(filename): run_cmd("cp %s %s" % (filename, SCREENSHOT_PATH))
def reload_kernel_module(device_vendor='148f', device_product='5370', module='rt2800usb'): ''' If the Kano USB deviceID is connected to the system, reload the kernel module. Returns True if reloaded. Works silently and ok even if the module is not currently loaded in the kernel. FIXME: This procedure should be called prior to connect() to circumvent current kernel module random problems. ''' reloaded = False # Terminate wpa_supplicant daemon run_cmd('wpa_cli terminate') time.sleep(0.5) logger.info('wpa_cli has been terminated') _, _, rc = run_cmd('lsusb -d %s:%s' % (device_vendor, device_product)) if rc == 0: # The device id is matched, reload the kernel driver rc_load = 0 _, _, rc = run_cmd('rmmod "{}"'.format(module)) time.sleep(0.5) rc_load += rc _, _, rc = run_cmd('modprobe "{}"'.format(module)) time.sleep(5) rc_load += rc logger.info('Reloading wifi dongle kernel module "%s" for deviceID %s:%s rc=%d' % (module, device_vendor, device_product, rc_load)) if rc_load == 0: reloaded = True else: logger.info('Not reloading kernel module because device not found (%s:%s)' % (device_vendor, device_product)) return reloaded
def network_info(): out, _, _ = run_cmd('ip route show') network_dict = dict() for line in out.splitlines(): if line.startswith('default'): continue interface = line.split('dev ')[1].split()[0] data = dict() if interface.startswith('wlan'): command_network = "/sbin/iwconfig wlan0" out, _, _ = run_cmd(command_network) essid_match = re.match(r'.*ESSID:"(.*)"\ *$', out, re.MULTILINE) essid = essid_match.groups()[0] \ if essid_match else 'Wireless Network' data['ESSID'] = essid data['nice_name'] = 'Wireless: {}'.format(essid) else: data['nice_name'] = 'Ethernet' data['address'] = line.split('src ')[1].split()[0] network_dict[interface] = data return network_dict
def __init__(self, _win): self.win = _win # Launch pipeline if not os.path.exists(OVERSCAN_PIPE): run_cmd('mknod {} c 100 0'.format(OVERSCAN_PIPE)) # Get current overscan self.original_overscan = get_overscan_status() self.overscan_values = get_overscan_status() # Listen for key events self.win.connect("key-press-event", self.on_key_press) # Create UI self.template = Template( img_path=os.path.join(MEDIA_DIR, "display_test2.png"), title="Use UP and DOWN keys", description="Stretch or shrink your screen, until the white " \ "lines are lined up with the edges", button1_text="CONTINUE", orange_button_text="Reset" ) self.template.kano_button.connect("button_release_event", self.apply_changes) self.template.kano_button.connect("key_release_event", self.apply_changes) self.template.orange_button.connect("button_release_event", self.reset) self.win.set_main_widget(self.template) self.template.kano_button.grab_focus() self.win.show_all()
def is_connected(iface): ''' Returns details on which wireless network we are currently associated. The linked variable tells us if Internet is reachable. ''' essid = mode = ap = None linked = False out, err, _ = run_cmd("iwgetid %s --raw" % iface) essid = out.strip() out, err, _ = run_cmd("iwgetid %s --raw --ap" % iface) ap = out.strip() # mode 2 = Managed out, err, _ = run_cmd("iwgetid %s --raw --mode" % iface) out = out.strip() if out == '2': mode = 'Managed' else: mode = out # Association status can be queried via ifplugstatus, # but we are returning linked=True if Internet is actually up. linked = is_internet() return (essid, mode, ap, linked)
def get_mem_stats(): """ Get information about memory usage """ mem_stats = '' out, _, _ = run_cmd('free --human --lohi --total') mem_stats += out + '\n' out, _, _ = run_cmd('vcgencmd get_mem arm') mem_stats += out out, _, _ = run_cmd('vcgencmd get_mem gpu') mem_stats += out out, _, _ = run_cmd('vcgencmd get_mem reloc') mem_stats += out out, _, _ = run_cmd('vcgencmd get_mem reloc_total') mem_stats += out out, _, _ = run_cmd('vcgencmd get_mem malloc') mem_stats += out out, _, _ = run_cmd('vcgencmd get_mem malloc_total') mem_stats += out + '\n' out, _, _ = run_cmd('vcgencmd mem_reloc_stats') mem_stats += out + '\n' out, _, _ = run_cmd('cat /proc/meminfo') mem_stats += out + '\n' out, _, _ = run_cmd('ps -eo pmem,args --no-headers --sort -pmem') mem_stats += out return mem_stats
def install_app(app, sudo_pwd=None, gui=True): pkgs = " ".join(app["packages"] + app["dependencies"]) cmd = "" if gui: cmd = "rxvt -title 'Installing {}' -e bash -c ".format(app["title"]) if sudo_pwd: cleanup_cmd = "echo {} | sudo -S dpkg --configure -a".format(sudo_pwd) update_cmd = "echo {} | sudo -S apt-get update".format(sudo_pwd) run = "echo {} | sudo -S apt-get install -y {}".format(sudo_pwd, pkgs) else: cleanup_cmd = "sudo dpkg --configure -a".format(sudo_pwd) update_cmd = "sudo apt-get update".format(sudo_pwd) run = "sudo apt-get install -y {}".format(pkgs) if gui: run = "'{}'".format(run) cmd += run # make sure there are no broken packages on the system run_cmd(cleanup_cmd) run_cmd(update_cmd) os.system(cmd) done = True installed_packages = get_dpkg_dict()[0] for pkg in app["packages"] + app["dependencies"]: if pkg not in installed_packages: done = False break return done
def set_to_HDMI(HDMI): if not hdmi_supported: HDMI = False # 1 analog # 2 hdmi # These are the changes we'll apply if they have changed from what they were if HDMI: amixer_cmd = amixer_set_cmd.format(value=hdmi_value) set_config_value("hdmi_ignore_edid_audio", None) set_config_value("hdmi_drive", 2) config = "HDMI" else: amixer_cmd = amixer_set_cmd.format(value=analogue_value) set_config_value("hdmi_ignore_edid_audio", 1) set_config_value("hdmi_drive", None) config = "Analogue" # Set audio path in amixer o, e, rc = run_cmd(amixer_cmd) if rc: logger.warn("error from amixer: {} {} {}".format(o, e, rc)) # trigger alsa-utils to store the path in /var/lib/alsa/asound.state o, e, rc = run_cmd(store_cmd) if rc: logger.warn("error from alsa-utils: {} {} {}".format(o, e, rc)) set_setting('Audio', config)
def print_themes(show_default=True, terminate=True): # List of default themes default_themes = "{{3Default themes}}: " for l in DEFAULT_THEMES: default_themes += '{{2' + l + "}} | " default_themes = default_themes[:-2] # List of custom themes custom_themes = "{{3Custom themes}}: " theme_list = update_theme_list() for l in theme_list: # Remove .xml extension l = os.path.splitext(l)[0] custom_themes += '{{2' + l + "}} | " custom_themes = custom_themes[:-2] # Print info default_themes, _, _ = run_cmd('colour_echo "%s"' % default_themes) custom_themes, _, _ = run_cmd('colour_echo "%s"' % custom_themes) # Print default themes print "\n" if show_default: print " " + default_themes.strip('\n') # Print custom themes print " " + custom_themes.strip('\n') + '\n' if terminate: exit(2)
def network_info(): out, _, _ = run_cmd("ip route show") network_dict = dict() for line in out.splitlines(): if line.startswith("default"): continue interface = line.split("dev ")[1].split()[0] data = dict() if interface.startswith("wlan"): command_network = "/sbin/iwconfig wlan0" out, _, _ = run_cmd(command_network) essid_match = re.match(r'.*ESSID:"(.*)"\ .*', out, re.MULTILINE) essid = essid_match.groups()[0] if essid_match else "Wireless Network" data["ESSID"] = essid data["nice_name"] = "Wireless: {}".format(essid) else: data["nice_name"] = "Ethernet" data["address"] = line.split("src ")[1].split()[0] network_dict[interface] = data return network_dict
def set_overscan_status(overscan_values): top = overscan_values['top'] bottom = overscan_values['bottom'] left = overscan_values['left'] right = overscan_values['right'] cmd = 'overscan {} {} {} {}'.format(top, bottom, left, right) run_cmd(cmd)
def first_scene(self): self._ctl.main_window.hide() while Gtk.events_pending(): Gtk.main_iteration() run_cmd('kdesk -w') run_cmd('sudo kano-settings first-boot-set-wallpaper') self._ctl.main_window.show() self.next_stage()
def kill_apps(): # since kano-updater is run as root, need to inform # kanolauncher about user user = get_user_unsudoed() home = os.path.join('/home/', user) variables = 'HOME={} USER={}'.format(home, user) run_cmd('{} /usr/bin/kano-launcher /bin/true kano-kill-apps'.format( variables))
def __init__(self): # The command below initialises the overscan pipe as root # TODO: This would be nice to refactor. run_cmd('sudo kano-init-flow-system-tool init-overscan-pipe') self._enabled = True self._step = 10 self._original = get_overscan_status() self._current = get_overscan_status()
def get_edid(): file_path = os.path.join(TMP_DIR, 'edid.dat') cmd = "tvservice -d {}".format(file_path) run_cmd(cmd) try: dat = read_file_contents(file_path) delete_file(file_path) return dat except: return "EMPTY"
def trigger_event(self, event_name): refresh_kdesk = False if event_name in self._event_map: for q in self._event_map[event_name]: not_fulfilled_before = q.state == Quest.ACTIVE if not_fulfilled_before == q.is_fulfilled(): refresh_kdesk = True if refresh_kdesk: run_cmd('kdesk -a profile')
def save_changes(self): if self._original != self._current: cmd_template = ("sudo kano-init-flow-system-tool write-overscan " + "{} {} {} {}") run_cmd(cmd_template.format( self._current['top'], self._current['left'], self._current['right'], self._current['bottom'], ))
def get_metadata_archive(): ''' It creates a file (ARCHIVE_NAME) with all the information Returns the file ''' ensure_dir(TMP_DIR) file_list = [ {'name': 'kanux_version.txt', 'contents': get_version()}, {'name': 'process.txt', 'contents': get_processes()}, {'name': 'packages.txt', 'contents': get_packages()}, {'name': 'dmesg.txt', 'contents': get_dmesg()}, {'name': 'syslog.txt', 'contents': get_syslog()}, {'name': 'cmdline.txt', 'contents': read_file_contents('/boot/cmdline.txt')}, {'name': 'config.txt', 'contents': read_file_contents('/boot/config.txt')}, {'name': 'wifi-info.txt', 'contents': get_wifi_info()}, {'name': 'usbdevices.txt', 'contents': get_usb_devices()}, # TODO: Remove raw logs when json ones become stable {'name': 'app-logs.txt', 'contents': get_app_logs_raw()}, {'name': 'app-logs-json.txt', 'contents': get_app_logs_json()}, {'name': 'hdmi-info.txt', 'contents': get_hdmi_info()}, {'name': 'xorg-log.txt', 'contents': get_xorg_log()}, {'name': 'cpu-info.txt', 'contents': get_cpu_info()}, {'name': 'lsof.txt', 'contents': get_lsof()}, {'name': 'content-objects.txt', 'contents': get_co_list()} ] # Include the screenshot if it exists if os.path.isfile(SCREENSHOT_PATH): file_list.append({ 'name': SCREENSHOT_NAME, 'contents': read_file_contents(SCREENSHOT_PATH) }) # create files for each non empty metadata info for file in file_list: if file['contents']: write_file_contents(TMP_DIR + file['name'], file['contents']) # Collect all coredumps, for applications that terminated unexpectedly for f in os.listdir('/var/tmp/'): if f.startswith('core-'): file_list.append({ 'name': f, 'contents': read_file_contents(os.path.join('/var/tmp', f)) }) # archive all the metadata files # need to change dir to avoid tar subdirectories current_directory = os.getcwd() os.chdir(TMP_DIR) run_cmd("tar -zcvf {} *".format(ARCHIVE_NAME)) # open the file and return it archive = open(ARCHIVE_NAME, 'rb') # restore the current working directory os.chdir(current_directory) return archive
def set_chromium(enable, host=None, port=None): if enable: proxy_type = 'http' strflags = '"--password-store=detect --proxy-server="{}:\/\/{}:{}""'.format(proxy_type, host, port) else: strflags = '"--password-store=detect"' cmd = "/bin/sed -i 's/CHROMIUM_FLAGS=.*/CHROMIUM_FLAGS={}/g' {}".format(strflags, chromium_cfg) run_cmd(cmd) return
def get_dmesg(): ''' Returns a string with dmesg and uptime info ''' cmd_dmesg = "dmesg" cmd_uptime = "uptime" d, _, _ = run_cmd(cmd_dmesg) t, _, _ = run_cmd(cmd_uptime) t = 'system uptime: %s' % t return '%s\n%s' % (d, t)
def try_connect(): ''' Returns internet status. If connection fails the first time, the WiFi config will be launched ''' if is_internet(): return True run_cmd('sudo /usr/bin/kano-settings 12', localised=True) return is_internet()
def install_locale(locale): locale = ensure_utf_locale(locale) if not is_locale_valid(locale): print 'locale not valid', locale return False enforce_root(_('You need to be root to change install a locale')) genfile_locale = standard_locale_to_genfile_entry(locale) sed(r'^# ({})'.format(genfile_locale), r'\1', LOCALE_GEN_FILE) run_cmd('locale-gen')
def get_hdmi_info(): ''' Returns a string with Display info ''' # Current resolution cmd = "tvservice -s" o, _, _ = run_cmd(cmd) res = 'Current resolution: {}\n\n'.format(o) # edid file file_path = os.path.join(TMP_DIR, 'edid.dat') cmd = "tvservice -d {} && edidparser {}".format(file_path, file_path) edid, _, _ = run_cmd(cmd) delete_file(file_path) return res + edid
def launch_project(app, filename, data_dir, background=False): # This is necessary to support the new official names # TODO: once the apps have been renamed this will not be necessary name_translation = { 'make-art': 'kano-draw', 'terminal-quest': 'linux-story' } app_tr = name_translation.get(app, app) logger.info("launch_project: {} {} {}".format(app_tr, filename, data_dir)) app_profiles = read_json(app_profiles_file) # XML file with complete pathname fullpath = os.path.join(data_dir, filename) # Prepare the command line to open the app with the new project try: cmd = (app_profiles[app_tr]['cmd'] .format(fullpath=fullpath, filename=filename)) except KeyError as exc: logger.warn( "Can't find app '{}' in the app profiles - [{}]" .format(app_tr, exc) ) raise ValueError(_("App '{}' not available").format(app_tr)) # Try to load the project if the app is already running, via a signal. _, _, rc = run_cmd('/usr/bin/kano-signal launch-share {}'.format(fullpath)) if rc: # Likely the app is not running and the signal could not be sent, so start it now logger.warn("Error sending launch signal, starting the app now, rc={}".format(rc)) if background: # TODO: After migrating to launching apps via systemd, shares for make-snake # stopped launching from KW. Created a special case here to avoid # fixing the make-snake cmd through systemd temporarily. FIX THIS. if app == 'make-snake': run_bg(cmd) else: run_cmd('systemd-run --user {cmd}'.format(cmd=cmd)) else: _, _, rc = run_print_output_error(cmd) return rc else: logger.info("Sent signal to app: {} to open : {}".format(app_tr, fullpath)) return 0
def get_status(): status = dict() status_str, _, _ = run_cmd(tvservice_path + ' -s') if 'DMT' in status_str: status['group'] = 'DMT' elif 'CEA' in status_str: status['group'] = 'CEA' else: logger.error('status parsing error') return status['mode'] = int(status_str.split('(')[1].split(')')[0].strip()) status['full_range'] = 'RGB full' in status_str status['overscan'] = not ( get_config_value('disable_overscan') == 1 and get_config_value('overscan_top') == 0 and get_config_value('overscan_bottom') == 0 and get_config_value('overscan_left') == 0 and get_config_value('overscan_right') == 0 ) res, hz = status_str.split(',')[1].split('@') status['resolution'] = res.strip() status['hz'] = float(hz.strip()[:-2]) return status
def restore_lxpanel_configuration(self): userid = os.getuid() groupid = os.getgid() original_lxpanel_path = '/etc/skel/.config/lxpanel/' user_lxpanel_path = os.path.join('/home/' + os.getenv('SUDO_USER'), '.config/lxpanel') # remove the current local copy shutil.rmtree(user_lxpanel_path, ignore_errors=True) # re-create the copy from the skeleton shutil.copytree(original_lxpanel_path, user_lxpanel_path, symlinks=False, ignore=None) for root, dirs, files in os.walk(user_lxpanel_path): for name in files: os.chown(os.path.join(root, name), userid, groupid) run_cmd('lxpanelctl restart')
def take_screenshot(): ''' Takes a screenshot and saves it into SCREENSHOT_PATH ''' ensure_dir(TMP_DIR) cmd = "kano-screenshot -w 1024 -p " + SCREENSHOT_PATH _, _, rc = run_cmd(cmd)
def getRawData(interface, iwlist=None): ''' Runs iwlist and gets WiFi data in a string Developped, tested with Wireless Extension v29 English translation, Nov 2007 If iwlist points to a file, you can mimic iwlist from a response file for testing ''' # Make sure the wlan interface is up, otherwise the network scan will not proceed run_cmd('ifconfig %s up' % interface) if iwlist: outdata = open(iwlist, 'r').read() else: # Contemplate those seldom cases where the dongle driver returns an empty list cstring = "iwlist " + interface + " scan" outdata, _, _ = run_cmd(cstring) return outdata
def get_networks_info(): ''' Returns a string with ifconfig info ''' cmd = "/sbin/ifconfig" o, _, _ = run_cmd(cmd) return o
def do_final_stage(flow_params): init_status = Status.get_instance() clear_screen() reconfigure_autostart_policy() # Force autologin for this user until he goes through the graphic # init flow. At the end of it, kano-uixinit should call kano-init # to finalise the process and switch the kit to multiuser. set_ldm_autologin(init_status.username) init_status.stage = Status.UI_INIT_STAGE init_status.save() # Start Lightdm with a splash screen if available, # Or do it the classy way otherwise (soft dependency). if os.path.isfile('/usr/bin/kano-dashboard-lightdm'): run_cmd('/usr/bin/kano-dashboard-lightdm') else: start_lightdm()
def read_edid(): edid_dat_path = '/tmp/edid.dat' delete_file(edid_dat_path) edid_txt, _, rc = run_cmd('{0} -d {1} && edidparser {1}'.format( tvservice_path, edid_dat_path)) edid_txt = edid_txt.splitlines() if rc != 0: logger.error("error getting edid dat") return delete_file(edid_dat_path) return edid_txt
def set_to_HDMI(HDMI, force=False): ''' Set audio output to HDMI if supported by the display, otherwise set it to Analogue output. Returns 'HDMI' or 'Analogue', whichever was applied. ''' if not is_hdmi_audio_supported() and not force: HDMI = False # 1 analog # 2 hdmi # These are the changes we'll apply if they have changed from what they were if HDMI: amixer_cmd = hdmi_cmd set_config_value('hdmi_ignore_edid_audio', None) set_config_value('hdmi_drive', 2) config = _("HDMI") else: amixer_cmd = analogue_cmd set_config_value('hdmi_ignore_edid_audio', 1) set_config_value('hdmi_drive', None) config = _("Analogue") end_config_transaction() # Set audio path in amixer o, e, rc = run_cmd(amixer_cmd) if rc: logger.warn("error from amixer: {} {} {}".format(o, e, rc)) # trigger alsa-store to store the path in /var/lib/alsa/asound.state o, e, rc = run_cmd(store_cmd) if rc: logger.warn("error from alsa-store: {} {} {}".format(o, e, rc)) set_setting('Audio', config) return config
def get_video_file_url(video_url): try: logger.info('Starting youtube-dl with url: %s ' % video_url) cmd_youtube = 'youtube-dl -g "{}" {}'.format(video_url, proxy_arg) output, error, rc = run_cmd(cmd_youtube) logger.info('youtube-dl returns with rc=%d' % rc) output = output.strip('\n') assert (rc == 0) return True, output except: return False, error