diff --git a/firmware/esp32/xterra-controller/bms.cpp b/firmware/esp32/xterra-controller/bms.cpp index 1aa9c02..8baaa33 100644 --- a/firmware/esp32/xterra-controller/bms.cpp +++ b/firmware/esp32/xterra-controller/bms.cpp @@ -19,6 +19,7 @@ static bool responseReady = false; static unsigned long lastReadAttempt = 0; static unsigned long bmsReconnectPausedUntil = 0; +static bool bmsSetupMode = false; static const unsigned long READ_INTERVAL_MS = 5000; BmsData bmsData; @@ -124,6 +125,45 @@ void pauseBmsReconnect(uint32_t pauseMs) { bmsReconnectPausedUntil = millis() + pauseMs; } + +void enterBmsSetupMode() { + Serial.print(logTimestamp()); + Serial.println(" BMS setup: entering setup mode"); + + bmsSetupMode = true; + pauseBmsReconnect(3600000UL); + + if (client && client->isConnected()) { + Serial.print(logTimestamp()); + Serial.println(" BMS setup: disconnecting BMS"); + client->disconnect(); + } + + if (client) { + NimBLEDevice::deleteClient(client); + client = nullptr; + } + + notifyChar = nullptr; + writeChar = nullptr; + bmsData.connected = false; + + Serial.print(logTimestamp()); + Serial.println(" BMS setup: ready for BLE scans"); +} + +void exitBmsSetupMode() { + Serial.print(logTimestamp()); + Serial.println(" BMS setup: exiting setup mode"); + + bmsSetupMode = false; + bmsReconnectPausedUntil = 0; +} + +bool isBmsSetupMode() { + return bmsSetupMode; +} + int getBleScanResultCount() { return bleScanResultCount; } @@ -138,61 +178,85 @@ const BleScanResult* getBleScanResult(int index) { int scanBleDevices(uint32_t scanSeconds) { Serial.print(logTimestamp()); - Serial.println(" BLE: Starting scan..."); - pauseBmsReconnect(60000UL); + Serial.println(" BLE: Starting setup scan..."); - if (client && client->isConnected()) { + if (!bmsSetupMode) { Serial.print(logTimestamp()); - Serial.println(" BLE: Disconnecting BMS before scan"); - client->disconnect(); - bmsData.connected = false; - - Serial.print(logTimestamp()); - Serial.println(" BLE: Waiting 5 seconds for device advertising..."); - delay(5000); + Serial.println(" BLE: auto-entering BMS setup mode for scan"); + enterBmsSetupMode(); } bleScanResultCount = 0; + Serial.print(logTimestamp()); + Serial.println(" BLE: waiting 5 seconds before scan"); + delay(5000); + NimBLEScan* scan = NimBLEDevice::getScan(); - scan->setScanCallbacks(&bleScanCallbacks, false); scan->setActiveScan(true); scan->setInterval(100); scan->setWindow(99); scan->clearResults(); Serial.print(logTimestamp()); - Serial.print(" BLE: Blocking scan requested for "); + Serial.print(" BLE: scanning for "); Serial.print(scanSeconds); Serial.println(" seconds..."); unsigned long scanStart = millis(); - bool started = scan->start(scanSeconds, false, true); + NimBLEScanResults results = scan->getResults(scanSeconds, false); - unsigned long scanElapsed = (millis() - scanStart) / 1000; + unsigned long elapsed = (millis() - scanStart) / 1000; Serial.print(logTimestamp()); - Serial.print(" BLE: scan call returned after "); - Serial.print(scanElapsed); + Serial.print(" BLE: scan returned after "); + Serial.print(elapsed); Serial.println(" seconds"); - if (!started) { - Serial.print(logTimestamp()); - Serial.println(" BLE: scan failed to start"); - return 0; + int resultCount = results.getCount(); + + Serial.print(logTimestamp()); + Serial.print(" BLE: raw devices seen: "); + Serial.println(resultCount); + + for (int i = 0; i < resultCount && bleScanResultCount < MAX_BLE_SCAN_RESULTS; i++) { + const NimBLEAdvertisedDevice* device = results.getDevice(i); + + String address = device->getAddress().toString().c_str(); + + bool alreadySeen = false; + for (int existing = 0; existing < bleScanResultCount; existing++) { + if (bleScanResults[existing].address == address) { + alreadySeen = true; + break; + } + } + + if (alreadySeen) { + continue; + } + + String name = ""; + if (device->haveName()) { + name = device->getName().c_str(); + } + + bleScanResults[bleScanResultCount].address = address; + bleScanResults[bleScanResultCount].name = name; + bleScanResults[bleScanResultCount].rssi = device->getRSSI(); + bleScanResultCount++; } - scan->stop(); scan->clearResults(); Serial.print(logTimestamp()); - Serial.print(" BLE: Devices found: "); + Serial.print(" BLE: devices found: "); Serial.println(bleScanResultCount); if (bleScanResultCount == 0) { Serial.println("No BLE devices found."); - return bleScanResultCount; + return 0; } Serial.println("BLE devices:"); @@ -214,6 +278,7 @@ int scanBleDevices(uint32_t scanSeconds) { } Serial.println("Use: select bms "); + Serial.println("Use: exit setup when finished"); return bleScanResultCount; } @@ -429,6 +494,10 @@ void initBms() { } void updateBms() { + if (bmsSetupMode) { + return; + } + if ((long)(bmsReconnectPausedUntil - millis()) > 0) { return; } diff --git a/firmware/esp32/xterra-controller/bms.h b/firmware/esp32/xterra-controller/bms.h index 3cbbe4c..b8b4b8d 100644 --- a/firmware/esp32/xterra-controller/bms.h +++ b/firmware/esp32/xterra-controller/bms.h @@ -42,3 +42,6 @@ int scanBleDevices(uint32_t scanSeconds = 10); int getBleScanResultCount(); const BleScanResult* getBleScanResult(int index); void pauseBmsReconnect(uint32_t pauseMs); +void enterBmsSetupMode(); +void exitBmsSetupMode(); +bool isBmsSetupMode(); diff --git a/firmware/esp32/xterra-controller/xterra-controller.ino b/firmware/esp32/xterra-controller/xterra-controller.ino index c595b40..d0b08b3 100644 --- a/firmware/esp32/xterra-controller/xterra-controller.ino +++ b/firmware/esp32/xterra-controller/xterra-controller.ino @@ -374,39 +374,18 @@ void handleDebugSerial() { return; } + if (command == "enter setup") { + enterBmsSetupMode(); + return; + } + + if (command == "exit setup") { + exitBmsSetupMode(); + return; + } + if (command == "scan ble") { - int count = scanBleDevices(20); - - if (count == 0) { - Serial.println("No BLE devices found."); - return; - } - - Serial.println("BLE devices:"); - - for (int i = 0; i < count; i++) { - const BleScanResult* result = getBleScanResult(i); - - if (!result) { - continue; - } - - Serial.print(i + 1); - Serial.print(") "); - - if (result->name.length() > 0) { - Serial.print(result->name); - } else { - Serial.print("(no name)"); - } - - Serial.print(" | "); - Serial.print(result->address); - Serial.print(" | RSSI "); - Serial.println(result->rssi); - } - - Serial.println("Use: select bms "); + scanBleDevices(20); return; } @@ -442,6 +421,7 @@ void handleDebugSerial() { Serial.print(" / "); Serial.println(appConfig.bms.address); Serial.println("BMS will reconnect on next update cycle."); + exitBmsSetupMode(); return; }