diff --git a/README.md b/README.md index c76e293..96c5414 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,12 @@ MQTT-based gauge controller for ESP32 / MicroPython. Drives a VID28/BKA30D/X25 s |------|-------------| | `boot.py` | WiFi connect + OTA trigger | | `ota.py` | Gitea API poller for OTA updates | -| `gaugemqtt.py` | Main MQTT controller | -| `gauge.py` | Stepper driver for VID28/BKA30D/X25 gauges | -| `config.json` | Configuration (create from `config.example.json`) | +| `ota_config.json` | OTA config (create from `ota_config.example.json`) | +| `ota_config.example.json` | OTA config template | +| `gaugemqttcontinuous.py` | Main MQTT controller | +| `gauge_vid6008.py` | Stepper driver for VID28/BKA30D/X25 gauges | +| `main.py` | Entry point, calls `ota.mark_ok()` on success | +| `config.json` | Application config (create from `config.example.json`) | | `config.example.json` | Template with all options | ## Deployment @@ -19,10 +22,11 @@ MQTT-based gauge controller for ESP32 / MicroPython. Drives a VID28/BKA30D/X25 s # First time: upload via USB ampy --port /dev/ttyUSB0 put boot.py ampy --port /dev/ttyUSB0 put ota.py -ampy --port /dev/ttyUSB0 put gaugemqtt.py -ampy --port /dev/ttyUSB0 put gauge.py +ampy --port /dev/ttyUSB0 put ota_config.json +ampy --port /dev/ttyUSB0 put main.py +ampy --port /dev/ttyUSB0 put gaugemqttcontinuous.py +ampy --port /dev/ttyUSB0 put gauge_vid6008.py ampy --port /dev/ttyUSB0 put config.json -ampy --port /dev/ttyUSB0 put lib/gauge.py /lib/gauge.py # Monitor serial output minicom -D /dev/ttyUSB0 -b 115200 @@ -39,19 +43,19 @@ All topics are prefixed with `mqtt_prefix`: | `/status` | → | `online`/`offline` | | `/zero` | ← | Trigger zero calibration | | `/led/red/set` | ← | `ON`/`OFF` | +| `/led/red/state` | → | `ON`/`OFF` | | `/led/green/set` | ← | `ON`/`OFF` | -| `/led/backlight/set` | ← | Brightness 0-100 | +| `/led/green/state` | → | `ON`/`OFF` | +| `/led/backlight/set` | ← | `{"state": "ON"/"OFF", "color": {"r","g","b"}, "brightness": 0-255}` | +| `/led/backlight/state` | → | Current backlight state | ## Configuration -Copy `config.example.json` to `config.json` and edit: +Copy `config.example.json` to `config.json` and `ota_config.example.json` to `ota_config.json` and edit: ### WiFi -| Key | Default | Description | -|-----|---------|-------------| -| `wifi_ssid` | — | WiFi network name | -| `wifi_password` | — | WiFi password | +WiFi credentials are in `ota_config.json` (shared with OTA settings), not `config.json`. ### MQTT @@ -68,7 +72,8 @@ Copy `config.example.json` to `config.json` and edit: | Key | Default | Description | |-----|---------|-------------| -| `gauge_pins` | `[12, 13, 26, 27]` | GPIO pins (IN1, IN2, IN3, IN4) | +| `gauge_pins` | `[12, 13]` | GPIO pins (`4phase`: IN1-4, `stepdir`: DIR, STEP) | +| `gauge_mode` | `stepdir` | Driver mode: `stepdir` (DIR+STEP) or `4phase` (full-wave) | | `gauge_min` | 0 | Minimum value | | `gauge_max` | 7300 | Maximum value | | `gauge_pulse` | 4 | Pulse width in milliseconds | @@ -77,13 +82,26 @@ Copy `config.example.json` to `config.json` and edit: | `idle_release_ms` | 3000 | Release coils after idle (ms) | | `rezero_interval_ms` | 3600000 | Auto-rezero interval (ms, default 1hr) | +### OTA + +| Key | Default | Description | +|-----|---------|-------------| +| `gitea_base` | — | Gitea server URL (no trailing slash) | +| `repo_owner` | — | Repository owner | +| `repo_name` | — | Repository name | +| `repo_folder` | — | Folder inside repo to sync | +| `repo_branch` | `main` | Branch to track | +| `api_token` | — | API token for private repos | +| `wifi_ssid` | — | WiFi network name | +| `wifi_password` | — | WiFi password | + ### LEDs | Key | Default | Description | |-----|---------|-------------| | `led_red_pin` | 33 | Red LED GPIO pin | | `led_green_pin` | 32 | Green LED GPIO pin | -| `led_bl_pin` | 23 | Backlight PWM GPIO pin | +| `led_bl_pin` | 23 | RGB backlight (WS2812/NeoPixel) GPIO pin | ### Home Assistant Discovery @@ -105,3 +123,23 @@ Copy `config.example.json` to `config.json` and edit: | Key | Default | Description | |-----|---------|-------------| | `heartbeat_ms` | 10000 | State publish interval (ms) | + +## OTA Updates + +On each boot, `boot.py` connects WiFi and runs `ota.update()`. The updater: + +1. If last boot was good and commit unchanged → skip file check entirely +2. Otherwise, compares file SHA1 hashes with local manifest +3. Downloads changed/missing files to `.tmp`, then renames into place +4. On success, saves manifest with commit SHA; `main.py` writes OK flag + +### Manifest + +Create `ota_manifest.txt` in your repo root to specify which files to sync: + +``` +boot.py # specific file +main.py # another file +*.py # wildcard (matches anywhere) +selsyn/ # entire directory (trailing slash) +``` diff --git a/config.example.json b/config.example.json index 547e482..f2f1a8d 100644 --- a/config.example.json +++ b/config.example.json @@ -18,7 +18,7 @@ "rezero_interval_ms": 3600000, "led_red_pin": 33, "led_green_pin": 32, - "led_bl_pin": 23, + "led_bl_pin": 3, "device_name": "Selsyn 1", "device_model": "Chernobyl Selsyn-inspired gauge", "device_manufacturer": "AdeBaumann",