Fix touch crash + make rain a reachability signal + calm the alarm churn
Test, Build and Push / test-gateway (push) Successful in 10s
Test, Build and Push / release (push) Skipped
Test, Build and Push / build-gateway (push) Skipped

TOUCH CRASH (the blue screen): app_on_touch ran a blocking WebSocket
send (up to 5s) directly in the LVGL touch callback, stalling the
MIPI-DSI flush into a garbage/blue frame + task-watchdog reboot on
every tap. Now touch_cb only gives a semaphore; a dedicated app_task
does the blocking sends, audio, and face changes off the render
thread. WS send timeout cut 5s to 1.5s as belt-and-braces.

RAIN = REACHABILITY (user request): rain now falls only while the
gateway WebSocket is live (gated on gw_connected in rain_tick). It
drains gracefully on disconnect, resumes on reconnect, a genuine
glanceable reachable signal. Idle density bumped 2 to 4 so
connected-idle reads distinctly from disconnected-black.

CALM THE WEDGE CHURN (user request): transient wifi/WS drops no longer
slam to the x_x error face or a CONNECTING banner. Boot goes straight
to the calm idle face (dry until connected). Only a sustained 30s+
outage escalates to x_x (clock_cb); the ~15s wedge-recovery just shows
a brief rain pause.

Two fixes from adversarial concurrency review before flashing:
- persistent single capture task (was xTaskCreate per utterance; a
  rapid re-tap or WS-stop-vs-app-start race could put two readers on
  one mic/I2S handle and corrupt the codec)
- reset s_talking on disconnect (app_on_disconnect) so the first tap
  after a mid-utterance drop starts fresh, not the stop branch

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 09:04:57 +02:00
co-authored by Claude Fable 5
parent 795a1d4baf
commit 5c6a6eba36
6 changed files with 93 additions and 18 deletions
+6 -3
View File
@@ -80,7 +80,10 @@ static void ws_event(void *arg, esp_event_base_t base, int32_t id, void *data)
}
s_connected = false;
audio_capture_stop();
face_set(FACE_ERROR);
app_on_disconnect();
/* Stay calm: the rain draining away signals "unreachable". A sustained
* outage escalates to the x_x error face in face.c (clock_cb). */
face_set(FACE_IDLE);
break;
case WEBSOCKET_EVENT_DATA:
if (ev->op_code == 0x01) { /* text */
@@ -120,13 +123,13 @@ bool gw_connected(void)
void gw_send_text(const char *json)
{
if (s_connected) {
esp_websocket_client_send_text(s_ws, json, strlen(json), pdMS_TO_TICKS(5000));
esp_websocket_client_send_text(s_ws, json, strlen(json), pdMS_TO_TICKS(1500));
}
}
void gw_send_bin(const uint8_t *data, size_t len)
{
if (s_connected) {
esp_websocket_client_send_bin(s_ws, (const char *)data, len, pdMS_TO_TICKS(5000));
esp_websocket_client_send_bin(s_ws, (const char *)data, len, pdMS_TO_TICKS(1500));
}
}