Difference between revisions of "API reference"
(Reframe: bcMeter (DIY) / source-available) |
(Restructure: platform separation (ESP32 commercial prioritised, Raspberry Pi DIY in own section); verified against firmware/Pi source; complete serial command list) |
||
| Line 1: | Line 1: | ||
== API Reference == | == 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 | 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 (<code>Access-Control-Allow-Origin: *</code>). | ||
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter github.com/dahljo/bcmeter] | The device identifies its platform via the <code>"env"</code> field in <code>/api/status</code>: <code>"env": "esp32"</code> for bcMeter (commercial) and <code>"env": "pi"</code> for bcMeter (DIY / Raspberry Pi). | ||
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter-pi github.com/dahljo/bcmeter-pi] (Pi / DIY version). | |||
=== Status & Diagnostics === | === Status & Diagnostics === | ||
{| class="wikitable" | {| class="wikitable" | ||
! Method !! Endpoint !! Description | ! Method !! Endpoint !! Description !! Platforms | ||
|- | |- | ||
| GET || <code>/api/status</code> || Current measurement state, last sensor readings, error codes, sample count, WiFi mode, firmware version, OTA | | GET || <code>/api/status</code> || 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 || <code>/api/system</code> || Hardware info: IP, MAC address, | | GET || <code>/api/system</code> || 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 || <code>/api/logs</code> || Structured health report as JSON with sections: <code>hardware</code>, <code>measurement</code>, <code>system</code>, <code>network</code>, <code>incidents</code>. Each entry has <code>{k, v, s}</code> (key, value, status: ok/warn/error/info). | | GET || <code>/api/logs</code> || Structured health report as JSON with sections: <code>hardware</code>, <code>measurement</code>, <code>system</code>, <code>network</code>, <code>incidents</code>. Each entry has <code>{k, v, s}</code> (key, value, status: ok/warn/error/info). || Both | ||
|- | |- | ||
| GET || <code>/api/debug_mobile/status</code> || Returns modem debug email send progress (from email handler). || Both | |||
| GET || <code>/api/debug_mobile/status</code> || Returns modem debug send progress (from email handler). | |||
|} | |} | ||
| Line 26: | Line 26: | ||
{| class="wikitable" | {| class="wikitable" | ||
! Method !! Endpoint !! Description | ! Method !! Endpoint !! Description !! Platforms | ||
|- | |||
| GET || <code>/api/control?action=start</code> || Begin measurement session. Returns 409 if time not synced, 423 if never calibrated, 424 if calibration stale (>28 days). Add <code>&force=1</code> to override preflight checks. Optional <code>&indoor=0|1</code> for one-shot indoor/outdoor override. || Both | |||
|- | |||
| GET || <code>/api/control?action=stop</code> || Stop measurement and finalise session file. || Both | |||
|- | |||
| GET || <code>/api/control?action=calibrate</code> || Start optical calibration routine (returns 202 immediately — poll <code>/api/calibration</code> for progress). Requires sampling to be stopped. || Both | |||
|- | |||
| GET || <code>/api/calibration</code> || Calibration status: <code>{running, done, ok, elapsed_ms, log}</code>. || Both | |||
|- | |||
| GET || <code>/api/control?action=clear_error</code> || Reset error state to ERR_NONE. || Both | |||
|- | |- | ||
| GET || <code>/api/control?action= | | GET || <code>/api/control?action=identify</code> || Triggers LED identify blink pattern (Morse code "bcmeter", ~30 seconds). Useful for locating a specific device when multiple units are deployed. || Both | ||
|- | |- | ||
| GET || <code>/api/control?action= | | GET || <code>/api/control?action=debug_mobile</code> || Triggers modem debug email via Lambda. Requires modem present. Returns 409 if modem unavailable or already running. || Both | ||
|- | |- | ||
| GET || <code>/api/control?action= | | GET || <code>/api/control?action=synctime&ts=EPOCH&tz=IANA</code> || Sync device clock. <code>ts</code> = Unix timestamp, <code>tz</code> = IANA timezone string (e.g. <code>Europe/Berlin</code>). || Both | ||
|- | |- | ||
| GET || <code>/api/ | | GET || <code>/api/control?action=cleardata</code> || Delete all stored log files. || Both | ||
|- | |- | ||
| GET || <code>/api/control?action= | | GET || <code>/api/control?action=reboot</code> || End session and reboot the device. || Both | ||
|- | |- | ||
| GET || <code>/api/control?action= | | GET || <code>/api/control?action=shutdown</code> || Safely shut down the device. || Both | ||
|- | |- | ||
| GET || <code>/api/control?action= | | GET || <code>/api/control?action=factory_reset</code> || Permanently erase all logs, WiFi credentials, calibration data, and settings. Reboots into factory state. || Both | ||
|} | |} | ||
| Line 46: | Line 56: | ||
{| class="wikitable" | {| class="wikitable" | ||
! Method !! Endpoint !! Description | ! Method !! Endpoint !! Description !! Platforms | ||
|- | |||
| GET || <code>/api/config</code> || All settings as JSON. Each parameter includes type, value, label, tab, and description. || Both | |||
|- | |||
| POST || <code>/api/config</code> || Update settings. JSON body with key-value pairs. Accepts <code>{key: value}</code> or <code>{key: {value: ...}}</code> format. Only changed values need to be sent. || Both | |||
|- | |- | ||
| | | POST || <code>/api/device/rename</code> || Set device name. Body: <code>{"name": "bcmeter-A3AB"}</code> (1–32 chars). Updates mDNS/hostname accordingly. || Both | ||
|- | |- | ||
| | | GET || <code>/api/ap-security</code> || Hotspot security settings: <code>{secured: bool, password: str}</code>. || Both | ||
|- | |- | ||
| POST || <code>/api/ | | POST || <code>/api/ap-security</code> || Update hotspot password. Body: <code>{"secured": true, "password": "..."}</code> (min 8 chars). || Both | ||
|- | |- | ||
| | | POST || <code>/api/email/validate</code> || Validate email API key against the Lambda endpoint. Body: <code>{"api_key": "..."}</code>. Returns <code>{valid: bool, error: str}</code>. || Both | ||
|} | |} | ||
| Line 60: | Line 74: | ||
{| class="wikitable" | {| class="wikitable" | ||
! Method !! Endpoint !! Description | ! Method !! Endpoint !! Description !! Platforms | ||
|- | |- | ||
| GET || <code>/api/wifi/ | | GET || <code>/api/wifi/scan</code> || List nearby networks: <code>{scanning: bool, networks: [{ssid, rssi, secure}]}</code>. Add <code>?refresh=1</code> to trigger a new background scan. || Both | ||
|- | |- | ||
| | | GET || <code>/api/wifi/status</code> || Current connection: <code>{mode, status, ssid, ip, rssi, quality (0-4), internet, timeSynced}</code>. || Both | ||
|- | |- | ||
| POST || <code>/api/wifi | | POST || <code>/api/wifi</code> || Save WiFi credentials. Body: <code>{"ssid": "...", "pass": "..."}</code> (password min 8 chars). Initiates reconnect. || Both | ||
|- | |- | ||
| | | POST || <code>/api/wifi/connect</code> || Save credentials and initiate background connection attempt (returns 202). Password must be 8–63 chars. Body: <code>{"ssid": "...", "pass": "..."}</code>. || Both | ||
|- | |- | ||
| | | GET || <code>/api/wifi/connect/status</code> || Connection progress: <code>{state: 0-3, elapsed, log, mode, ip, ssid, device_name, hostname}</code>. States: 0=idle, 1=connecting, 2=success, 3=failed. Poll after POST to <code>/api/wifi/connect</code>. || Both | ||
|- | |- | ||
| | | POST || <code>/api/wifi/delete</code> || Delete credentials and switch to AP mode (deferred 2s background switch). || Both | ||
|- | |- | ||
| POST || <code>/api/ | | POST || <code>/api/wifi/scan/refresh</code> || Explicitly trigger a new WiFi scan (returns 202, or 409 if already scanning). || Both | ||
|} | |} | ||
| Line 84: | Line 94: | ||
{| class="wikitable" | {| class="wikitable" | ||
! Method !! Endpoint !! Description | ! Method !! Endpoint !! Description !! Platforms | ||
|- | |- | ||
| GET || <code>/api/csv</code> || Current session CSV data. Returns header-only if no active session. Add <code>?file=FILENAME</code> for archived files. | | GET || <code>/api/csv</code> || Current session CSV data. Returns header-only if no active session. Add <code>?file=FILENAME</code> for archived files. || Both | ||
|- | |- | ||
| GET || <code>/api/files</code> || List stored CSV logs: <code>[{name, size, lines, date}]</code> sorted newest first. | | GET || <code>/api/files</code> || List stored CSV logs: <code>[{name, size, lines, date}]</code> sorted newest first. Add <code>?name=FILENAME</code> to download a specific file. || Both | ||
|} | |} | ||
| Line 96: | Line 104: | ||
{| class="wikitable" | {| class="wikitable" | ||
! Method !! Endpoint !! Description | ! Method !! Endpoint !! Description !! Platforms | ||
|- | |- | ||
| | | GET || <code>/api/ota/status</code> || Check if update available: <code>{available, version, notes, apply_state, apply_progress, apply_error}</code>. || Both | ||
|- | |- | ||
| POST || <code>/api/ | | POST || <code>/api/ota/check</code> || Force check for new firmware. || Both | ||
| | |||
|- | |- | ||
| | | POST || <code>/api/ota/skip</code> || Skip current available update. || Both | ||
|- | |- | ||
| | | POST || <code>/api/ota/apply</code> || Download and apply firmware update. Returns 409 if none pending. || Both | ||
|- | |- | ||
| POST || <code>/api/ | | POST || <code>/api/update</code> || Direct firmware upload. ESP32: accepts a raw <code>.bin</code> file, flashes to the OTA partition, reboots. Pi: accepts a <code>.tar.gz</code> or <code>.zip</code> archive, extracts over the code directory, restarts the <code>bcMeter.service</code>. || Both | ||
|} | |} | ||
| Line 144: | Line 140: | ||
! Path !! Description | ! Path !! Description | ||
|- | |- | ||
| <code>/</code> || Serves the SPA frontend | | <code>/</code> || Serves the SPA frontend | ||
|- | |- | ||
| <code>/discover</code> || Standalone device discovery page | | <code>/discover</code> || Standalone device discovery page | ||
|- | |- | ||
| <code>/ | | <code>/current_log.csv</code> || Legacy redirect to <code>/api/csv</code> | ||
|} | |||
=== bcMeter (DIY) — Raspberry Pi OS-level extras === | |||
The following endpoints exist '''only on the Raspberry Pi''' version. They use Linux system commands and are not applicable to the ESP32. | |||
{| class="wikitable" | |||
! Method !! Endpoint !! Description | |||
|- | |- | ||
| <code>/ | | GET || <code>/api/maintenance-logs</code> || 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 <code>journalctl</code> and <code>dmesg</code> — Linux only. | ||
|} | |||
Additionally, on the Pi: | |||
* <code>/api/control?action=reboot</code> runs <code>sudo reboot</code> (Pi: <code>routes_control.py:151</code>) | |||
* <code>/api/control?action=shutdown</code> runs <code>sudo shutdown -h now</code> (Pi: <code>routes_control.py:161</code>) | |||
* <code>/api/control?action=synctime</code> sets the timezone via <code>sudo timedatectl set-timezone</code> (Pi: <code>routes_control.py:276</code>) | |||
* <code>/api/device/rename</code> calls <code>sudo hostnamectl set-hostname</code> and restarts avahi (Pi: <code>bcmeter/identity.py:41</code>) | |||
* <code>/api/update</code> runs <code>sudo systemctl restart bcMeter.service</code> after extracting the archive (Pi: <code>routes_update.py:134</code>) | |||
The following endpoints exist only on the Pi and have no ESP32 equivalent: | |||
{| class="wikitable" | |||
! Method !! Endpoint !! Description | |||
|- | |||
| GET || <code>/api/qc/pi/report</code> || Pi QC test report as JSON. | |||
|- | |||
| GET || <code>/api/qc/pi/report.html</code> || Pi QC test report as HTML. | |||
|- | |||
| POST || <code>/api/qc/pi/start</code> || Start the Pi QC test sequence. | |||
|- | |||
| GET || <code>/api/qc/pi/status</code> || Pi QC test status. | |||
|- | |||
| GET || <code>/api/lab/run</code> || Lab/engineering raw ADC capture (Pi equivalent of ESP32 serial LAB mode). | |||
|- | |||
| GET || <code>/api/lab/info</code> || Lab session status. | |||
|} | |||
The following endpoints exist only on the '''ESP32''' and have no Pi equivalent: | |||
{| class="wikitable" | |||
! Method !! Endpoint !! Description | |||
|- | |||
| GET || <code>/api/sdfiles</code> || List CSV files on the SD card. | |||
|- | |||
| GET || <code>/api/crash</code> || Last crash/reset report from CrashReport module. | |||
|- | |||
| GET || <code>/api/coredump</code> || Stream the raw ELF coredump from the coredump flash partition. Add <code>?erase=1</code> to erase after download. | |||
|- | |||
| GET || <code>/api/modem/test</code> || Run modem AT diagnostic and return results as JSON. | |||
|- | |||
| POST || <code>/api/lab/start</code> || Start a lab ADC capture session (params: <code>led_ch</code>, <code>led_duty</code>, <code>pump_duty</code>, <code>pump_hz</code>). | |||
|- | |||
| POST || <code>/api/lab/stop</code> || Stop the lab capture session. | |||
|- | |||
| GET || <code>/api/lab/status</code> || Lab session status: active, pairs captured, LED/pump settings. | |||
|- | |||
| POST || <code>/api/raw_capture/enable</code> || Toggle raw ADC sample capture ring buffer (param: <code>on=0|1</code>). | |||
|- | |||
| GET || <code>/api/raw_capture/read</code> || Drain the raw capture ring buffer as binary float32 pairs (8 bytes each). <code>X-Dropped</code> header reports overflow count. | |||
|- | |||
| GET || <code>/api/qc/sensors</code> || Live SPS30 + env-sensor read for QC (409 while sampling). | |||
|- | |||
| GET || <code>/api/qc/diag</code> || Passive diagnostic snapshot: heap, PSRAM, uptime, reset reason, WiFi, modem state. No AT calls. | |||
|- | |||
| GET || <code>/api/qc/pump_ramp/status</code> || QC pump ramp test status. | |||
|- | |||
| GET || <code>/api/qc/led_880/status</code> || QC LED stability test status. | |||
|} | |} | ||
Latest revision as of 20:59, 8 June 2026
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
|
bcMeter (DIY) — Raspberry Pi OS-level extras
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=rebootrunssudo reboot(Pi:routes_control.py:151)/api/control?action=shutdownrunssudo shutdown -h now(Pi:routes_control.py:161)/api/control?action=synctimesets the timezone viasudo timedatectl set-timezone(Pi:routes_control.py:276)/api/device/renamecallssudo hostnamectl set-hostnameand restarts avahi (Pi:bcmeter/identity.py:41)/api/updaterunssudo systemctl restart bcMeter.serviceafter 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