# DoorCounter Retail door traffic counter using M5Stack TimerCamera-F (ESP32 + OV3660). Counts entries/exits via overhead camera CV, passively scans BLE foot traffic, and reports hourly to `logs.research.bike`. ## Hardware - **Device**: M5Stack TimerCamera-F (ESP32-S, OV3660, PSRAM, WiFi/BLE) - **Mount**: Overhead, camera pointing straight down, centered above doorway - **Power**: USB (any phone charger) ## Firmware Built with PlatformIO. Target: `timercam`. ```bash cd firmware pio run -t upload --upload-port /dev/ttyUSB0 ``` ### What it does | Module | Behavior | |--------|----------| | CV pipeline | 5 fps, 96×96 grayscale, blob tracking, line-crossing count | | BLE scanner | Continuous passive scan; deinits during hourly upload to free heap | | Reporter | Hourly HMAC-signed POST; 60s boot report for fast connectivity check | | Provisioning | Captive portal AP on first boot for WiFi setup | | OTA | Arduino OTA; operator push via `ota_push.py` | ### Reporting intervals - **First report**: 60 seconds after NTP sync (connectivity check) - **Subsequent reports**: every 3600 seconds ## Operator Setup ### 1. Flash firmware ```bash cd firmware pio run -t upload --upload-port /dev/ttyUSB0 ``` ### 2. Provision device identity ```bash python tools/flash_device.py \ --port /dev/ttyUSB0 \ --device-id dc-0042 \ --location-id retailer-123 \ --hmac-secret <32-byte-hex> \ --wifi-ssid "StoreWiFi" \ --wifi-password "secret" ``` WiFi credentials are optional — if omitted, device starts captive portal on boot. ### 3. OTA updates ```bash python tools/ota_push.py \ --host dc-0042.local \ --firmware firmware/.pio/build/timercam/firmware.bin ``` ## End User Setup 1. Mount device overhead, camera pointing straight down 2. Plug into USB power 3. Connect phone to `DoorCounter-Setup` WiFi 4. Browser opens automatically → enter store WiFi password → done **LED indicators**: Red = no WiFi · Blue = counting · Yellow = uploading ## API Endpoint: `http://logs.research.bike` | Endpoint | Data | |----------|------| | `POST /api/v1/camera/events/batch` | Hourly entry/exit counts | | `POST /api/v1/events/batch` | Hourly BLE proximity records | | `POST /api/v1/heartbeat` | Device health (uptime, RSSI, pending records) | All requests are HMAC-SHA256 signed. See [design spec](docs/superpowers/specs/2026-04-13-door-counter-design.md) for full API shapes and auth scheme. ## Project Structure ``` DoorCounter/ ├── firmware/ │ ├── platformio.ini │ ├── lib/hmac/ — HMAC-SHA256 signing library │ └── src/ │ ├── main.cpp — FreeRTOS tasks, boot sequence │ ├── config.* — NVS read/write │ ├── provisioning.* — captive portal │ ├── camera.* — frame capture + CV pipeline │ ├── ble_scanner.* — BLE passive scan │ └── reporter.* — hourly batch POST + local buffer ├── tools/ │ ├── flash_device.py — NVS provisioning script │ └── ota_push.py — OTA push script ├── docs/superpowers/specs/ │ └── 2026-04-13-door-counter-design.md └── server/ — API server (separate deployment) ```