Saving settings¶
Widgets: read and write¶
A widget's settings are saved inside the model file, alongside the screen layout. You don't pick a file: implement read and write, and use storage.read / storage.write inside them.
local function read(widget)
widget.source = storage.read("source")
widget.warn = storage.read("warn") or 33 -- default for widgets saved by an older version
widget.color = storage.read("color") or lcd.RGB(0, 200, 0)
end
local function write(widget)
storage.write("source", widget.source)
storage.write("warn", widget.warn)
storage.write("color", widget.color)
end
- Values can be numbers, strings, booleans, colors, and Source objects. A saved source is restored as a live
Source. - Keep
readandwritein step: same keys, same order. It makes them easy to compare when you add a setting. - When you add a setting in a new version, give it a default (
or 33). Widgets saved by the old version won't have it.
Ethos calls write after the pilot leaves the widget's configuration, and read when the model loads.
Version your settings
Write a version number first. A later release can then migrate old layouts:
local SETTINGS_VERSION = 2
local function write(widget)
storage.write("v", SETTINGS_VERSION)
storage.write("source", widget.source)
storage.write("warn", widget.warn)
end
local function read(widget)
local v = storage.read("v")
widget.source = storage.read("source")
widget.warn = storage.read("warn")
if v == nil then -- saved by version 1: warn was stored in tenths
widget.warn = widget.warn and widget.warn / 10
end
end
Tasks and sources support the same read/write pair.
Tools and global settings: files¶
System tools aren't tied to a model, so they keep their settings in files. Store them under your script's folder or a LOGS: subfolder for data. Use absolute paths, because these functions run from callbacks (see why):
local FILE = "SCRIPTS:/mytool/settings.lua" -- absolute, never relative in callbacks
local function save(t)
local f = io.open(FILE, "w")
if not f then return false end
f:write("return {\n")
for k, v in pairs(t) do
if type(v) == "string" then
f:write(string.format(" %s = %q,\n", k, v))
else
f:write(string.format(" %s = %s,\n", k, tostring(v)))
end
end
f:write("}\n")
f:close()
return true
end
local function load()
local chunk = loadfile(FILE)
local ok, t = pcall(chunk or function() return {} end)
return (ok and type(t) == "table") and t or {}
end
Saving as a Lua table and reading it back with loadfile needs no parser code. For larger or user-editable data, INI or CSV files are common in open-source suites.
Write rarely
Flash storage is slow and wears out. Never write files from wakeup on every tick. Save when the pilot confirms a change, or when a tool closes. For logging, buffer lines in a table and flush every few seconds (see Saving CPU).
Per-model data from a tool¶
To keep tool data per model, include the model in the file name: