# ═══════════════════════════════════════════════════════════ # Klubhaus Doorbell — Multi-Target Build Harness # ═══════════════════════════════════════════════════════════ # Required tools [tools] hk = "latest" pkl = "latest" # Usage: # BOARD=esp32-32e-4 mise run compile # compile # BOARD=esp32-32e-4 mise run upload # upload # BOARD=esp32-32e-4 mise run monitor # monitor # BOARD=esp32-32e-4 mise run monitor-screen # screen monitor with auto-reconnect # # Valid BOARD: esp32-32e, esp32-32e-4, esp32-s3-43 [tasks.compile] description = "Compile (uses BOARD env var)" run = """ case "$BOARD" in esp32-32e) FQBN="esp32:esp32:esp32:FlashSize=4M,PartitionScheme=default" LIBS="--libraries ./vendor/esp32-32e/TFT_eSPI" OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM" ;; esp32-32e-4) FQBN="esp32:esp32:esp32:FlashSize=4M,PartitionScheme=default" LIBS="--libraries ./vendor/esp32-32e-4/TFT_eSPI" OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM" ;; esp32-s3-43) FQBN="esp32:esp32:waveshare_esp32_s3_touch_lcd_43:PSRAM=enabled,FlashSize=16M,USBMode=hwcdc,PartitionScheme=app3M_fat9M_16MB" LIBS="--libraries ./vendor/esp32-s3-lcd-43/LovyanGFX" OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM -DLGFX_USE_V1" ;; *) echo "Unknown BOARD: $BOARD" && exit 1 ;; esac arduino-cli compile --fqbn "$FQBN" --libraries ./libraries $LIBS --build-property "compiler.cpp.extra_flags=$OPTS" --warnings default ./boards/$BOARD """ [tasks.upload] description = "Upload (uses BOARD env var)" run = """ case "$BOARD" in esp32-32e) PORT="${PORT:-/dev/ttyUSB0}" ;; esp32-32e-4) PORT="${PORT:-/dev/ttyUSB0}" ;; esp32-s3-43) PORT="${PORT:-/dev/ttyACM0}" ;; *) echo "Unknown BOARD: $BOARD" && exit 1 ;; esac FQBN="" case "$BOARD" in esp32-32e) FQBN="esp32:esp32:esp32:FlashSize=4M,PartitionScheme=default" ;; esp32-32e-4) FQBN="esp32:esp32:esp32:FlashSize=4M,PartitionScheme=default" ;; esp32-s3-43) FQBN="esp32:esp32:waveshare_esp32_s3_touch_lcd_43:PSRAM=enabled,FlashSize=16M,USBMode=hwcdc,PartitionScheme=app3M_fat9M_16MB" ;; esac LIBS="" case "$BOARD" in esp32-32e) LIBS="--libraries ./vendor/esp32-32e/TFT_eSPI" ;; esp32-32e-4) LIBS="--libraries ./vendor/esp32-32e-4/TFT_eSPI" ;; esp32-s3-43) LIBS="--libraries ./vendor/esp32-s3-lcd-43/LovyanGFX" ;; esac OPTS="" case "$BOARD" in esp32-32e) OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM" ;; esp32-32e-4) OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM" ;; esp32-s3-43) OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM -DLGFX_USE_V1" ;; esac arduino-cli compile --fqbn "$FQBN" --libraries ./libraries $LIBS --build-property "compiler.cpp.extra_flags=$OPTS" --warnings default ./boards/$BOARD && \ arduino-cli upload --fqbn "$FQBN" --port "$PORT" ./boards/$BOARD """ [tasks.monitor] description = "Monitor (uses BOARD env var)" run = """ case "$BOARD" in esp32-32e) PORT="${PORT:-/dev/ttyUSB0}" ;; esp32-32e-4) PORT="${PORT:-/dev/ttyUSB0}" ;; esp32-s3-43) PORT="${PORT:-/dev/ttyACM0}" ;; *) echo "Unknown BOARD: $BOARD" && exit 1 ;; esac TARGET="$(readlink -f "$PORT" 2>/dev/null || echo "$PORT")" arduino-cli monitor -p "$TARGET" --config baudrate=115200 """ [tasks.monitor-screen] description = "Screen monitor with auto-reconnect (uses BOARD env var)" run = """ case "$BOARD" in esp32-32e) PORT="${PORT:-/dev/ttyUSB0}" ;; esp32-32e-4) PORT="${PORT:-/dev/ttyUSB0}" ;; esp32-s3-43) PORT="${PORT:-/dev/ttyACM0}" ;; *) echo "Unknown BOARD: $BOARD" && exit 1 ;; esac TARGET="$(readlink -f "$PORT" 2>/dev/null || echo "$PORT")" screen -dmS doorbell bash -c " while true; do echo \"Connecting to $TARGET...\" arduino-cli monitor -p \"$TARGET\" --config baudrate=115200 echo \"Disconnected, retrying in 3s...\" sleep 3 done " echo "Screen session 'doorbell' started. Attach with: screen -r doorbell" echo "Detach: Ctrl+A D" """ [tasks.monitor-screen-kill] description = "Kill screen-based monitor" run = """ screen -X -S doorbell quit 2>/dev/null && echo "Killed screen session 'doorbell'" || echo "No session found" """ [tasks.install-libs-shared] description = "Install shared (platform-independent) libraries" run = """ arduino-cli lib install "ArduinoJson@7.4.1" arduino-cli lib install "NTPClient@3.2.1" echo "[OK] Shared libraries installed" """ [tasks.install-libs-32e] description = "Vendor TFT_eSPI into vendor/esp32-32e" run = """ #!/usr/bin/env bash set -euo pipefail if [ ! -d "vendor/esp32-32e/TFT_eSPI" ]; then echo "Cloning TFT_eSPI..." git clone --depth 1 --branch V2.5.43 \ https://github.com/Bodmer/TFT_eSPI.git \ vendor/esp32-32e/TFT_eSPI fi echo "Copying board-specific User_Setup.h..." cp boards/esp32-32e/tft_user_setup.h vendor/esp32-32e/TFT_eSPI/User_Setup.h echo "[OK] TFT_eSPI 2.5.43 vendored + configured" """ [tasks.install-libs-32e-4] description = "Vendor TFT_eSPI into vendor/esp32-32e-4 (ST7796 320x480)" run = """ #!/usr/bin/env bash set -euo pipefail if [ ! -d "vendor/esp32-32e-4/TFT_eSPI" ]; then echo "Cloning TFT_eSPI..." git clone --depth 1 --branch V2.5.43 \ https://github.com/Bodmer/TFT_eSPI.git \ vendor/esp32-32e-4/TFT_eSPI fi echo "Copying board-specific User_Setup.h..." cp boards/esp32-32e-4/tft_user_setup.h vendor/esp32-32e-4/TFT_eSPI/User_Setup.h echo "[OK] TFT_eSPI 2.5.43 vendored + configured for 4 inch" """ [tasks.install-libs-s3-43] description = "Vendor LovyanGFX into vendor/esp32-s3-lcd-43" run = """ #!/usr/bin/env bash set -euo pipefail LOVyanGFX_DIR="vendor/esp32-s3-lcd-43/LovyanGFX" # Clone LovyanGFX (latest) if [ ! -d "$LOVyanGFX_DIR" ]; then echo "Cloning LovyanGFX..." git clone --depth 1 \ https://github.com/lovyan03/LovyanGFX.git \ "$LOVyanGFX_DIR" else echo "LovyanGFX already exists, skipping" fi # Create library.properties that correctly points to source cat > "$LOVyanGFX_DIR/library.properties" << 'EOF' name=LovyanGFX version=1.2.0 author=lovyan03 maintainer=lovyan03 sentence=Display and touch driver library for ESP32 paragraph=Universal graphics library for ESP32 with support for various displays and touch controllers category=Display url=https://github.com/lovyan03/LovyanGFX architectures=esp32 includes=LovyanGFX.hpp # This tells Arduino to build from src/ # Arduino will look in src/ for .cpp files EOF # Create a empty src to ensure sources are found mkdir -p "$LOVyanGFX_DIR/src" echo "[OK] LovyanGFX vendored" """ [tasks.install-libs] description = "Install all libraries (shared + vendored)" depends = ["install-libs-shared", "install-libs-32e", "install-libs-32e-4", "install-libs-s3-43"] # Convenience [tasks.clean] description = "Remove build artifacts" run = """ rm -rf vendor/ rm -rf boards/esp32-32e/build rm -rf boards/esp32-32e-4/build rm -rf boards/esp32-s3-lcd-43/build echo "[OK] Build artifacts cleaned" """ [tasks.format] run = """ clang-format -i --style=file \ boards/esp32-32e/*.cpp \ boards/esp32-32e/*.h \ boards/esp32-32e/*.ino \ boards/esp32-32e-4/*.cpp \ boards/esp32-32e-4/*.h \ boards/esp32-32e-4/*.ino \ boards/esp32-s3-lcd-43/*.cpp \ boards/esp32-s3-lcd-43/*.h \ boards/esp32-s3-lcd-43/*.ino \ libraries/KlubhausCore/src/*.cpp \ libraries/KlubhausCore/src/*.h \ libraries/KlubhausCore/*.properties """ [env] BOARD = "esp32-32e-4"