feat: production-ready firmware with BLE memory management, device_id fixes, and docs
- Reduce debug level to 1 (errors only) for production builds - Replace BLE pause/resume with full deinit/reinit during HTTP uploads (~25KB freed) - Add 60s boot report delay for fast post-deploy connectivity verification - Add device_id to BLE batch and heartbeat request bodies - Correct API host to http:// (plain HTTP, not HTTPS) - Add HTTP response logging and CV entry/exit serial logging - Create root README.md with operator setup and architecture overview - Update design spec: HMAC format, BLE memory approach, request body shapes, reporting intervals Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#define CAM_FPS 5
|
||||
#define CAM_INTERVAL_MS (1000 / CAM_FPS)
|
||||
#define REPORT_INTERVAL_S 3600
|
||||
#define BOOT_REPORT_DELAY_S 60 // first report fires 60s after NTP sync
|
||||
|
||||
static DeviceConfig g_cfg;
|
||||
static CVState g_cv;
|
||||
@@ -44,7 +45,9 @@ static void task_camera(void*) {
|
||||
while (true) {
|
||||
if (camera_capture_96(frame)) {
|
||||
if (xSemaphoreTake(s_cv_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
cv_process(g_cv, frame, g_cfg.line_offset);
|
||||
CVResult r = cv_process(g_cv, frame, g_cfg.line_offset);
|
||||
if (r.entries_delta) Serial.printf("[CV] entry +%d (total %d)\n", r.entries_delta, g_cv.entries);
|
||||
if (r.exits_delta) Serial.printf("[CV] exit +%d (total %d)\n", r.exits_delta, g_cv.exits);
|
||||
xSemaphoreGive(s_cv_mutex);
|
||||
}
|
||||
}
|
||||
@@ -62,8 +65,11 @@ static void task_reporter(void*) {
|
||||
uint32_t now = (uint32_t)(time(nullptr));
|
||||
if (now < 1700000000UL) continue; // NTP not synced
|
||||
|
||||
// First valid timestamp — initialize without reporting
|
||||
if (last_report_ts == 0) { last_report_ts = now; continue; }
|
||||
// First valid timestamp — schedule boot report 60s from now
|
||||
if (last_report_ts == 0) {
|
||||
last_report_ts = now - (REPORT_INTERVAL_S - BOOT_REPORT_DELAY_S);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((now - last_report_ts) < REPORT_INTERVAL_S) continue;
|
||||
|
||||
@@ -71,9 +77,9 @@ static void task_reporter(void*) {
|
||||
uint32_t period_end = now;
|
||||
last_report_ts = now;
|
||||
|
||||
// Pause BLE during upload
|
||||
ble_scanner_pause();
|
||||
led_set(true); // yellow indicator (single LED: on = uploading)
|
||||
// Deinit BLE to free ~25KB heap for SSL handshakes
|
||||
ble_scanner_deinit();
|
||||
led_set(true); // on = uploading
|
||||
|
||||
CameraHourlyRecord cam_rec;
|
||||
if (xSemaphoreTake(s_cv_mutex, pdMS_TO_TICKS(500)) == pdTRUE) {
|
||||
@@ -82,7 +88,7 @@ static void task_reporter(void*) {
|
||||
xSemaphoreGive(s_cv_mutex);
|
||||
} else {
|
||||
// Failed to acquire — skip this cycle, will report next hour
|
||||
ble_scanner_resume();
|
||||
ble_scanner_reinit();
|
||||
led_set(false);
|
||||
continue;
|
||||
}
|
||||
@@ -93,7 +99,7 @@ static void task_reporter(void*) {
|
||||
reporter_submit_ble(g_cfg, ble_rec);
|
||||
reporter_heartbeat(g_cfg, millis() / 1000, WiFi.RSSI());
|
||||
|
||||
ble_scanner_resume();
|
||||
ble_scanner_reinit();
|
||||
led_set(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user