Serve a diagnostic frame when camera init fails - #40
Open
misonyah wants to merge 3 commits into
Open
Conversation
When esp_camera_init() fails (e.g. sensor not seated in its socket), the stream server used to just skip registering "/" entirely, so clients lost the video feed with no indication of why. CameraManager now renders the esp_err_t as a small hex code using a hand-rolled 5x7 pixel font, tiled in a 3x3 grid across the frame with each tile independently rotated 0/90/180/270 degrees. A single large centered label isn't reliable here: eye-tracking clients (Baballonia, EyeTrackVR, etc.) crop/zoom toward wherever they guess the pupil is, which can clip a single label entirely or blow it up into an unreadable blob at whatever rotation the crop applies. Tiling with per-tile rotation means at least one instance should land inside the crop window right-side-up. The frame is encoded once via fmt2jpg and served on a loop through the existing StreamServer multipart path. Adds DIAGNOSTIC_ERROR_CODES.md documenting which esp_err_t codes are actually reachable through this path (and which esp32-camera codes aren't, since the frame only renders 3 hex digits). Currently hardcoded to the 240x240 grayscale frame this board's CameraManager config uses - not derived from the configured camera_config_t, so boards with a different resolution/pixel format would need to adjust FRAME_DIM/PIXFORMAT_GRAYSCALE accordingly.
Camera init previously only ran once at boot; if it failed there was no way to recover without a manual reboot. CameraManager now spawns a background task that retries setupCamera() every 5s while it hasn't succeeded, and StreamServer re-checks camera state on every loop iteration (not just once at connection start) so an already-open stream picks up live video automatically the moment the camera comes up, no client reconnect required.
StateManager never sent an LED event on Camera_Success, and LEDManager::updateState() unconditionally refused to leave any error state once entered. Both were fine when a camera failure was permanent until reboot, but now that CameraManager retries and can genuinely recover, the LED needs to reflect that instead of showing CameraError forever after the camera is already back and streaming live video. StateManager now sends LedStateNone on Camera_Success. LEDManager's error guard switches to the already-sketched-out "recoverable" variant: error states still block other error states from overriding them, but a non-error transition (like the recovery signal above) is allowed through.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
esp_camera_init()fails (e.g. sensor not seated in its socket), the stream server currently skips registering/entirely, so clients just lose the video feed with no indication of why.esp_err_tas a small hex code using a hand-rolled 5x7 pixel font, tiled in a 3x3 grid across the frame with each tile independently rotated 0/90/180/270 degrees, and serves it through the existing multipart stream path instead.components/CameraManager/DIAGNOSTIC_ERROR_CODES.mddocumenting whichesp_err_tcodes are actually reachable through this path.StreamServeralso re-checks camera state on every loop iteration of an open connection (not just once when the connection starts), so an already-connected client automatically switches from the diagnostic frame to live video the moment the camera recovers - no reboot or reconnect needed.StateManagernever sent an LED event on camera recovery, andLEDManager::updateState()unconditionally refused to leave any error state once entered - together the status LED would show CameraError forever even after the camera actually recovered and was streaming live video. Now the LED clears back to idle on recovery, while still staying sticky against other errors overriding a real camera fault.Known limitation
Currently hardcoded to the 240x240 grayscale frame this board's
CameraManagerconfig uses, not derived from the configuredcamera_config_t. Boards with a different resolution/pixel format would need to adjustFRAME_DIM/PIXFORMAT_GRAYSCALEaccordingly - happy to make this dynamic if that's a blocker for merging.Test plan
curland by pulling a frame out of the live MJPEG stream that the tiled, rotated hex code renders correctlyesp_camera_init()while the camera hasn't recovered