API Reference
The bcMeter exposes a REST API on port 80. All endpoints are accessible without authentication when connected to the device network. CORS is enabled for all responses (Access-Control-Allow-Origin: *).
The device identifies its platform via the "env" field in /api/status: "env": "esp32" for bcMeter (commercial) and "env": "pi" for bcMeter (DIY / Raspberry Pi).
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): github.com/dahljo/bcmeter-pi (Pi / DIY version).
Status & Diagnostics
| Method |
Endpoint |
Description |
Platforms
|
| GET |
/api/status |
Current measurement state, last sensor readings (BC, ATN, sensor/reference voltages, flow, filter loading), error codes, sample count, session active, WiFi mode/SSID/RSSI, internet flag, firmware version, OTA result flag, time-sync state. |
Both
|
| GET |
/api/system |
Hardware info: IP, MAC address, heap and PSRAM usage, flash usage, modem status and signal, GPS detail, barometric altitude, geolocation source, current time, cycle timing statistics. |
Both
|
| GET |
/api/logs |
Structured health report as JSON with sections: hardware, measurement, system, network, incidents. Each entry has {k, v, s} (key, value, status: ok/warn/error/info). |
Both
|
| GET |
/api/debug_mobile/status |
Returns modem debug email send progress (from email handler). |
Both
|
Measurement Control
All control is dispatched through a single endpoint with an action query parameter:
| Method |
Endpoint |
Description |
Platforms
|
| GET |
/api/control?action=start |
1 for one-shot indoor/outdoor override. |
Both
|
| GET |
/api/control?action=stop |
Stop measurement and finalise session file. |
Both
|
| GET |
/api/control?action=calibrate |
Start optical calibration routine (returns 202 immediately — poll /api/calibration for progress). Requires sampling to be stopped. |
Both
|
| GET |
/api/calibration |
Calibration status: {running, done, ok, elapsed_ms, log}. |
Both
|
| GET |
/api/control?action=clear_error |
Reset error state to ERR_NONE. |
Both
|
| GET |
/api/control?action=identify |
Triggers LED identify blink pattern (Morse code "bcmeter", ~30 seconds). Useful for locating a specific device when multiple units are deployed. |
Both
|
| GET |
/api/control?action=debug_mobile |
Triggers modem debug email via Lambda. Requires modem present. Returns 409 if modem unavailable or already running. |
Both
|
| GET |
/api/control?action=synctime&ts=EPOCH&tz=IANA |
Sync device clock. ts = Unix timestamp, tz = IANA timezone string (e.g. Europe/Berlin). |
Both
|
| GET |
/api/control?action=cleardata |
Delete all stored log files. |
Both
|
| GET |
/api/control?action=reboot |
End session and reboot the device. |
Both
|
| GET |
/api/control?action=shutdown |
Safely shut down the device. |
Both
|
| GET |
/api/control?action=factory_reset |
Permanently erase all logs, WiFi credentials, calibration data, and settings. Reboots into factory state. |
Both
|
Configuration
| Method |
Endpoint |
Description |
Platforms
|
| GET |
/api/config |
All settings as JSON. Each parameter includes type, value, label, tab, and description. |
Both
|
| POST |
/api/config |
Update settings. JSON body with key-value pairs. Accepts {key: value} or {key: {value: ...}} format. Only changed values need to be sent. |
Both
|
| POST |
/api/device/rename |
Set device name. Body: {"name": "bcmeter-A3AB"} (1–32 chars). Updates mDNS/hostname accordingly. |
Both
|
| GET |
/api/ap-security |
Hotspot security settings: {secured: bool, password: str}. |
Both
|
| POST |
/api/ap-security |
Update hotspot password. Body: {"secured": true, "password": "..."} (min 8 chars). |
Both
|
| POST |
/api/email/validate |
Validate email API key against the Lambda endpoint. Body: {"api_key": "..."}. Returns {valid: bool, error: str}. |
Both
|
WiFi Management
| Method |
Endpoint |
Description |
Platforms
|
| GET |
/api/wifi/scan |
List nearby networks: {scanning: bool, networks: [{ssid, rssi, secure}]}. Add ?refresh=1 to trigger a new background scan. |
Both
|
| GET |
/api/wifi/status |
Current connection: {mode, status, ssid, ip, rssi, quality (0-4), internet, timeSynced}. |
Both
|
| POST |
/api/wifi |
Save WiFi credentials. Body: {"ssid": "...", "pass": "..."} (password min 8 chars). Initiates reconnect. |
Both
|
| POST |
/api/wifi/connect |
Save credentials and initiate background connection attempt (returns 202). Password must be 8–63 chars. Body: {"ssid": "...", "pass": "..."}. |
Both
|
| GET |
/api/wifi/connect/status |
Connection progress: {state: 0-3, elapsed, log, mode, ip, ssid, device_name, hostname}. States: 0=idle, 1=connecting, 2=success, 3=failed. Poll after POST to /api/wifi/connect. |
Both
|
| POST |
/api/wifi/delete |
Delete credentials and switch to AP mode (deferred 2s background switch). |
Both
|
| POST |
/api/wifi/scan/refresh |
Explicitly trigger a new WiFi scan (returns 202, or 409 if already scanning). |
Both
|
Data Management
| Method |
Endpoint |
Description |
Platforms
|
| GET |
/api/csv |
Current session CSV data. Returns header-only if no active session. Add ?file=FILENAME for archived files. |
Both
|
| GET |
/api/files |
List stored CSV logs: [{name, size, lines, date}] sorted newest first. Add ?name=FILENAME to download a specific file. |
Both
|
Firmware Updates
| Method |
Endpoint |
Description |
Platforms
|
| GET |
/api/ota/status |
Check if update available: {available, version, notes, apply_state, apply_progress, apply_error}. |
Both
|
| POST |
/api/ota/check |
Force check for new firmware. |
Both
|
| POST |
/api/ota/skip |
Skip current available update. |
Both
|
| POST |
/api/ota/apply |
Download and apply firmware update. Returns 409 if none pending. |
Both
|
| POST |
/api/update |
Direct firmware upload. ESP32: accepts a raw .bin file, flashes to the OTA partition, reboots. Pi: accepts a .tar.gz or .zip archive, extracts over the code directory, restarts the bcMeter.service. |
Both
|
Captive Portal
These endpoints handle captive portal detection on mobile devices and redirect to the main interface in AP mode:
| Endpoint |
Purpose
|
/generate_204 |
Android captive portal check
|
/hotspot-detect.html |
Apple captive portal check
|
/canonical.html |
Firefox captive portal check
|
/ncsi.txt |
Windows captive portal check
|
/success.txt |
Generic connectivity probe (returns "success")
|
Static Routes
| Path |
Description
|
/ |
Serves the SPA frontend
|
/discover |
Standalone device discovery page
|
/current_log.csv |
Legacy redirect to /api/csv
|
The following endpoints exist only on the Raspberry Pi version. They use Linux system commands and are not applicable to the ESP32.
| Method |
Endpoint |
Description
|
| GET |
/api/maintenance-logs |
Downloads a zip bundle containing: rotating bcmeter.log files, syslog, 10 newest CSV sessions, dmesg, journalctl output for bcmeter and pigpiod services, config JSON, incident log. Uses journalctl and dmesg — Linux only.
|
Additionally, on the Pi:
/api/control?action=reboot runs sudo reboot (Pi: routes_control.py:151)
/api/control?action=shutdown runs sudo shutdown -h now (Pi: routes_control.py:161)
/api/control?action=synctime sets the timezone via sudo timedatectl set-timezone (Pi: routes_control.py:276)
/api/device/rename calls sudo hostnamectl set-hostname and restarts avahi (Pi: bcmeter/identity.py:41)
/api/update runs sudo systemctl restart bcMeter.service after extracting the archive (Pi: routes_update.py:134)
The following endpoints exist only on the Pi and have no ESP32 equivalent:
| Method |
Endpoint |
Description
|
| GET |
/api/qc/pi/report |
Pi QC test report as JSON.
|
| GET |
/api/qc/pi/report.html |
Pi QC test report as HTML.
|
| POST |
/api/qc/pi/start |
Start the Pi QC test sequence.
|
| GET |
/api/qc/pi/status |
Pi QC test status.
|
| GET |
/api/lab/run |
Lab/engineering raw ADC capture (Pi equivalent of ESP32 serial LAB mode).
|
| GET |
/api/lab/info |
Lab session status.
|
The following endpoints exist only on the ESP32 and have no Pi equivalent:
| Method |
Endpoint |
Description
|
| GET |
/api/sdfiles |
List CSV files on the SD card.
|
| GET |
/api/crash |
Last crash/reset report from CrashReport module.
|
| GET |
/api/coredump |
Stream the raw ELF coredump from the coredump flash partition. Add ?erase=1 to erase after download.
|
| GET |
/api/modem/test |
Run modem AT diagnostic and return results as JSON.
|
| POST |
/api/lab/start |
Start a lab ADC capture session (params: led_ch, led_duty, pump_duty, pump_hz).
|
| POST |
/api/lab/stop |
Stop the lab capture session.
|
| GET |
/api/lab/status |
Lab session status: active, pairs captured, LED/pump settings.
|
| POST |
/api/raw_capture/enable |
1).
|
| GET |
/api/raw_capture/read |
Drain the raw capture ring buffer as binary float32 pairs (8 bytes each). X-Dropped header reports overflow count.
|
| GET |
/api/qc/sensors |
Live SPS30 + env-sensor read for QC (409 while sampling).
|
| GET |
/api/qc/diag |
Passive diagnostic snapshot: heap, PSRAM, uptime, reset reason, WiFi, modem state. No AT calls.
|
| GET |
/api/qc/pump_ramp/status |
QC pump ramp test status.
|
| GET |
/api/qc/led_880/status |
QC LED stability test status.
|
Example: Start a Measurement
# Sync time first
curl "http://bcmeter-XXXX.local/api/control?action=synctime&ts=$(date +%s)&tz=Europe/Berlin"
# Start measurement
curl "http://bcmeter-XXXX.local/api/control?action=start"
# Poll status
curl "http://bcmeter-XXXX.local/api/status"
# Download current data
curl "http://bcmeter-XXXX.local/api/csv" -o measurement.csv