# Emulating and linting OpenScribe How to check each part of the project without (and with) the physical device. Everything here also runs in CI (`.forgejo/workflows/ci.yml`). ## TL;DR | Part | Lint / static check | Compile / build | Emulate / run | |------|--------------------|------------------|----------------| | Firmware | `pio check` (cppcheck) | `pio run -e esp32s3_dev` | Wokwi (`pio run -e esp32s3_wokwi` + wokwi-cli) | | Firmware logic | - | `pio test -e native` | native unit tests (host) | | Server | `ruff check app` | - | `uvicorn app.main:app` + hit `/docs` | | API spec | `openapi-spec-validator` | - | Swagger UI at `/docs` | | App | `flutter analyze` | `flutter build` | `flutter run` / emulator | | Case | - | `openscad -o out.stl ...` | OpenSCAD preview (F5) | ## Firmware (ESP32-S3) You do not need the board to catch most problems. ### 1. Compile-check (the strongest lint for C++) Install PlatformIO once (`pip install platformio`), then from `firmware/`: ```bash pio run -e esp32s3_dev # dev board profile pio run -e xiao_esp32s3 # compact profile ``` A clean build type-checks every file and every library call. This is what CI does. ### 2. Static analysis ```bash pio check -e esp32s3_dev --fail-on-defect high --skip-packages ``` Runs cppcheck across the sources. Add clang-tidy locally with `--tool clangtidy` if installed. ### 3. Native unit tests (no hardware, fast) The hardware-independent logic is factored into header-only files (`src/wav.h`, `src/httprange.h`) so it compiles and runs on your PC: ```bash pio test -e native ``` This builds and runs `test/test_pure/` against desktop GCC and checks the WAV header byte layout and the HTTP Range parser. No board, no toolchain download for Xtensa. ### 4. Emulate the running firmware with Wokwi [Wokwi](https://wokwi.com) simulates the ESP32-S3 including virtual WiFi, so you can boot the firmware, watch the serial log, and reach the REST API without hardware. Build the emulator profile (its WiFi defaults to the open `Wokwi-GUEST` network so the API comes up): ```bash pio run -e esp32s3_wokwi ``` Then either: - **VS Code:** install the "Wokwi Simulator" extension, open `firmware/`, press play. It reads `wokwi.toml` + `diagram.json`. - **CLI / CI:** with a free `WOKWI_CLI_TOKEN`, `wokwi-cli --timeout 15000 --expect-text "API at http" firmware`. Wokwi limitations to know: there is no I2S MEMS microphone part, so audio capture is not emulated (the mic reads nothing); microSD support is basic. The harness is for boot, WiFi, and the REST API surface, which is exactly what the emulator profile targets. Because the firmware brings the API up even when audio/SD init fails, `GET /api/v1/device` is reachable in the sim and reports the fault. ## Server (FastAPI) From `server/`: ```bash python -m venv .venv && . .venv/Scripts/activate # or .venv/bin/activate pip install -r requirements.txt ruff check app # lint uvicorn app.main:app --reload # run; browse http://localhost:8000/docs pytest # tests (added as endpoints gain logic in M5+) ``` `GET /health` and the stubbed recording routes are live now; the AI pipeline arrives in M5/M6. ## API spec (OpenAPI) `api/openapi.yaml` is the contract both the device and server implement. Validate it: ```bash pip install openapi-spec-validator pyyaml python -c "from openapi_spec_validator import validate; import yaml; \ validate(yaml.safe_load(open('api/openapi.yaml'))); print('OpenAPI valid')" ``` Browse it interactively by running the server (`/docs`) or pasting the file into https://editor.swagger.io. ## App (Flutter, from M7) Once the app project exists: ```bash cd app flutter pub get flutter analyze # lint + type-check flutter test # widget/unit tests flutter run # on an Android/iOS emulator or device ``` ## Case (OpenSCAD) ```bash openscad -o case_top.stl -D 'part="top"' case/openscribe_case.scad ``` `openscad --check-parameters` and a headless render catch syntax/geometry errors; the GUI preview (F5) is the visual check. ## What CI runs `.forgejo/workflows/ci.yml` on the self-hosted runner: firmware build (both profiles) + native tests + cppcheck; OpenAPI validation; a Wokwi build (and a full emulator run if `WOKWI_CLI_TOKEN` is set); server lint + import check.