From 946ec81206003efe50568a5d3b17da93faa2de8f Mon Sep 17 00:00:00 2001 From: flatsiedatsie Date: Fri, 17 Nov 2023 22:09:22 +0100 Subject: [PATCH] Add files via upload --- css/extension.css | 85 +++++++++- js/extension.js | 256 +++++++++++++++++++++--------- manifest.json | 2 +- pkg/candleappstore_adapter.py | 185 ++++++++++++++------- pkg/candleappstore_api_handler.py | 22 ++- views/content.html | 18 ++- 6 files changed, 420 insertions(+), 148 deletions(-) diff --git a/css/extension.css b/css/extension.css index 7b27683..a53769d 100755 --- a/css/extension.css +++ b/css/extension.css @@ -357,6 +357,17 @@ text-transform: capitalize; } + +.extension-candleappstore-addon-size{ + display:none; + font-style:italic; +} +.extension-candleappstore-low-disk-space .extension-candleappstore-addon-size, +.developer .extension-candleappstore-addon-size{ + display:inline; +} + +.extension-candleappstore-addon-size, .extension-candleappstore-basic-version{ margin-left:1rem; opacity:.5; @@ -364,6 +375,11 @@ font-size:1.6rem; } +.extension-candleappstore-addon-size:after{ + content:"Mb"; + font-style:italic; +} + .extension-candleappstore-selected-author:before{ content:"By "; @@ -400,6 +416,69 @@ } +/* Low disk space and low memory warning */ + +#extension-candleappstore-disk-space{ + display:none; + text-align:center; + padding:4rem 0; + box-sizing:border-box; +} +#extension-candleappstore-low-disk-space-hint{ + display:none; + margin-bottom:2rem; +} +.extension-candleappstore-low-memory-warning, +#extension-candleappstore-disk-space > div{ + display:inline-block; + line-height:3rem; + font-weight:bold; + padding:2rem; + border-radius:.5rem; + background-color:#c57f00; +} +.extension-candleappstore-low-disk-space #extension-candleappstore-disk-space > div{ + background-color:#c57f00; +} + +.extension-candleappstore-low-disk-space #extension-candleappstore-disk-space, +.developer #extension-candleappstore-disk-space{ + display:block; +} +.extension-candleappstore-low-disk-space #extension-candleappstore-low-disk-space-hint{ + display:block; +} + +.extension-candleappstore-low-memory-warning{ + display:none; + text-align:center; + width:100%; + margin: 2rem 0; + box-sizing:border-box; +} +.extension-candleappstore-low-memory-warning > div{ + max-width:33rem; + display:inline-block; +} +#extension-candleappstore-overview-available-memory:not(:empty), +#extension-candleappstore-install-available-memory:not(:empty){ + display:block; + margin-top:2rem; +} + +.extension-candleappstore-low-memory #extension-candleappstore-install-low-memory-warning{ + display:block; +} + +.extension-candleappstore-very-low-memory #extension-candleappstore-install-low-memory-warning, +.extension-candleappstore-very-low-memory #extension-candleappstore-overview-low-memory-warning{ + display:block; + background-color:red; +} +#extension-candleappstore-overview-low-memory-warning{ + margin-bottom:6rem; +} + /* SELECTED */ #extension-candleappstore-selected{ @@ -463,7 +542,7 @@ .extension-candleappstore-settings-left{ margin-right:2rem; min-width:150px; - max-width:75%; + max-width:calc(75% - 1rem); } @@ -2089,6 +2168,10 @@ body:not(.developer) #extension-candleappstore-show-advanced-settings-button + d padding: 11rem 8rem 30vh 8rem; } + #extension-candleappstore-disk-space{ + padding:4rem; + } + } diff --git a/js/extension.js b/js/extension.js index 225ed62..f80f26d 100755 --- a/js/extension.js +++ b/js/extension.js @@ -39,6 +39,11 @@ this.addon_dirs = []; // reflects actual directories on the disk this.extensions = []; // holds all the data about installed addons data that extend the UI (css and js files) this.addon_defaults = {}; // holds addon settings defaults, loaded via the addon api (not available through window.API) + this.addon_sizes = {}; // holds sizes of addon directories on disk in bytes + this.total_addons_size = null; // total combined size of all addons + this.free_disk_space = null; + this.free_memory = null; + this.available_memory = null; this.extensions_list = []; this.selector = ""; this.username = ""; @@ -117,32 +122,6 @@ } - if(typeof body.bits != 'undefined'){ - this.bits = parseInt(body.bits); - if(this.debug){ - console.log("candle store debug: system bits: ", this.bits); - } - } - if(typeof body.python_version != 'undefined'){ - this.python_version = body.python_version; - if(this.debug){ - console.log("candle store debug: python_version: ", this.python_version); - } - } - if(typeof body.node_version != 'undefined'){ - this.node_version = body.node_version; - if(this.debug){ - console.log("candle store debug: node_version: ", this.node_version); - } - } - if(typeof body.addon_defaults != 'undefined'){ - this.addon_defaults = body.addon_defaults; - if(this.debug){ - console.log("candle store debug: addon_defaults: ", this.addon_defaults); - } - } - - // Show developer options if(typeof body.developer != 'undefined'){ @@ -171,10 +150,15 @@ } + // Parse most of the data + this.parse_body(body); + // Make sure menu button is always visible. Can be hidden if the user returns from a complex addon settings page using their browser's back button. //document.getElementById('menu-button').classList.remove('hidden'); + + }) .catch((e) => { @@ -185,6 +169,151 @@ + // A single place to parse various Api responses + parse_body(body){ + + if(typeof body.bits != 'undefined'){ + this.bits = parseInt(body.bits); + if(this.debug){ + console.log("candle store debug: system bits: ", this.bits); + } + } + if(typeof body.python_version != 'undefined'){ + this.python_version = body.python_version; + if(this.debug){ + console.log("candle store debug: python_version: ", this.python_version); + } + } + if(typeof body.node_version != 'undefined'){ + this.node_version = body.node_version; + if(this.debug){ + console.log("candle store debug: node_version: ", this.node_version); + } + } + if(typeof body.addon_defaults != 'undefined'){ + this.addon_defaults = body.addon_defaults; + if(this.debug){ + console.log("candle store debug: addon_defaults: ", this.addon_defaults); + } + } + if(typeof body.addon_sizes != 'undefined'){ + this.addon_sizes = body.addon_sizes; + if(this.debug){ + console.log("candle store debug: addon_sizes: ", this.addon_sizes); + } + } + if(typeof body.total_addons_size != 'undefined'){ + this.total_addons_size = body.total_addons_size; + if(this.debug){ + console.log("candle store debug: total_addons_size: ", this.total_addons_size); + } + } + if(typeof body.free_disk_space != 'undefined'){ + this.free_disk_space = body.free_disk_space; + if(this.debug){ + console.log("candle store debug: free_disk_space: ", this.free_disk_space); + } + } + if(typeof body.free_memory != 'undefined'){ // Not currently used + this.free_memory = body.free_memory; + if(this.debug){ + console.log("candle store debug: free_memory: ", this.free_memory); + } + } + if(typeof body.available_memory != 'undefined'){ + this.available_memory = body.available_memory; + if(this.debug){ + console.log("candle store debug: available_memory: ", this.available_memory); + } + } + + // UPDATE UI BASED ON UPDATED VALUES + + if(document.getElementById('extension-candleappstore-disk-space') != null){ + // Update low disk space class + console.log("this.free_disk_space: ", this.free_disk_space); + try{ + + if(this.free_disk_space != null && this.total_addons_size != null){ + + + const available_disk_mb = Math.round(this.free_disk_space/1000); + const addons_size_mb = Math.round(this.total_addons_size/1000); + + document.getElementById('extension-candleappstore-disk-space').innerHTML = '
Warning, the disk is getting full
Total addons size: ' + addons_size_mb + 'Mb
Available disk space: ' + available_disk_mb + 'Mb
'; + if(this.debug){ + console.log("candleappstore: available disk space in Mb: ", available_disk_mb); + } + if(this.free_disk_space < 1000000){ // less than a gigabyte of space remaning + if(this.debug){ + console.log("candleappstore: low disk space"); + } + document.getElementById('extension-candleappstore-content').classList.add('extension-candleappstore-low-disk-space'); + } + else{ + if(this.debug){ + console.log("candleappstore: enough disk space"); + } + document.getElementById('extension-candleappstore-content').classList.remove('extension-candleappstore-low-disk-space'); + } + + } + + } + catch(e){ + console.log("Error checking/setting low disk space indicator class: ", e); + } + + + // Update low memory indicator + console.log("this.available_memory: ", this.available_memory); + try{ + + if(this.available_memory != null){ + + const available_memory_mb = Math.round(this.available_memory/1000); + + document.getElementById('extension-candleappstore-overview-available-memory').innerText = 'Available memory: ' + available_memory_mb + 'Mb'; + document.getElementById('extension-candleappstore-install-available-memory').innerText = 'Available memory: ' + available_memory_mb + 'Mb'; + if(this.debug){ + console.log("candleappstore: available memory in Mb: ", available_memory_mb ); + } + if(this.available_memory < 250000){ // less than 250Mb remaining + if(this.debug){ + console.log("candleappstore: low memory."); + } + document.getElementById('extension-candleappstore-content').classList.add('extension-candleappstore-low-memory'); + + // Very low memory, less than 100mb + if(this.available_memory < 100000){ + if(this.debug){ + console.log("candleappstore: VERY low memory."); + } + document.getElementById('extension-candleappstore-content').classList.add('extension-candleappstore-very-low-memory'); + } + else{ + document.getElementById('extension-candleappstore-content').classList.remove('extension-candleappstore-very-low-memory'); + } + } + else{ + if(this.debug){ + console.log("candleappstore: enough available memory"); + } + document.getElementById('extension-candleappstore-content').classList.remove('extension-candleappstore-low-memory'); + document.getElementById('extension-candleappstore-content').classList.remove('extension-candleappstore-very-low-memory'); + } + + } + + } + catch(e){ + console.log("Error checking/setting low disk space indicator class: ", e); + } + } + + + } + // Compares the data from the internal API with the cloud data @@ -924,7 +1053,6 @@ }); - show_signup_button.addEventListener('click', (event) => { //console.log("show signup button clicked"); login_form.style.display = 'none'; @@ -944,7 +1072,6 @@ }); - signup_button.addEventListener('click', (event) => { //console.log("signup button clicked"); @@ -1764,6 +1891,8 @@ }; + // No longer used + /* remember_permission = (addon_id, permission, value) => { //const pre = document.getElementById('extension-candleappstore-response-data'); @@ -1795,15 +1924,11 @@ } }).catch((e) => { - //console.log("Error getting timer items: " + e.toString()); - //console.log("Error: " + e); - //pre.innerText = "remembering permission failed - connection error?"; - //return {}; myReject({}); }); }); } - + */ @@ -1955,11 +2080,11 @@ const search_text = document.getElementById('extension-candleappstore-filter-search-input').value; + // // UPDATE ADDONS // - //console.log('this.installed (from python): ', this.installed); output_list_element.innerHTML = ""; @@ -2034,7 +2159,6 @@ //console.log("Error getting extension value: ", e); } - const keys = Object.keys(data[i]); //console.log("keys: ", keys); @@ -2050,8 +2174,21 @@ if(page == 'installed' && info == 'name'){ text += '' + data[i]['version'] + ''; + + try{ + if(typeof this.addon_sizes[addon_id] != 'undefined'){ + let rounded_size = Math.round(0.5 + (this.addon_sizes[addon_id] / 1000) ); + text += '' + rounded_size + ''; + } + } + catch(e){ + console.log("Error adding addon size: ", e); + } + } + + t.innerHTML = text; const selector_name = '.extension-candleappstore-basic-' + info; @@ -2349,9 +2486,6 @@ console.log("init: get_installed_addons_data catch (error?):", e); }); - - - }).catch((e) => { //console.log("Error enabling/disabling addon: ", this_addon_id); @@ -2371,25 +2505,6 @@ alert("There is something wrong with this app. You could try re-installing it."); } - - /* - window.API.getAddonConfig( data[i]["addon_id"]) - .then((result) => { - //console.log("get addon config result: "); - //console.log(result); - //console.log(data[i]); - document.getElementById("extension-candleappstore-settings-title").innerText = data[i]["name"]; - this.show_addon_config(data[i]["addon_id"], result); - - }).catch((e) => { - //console.log("get addon config catch (error?)"); - //console.log(e); - //pre.innerText = e.toString(); - }); - */ - - - }); //console.log("adding play/pause button"); @@ -2429,27 +2544,6 @@ return; } - - /* - window.API.postJson( - `/extensions/candleappstore/api/ajax`, - {'action':'get_manifest','addon_id': data[i]["addon_id"] } - ).then((body) => { - //console.log("clear item reaction: "); - //console.log(body); - if( body['state'] != true ){ - //pre.innerText = body['message']; - } - else{ - this.show_selected_app(JSON.parse(body['body']), target.getAttribute('data-installed') ); // data, and whether it is installed already - } - - }).catch((e) => { - //console.log("candleappstore: error in clear device handler"); - //pre.innerText = e.toString(); - }); - */ - this.show_addon_config( event.target.getAttribute('data-addon-id') ); @@ -4603,8 +4697,12 @@ {'action':'get_installed_dirs'} ).then((body) => { + //console.log("get_installed_dirs response: ", body); if(body['state'] == true){ - this.addon_defaults = body.addon_defaults; + + // Update all the values in a central method + this.parse_body(body); + myResolve( body.addon_defaults ); } else{ diff --git a/manifest.json b/manifest.json index 5afd207..6b14734 100755 --- a/manifest.json +++ b/manifest.json @@ -55,7 +55,7 @@ } }, "short_name": "candleapps", - "version": "0.5.11", + "version": "0.5.12", "web_accessible_resources": [ "css/*.css", "images/*.svg", diff --git a/pkg/candleappstore_adapter.py b/pkg/candleappstore_adapter.py index 4bdeefb..a088dca 100755 --- a/pkg/candleappstore_adapter.py +++ b/pkg/candleappstore_adapter.py @@ -7,18 +7,12 @@ from __future__ import print_function import os -#from os import path import sys sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')) -#try: -# sys.path.append(os.path.join(os.sep,'home','pi','.webthings','addons','candleappstore','lib')) -#except: -# print("couldn't add extra path") + import re import json import time -#import queue -#import signal import socket #import asyncio #import logging @@ -29,13 +23,6 @@ from subprocess import call, Popen #from collections import namedtuple - -try: -# from .intentions import * -# print("succesfully imported intentions.py file") - pass -except Exception as ex: - print("ERROR loading intentions.py: " + str(ex)) from gateway_addon import Database, Adapter from .util import * @@ -43,10 +30,7 @@ #from .candleappstore_notifier import * try: - #from gateway_addon import APIHandler, APIResponse from .candleappstore_api_handler import * - print("CandleappstoreAPIHandler imported") - #pass except Exception as ex: print("Unable to load CandleappstoreAPIHandler (which is used for UI extention): " + str(ex)) @@ -81,39 +65,50 @@ def __init__(self, verbose=True): self.name = self.__class__.__name__ # CandleappstoreAdapter #print("self.name = " + str(self.name)) Adapter.__init__(self, self.addon_name, self.addon_name, verbose=verbose) - #print("Adapter ID = " + self.get_id()) - - #os.environ["LD_LIBRARY_PATH"] = os.path.join(self.user_profile['addonsDir'],self.addon_name,'snips') - - # Get initial audio_output options - #self.audio_controls = get_audio_controls() - #print("audio controls: " + str(self.audio_controls)) self.developer = False self.running = True self.app_store_url = 'https://www.candlesmarthome.com/appstore/' + self.boot_path = '/boot' + if os.path.exists('/boot/firmware'): + self.boot_path = '/boot/firmware' + # Exhibit mode self.exhibit_mode = False - if os.path.isfile('/boot/exhibit_mode.txt'): + if os.path.isfile(self.boot_path + '/exhibit_mode.txt'): self.exhibit_mode = True # Uninstall self.keep_data_on_uninstall = False - - # not available via window.API, so have to scrape addon settings defaults manually - self.addon_defaults = {} # holds all default settings from all addons manifest files + + self.addon_defaults = {} # addon defaults are not available via window.API, so have to scrape addon settings defaults manually from the manifest files + self.addon_sizes = {} # holds how big the addon directories are self.installed_addons = [] # simple directory names list of installed addons (including broken ones) - #print("os.uname() = " + str(os.uname())) + self.total_addons_size = None # will hold the total disk size of all the addons - # Some paths - #print("self.user_profile:") - #print(str(self.user_profile)) + # Disk space + self.user_partition_free_disk_space = None + # Total memory + self.total_memory = None + try: + total_memory = run_command("awk '/^MemTotal:/{print $2}' /proc/meminfo | tr -d '\n'") + self.total_memory = int( int(''.join(filter(str.isdigit, total_memory))) / 1000) + except Exception as ex: + print("Error: could not get total installed memory: " + str(ex)) + + # Available memory + self.free_memory = None #free memory is literally empty, while + self.available_memory = None # available memory can be freed up if need be + self.update_free_memory_and_disk_space() + + + + # Paths self.addon_path = os.path.join(self.user_profile['addonsDir'], self.addon_name) self.data_dir_path = os.path.join(self.user_profile['dataDir'], self.addon_name) - # Make sure the data directory exists try: if not os.path.isdir(self.data_dir_path): @@ -121,31 +116,19 @@ def __init__(self, verbose=True): print("data directory did not exist, created it now") except Exception as ex: print("Error: could not make sure data dir exists: " + str(ex)) - # Cached files paths self.cached_get_apps_path = os.path.join(self.data_dir_path,'get_apps.json') if os.path.exists(self.cached_get_apps_path): os.system('rm ' + str(self.cached_get_apps_path)) # start without a cached version - # determine the persistent data path - try: - self.persistence_file_path = os.path.join(self.data_dir_path, 'persistence.json') - if self.DEBUG: - print("self.persistence_file_path = " + str(self.persistence_file_path)) - except: - try: - print("setting persistence file path failed, will try older method.") - self.persistence_file_path = os.path.join(os.path.expanduser('~'), '.webthings', 'data', 'candleappstore','persistence.json') - except: - print("Double error making persistence file path") - self.persistence_file_path = "/home/pi/.webthings/data/candleappstore/persistence.json" - - - + self.persistence_file_path = os.path.join(self.data_dir_path, 'persistence.json') + if self.DEBUG: + print("self.persistence_file_path = " + str(self.persistence_file_path)) - # Get persistent data + + # Get persistent data self.persistent_data = {} first_run = False try: @@ -185,8 +168,12 @@ def __init__(self, verbose=True): # if self.DEBUG: # print("addons was not in persistent data, adding it now.") # self.persistent_data['addons'] = {} + + # Permisisons not currently used anymore? if 'permissions' not in self.persistent_data: self.persistent_data['permissions'] = {} + + # should be used to find out of the candle webserver has fresh addon updates, but is unfinished if 'meta_updated_time' not in self.persistent_data: self.persistent_data['meta_updated_time'] = 0 @@ -201,6 +188,8 @@ def __init__(self, verbose=True): except Exception as ex: print("Error loading config: " + str(ex)) + self.DEBUG = True + #self.ssid = self.candleappstore_name + " " + self.persistent_data['unique_id'] + "_nomap" #print("ssid = " + str(self.ssid)) @@ -218,17 +207,17 @@ def __init__(self, verbose=True): print("Failed to start API handler (this only works on gateway version 0.10 or higher). Error: " + str(e)) - # create or remove developer.txt from /boot + # create or remove developer.txt from boot partition if self.developer: if self.DEBUG: print("creating developer.txt file") - os.system('sudo touch /boot/developer.txt') + os.system('sudo touch ' + str(self.boot_path) + '/developer.txt') os.system('sudo systemctl start rsyslog.service') else: - if os.path.isfile('/boot/developer.txt'): + if os.path.isfile(self.boot_path + '/developer.txt'): if self.DEBUG: print("removing developer.txt file") - os.system('sudo rm /boot/developer.txt') + os.system('sudo rm ' + str(self.boot_path) + '/developer.txt') @@ -277,11 +266,20 @@ def __init__(self, verbose=True): print("Current working directory: " + str(os.getcwd())) print("End of candle app store adapter init") + print("doing scans") + # Find out which addons are really installed, and what their default settings are self.scan_installed_addons() - self.ready = True + # find out how big the addon directories are + if not self.DEBUG: + time.sleep(5) + self.scan_addons_file_size() + self.ready = True + + + # # GET CONFIG # @@ -311,7 +309,6 @@ def add_from_config(self): #print(str(config)) if 'Debugging' in config: - print("-Debugging was in config") self.DEBUG = bool(config['Debugging']) if self.DEBUG: print("Debugging enabled") @@ -323,7 +320,6 @@ def add_from_config(self): self.keep_data_on_uninstall = bool(config['Keep addon data when uninstalling']) - if 'Show developer options' in config: if self.DEBUG: print("-Developer preference was in config: " + str(config['Show developer options'])) @@ -383,7 +379,12 @@ def add_from_config(self): print("Error loading api token from settings: " + str(ex)) + # returns list of installed addons by scanning addons directory. + # Also grabs default addon settings from manifest files def scan_installed_addons(self): + start_time = time.time() + if self.DEBUG: + print("in scan_installed_addons") real_dirs = [] new_default_settings = {} #if self.DEBUG: @@ -394,6 +395,7 @@ def scan_installed_addons(self): if os.path.isdir( os.path.join(self.user_profile['addonsDir'],filename) ): real_dirs.append(filename) + # get default addon settings from manifest file try: manifest_path = os.path.join(self.user_profile['addonsDir'],filename,'manifest.json') #print("manifest_path: " + str(manifest_path)) @@ -428,9 +430,76 @@ def scan_installed_addons(self): self.addon_defaults = new_default_settings #print("self.addon_defaults: " + str(self.addon_defaults)) + # also update how much memory is available + self.update_free_memory_and_disk_space() + + end_time = time.time() + if self.DEBUG: + print("scan_installed_addons: time taken: " + str(end_time - start_time)) + return real_dirs - + + # Find out how big the addons are + def scan_addons_file_size(self): + start_time = time.time() + + if self.DEBUG: + print("in scan_addons_file_size") + + file_sizes = shell('du ' + str(self.user_profile['addonsDir']) + ' --max-depth=1') + for line in file_sizes.splitlines(): + try: + line_parts1 = line.split('\t') + line_parts2 = line.split('addons/') + + if len(line_parts1) > 1 and len(line_parts2) > 1: + self.addon_sizes[ line_parts2[1] ] = int( line_parts1[0] ) + elif len(line_parts1) > 0 and line.endswith('/addons'): + self.total_addons_size = int( line_parts1[0] ) + + except Exception as ex: + print("Error parsing addon file size scan line: " + str(ex)) + + if self.DEBUG: + print("self.addon_sizes: " + str(self.addon_sizes) ) + print("self.total_addons_size: " + str(self.total_addons_size)) + + # also update how much memory is available + self.update_free_memory_and_disk_space() + + end_time = time.time() + if self.DEBUG: + print("scan_addons_file_size: time taken: " + str(end_time - start_time)) + + + def update_free_memory_and_disk_space(self): + if self.DEBUG: + print("in update_free_memory_and_disk_space") + try: + # Available disk space + self.user_partition_free_disk_space = int(shell("df /home/pi/.webthings | awk 'NR==2{print $4}' | tr -d '\n'")) + + # Check free memory + free_memory = subprocess.check_output(['grep','^MemFree','/proc/meminfo']) + free_memory = free_memory.decode('utf-8') + self.free_memory = int( int(''.join(filter(str.isdigit, free_memory))) / 1000) + if self.DEBUG: + print("free_memory: " + str(free_memory)) + + # Check available memory + available_memory = subprocess.check_output("free | grep Mem:", shell=True) + available_memory = available_memory.decode('utf-8') + available_memory_parts = available_memory.split() + available_memory = available_memory_parts[-1] + self.available_memory = int( int(''.join(filter(str.isdigit, available_memory)))) + if self.DEBUG: + print("available_memory: " + str(available_memory)) + + except Exception as ex: + print("Error getting memory / free user partition disk space: " + str(ex)) + + def remove_thing(self, device_id): try: obj = self.get_device(device_id) diff --git a/pkg/candleappstore_api_handler.py b/pkg/candleappstore_api_handler.py index 8ca7972..52f2f29 100755 --- a/pkg/candleappstore_api_handler.py +++ b/pkg/candleappstore_api_handler.py @@ -118,15 +118,21 @@ def handle_request(self, request): #'addons': self.adapter.persistent_data['addons'], # doesn't seem used by anything 'meta_updated_time': self.adapter.persistent_data['meta_updated_time'], 'app_store_url':self.adapter.app_store_url, - 'installed':self.adapter.installed_addons, - 'permissions':self.adapter.persistent_data['permissions'], + 'permissions':self.adapter.persistent_data['permissions'], # doesn't seem used anymore 'developer':self.adapter.developer, 'exhibit_mode':self.adapter.exhibit_mode, 'bits':self.adapter.bits, 'python_version':self.adapter.python_version, 'python_minor_version':self.adapter.python_minor_version, 'node_version':self.adapter.node_version, + 'installed':self.adapter.installed_addons, 'addon_defaults':self.adapter.addon_defaults, + 'addon_sizes':self.adapter.addon_sizes, + 'total_addons_size':self.adapter.total_addons_size, + 'free_disk_space':self.adapter.user_partition_free_disk_space, + 'total_memory':self.adapter.total_memory, + 'free_memory':self.adapter.free_memory, + 'available_memory':self.adapter.available_memory, 'debug':self.adapter.DEBUG }), ) @@ -252,6 +258,8 @@ def handle_request(self, request): addon_dirs = [] try: addon_dirs = self.adapter.scan_installed_addons() + self.adapter.scan_addons_file_size() + except Exception as ex: if self.DEBUG: print("Getting installed addon dirs error: " + str(ex)) @@ -259,7 +267,15 @@ def handle_request(self, request): return APIResponse( status=200, content_type='application/json', - content=json.dumps({'state':True, 'installed':addon_dirs, 'addon_defaults':self.adapter.addon_defaults }), + content=json.dumps({'state':True, + 'installed':addon_dirs, + 'addon_defaults':self.adapter.addon_defaults, + 'addon_sizes':self.adapter.addon_sizes, + 'total_addons_size':self.adapter.total_addons_size, + 'free_disk_space':self.adapter.user_partition_free_disk_space, + 'free_memory':self.adapter.free_memory, + 'available_memory':self.adapter.available_memory, + }), ) diff --git a/views/content.html b/views/content.html index a2fcb8f..dfa8b77 100755 --- a/views/content.html +++ b/views/content.html @@ -16,11 +16,8 @@

Candle Store

- -
-

A system update is available

@@ -28,6 +25,11 @@

Candle Store

+
+
Warning, your controller is very low on memory. This could cause instability. + +
+

Installed

@@ -37,6 +39,8 @@

Installed

+
+ @@ -241,9 +245,6 @@

Advanced setting
- - -
+
+
Warning, your controller is low on memory. Installing another addon could cause instability. + +
+