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 GET requests (allow_origins=["*"]).
The software is open source: github.com/dahljo/bcmeter
Status & Diagnostics
| Method |
Endpoint |
Description
|
| GET |
/api/status |
Current measurement state, last sensor readings, error codes, sample count, WiFi mode, firmware version, OTA info. Returns "env": "pi" to distinguish from ESP32 ("env": "esp32").
|
| GET |
/api/system |
Hardware info: IP, MAC address, disk usage, memory, modem status, GPS detail, barometric altitude, geolocation, current time
|
| 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).
|
| GET |
/api/maintenance-logs |
Downloads a zip bundle containing: rotating bcmeter.log files, syslog, 10 newest CSV sessions, dmesg, journalctl for bcmeter and pigpiod services, config JSON, incident log.
|
| GET |
/api/debug_mobile/status |
Returns modem debug send progress (from email handler).
|
Measurement Control
All control is dispatched through a single endpoint with an action query parameter:
| Method |
Endpoint |
Description
|
| GET |
/api/control?action=start |
Begin measurement session. Returns 409 if time not synced, 423 if never calibrated, 424 if calibration stale (>28 days). Add &force=1 to override preflight checks.
|
| GET |
/api/control?action=stop |
Stop measurement and save session file.
|
| GET |
/api/control?action=calibrate |
Start calibration routine (returns 202 immediately — poll /api/calibration for progress). Requires sampling to be stopped.
|
| GET |
/api/calibration |
Calibration status: {running, done, ok, elapsed_ms, log}.
|
| GET |
/api/control?action=clear_error |
Reset error state to ERR_NONE.
|
| GET |
/api/control?action=identify |
Triggers LED identify blink pattern (Morse code spelling "bcmeter" for 30 seconds). Useful for locating a specific device when multiple units are deployed.
|
| GET |
/api/control?action=debug_mobile |
Triggers modem debug email via Lambda. Requires modem present.
|
Configuration
| Method |
Endpoint |
Description
|
| GET |
/api/config |
All settings as JSON. Each parameter includes type, value, label, tab, and description.
|
| 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. Triggers deferred modem onboarding if mail_logs_to is set.
|
| POST |
/api/device/rename |
Set device name and hostname. Body: {"name": "bcmeter01"} (1–32 chars). Runs hostnamectl set-hostname.
|
| GET |
/api/control?action=synctime&ts=EPOCH&tz=IANA |
Sync device clock. ts = Unix timestamp, tz = IANA timezone string (e.g. Europe/Berlin). Applies timezone via timedatectl.
|
WiFi Management
| Method |
Endpoint |
Description
|
| GET |
/api/wifi/scan |
List nearby networks: {scanning: bool, networks: [{ssid, rssi, secure}]}. Add ?refresh=1 to trigger a new background scan.
|
| POST |
/api/wifi/scan/refresh |
Explicitly trigger a new WiFi scan (returns 202, or 409 if already scanning).
|
| GET |
/api/wifi/status |
Current connection: {mode, status, ssid, ip, rssi, quality (0-4), internet, timeSynced}.
|
| POST |
/api/wifi |
Save WiFi credentials. Body: {"ssid": "...", "pass": "..."} (password min 8 chars).
|
| POST |
/api/wifi/connect |
Save credentials and initiate background connection attempt (returns 202). Password must be 8–63 chars. Body: {"ssid": "...", "pass": "..."}
|
| 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.
|
| POST |
/api/wifi/delete |
Delete credentials and switch to AP mode (deferred 2s background switch).
|
| GET |
/api/ap-security |
Hotspot security settings: {secured: bool, password: str}.
|
| POST |
/api/ap-security |
Update hotspot password. Body: {"secured": true, "password": "..."} (min 8 chars).
|
Data Management
| Method |
Endpoint |
Description
|
| GET |
/api/csv |
Current session CSV data. Returns header-only if no active session. Add ?file=FILENAME for archived files.
|
| GET |
/api/files |
List stored CSV logs: [{name, size, lines, date}] sorted newest first.
|
| GET |
/api/control?action=cleardata |
Delete all stored log files.
|
Firmware Updates
| Method |
Endpoint |
Description
|
| GET |
/api/ota/status |
Check if update available: {available, version, url, sha256, notes, skipped}.
|
| POST |
/api/ota/check |
Force check for new firmware against GitHub Releases.
|
| POST |
/api/ota/skip |
Skip current available update for this boot.
|
| POST |
/api/ota/apply |
Download and apply firmware update. Returns 409 if none pending.
|
| POST |
/api/update |
Direct firmware upload (.tar.gz or .zip archive). Extracts over the code directory and restarts bcMeter.service via systemctl. Stops active session first.
|
System Operations
| Method |
Endpoint |
Description
|
| GET |
/api/control?action=reboot |
End session and reboot the device (fire-and-forget thread via sudo reboot).
|
| GET |
/api/control?action=shutdown |
Safely shut down via sudo shutdown -h now.
|
| POST |
/api/email/validate |
Validate email API key against the Lambda endpoint. Body: {"api_key": "..."}. Returns {valid: bool, error: str}.
|
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 (interface/index.html)
|
/discover |
Standalone device discovery page (also hostable on bcmeter.org)
|
/manual/* |
Static files from interface/manual/
|
/current_log.csv |
Legacy redirect to /api/csv
|
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