desk-beam-------ESP32-S31 Desktop Secondary Screen Companion — Lyrics Display · Ambient Light · DeepSeek Usage Monitoring

This content is AI-translated and may differ from the original.


<h1 align="center">desk-beam</h1>

<p align="center">

 <em>ESP32-S31 desktop secondary-screen companion — lyric display · ambient lighting · DeepSeek usage monitoring</em>

</p>




<p align="center">

 <img alt="License" src="https://img.shields.io/badge/license-MIT-green"/>

 <img alt="ESP-IDF" src="https://img.shields.io/badge/ESP--IDF-v6.2-blue"/>

 <img alt="LVGL" src="https://img.shields.io/badge/LVGL-8.4-purple"/>

 <img alt="Platform" src="https://img.shields.io/badge/platform-ESP32--S31-orange"/>

</p>


---


## 📖 Overview


**desk-beam** is a desktop secondary screen based on ESP32-S31, connecting to a PC-side service via WiFi/WebSocket, providing:


- 🎵 **Desktop lyrics + album cover** — sync scrolling lyrics and cover art from QQ Music, NetEase Cloud, etc.

- 🖼️ **Album cover display** — Now Playing mode shows the current song's cover (added in v2.0.0)

- 💡 **WS2812 ambient light** — reacts to music (pulse/breath/rainbow)

- 🎮 **Music remote** — remote playback control via ADC buttons

- 📊 **DeepSeek usage monitoring** — real-time view of API balance and consumption

- 🗂️ **SD card storage** — cache lyrics/cover and store configuration (added in v2.0.0)


```

QQ音乐/网易云 → Windows SMTC → PC 桥接服务 → WebSocket → ESP32 → LVGL 屏幕 + WS2812

```


---


## ✨ Features


- **Full-screen lyric interface** — LVGL 8.4 rendering, 6-line scroll, 4 display modes (lyrics/now playing/spectrum/info)

- **Chinese display** — pre-rendered Noto Sans SC Chinese font (20px + 28px RLE compressed)

- **WS2812 ambient light** — 3 LEDs, 4 effect modes (pulse/breath/rainbow/off), adjustable brightness

- **DeepSeek usage visualization** — balance card + consumption bar chart + model detail table

- **WiFi auto-connect** — STA mode + event group sync + timeout protection

- **WebSocket full-duplex** — auto-reconnect (exponential backoff) + JSON protocol

- **SD card support** — SDMMC 4-bit FATFS mount (optional)

- **Touch interaction** — GT1151 touch + ADC button dual input

- **Album cover display** — Now Playing mode shows album cover cached on SD card


---


## 🖥️ Demo


| Music lyric screen | Album cover screen (v2.0.0) | DeepSeek usage screen |

|:---:|:---:|:---:|

| ![音乐歌词屏](image/music.jpg) | ![专辑封面](image/music1.jpg) | ![DeepSeek 用量屏](image/deepseek_usage.jpg) |

| DeepSeek usage improvements (v2.0.0) | New lyric page interface (v2.0.0) | |

| ![DeepSeek 改进](image/deepseek_usage1.jpg) | ![歌词新界面](image/music2.jpg) | |


---


## 🛠️ Hardware


### Bill of Materials


| Component | Model | Quantity |

|------|------|:----:|

| SoC development board | ESP32-S31-Korvo-2-LCD | ×1 |

| LCD screen | ST7262E43 800×480 RGB565 parallel interface | ×1 |

| Touch chip | GT1151 (I2C) | ×1 |

| RGB LED | WS2812 | ×3 |

| SD card | microSD (for extended storage) | ×1 |

| Power | 5V USB-C | ×1 |


### Pin Definitions


| Function | GPIO | Bus |

|------|:----:|------|

| LCD data | GPIO8~36 (16bit) | RGB565 parallel |

| LCD sync | HSYNC=44, VSYNC=45, DE=43, PCLK=40 | — |

| Touch I2C | SDA=0, SCL=1 | I2C |

| WS2812 | GPIO37 | RMT TX |

| ADC buttons | GPIO42 | voltage‑divider array (×4 buttons) |

| SD card | CLK=24, CMD=25, D0~D3=20~23 | SDMMC 4-bit |


> See pin‑definition details in components/bsp/include/bsp/bsp_board.h


---


## 🚀 Quick Start


### 1️⃣ Environment Setup


- **ESP-IDF** v6.2+ (target chip `esp32s31`)

- **PSRAM** enabled (required for LVGL display buffer)

- Install dependencies:


```bash

# ESP-IDF component manager automatically installs LVGL + WebSocket etc.

idf.py set-target esp32s31

idf.py build

```


### 2️⃣ Configure WiFi and PC address


**Modify the configuration section in `main/main.c`:**


```c

// Lines 50‑57 — replace with your own info

#define WIFI_SSID "你的WiFi名称" // 2.4GHz only

#define WIFI_PASSWORD "你的WiFi密码"

#define PC_HOST "192.168.1.100" // IP of the PC running the service

#define PC_WS_PORT 8765 // WebSocket port (default)

```


> ⚠️ **Important**: Before committing, ensure `WIFI_SSID` / `WIFI_PASSWORD` are reverted to the placeholder `"xxxxxxxx"` to avoid exposing home WiFi credentials.


### 3️⃣ Flash


```bash

idf.py -p COMx flash monitor

```


### 4️⃣ Start PC-side service


See the [PC 端服务](#pc-端服务) section.


---


## 🏗️ Architecture


### Software Layers


```

┌─────────────────────────────────────────────────────────────┐

│ Application layer (main/) │

│ app_music_screen app_deepseek_screen app_led_effects │

│ app_ws_client app_network app_logic │

├─────────────────────────────────────────────────────────────┤

│ Hardware abstraction layer (components/) │

│ hal_display hal_led hal_key hal_sdcard bsp │

├─────────────────────────────────────────────────────────────┤

│ Middleware (managed_components/) │

│ LVGL 8.x esp_lvgl_port esp_websocket_client cJSON │

├─────────────────────────────────────────────────────────────┤

│ FreeRTOS + ESP-IDF │

└─────────────────────────────────────────────────────────────┘

```


### Task Scheduling


| Task | Priority | Stack size | Core | Responsibility |

|------|:------:|:------:|:----:|------|

| LVGL main loop | — | Inherited | — | `lv_timer_handler()` driver |

| `hal_key` | 5 | 4KB | — | ADC button scan + debounce |

| `app_ws` | 4 | 8KB | 0 | WebSocket send/receive + dispatch |

| `network_task` | 3 | 8KB | — | WiFi connect + status monitor |

| `app_led_effects` | 3 | 2KB | — | WS2812 effect frame rendering |


### Startup Flow


```

app_main()

├─ BSP init

├─ LCD init (RGB parallel)

├─ LVGL port registration (display+touch)

├─ Music screen creation

├─ DeepSeek screen creation

├─ LED effect task start

├─ Button scan task start

├─ Network task start (WiFi → WebSocket)

└─ LVGL main loop

```


---


## 💻 PC-side Service


### Install and start


```bash

cd pc_tools

pip install -r requirements.txt

python windows_media_server.py

```


After starting, it listens on `ws://0.0.0.0:8765`; the console prints the local LAN IP address, to be set in ESP32's `PC_HOST`.


### Lyric query priority


| Source | Description |

|------|------|

| 🥇 QQ Music API | SMTC Track ID direct, most accurate |

| 🥈 NetEase Cloud Music API | Generic title+artist search |

| 🥉 LRCLIB | Overseas public API fallback |


### Hotkeys


| Key | Function |

|:----:|------|

| `P` | Pause/resume WebSocket broadcast |

| `Q` | Quit server |


### DeepSeek usage data integration


The PC side can read a local JSON file and push DeepSeek API usage data to the ESP32 for display.


#### Command-line mode (direct file path)


```bash

python windows_media_server.py --deepseek-file D:\path\to\deepseek_usage_data.json

```


#### Integrated WorkBuddy automated scraping (recommended)


This project includes a WorkBuddy Skill that automatically scrapes the DeepSeek usage page every hour, generating a JSON file for the ESP32 to read.


**Data flow:**


```

Edge browser (logged into platform.deepseek.com)

↓ CDP automated scrape (once per hour)

deepseek_usage_data.json (local file)

↓ windows_media_server.py reads every 300 s

WebSocket → deepseek_usage message

ESP32 screen (DeepSeek usage page)

```


**Prerequisites:**


1. [Install WorkBuddy](https://workbuddy.ai) (Claude Code plugin)

2. Log into Edge browser at [platform.deepseek.com](https://platform.deepseek.com)

3. Enable Edge remote debugging: visit `edge://inspect/#remote-debugging` and check **"Allow remote debugging for this browser instance"**

4. Install the Skill file (see below)


#### WorkBuddy Skill installation


```bash

# Skill definition

Comments (0)

Comments

Sign in to leave a comment

No data
No data