Extension Manager, replacing loading of Partition Wizard (#23955)
This commit is contained in:
parent
8a5a12b48d
commit
f2006566d7
@ -23,6 +23,7 @@ All notable changes to this project will be documented in this file.
|
||||
- Extend state JSON message with functional hostname and ipaddress which could be WiFi or Ethernet
|
||||
- Berry multiplication between string and int (#23850)
|
||||
- Support for RX8030 RTC (#23855)
|
||||
- Extension Manager, replacing loading of Partition Wizard
|
||||
|
||||
### Breaking Changed
|
||||
- Berry `animate` framework is DEPRECATED, will be replace by `animation` framework (#23854)
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
var extension_manager = module("extension_manager")
|
||||
|
||||
#@ solidify:extension_manager
|
||||
@ -40,10 +39,10 @@ class Extension_manager
|
||||
# tapp_name(wd)
|
||||
#
|
||||
# Takes a working directory 'wd' and extract the name of the tapp file.
|
||||
# Ex: '/.extensions/Leds_Panel.tapp#' becomes 'Leds_Panel.tapp'
|
||||
# Ex: '/.extensions/Leds_Panel.tapp#' becomes 'Leds_Panel'
|
||||
#
|
||||
# @param wv: string - the Working Dir of the tapp file like '/.extensions/Leds_Panel.tapp#'
|
||||
# @return string - the raw name of the tapp file, like 'Leds_Panel.tapp'
|
||||
# @return string - the raw name of the tapp file, like 'Leds_Panel'
|
||||
#####################################################################################################
|
||||
static def tapp_name(wd)
|
||||
import string
|
||||
@ -113,6 +112,10 @@ class Extension_manager
|
||||
# Return a map of installed tap files, by tapp file name
|
||||
# tapp_name -> path {'Leds_Panel.tapp': '/.extensions/Leds_Panel.tapp'}
|
||||
#
|
||||
# Example:
|
||||
# > extension_manager.list_installed_ext()
|
||||
# {'Leds_Panel': '/.extensions/Leds_Panel.tapp', 'Partition_Wizard': '/.extensions/Partition_Wizard.tapp_'}
|
||||
#
|
||||
# @return map: tapp_namt -> full path (or wd)
|
||||
static def list_installed_ext()
|
||||
# Read extensions in file system
|
||||
@ -130,6 +133,10 @@ class Extension_manager
|
||||
#
|
||||
# List all extensions in file-system, whether they are running or not
|
||||
#
|
||||
# Example:
|
||||
# > extension_manager.list_extensions_in_fs()
|
||||
# {'Leds Panel': '/.extensions/Leds_Panel.tapp', 'Partition Wizard': '/.extensions/Partition_Wizard.tapp_'}
|
||||
#
|
||||
# @return sortedmap: with Name of App as key, and following map:
|
||||
# name, description, version (int), autorun (bool)
|
||||
static def list_extensions_in_fs()
|
||||
@ -195,19 +202,97 @@ class Extension_manager
|
||||
# all good, created successfully
|
||||
end
|
||||
|
||||
#####################################################################################################
|
||||
# run_stop_ext(tapp_fname, run_stop)
|
||||
#
|
||||
# @param tapp_fname : string - name of tapp file to install from repository (ex: "Leds_Panel")
|
||||
# @param run_stop : bool - `true` to run , `false` to stop
|
||||
# @return bool - `true` if success
|
||||
static def run_stop_ext(tapp_fname, run_stop)
|
||||
# sanitize
|
||||
tapp_fname = _class.tapp_name(tapp_fname)
|
||||
|
||||
# get the path for actual file
|
||||
var tapp_path = _class.list_installed_ext().find(tapp_fname)
|
||||
if tapp_path != nil
|
||||
if run_stop
|
||||
return tasmota.load(tapp_path)
|
||||
else
|
||||
return tasmota.unload_extension(tapp_path)
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
#####################################################################################################
|
||||
# enable_disable_ext(tapp_fname, run_stop)
|
||||
#
|
||||
# @param tapp_fname : string - name of tapp file to enable or disable (ex: "Leds_Panel")
|
||||
# @param enable : bool - `true` to enable , `false` to disable
|
||||
# @return bool - `true` if success
|
||||
static def enable_disable_ext(tapp_fname, enable)
|
||||
import string
|
||||
# sanitize
|
||||
tapp_fname = _class.tapp_name(tapp_fname)
|
||||
|
||||
# get the path for actual file
|
||||
var tapp_path = _class.list_installed_ext().find(tapp_fname)
|
||||
if tapp_path != nil
|
||||
|
||||
var new_name
|
||||
if enable && string.endswith(tapp_path, ".tapp_")
|
||||
new_name = tapp_path[0..-2] # remove trailing '_'
|
||||
elif !enable && string.endswith(tapp_path, ".tapp")
|
||||
new_name = tapp_path + '_' # add trailing '_'
|
||||
end
|
||||
|
||||
if new_name
|
||||
import path
|
||||
var success = path.rename(tapp_path, new_name)
|
||||
if (success) # update any running extension with its new name
|
||||
if (tasmota._ext != nil) && tasmota._ext.contains(tapp_path)
|
||||
tasmota._ext[new_name] = tasmota._ext[tapp_path]
|
||||
tasmota._ext.remove(tapp_path)
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#####################################################################################################
|
||||
# delete_ext(tapp_fname)
|
||||
#
|
||||
# @param tapp_fname : string - name of tapp file to delete from file system (ex: "Leds_Panel")
|
||||
# @return bool - `true` if success
|
||||
static def delete_ext(tapp_fname)
|
||||
# sanitize
|
||||
tapp_fname = _class.tapp_name(tapp_fname)
|
||||
|
||||
# get the path for actual file
|
||||
var tapp_path = _class.list_installed_ext().find(tapp_fname)
|
||||
if tapp_path != nil
|
||||
import path
|
||||
_class.run_stop_ext(tapp_fname, false) # stop the extension if it's running
|
||||
var success = path.remove(tapp_path)
|
||||
return success
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
#####################################################################################################
|
||||
# install_from_store(tapp_fname)
|
||||
#
|
||||
# @param tapp_fname : string - name of tapp file to install from repository
|
||||
# @return bool : 'true' if success
|
||||
def install_from_store(tapp_fname)
|
||||
import string
|
||||
import path
|
||||
# sanitize
|
||||
tapp_fname = self.tapp_name(tapp_fname)
|
||||
# add '.tapp' extension if it is not present
|
||||
if !string.endswith(tapp_fname, ".tapp")
|
||||
tapp_fname += '.tapp'
|
||||
end
|
||||
tapp_fname = self.tapp_name(tapp_fname) + ".tapp"
|
||||
# full url
|
||||
var ext_url = f"{self.EXT_REPO}{self.EXT_REPO_FOLDER}{tapp_fname}"
|
||||
log(f"EXT: installing from '{ext_url}'", 3)
|
||||
@ -222,19 +307,20 @@ class Extension_manager
|
||||
var r = cl.GET()
|
||||
if r != 200
|
||||
log(f"EXT: return_code={r}", 2)
|
||||
return
|
||||
return false
|
||||
end
|
||||
var ret = cl.write_file(local_file)
|
||||
cl.close()
|
||||
# test if file exists and tell its size
|
||||
if ret > 0 && path.exists(local_file)
|
||||
log(f"EXT: successfully installed '{local_file}' {ret} bytes", 3)
|
||||
return true
|
||||
else
|
||||
raise "io_error", f"could not download into '{local_file}' ret={ret}"
|
||||
end
|
||||
except .. as e, m
|
||||
tasmota.log(format("EXT: exception '%s' - '%s'", e, m), 2)
|
||||
return nil
|
||||
log(format("EXT: exception '%s' - '%s'", e, m), 2)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
@ -278,7 +364,6 @@ class Extension_manager
|
||||
webserver.content_send("<script>"
|
||||
"function loadext() {"
|
||||
"eb('store').disabled=true;"
|
||||
# "eb('store').innerHTML = '[ <span style=\"color:var(--c_btnsv);\">Loading from Store...</span> ]';"
|
||||
"x=new XMLHttpRequest();"
|
||||
"x.timeout=4000;"
|
||||
"x.onreadystatechange = () => {"
|
||||
@ -286,8 +371,6 @@ class Extension_manager
|
||||
"if(x.status==200){"
|
||||
"eb('inet').style.display='none';"
|
||||
"eb('store').outerHTML=x.responseText;"
|
||||
# "}else{"
|
||||
# "eb('store').innerHTML='<b>[ <span style=\"color:var(--c_btnrsthvr);\">Error loading manifest.</span> ]</b>';"
|
||||
"}"
|
||||
"}"
|
||||
"};"
|
||||
@ -327,23 +410,23 @@ class Extension_manager
|
||||
"</script>"
|
||||
)
|
||||
|
||||
webserver.content_send("<fieldset style='padding:0 5px;'>"
|
||||
"<style>"
|
||||
# Fix for small text - the key is width: min-content on parent */
|
||||
".ext-item{width:min-content;min-width:100%;}"
|
||||
".ext-item small{display:block;word-wrap:break-word;overflow-wrap:break-word;white-space:normal;padding-right:5px;padding-top:2px;}"
|
||||
# Control bar styles
|
||||
".ext-controls{display:flex;gap:8px;align-items:center;margin-top:4px;padding:0px}"
|
||||
# Small action buttons
|
||||
".btn-small{padding:0 6px;line-height:1.8rem;font-size:0.9rem;min-width:auto;width:auto;flex-shrink:0;}"
|
||||
# form
|
||||
"form{padding-top:0px;padding-bottom:0px;}"
|
||||
# Running indicator
|
||||
".running-indicator{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:8px;background:var(--c_btnsvhvr);animation:pulse 1.5s infinite;}"
|
||||
"@keyframes pulse{0%{opacity:1;}50%{opacity:0.5;}100%{opacity:1;}}"
|
||||
webserver.content_send(
|
||||
"<fieldset style='padding:0 5px;'>"
|
||||
"<style>"
|
||||
# Fix for small text - the key is width: min-content on parent */
|
||||
".ext-item{width:min-content;min-width:100%;}"
|
||||
".ext-item small{display:block;word-wrap:break-word;overflow-wrap:break-word;white-space:normal;padding-right:5px;padding-top:2px;}"
|
||||
# Control bar styles
|
||||
".ext-controls{display:flex;gap:8px;align-items:center;margin-top:4px;padding:0px}"
|
||||
# Small action buttons
|
||||
".btn-small{padding:0 6px;line-height:1.8rem;font-size:0.9rem;min-width:auto;width:auto;flex-shrink:0;}"
|
||||
# form
|
||||
"form{padding-top:0px;padding-bottom:0px;}"
|
||||
# Running indicator
|
||||
".running-indicator{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:8px;background:var(--c_btnsvhvr);animation:pulse 1.5s infinite;}"
|
||||
"@keyframes pulse{0%{opacity:1;}50%{opacity:0.5;}100%{opacity:1;}}"
|
||||
|
||||
# for store
|
||||
|
||||
# /* Extension Store specific styles */
|
||||
".store-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;}"
|
||||
".store-stats{font-size:0.9em;color:var(--c_in);}"
|
||||
@ -379,24 +462,23 @@ class Extension_manager
|
||||
while ext_nb < size(installed_ext)
|
||||
if (ext_nb > 0) webserver.content_send("<hr style='margin:2px 0 0 0;'>") end
|
||||
var ext_path = installed_ext.get_by_index(ext_nb) # ex: '/.extensions/Partition_Wizard.tapp'
|
||||
var ext_path_html = webserver.html_escape(ext_path)
|
||||
var tapp_name = self.tapp_name(ext_path)
|
||||
var tapp_name_html = webserver.html_escape(tapp_name)
|
||||
var details = tasmota.read_extension_manifest(ext_path)
|
||||
# log(f"EXT: {details=}")
|
||||
var running = tasmota._ext ? tasmota._ext.contains(ext_path) : false
|
||||
var running_indicator = running ? " <span class='running-indicator' title='Running'></span>" : ""
|
||||
var autorun = details.find("autorun", false)
|
||||
var back_green = "style='background:var(--c_btnsvhvr);'"
|
||||
var dark_blue = "style='background:var(--c_btnoff);'"
|
||||
webserver.content_send("<div class='ext-item'>")
|
||||
webserver.content_send(f"<span title='path: {ext_path_html}'><b>{webserver.html_escape(details['name'])}</b>{running_indicator}</span><br>")
|
||||
webserver.content_send(f"<span title='path: {tapp_name_html}'><b>{webserver.html_escape(details['name'])}</b>{running_indicator}</span><br>")
|
||||
webserver.content_send(f"<small>{webserver.html_escape(details['description'])}</small>")
|
||||
|
||||
webserver.content_send("<div class='ext-controls' style='padding-top:0px;padding-bottom:0px;'>")
|
||||
webserver.content_send("<form action='/ext' method='post' class='ext-controls'>")
|
||||
webserver.content_send(f"<button type='submit' class='btn-small' {running ? back_green :: dark_blue} name='{running ? 's' :: 'r'}{ext_path_html}'>{running ? 'Running' :: 'Stopped'}</button>")
|
||||
webserver.content_send(f"<button type='submit' class='btn-small' {autorun ? '' :: dark_blue} name='{autorun ? 'a' :: 'A'}{ext_path_html}'>Auto-run: {autorun ? 'ON' :: 'OFF'}</button>")
|
||||
webserver.content_send(f"<button type='submit' class='btn-small bred' name='d{ext_path_html}' onclick='return confirm(\"Confirm deletion of {webserver.html_escape(ext_path)}\")'>Uninstall</button>")
|
||||
# webserver.content_send(f"<button type='submit' class='btn-small' style='background-color:var(--c_btnoff);border-color:var(--c_btnrst);border-width:3px;border-style:solid;' name='d{ext_path_html}' onclick='return confirm(\"Confirm deletion of {webserver.html_escape(ext_path)}\")'>Uninstall</button>")
|
||||
webserver.content_send(f"<button type='submit' class='btn-small' {running ? back_green :: dark_blue} name='{running ? 's' :: 'r'}{tapp_name_html}'>{running ? 'Running' :: 'Stopped'}</button>")
|
||||
webserver.content_send(f"<button type='submit' class='btn-small' {autorun ? '' :: dark_blue} name='{autorun ? 'a' :: 'A'}{tapp_name_html}'>Auto-run: {autorun ? 'ON' :: 'OFF'}</button>")
|
||||
webserver.content_send(f"<button type='submit' class='btn-small bred' name='d{tapp_name_html}' onclick='return confirm(\"Confirm deletion of {tapp_name_html}.tapp\")'>Uninstall</button>")
|
||||
webserver.content_send("</form></div></div>")
|
||||
|
||||
ext_nb += 1
|
||||
@ -412,7 +494,6 @@ class Extension_manager
|
||||
"<hr style='margin-bottom:0;'>"
|
||||
"<span id='inet' style='font-size:small;font-weight:normal;''> (This feature requires an internet connection)</span>"
|
||||
"</h3></div>")
|
||||
# "<p><small> (This feature requires an internet connection)</small></p>")
|
||||
|
||||
webserver.content_send("<b id='store'>[ <span style='color:var(--c_btnsv);'>Loading from Store...</span> ]</b>")
|
||||
|
||||
@ -483,10 +564,8 @@ class Extension_manager
|
||||
installed_tapp_name = self.tapp_name(entry['file'])
|
||||
var installed_tapp_name_web = webserver.html_escape(installed_tapp_name)
|
||||
installed = installed_ext.contains(installed_tapp_name)
|
||||
var installed_path_web
|
||||
if installed
|
||||
var installed_path = installed_ext[installed_tapp_name]
|
||||
installed_path_web = webserver.html_escape(installed_path)
|
||||
var details = tasmota.read_extension_manifest(installed_path)
|
||||
installed_version = int(details.find('version', 0))
|
||||
end
|
||||
@ -524,14 +603,14 @@ class Extension_manager
|
||||
"<div style='width:30%'></div>")
|
||||
if installed
|
||||
if upgrade
|
||||
webserver.content_send( f"<button type='submit' class='btn-action' name='u{installed_path_web}' onclick='return confirm(\"Confirm upgrade of {installed_path_web}\")'>Upgrade</button>")
|
||||
webserver.content_send( f"<button type='submit' class='btn-action' name='u{installed_tapp_name_web}' onclick='return confirm(\"Confirm upgrade of {installed_tapp_name_web}\")'>Upgrade</button>")
|
||||
else
|
||||
webserver.content_send( "<button type='submit' class='btn-action' style='visibility:hidden;'></button>")
|
||||
end
|
||||
webserver.content_send( f"<button type='submit' class='btn-action bred' name='d{installed_path_web}' onclick='return confirm(\"Confirm deletion of {installed_path_web}\")'>Uninstall</button>")
|
||||
webserver.content_send( f"<button type='submit' class='btn-action bred' name='d{installed_tapp_name_web}' onclick='return confirm(\"Confirm deletion of {installed_tapp_name_web}\")'>Uninstall</button>")
|
||||
else
|
||||
webserver.content_send( f"<button type='submit' class='btn-action' style='visibility:hidden;'></button>"
|
||||
"<button type='submit' class='btn-action bgrn' name='i{installed_tapp_name_web}' onclick='return confirm(\"Confirm installation of {app_name_web}\")'>Install</button>")
|
||||
webserver.content_send( f"<button type='submit' class='btn-action' name='i{installed_tapp_name_web}' onclick='return confirm(\"Confirm installation of {app_name_web}\")'>Install</button>"
|
||||
"<button type='submit' class='btn-action bgrn' name='I{installed_tapp_name_web}' onclick='return confirm(\"Confirm installation of {app_name_web}\")'>Install+Run</button>")
|
||||
end
|
||||
webserver.content_send( "</form>"
|
||||
"</div>"
|
||||
@ -565,14 +644,14 @@ class Extension_manager
|
||||
cl.begin(url)
|
||||
var r = cl.GET()
|
||||
if r != 200
|
||||
tasmota.log(f"EXT: error fetching manifest {r}", 2)
|
||||
log(f"EXT: error fetching manifest {r}", 2)
|
||||
raise "webclient_error", f"Error fetching manifest code={r}"
|
||||
end
|
||||
var s = cl.get_string()
|
||||
cl.close()
|
||||
return s
|
||||
except .. as e, m
|
||||
tasmota.log(format("EXT: exception '%s' - '%s'", e, m), 2)
|
||||
log(format("EXT: exception '%s' - '%s'", e, m), 2)
|
||||
raise e, m
|
||||
end
|
||||
end
|
||||
@ -591,73 +670,46 @@ class Extension_manager
|
||||
|
||||
try
|
||||
# log(f">>> {webserver.arg_name(0)=} {webserver.arg(0)=} {webserver.arg_size()=}")
|
||||
# var redirect_to_store = false # add suffix to redirect to store
|
||||
|
||||
var btn_name = webserver.arg_name(0)
|
||||
var action = btn_name[0] # first character
|
||||
var action_path = btn_name[1..] # remove first character
|
||||
|
||||
if (action == "r") # button "Run"
|
||||
if (action_path != "")
|
||||
# log(f"EXT: run '{action_path}'")
|
||||
tasmota.load(action_path)
|
||||
end
|
||||
elif (action == "s") # button "Stop"
|
||||
# log(f"EXT: stop '{action_path}'")
|
||||
tasmota.unload_extension(action_path)
|
||||
if (action == "r") || (action == "s") # button "Run" or "Stop"
|
||||
self.run_stop_ext(action_path, action == "r")
|
||||
elif (action == "a") || (action == "A") # button "Autorun", "A" enable, "a" disable
|
||||
var new_name
|
||||
if (action == "a") && string.endswith(action_path, ".tapp") # Autorun is enabled, disable it
|
||||
new_name = action_path[0..-5] + "tapp_"
|
||||
elif (action == "A") && string.endswith(action_path, ".tapp_")
|
||||
new_name = action_path[0..-6] + "tapp"
|
||||
end
|
||||
if new_name
|
||||
var success = path.rename(action_path, new_name)
|
||||
# log(f"EXT: rename '{action_path}' to '{new_name} {success=}", 3)
|
||||
if (success) # update any running extension with its new name
|
||||
if tasmota._ext.contains(action_path)
|
||||
tasmota._ext[new_name] = tasmota._ext[action_path]
|
||||
tasmota._ext.remove(action_path)
|
||||
end
|
||||
end
|
||||
else
|
||||
log(f"EXT: wrong action '{btn_name}'", 3)
|
||||
end
|
||||
self.enable_disable_ext(action_path, action == "A")
|
||||
elif (action == 'd') # button "Delete"
|
||||
if (action_path != "")
|
||||
# first stop if it was running
|
||||
tasmota.unload_extension(action_path)
|
||||
# then delete file
|
||||
var success = path.remove(action_path)
|
||||
# log(f"EXT: delete '{action_path}' {success=}", 3)
|
||||
end
|
||||
|
||||
self.delete_ext(action_path)
|
||||
|
||||
# Now try the store commands
|
||||
elif (action == 'u') # Upgrade ext
|
||||
# log(f"EXT: upgrade '{action_path}'", 3)
|
||||
# first stop the app if it's running
|
||||
tasmota.unload_extension(action_path)
|
||||
self.install_from_store(self.tapp_name(action_path))
|
||||
# redirect_to_store = true
|
||||
elif (action == 'i') # Install ext
|
||||
# log(f"EXT: install '{action_path}'", 3)
|
||||
self.install_from_store(self.tapp_name(action_path))
|
||||
# redirect_to_store = true
|
||||
self.run_stop_ext(action_path, false) # stop the extension
|
||||
var success = self.install_from_store(self.tapp_name(action_path))
|
||||
elif (action == 'i') || (action == 'I') # Install ext ('I' for run as well)
|
||||
var success = self.install_from_store(self.tapp_name(action_path))
|
||||
if success
|
||||
if (action == 'I') # run
|
||||
self.run_stop_ext(action_path, true)
|
||||
else # disable
|
||||
self.enable_disable_ext(action_path, false)
|
||||
end
|
||||
end
|
||||
else
|
||||
log(f"EXT: wrong action '{btn_name}'", 3)
|
||||
end
|
||||
|
||||
# var redirect_suffix = redirect_to_store ? "store=" : ""
|
||||
# webserver.redirect(f"/ext?{redirect_suffix}")
|
||||
webserver.redirect(f"/ext")
|
||||
except .. as e, m
|
||||
log(f"CFG: Exception> '{e}' - {m}", 2)
|
||||
log(f"EXT: Exception> '{e}' - {m}", 2)
|
||||
#- display error page -#
|
||||
webserver.content_start("Parameter error") #- title of the web page -#
|
||||
webserver.content_send_style() #- send standard Tasmota styles -#
|
||||
|
||||
webserver.content_send(f"<p style='width:340px;'><b>Exception:</b><br>'{webserver.html_escape(e)}'<br>{webserver.html_escape(m)}</p>")
|
||||
|
||||
webserver.content_button(webserver.BUTTON_CONFIGURATION) #- button back to management page -#
|
||||
webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -#
|
||||
webserver.content_stop() #- end of web page -#
|
||||
end
|
||||
end
|
||||
|
||||
@ -948,7 +948,7 @@ class Tasmota
|
||||
end
|
||||
|
||||
def unload_extension(name_or_instance)
|
||||
if (self._ext == nil) return end
|
||||
if (self._ext == nil) return false end
|
||||
var d = name_or_instance # d = driver
|
||||
|
||||
if type(name_or_instance) == 'string'
|
||||
@ -961,11 +961,14 @@ class Tasmota
|
||||
d.unload()
|
||||
end
|
||||
self.remove_driver(d)
|
||||
# force gc of instance
|
||||
name_or_instance = nil
|
||||
d = nil
|
||||
tasmota.gc()
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
# force gc of instance
|
||||
name_or_instance = nil
|
||||
d = nil
|
||||
tasmota.gc()
|
||||
end
|
||||
|
||||
# cmd high-level function
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1893,45 +1893,51 @@ be_local_closure(class_Tasmota_unload_extension, /* name */
|
||||
&be_ktab_class_Tasmota, /* shared constants */
|
||||
&be_const_str_unload_extension,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[38]) { /* code */
|
||||
( &(const binstruction[44]) { /* code */
|
||||
0x8808014B, // 0000 GETMBR R2 R0 K75
|
||||
0x4C0C0000, // 0001 LDNIL R3
|
||||
0x1C080403, // 0002 EQ R2 R2 R3
|
||||
0x780A0000, // 0003 JMPF R2 #0005
|
||||
0x80000400, // 0004 RET 0
|
||||
0x5C080200, // 0005 MOVE R2 R1
|
||||
0x600C0004, // 0006 GETGBL R3 G4
|
||||
0x5C100200, // 0007 MOVE R4 R1
|
||||
0x7C0C0200, // 0008 CALL R3 1
|
||||
0x1C0C0701, // 0009 EQ R3 R3 K1
|
||||
0x780E0004, // 000A JMPF R3 #0010
|
||||
0x880C014B, // 000B GETMBR R3 R0 K75
|
||||
0x8C0C070C, // 000C GETMET R3 R3 K12
|
||||
0x5C140200, // 000D MOVE R5 R1
|
||||
0x7C0C0400, // 000E CALL R3 2
|
||||
0x5C080600, // 000F MOVE R2 R3
|
||||
0x600C0004, // 0010 GETGBL R3 G4
|
||||
0x5C100400, // 0011 MOVE R4 R2
|
||||
0x7C0C0200, // 0012 CALL R3 1
|
||||
0x1C0C0757, // 0013 EQ R3 R3 K87
|
||||
0x780E000A, // 0014 JMPF R3 #0020
|
||||
0xA40EE000, // 0015 IMPORT R3 K112
|
||||
0x8C10075A, // 0016 GETMET R4 R3 K90
|
||||
0x5C180400, // 0017 MOVE R6 R2
|
||||
0x581C007A, // 0018 LDCONST R7 K122
|
||||
0x7C100600, // 0019 CALL R4 3
|
||||
0x78120001, // 001A JMPF R4 #001D
|
||||
0x8C10057A, // 001B GETMET R4 R2 K122
|
||||
0x7C100200, // 001C CALL R4 1
|
||||
0x8C10017B, // 001D GETMET R4 R0 K123
|
||||
0x5C180400, // 001E MOVE R6 R2
|
||||
0x7C100400, // 001F CALL R4 2
|
||||
0x4C040000, // 0020 LDNIL R1
|
||||
0x4C080000, // 0021 LDNIL R2
|
||||
0xB80E0400, // 0022 GETNGBL R3 K2
|
||||
0x8C0C077C, // 0023 GETMET R3 R3 K124
|
||||
0x7C0C0200, // 0024 CALL R3 1
|
||||
0x80000000, // 0025 RET 0
|
||||
0x780A0001, // 0003 JMPF R2 #0006
|
||||
0x50080000, // 0004 LDBOOL R2 0 0
|
||||
0x80040400, // 0005 RET 1 R2
|
||||
0x5C080200, // 0006 MOVE R2 R1
|
||||
0x600C0004, // 0007 GETGBL R3 G4
|
||||
0x5C100200, // 0008 MOVE R4 R1
|
||||
0x7C0C0200, // 0009 CALL R3 1
|
||||
0x1C0C0701, // 000A EQ R3 R3 K1
|
||||
0x780E0004, // 000B JMPF R3 #0011
|
||||
0x880C014B, // 000C GETMBR R3 R0 K75
|
||||
0x8C0C070C, // 000D GETMET R3 R3 K12
|
||||
0x5C140200, // 000E MOVE R5 R1
|
||||
0x7C0C0400, // 000F CALL R3 2
|
||||
0x5C080600, // 0010 MOVE R2 R3
|
||||
0x600C0004, // 0011 GETGBL R3 G4
|
||||
0x5C100400, // 0012 MOVE R4 R2
|
||||
0x7C0C0200, // 0013 CALL R3 1
|
||||
0x1C0C0757, // 0014 EQ R3 R3 K87
|
||||
0x780E0012, // 0015 JMPF R3 #0029
|
||||
0xA40EE000, // 0016 IMPORT R3 K112
|
||||
0x8C10075A, // 0017 GETMET R4 R3 K90
|
||||
0x5C180400, // 0018 MOVE R6 R2
|
||||
0x581C007A, // 0019 LDCONST R7 K122
|
||||
0x7C100600, // 001A CALL R4 3
|
||||
0x78120001, // 001B JMPF R4 #001E
|
||||
0x8C10057A, // 001C GETMET R4 R2 K122
|
||||
0x7C100200, // 001D CALL R4 1
|
||||
0x8C10017B, // 001E GETMET R4 R0 K123
|
||||
0x5C180400, // 001F MOVE R6 R2
|
||||
0x7C100400, // 0020 CALL R4 2
|
||||
0x4C040000, // 0021 LDNIL R1
|
||||
0x4C080000, // 0022 LDNIL R2
|
||||
0xB8120400, // 0023 GETNGBL R4 K2
|
||||
0x8C10097C, // 0024 GETMET R4 R4 K124
|
||||
0x7C100200, // 0025 CALL R4 1
|
||||
0x50100200, // 0026 LDBOOL R4 1 0
|
||||
0x80040800, // 0027 RET 1 R4
|
||||
0x70020001, // 0028 JMP #002B
|
||||
0x500C0000, // 0029 LDBOOL R3 0 0
|
||||
0x80040600, // 002A RET 1 R3
|
||||
0x80000000, // 002B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
@ -49,7 +49,7 @@ default_envs =
|
||||
[tasmota]
|
||||
; *** Global build / unbuild compile time flags for ALL Tasmota / Tasmota32 [env]
|
||||
;build_unflags =
|
||||
build_flags = -DUSE_BERRY_PARTITION_WIZARD
|
||||
;build_flags =
|
||||
|
||||
[env]
|
||||
;build_unflags = ${common.build_unflags}
|
||||
|
||||
@ -1221,7 +1221,7 @@
|
||||
//#define USE_WEBCAM // Add support for webcam
|
||||
|
||||
#define USE_AUTOCONF // Enable Esp32(x) autoconf feature, requires USE_BERRY and USE_WEBCLIENT_HTTPS (12KB Flash)
|
||||
// #define USE_EXTENSION_MANAGER // Enable Esp32(x) extensions manager, requires USE_BERRY and USE_WEBCLIENT_HTTPS (9KB Flash)
|
||||
#define USE_EXTENSION_MANAGER // Enable Esp32(x) extensions manager, requires USE_BERRY and USE_WEBCLIENT_HTTPS (11KB Flash)
|
||||
#define USE_BERRY // Enable Berry scripting language
|
||||
#define USE_BERRY_PYTHON_COMPAT // Enable by default `import python_compat`
|
||||
#define USE_BERRY_TIMEOUT 4000 // Timeout in ms, will raise an exception if running time exceeds this timeout
|
||||
@ -1235,9 +1235,9 @@
|
||||
// Note that only two ciphers are enabled: ECDHE_RSA_WITH_AES_128_GCM_SHA256, ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
||||
#define USE_BERRY_WEBCLIENT_USERAGENT "TasmotaClient" // default user-agent used, can be changed with `wc.set_useragent()`
|
||||
#define USE_BERRY_WEBCLIENT_TIMEOUT 2000 // Default timeout in milliseconds
|
||||
#define USE_BERRY_LEDS_PANEL // Add button to dynamically load the Leds Panel from a bec file online
|
||||
// #define USE_BERRY_LEDS_PANEL // Add button to dynamically load the Leds Panel from a bec file online
|
||||
#define USE_BERRY_LEDS_PANEL_URL "http://ota.tasmota.com/tapp/leds_panel.bec"
|
||||
#define USE_BERRY_LVGL_PANEL // Add button to dynamically load the LVGL Panel from a bec file online
|
||||
// #define USE_BERRY_LVGL_PANEL // Add button to dynamically load the LVGL Panel from a bec file online
|
||||
#define USE_BERRY_LVGL_PANEL_URL "http://ota.tasmota.com/tapp/lvgl_panel.bec"
|
||||
//#define USE_BERRY_PARTITION_WIZARD // Add a button to dynamically load the Partion Wizard from a bec file online (+1.3KB Flash)
|
||||
#define USE_BERRY_PARTITION_WIZARD_URL "http://ota.tasmota.com/tapp/partition_wizard.bec"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user