Files
aes67-ESP32-P4/docs/hardware-and-design-notes.md
T
bsncubed 7bbda0a1e8 Step 7.5a: Spotify client credentials in config/UI, write-only secrets
- Core config: cfg_mark_secret(group, key). GET /api/config returns ""
  for secret keys; a POST with "" keeps the stored value, null clears it;
  cfg_get() returns the real value. Documented in aes67-core-base.md.
- source.spotify_client_id / spotify_client_secret (secret write-only):
  each user's own Spotify developer app, needed by the maintained cspot
  fork (philippe44/cspot) since Spotify's 2025 API restrictions.
- UI: client ID field, password field for the secret ("leave empty to
  keep"), link to developer.spotify.com; enabled for spotify/auto modes.
- status.spotify_state: "no client credentials" while either is missing.
- Verified: secret never appears in GET; UI-style re-save keeps it;
  survives reboot; null clears it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:16:42 +10:00

47 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ESP32-P4-ETH AES67 streamer — hardware & project notes
Core AES67 parts (PTP, TX, SDP/SAP, network/VLAN, syslog, web UI base, config schema, component layout) are in **aes67-core-base.md**. This file covers the board and the project-specific parts.
## Board: Waveshare ESP32-P4-ETH (bought as ESP32-P4-POE-ETH, i.e. with PoE add-on module)
- ESP32-P4, dual-core RISC-V HP @ 360 MHz + LP core, 32 MB in-package PSRAM, 32 MB NOR flash (confirmed with `esptool.py flash_id`)
- **No Wi-Fi/BT** on this variant (the -WIFI6- variant adds an ESP32-C6). Ethernet only.
- Ethernet: IP101GRI PHY, RMII, 100 Mb, 50 MHz ref clock from PHY (25 MHz xtal), PHY addr 1
- REF_CLK 50 (EMAC_CLK_EXT_IN), TX_EN 49, TXD0 34, TXD1 35, CRS_DV 28, RXD0 29, RXD1 30, MDC 31, MDIO 52, PHY_RST/power 51
- Audio: ES8311 codec (I2C 0x18), NS4150B amp (PA enable GPIO53), onboard mic
- I2S MCLK 13, BCLK 12, LRCK 10, DOUT(to codec) 9, DIN(from codec) 11 — Waveshare wiki lists 9/11 swapped vs ESPHome/espp; verify
- I2C SDA 7, SCL 8 (shared with DSI touch / CSI SCCB)
- Also: MIPI-CSI + MIPI-DSI FPC, USB 2.0 HS OTG (4-pin), USB-C UART, microSD 4-bit (CLK43 CMD44 D0-D3 39-42), 2x20 header
- ESP-IDF >= 5.3.1 per Waveshare.
- **Chip revision caveat** (buyer review): some boards ship engineering silicon v1.x (not v3.x). IDF 5.5+ defaults to rev3 — enable `CONFIG_ESP32P4_SELECTS_REV_LESS_V3` (check `esptool.py chip_id` output first). Binaries are not interchangeable between rev <3 and rev 3.
- Crystal-based clock: fine as PTP GM on a closed network (±tens of ppm).
- Sources: Waveshare wiki (waveshare.com/wiki/ESP32-P4-ETH), ESPHome device page (devices.esphome.io/devices/waveshare-esp32-p4-eth), espp board docs (esp-cpp.github.io/espp/dev_boards/waveshare/esp32_p4_eth.html).
## Project pipeline
source (cspot Spotify Connect | HLS player) -> decode (Vorbis/AAC/MP3) -> SRC 44.1k->48k -> volume/gain -> PSRAM ring buffer -> aes67_tx pull callback
- Spotify Connect: cspot (feelfreelinux/cspot), needs Premium, zeroconf via mDNS (on the internet interface when VLAN split). Spotify occasionally changes auth for 3rd-party clients — expect breakage risk.
- HLS: HTTPS (mbedTLS), m3u8 parse (master->media playlist), segment fetch, TS demux or fMP4/ADTS, AAC decode (esp_audio_codec / esp-gmf).
- Stereo L24/48k at 1 ms is about 3 Mbit/s on the wire; 100 Mb has plenty of headroom.
## Source mode "auto" (Spotify with HLS failover)
- Spotify Connect stays advertised the whole time. The HLS player runs whenever Spotify is not active.
- Fail over to HLS when there is no Spotify session for `failover_delay_s` seconds. With `failover_on_pause`, a paused or stopped Spotify session also counts as inactive.
- Switch back to Spotify as soon as it starts playing. Stop HLS so it doesn't use bandwidth or CPU.
- Short crossfade or ramp (~20–50 ms) at the switch to avoid clicks. The AES67 stream and SDP are unaffected.
- Firmware needs Spotify events: cspot connect, disconnect, play, pause.
## Project config group
- source: {mode: spotify|hls|auto|tone|off, spotify_name, spotify_bitrate, hls_url, autoplay, gain_db, failover_delay_s, failover_on_pause, spotify_client_id, spotify_client_secret}
- spotify_client_id / spotify_client_secret: each user's own Spotify developer app (developer.spotify.com, Premium account), needed by the maintained cspot fork (philippe44/cspot) since Spotify's 2025 API restrictions. The secret is write-only (never returned by GET /api/config). spotify_state reports "no client credentials" while either is missing.
- Project status fields: active_source, source_state, spotify_state, buffer_ms
- mode "tone": the core's 1 kHz / -18 dBFS test tone, phase-locked to PTP (commissioning, e.g. Riedel import tests). "off": silence.
## Player control API (project routes)
- GET /api/player -> {source, forced, state(playing|paused|stopped|buffering|idle), artist, title, album, position_ms, duration_ms, volume(0-100), can:{pause,next,prev,seek}}
- POST /api/player/{play|pause|toggle|stop|next|prev} (no body); every POST returns the same JSON as GET /api/player
- POST /api/player/seek {ms}; POST /api/player/volume {value} or {delta}
- POST /api/player/source {source: spotify|hls|off|config}: runtime override, not saved; "config" returns to the configured mode
- POST /api/player/url {url}: play an m3u8 now (runtime, not saved)
- On Spotify, commands go to cspot (the Spotify app stays in sync, including volume). On HLS (live): pause = stop fetching, resume = rejoin at live edge; next/prev/seek return 409 and `can` reflects that.
- Volume = runtime player volume; source.gain_db is a fixed trim on top.
- No auth yet: LAN only.