# ESP32-C3 状态灯客户安装与测试说明

这是一份给 Windows 用户的开箱安装与使用说明。按照下面步骤操作，可以完成：

1. 第一次打开本地网页演示
2. 让网页连接 Codex 状态
3. 将程序下载到 ESP32-C3
4. 用 Python 做真实灯板测试
5. 在 Codex 中接入真实状态灯

本文尽量按“小白也能照着做”的方式写。

## 一键入口

如果你不想再手动启动多个 `.ps1`，现在可以直接双击下面几个文件：

- `一键启动全套程序.cmd`
  会自动启动网页服务、Codex WebSocket bridge、ESP32 串口 daemon，并打开浏览器到 `http://localhost:2026`
- `一键停止全套程序.cmd`
  会停止上面这套后台服务
- `一键测试状态灯.cmd`
  会直接打开手工测试菜单，对灯板发送 `IDLE`、`THINKING`、`DONE` 等命令

说明：

- `一键启动全套程序.cmd` 不会重复烧录固件，它只负责运行整套软件
- 第一次启动时如果本地 `.venv` 缺失或损坏，会自动重建并安装 `requirements.txt`
- 如果串口被常见测试程序占用，启动器会先尝试自动清理，再启动真实灯板 daemon

## 先看这里：客户第一次应该运行什么

你可以根据手上的情况选择一种使用方式。

### A. 没有连接开发板，只想看网页演示

只需要启动网页展示服务：

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

然后打开：

```text
http://localhost:2026
```

右侧保持默认：

```text
数据来源 → Web Demo
```

这个模式不连接真实 Agent，也不需要开发板。

### B. 想让网页跟随 Codex 状态变化

需要启动两个服务。

第一个 PowerShell：启动网页。

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

第二个 PowerShell：启动 Codex WebSocket bridge。

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_codex_ws_bridge.ps1
```

然后打开：

```text
http://localhost:2026
```

右侧选择：

```text
数据来源 → Codex
```

如果连接成功，页面会显示“已连接”。

### C. 想让真实 ESP32-C3 状态灯跟随 Codex

需要连接开发板，并启动串口后台进程：

```powershell
.\start_codex_light_daemon.ps1
```

这个进程会读取 Codex 状态和 token，用串口发给真实灯板。

### 三个服务不要混淆

| 脚本 | 作用 | 端口 |
| --- | --- | --- |
| `local_demo\start_server_2026.ps1` | 启动网页展示 | `2026` |
| `local_demo\start_codex_ws_bridge.ps1` | 启动网页 Codex 数据源 | `8765` |
| `start_codex_light_daemon.ps1` | 启动真实开发板串口通信 | `37637` |

第一次给客户演示，推荐先跑 A；确认网页正常后，再跑 B；最后有开发板时再跑 C。



有经验的客户请直接跳转到第14步，[14. 速通版](##14. 速通版)

直接买成品、暂时不想烧录固件的客户，建议先看第4B步网页演示；要测试真实灯板再看第8步。

## 0. 你会拿到什么

目录结构如下：

```powershell
sketch_may27a/
├─ .codex/
├─ agent_light_control.py
├─ codex_light_hook.py
├─ codex_light_serial.py
├─ requirements.txt
├─ start_codex_light_daemon.ps1
├─ setup_esp32c3_test_env.ps1
├─ build_esp32c3.ps1
├─ flash_esp32c3.ps1
├─ sketch_may27a.ino
├─ local_demo/
│  ├─ index.html
│  ├─ start_server_2026.ps1
│  ├─ start_codex_ws_bridge.ps1
│  ├─ codex_ws_bridge.py
│  └─ server_2026.py
└─ python_test_tools/
```

建议把整个文件夹放到：

```powershell
C:\Users\你的用户名\Documents\Arduino\sketch_may27a
```

## 1. 硬件准备

需要准备：

- 一根支持数据传输的 USB 线
- 成品AI状态灯

注意：

- USB 线必须是“数据线”，不能只是充电线
- 如果电脑上插了多个串口设备，后面看到的 `COM` 口可能不是固定数字，这属于正常情况

## 2. 安装 Python 3

### 2.1 检查是否已经安装

打开 PowerShell，输入：

```powershell
python --version
```

如果能看到类似：

```powershell
Python 3.10.6
```

就说明已经安装好了。

### 2.2 如果没有安装

去 Python 官网下载安装 Python 3。

安装时务必勾选：

```powershell
Add python.exe to PATH
```

安装完成后，关闭 PowerShell，再重新打开，再执行一次：

```powershell
python --version
```

## 3. 安装 Arduino CLI

Arduino CLI 是用来编译和下载 ESP32-C3 固件的命令行工具。

如果你只想先跑网页演示，可以暂时跳过 Arduino CLI。只有需要烧录 ESP32-C3 固件时才必须安装。

### 3.1 最简单安装方式

在 PowerShell 中输入：

```powershell
winget install ArduinoSA.CLI
```

安装完成后，关闭 PowerShell，再重新打开。

### 3.2 检查是否安装成功

输入：

```powershell
arduino-cli version
```

如果能看到版本号，就说明安装成功。

## 4. 打开项目目录

在 PowerShell 中进入项目目录：

```powershell
Set-Location C:\Users\你的用户名\Documents\Arduino\sketch_may27a
```

如果你的文件夹不在这个位置，请换成你自己的实际路径。

## 4A. 安装本项目 Python 依赖

网页演示、Codex WebSocket bridge、串口通信都需要 Python 依赖。

在项目根目录执行：

```powershell
python -m venv .venv
.\.venv\Scripts\python -m pip install -r requirements.txt
```

正常情况下会安装：

- `pyserial`：用于串口通信
- `websockets`：用于网页 Codex 数据源

如果看到 `Successfully installed`，说明依赖安装成功。

后面的脚本会优先使用项目里的：

```text
.venv\Scripts\python.exe
```

这样不会污染系统 Python，也不容易因为系统权限导致安装失败。

## 4B. 第一次开箱：先跑网页演示

这一步不需要开发板，也不需要 Codex。适合客户刚收到文件后先确认展示效果。

在项目根目录执行：

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

PowerShell 窗口不要关闭。然后打开浏览器访问：

```text
http://localhost:2026
```

右侧默认是：

```text
数据来源 → Web Demo
```

这个模式可以直接用右侧按钮测试：

- `IDLE`
- `THINKING`
- `WRITING`
- `RUNNING`
- `DONE`
- `ERROR`
- `NEED_CONFIRM`

也可以拖动 Token 滑块，看中心显示区和进度条变化。

如果打不开网页，请确认：

- 启动网页的 PowerShell 窗口还在运行
- 浏览器地址是 `http://localhost:2026`
- 没有其他程序占用 `2026` 端口

## 4C. 网页连接 Codex 状态

这一步用于让网页自动接收 Codex 状态。需要同时启动网页服务和 Codex WebSocket bridge。

第一个 PowerShell：启动网页。

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

第二个 PowerShell：启动 Codex WebSocket bridge。

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_codex_ws_bridge.ps1
```

然后打开：

```text
http://localhost:2026
```

右侧选择：

```text
数据来源 → Codex
```

连接成功时，页面会显示：

```text
Codex：已连接
```

如果显示“Codex 状态服务未启动”，说明 `start_codex_ws_bridge.ps1` 没有启动成功。

### 4C.1 手动测试 Codex bridge

启动 `start_codex_ws_bridge.ps1` 的 PowerShell 窗口里可以直接输入：

```text
thinking
writing
running
done
error
token 68
```

每输入一行回车，网页都会收到状态并更新灯效。

### 4C.2 用日志文件测试 Codex bridge

也可以往这个文件追加内容：

```text
local_demo\codex_status.log
```

例如在项目根目录执行：

```powershell
Add-Content .\local_demo\codex_status.log "thinking"
Add-Content .\local_demo\codex_status.log "token 68"
Add-Content .\local_demo\codex_status.log "done"
```

网页应该会跟随变成 `THINKING`、`Token 68%`、`DONE`。

## 5. 一键安装 ESP32-C3 所需环境

在项目目录执行：

```powershell
.\setup_esp32c3_test_env.ps1
```

这个脚本会自动检查并安装：

- ESP32 开发板核心
- Adafruit 相关库
- Python 依赖 `pyserial` 和 `websockets`
- 项目本地虚拟环境 `.venv`

如果最后看到了类似：

```powershell
Detected ESP32 port: COM40
```

说明电脑已经识别到了开发板。

## 6. 查看开发板端口

插好 ESP32-C3 后，在项目目录执行：

```powershell
arduino-cli board list
```

你会看到类似：

```powershell
COM40 serial Serial Port (USB) ESP32 Family Device
```

这里的 `COM40` 就是当前开发板端口。

注意：

- 这个端口号可能会变
- 今天是 `COM40`，明天可能变成 `COM38`
- 这是正常现象，不代表设备坏了

## 7. 编译并下载程序到 ESP32-C3

### 7.1 推荐方式：直接使用项目自带脚本

在项目目录执行：

```powershell
.\flash_esp32c3.ps1
```

这个脚本会自动做两件事：

1. 编译程序
2. 下载到当前检测到的 ESP32-C3

### 7.2 成功的典型输出

成功时一般能看到类似：

```powershell
Connected to ESP32-C3 on COM40
Hash of data verified.
Hard resetting via RTS pin...
```

### 7.3 如果下载失败

优先检查这几项：

- 是否使用了支持数据传输的 USB 线
- 是否选中了正确的开发板
- 是否有别的软件占用了串口
- 是否把 Arduino IDE 的串口监视器关掉了
- 是否把 Python 测试程序关掉了

## 8. 用 Python 做简单测试

### 8.1 进入 Python 测试目录

```powershell
Set-Location C:\Users\你的用户名\Documents\Arduino\sketch_may27a\python_test_tools
```

### 8.2 安装 Python 依赖

```powershell
..\.venv\Scripts\python -m pip install -r ..\requirements.txt
```

如果你已经执行过第 4A 步，可以跳过这一步。

### 8.3 发送一条测试命令

```powershell
..\.venv\Scripts\python .\send_state.py THINKING
```

如果看到类似：

```text
Port: COM40
Sent: THINKING
```

说明 Python 已经能把命令发给 ESP32-C3。

### 8.4 运行一整套状态测试

```powershell
..\.venv\Scripts\python .\run_sequence.py
```

它会依次发送：

- `IDLE`
- `THINKING`
- `WRITING`
- `RUNNING`
- `DONE`
- `ERROR`
- `NEED_CONFIRM`
- `TOKEN:75`

### 8.5 如果自动识别不到串口

先手动指定端口，再执行测试：

```powershell
$env:CODEX_LIGHT_PORT="COM40"
..\.venv\Scripts\python .\send_state.py THINKING
```

把 `COM40` 换成你机器上实际看到的端口号。

## 9. 用菜单程序测试

回到项目根目录：

```powershell
Set-Location C:\Users\你的用户名\Documents\Arduino\sketch_may27a
```

运行：

```powershell
.\.venv\Scripts\python .\agent_light_control.py
```

你会看到一个菜单：

```text
1 IDLE
2 THINKING
3 WRITING
4 RUNNING
5 DONE
6 ERROR
7 TOKEN:75
q 退出
```

输入数字后回车，就会发送对应状态。

这是最适合客户自己手工试灯的方式。

## 10. 配置 Codex

### 10.1 重要说明

项目里已经自带好了：

- `.codex\hooks.json`
- `codex_light_hook.py`
- `codex_light_serial.py`

所以你要做的重点不是“自己写 hook”，而是：

1. 保留整个项目目录
2. 不要删除 `.codex` 文件夹
3. 用 Codex 打开这个项目目录

### 10.2 启动后台串口桥

在项目根目录执行：

```powershell
.\start_codex_light_daemon.ps1
```

这个后台进程会：

- 持续占用 ESP32-C3 串口
- 接收 Codex hook 发来的状态
- 读取本机 Codex 会话日志里的 token 用量
- 再转发到灯板

如果不启动这个后台进程，Codex hook 虽然会触发，但不会真正把状态送到灯上。

Token 显示也是由这个后台进程负责。它会读取：

```powershell
C:\Users\你的用户名\.codex\sessions\**\rollout-*.jsonl
```

从里面的 `token_count` 事件取出：

```text
rate_limits.primary.used_percent
```

然后换算为：

```text
剩余百分比 = 100 - used_percent
```

最后通过串口发送给灯板：

```text
TOKEN:68
```

灯板本身不会直接读取 Codex 日志，它只接收串口命令 `TOKEN:x` 并显示为 `Token x%`。

### 10.3 检查后台是否已经启动

执行：

```powershell
Get-NetTCPConnection -LocalPort 37637 -State Listen
```

如果能看到监听信息，说明 daemon 已经正常运行。

## 11. 在 Codex 中做实际测试

### 11.1 准备动作

先确认：

- ESP32-C3 已经烧录成功
- Python 手工测试已经通过
- `start_codex_light_daemon.ps1` 已经启动
- 用 Codex 打开的是**整个项目目录**

### 11.2 测试方法

在 Codex 中正常发一个任务，例如：

```text
帮我查看这个目录里有哪些文件
```

然后观察灯效。

### 11.3 正常情况下的状态变化

通常会看到：

- 用户提交消息后：`THINKING`
- Codex 开始执行命令时：`RUNNING`
- Codex 修改文件时：`WRITING`
- 任务结束时：`DONE`
- Codex 输出 token 统计时：OLED 显示 `Token xx%`

## 11A. Codex 真实状态模式

本项目的本地网页演示支持右侧选择：

```text
数据来源 → Codex
```

这个模式需要同时启动两个本地服务。

### 11A.1 启动网页展示服务

在项目根目录执行：

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

这个服务用于打开网页展示，端口是：

```text
http://localhost:2026
```

### 11A.2 启动 Codex WebSocket bridge

另开一个 PowerShell，在项目根目录执行：

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_codex_ws_bridge.ps1
```

这个服务用于给网页推送 Codex 状态，WebSocket 地址是：

```text
ws://localhost:8765
```

如果提示缺少依赖 `websockets`，执行：

```powershell
.\.venv\Scripts\python -m pip install websockets
```

### 11A.3 打开网页并选择 Codex

浏览器打开：

```text
http://localhost:2026
```

右侧选择：

```text
数据来源 → Codex
```

如果连接成功，页面会显示“已连接”。

### 11A.4 手动测试 Codex bridge

`start_codex_ws_bridge.ps1` 启动后，可以直接在它的终端里输入：

```text
thinking
writing
done
error
token 68
```

网页会收到类似下面的统一 JSON：

```json
{
  "source": "codex",
  "state": "THINKING",
  "token": 86,
  "message": "Codex is thinking"
}
```

也可以往下面这个文件追加内容：

```text
local_demo\codex_status.log
```

bridge 会监听关键词并转换成网页状态：

- `thinking` / `思考` / `analyzing` / `reasoning` → `THINKING`
- `writing` / `edit` / `patch` / `modify` / `update` → `WRITING`
- `running` / `exec` / `command` / `tool` → `RUNNING`
- `done` / `complete` / `success` / `finished` → `DONE`
- `error` / `failed` / `exception` → `ERROR`
- `confirm` / `approval` / `need confirm` → `NEED_CONFIRM`
- `idle` / `wait` / `waiting` → `IDLE`

Token 支持下面写法：

```text
token 86
TOKEN:86
Token 86%
remaining 86
```

### 11A.5 三个服务的区别

请注意区分：

1. `local_demo\start_server_2026.ps1`
   用于启动网页展示服务，端口 `2026`。

2. `local_demo\start_codex_ws_bridge.ps1`
   用于启动 Codex 状态 WebSocket bridge，端口 `8765`。

3. `start_codex_light_daemon.ps1`
   用于真实开发板串口通信，不是网页 Codex 模式必须项。

## 12. 如果 Codex 里没反应，怎么排查

### 12.1 先看 hook 日志

在项目根目录执行：

```powershell
Get-Content .\codex_light_hook.log -Tail 30
```

如果能看到类似：

```text
event=UserPromptSubmit tool= command=THINKING
sent=THINKING
```

说明 Codex hook 已经触发。

### 12.2 再看串口桥日志

执行：

```powershell
Get-Content .\codex_light.log -Tail 30
```

如果能看到类似：

```text
2026-06-05 11:03:40 THINKING socket
2026-06-05 11:03:46 RUNNING rollout
2026-06-05 11:03:50 TOKEN:68 rollout
```

说明状态已经真正发给 ESP32-C3。

### 12.3 检查 Codex 是否有 token 源数据

如果状态灯有反应，但 token 百分比不变化，先检查本机 Codex 日志里有没有 `token_count`：

```powershell
Get-ChildItem "$HOME\.codex\sessions" -Recurse -Filter "rollout-*.jsonl" |
  Sort-Object LastWriteTime -Descending |
  Select-Object -First 1 |
  ForEach-Object { Select-String -Path $_.FullName -Pattern '"token_count"|used_percent' | Select-Object -First 20 }
```

如果能看到 `token_count` 和 `used_percent`，说明 Codex 已经提供 token 数据。

### 12.4 无开发板时测试 token 换算

如果开发板不在身边，也可以先测试软件换算逻辑：

```powershell
.\.venv\Scripts\python -c "import codex_light_serial as c; print(c.command_from_rollout_event({'type':'event_msg','payload':{'type':'token_count','rate_limits':{'primary':{'used_percent':27.2,'window_minutes':300}}}}))"
```

正常输出：

```text
TOKEN:73
```

这说明 `used_percent` 到 `TOKEN:x` 的转换是正常的。

### 12.5 如果 Python 手工测试正常，但 Codex 没反应

优先检查：

- `start_codex_light_daemon.ps1` 有没有启动
- 是否用 Codex 打开的是整个项目目录
- `.codex` 文件夹是否还在
- `codex_light_hook.log` 里有没有新内容
- `codex_light.log` 里有没有 `rollout watch` 或 `TOKEN:x rollout`

## 13. 常见问题

### 问题 1：看不到串口

检查：

- USB 线是不是数据线
- 有没有换 USB 口
- 设备管理器里有没有新 COM 口

### 问题 2：端口号变了

这是正常情况。

重新执行：

```powershell
arduino-cli board list
```

看当前实际端口号。

### 问题 3：串口被占用

如果提示 `PermissionError`、`port is busy`、`could not open port`，请先关闭这些程序：

- Arduino IDE 串口监视器
- `agent_light_control.py`
- `python_test_tools` 里的测试脚本
- 旧的 daemon 进程

### 问题 4：只复制了 `.ino` 文件

这是不推荐的。

因为除了 `.ino` 之外，还需要：

- Python 测试脚本
- Codex hook 脚本
- `.codex\hooks.json`
- PowerShell 脚本

正确做法是复制整个项目文件夹。

## 14. 速通版

只想最快跑通，请按你的目标选择下面一种。

### 14.1 只看网页演示

```powershell
Set-Location C:\Users\你的用户名\Documents\Arduino\sketch_may27a
python -m venv .venv
.\.venv\Scripts\python -m pip install -r requirements.txt
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

然后浏览器打开：

```text
http://localhost:2026
```

右侧保持：

```text
数据来源 → Web Demo
```

### 14.2 网页连接 Codex

```powershell
Set-Location C:\Users\你的用户名\Documents\Arduino\sketch_may27a
python -m venv .venv
.\.venv\Scripts\python -m pip install -r requirements.txt
```

第一个 PowerShell：

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_server_2026.ps1
```

第二个 PowerShell：

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\local_demo\start_codex_ws_bridge.ps1
```

然后浏览器打开：

```text
http://localhost:2026
```

右侧选择：

```text
数据来源 → Codex
```

### 14.3 真实开发板跟随 Codex

先安装 Python 和 Arduino CLI，然后执行：

```powershell
Set-Location C:\Users\你的用户名\Documents\Arduino\sketch_may27a
.\setup_esp32c3_test_env.ps1
.\flash_esp32c3.ps1
.\.venv\Scripts\python .\agent_light_control.py
```

确认手动测试正常后，启动 Codex 后台串口桥：

```powershell
.\start_codex_light_daemon.ps1
```

最后用 Codex 打开这个项目目录并发送一个任务：

```
帮我查看这个目录里有哪些文件
```

