New panel design
This commit is contained in:
1 parent
face2432e4
commit
b5d6b4a897
30 files changed
+4540
-171
No files matched your search
+109
@@ -0,0 +1,109 @@
|
||||
# Desktop simulator
|
||||
|
||||
Runs the firmware's UI on a Linux desktop so layout work does not need a
|
||||
flash-and-look cycle. `main/ui/ui_manager.c` is compiled **unmodified** — the
|
||||
same source the device runs.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cmake -S sim -B sim/build -G Ninja
|
||||
cmake --build sim/build
|
||||
```
|
||||
|
||||
LVGL comes from `managed_components/lvgl__lvgl`, which the ESP-IDF component
|
||||
manager populates. If that directory is missing, CMake says so; run
|
||||
`. ~/esp/esp-idf/export.sh && idf.py reconfigure` once to fetch it.
|
||||
|
||||
No ESP-IDF environment is needed to *build* the simulator — only a host
|
||||
compiler, CMake, Ninja and `libsdl2-dev`.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
./sim/build/thermostat_sim # SDL window, mouse acts as touch
|
||||
./sim/build/thermostat_sim --png shot.png # render one frame, write a PNG, exit
|
||||
./sim/build/thermostat_sim --png shot.png --settle-ms 1500
|
||||
```
|
||||
|
||||
The `--png` mode is what makes UI review possible without a human at a screen:
|
||||
it renders headless, so it works over SSH and in CI, and the resulting image
|
||||
can be inspected directly.
|
||||
|
||||
Clicking a light tile in the window calls the same `ui_set_light_cb` path the
|
||||
firmware uses; the simulator applies the change locally and logs the command,
|
||||
so tiles respond with no Home Assistant present.
|
||||
|
||||
## Snapshots
|
||||
|
||||
The interesting screens — rain falling, a light dimmed, a sensor dropping out
|
||||
— do not happen on demand, and live data changes underneath a before/after
|
||||
comparison. So capture real responses and render those:
|
||||
|
||||
```bash
|
||||
export HA_TOKEN=$(cat ~/.config/thermostat-hw/ha_token)
|
||||
python3 tools/ha_snapshot.py --name rainy
|
||||
|
||||
./sim/build/thermostat_sim --data sim/snapshots/rainy.json \
|
||||
--forecast sim/snapshots/rainy.forecast.json
|
||||
```
|
||||
|
||||
Snapshots are plain JSON and are meant to be hand-edited into states that have
|
||||
not occurred yet — `sim/snapshots/evening.json` was made that way, to check
|
||||
the on/dimmed/unavailable tile styling while every real light was off.
|
||||
|
||||
`ha_snapshot.py` does **not** carry its own copy of the Jinja template. It
|
||||
reads it from `thermostat_sim --print-template`, which the preprocessor builds
|
||||
from `main/api/ha_template.h`, so a snapshot cannot be captured with a
|
||||
template the firmware does not use.
|
||||
|
||||
## How it stays honest
|
||||
|
||||
A simulator that renders differently from the panel is worse than none, so
|
||||
these are deliberately pinned to the device:
|
||||
|
||||
| Property | Value | Enforced by |
|
||||
|---|---|---|
|
||||
| Resolution | 800×480 | `PANEL_H_RES/V_RES` in `sim_main.c` |
|
||||
| Colour depth | RGB565 | `LV_COLOR_DEPTH 16` in `lv_conf.h` |
|
||||
| Render mode | `DIRECT` | `lv_conf.h` / `headless_display_create()` |
|
||||
| LVGL version | whatever IDF resolved | builds the same `managed_components` tree |
|
||||
| Fonts | Montserrat 12–48 | `lv_conf.h` **and** `sdkconfig.defaults` |
|
||||
|
||||
**The font lists must be edited together.** Enabling a size in one build and
|
||||
not the other makes the simulator lie: text silently falls back to a different
|
||||
size and every metric shifts.
|
||||
|
||||
## What it does not simulate
|
||||
|
||||
- **PSRAM bandwidth, the bounce-buffer refill ISR, and RGB scan timing.** The
|
||||
left-edge artefacts in the root README are invisible here by construction.
|
||||
This tool answers "does the layout look right", never "does the panel keep
|
||||
up". Timing-sensitive changes still need hardware.
|
||||
- **Touch hardware.** The mouse is a stand-in for the GT911: one contact
|
||||
point, pixel-accurate, no palm rejection, and none of the I2C contention the
|
||||
real panel has with the backlight controller.
|
||||
- **Anything in `main/drivers/`.** Those touch real peripherals and are never
|
||||
compiled here.
|
||||
|
||||
## Layout
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `sim_main.c` | Entry point: display setup, PNG capture, mock data |
|
||||
| `lvgl_port_sim.c` | Host implementation of the firmware's `lvgl_port.h` |
|
||||
| `compat/` | Stand-ins for the ESP-IDF headers shared sources include |
|
||||
| `lv_conf.h` | Host LVGL config, mirroring the device's Kconfig settings |
|
||||
|
||||
`compat/` exists so firmware sources compile as-is instead of growing
|
||||
`#ifdef`s. If a newly shared source fails to compile, extend `compat/` — do
|
||||
not fork the firmware source.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Montserrat has no `·` (U+00B7).** It renders as a tofu box.
|
||||
`weather_get_string()` uses one, but its output only ever reaches a log
|
||||
line. Anything routed to an on-screen label must avoid it.
|
||||
- **`lodepng_encode32_file()` does not work here.** LVGL patches its bundled
|
||||
lodepng to do file I/O through `lv_fs`, which needs a registered driver and
|
||||
drive-letter paths. `sim_main.c` encodes to memory and uses `fwrite`.
|
||||
Reference in new issue
Block a user