diff --git a/firmware/esp32/overland-controller/overland-controller.ino b/firmware/esp32/overland-controller/overland-controller.ino index a877a78..9d7f0fd 100644 --- a/firmware/esp32/overland-controller/overland-controller.ino +++ b/firmware/esp32/overland-controller/overland-controller.ino @@ -923,6 +923,100 @@ void handleFactoryResetConfig() { sendConfigJson(); } + +void handleSaveConfig() { + saveConfig(); + sendConfigJson(); +} + +void handleEnterBmsSetup() { + enterBmsSetupMode(); + + server.send(200, "application/json", "{\"type\":\"bms_setup_response\",\"ok\":true,\"mode\":\"setup\"}"); +} + +void handleExitBmsSetup() { + exitBmsSetupMode(); + + server.send(200, "application/json", "{\"type\":\"bms_setup_response\",\"ok\":true,\"mode\":\"normal\"}"); +} + +void handleBleScan() { + scanBleDevices(20); + + DynamicJsonDocument doc(2048); + doc["type"] = "ble_scan_response"; + + JsonArray devices = doc.createNestedArray("devices"); + + int count = getBleScanResultCount(); + + for (int i = 0; i < count; i++) { + const BleScanResult* result = getBleScanResult(i); + + if (!result) { + continue; + } + + JsonObject device = devices.createNestedObject(); + device["index"] = i + 1; + device["name"] = result->name; + device["address"] = result->address; + device["rssi"] = result->rssi; + } + + String output; + serializeJson(doc, output); + server.send(200, "application/json", output); +} + +void handleSelectBms() { + DynamicJsonDocument doc(512); + DeserializationError error = deserializeJson(doc, server.arg("plain")); + + if (error) { + server.send(400, "application/json", "{\"ok\":false,\"error\":\"invalid_json\"}"); + return; + } + + int selected = doc["index"] | 0; + + if (selected < 1 || selected > getBleScanResultCount()) { + server.send(400, "application/json", "{\"ok\":false,\"error\":\"invalid_bms_selection\"}"); + return; + } + + const BleScanResult* result = getBleScanResult(selected - 1); + + if (!result) { + server.send(400, "application/json", "{\"ok\":false,\"error\":\"invalid_bms_selection\"}"); + return; + } + + appConfig.bms.enabled = true; + appConfig.bms.address = result->address; + appConfig.bms.addressType = "public"; + + if (result->name.length() > 0) { + appConfig.bms.name = result->name; + } else { + appConfig.bms.name = "BMS"; + } + + saveConfig(); + exitBmsSetupMode(); + + DynamicJsonDocument response(512); + response["type"] = "bms_setup_response"; + response["ok"] = true; + response["name"] = appConfig.bms.name; + response["address"] = appConfig.bms.address; + + String output; + serializeJson(response, output); + server.send(200, "application/json", output); +} + void handleGenericRelayRoute() { String uri = server.uri(); String prefix = "/relay/"; @@ -1026,6 +1120,13 @@ void setup() { server.on("/config/bms", HTTP_POST, handleUpdateBmsConfig); server.on("/config/temp", HTTP_POST, handleUpdateTempSensorConfig); server.on("/config/factory-reset", HTTP_POST, handleFactoryResetConfig); + server.on("/config/save", HTTP_POST, handleSaveConfig); + + server.on("/bms/setup/enter", HTTP_POST, handleEnterBmsSetup); + server.on("/bms/setup/exit", HTTP_POST, handleExitBmsSetup); + server.on("/bms/scan", HTTP_POST, handleBleScan); + server.on("/bms/select", HTTP_POST, handleSelectBms); + server.begin();