Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/arduino-legacy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# CI build for the frozen legacy Arduino/PlatformIO firmware.
# Lives on the arduino-maintenance branch only — never merged to main.
# Guarantees the PRD success criterion: `git checkout arduino-final` always builds.
#
# Note: GitHub only surfaces workflow_dispatch in the UI/API for workflows on the
# default branch. Manual/scheduled reproducibility builds of this branch are
# provided by .github/workflows/arduino-legacy-cold.yml on main (added in the
# phase 0 PR); this file's push/PR triggers cover changes to the branch itself.
name: arduino-legacy-build

on:
push:
branches:
- arduino-maintenance
pull_request:
branches:
- arduino-maintenance
workflow_dispatch:

jobs:
build:
name: Build legacy firmware (pinned deps)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Cache PlatformIO and pip
uses: actions/cache@v4
with:
path: |
~/.platformio/.cache
~/.cache/pip
key: pio-legacy-${{ runner.os }}-${{ hashFiles('platformio.ini') }}
restore-keys: |
pio-legacy-${{ runner.os }}-

- name: Install PlatformIO Core (pinned)
run: pip install platformio==6.1.19

- name: Build firmware
run: pio run -e wateringsystem

- name: Build LittleFS filesystem image
run: pio run -e wateringsystem -t buildfs

# if-no-files-found: error only fires when ZERO files match, so a partial
# match could silently upload an incomplete artifact set. Verify all four
# files exist before uploading.
- name: Verify all artifacts exist
run: |
test -f .pio/build/wateringsystem/firmware.bin
test -f .pio/build/wateringsystem/littlefs.bin
test -f .pio/build/wateringsystem/bootloader.bin
test -f .pio/build/wateringsystem/partitions.bin

- name: Upload flashable artifacts
uses: actions/upload-artifact@v4
with:
name: arduino-firmware
retention-days: 90
if-no-files-found: error
path: |
.pio/build/wateringsystem/firmware.bin
.pio/build/wateringsystem/littlefs.bin
.pio/build/wateringsystem/bootloader.bin
.pio/build/wateringsystem/partitions.bin
39 changes: 32 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# CLAUDE.md

> ⚠️ **MAINTENANCE BRANCH — FROZEN LEGACY FIRMWARE**
> This branch (`arduino-maintenance`) preserves the Arduino/PlatformIO firmware (v2.3.x)
> that runs the production greenhouse unit. It is NEVER merged into `main`.
> Active development happens on `main` under `firmware/` (ESP-IDF).
> All platform and library dependencies are pinned exactly in `platformio.ini`
> (do not relax the pins), and CI (`.github/workflows/arduino-legacy.yml`) is the
> canonical build. Patch flow: worktree → fix → CI build (pinned deps) → deploy to the
> production unit (serial flash — this firmware has no web-OTA endpoint) →
> tag `arduino-v2.3.x`.

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview
Expand All @@ -19,6 +29,12 @@ WateringSystem v2.3 is a production-ready embedded IoT system for automated gree

### Essential Build Commands

**CI is the canonical build:** every push to `arduino-maintenance` runs
`.github/workflows/arduino-legacy.yml`, which builds with exactly pinned
dependencies and uploads a fully flashable artifact set (`firmware.bin`,
`littlefs.bin`, `bootloader.bin`, `partitions.bin`). Local PlatformIO builds
are optional and only needed for flashing/monitoring over USB.

```bash
# Build the project
platformio run --environment wateringsystem
Expand Down Expand Up @@ -115,7 +131,7 @@ The codebase follows strict interface-based design with clean separation of conc
### Development Server
- **Framework:** ESPAsyncWebServer with LittleFS file storage
- **Features:** Real-time sensor monitoring, pump control, configuration management
- **OTA Updates:** Web-based firmware updates via /update endpoint
- **Firmware Updates:** No web-OTA endpoint exists in this firmware; updates are flashed over serial (use the CI artifacts: firmware.bin, littlefs.bin, bootloader.bin, partitions.bin)
- **WiFi Configuration:** AP mode setup at 192.168.4.1 when unconfigured

### API Endpoints Structure
Expand Down Expand Up @@ -178,15 +194,24 @@ The system includes comprehensive diagnostic commands accessible via Serial moni

## Key Dependencies

All dependencies are pinned to exact versions (the known-good set that built the
production binary). Never reintroduce `^`/`~` ranges or unpinned entries on this branch.

```ini
lib_deps =
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit Unified Sensor@^1.1.6
bblanchon/ArduinoJson@^6.20.0
me-no-dev/AsyncTCP
me-no-dev/ESPAsyncWebServer
platform = espressif32@6.12.0
lib_deps =
adafruit/Adafruit BME280 Library@2.2.4
adafruit/Adafruit Unified Sensor@1.1.15
bblanchon/ArduinoJson@6.21.5
me-no-dev/AsyncTCP@3.3.2
me-no-dev/ESPAsyncWebServer@3.6.0
adafruit/Adafruit BusIO@1.17.0 ; transitive pin (BME280 dep)
```

Note: ESPAsyncWebServer also installs ESP32Async/AsyncTCP transitively, but only the
direct `me-no-dev/AsyncTCP@3.3.2` copy is linked (same as the production build). Do not
add the esp32async copy to `lib_deps` — it causes multiple-definition linker errors.

## System Monitoring & Maintenance

### Status Indicators
Expand Down
36 changes: 26 additions & 10 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,23 @@
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
;
; FROZEN LEGACY CONFIGURATION (arduino-maintenance branch)
; All platform and library versions are pinned exactly to the known-good
; set that produced the April 2026 production binary. Do NOT relax these
; pins on this branch — reproducibility is the whole point.

[env:wateringsystem]
platform = espressif32
platform = espressif32@6.12.0
board = esp32dev
framework = arduino
upload_port = COM4
monitor_port = COM4
; Builds are CI-only (see .github/workflows/arduino-legacy.yml); serial ports
; are machine-specific, so the upload/monitor ports are intentionally not set.
; Uncomment and adjust locally if you need to flash/monitor over USB.
; upload_port = COM4
; monitor_port = COM4
monitor_speed = 115200
build_flags =
build_flags =
-D VERSION=0.1.0
-D DEBUG=1
; Prevent conflict with ESP header HTTP method macros by undefining them before ESPAsyncWebServer includes
Expand All @@ -34,11 +42,19 @@ build_flags =
-UHTTP_PATCH
-UHTTP_HEAD
-UHTTP_OPTIONS
lib_deps =
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit Unified Sensor@^1.1.6
bblanchon/ArduinoJson@^6.20.0
me-no-dev/AsyncTCP
me-no-dev/ESPAsyncWebServer
lib_deps =
adafruit/Adafruit BME280 Library@2.2.4
adafruit/Adafruit Unified Sensor@1.1.15
bblanchon/ArduinoJson@6.21.5
me-no-dev/AsyncTCP@3.3.2
me-no-dev/ESPAsyncWebServer@3.6.0
; Transitive dependency pinned explicitly (pulled in by Adafruit BME280):
adafruit/Adafruit BusIO@1.17.0
; NOTE: ESPAsyncWebServer 3.6.0 also declares ESP32Async/AsyncTCP@^3.3.2,
; which gets *installed* alongside me-no-dev/AsyncTCP@3.3.2, but the LDF
; links only the direct lib_deps copy (3.3.2) — verified identical to the
; known-good April 2026 build. Do NOT add esp32async/AsyncTCP to lib_deps;
; that promotes it to a linked dependency and causes multiple-definition
; linker errors against the 3.3.2 copy.
board_build.filesystem = littlefs
board_build.partitions = default.csv
Loading