b2f58118e1
Remove OpenFontRender, embedded Meslo assets, custom-font APIs, and their runtime allocation overhead. Keep the taller status layout and compact card grid, with used RAM, aligned faded WiFi bars, and tighter telemetry rows.
102 lines
6.7 KiB
Markdown
102 lines
6.7 KiB
Markdown
# Lua API parity with crosspoint-reader
|
|
|
|
Both firmwares expose a Lua API to apps on an SD card, and both are ESP32 devices, so a
|
|
script that only touches files and the network should behave the same on either. This
|
|
records where they agree, where they differ **for a reason**, and where they differ
|
|
because nobody noticed. The last group is a bug list, not a design.
|
|
|
|
Compared against crosspoint-reader at `src/util/lua/LuaBindings*.cpp`.
|
|
|
|
## Identical
|
|
|
|
`fs.listDirs`, `fs.listFiles`, `fs.exists`, `fs.readFile`, `fs.writeFile`,
|
|
`gui.getWidth`, `gui.getHeight`, `gui.fillRect`, `gui.drawRect`, `gui.drawLine`,
|
|
`sys.getMillis`, `sys.delay`, `log.debug/info/error`, the whole `http` table,
|
|
`sys.setTickInterval`, `wifi.getStatus`, `wifi.isConnected`, `wifi.getLocalIP`, and the
|
|
`draw()` / `on_tick()` callbacks. `init()` is required in both, so a misspelled entry
|
|
point is an error rather than an app that quietly draws nothing.
|
|
|
|
`wifi.getStatus()` returns `{state, ssid, ip, rssi}` in both. crosspoint returned a bare
|
|
string until this was reconciled; a string had nowhere to put the address and signal
|
|
strength a status screen wants. Its `state` vocabulary is a subset: crosspoint reports
|
|
`disconnected`, `connecting`, `connected` and `failed`, while this firmware adds
|
|
`not_found`, because it joins one named network rather than walking a credential list.
|
|
|
|
## Deliberate differences
|
|
|
|
| Area | crosspoint-reader | slate32 | Why |
|
|
|---|---|---|---|
|
|
| App lifecycle | `sys.exit()`, `init()` | `sys.back()`, `sys.launch/replace(path, arg)`, `init(arg)` | slate32 apps form a reloadable route stack; only the path and optional string cross between Lua states. |
|
|
| Input | `input.wasPressed(button)` and friends, 8 named buttons | `input.getTouch`, `getRawTouch`, `touched` | Different hardware. A touch panel has no button names and a button device has no coordinates. |
|
|
| Drawing | `gui.drawText(font, x, y, text, color, style)`, `getTextWidth(font, text)` | `gui.drawText(text, x, y, color, bg)`, `gui.getTextWidth(text)` | crosspoint ships several fonts; this firmware has one built-in font scaled by `gui.setTextSize(n)`, and needs an opaque background colour because the panel is not e-ink. |
|
|
| Refresh | `gui.refresh(mode)`, `REFRESH_FULL/HALF/FAST` | none | An LCD has no waveform modes. |
|
|
| Colour | `COLOR_*` constants, 4 grey levels | `gui.color(r, g, b)` returning RGB565 | 16-bit colour has too many values to enumerate. |
|
|
| Shapes | `drawRoundedRect` + `fillRoundedRect` | one `gui.roundRect(...)` with gradient and border | Fill and border derive from a single distance field, so their edges cannot disagree. |
|
|
| Themes | none | `settings.getTheme/setTheme`, `/lib/theme.lua` | Colour panel. |
|
|
| Rotation | `gui.setOrientation("portrait")` | `settings.setRotation(degrees)` persisted, `gui.setRotation(degrees)` for one frame | This device stores rotation in settings and remaps touch to match. |
|
|
| Clock | nothing exposed; UTC offset is a C++ setting | `sys.isClockSynced`, `settings.getTimezone/setTimezone` with POSIX TZ rules | Timezone here is a stored rule, so `os.date()` returns local time with DST handled by libc. |
|
|
| Launching | launcher is C++ | `sys.launch(path)`, home is a Lua app | The launcher is just another app here, named `home`. |
|
|
| Modules | single-file apps; `require` unusable | `require` works, `package.searchers` reads the SD card, `/lib` on the path | Shared code such as `ui.lua` needs it. **crosspoint should adopt this.** |
|
|
| BLE | `ble.*` | none | No BLE use case here yet. |
|
|
| TLS memory | `TlsScratchLoan` lends the framebuffer to wolfSSL | none | crosspoint is heap-starved; this device has ~280KB free. |
|
|
|
|
## Accidental differences — drift, not design
|
|
|
|
Each of these is the same concept spelled two ways. Fixing them means changing one repo.
|
|
|
|
| Concern | crosspoint-reader | slate32 | Suggested resolution |
|
|
|---|---|---|---|
|
|
| `wifi.connect()` | no arguments, uses stored credentials | `(ssid, password)`, saves them | Both are wanted: a no-argument reconnect and an explicit join. |
|
|
| `fs.readFile` cap | 50000 bytes | 65536 bytes | Arbitrary in both. |
|
|
| `fs` mutation | `mkdir`, `rename`, `remove`, `removeTree`, plus a path-safety check rejecting `..` | absent | **This repo is missing them, including the traversal guard.** |
|
|
| `fs.fileSize`, `fs.readLineAt` | present | absent | Worth porting; `readLineAt` exists for paging large files. |
|
|
| Timers | `timer.after/every/cancel` + `on_timer(id)` | absent | Worth porting. |
|
|
|
|
## The `http` table
|
|
|
|
Signatures match crosspoint exactly, so scripts port unchanged:
|
|
|
|
```lua
|
|
http.get(url, headers?) -> body|nil, status
|
|
http.head(url, headers?) -> body|nil, status
|
|
http.delete(url, headers?) -> body|nil, status
|
|
http.post(url, body?, headers?) -> body|nil, status
|
|
http.patch(url, body?, headers?) -> body|nil, status
|
|
http.download(url, dest, options) -> bytesWritten | nil, error
|
|
http.urlencode(input) -> string
|
|
```
|
|
|
|
`status` is `-1` when the request never left the device. Bodies are capped at 50000
|
|
bytes, matching crosspoint, and a larger response yields `nil` with the real status.
|
|
`http.download` requires HTTPS, requires `maxBytes`, accepts `expectedSize` and
|
|
`sha256`, rejects unknown option keys, and deletes the file if any check fails.
|
|
|
|
Two behaviours are **deliberately not** copied:
|
|
|
|
1. **No argument shifting.** crosspoint (`LuaBindingsNet.cpp:209`) treats a string in
|
|
argument 2 of `get`/`head`/`delete` as a request *body*, so a mistyped headers table
|
|
becomes a silent protocol error. Here that raises.
|
|
2. **Certificates are verified.** crosspoint calls `setInsecure()` for every Lua request
|
|
and for `http.download`, so traffic is encrypted but unauthenticated — including the
|
|
path a firmware update would use. This firmware verifies against the root bundle
|
|
already embedded in the framework (`_binary_x509_crt_bundle_start`, ~62KB, linked
|
|
only when referenced). Verified in the emulator: `https://expired.badssl.com`
|
|
returns status `-1`, and a matching `sha256` accepts while a wrong one deletes the
|
|
file.
|
|
|
|
The cost of matching the signatures is that there is nowhere to put a per-request CA or
|
|
an insecure escape hatch, so TLS policy is device-wide and scripts cannot weaken it.
|
|
That is the right trade for a device that flashes itself.
|
|
|
|
## Stub generation
|
|
|
|
`scripts/gen_lua_stubs.py` emits `stubs/slate32.lua` in the same LuaLS `---@meta`
|
|
format crosspoint uses for `data/lua/crosspoint.lua`, so one editor setup covers both.
|
|
|
|
The parser differs: crosspoint annotates each C function and reads `addFunction(...)`
|
|
calls, while this repo annotates the `luaL_Reg` table so a module's documentation stays
|
|
contiguous with its registration.
|
|
|
|
`make test` runs `--check`. crosspoint's generator has no such wiring, so its stub can
|
|
drift from its bindings silently; that is worth copying back.
|