audio bus crypto display ez global gps keyboard mesh net radio sprite storage synth system wifi

File I/O for internal flash (LittleFS) and SD card

Mount points: /sd/ - SD card (removable, for maps, logs, large files) /fs/ - LittleFS internal flash (for user data) /img/ - Embedded scripts (read-only, compiled into firmware) Script loading uses /scripts/ paths with overlay: SD > FS > embedded. The /img/ mount point is for file browsing; internally maps to /scripts/. Also provides persistent key-value preferences stored in NVS flash.

Functions

append_file() → boolean Append content to file
ez.storage.append_file(path, content) -> boolean
Adds content to the end of an existing file, or creates the file if it doesn't exist. Useful for logging, collecting data, or building files incrementally.
ParameterDescription
pathFile path (prefix /sd/ for SD card)
contentContent to append
Returns: true if successful, or false with error message
-- Append to log file
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
ez.storage.append_file("/sd/log.txt", timestamp .. " System started\n")
clear_prefs() → boolean Clear all preferences
ez.storage.clear_prefs() -> boolean
Removes all stored preferences from non-volatile storage. Use with caution - this resets all settings to defaults. Useful for factory reset functionality.
Returns: true if all preferences were cleared
-- Factory reset
ez.storage.clear_prefs()
print("All settings reset to defaults")
copy_file() → boolean Copy a file from source to destination
ez.storage.copy_file(src, dst) -> boolean
Copies a file from source to destination. Can copy between different filesystems (e.g., from LittleFS to SD card or vice versa). The destination file is overwritten if it exists. Uses 512-byte chunks to minimize memory usage.
ParameterDescription
srcSource file path (prefix /sd/ for SD card)
dstDestination file path (prefix /sd/ for SD card)
Returns: true if copy was successful
-- Backup config to SD card
ez.storage.copy_file("/config.json", "/sd/backup/config.json")
-- Copy from SD to flash
ez.storage.copy_file("/sd/assets/image.bin", "/cache/image.bin")
exists() → boolean Check if file or directory exists
ez.storage.exists(path) -> boolean
Checks whether a file or directory exists at the given path. Use before reading to avoid errors, or before writing to check for existing files.
ParameterDescription
pathPath to check (prefix /sd/ for SD card)
Returns: true if file or directory exists
if ez.storage.exists("/config.json") then
local content = ez.storage.read_file("/config.json")
else
print("Config not found, using defaults")
end
file_size() → integer Get file size in bytes
ez.storage.file_size(path) -> integer
Returns the size of a file in bytes. Useful for checking if a file is empty, allocating buffers, or calculating offsets for random access reads.
ParameterDescription
pathFile path (prefix /sd/ for SD card)
Returns: File size in bytes, or nil with error message if file not found
local size = ez.storage.file_size("/config.json")
if size then
print("Config file is", size, "bytes")
end
get_flash_info() → table Get flash storage info
ez.storage.get_flash_info() -> table
Returns information about the LittleFS flash filesystem. This is the internal storage used for scripts, configuration, and small data files. Typically a few megabytes, shared with the firmware.
Returns: Table with total_bytes, used_bytes, free_bytes
local info = ez.storage.get_flash_info()
local free_kb = info.free_bytes / 1024
print(string.format("Flash: %.1f KB free", free_kb))
get_free_space() → integer Get free space on filesystem in bytes
ez.storage.get_free_space(path) -> integer
Returns the available free space on the specified filesystem. Use before writing large files to ensure sufficient space. Returns 0 if the filesystem is not available.
ParameterDescription
pathPath to check ("/sd/" for SD card, otherwise LittleFS), default "/sd/"
Returns: Free space in bytes, or 0 on error
local sd_free = ez.storage.get_free_space("/sd/")
local flash_free = ez.storage.get_free_space("/")
print(string.format("SD: %d MB, Flash: %d KB free",
sd_free / (1024*1024), flash_free / 1024))
get_pref() → string Get preference value
ez.storage.get_pref(key, default) -> string
Retrieves a stored preference value from non-volatile storage (NVS). Preferences persist across reboots and are faster to access than files. Use for settings, calibration values, and other small key-value data.
ParameterDescription
keyPreference key (max 15 chars)
defaultDefault value if key not found (optional)
Returns: Stored value as string, or default/nil if not found
local brightness = ez.storage.get_pref("brightness", "200")
local volume = ez.storage.get_pref("volume", "80")
get_sd_info() → table Get SD card info
ez.storage.get_sd_info() -> table
Returns information about the SD card including capacity, used space, and card type. Returns nil if SD card is not available.
Returns: Table with total_bytes, used_bytes, free_bytes, card_type, or nil
local info = ez.storage.get_sd_info()
if info then
local free_mb = info.free_bytes / (1024 * 1024)
print(string.format("SD card: %.1f MB free", free_mb))
end
is_embedded() → boolean Check if a path is an embedded script
ez.storage.is_embedded(path) -> boolean
Returns true if the given path corresponds to an embedded Lua script. Useful for determining if a file is read-only (embedded) or editable (on SD/flash).
ParameterDescription
pathPath to check
Returns: true if path is an embedded script
if ez.storage.is_embedded("/scripts/boot.lua") then
print("This is a read-only embedded script")
end
is_sd_available() → boolean Check if SD card is mounted
ez.storage.is_sd_available() -> boolean
Checks if an SD card is inserted and accessible. The SD card is initialized on first access. Use this before attempting SD card operations to provide better error messages.
Returns: true if SD card is available and mounted
if ez.storage.is_sd_available() then
print("SD card ready")
else
print("Please insert SD card")
end
json_decode() → value Decode JSON string to Lua value
ez.storage.json_decode(json_string) -> value
Parses a JSON string and returns the corresponding Lua value. JSON objects become Lua tables, arrays become indexed tables, and primitives become their Lua equivalents. Returns nil with error message on parse failure.
ParameterDescription
json_stringJSON string to parse
Returns: Lua value (table, string, number, boolean, or nil), or nil with error
local json = ez.storage.read_file("/config.json")
local config, err = ez.storage.json_decode(json)
if config then
print("Username:", config.username)
else
print("Parse error:", err)
end
json_encode() → string Encode Lua value to JSON string
ez.storage.json_encode(value) -> string
Converts a Lua value to a JSON string. Supports tables (converted to arrays or objects), strings, numbers, booleans, and nil. Nested tables are supported. Useful for saving configuration or sending data over network.
ParameterDescription
valueLua table, string, number, boolean, or nil
Returns: JSON string
local data = {
name = "Alice",
scores = {95, 87, 92},
settings = {sound = true, level = 5}
}
local json = ez.storage.json_encode(data)
ez.storage.write_file("/save.json", json)
list_dir() → table List directory contents
ez.storage.list_dir(path) -> table
Returns an array of all files and subdirectories in the given directory. Each entry is a table with name (string), is_dir (boolean), and size (integer, 0 for directories).
ParameterDescription
pathDirectory path (default "/", prefix /sd/ for SD card)
Returns: Array of tables with name, is_dir, size fields
local files = ez.storage.list_dir("/sd/music")
for _, file in ipairs(files) do
if file.is_dir then
print("[DIR]", file.name)
else
print(file.name, file.size, "bytes")
end
end
list_embedded() → table List embedded script paths
ez.storage.list_embedded(prefix) -> table
Returns a list of all embedded Lua scripts. These are scripts compiled into the firmware and cannot be modified. Optionally filter by prefix to list only scripts in a subdirectory (e.g., "/scripts/ui/screens").
ParameterDescription
prefixOptional path prefix filter (default: list all)
Returns: Array of tables with path, size, and is_embedded fields
local scripts = ez.storage.list_embedded("/scripts/ui/screens")
for _, script in ipairs(scripts) do
print(script.path, script.size, "bytes")
end
list_prefs() → table Enumerate every pref in the lua_storage namespace
ez.storage.list_prefs() -> table
Returns an array of { key = "...", type = "bool" | "int" | "string" | "float" | "blob" } for every key currently stored in NVS under the Lua prefs namespace. Used by the developer prefs editor to show all keys — including ones not declared in the system-prefs registry.
Returns: Array of {key, type} tables
mkdir() → boolean Create directory
ez.storage.mkdir(path) -> boolean
Creates a new directory. Parent directories must already exist. Returns false if directory already exists or creation failed.
ParameterDescription
pathDirectory path to create (prefix /sd/ for SD card)
Returns: true if directory was created
ez.storage.mkdir("/sd/logs")
ez.storage.mkdir("/sd/logs/2024")
read_bytes() → string Read bytes from file at specific offset (for random access)
ez.storage.read_bytes(path, offset, length) -> string
Reads a specific range of bytes from a file without loading the entire file into memory. Useful for reading headers, seeking within large files, or implementing file formats with random access. The read is buffered in PSRAM when available (falls back to internal heap), so country-scale map indexes and other ~1 MB blocks load in a single call. For larger blobs, call in a loop with successive offsets — each call is still a single file open.
ParameterDescription
pathFile path (prefix /sd/ for SD card)
offsetByte offset to start reading from (0-based)
lengthNumber of bytes to read (max 1048576 — 1 MB per call)
Returns: Binary data as string, or nil with error message
-- Read file header(first 16 bytes)
local header = ez.storage.read_bytes("/sd/maps/tiles.bin", 0, 16)
-- Stream a multi-megabyte file in 64KB chunks
local offset = 0
while true do
local chunk = ez.storage.read_bytes("/sd/huge.bin", offset, 65536)
if not chunk or #chunk == 0 then break end
process(chunk); offset = offset + #chunk
end
read_embedded() → string Read embedded script content
ez.storage.read_embedded(path) -> string
Reads the content of an embedded Lua script. These scripts are compiled into firmware and are read-only. Use list_embedded() to discover available embedded scripts.
ParameterDescription
pathFull path of the embedded script (e.g., "/scripts/boot.lua")
Returns: Script content as string, or nil if not found
local content = ez.storage.read_embedded("/scripts/boot.lua")
if content then
print("Boot script is", #content, "bytes")
end
read_file() → string Read entire file contents
ez.storage.read_file(path) -> string
Reads an entire file into memory and returns it as a string. Files up to 1MB are supported. For larger files or binary data, use read_bytes() for random access. Paths starting with /sd/ read from SD card, others from LittleFS.
ParameterDescription
pathFile path (prefix /sd/ for SD card)
Returns: File content as string, or nil with error message
local content = ez.storage.read_file("/config.json")
if content then
local config = ez.storage.json_decode(content)
end
remove() → boolean Delete a file
ez.storage.remove(path) -> boolean
Permanently deletes a file. Cannot be undone. For directories, use rmdir() instead (directory must be empty). Returns false if file doesn't exist or couldn't be deleted.
ParameterDescription
pathFile path to delete (prefix /sd/ for SD card)
Returns: true if file was deleted
if ez.storage.remove("/sd/old_backup.json") then
print("Backup deleted")
end
remove_pref() → boolean Remove a preference
ez.storage.remove_pref(key) -> boolean
Deletes a single preference from non-volatile storage. Use clear_prefs() to remove all preferences at once.
ParameterDescription
keyPreference key to remove
Returns: true if preference was removed
ez.storage.remove_pref("old_setting")
rename() → boolean Rename or move a file
ez.storage.rename(old_path, new_path) -> boolean
Renames a file or moves it to a different location within the same filesystem. Both paths must be on the same filesystem (both SD or both LittleFS). Can also be used to move files between directories.
ParameterDescription
old_pathCurrent file path
new_pathNew file path
Returns: true if renamed successfully
-- Rename a file
ez.storage.rename("/temp.txt", "/final.txt")
-- Move to different directory
ez.storage.rename("/downloads/file.txt", "/documents/file.txt")
rmdir() → boolean Remove empty directory
ez.storage.rmdir(path) -> boolean
Removes an empty directory. The directory must be empty - remove all files and subdirectories first. Returns false if directory is not empty, doesn't exist, or couldn't be removed.
ParameterDescription
pathDirectory path to remove (prefix /sd/ for SD card)
Returns: true if directory was removed
-- Remove directory contents first, then the directory
for _, file in ipairs(ez.storage.list_dir("/sd/temp")) do
ez.storage.remove("/sd/temp/" .. file.name)
end
ez.storage.rmdir("/sd/temp")
set_pref() → boolean Set preference value
ez.storage.set_pref(key, value) -> boolean
Stores a value in non-volatile storage (NVS). Values persist across reboots. Supports strings, integers, floats, and booleans. The key length is limited to 15 characters.
ParameterDescription
keyPreference key (max 15 chars)
valueValue to store (string, number, or boolean)
Returns: true if saved successfully
ez.storage.set_pref("brightness", 200)
ez.storage.set_pref("username", "Alice")
ez.storage.set_pref("gps_enabled", true)
write_file() → boolean Write content to file (creates/overwrites)
ez.storage.write_file(path, content) -> boolean
Creates a new file or overwrites an existing file with the given content. Parent directories must already exist. For binary data, pass a string with binary bytes. Use append_file() to add to existing file instead.
ParameterDescription
pathFile path (prefix /sd/ for SD card)
contentContent to write (string, can be binary)
Returns: true if successful, or false with error message
local config = {brightness = 200, volume = 80}
local json = ez.storage.json_encode(config)
ez.storage.write_file("/config.json", json)