Standardize API UART parity and update docs
This commit is contained in:
+305
@@ -233,3 +233,308 @@ text 0.3.x
|
|||||||
Future firmware versions may add fields while maintaining backward compatibility.
|
Future firmware versions may add fields while maintaining backward compatibility.
|
||||||
|
|
||||||
Consumers should ignore unknown fields.
|
Consumers should ignore unknown fields.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Embedded Dashboard
|
||||||
|
|
||||||
|
The ESP32 is planned to serve a lightweight mobile dashboard at:
|
||||||
|
|
||||||
|
GET /
|
||||||
|
|
||||||
|
When connected directly to the ESP32 AP:
|
||||||
|
|
||||||
|
http://192.168.4.1/
|
||||||
|
|
||||||
|
The page should:
|
||||||
|
|
||||||
|
- Poll /status
|
||||||
|
- Display battery state
|
||||||
|
- Display temperature sensors
|
||||||
|
- Display relay states
|
||||||
|
- Show alarms
|
||||||
|
- Allow basic relay control
|
||||||
|
|
||||||
|
Design limits:
|
||||||
|
|
||||||
|
- Small inline HTML/CSS/JS
|
||||||
|
- No external libraries
|
||||||
|
- No large assets
|
||||||
|
- No heavy JavaScript framework
|
||||||
|
|
||||||
|
The embedded dashboard is intended as a convenient phone view, not a replacement for the physical Pico dashboard.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future WiFi API
|
||||||
|
|
||||||
|
Future configuration may include WiFi management endpoints.
|
||||||
|
|
||||||
|
Possible future endpoints:
|
||||||
|
|
||||||
|
GET /config/wifi
|
||||||
|
POST /config/wifi
|
||||||
|
POST /config/wifi/add
|
||||||
|
POST /config/wifi/remove
|
||||||
|
POST /config/wifi/reorder
|
||||||
|
|
||||||
|
Potential config model:
|
||||||
|
|
||||||
|
ap_enabled
|
||||||
|
sta_enabled
|
||||||
|
hostname
|
||||||
|
saved_networks
|
||||||
|
|
||||||
|
Saved networks should support priority order.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Starlink
|
||||||
|
Home WiFi
|
||||||
|
Shop WiFi
|
||||||
|
|
||||||
|
The AP should remain enabled even when connected to STA WiFi.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# HTTP / UART Parity Endpoints
|
||||||
|
|
||||||
|
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.
|
||||||
|
|||||||
@@ -233,3 +233,99 @@ Possible future integrations:
|
|||||||
- OTA updates
|
- OTA updates
|
||||||
|
|
||||||
All future integrations should consume the same generic status/config model.
|
All future integrations should consume the same generic status/config model.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Networking Architecture
|
||||||
|
|
||||||
|
### Current Network Mode
|
||||||
|
|
||||||
|
The ESP32 currently runs in Access Point mode.
|
||||||
|
|
||||||
|
Default access:
|
||||||
|
|
||||||
|
http://192.168.4.1
|
||||||
|
|
||||||
|
The AP is the recovery/setup network.
|
||||||
|
|
||||||
|
### Planned Network Mode
|
||||||
|
|
||||||
|
The planned long-term network mode is AP + STA.
|
||||||
|
|
||||||
|
AP mode:
|
||||||
|
|
||||||
|
Always available
|
||||||
|
Used for recovery and direct setup
|
||||||
|
|
||||||
|
STA mode:
|
||||||
|
|
||||||
|
Connects to a configured WiFi network
|
||||||
|
Used for camp/home access from phone or laptop
|
||||||
|
|
||||||
|
Example networks:
|
||||||
|
|
||||||
|
Starlink
|
||||||
|
Home WiFi
|
||||||
|
Shop WiFi
|
||||||
|
|
||||||
|
### Multiple WiFi Profiles
|
||||||
|
|
||||||
|
The ESP32 should eventually store multiple WiFi profiles and try them in priority order.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
1. Starlink
|
||||||
|
2. Home WiFi
|
||||||
|
3. Shop WiFi
|
||||||
|
|
||||||
|
Expected behavior:
|
||||||
|
|
||||||
|
Start AP first
|
||||||
|
Try configured STA networks
|
||||||
|
Connect to the first available network
|
||||||
|
Keep AP available even after STA connects
|
||||||
|
|
||||||
|
Reason:
|
||||||
|
|
||||||
|
- Starlink may be off
|
||||||
|
- Home WiFi may only be available in the driveway
|
||||||
|
- AP must remain available for recovery
|
||||||
|
- User should not lose access because of a bad WiFi password
|
||||||
|
|
||||||
|
### Phone Dashboard Access
|
||||||
|
|
||||||
|
When connected to the ESP32 AP:
|
||||||
|
|
||||||
|
http://192.168.4.1
|
||||||
|
|
||||||
|
When connected through Starlink/home WiFi:
|
||||||
|
|
||||||
|
http://controller-ip
|
||||||
|
|
||||||
|
Future mDNS target:
|
||||||
|
|
||||||
|
http://overland-controller.local
|
||||||
|
|
||||||
|
### Dashboard Roles
|
||||||
|
|
||||||
|
ESP32:
|
||||||
|
|
||||||
|
Source of truth
|
||||||
|
Lightweight phone dashboard
|
||||||
|
HTTP API
|
||||||
|
Recovery AP
|
||||||
|
|
||||||
|
Pico 2 W:
|
||||||
|
|
||||||
|
Instant physical dashboard
|
||||||
|
UART client
|
||||||
|
Touchscreen UI
|
||||||
|
|
||||||
|
Optional future Pi Zero:
|
||||||
|
|
||||||
|
Advanced web dashboard
|
||||||
|
Logging
|
||||||
|
Charts
|
||||||
|
Integrations
|
||||||
|
|
||||||
|
The Pi Zero should be optional, not required for core operation.
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# Command Parity Matrix
|
||||||
|
|
||||||
|
This document tracks feature parity across the three control surfaces.
|
||||||
|
|
||||||
|
Control surfaces:
|
||||||
|
|
||||||
|
- USB serial console
|
||||||
|
- UART JSON protocol
|
||||||
|
- HTTP API
|
||||||
|
|
||||||
|
## Current Parity
|
||||||
|
|
||||||
|
| Feature | USB Serial | UART JSON | HTTP API | Notes |
|
||||||
|
|---|---:|---:|---:|---|
|
||||||
|
| Status | Yes | Yes | Yes | `/status` equals `status_request` |
|
||||||
|
| Config view | Yes | Yes | Yes | `/config` equals `config_request` |
|
||||||
|
| Relay control | Yes | Yes | Yes | Preferred HTTP endpoint is `POST /relay/set` |
|
||||||
|
| Device name config | Yes | Yes | Yes | `devicename`, `config_device`, `/config/device` |
|
||||||
|
| Relay config | Yes | Yes | Yes | `relayname`, `config_relay`, `/config/relay` |
|
||||||
|
| Temperature config | Yes | Yes | Yes | `tempname`, `config_temp`, `/config/temp` |
|
||||||
|
| BMS config | Yes | Yes | Yes | `bmsname`/`bmsaddr`, `config_bms`, `/config/bms` |
|
||||||
|
| Save config | Yes | Yes | Yes | `save`, `save_config`, `/config/save` |
|
||||||
|
| Factory reset | Yes | Yes | Yes | AP remains recovery path |
|
||||||
|
| BMS setup enter | Yes | Yes | Yes | Setup pauses normal BMS reconnect behavior |
|
||||||
|
| BMS setup exit | Yes | Yes | Yes | Returns to normal mode |
|
||||||
|
| BLE scan | Yes | Yes | Yes | Some BMS devices require repeated scans |
|
||||||
|
| Select BMS | Yes | Yes | Yes | Uses most recent scan result index |
|
||||||
|
| WiFi config | Yes | Yes | Yes | Supports multiple saved STA networks |
|
||||||
|
| WiFi priority | Yes | Yes | Yes | Lower priority number is tried first |
|
||||||
|
| WiFi connect | Yes | Yes | Yes | AP remains available |
|
||||||
|
| WiFi clear | Yes | Yes | Yes | Clears saved STA networks |
|
||||||
|
|
||||||
|
## Preferred Command Model
|
||||||
|
|
||||||
|
Use generic IDs everywhere.
|
||||||
|
|
||||||
|
Relays:
|
||||||
|
|
||||||
|
relay_1
|
||||||
|
relay_2
|
||||||
|
|
||||||
|
Temperature sensors:
|
||||||
|
|
||||||
|
temp_1 through temp_8
|
||||||
|
|
||||||
|
Preferred relay command shape:
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "set_relay",
|
||||||
|
"id": "relay_1",
|
||||||
|
"state": true
|
||||||
|
}
|
||||||
|
|
||||||
|
Legacy UART relay fields may still be accepted:
|
||||||
|
|
||||||
|
relay
|
||||||
|
enabled
|
||||||
|
|
||||||
|
Preferred HTTP relay endpoint:
|
||||||
|
|
||||||
|
POST /relay/set
|
||||||
|
|
||||||
|
Legacy HTTP 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
|
||||||
|
|
||||||
|
## Response Shape Standard
|
||||||
|
|
||||||
|
Success responses should include:
|
||||||
|
|
||||||
|
ok: true
|
||||||
|
|
||||||
|
Error responses should include:
|
||||||
|
|
||||||
|
ok: false
|
||||||
|
error: "error_code"
|
||||||
|
|
||||||
|
Status/config responses should preserve the generic data model used by `/status`.
|
||||||
@@ -27,3 +27,8 @@ This folder contains project documentation for Overland Controller.
|
|||||||
Older or duplicate documents have been moved to `archive/`.
|
Older or duplicate documents have been moved to `archive/`.
|
||||||
|
|
||||||
Archived documents are kept for history, but the primary documents above should be treated as the current source of truth.
|
Archived documents are kept for history, but the primary documents above should be treated as the current source of truth.
|
||||||
|
|
||||||
|
|
||||||
|
## Parity
|
||||||
|
|
||||||
|
- `PARITY_MATRIX.md` - Command parity across USB serial, UART JSON, and HTTP API
|
||||||
|
|||||||
@@ -364,3 +364,53 @@ Returns complete runtime status including:
|
|||||||
- Alarms
|
- Alarms
|
||||||
- Network state
|
- Network state
|
||||||
- System information
|
- System information
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# WiFi Serial Commands
|
||||||
|
|
||||||
|
## wifi status
|
||||||
|
|
||||||
|
Print current WiFi status.
|
||||||
|
|
||||||
|
## wifi list
|
||||||
|
|
||||||
|
Print saved WiFi networks, priorities, and whether passwords are set.
|
||||||
|
|
||||||
|
## wifi clear
|
||||||
|
|
||||||
|
Clear saved STA WiFi networks.
|
||||||
|
|
||||||
|
## wifi ssid <ssid>
|
||||||
|
|
||||||
|
Set primary WiFi SSID.
|
||||||
|
|
||||||
|
## wifi pass <password>
|
||||||
|
|
||||||
|
Set primary WiFi password.
|
||||||
|
|
||||||
|
## wifi add <ssid>|<password>|<priority>
|
||||||
|
|
||||||
|
Add a saved WiFi network.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
wifi add Starlink|starlink_password|1
|
||||||
|
wifi add WardAP|Ward5213|2
|
||||||
|
wifi save
|
||||||
|
wifi connect
|
||||||
|
|
||||||
|
Lower priority numbers are tried first.
|
||||||
|
|
||||||
|
## wifi save
|
||||||
|
|
||||||
|
Save WiFi configuration.
|
||||||
|
|
||||||
|
## wifi connect
|
||||||
|
|
||||||
|
Attempt STA WiFi connection using saved networks by priority.
|
||||||
|
|
||||||
|
AP remains available at:
|
||||||
|
|
||||||
|
192.168.4.1
|
||||||
|
|||||||
@@ -205,3 +205,30 @@ Runtime behavior:
|
|||||||
|
|
||||||
If STA disconnects, the ESP32 retries saved networks by priority every 30 seconds.
|
If STA disconnects, the ESP32 retries saved networks by priority every 30 seconds.
|
||||||
AP mode remains available as a recovery path.
|
AP mode remains available as a recovery path.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# UART Parity Notes
|
||||||
|
|
||||||
|
UART should use the same generic command model as HTTP.
|
||||||
|
|
||||||
|
## Preferred Relay Command
|
||||||
|
|
||||||
|
Preferred:
|
||||||
|
|
||||||
|
{"type":"set_relay","id":"relay_1","state":true}
|
||||||
|
|
||||||
|
Legacy accepted shape:
|
||||||
|
|
||||||
|
{"type":"set_relay","relay":"relay_1","enabled":true}
|
||||||
|
|
||||||
|
Preferred response:
|
||||||
|
|
||||||
|
{"type":"relay_response","ok":true,"id":"relay_1","state":true}
|
||||||
|
|
||||||
|
## WiFi Priority Config
|
||||||
|
|
||||||
|
{"type":"config_wifi","networks":[{"ssid":"Starlink","password":"password","priority":1},{"ssid":"Home WiFi","password":"password","priority":2}]}
|
||||||
|
|
||||||
|
Lower priority numbers are tried first.
|
||||||
|
|||||||
@@ -591,8 +591,8 @@ bool setRelayById(const String& relayId, bool enabled) {
|
|||||||
void sendRelayResponse(Stream& output, const String& relayId, bool enabled) {
|
void sendRelayResponse(Stream& output, const String& relayId, bool enabled) {
|
||||||
DynamicJsonDocument doc(256);
|
DynamicJsonDocument doc(256);
|
||||||
doc["type"] = MSG_RELAY_RESPONSE;
|
doc["type"] = MSG_RELAY_RESPONSE;
|
||||||
doc["relay"] = relayId;
|
doc["id"] = relayId;
|
||||||
doc["enabled"] = enabled;
|
doc["state"] = enabled;
|
||||||
doc["ok"] = true;
|
doc["ok"] = true;
|
||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
output.println();
|
output.println();
|
||||||
@@ -712,8 +712,15 @@ void handleUartMessage(const String& line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(type, MSG_SET_RELAY) == 0 || strcmp(type, "set_relay") == 0) {
|
if (strcmp(type, MSG_SET_RELAY) == 0 || strcmp(type, "set_relay") == 0) {
|
||||||
String relayId = doc["relay"] | "";
|
String relayId = doc["id"] | "";
|
||||||
bool enabled = doc["enabled"] | false;
|
if (relayId.length() == 0) {
|
||||||
|
relayId = doc["relay"] | "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enabled = doc["state"] | false;
|
||||||
|
if (doc["enabled"].is<bool>()) {
|
||||||
|
enabled = doc["enabled"].as<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
if (!setRelayById(relayId, enabled)) {
|
if (!setRelayById(relayId, enabled)) {
|
||||||
sendError(DashboardSerial, "unknown_relay");
|
sendError(DashboardSerial, "unknown_relay");
|
||||||
@@ -1631,9 +1638,8 @@ void handleSetRelayPost() {
|
|||||||
DynamicJsonDocument response(512);
|
DynamicJsonDocument response(512);
|
||||||
response["type"] = "relay_response";
|
response["type"] = "relay_response";
|
||||||
response["ok"] = true;
|
response["ok"] = true;
|
||||||
response["relay"] = relayId;
|
response["id"] = relayId;
|
||||||
response["state"] = state;
|
response["state"] = state;
|
||||||
response["enabled"] = state;
|
|
||||||
|
|
||||||
String output;
|
String output;
|
||||||
serializeJson(response, output);
|
serializeJson(response, output);
|
||||||
|
|||||||
Reference in New Issue
Block a user