Flash Displays
Overview
Use the local development ESPHome configs to flash the known EspControl displays. If the user invokes /flash-displays with no additional display name or target, assume they mean all displays. Flash one requested display, or flash all displays in the fixed order below. Use OTA with the default hard-coded target unless the user provides a different target; use USB only when the user explicitly asks for USB.
Device Map
| Request names |
ESPHome config directory |
Default OTA target |
7inch, 7-inch, 7inch P4, 7-inch P4, 7inch V1, 7-inch V1, JC1060P470 |
devices/guition-esp32-p4-jc1060p470 |
192.168.6.102 |
7inch V2, 7-inch V2, JC1060P470 V2 |
devices/guition-esp32-p4-jc1060p470-v2 |
Ask for the target |
10inch, 10-inch, 10inch P4, 10-inch P4, 10inch V1, 10-inch V1, JC8012P4A1 |
devices/guition-esp32-p4-jc8012p4a1 |
192.168.6.103 |
10inch V2, 10-inch V2, JC8012P4A1 V2 |
devices/guition-esp32-p4-jc8012p4a1-v2 |
Ask for the target |
4inch P4, 4-inch P4, P4-86, 86 Panel, Waveshare P4-86, esp32-p4-86 |
devices/esp32-p4-86 |
192.168.6.104 |
4.3inch P4, 4.3-inch P4, P4 4.3inch, P4 4.3-inch, JC4880P443 |
devices/guition-esp32-p4-jc4880p443 |
192.168.6.101 |
S3, 4inch S3, 4-inch S3, 4848S040 |
devices/guition-esp32-s3-4848s040 |
192.168.6.105 |
Treat the 7-inch panel at 192.168.6.102, and an ambiguous or default 7inch request, as V1 hardware. Always flash that panel with the V1 JC1060P470 configuration in devices/guition-esp32-p4-jc1060p470; never substitute the V2 configuration because that firmware will not work on this panel. Select the V2 directory only when the user explicitly requests the 7-inch V2 panel and supplies a different OTA target or explicitly requests USB.
Treat the 10-inch panel at 192.168.6.103, and an ambiguous or default 10inch request, as V1 hardware. Always flash that panel with the V1 JC8012P4A1 configuration in devices/guition-esp32-p4-jc8012p4a1; never substitute the V2 configuration because that firmware will not work on this panel. Select the V2 directory only when the user explicitly requests the 10-inch V2 panel and supplies a different OTA target or explicitly requests USB.
All screens can also be flashed over USB when explicitly requested. Use the selected screen's config directory and the local serial target, normally /dev/cu.usbmodem201301.
If the user says only 4inch or 4-inch, ask whether they mean the 4-inch P4 screen or the S3 screen.
For /flash-displays with no extra target, or for all, flash in this sequence by default over OTA using the default targets above:
- 7-inch P4 V1.
- 10-inch P4 V1.
- 4-inch P4 / P4-86.
- 4.3-inch P4.
- S3.
YAML Selection
Use dev.yaml by default. If the user names another YAML file, use that file instead.
- If the user explicitly says
dev, dev file, or dev.yaml, use dev.yaml instead.
- If the user gives a bare filename such as
esphome.yaml, resolve it inside the selected display's config directory.
- If the user gives a repo-relative path such as
devices/guition-esp32-p4-jc8012p4a1/esphome.yaml, resolve it from the repository root.
- For the 7-inch panel at
192.168.6.102, or an ambiguous/default 7-inch request, require the selected YAML to resolve inside devices/guition-esp32-p4-jc1060p470, which is the V1 configuration. Allow devices/guition-esp32-p4-jc1060p470-v2 only when the user explicitly requests V2 and supplies a different OTA target or explicitly requests USB; otherwise stop and clarify instead of flashing it.
- For the 10-inch panel at
192.168.6.103, or an ambiguous/default 10-inch request, require the selected YAML to resolve inside devices/guition-esp32-p4-jc8012p4a1, which is the V1 configuration. Allow devices/guition-esp32-p4-jc8012p4a1-v2 only when the user explicitly requests V2 and supplies a different OTA target or explicitly requests USB; otherwise stop and clarify instead of flashing it.
- Only use YAML files inside this repository. If the selected file does not exist, ask for the correct file instead of guessing.
- Use the required local secrets file described below. Do not create secret values or print, modify, copy, or commit the file contents.
Secrets File
All development YAML files require a local secrets.yaml containing wifi_ssid and wifi_password. Always use this existing local file as the only secrets source:
/home/jtenniswood/git/espcontrol/secrets.yaml
Before flashing each selected display:
Confirm the source exists with test -f /home/jtenniswood/git/espcontrol/secrets.yaml. If it is missing, stop and tell the user; do not create or guess secret values.
Run the following from the selected display's config directory. This creates the ignored local symlink only when secrets.yaml is absent, and verifies that any existing file or symlink resolves to the required source:
SECRETS_SOURCE=/home/jtenniswood/git/espcontrol/secrets.yaml
if [ ! -e secrets.yaml ] && [ ! -L secrets.yaml ]; then
ln -s "$SECRETS_SOURCE" secrets.yaml
fi
test "$(realpath secrets.yaml)" = "$(realpath "$SECRETS_SOURCE")"
If verification fails, stop and explain that the selected display already has a different secrets.yaml; do not replace it without the user's approval.
Never display the secrets file, include its contents in command output, or add it to Git. The per-device .gitignore files exclude secrets.yaml.
Workflow
- Confirm the repository state:
- Run
git status --short --branch.
- Use
main as the source. If not on main, switch only when it is safe and there are no blocking local changes; otherwise explain the issue.
- If the worktree is dirty, do not revert or commit unrelated changes. Tell the user the flash will use the current local checkout as-is.
- If the worktree is clean, run
git pull --ff-only before flashing.
- Resolve the requested display names from the device map. If the user invoked
/flash-displays without naming a display, resolve it as all. If the request is ambiguous, ask one short clarification.
- Resolve the YAML file from the user's request. If none is provided, use
dev.yaml.
- Prepare and verify the required local
secrets.yaml symlink in each selected display's config directory by following the Secrets File section. Do not print or commit the secrets.
- Resolve OTA targets from an explicit user-supplied target first, then from the device's default hard-coded target. If a needed OTA target is missing, ask for that target or ask whether to use USB.
- If the user says
USB, over USB, use USB, local, or similar, use USB for the selected display instead of OTA.
- For a single display, use that display's config directory and the USB target.
- For
all over USB, flash the displays in the normal all-display sequence, but ask the user to connect the correct display before each USB flash if the connected device is not clearly identifiable.
- For OTA targets, check reachability first with
ping -c 2 -W 1000 <target>.
- For USB flashing:
- List ports with
ls -1 /dev/cu.*.
- Prefer
/dev/cu.usbmodem201301 when present.
- If that port is missing and exactly one obvious
/dev/cu.usbmodem* port exists, use it.
- If no clear USB modem port exists, ask the user to connect the display or choose the port.
- Flash each selected display with the command below, running displays sequentially. Do not run multiple flashes in parallel.
- After each OTA flash, ping the target again. A first ping may fail during reboot; retry once after a short delay before reporting a problem.
- Do not commit or push for flashing alone. Commit/push only if this skill or other source files were intentionally changed as part of the user request.
Commands
Use the project wrapper so a flash always uses the ESPHome version pinned by
.github/esphome.env. It stops before compiling if the installed executable is
older or newer than the release version. The wrapper also builds from the local
repository checkout:
python3 scripts/local_esphome.py <yaml-file> run --device <target> --no-logs
Run from the appropriate config directory:
# 7-inch P4 over OTA
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc1060p470
python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.102 --no-logs
# 7-inch P4 over USB, only when explicitly requested
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc1060p470
python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs
# 10-inch P4 V1 over OTA
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc8012p4a1
python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.103 --no-logs
# 10-inch P4 V1 over USB, only when explicitly requested
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc8012p4a1
python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs
# 4-inch P4 / P4-86 over OTA
cd /Users/jtenniswood/Git/espcontrol/devices/esp32-p4-86
python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.104 --no-logs
# 4-inch P4 / P4-86 over USB, only when explicitly requested
cd /Users/jtenniswood/Git/espcontrol/devices/esp32-p4-86
python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs
# 4.3-inch P4 over OTA
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc4880p443
python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.101 --no-logs
# 4.3-inch P4 over USB, only when explicitly requested
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc4880p443
python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs
# S3 over OTA
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-s3-4848s040
python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.105 --no-logs
# S3 over USB, only when explicitly requested
cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-s3-4848s040
python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs
Reporting
Keep user updates concise:
- Say which display is currently compiling/uploading.
- Mention known ESPHome warnings only if they affect the result; framework, platform, GPIO19/GPIO20, and MIPI narrowing warnings are normally non-blocking.
- Final response: list each requested display as flashed successfully, or clearly identify the display that failed and the blocking symptom.
1---2name: flash-displays3description: Flash EspControl display firmware from this repository using ESPHome. Use when the user invokes /flash-displays with no extra display name, or asks to flash, reflash, update, or upload firmware to all known displays in sequence, or to a specific display such as 7inch, 7-inch P4, 10inch, 10-inch V1, 10-inch V2, P4-86, 4.3-inch P4, 4-inch P4, or S3, over an explicitly supplied OTA target or USB.4---56# Flash Displays78## Overview910Use the local development ESPHome configs to flash the known EspControl displays. If the user invokes `/flash-displays` with no additional display name or target, assume they mean all displays. Flash one requested display, or flash all displays in the fixed order below. Use OTA with the default hard-coded target unless the user provides a different target; use USB only when the user explicitly asks for USB.1112## Device Map1314| Request names | ESPHome config directory | Default OTA target |15|---|---|---|16| `7inch`, `7-inch`, `7inch P4`, `7-inch P4`, `7inch V1`, `7-inch V1`, `JC1060P470` | `devices/guition-esp32-p4-jc1060p470` | `192.168.6.102` |17| `7inch V2`, `7-inch V2`, `JC1060P470 V2` | `devices/guition-esp32-p4-jc1060p470-v2` | Ask for the target |18| `10inch`, `10-inch`, `10inch P4`, `10-inch P4`, `10inch V1`, `10-inch V1`, `JC8012P4A1` | `devices/guition-esp32-p4-jc8012p4a1` | `192.168.6.103` |19| `10inch V2`, `10-inch V2`, `JC8012P4A1 V2` | `devices/guition-esp32-p4-jc8012p4a1-v2` | Ask for the target |20| `4inch P4`, `4-inch P4`, `P4-86`, `86 Panel`, `Waveshare P4-86`, `esp32-p4-86` | `devices/esp32-p4-86` | `192.168.6.104` |21| `4.3inch P4`, `4.3-inch P4`, `P4 4.3inch`, `P4 4.3-inch`, `JC4880P443` | `devices/guition-esp32-p4-jc4880p443` | `192.168.6.101` |22| `S3`, `4inch S3`, `4-inch S3`, `4848S040` | `devices/guition-esp32-s3-4848s040` | `192.168.6.105` |2324Treat the 7-inch panel at `192.168.6.102`, and an ambiguous or default `7inch` request, as V1 hardware. Always flash that panel with the V1 `JC1060P470` configuration in `devices/guition-esp32-p4-jc1060p470`; never substitute the V2 configuration because that firmware will not work on this panel. Select the V2 directory only when the user explicitly requests the 7-inch V2 panel and supplies a different OTA target or explicitly requests USB.2526Treat the 10-inch panel at `192.168.6.103`, and an ambiguous or default `10inch` request, as V1 hardware. Always flash that panel with the V1 `JC8012P4A1` configuration in `devices/guition-esp32-p4-jc8012p4a1`; never substitute the V2 configuration because that firmware will not work on this panel. Select the V2 directory only when the user explicitly requests the 10-inch V2 panel and supplies a different OTA target or explicitly requests USB.2728All screens can also be flashed over USB when explicitly requested. Use the selected screen's config directory and the local serial target, normally `/dev/cu.usbmodem201301`.2930If the user says only `4inch` or `4-inch`, ask whether they mean the 4-inch P4 screen or the S3 screen.3132For `/flash-displays` with no extra target, or for `all`, flash in this sequence by default over OTA using the default targets above:33341. 7-inch P4 V1.352. 10-inch P4 V1.363. 4-inch P4 / P4-86.374. 4.3-inch P4.385. S3.3940## YAML Selection4142Use `dev.yaml` by default. If the user names another YAML file, use that file instead.4344- If the user explicitly says `dev`, `dev file`, or `dev.yaml`, use `dev.yaml` instead.45- If the user gives a bare filename such as `esphome.yaml`, resolve it inside the selected display's config directory.46- If the user gives a repo-relative path such as `devices/guition-esp32-p4-jc8012p4a1/esphome.yaml`, resolve it from the repository root.47- For the 7-inch panel at `192.168.6.102`, or an ambiguous/default 7-inch request, require the selected YAML to resolve inside `devices/guition-esp32-p4-jc1060p470`, which is the V1 configuration. Allow `devices/guition-esp32-p4-jc1060p470-v2` only when the user explicitly requests V2 and supplies a different OTA target or explicitly requests USB; otherwise stop and clarify instead of flashing it.48- For the 10-inch panel at `192.168.6.103`, or an ambiguous/default 10-inch request, require the selected YAML to resolve inside `devices/guition-esp32-p4-jc8012p4a1`, which is the V1 configuration. Allow `devices/guition-esp32-p4-jc8012p4a1-v2` only when the user explicitly requests V2 and supplies a different OTA target or explicitly requests USB; otherwise stop and clarify instead of flashing it.49- Only use YAML files inside this repository. If the selected file does not exist, ask for the correct file instead of guessing.50- Use the required local secrets file described below. Do not create secret values or print, modify, copy, or commit the file contents.5152## Secrets File5354All development YAML files require a local `secrets.yaml` containing `wifi_ssid` and `wifi_password`. Always use this existing local file as the only secrets source:5556```text57/home/jtenniswood/git/espcontrol/secrets.yaml58```5960Before flashing each selected display:61621. Confirm the source exists with `test -f /home/jtenniswood/git/espcontrol/secrets.yaml`. If it is missing, stop and tell the user; do not create or guess secret values.632. Run the following from the selected display's config directory. This creates the ignored local symlink only when `secrets.yaml` is absent, and verifies that any existing file or symlink resolves to the required source:6465 ```bash66 SECRETS_SOURCE=/home/jtenniswood/git/espcontrol/secrets.yaml67 if [ ! -e secrets.yaml ] && [ ! -L secrets.yaml ]; then68 ln -s "$SECRETS_SOURCE" secrets.yaml69 fi70 test "$(realpath secrets.yaml)" = "$(realpath "$SECRETS_SOURCE")"71 ```72733. If verification fails, stop and explain that the selected display already has a different `secrets.yaml`; do not replace it without the user's approval.7475Never display the secrets file, include its contents in command output, or add it to Git. The per-device `.gitignore` files exclude `secrets.yaml`.7677## Workflow78791. Confirm the repository state:80 - Run `git status --short --branch`.81 - Use `main` as the source. If not on `main`, switch only when it is safe and there are no blocking local changes; otherwise explain the issue.82 - If the worktree is dirty, do not revert or commit unrelated changes. Tell the user the flash will use the current local checkout as-is.83 - If the worktree is clean, run `git pull --ff-only` before flashing.842. Resolve the requested display names from the device map. If the user invoked `/flash-displays` without naming a display, resolve it as `all`. If the request is ambiguous, ask one short clarification.853. Resolve the YAML file from the user's request. If none is provided, use `dev.yaml`.864. Prepare and verify the required local `secrets.yaml` symlink in each selected display's config directory by following the Secrets File section. Do not print or commit the secrets.875. Resolve OTA targets from an explicit user-supplied target first, then from the device's default hard-coded target. If a needed OTA target is missing, ask for that target or ask whether to use USB.886. If the user says `USB`, `over USB`, `use USB`, `local`, or similar, use USB for the selected display instead of OTA.89 - For a single display, use that display's config directory and the USB target.90 - For `all over USB`, flash the displays in the normal all-display sequence, but ask the user to connect the correct display before each USB flash if the connected device is not clearly identifiable.917. For OTA targets, check reachability first with `ping -c 2 -W 1000 <target>`.928. For USB flashing:93 - List ports with `ls -1 /dev/cu.*`.94 - Prefer `/dev/cu.usbmodem201301` when present.95 - If that port is missing and exactly one obvious `/dev/cu.usbmodem*` port exists, use it.96 - If no clear USB modem port exists, ask the user to connect the display or choose the port.979. Flash each selected display with the command below, running displays sequentially. Do not run multiple flashes in parallel.9810. After each OTA flash, ping the target again. A first ping may fail during reboot; retry once after a short delay before reporting a problem.9911. Do not commit or push for flashing alone. Commit/push only if this skill or other source files were intentionally changed as part of the user request.100101## Commands102103Use the project wrapper so a flash always uses the ESPHome version pinned by104`.github/esphome.env`. It stops before compiling if the installed executable is105older or newer than the release version. The wrapper also builds from the local106repository checkout:107108```bash109python3 scripts/local_esphome.py <yaml-file> run --device <target> --no-logs110```111112Run from the appropriate config directory:113114```bash115# 7-inch P4 over OTA116cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc1060p470117python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.102 --no-logs118119# 7-inch P4 over USB, only when explicitly requested120cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc1060p470121python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs122123# 10-inch P4 V1 over OTA124cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc8012p4a1125python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.103 --no-logs126127# 10-inch P4 V1 over USB, only when explicitly requested128cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc8012p4a1129python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs130131# 4-inch P4 / P4-86 over OTA132cd /Users/jtenniswood/Git/espcontrol/devices/esp32-p4-86133python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.104 --no-logs134135# 4-inch P4 / P4-86 over USB, only when explicitly requested136cd /Users/jtenniswood/Git/espcontrol/devices/esp32-p4-86137python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs138139# 4.3-inch P4 over OTA140cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc4880p443141python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.101 --no-logs142143# 4.3-inch P4 over USB, only when explicitly requested144cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-p4-jc4880p443145python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs146147# S3 over OTA148cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-s3-4848s040149python3 ../../scripts/local_esphome.py dev.yaml run --device 192.168.6.105 --no-logs150151# S3 over USB, only when explicitly requested152cd /Users/jtenniswood/Git/espcontrol/devices/guition-esp32-s3-4848s040153python3 ../../scripts/local_esphome.py dev.yaml run --device /dev/cu.usbmodem201301 --no-logs154155```156157## Reporting158159Keep user updates concise:160161- Say which display is currently compiling/uploading.162- Mention known ESPHome warnings only if they affect the result; framework, platform, GPIO19/GPIO20, and MIPI narrowing warnings are normally non-blocking.163- Final response: list each requested display as flashed successfully, or clearly identify the display that failed and the blocking symptom.