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:
2026-04-16 11:13:50 -07:00
parent 4b671843b3
commit 9d5b588231
8 changed files with 190 additions and 26 deletions

View File

@@ -103,7 +103,7 @@ Counts accumulate as `{entries, exits}` in RAM and reset each hour on report.
## 4. BLE Scanning
Uses ESP32 built-in WiFi+BLE coexistence mode — BLE scans continuously while WiFi remains available. The only pause is a ~3s window during the hourly HTTP POST.
Uses ESP32 built-in WiFi+BLE coexistence mode — BLE scans continuously while WiFi is available. During each hourly upload the BLE stack is fully deinitialized (freeing ~25KB heap for the HTTP client) then reinitialized after the upload completes.
- Passive BLE scan, accumulates unique device hashes, near/mid/far counts per hour
- Reports to existing `/api/v1/events/batch` endpoint (no server changes needed for BLE)
@@ -115,13 +115,15 @@ Uses ESP32 built-in WiFi+BLE coexistence mode — BLE scans continuously while W
### HMAC scheme
Each request includes header:
Each request includes headers:
```
X-HMAC-Signature: <hex>
X-Device-Id: <device_id>
X-Timestamp: <unix_timestamp>
X-Signature: <hex>
```
Computed as:
Signature computed as:
```
HMAC-SHA256(secret, device_id + ":" + unix_timestamp + ":" + body_sha256)
HMAC-SHA256(secret, "POST\n" + path + "\n" + timestamp + "\n" + hex(sha256(body)))
```
Timestamp prevents replay attacks. Server validates within ±5 minute window.
@@ -142,6 +144,8 @@ Request body:
}
```
Note: `device_id` is sent as the `X-Device-Id` header, not in the body.
Success response:
```json
{ "status": "ok", "accepted": 1 }
@@ -165,10 +169,38 @@ CREATE TABLE camera_records (
Idempotent on `(device_id, period_start)` — duplicate submissions are silently ignored.
### Existing endpoints (unchanged)
### Existing endpoints (body shapes)
- `POST /api/v1/heartbeat` — device health ping, reused as-is
- `POST /api/v1/events/batch` — BLE data, reused as-is
**POST /api/v1/events/batch** (BLE data):
```json
{
"device_id": "dc-0042",
"location_id": "retailer-123",
"records": [
{
"period_start": 1712000000,
"period_end": 1712003600,
"unique_devices": 18,
"max_concurrent": 5,
"near_count": 3,
"mid_count": 8,
"far_count": 7
}
]
}
```
**POST /api/v1/heartbeat**:
```json
{
"device_id": "dc-0042",
"firmware_version": "1.0.0",
"free_storage_pct": 100,
"wifi_rssi": -65,
"pending_records": 0,
"uptime_seconds": 3661
}
```
### Local buffering
@@ -230,9 +262,14 @@ DoorCounter/
---
## 8. Open Questions / Future Work
## 8. Reporting Behavior
- **Boot report delay**: First report fires 60 seconds after NTP sync (not at the top of the first full hour). This gives a quick connectivity check after deployment.
- **Hourly thereafter**: Reports fire every 3600 seconds.
- **Debug level**: `CORE_DEBUG_LEVEL=1` (errors only) for production builds.
## 9. Open Questions / Future Work
- Confirm HMAC validation window (±5 min) matches existing server implementation
- Line offset calibration: consider a web UI at `<device_id>.local/config` for adjusting the virtual line position after install
- Multi-zone counting (two lines = zone dwell time) — out of scope for v1
- Dashboard / analytics UI — out of scope for v1