From d9b851aa53dd1b4fc53e0dc73c1daea1021a5494 Mon Sep 17 00:00:00 2001 From: nick Date: Sun, 7 Jun 2026 09:56:20 -0600 Subject: [PATCH] Clarify current HTTP API contract --- docs/API.md | 1168 ++++++++++++++++++++++++++------------------------- 1 file changed, 602 insertions(+), 566 deletions(-) diff --git a/docs/API.md b/docs/API.md index 5976c42..fbc6235 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,658 +1,694 @@ -# API.md - # HTTP API Reference -The ESP32 controller exposes a local HTTP API used by dashboards, management interfaces, and future integrations. +The Cargo ESP32 exposes a local JSON HTTP API for the embedded WebUI, the planned Waveshare ESP32-S3 dashboard, diagnostics, simulators, and future local integrations. -Default access point address: +Default AP address: -text http://192.168.4.1 +```text +http://192.168.4.1 +``` -All responses are JSON. +All documented endpoints are local-first and must continue to work without internet access. Consumers should ignore unknown response fields for forward compatibility. ---- +Current firmware version: -# GET /status +```text +0.4.0 +``` + +## Current Endpoints + +```text +GET / +GET /status +GET /config + +POST /relay/set + +POST /config/device +POST /config/relay +POST /config/temp +POST /config/bms +POST /config/save +POST /config/factory-reset + +GET /config/wifi +POST /config/wifi +POST /wifi/connect +POST /wifi/clear + +POST /temps/scan +POST /temps/assign +POST /temps/clear + +POST /bms/setup/enter +POST /bms/setup/exit +POST /bms/scan +POST /bms/select +``` + +Legacy relay routes remain available: + +```text +GET /relay/relay_1/on +GET /relay/relay_1/off +GET /relay/relay_2/on +GET /relay/relay_2/off +``` + +## Dashboard Contract + +The Waveshare ESP32-S3 dashboard MVP should use only: + +```text +GET /status +POST /relay/set +``` + +The dashboard is a client only. It may cache last-known values for display, but the Cargo ESP32 remains the source of truth for relay state, BMS state, alarms, and configuration. + +## Status + +### GET /status Returns complete controller status. -Includes: +Top-level response: -- Battery telemetry -- Temperature sensor status -- Relay status -- Vehicle status -- Network status -- Alarm status -- System information -- Current configuration +```json +{ + "type": "status_response", + "timestamp": 123456, + "battery": {}, + "temps": [], + "relays": [], + "vehicle": {}, + "network": {}, + "alarms": {}, + "system": {}, + "config": {} +} +``` -Example: +### battery -json { "type": "status_response", "battery": {}, "temps": [], "relays": [], "vehicle": {}, "network": {}, "alarms": {}, "system": {}, "config": {} } +```json +{ + "source": "jbd_bms", + "connected": true, + "soc": 70, + "voltage": 13.34, + "current": 0.0, + "remaining_ah": 104.8, + "capacity_ah": 150.0, + "runtime_hours": 0, + "temperature_f": 76.5, + "cycle_count": 3, + "cell_count": 4, + "ntc_count": 2, + "cell_voltages": [3.334, 3.333, 3.334, 3.333], + "cell_min_voltage": 3.333, + "cell_max_voltage": 3.334, + "cell_delta_mv": 1, + "cells_valid": true +} +``` ---- +`source` is `jbd_bms` when a configured BMS is expected, even if disconnected. It is `unconfigured` when BMS is not configured. -# Temperature Sensors +`runtime_hours` is discharge runtime estimated from remaining amp-hours and negative current. Charging time-to-full is derived by clients from `capacity_ah`, `remaining_ah`, and positive current. -Temperature sensors are returned as an array. +### temps -Example: +Runtime temperature sensors are returned as an array. -json { "id": "temp_1", "name": "Cabin", "enabled": true, "online": true, "temperature_f": 72.4 } +```json +{ + "id": "temp_1", + "name": "Cabin", + "enabled": true, + "weather": false, + "online": true, + "temperature_f": 72.4 +} +``` Fields: | Field | Description | -|---------|---------| -| id | Internal sensor identifier | -| name | User configured name | -| enabled | Sensor enabled | -| online | Sensor currently detected | -| temperature_f | Current temperature | +|---|---| +| `id` | Generic sensor ID | +| `name` | User-configured display name | +| `enabled` | Configured sensor enabled state | +| `weather` | Marks the outside/weather display sensor | +| `online` | Current sensor detection state | +| `temperature_f` | Current Fahrenheit value, or `null` when offline | -Valid IDs: +Config supports `temp_1` through `temp_8`. Current `/status` runtime output is limited to the configured count capped at four sensors. -text temp_1 temp_2 temp_3 temp_4 temp_5 temp_6 temp_7 temp_8 +### relays ---- +```json +{ + "id": "relay_1", + "name": "Aux Power", + "pin": 16, + "enabled": true, + "state": false +} +``` -# Relays +Valid relay IDs: -Relay states are returned as an array. +```text +relay_1 +relay_2 +``` -Example: +Relay names are user configuration. Firmware and clients should use generic IDs for commands. -json { "id": "relay_1", "name": "Aux Power", "pin": 16, "enabled": true, "state": false } +### vehicle + +```json +{ + "ignition_on": false +} +``` + +### network + +```json +{ + "wifi_enabled": true, + "uart_connected": true, + "ap_enabled": true, + "ap_ip": "192.168.4.1", + "sta_enabled": true, + "sta_connected": false, + "sta_ssid": "", + "sta_ip": "", + "saved_network_count": 2, + "saved_networks": [ + { + "index": 1, + "ssid": "Starlink", + "priority": 1, + "active": false + } + ] +} +``` + +The AP remains enabled even when STA WiFi is configured or connected. + +### alarms + +```json +{ + "low_soc": false, + "critical_soc": false, + "low_voltage": false, + "high_battery_temp": false, + "cell_imbalance": false, + "bms_disconnected": false +} +``` + +### system + +```json +{ + "firmware_name": "overland-controller", + "firmware_version": "0.4.0", + "build_date": "Jun 7 2026", + "build_time": "12:00:00", + "uptime_seconds": 123 +} +``` + +### config + +`/status.config` embeds the same core configuration model used by `GET /config`. + +## Configuration + +### GET /config + +Returns saved controller configuration. + +```json +{ + "device_name": "Overland Controller", + "relays": [ + { + "id": "relay_1", + "name": "Aux Power", + "pin": 16, + "enabled": true + } + ], + "bms": { + "enabled": true, + "name": "House Battery", + "address": "AA:BB:CC:DD:EE:FF", + "address_type": "public" + }, + "temperature_sensors": [ + { + "id": "temp_1", + "name": "Cabin", + "address": "28:AA:BB:CC:DD:EE:FF:00", + "enabled": true + } + ] +} +``` + +Note: current `GET /config` omits the `weather` field, while `/status.config.temperature_sensors[]` includes it. + +### POST /config/device + +Updates the controller display name. + +```json +{ + "device_name": "Overland Controller" +} +``` + +Returns the updated config. + +### POST /config/relay + +Updates relay configuration. + +```json +{ + "id": "relay_1", + "name": "Aux Power", + "enabled": true +} +``` Fields: -| Field | Description | -|---------|---------| -| id | Internal relay identifier | -| name | User configured name | -| pin | GPIO pin | -| enabled | Relay enabled | -| state | Current output state | +| Field | Required | Description | +|---|---:|---| +| `id` | Yes | `relay_1` or `relay_2` | +| `name` | No | User display name | +| `enabled` | No | Configured enabled state | -Valid IDs: +Returns the updated config. -text relay_1 relay_2 +### POST /config/temp -Future firmware versions may support additional relay outputs. +Updates temperature sensor configuration. ---- - -# Battery Object - -Example: - -json { "source": "jbd_bms", "connected": true, "soc": 70, "voltage": 13.34, "current": 0.0, "remaining_ah": 104.8, "capacity_ah": 150.0, "temperature_f": 76.5, "cycle_count": 3 } - -Additional fields may include: - -text cell_count cell_voltages cell_min_voltage cell_max_voltage cell_delta_mv runtime_hours ntc_count cells_valid - -`runtime_hours` is discharge runtime from the ESP32 status payload. The WebUI derives charging time-to-full from `capacity_ah`, `remaining_ah`, and positive incoming `current` without changing the API shape. - ---- - -# GET /config - -Returns the current saved configuration. - -Example: - -json { "device_name": "Overland Controller", "relays": [], "temperature_sensors": [], "bms": {} } - ---- - -# Relay Control - -## Turn Relay On - -text GET /relay/relay_1/on - -Example response: - -json { "ok": true, "id": "relay_1", "state": true } - ---- - -## Turn Relay Off - -text GET /relay/relay_1/off - -Example response: - -json { "ok": true, "id": "relay_1", "state": false } - ---- - -# Device Configuration - -## POST /config/device - -Updates the controller device name. - -Example request: - -json { "device_name": "Overland Controller" } - -Example response: - -json { "ok": true } - ---- - -# Relay Configuration - -## POST /config/relay - -Updates relay settings. - -Example request: - -json { "id": "relay_1", "name": "Aux Power", "enabled": true } +```json +{ + "id": "temp_1", + "name": "Cabin", + "address": "28:AA:BB:CC:DD:EE:FF:00", + "enabled": true, + "weather": false +} +``` Fields: -| Field | Required | -|---------|---------| -| id | Yes | -| name | No | -| enabled | No | +| Field | Required | Description | +|---|---:|---| +| `id` | Yes | `temp_1` through `temp_8` | +| `name` | No | User display name | +| `address` | No | DS18B20 address | +| `enabled` | No | Configured enabled state | +| `weather` | No | Outside/weather display flag | ---- +Returns the updated config. -# Temperature Sensor Configuration +### POST /config/bms -## POST /config/temp +Updates BMS configuration. -Updates temperature sensor settings. - -Example request: - -json { "id": "temp_1", "name": "Cabin", "enabled": true, "address": "" } - -Fields: - -| Field | Required | -|---------|---------| -| id | Yes | -| name | No | -| enabled | No | -| address | No | - ---- - -# BMS Configuration - -## POST /config/bms - -Updates BMS settings. - -Example request: - -json { "enabled": true, "name": "House Battery", "address": "AA:BB:CC:DD:EE:FF", "address_type": "public" } +```json +{ + "enabled": true, + "name": "House Battery", + "address": "AA:BB:CC:DD:EE:FF", + "address_type": "public" +} +``` Address types: -text public random +```text +public +random +``` ---- +Returns the updated config. -# Factory Reset +### POST /config/save -## POST /config/factory-reset +Persists the current active configuration. -Clears stored configuration and restores firmware defaults. +Returns the current config. -Example response: +### POST /config/factory-reset -json { "ok": true } +Clears saved configuration and restores firmware defaults. ---- +Returns the reset config. -# Error Responses +## Relay Control -Example: +### POST /relay/set -json { "ok": false, "error": "invalid relay id" } +Preferred relay command endpoint. -Typical errors: +```json +{ + "id": "relay_1", + "state": true +} +``` -text invalid relay id invalid sensor id invalid request missing parameter configuration save failed +Response: ---- +```json +{ + "type": "relay_response", + "ok": true, + "id": "relay_1", + "state": true +} +``` -# Versioning +### Legacy GET relay routes -Current firmware: +These routes remain for compatibility but should not be used by new clients: -text 0.3.x +```text +GET /relay/relay_1/on +GET /relay/relay_1/off +GET /relay/relay_2/on +GET /relay/relay_2/off +``` -Future firmware versions may add fields while maintaining backward compatibility. +Response: -Consumers should ignore unknown fields. +```json +{ + "ok": true, + "id": "relay_1", + "state": true +} +``` ---- +## WiFi -## Embedded Dashboard +### GET /config/wifi -The ESP32 is planned to serve a lightweight mobile dashboard at: +Returns AP/STA WiFi configuration status. Passwords are not returned. - GET / +```json +{ + "type": "wifi_config_response", + "ok": true, + "wifi": { + "ap_enabled": true, + "sta_enabled": true, + "network_count": 2, + "active_ssid": "Starlink", + "sta_connected": true, + "ap_ip": "192.168.4.1", + "sta_ip": "192.168.1.50", + "networks": [ + { + "index": 1, + "ssid": "Starlink", + "priority": 1, + "password_set": true + } + ] + } +} +``` -When connected directly to the ESP32 AP: +### POST /config/wifi - http://192.168.4.1/ +Preferred multi-network request: -The page should: +```json +{ + "networks": [ + { + "ssid": "Starlink", + "password": "password_here", + "priority": 1 + }, + { + "ssid": "Home WiFi", + "password": "password_here", + "priority": 2 + } + ] +} +``` -- Poll /status -- Display battery state -- Display temperature sensors -- Display relay states -- Show alarms -- Allow basic relay control +Legacy single-network shape is also accepted: -Design limits: +```json +{ + "ssid": "Starlink", + "password": "password_here" +} +``` -- Small inline HTML/CSS/JS +Returns WiFi config status. + +Runtime behavior: + +- AP remains enabled. +- Lower priority numbers are tried first. +- If STA disconnects, saved networks are retried by priority. + +### POST /wifi/connect + +Attempts STA connection using saved networks by priority. + +Returns WiFi config status. + +### POST /wifi/clear + +Clears saved STA WiFi networks. + +Returns WiFi config status. + +## Temperature Probe Setup + +### POST /temps/scan + +Scans the DS18B20 bus and returns unassigned probe addresses. + +```json +{ + "type": "temp_scan_response", + "ok": true, + "devices": [ + { + "index": 1, + "address": "28:AA:BB:CC:DD:EE:FF:00" + } + ] +} +``` + +Already-assigned probe addresses are hidden from scan results until cleared. + +### POST /temps/assign + +Assigns a scanned probe to a logical temperature slot. + +By ID: + +```json +{ + "id": "temp_1", + "index": 1 +} +``` + +By slot number: + +```json +{ + "slot": 1, + "index": 1 +} +``` + +Returns the updated config. + +### POST /temps/clear + +Clears one or all temperature assignments. + +By ID: + +```json +{ + "id": "temp_1" +} +``` + +By slot number: + +```json +{ + "slot": 1 +} +``` + +Empty POST body clears all temperature assignments. + +Clearing removes the stored DS18B20 address, disables the slot, clears the weather flag, resets cached temperature state, and persists config. + +Returns the updated config. + +## BMS Setup + +These endpoints are for BMS discovery and selection. Do not change JBD/Xiaoxiang BLE behavior without explicit approval. + +### POST /bms/setup/enter + +Enters BMS setup mode. + +Response: + +```json +{ + "type": "bms_setup_response", + "ok": true, + "mode": "setup" +} +``` + +### POST /bms/setup/exit + +Exits BMS setup mode. + +Response: + +```json +{ + "type": "bms_setup_response", + "ok": true, + "mode": "normal" +} +``` + +### POST /bms/scan + +Scans for BLE devices. + +Response: + +```json +{ + "type": "ble_scan_response", + "devices": [ + { + "index": 1, + "name": "House Battery", + "address": "aa:bb:cc:dd:ee:ff", + "rssi": -65 + } + ] +} +``` + +Some BMS devices advertise intermittently. Repeated scans may be needed. + +### POST /bms/select + +Selects a BMS from the most recent scan result. + +```json +{ + "index": 1 +} +``` + +Response: + +```json +{ + "type": "bms_setup_response", + "ok": true, + "name": "House Battery", + "address": "aa:bb:cc:dd:ee:ff" +} +``` + +Selection enables BMS config, saves the selected address, exits setup mode, and reconnects on the next update cycle. + +## Embedded WebUI + +### GET / + +Serves the embedded WebUI. + +The WebUI is a lightweight local setup and phone dashboard surface. It should remain small and self-contained: + +- Inline HTML/CSS/JS - No external libraries - No large assets - No heavy JavaScript framework -The embedded dashboard is intended as a convenient phone view and setup interface. It does not replace the planned Waveshare ESP32-S3 physical dashboard. +The WebUI is not a replacement for the planned Waveshare ESP32-S3 physical dashboard. ---- +## Errors -## Future WiFi API +Error responses use this shape: -Future configuration may include WiFi management endpoints. +```json +{ + "ok": false, + "error": "invalid_json" +} +``` -Possible future endpoints: +Known error codes: - GET /config/wifi - POST /config/wifi - POST /config/wifi/add - POST /config/wifi/remove - POST /config/wifi/reorder +```text +invalid_json +unknown_relay +unknown_temp_sensor +invalid_temp_selection +invalid_bms_selection +invalid_relay_route +missing_relay_action +invalid_relay_action +``` -Potential config model: +Some serial/UART errors use `message` instead of `error`; HTTP clients should rely on `error` for HTTP failures. - ap_enabled - sta_enabled - hostname - saved_networks +## Compatibility -Saved networks should support priority order. +Current stable route prefix is the root API path, for example `GET /status`. -Example: +Future versioning may move to `/api/v1`. Do not introduce versioned routes until consumers and docs are updated together. - Starlink - Home WiFi - Shop WiFi +New fields may be added to existing JSON objects. Consumers should ignore unknown fields. -The AP should remain enabled even when connected to STA WiFi. +## Not Current API ---- +These routes are not part of the current registered HTTP API: -# HTTP / UART Parity Endpoints +```text +POST /bms/reconnect +POST /system/restart +``` -These endpoints mirror UART setup/control messages. - -## Save Config - - POST /config/save - -Equivalent UART message: - - {"type":"save_config"} - -## BMS Setup Mode - -Enter BMS setup mode: - - POST /bms/setup/enter - -Equivalent UART message: - - {"type":"enter_bms_setup"} - -Exit BMS setup mode: - - POST /bms/setup/exit - -Equivalent UART message: - - {"type":"exit_bms_setup"} - -## BLE Scan - -Scan for BLE devices: - - POST /bms/scan - -Equivalent UART message: - - {"type":"scan_ble"} - -Response: - - { - "type": "ble_scan_response", - "devices": [ - { - "index": 1, - "name": "House Battery", - "address": "aa:bb:cc:dd:ee:ff", - "rssi": -65 - } - ] - } - -## Select BMS - -Select a BMS from the most recent scan: - - POST /bms/select - -Request body: - - { - "index": 1 - } - -Equivalent UART message: - - {"type":"select_bms","index":1} - ---- - -# Preferred Relay Command Endpoint - -The preferred relay control endpoint is: - - POST /relay/set - -Request body: - - { - "id": "relay_1", - "state": true - } - -Example: - - curl -X POST http://192.168.88.108/relay/set \ - -H "Content-Type: application/json" \ - -d '{"id":"relay_1","state":true}' - -Equivalent UART message: - - {"type":"set_relay","relay":"relay_1","enabled":true} - -Legacy GET relay routes may remain for compatibility: - - GET /relay/relay_1/on - GET /relay/relay_1/off - GET /relay/relay_2/on - GET /relay/relay_2/off - ---- - -# WiFi Configuration API - -## Get WiFi Config - - GET /config/wifi - -## Set WiFi Config - - POST /config/wifi - -Request body: - - { - "ssid": "Starlink", - "password": "password_here" - } - -## Connect STA WiFi - - POST /wifi/connect - -## Clear WiFi Config - - POST /wifi/clear - -The ESP32 AP remains available even when STA WiFi is configured. - -Equivalent UART messages: - - {"type":"wifi_request"} - - {"type":"config_wifi","ssid":"Starlink","password":"password_here"} - - {"type":"wifi_connect"} - - {"type":"wifi_clear"} - ---- - -# WiFi Priority and Runtime Failover - -Saved WiFi networks support priority. - -Lower priority numbers are attempted first. - -Example: - - { - "networks": [ - { - "ssid": "Starlink", - "password": "starlink_password", - "priority": 1 - }, - { - "ssid": "Home WiFi", - "password": "home_password", - "priority": 2 - } - ] - } - -The ESP32 behavior is: - - AP always stays enabled - STA tries saved networks by priority - If disconnected at runtime, STA retries saved networks every 30 seconds - If all STA networks fail, AP remains available at 192.168.4.1 - - ---- - -# API Parity Notes - -The HTTP API is intended to mirror the UART JSON protocol where practical. - -## Preferred Relay Control - -Preferred endpoint: - - POST /relay/set - -Request: - - { - "id": "relay_1", - "state": true - } - -Response: - - { - "type": "relay_response", - "ok": true, - "id": "relay_1", - "state": true - } - -Legacy relay routes may remain available for compatibility: - - GET /relay/relay_1/on - GET /relay/relay_1/off - GET /relay/relay_2/on - GET /relay/relay_2/off - -## WiFi Parity - -WiFi configuration supports multiple saved STA networks. - -Request: - - POST /config/wifi - -Body: - - { - "networks": [ - { - "ssid": "Starlink", - "password": "starlink_password", - "priority": 1 - }, - { - "ssid": "Home WiFi", - "password": "home_password", - "priority": 2 - } - ] - } - -Lower priority numbers are attempted first. - -Runtime behavior: - - AP always remains enabled. - STA tries saved networks by priority. - If STA disconnects, saved networks are retried every 30 seconds. - ---- - -# Temperature Probe Setup API - -## Scan Temperature Sensors - - POST /temps/scan - -Response: - - { - "type": "temp_scan_response", - "ok": true, - "devices": [ - { - "index": 1, - "address": "28:AA:BB:CC:DD:EE:FF:00" - } - ] - } - -## Assign Temperature Sensor - - POST /temps/assign - -Request: - - { - "id": "temp_1", - "index": 1 - } - -Alternative request: - - { - "slot": 1, - "index": 1 - } - -## Clear Temperature Sensor - - POST /temps/clear - -Request: - - { - "id": "temp_1" - } - -Alternative request: - - { - "slot": 1 - } - - ---- - -## Version 0.4.0 Notes - -The WebUI Config tab now exposes the preferred setup workflow. - -Important endpoints used by the WebUI: - - GET /status - GET /config - - POST /config/device - POST /config/relay - POST /config/temp - POST /config/bms - POST /config/save - POST /config/factory-reset - - POST /relay/set - - POST /temps/scan - POST /temps/assign - POST /temps/clear - - POST /config/wifi - POST /wifi/connect - POST /wifi/clear - - POST /bms/reconnect - POST /system/restart - -The preferred relay command endpoint remains: - - POST /relay/set - -Request: - - { - "id": "relay_1", - "state": true - } - -### Weather temperature sensor flag - -Temperature sensor config entries now include `weather: true`. - -When a configured temp sensor has `weather: true`, the WebUI may show it as the outside/weather temperature badge. The `/status` temp objects also include this flag so HTTP, UART, USB serial, and dashboard clients can identify the selected outside-air sensor without guessing from the sensor name. - -### Clear temperature assignments - -`POST /temps/clear` - -Request body options: - -- `{ "id": "temp_1" }` clears one logical temp slot by ID. -- `{ "slot": 1 }` clears one logical temp slot by number. -- Empty POST body clears all temp assignments. - -Clearing removes the stored DS18B20 address, disables the slot, clears the weather flag, resets cached temperature state, and persists config. +If added later, update this document and add contract tests.