Agent skill
esp32-workbench-integration
Integrates an ESP32 project with the Universal ESP32 Workbench. Adds firmware modules (UDP logging, WiFi provisioning, OTA, BLE command handling, strategic log messages), updates build config, then writes the Workbench operations, Testing, and Appendix chapters into the project's existing FSD. Triggers on "integrate workbench", "add workbench", "workbench integration", "set up project", "add testing", "add tester".
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/esp32-workbench-integration
SKILL.md
ESP32 Workbench Integration
This is a procedure. When triggered, read the project's existing FSD, integrate the firmware with the workbench infrastructure (UDP logging, OTA, BLE command handling, strategic log messages), then write the operational, testing, and appendix chapters into the FSD.
Prerequisite: The project must already have an FSD with at least a System
Overview and Functional Requirements section. Use the fsd-writer skill first
to generate one from a rough description if needed.
The workbench provides the test infrastructure. This skill adds both the firmware integration (modules the workbench needs to interact with the device) and the FSD documentation (operational guide, test plan, troubleshooting).
FSD Document Structure
This skill operates on FSDs produced by the fsd-writer skill, which uses
this canonical numbered structure:
# <Project Name> — Functional Specification Document (FSD)
## 1. System Overview ← pre-existing (read-only)
## 2. System Architecture ← pre-existing (read-only)
## 3. Implementation Phases ← pre-existing (read-only)
## 4. Functional Requirements ← pre-existing (read-only)
## 5. Risks, Assumptions & Dependencies ← pre-existing (read-only)
## 6. Interface Specifications ← pre-existing (read-only)
## 7. Operational Procedures ← REPLACED by this skill with workbench-specific content
## 8. Verification & Validation ← REPLACED by this skill with workbench test cases
## 9. Troubleshooting Guide ← REPLACED by this skill with workbench diagnostics
## 10. Appendix ← REPLACED by this skill with logging strategy + constants
Sections 1–6 are written by the fsd-writer skill and contain system
overview, architecture, phases, requirements, risks, and interfaces. This skill
reads them to extract features, phases, and constants but does not modify them.
Sections 7–10 are written (or replaced) by this skill with workbench-specific operational procedures, test cases, troubleshooting, and appendix content.
Steps 1–7 handle firmware integration. Steps 8–12 write FSD sections 7–10.
Template Reference
All template code lives in Universal-ESP32-Workbench/test-firmware/. When adding modules, copy from these templates and customize project-specific values:
| Module | Template source | Customization |
|---|---|---|
udp_log.c/.h |
test-firmware/main/udp_log.c |
None (universal) |
wifi_prov.c/.h |
test-firmware/main/wifi_prov.c |
Change AP_SSID. |
portal.html |
test-firmware/main/portal.html |
Change <title> and <h1> |
ota_update.c/.h |
test-firmware/main/ota_update.c |
Change OTA_DEFAULT_URL |
ble_nus.c/.h |
test-firmware/main/ble_nus.c |
Change BLE device name |
http_server.c/.h |
test-firmware/main/http_server.c |
Add project-specific endpoints |
nvs_store.c/.h |
test-firmware/main/nvs_store.c |
Change NVS_NAMESPACE |
dns_server/ |
test-firmware/components/dns_server/ |
None (copy entire dir) |
partitions.csv |
test-firmware/partitions.csv |
None (dual OTA layout) |
sdkconfig.defaults |
test-firmware/sdkconfig.defaults |
Reference for required options |
app_main.c |
test-firmware/main/app_main.c |
Reference for init order only |
Workbench Compatibility Contract
The workbench is not a passive observer — it actively drives the device through BLE commands, HTTP relay, captive portal automation, and serial/UDP log parsing. For this to work, the firmware must conform to two contracts:
Contract 1: Required Log Messages
The workbench skills detect device state by grepping serial and UDP log output for specific format strings. These are not optional debug messages — they are required infrastructure. If a log message is missing or uses a different format string, the corresponding workbench skill will fail to detect the event.
The firmware must emit these exact strings at the specified locations:
| Pattern | Workbench skill that needs it | Where | Why the workbench needs it |
|---|---|---|---|
"Init complete" |
serial monitor | End of app_main() | Confirms boot finished; workbench waits for this before proceeding |
"alive %lu" |
serial monitor | Heartbeat task | Proves device is running, not hung |
"OTA succeeded" / "OTA failed" |
OTA skill | OTA task | Confirms OTA result; workbench blocks until one appears |
"OTA update requested" |
BLE skill | cmd_handler | Confirms BLE OTA command was received |
"WiFi reset requested" |
BLE skill | cmd_handler | Confirms BLE WiFi reset command was received |
"WiFi credentials erased" |
WiFi skill | wifi_prov_reset() | Confirms NVS wipe before reboot into AP mode |
"INSERT: %.*s", "ENTER", "BACKSPACE x%d" |
UDP log skill | cmd_handler | Verifies BLE text commands are being processed |
"UDP logging -> %s:%d" |
logging skill | udp_log_init() | Confirms UDP log channel is active |
"No WiFi credentials" |
WiFi skill | wifi_prov_init() | Confirms device will enter AP mode (no stored creds) |
"AP mode: SSID='%s'" |
WiFi skill | WiFi AP start | Workbench detects AP name to drive captive portal |
"Portal page requested" |
WiFi skill | portal_get_handler() | Confirms workbench HTTP request reached the portal |
"Credentials saved" |
WiFi skill | connect_post_handler() | Confirms portal form submission succeeded |
"STA mode, connecting to '%s'" |
WiFi skill | start_sta() | Confirms device is attempting WiFi connection |
"STA got IP" |
WiFi skill | wifi_event_handler() | Confirms device joined the network; workbench proceeds |
"STA disconnect, retry" |
WiFi skill | wifi_event_handler() | Diagnoses WiFi connection failures |
"BLE NUS initialized" |
BLE skill | BLE init | Confirms BLE is ready; workbench can start scanning |
Step 5 of the procedure ensures every required pattern exists in the firmware.
Contract 2: Required Process Flows
The workbench automates device operations by driving specific sequences. The firmware must implement these flows exactly as described — alternative implementations (e.g., BLE-based provisioning instead of captive portal, SmartConfig instead of SoftAP) are not compatible with the workbench.
WiFi Provisioning Flow (Captive Portal)
The workbench drives this exact sequence:
1. Device boots with no WiFi credentials
→ firmware logs "No WiFi credentials"
→ firmware starts SoftAP with configured SSID
→ firmware logs "AP mode: SSID='<SSID>'"
2. Workbench connects to device's SoftAP (via enter-portal)
→ workbench sends HTTP GET to portal page
→ firmware logs "Portal page requested"
→ workbench submits credentials via POST
→ firmware logs "Credentials saved"
3. Device switches to STA mode
→ firmware logs "STA mode, connecting to '<SSID>'"
→ on success: firmware logs "STA got IP"
→ on failure: firmware logs "STA disconnect, retry" (with backoff)
The firmware must use: SoftAP → captive portal (HTTP) → NVS credential storage →
STA connect. The wifi_prov.c template implements this exactly.
WiFi Reset Flow (BLE-triggered)
1. Workbench sends CMD_WIFI_RESET via BLE NUS
→ firmware logs "WiFi reset requested"
→ firmware erases WiFi credentials from NVS
→ firmware logs "WiFi credentials erased"
→ firmware reboots
→ device enters AP mode (see provisioning flow above)
OTA Update Flow
1. Workbench uploads firmware binary to its HTTP server
2. Workbench triggers OTA via one of:
a. BLE: sends CMD_OTA via NUS → firmware logs "OTA update requested"
b. HTTP relay: POST to device's /ota endpoint
3. Device downloads firmware from workbench URL
→ on success: firmware logs "OTA succeeded", reboots
→ on failure: firmware logs "OTA failed", stays on current firmware
The firmware must expose an HTTP /ota endpoint that accepts
{"url": "<firmware-url>"} and performs esp_https_ota (or esp_http_ota).
The ota.c template implements this exactly.
BLE Command Protocol (NUS)
1. Workbench scans for device by BLE name
2. Workbench connects to device's NUS service
3. Workbench writes binary commands to NUS RX characteristic:
- Each command starts with a 1-byte opcode
- Followed by opcode-specific payload
4. Device logs each command execution via UDP/serial
The firmware must use NimBLE with Nordic UART Service. The ble_nus.c and
cmd_handler.c templates implement this exactly.
Boot Sequence
The firmware must initialize in this order: NVS → netif/event loop → UDP log → WiFi provisioning → BLE → heartbeat → "Init complete"
This order ensures: UDP logging is ready before WiFi events fire, WiFi is up before BLE (which may trigger WiFi reset), and "Init complete" is the last message (so the workbench knows init is done).
Compatibility Validation
In Step 2 (Parse FSD), after extracting features, the skill must check for compatibility conflicts:
| Conflict | Detection | Resolution |
|---|---|---|
| FSD specifies BLE provisioning instead of captive portal | FR mentions "BLE provisioning" or "SmartConfig" | Flag to user: workbench requires captive portal flow |
| FSD specifies MQTT-based OTA instead of HTTP | FR mentions MQTT OTA trigger | Flag to user: workbench requires HTTP /ota endpoint |
| FSD specifies custom BLE protocol instead of NUS | Interface spec shows non-NUS UUIDs | Flag to user: workbench requires NUS for BLE commands |
| No WiFi mentioned | Feature checklist NEEDS_WIFI=no | UDP logging and OTA are unavailable; document serial-only workflow |
If the project's architecture conflicts with a required flow, the skill must ask the user whether to adapt the project or document a limited-compatibility mode.
Procedure
Step 1: Identify project
Find the project's FSD path and firmware root directory. Confirm:
- What chip is being used (ESP32, ESP32-S3, etc.)
- Where the firmware source lives (e.g.
main/directory) - The project name
Step 2: Parse FSD — extract features and build checklist
Read the entire FSD (produced by the fsd-writer skill). Extract features from
Section 4 (Functional Requirements), phases from Section 3 (Implementation
Phases), interfaces from Section 6 (Interface Specifications), and
architecture details from Section 2 (System Architecture).
Build a feature checklist:
NEEDS_WIFI → if project uses WiFi
NEEDS_BLE → if project uses BLE
NEEDS_BLE_NUS → if project uses Nordic UART Service
NEEDS_OTA → if project supports firmware updates
NEEDS_MQTT → if project uses MQTT
NEEDS_UDP_LOG → always yes when NEEDS_WIFI=yes
NEEDS_CMD_HANDLER → if NEEDS_BLE_NUS=yes
OTA_TRIGGER → ble / http / both
Record project-specific values:
- WiFi AP SSID for captive portal (e.g.
"KB-Setup") - BLE device name (e.g.
"iOS-KB") - OTA URL (e.g.
"http://192.168.0.87:8080/firmware/ios-keyboard/ios-keyboard.bin") - NVS namespace
- Any project-specific command opcodes
Step 3: Audit firmware code
Inventory the project's source files. For each module in the template reference table, check:
- Does the file exist?
- Does it contain the required log patterns?
- Does it match the template's API signatures?
Also check:
CMakeLists.txt— are all sources listed in SRCS? Are all PRIV_REQUIRES present?sdkconfig.defaults— are required options set?partitions.csv— does it have OTA slots (if NEEDS_OTA)?app_main.c— what's the init order? Is "Init complete" the last log?components/dns_server/— does it exist (if NEEDS_WIFI)?
Step 4: Add missing modules (Enforce Contract 2)
Follow this decision tree. For each missing module, copy from
workbench-test/main/ and customize. These templates implement the exact process
flows required by the Workbench Compatibility Contract (Contract 2) — WiFi
captive portal, BLE NUS command protocol, OTA via HTTP endpoint, and the
canonical boot sequence:
Does the project use WiFi? --NO--> Skip WiFi, UDP, OTA
|YES
v
Has udp_log.c? --YES--> Check log message exists
|NO --> Copy from workbench-test
v
Has wifi_prov.c? --YES--> Check AP_SSID, check wifi_prov_reset()
|NO --> Copy from workbench-test, customize AP_SSID
v
Needs OTA? --NO--> Skip
|YES
v
Has ota.c? --YES--> Check OTA_DEFAULT_URL, check log messages
|NO --> Copy from workbench-test, customize URL
Ensure partitions.csv has OTA slots
v
Uses BLE? --NO--> Skip BLE modules
|YES
v
Has ble_nus.c? --YES--> Check device name
|NO --> Copy from workbench-test, customize name
v
Has cmd_handler.c? --YES--> Check CMD_OTA + CMD_WIFI_RESET exist
|NO --> Copy from workbench-test, add project-specific opcodes
v
Has heartbeat task? --YES--> Check "alive" pattern
|NO --> Add to app_main.c
v
Has "Init complete"? --YES--> Done
|NO --> Add to end of app_main()
When copying files:
- Read the template source from workbench-test
- Customize project-specific values (AP_SSID, BLE name, OTA URL, NVS namespace)
- Add or remove project-specific opcodes in cmd_handler
- Write the customized file to the project
Step 5: Enforce Contract 1 — Required Log Messages
Check every required log pattern from the Workbench Compatibility Contract (Contract 1) table. For each missing pattern:
- Add the exact log statement at the correct location
- Use the exact format string — the workbench skills grep for these patterns
- Do not paraphrase, reformat, or localize the strings
- These are infrastructure, not debug aids — they must survive any "clean up logging" refactors
Step 6: Update build config
Update the project's build configuration:
CMakeLists.txt — add new source files to SRCS, add any missing PRIV_REQUIRES:
nvs_flash,esp_wifi,esp_netif,esp_event(WiFi)esp_http_server,esp_http_client,esp_https_ota(OTA)bt(BLE)dns_server,lwip(captive portal)esp_app_format,app_update(OTA + status endpoint)json(OTA HTTP endpoint)- Add
EMBED_FILES "portal.html"if wifi_prov uses captive portal
partitions.csv — copy from test-firmware/ (partitions-4mb.csv for 4MB flash, partitions.csv for 8MB+). See idf-flash skill for flash size and partition table rules.
sdkconfig.defaults — verify required options are set (NimBLE, partition table, flash size, etc.). See idf-flash skill for flash size defaults.
dns_server component — copy workbench-test/components/dns_server/ if project needs captive portal but doesn't have it
Step 7: Update app_main.c
Ensure the canonical init order:
- NVS init (with erase-on-corrupt fallback)
- Boot count increment
esp_netif_init()+esp_event_loop_create_default()udp_log_init("192.168.0.87", 5555)- Register IP event handler for HTTP server
wifi_prov_init()ble_nus_init(cmd_handler_on_rx)- Heartbeat task (
alive_task) ESP_LOGI(TAG, "Init complete, running event-driven")
The exact implementation can vary, but the order must be: NVS → netif → UDP → WiFi → BLE → cmd handler → heartbeat → "Init complete".
Step 8: Write "7. Operational Procedures" (Workbench Operations)
Replace ## 7. Operational Procedures in the FSD with workbench-specific
operational content. This section becomes a standalone operations guide — how
to interact with the device through the workbench. It contains no test cases.
If the fsd-writer left a generic Section 7, replace it entirely. The workbench operations are the operational procedures for this project.
8a. Hardware setup
Query the workbench for hardware details:
curl -s http://192.168.0.87:8080/api/devices | jq .
curl -s http://192.168.0.87:8080/api/info | jq .
Record: slot label, TCP port, RFC2217 URL, device state.
Check for dual-USB hub boards: If the board occupies two slots (onboard USB hub exposing both JTAG and UART), identify which slot is which:
- Espressif USB-Serial/JTAG (
303a:1001) → JTAG slot (flash here) - CH340/CP2102 UART bridge (
1a86:55d3/10c4:ea60) → UART slot (console output here)
Write a hardware table and a project-specific values table:
### Hardware Setup
| What | Where |
|------|-------|
| ESP32 USB | Workbench slot <N>, serial at `rfc2217://192.168.0.87:<PORT>` |
| Workbench host | `192.168.0.87:8080` |
| UDP log sink | `192.168.0.87:5555` |
| OTA firmware URL | `http://192.168.0.87:8080/firmware/<project>/<project>.bin` |
#### Project-Specific Values
| Value | Setting |
|-------|---------|
| WiFi portal SSID | `<SSID>` (device SoftAP name when no credentials stored) |
| Workbench AP SSID | `WB-TestAP` |
| Workbench AP password | `wbtestpass` |
| BLE device name | `<NAME>` |
| NVS namespace | `<NS>` |
| NUS RX characteristic | `6e400002-b5a3-f393-e0a9-e50e24dcca9e` |
Important: Fill in all actual values from the firmware source — never leave <placeholder> in the final FSD.
8b. Flashing
Document the project-specific esptool command for serial flashing via RFC2217. Reference the esp32-workbench-serial-flashing skill for download mode, crash-loop recovery, and dual-USB hub details.
8c. WiFi provisioning
WiFi provisioning is a prerequisite for most operations (OTA, UDP logs, HTTP endpoints). Document it as a complete two-phase procedure with filled-in project values.
Three values are involved — document all three clearly:
| Value | What it is | Where it's defined |
|---|---|---|
| Device portal SSID | The SoftAP name the device broadcasts when it has no WiFi credentials | wifi_prov.c → AP_SSID |
| Workbench AP SSID | The WiFi network the workbench creates for the device to join | Passed in enter-portal request |
| Workbench AP password | Password for the workbench's AP | Passed in enter-portal request |
Always document both phases:
- Ensure device is in AP mode — BLE WiFi reset if previously provisioned, skip if freshly flashed
- Provision via captive portal —
enter-portalwith all three values filled in, serial monitor for confirmation
Include the enter-portal failure diagnostic steps (check AP mode, check WiFi scan, check activity log).
8d. BLE commands
Document how to scan, connect, and send each opcode. Write a command reference table:
| Opcode | Hex example | Description | Expected log |
|--------|-------------|-------------|--------------|
| `0x01 <count>` | `0103` | Backspace | `"BACKSPACE x3"` |
| ... | ... | ... | ... |
Include one example curl write command. This is reference material — test cases go in the Testing chapter.
8e. OTA updates
Document the complete OTA workflow:
- Upload firmware to the workbench (
/api/firmware/upload) - Trigger OTA via BLE (
CMD_OTAopcode) or via HTTP (POST /otathrough relay) - Monitor result via serial
8f. HTTP endpoints
Document the device's HTTP endpoints and how to reach them via the workbench HTTP relay (/api/wifi/http). Typical endpoints: /status, /ota.
8g. Log monitoring
Document the two log methods (serial monitor and UDP logs) with example commands. This is the "how" — when to use which method goes in the Appendix.
Step 9: Write "8. Verification & Validation" (Testing)
Replace ## 8. Verification & Validation in the FSD with workbench test cases.
This section contains only test cases — verification tables with pass/fail
criteria. It does not repeat operational procedures from Section 7.
If the fsd-writer left a generic Section 8 with a traceability matrix, preserve the traceability matrix (Section 8.4) and replace the phase verification tables (Sections 8.1, 8.2, 8.3) with workbench-specific test procedures.
9a. Phase verification tables
For each implementation phase, write a table:
### Phase N Verification
| Step | Feature | Test procedure | Success criteria |
|------|---------|---------------|-----------------|
| 1 | <feature> | <brief description, reference workbench chapter> | <expected output> |
Rules:
- Every FSD feature must appear in exactly one phase verification table
- Test procedures reference operations from Section 7 (Operational Procedures) (e.g., "Provision WiFi (see WiFi Provisioning)") — they don't duplicate curl commands
- Every step must have concrete, observable success criteria — no vague "verify it works"
- Include the hex data for BLE commands inline (e.g., "BLE write
024869") since that's test-specific
Step 10: Write "9. Troubleshooting Guide" and "10. Appendix"
Replace ## 9. Troubleshooting Guide and ## 10. Appendix in the FSD with
workbench-specific diagnostics and reference material.
10a. Logging strategy
Document when to use each log method:
### Logging Strategy
| Situation | Method | Why |
|-----------|--------|-----|
| Verify boot output | Serial monitor | Captures UART before WiFi is up |
| Monitor BLE commands | UDP logs | Non-blocking, works while device runs |
| Capture crash output | Serial monitor | Only UART captures panic handler output |
10b. Troubleshooting
Add a failure-to-diagnostic-to-fix mapping table covering likely failure modes:
### Troubleshooting
| Test failure | Diagnostic | Fix |
|-------------|-----------|-----|
| Serial monitor shows no output | Check `/api/devices` | Device absent or flapping |
| enter-portal times out | Check serial for AP mode | BLE `CMD_WIFI_RESET` first |
| ... | ... | ... |
Step 11: Build verification
cd <project-root> && idf.py build
Fix any compilation errors. Common issues:
- Missing PRIV_REQUIRES in CMakeLists.txt
- Missing
#includedirectives - Function signature mismatches between header and implementation
Step 12: Summary report
List what was added/changed:
- New files copied from workbench-test (with customizations noted)
- Modified files (what changed)
- Build result
- Any issues found and fixed
Completeness Checklist
After completing all steps, verify:
Firmware integration (Steps 1–7):
- Every module needed by the feature checklist exists
- Every required log pattern is present
- CMakeLists.txt has all sources and dependencies
- app_main.c follows the canonical init order
- "Init complete" is the last log message in app_main()
Section 7 — Operational Procedures (Step 8):
- Hardware table documents all slots (including dual-USB if applicable)
- All project-specific values are filled in (no
<placeholder>the AI must guess) - WiFi provisioning includes all three values:
portal_ssid,ssid,password - WiFi provisioning documents both phases (ensure AP mode + provision via portal)
- BLE command reference table covers every opcode
- OTA workflow covers upload + both trigger methods (BLE and HTTP)
- HTTP endpoints documented with relay examples
- Section 7 works as a standalone operations guide
Section 8 — Verification & Validation (Step 9):
- Every FSD feature appears in a phase verification table
- Every implementation phase has a verification table
- Test procedures reference (not duplicate) Section 7
- Every test step has concrete success criteria
Sections 9 & 10 — Troubleshooting & Appendix (Step 10):
- Logging strategy explains when to use serial monitor vs UDP logs
- Troubleshooting covers likely failure modes
Build (Step 11):
- Project builds cleanly with
idf.py build
Workbench Skills Reference
| Skill | Key endpoints | What it enables |
|---|---|---|
esp32-tester-serial |
GET /api/devices, POST /api/serial/reset |
Device discovery, remote flashing (esptool via RFC2217), GPIO download mode, crash-loop recovery |
esp32-tester-udplog |
POST /api/serial/monitor, GET /api/udplog |
Serial monitor with pattern matching, UDP log collection, boot/crash capture |
esp32-tester-wifi |
POST /api/enter-portal, GET /api/wifi/ap_status, GET /api/wifi/scan, POST /api/wifi/http, GET /api/wifi/events |
Captive portal provisioning, AP control, WiFi on/off testing, HTTP relay, event monitoring |
esp32-tester-gpio |
POST /api/gpio/set, GET /api/gpio/status |
Boot mode control, hardware reset, button simulation, GPIO probe |
esp32-tester-ota |
POST /api/firmware/upload, GET /api/firmware/list, POST /api/wifi/http |
Firmware upload/serve, OTA trigger via HTTP relay |
esp32-tester-ble |
POST /api/ble/scan, POST /api/ble/connect, POST /api/ble/write, POST /api/ble/disconnect |
BLE scan, connect, GATT write, remote BLE testing |
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?