Files
Freddy-Fazbear-Digital-Eyes/firmware/ota.md
T
2026-10-02 12:23:58 -04:00

5.6 KiB

Local Wi-Fi and OTA updates

The two eye boards and the DFR1154 camera can receive application updates while on the same trusted 2.4 GHz home Wi-Fi as the updating laptop. Eye gaze still travels over the existing UART wires; Wi-Fi is only for maintenance. Each device has its own identity: eye-1, eye-2, or camera. The update tool checks that identity and an embedded image marker before sending a binary. The device requires a one-use nonce and HMAC-SHA256 signature, checks the received SHA-256, writes the inactive app slot, and reboots. The update tool waits for the other slot to come online.

This is a local HTTP service on port 3232 with authenticated image uploads. Do not port-forward it or expose it to the internet. HMAC protects update authorization and integrity, but HTTP does not encrypt the image. Use only a trusted home network. The Wi-Fi password and OTA key are compiled into firmware, so keep binaries and the ignored firmware/private/ directory private. The camera's bootloader has rollback enabled; the Arduino eye build does not have proven automatic rollback, so retain USB access for recovery.

One-time setup

  1. Run python3 firmware/tools/configure_ota.py from the project root and enter the 2.4 GHz Wi-Fi name and password at the prompts. It creates firmware/private/ota.json and firmware/private/OtaSecrets.h with an automatically generated update key. Both are ignored by Git. Do not share those files or paste the password into project documentation. For the 2026-09-30 deployment, Joshua supplied the credentials in ~/.llms/credentials.env; only the Wi-Fi name and password were read to generate these private project files.
  2. Clean-build both eye variants using the commands in firmware/README.md. Board 1 and Board 2 must use their respective build paths and board-number setting. Keep the same 16 MB / 3 MB app partition scheme; it already contains ota_0, ota_1, and otadata.
  3. Build the camera IDF project with ESP-IDF 5.5.2. Its partition table has two 7 MB app slots. For a camera still using the old single-slot layout, verify its hardware address, back up its current application, then perform a one-time USB flash that erases the old layout; erase-flash clears its entire 16 MB flash. Each eye likewise needs one USB flash of its matching Wi-Fi-enabled build. The current three boards completed these USB steps on 2026-09-30; do not erase them again for ordinary application updates.
  4. Watch the USB logs for OTA_READY device=… ip=… port=3232. Reserve a stable IP for each board in the router, or record the current addresses. Check that eye motion, blinking, and wired gaze still work after joining Wi-Fi.

Without a local secrets header, builds remain possible but Wi-Fi/OTA is disabled and logs OTA_DISABLED. Test-only binaries built with a placeholder SSID are not deployment images; run the configuration tool and clean-rebuild before flashing real boards.

Later updates

Build a fresh application image for the desired target. From the project root, update one device at a time:

python3 firmware/tools/push_ota.py --host EYE_1_IP --target eye-1 --bin firmware/build-eye-test/eye_test.ino.bin
python3 firmware/tools/push_ota.py --host EYE_2_IP --target eye-2 --bin firmware/build-eye-test-board2/eye_test.ino.bin
python3 firmware/tools/push_ota.py --host CAMERA_IP --target camera --bin firmware/camera_person_idf/build/freddy_camera_person.bin

The script rejects the wrong target marker, a device identity mismatch, or an image larger than its inactive slot. It reports success only after the device responds from the new slot. Confirm the expected eye behavior and camera detections after each update. If a device does not return, connect it by USB and inspect its log before attempting another update. OTA updates carry only the application binary; changes to the partition table or bootloader still require USB.

Hardware verification — 2026-09-30

Each board was identified by its hardware address before USB flashing. Board 1 (28:84:85:91:CF:F8) and Board 2 (28:84:85:91:D2:10) were USB-flashed and verified with their distinct builds; USB logs showed both connected to Wi-Fi. The camera (E8:F6:0A:87:0B:4C) had its prior 3 MB application saved as the ignored firmware/backups/camera-pre-ota-app-2026-09-30.bin (whole-file SHA-256 0e44f5f2bb80e59a1727046fee8351bb54713ca5b8673f173fc390ea34694b77). Its new bootloader, dual-slot partition table, and application were USB-flashed and hash-verified.

The same matching application image was then sent to each device over Wi-Fi, one at a time. Each accepted its image, rebooted, and returned in slot 1. Current DHCP addresses at verification time were Board 1 192.168.69.37, Board 2 192.168.69.141, and camera 192.168.69.204; these can change. A later /ota/info check confirmed all three identities and slot 1. The camera's live USB log still showed person-detection results and gaze_valid transitions; Board 2 continued accepting gaze packets, including valid targets. Board 1 initially showed no incoming gaze packets; Joshua fixed its cable, after which Board 1 accepted 48 gaze packets in 12 seconds, including valid targets, with no rejections or timeouts in that sample. Post-update eye appearance has not yet been visually reconfirmed.

Wi-Fi reconnect after router loss and a power cycle of all three devices remain untested. On 2026-10-01, a later camera application update was installed by USB (the laptop was no longer on the devices' Wi-Fi subnet), leaving the camera in slot 0; both eyes remained on their 2026-10-01 OTA-updated slot 0. See the tracking-filter check.