Difference between revisions of "API reference"

From bcmeter.org
Jump to navigation Jump to search
(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 GET requests (<code>allow_origins=["*"]</code>).
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 info. Returns <code>"env": "pi"</code> to distinguish from ESP32 (<code>"env": "esp32"</code>).
| 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, disk usage, memory, modem status, GPS detail, barometric altitude, geolocation, current time
| 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/maintenance-logs</code> || 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 || <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=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.
| 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=stop</code> || Stop measurement and save session file.
| 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=calibrate</code> || Start calibration routine (returns 202 immediately — poll <code>/api/calibration</code> for progress). Requires sampling to be stopped.
| 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/calibration</code> || Calibration status: <code>{running, done, ok, elapsed_ms, log}</code>.
| GET || <code>/api/control?action=cleardata</code> || Delete all stored log files. || Both
|-
|-
| GET || <code>/api/control?action=clear_error</code> || Reset error state to ERR_NONE.
| GET || <code>/api/control?action=reboot</code> || End session and reboot the device. || Both
|-
|-
| GET || <code>/api/control?action=identify</code> || Triggers LED identify blink pattern (Morse code spelling "bcmeter" for 30 seconds). Useful for locating a specific device when multiple units are deployed.
| GET || <code>/api/control?action=shutdown</code> || Safely shut down the device. || Both
|-
|-
| GET || <code>/api/control?action=debug_mobile</code> || Triggers modem debug email via Lambda. Requires modem present.
| 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
|-
|-
| GET || <code>/api/config</code> || All settings as JSON. Each parameter includes type, value, label, tab, and description.
| POST || <code>/api/device/rename</code> || Set device name. Body: <code>{"name": "bcmeter-A3AB"}</code> (1–32 chars). Updates mDNS/hostname accordingly. || 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. Triggers deferred modem onboarding if <code>mail_logs_to</code> is set.
| GET || <code>/api/ap-security</code> || Hotspot security settings: <code>{secured: bool, password: str}</code>. || Both
|-
|-
| POST || <code>/api/device/rename</code> || Set device name and hostname. Body: <code>{"name": "bcmeter01"}</code> (1–32 chars). Runs <code>hostnamectl set-hostname</code>.
| POST || <code>/api/ap-security</code> || Update hotspot password. Body: <code>{"secured": true, "password": "..."}</code> (min 8 chars). || Both
|-
|-
| 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>). Applies timezone via <code>timedatectl</code>.
| 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/scan</code> || List nearby networks: <code>{scanning: bool, networks: [{ssid, rssi, secure}]}</code>. Add <code>?refresh=1</code> to trigger a new background scan.
|-
| POST || <code>/api/wifi/scan/refresh</code> || Explicitly trigger a new WiFi scan (returns 202, or 409 if already scanning).
|-
|-
| GET || <code>/api/wifi/status</code> || Current connection: <code>{mode, status, ssid, ip, rssi, quality (0-4), internet, timeSynced}</code>.
| 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
|-
|-
| POST || <code>/api/wifi</code> || Save WiFi credentials. Body: <code>{"ssid": "...", "pass": "..."}</code> (password min 8 chars).
| 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/connect</code> || Save credentials and initiate background connection attempt (returns 202). Password must be 8–63 chars. Body: <code>{"ssid": "...", "pass": "..."}</code>
| POST || <code>/api/wifi</code> || Save WiFi credentials. Body: <code>{"ssid": "...", "pass": "..."}</code> (password min 8 chars). Initiates reconnect. || 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>.
| 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
|-
|-
| POST || <code>/api/wifi/delete</code> || Delete credentials and switch to AP mode (deferred 2s background switch).
| 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
|-
|-
| GET || <code>/api/ap-security</code> || Hotspot security settings: <code>{secured: bool, password: str}</code>.
| POST || <code>/api/wifi/delete</code> || Delete credentials and switch to AP mode (deferred 2s background switch). || Both
|-
|-
| POST || <code>/api/ap-security</code> || Update hotspot password. Body: <code>{"secured": true, "password": "..."}</code> (min 8 chars).
| 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
|-
| GET || <code>/api/control?action=cleardata</code> || Delete all stored log files.
|}
|}


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, url, sha256, notes, skipped}</code>.
|-
| POST || <code>/api/ota/check</code> || Force check for new firmware against GitHub Releases.
|-
| POST || <code>/api/ota/skip</code> || Skip current available update for this boot.
|-
|-
| POST || <code>/api/ota/apply</code> || Download and apply firmware update. Returns 409 if none pending.
| 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/update</code> || Direct firmware upload (.tar.gz or .zip archive). Extracts over the code directory and restarts <code>bcMeter.service</code> via <code>systemctl</code>. Stops active session first.
| POST || <code>/api/ota/check</code> || Force check for new firmware. || Both
|}
 
=== System Operations ===
 
{| class="wikitable"
! Method !! Endpoint !! Description
|-
|-
| GET || <code>/api/control?action=reboot</code> || End session and reboot the device (fire-and-forget thread via <code>sudo reboot</code>).
| POST || <code>/api/ota/skip</code> || Skip current available update. || Both
|-
|-
| GET || <code>/api/control?action=shutdown</code> || Safely shut down via <code>sudo shutdown -h now</code>.
| POST || <code>/api/ota/apply</code> || Download and apply firmware update. Returns 409 if none pending. || 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>.
| 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>interface/index.html</code>)
| <code>/</code> || Serves the SPA frontend
|-
|-
| <code>/discover</code> || Standalone device discovery page (also hostable on bcmeter.org)
| <code>/discover</code> || Standalone device discovery page
|-
|-
| <code>/manual/*</code> || Static files from <code>interface/manual/</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>/current_log.csv</code> || Legacy redirect to <code>/api/csv</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=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