fix: replace EncryptedSharedPreferences with plain MODE_PRIVATE for update survival

This commit is contained in:
eddy 2026-07-29 18:51:21 +02:00
commit 34d3db445e
7 changed files with 906 additions and 19 deletions

View file

@ -0,0 +1,127 @@
# ESP32-PICO-D4 (M5Stack Atom Lite) Port — Design Spec
> **Goal:** Port the Sylvia Touch Relay project from ESP32-S3-Pico (Atom VoiceS3R) to ESP32-PICO-D4 (Atom Lite), update the Android app for CDC-class USB detection, compile, bundle, and deploy via ADB wireless.
## Current State
The project targets the M5Stack Atom VoiceS3R with ESP32-S3-PICO-1-N8R8 (8MB Flash, 8MB PSRAM). The Android app filters USB devices by Espressif vendor ID (`0x303A`) for key exchange and firmware flashing. The `esp32-flash-lib` handles DTR/RTS via the `SerialTransport` interface implemented by `UsbSerialTransport`.
## Target Hardware
M5Stack Atom Lite with ESP32-PICO-D4:
- 4MB Flash (no PSRAM)
- FTDI FT2232C/D USB-to-UART bridge (VID `0x0403`) — appears as `/dev/ttyUSB0`
- SK6812 addressable RGB LED on GPIO27
- Relay on GPIO32 (G32)
- Touch sensor on GPIO33 (G33) — open-drain type, needs pullup
## Design Decisions
### 1. Side Branch & Git Worktree
Create branch `esp32picod4` via git worktree at `.worktrees/esp32picod4` to isolate the port from the main S3 variant.
### 2. Firmware (`platformio.ini` + `src/main.cpp`)
**New PlatformIO environment `m5stack-atom`:**
| Setting | Old (S3) | New (PICO-D4) | Reason |
|---------|----------|---------------|--------|
| `board` | `esp32-s3-devkitc-1` | `m5stack-atom` | PlatformIO board ID for M5Stack Atom Lite |
| `board_build.arduino.memory_type` | `qio_opi` | removed | Not needed for PICO-D4 |
| `-DESP32S3` | present | `-DESP32` | Correct chip family |
| `-DBOARD_HAS_PSRAM` | present | removed | Atom Lite has no PSRAM |
| `-mfix-esp32-psram-cache-issue` | present | removed | Only needed with PSRAM |
| `-DARDUINO_USB_CDC_ON_BOOT=1` | present | removed | No native USB on PICO-D4 |
| `-DARDUINO_USB_MODE=1` | present | removed | No native USB |
| `upload_port` | `/dev/ttyACM0` | `/dev/ttyUSB0` | FTDI serial device |
| `lib_deps` | (empty) | `fastled/FastLED@^3.7` | SK6812 Neopixel library |
**Pin definitions:**
| Constant | Old | New | Notes |
|----------|-----|-----|-------|
| `SENSOR_PIN` | 38 | 33 | G33, open-drain, `INPUT_PULLUP` unchanged |
| `RELAY_PIN` | 1 | 32 | G32 |
| `LED_PIN` | 27 | 27 | SK6812 Neopixel — replaces `digitalWrite` with FastLED API |
**BLE device name:** `"SyldaServer"` (was `"AtomS3R-Relay"`)
**Serial banner:** `"Atom Lite BLE Relay"` (was `"Atom VoiceS3R BLE Relay"`)
**LED code change:** Replace `digitalWrite(LED_PIN, HIGH/LOW)` with FastLED:
- Include `FastLED.h`
- Define `#define NUM_LEDS 1`
- `CRGB leds[NUM_LEDS]`
- `FastLED.addLeds<SK6812, LED_PIN, GRB>(leds, NUM_LEDS)` in setup
- Startup blink: 3x green (`leds[0] = CRGB::Green; FastLED.show()`)
No other firmware logic changes — HMAC key exchange, BLE relay control, touch sensor logic remain identical.
### 3. Android USB Detection
**Problem:** The Atom Lite's FTDI bridge presents VID `0x0403`, not Espressif's `0x303A`. The app currently filters on VID and won't detect the device.
**Solution:** Replace VID (`0x303A`) filtering with CDC-ACM class filtering (interface class `0x0A`).
**Changes in `UsbUtils.kt`:**
- Add `hasCdcDataInterface(device: UsbDevice): Boolean` — iterates interfaces, returns true if any has `interfaceClass == 0x0A`
**Changes in `SettingsActivity.kt`:**
- Remove `ESP_VENDOR_ID` constant
- Replace all `device?.vendorId == ESP_VENDOR_ID` checks with `UsbUtils.hasCdcDataInterface(device)`
This detects all CDC-ACM serial devices including:
- FTDI FT2232C/D (Atom Lite)
- CP210x (some Atom Lite revisions)
- ESP32-S3 native USB (current hardware)
- CH340/CH9102 (other Atom variants)
### 4. DTR/RTS — No Changes Needed
**Research findings:**
The `esp32-flash-lib`'s `EspFlasherProtocol.enterBootLoader()` implements the standard DTR/RTS download-mode sequence:
```
setControlLines(true, false) // DTR=High → EN released, RTS=Low → GPIO0=Low (download mode)
delayMS(100)
setControlLines(false, true) // DTR=Low → reset pulse via capacitor, RTS=High → GPIO0=High
delayMS(100)
setControlLines(true, false) // DTR=High → release reset, RTS=Low → GPIO0=Low → boot in download mode
```
The `UsbSerialTransport.setControlLines()` implementation sends `CDC_SET_CONTROL_LINE_STATE` control transfers with correct DTR/RTS bit flags. This works for FTDI, CP2104, and native USB CDC-ACM.
The `SettingsActivity.setupCdcControl()` sets DTR|RTS both HIGH for normal serial operation (key exchange), which is correct for all bridge types.
**Verdict: No changes to `EspFlasher.kt`, `UsbSerialTransport.kt`, or key exchange logic.**
### 5. Build, Bundle & Deploy
1. `pio run -e m5stack-atom` to compile firmware
2. `tools/copy_firmware.sh` to copy binaries to `android/app/src/main/assets/firmware/` (environment dir is now `m5stack-atom`)
3. `./gradlew assembleDebug` in `android/` to build APK
4. ADB wireless to connect phone (`adb-wireless` skill)
5. `adb install -r app-debug.apk` to deploy
## Files Changed
| File | Change |
|------|--------|
| `platformio.ini` | New environment `m5stack-atom` replacing S3 config |
| `src/main.cpp` | New pin definitions, BLE name, FastLED LED code |
| `android/.../UsbUtils.kt` | Add `hasCdcDataInterface()` |
| `android/.../SettingsActivity.kt` | VID filter → CDC class filter |
| `tools/copy_firmware.sh` | Environment name `m5stack-atoms3r` → `m5stack-atom` |
## Files Not Changed
| File | Reason |
|------|--------|
| `EspFlasher.kt` | DTR/RTS handled by library |
| `UsbSerialTransport.kt` | Correct implementation |
| `MainActivity.kt` | No BLE changes beyond device name (auto-discovered) |
| `PrefsHelper.kt` | No changes |
| `AndroidManifest.xml` | No changes |
| `build.gradle` | No dependency changes |