diff --git a/CHANGELOG.md b/CHANGELOG.md index 36436cdf..b76f54db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Added battery monitoring of BLE devices by @Flo100. +- Added battery monitoring of BLE devices by @Flo100. Implemented BLE HID shifting. ### Changed +-Disregard Peloton serial power and cadence if user has a BLE power Meter selected. - Filesystem no longer updates when auto-update is unchecked. - Holding shifter buttons on boot now erases LittleFS as well as resetting settings. - Fixed bug where "none" hr still scanned. Credit to @xpectnil for discovering. @@ -122,7 +123,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added comment when files are written to LittleFS. - Added comment when firmware starts to update. -- Added setting for minWatts +- Added setting for minWatts. +- Can now update LittleFS via update page. +- Removed dependency on jQuery. (Saves 30k in filesystem) ### Changed - Driver Over Temp logging fixed. @@ -130,7 +133,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Disabled setting of min/maxWatts if minWatts/maxWatts is 0. - Added a check to workaround a bug where a powertable pair member was zero. - Fixed a bug where a powertable pair could be returned that was larger than the powertable size. -- changes to default settings +- Changes to default settings. +- Fixed scanning memory leak. +- Scans continuously unless all devices are connected or set "none" ### Hardware diff --git a/data/bluetoothscanner.html b/data/bluetoothscanner.html index 403f4c48..27bb9fba 100644 --- a/data/bluetoothscanner.html +++ b/data/bluetoothscanner.html @@ -37,6 +37,12 @@

+ + +

+ + +

@@ -51,6 +57,13 @@

+ +
Power Correction FactorIncrease or decrease @@ -90,8 +103,10 @@

" + - OTAStyle; +String OTALoginIndex = "
" + "

ESP32 Login

" + " " + " " + "
" + "" + + OTAStyle; -String noIndexHTML = - "" - "" - "" - "

The webserver files
need to be updated.

" - "Please enter the credentials for your network
or upload a new " - "filesystem image using the
link below." - "" - " SmartSpin2K Web Server" - "" - "" - "
" - "

" - "" - "" - "" - "" - "
" - "
" - "" - "
" - "

Update " - "Firmware

" - "" - " " + - OTAStyle; +String noIndexHTML = "" + "" + "" + "

The webserver files
need to be updated.

" + "Please enter the credentials for your network
or upload a new " + "filesystem image using the
link below." + "" + " SmartSpin2K Web Server" + "" + "" + "
" + "

" + "" + "" + "" + "" + "
" + "
" + "" + "
" + "

Update " + "Firmware

" + "" + " " + + OTAStyle; /* Server Index Page */ -String OTAServerIndex = - "" - "
" - "" - "" - "" - "

" - "
" - "

" - "
" - "" + - OTAStyle; +String OTAServerIndex = "" + "
" + "
SmartSpin2k OTA
" + "
" + "" + "" + "
" + "
" + "
0%
" + "
" + "
" + "" + ""; diff --git a/include/Main.h b/include/Main.h index d7af547e..4fecab69 100644 --- a/include/Main.h +++ b/include/Main.h @@ -42,7 +42,6 @@ class SS2K { static void IRAM_ATTR shiftUp(); static void IRAM_ATTR shiftDown(); void resetIfShiftersHeld(); - void scanIfShiftersHeld(); void startTasks(); void stopTasks(); void restartWifi(); @@ -51,7 +50,6 @@ class SS2K { void updateStealthChop(); void checkDriverTemperature(); void motorStop(bool releaseTension = false); - void checkBLEReconnect(); void FTMSModeShiftModifier(); static void rxSerial(void); void txSerial(); diff --git a/include/SS2KLog.h b/include/SS2KLog.h index 9edf956a..d35e2513 100644 --- a/include/SS2KLog.h +++ b/include/SS2KLog.h @@ -23,8 +23,7 @@ #define LOG_HANDLER_TAG "Log_Handler" #ifndef DEBUG_LOG_BUFFER_SIZE -#define DEBUG_LOG_BUFFER_SIZE 0 -// #define DEBUG_LOG_BUFFER_SIZE 1500 +#define DEBUG_LOG_BUFFER_SIZE 2000 #endif #ifndef DEBUG_FILE_CHARS_PER_LINE diff --git a/include/SmartSpin_parameters.h b/include/SmartSpin_parameters.h index 0602e598..2fc3108f 100644 --- a/include/SmartSpin_parameters.h +++ b/include/SmartSpin_parameters.h @@ -121,10 +121,12 @@ class userParameters { bool stepperDir; bool shifterDir; bool udpLogEnabled = false; + bool logComm = false; String ssid; String password; String connectedPowerMeter = "any"; String connectedHeartMonitor = "any"; + String connectedRemote = "any"; String foundDevices = " "; public: @@ -164,6 +166,9 @@ class userParameters { void setConnectedHeartMonitor(String cHr) { connectedHeartMonitor = cHr; } const char* getConnectedHeartMonitor() { return connectedHeartMonitor.c_str(); } + void setConnectedRemote(String cRemote) { connectedRemote = cRemote; } + const char* getConnectedRemote() { return connectedRemote.c_str();} + void setStepperPower(int sp) { stepperPower = sp; } int getStepperPower() { return stepperPower; } @@ -182,6 +187,9 @@ class userParameters { void setUdpLogEnabled(bool enabled) { udpLogEnabled = enabled; } bool getUdpLogEnabled() { return udpLogEnabled; } + void setLogComm(bool lgcm) { logComm = lgcm; } + bool getLogComm() { return logComm; } + void setFoundDevices(String fdv) { foundDevices = fdv; } const char* getFoundDevices() { return foundDevices.c_str(); } diff --git a/include/settings.h b/include/settings.h index 1fe2e9d2..b6b03012 100644 --- a/include/settings.h +++ b/include/settings.h @@ -203,22 +203,17 @@ // Max tries that BLE client will perform on reconnect #define MAX_RECONNECT_TRIES 3 -// When quick reconnect fails ^^, we try to scan for the disconnected server. -// Scans slow BLE & WiFi traffic so we don't want to do this forever. -// Give up scanning for the lost connection after this many tries: -#define MAX_SCAN_RETRIES 2 - // loop speed for the SmartSpin2k BLE communications -#define BLE_NOTIFY_DELAY 500 +#define BLE_NOTIFY_DELAY 503 // loop speed for the SmartSpin2k BLE Client reconnect -#define BLE_CLIENT_DELAY 1000 +#define BLE_CLIENT_DELAY 101 // Number of devices that can be connected to the Client (myBLEDevices size) #define NUM_BLE_DEVICES 4 // loop speed for the Webserver -#define WEBSERVER_DELAY 60 +#define WEBSERVER_DELAY 7 // Name of default Power Meter. any connects to anything, none connects to // nothing. @@ -228,6 +223,10 @@ // nothing. #define CONNECTED_HEART_MONITOR "any" +// Name of default remote. any connects to anything, none connects to +// nothing. +#define CONNECTED_REMOTE "none" + // number of main loops the shifters need to be held before a BLE scan is // initiated. #define SHIFTERS_HOLD_FOR_SCAN 2 @@ -239,7 +238,7 @@ #define WIFI_CONNECT_TIMEOUT 10 // Max size of userconfig -#define USERCONFIG_JSON_SIZE 1024 + DEBUG_LOG_BUFFER_SIZE +#define USERCONFIG_JSON_SIZE 1524 + DEBUG_LOG_BUFFER_SIZE #define RUNTIMECONFIG_JSON_SIZE 512 + DEBUG_LOG_BUFFER_SIZE @@ -271,16 +270,16 @@ #define TX_CHECK_INTERVAL 20 // If ble devices are both setup, how often to attempt a reconnect. -#define BLE_RECONNECT_INTERVAL 15 +#define BLE_RECONNECT_INTERVAL 1 // Interval for polling ble battery updates #define BATTERY_UPDATE_INTERVAL_MILLIS 300000 // Initial and web scan duration. -#define DEFAULT_SCAN_DURATION 10 +#define DEFAULT_SCAN_DURATION 1 // BLE automatic reconnect duration. Set this low to avoid interruption. -#define BLE_RECONNECT_SCAN_DURATION 3 +#define BLE_RECONNECT_SCAN_DURATION 1 // Uncomment to enable sending Telegram debug messages back to the chat // specified in telegram_token.h diff --git a/lib/SS2K/include/Constants.h b/lib/SS2K/include/Constants.h index f56a0c12..faa52a13 100644 --- a/lib/SS2K/include/Constants.h +++ b/lib/SS2K/include/Constants.h @@ -65,3 +65,22 @@ #define PELOTON_POW_ID 0x44 #define PELOTON_REQ_POS 1 #define PELOTON_CHECKSUM_POS 2 + +//BLE HID +#define APPEARANCE_HID_GENERIC_UUID NimBLEUUID((uint16_t)0x3C0) +#define APPEARANCE_HID_KEYBOARD_UUID NimBLEUUID((uint16_t)0x3C1) +#define APPEARANCE_HID_MOUSE_UUID NimBLEUUID((uint16_t) 0x3C2) +#define APPEARANCE_HID_JOYSTICK_UUID NimBLEUUID((uint16_t)0x3C3) +#define APPEARANCE_HID_GAMEPAD_UUID NimBLEUUID((uint16_t)0x3C4) +#define APPEARANCE_HID_DIGITIZER_TABLET_UUID NimBLEUUID((uint16_t)0x3C5) +#define APPEARANCE_HID_CARD_READER_UUID NimBLEUUID((uint16_t)0x3C6) +#define APPEARANCE_HID_DIGITAL_PEN_UUID NimBLEUUID((uint16_t)0x3C7) +#define APPEARANCE_HID_BARCODE_SCANNER_UUID NimBLEUUID((uint16_t)0x3C8) +#define APPEARANCE_HID_TOUCHPAD_UUID NimBLEUUID((uint16_t)0x3C9) +#define APPEARANCE_HID_PRESENTATION_REMOTE_UUID NimBLEUUID((uint16_t)0x3CA) + +#define HID_SERVICE_UUID NimBLEUUID((uint16_t)0x1812) +#define HID_INFORMATION_UUID NimBLEUUID((uint16_t)0x2A4A) +#define HID_REPORT_MAP_UUID NimBLEUUID((uint16_t)0x2A4B) +#define HID_CONTROL_POINT_UUID NimBLEUUID((uint16_t)0x2A4C) +#define HID_REPORT_DATA_UUID NimBLEUUID((uint16_t)0x2A4D) diff --git a/platformio.ini b/platformio.ini index 975afc89..cb7f04c9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ default_envs = release [esp32doit] lib_ldf_mode = chain lib_compat_mode = strict -platform = espressif32 @ 5.3.0 +platform = espressif32 @ 6.0.1 board = esp32doit-devkit-v1 framework = arduino board_build.partitions = min_spiffs.csv @@ -26,10 +26,10 @@ build_flags = !python build_date_macro.py -D CONFIG_BT_NIMBLE_MAX_CONNECTIONS=6 -D CONFIG_MDNS_STRICT_MODE=1 - -D CORE_DEBUG_LEVEL=2 + -D CORE_DEBUG_LEVEL=1 -D ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE=3500 lib_deps = - https://github.com/h2zero/NimBLE-Arduino/archive/refs/tags/1.3.8.zip + https://github.com/h2zero/NimBLE-Arduino/archive/refs/tags/1.4.0.zip https://github.com/teemuatlut/TMCStepper/archive/refs/tags/v0.7.3.zip https://github.com/bblanchon/ArduinoJson/archive/refs/tags/v6.20.0.zip https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/archive/refs/tags/V1.3.0.zip diff --git a/src/BLE_Client.cpp b/src/BLE_Client.cpp index 61d90924..964dd6cd 100644 --- a/src/BLE_Client.cpp +++ b/src/BLE_Client.cpp @@ -25,6 +25,7 @@ TaskHandle_t BLEClientTask; SpinBLEClient spinBLEClient; static MyClientCallback myClientCallback; +static MyAdvertisedDeviceCallback myAdvertisedDeviceCallbacks; void SpinBLEClient::start() { // Create the task for the BLE Client loop @@ -38,6 +39,18 @@ void SpinBLEClient::start() { } static void onNotify(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) { + // Parse BLE shifter info. + if (pBLERemoteCharacteristic->getRemoteService()->getUUID() == HID_SERVICE_UUID) { + Serial.print(pData[0], HEX); + if (pData[0] == 0x04) { + rtConfig.setShifterPosition(rtConfig.getShifterPosition() + 1); + } + if (pData[0] == 0x08) { + rtConfig.setShifterPosition(rtConfig.getShifterPosition() - 1); + } + } + + // enqueue sensor data for (size_t i = 0; i < NUM_BLE_DEVICES; i++) { if (pBLERemoteCharacteristic->getUUID() == spinBLEClient.myBLEDevices[i].charUUID) { spinBLEClient.myBLEDevices[i].enqueueData(pData, length); @@ -49,11 +62,12 @@ static void onNotify(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t void bleClientTask(void *pvParameters) { for (;;) { vTaskDelay(BLE_CLIENT_DELAY / portTICK_PERIOD_MS); // Delay a second between loops. - if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0) && !NimBLEDevice::getScan()->isScanning()) { - spinBLEClient.scanRetries--; - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Initiating Scan from Client Task:"); - spinBLEClient.scanProcess(); - } + spinBLEClient.checkBLEReconnect(); + // if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0) && !NimBLEDevice::getScan()->isScanning()) { + // spinBLEClient.scanRetries--; + // SS2K_LOG(BLE_CLIENT_LOG_TAG, "Initiating Scan from Client Task:"); + // spinBLEClient.scanProcess(); + // } #ifdef DEBUG_STACK Serial.printf("BLEClient: %d \n", uxTaskGetStackHighWaterMark(BLEClientTask)); #endif // DEBUG_STACK @@ -61,7 +75,7 @@ void bleClientTask(void *pvParameters) { if (spinBLEClient.myBLEDevices[x].doConnect == true) { if (spinBLEClient.connectToServer()) { SS2K_LOG(BLE_CLIENT_LOG_TAG, "We are now connected to the BLE Server."); - vTaskDelay(5000 / portTICK_PERIOD_MS); + // vTaskDelay(5000 / portTICK_PERIOD_MS); } else { } } @@ -95,7 +109,7 @@ bool SpinBLEClient::connectToServer() { } else { SS2K_LOG(BLE_CLIENT_LOG_TAG, "doConnect and client out of alignment. Resetting device slot"); spinBLEClient.myBLEDevices[i].reset(); - spinBLEClient.serverScan(true); + // spinBLEClient.serverScan(true); return false; } } @@ -126,6 +140,10 @@ bool SpinBLEClient::connectToServer() { serviceUUID = HEARTSERVICE_UUID; charUUID = HEARTCHARACTERISTIC_UUID; SS2K_LOG(BLE_CLIENT_LOG_TAG, "Trying to connect to HRM"); + } else if (myDevice->isAdvertisingService(HID_SERVICE_UUID)) { + serviceUUID = HID_SERVICE_UUID; + charUUID = HID_REPORT_DATA_UUID; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Trying to connect to BLE HID remote"); } else { SS2K_LOG(BLE_CLIENT_LOG_TAG, "No advertised UUID found"); spinBLEClient.myBLEDevices[device_number].reset(); @@ -134,7 +152,7 @@ bool SpinBLEClient::connectToServer() { } else { SS2K_LOG(BLE_CLIENT_LOG_TAG, "Device has no Service UUID"); spinBLEClient.myBLEDevices[device_number].reset(); - spinBLEClient.serverScan(true); + // spinBLEClient.serverScan(true); return false; } String t_name = ""; @@ -153,6 +171,7 @@ bool SpinBLEClient::connectToServer() { */ pClient = NimBLEDevice::getClientByPeerAddress(myDevice->getAddress()); if (pClient) { + pClient->setConnectTimeout(2); SS2K_LOG(BLE_CLIENT_LOG_TAG, "Reusing Client"); if (!pClient->connect(myDevice, false)) { SS2K_LOG(BLE_CLIENT_LOG_TAG, "Reconnect failed "); @@ -160,9 +179,11 @@ bool SpinBLEClient::connectToServer() { SS2K_LOG(BLE_CLIENT_LOG_TAG, "%d left.", reconnectTries); if (reconnectTries < 1) { spinBLEClient.myBLEDevices[device_number].reset(); - spinBLEClient.myBLEDevices[device_number].doConnect = false; - connectedPM = false; - serverScan(false); + spinBLEClient.resetDevices(pClient); + pClient->deleteServices(); + pClient->disconnect(); + NimBLEDevice::getScan()->erase(pClient->getPeerAddress()); + NimBLEDevice::deleteClient(pClient); } return false; } @@ -193,14 +214,18 @@ bool SpinBLEClient::connectToServer() { * connections. Timeout should be a multiple of the interval, minimum is 100ms. * Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 51 * 10ms = 510ms timeout */ - pClient->setConnectionParams(12, 12, 0, 100); + pClient->setConnectionParams(6, 6, 0, 200); /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */ - pClient->setConnectTimeout(5); + pClient->setConnectTimeout(2); // 5 if (!pClient->connect(myDevice->getAddress())) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, " - Failed to connect client"); /** Created a client but failed to connect, don't need to keep it as it has no data */ + spinBLEClient.myBLEDevices[device_number].reset(); + pClient->deleteServices(); + pClient->disconnect(); + NimBLEDevice::getScan()->erase(pClient->getPeerAddress()); NimBLEDevice::deleteClient(pClient); - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Failed to connect, deleted client"); return false; } } @@ -214,7 +239,18 @@ bool SpinBLEClient::connectToServer() { SS2K_LOG(BLE_CLIENT_LOG_TAG, "Connected to: %s RSSI %d", pClient->getPeerAddress().toString().c_str(), pClient->getRssi()); - /** Now we can read/write/subscribe the charateristics of the services we are interested in */ + if (serviceUUID == HID_SERVICE_UUID) { + connectBLE_HID(pClient); + this->reconnectTries = MAX_RECONNECT_TRIES; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Successful remote subscription."); + spinBLEClient.myBLEDevices[device_number].doConnect = false; + this->reconnectTries = MAX_RECONNECT_TRIES; + spinBLEClient.myBLEDevices[device_number].set(myDevice, pClient->getConnId(), serviceUUID, charUUID); + removeDuplicates(pClient); + return true; + } + + /** Now we can read/write/subscribe the characteristics of the services we are interested in */ NimBLERemoteService *pSvc = nullptr; NimBLERemoteCharacteristic *pChr = nullptr; NimBLERemoteDescriptor *pDsc = nullptr; @@ -233,7 +269,11 @@ bool SpinBLEClient::connectToServer() { // if(!pChr->registerForNotify(notifyCB)) { if (!pChr->subscribe(true, onNotify)) { /** Disconnect if subscribe failed */ + spinBLEClient.myBLEDevices[device_number].reset(); + pClient->deleteServices(); pClient->disconnect(); + NimBLEDevice::getScan()->erase(pClient->getPeerAddress()); + NimBLEDevice::deleteClient(pClient); return false; } } else if (pChr->canIndicate()) { @@ -241,12 +281,15 @@ bool SpinBLEClient::connectToServer() { // if(!pChr->registerForNotify(notifyCB, false)) { if (!pChr->subscribe(false, onNotify)) { /** Disconnect if subscribe failed */ + spinBLEClient.myBLEDevices[device_number].reset(); + pClient->deleteServices(); pClient->disconnect(); + NimBLEDevice::getScan()->erase(pClient->getPeerAddress()); + NimBLEDevice::deleteClient(pClient); return false; } } this->reconnectTries = MAX_RECONNECT_TRIES; - this->scanRetries = MAX_SCAN_RETRIES; SS2K_LOG(BLE_CLIENT_LOG_TAG, "Successful %s subscription.", pChr->getUUID().toString().c_str()); spinBLEClient.myBLEDevices[device_number].doConnect = false; this->reconnectTries = MAX_RECONNECT_TRIES; @@ -272,15 +315,15 @@ void MyClientCallback::onConnect(NimBLEClient *pClient) { } void MyClientCallback::onDisconnect(NimBLEClient *pClient) { + NimBLEDevice::getScan()->stop(); + //NimBLEDevice::getScan()->clearResults(); + //NimBLEDevice::getScan()->clearDuplicateCache(); SS2K_LOG(BLE_CLIENT_LOG_TAG, "Disconnect Called"); - if (spinBLEClient.intentionalDisconnect) { SS2K_LOG(BLE_CLIENT_LOG_TAG, "Intentional Disconnect"); spinBLEClient.intentionalDisconnect = false; return; } - - //cleanup spinBLE.myDevices if (!pClient->isConnected()) { NimBLEAddress addr = pClient->getPeerAddress(); // auto addr = BLEDevice::getDisconnectedClient()->getPeerAddress(); @@ -301,7 +344,12 @@ void MyClientCallback::onDisconnect(NimBLEClient *pClient) { if ((spinBLEClient.myBLEDevices[i].charUUID == HEARTCHARACTERISTIC_UUID)) { SS2K_LOG(BLE_CLIENT_LOG_TAG, "Deregistered HR on Disconnect"); rtConfig.hr_batt.setValue(0); - spinBLEClient.connectedHR = false; + spinBLEClient.connectedHRM = false; + break; + } + if ((spinBLEClient.myBLEDevices[i].charUUID == HID_REPORT_DATA_UUID)) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Deregistered Remote on Disconnect"); + spinBLEClient.connectedRemote = false; break; } } @@ -331,7 +379,6 @@ void MyClientCallback::onAuthenticationComplete(ble_gap_conn_desc desc) { SS2K_L void MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *advertisedDevice) { auto advertisedDeviceInfo = advertisedDevice->toString(); ss2k_remove_newlines(&advertisedDeviceInfo); - SS2K_LOG(BLE_CLIENT_LOG_TAG, "BLE Advertised Device found: %s", advertisedDeviceInfo.c_str()); String aDevName; if (advertisedDevice->haveName()) { aDevName = String(advertisedDevice->getName().c_str()); @@ -341,12 +388,19 @@ void MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *advertisedDevice) if ((advertisedDevice->haveServiceUUID()) && (advertisedDevice->isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || (advertisedDevice->isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) && aDevName == FLYWHEEL_BLE_NAME) || advertisedDevice->isAdvertisingService(FITNESSMACHINESERVICE_UUID) || advertisedDevice->isAdvertisingService(HEARTSERVICE_UUID) || - advertisedDevice->isAdvertisingService(ECHELON_DEVICE_UUID))) { - // if ((aDevName == c_PM) || (advertisedDevice->getAddress().toString().c_str() == c_PM) || (aDevName == c_HR) || (advertisedDevice->getAddress().toString().c_str() == c_HR) || - // (String(c_PM) == ("any")) || (String(c_HR) == ("any"))) { //notice the subtle difference vv getServiceUUID(int) returns the index of the service in the list or the 0 slot if - // not specified. + advertisedDevice->isAdvertisingService(ECHELON_DEVICE_UUID) || advertisedDevice->isAdvertisingService(HID_SERVICE_UUID))) { SS2K_LOG(BLE_CLIENT_LOG_TAG, "Matching Device Name: %s", aDevName.c_str()); - if (advertisedDevice->getServiceUUID() == HEARTSERVICE_UUID) { + if (advertisedDevice->getServiceUUID() == HID_SERVICE_UUID) { + if (String(userConfig.getConnectedRemote()) == "any") { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Remote String Matched Any"); + // continue + } else if (aDevName != String(userConfig.getConnectedRemote()) || (String(userConfig.getConnectedRemote()) == "none")) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Skipping non-selected Remote |%s|%s", aDevName.c_str(), userConfig.getConnectedRemote()); + return; + } else if (aDevName == String(userConfig.getConnectedRemote())) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Remote String Matched %s", aDevName.c_str()); + } + } else if (advertisedDevice->getServiceUUID() == HEARTSERVICE_UUID) { if (String(userConfig.getConnectedHeartMonitor()) == "any") { SS2K_LOG(BLE_CLIENT_LOG_TAG, "HR String Matched Any"); // continue @@ -356,8 +410,7 @@ void MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *advertisedDevice) } else if (aDevName == String(userConfig.getConnectedHeartMonitor())) { SS2K_LOG(BLE_CLIENT_LOG_TAG, "HR String Matched %s", aDevName.c_str()); } - } else { // Already tested -->((advertisedDevice->getServiceUUID()(CYCLINGPOWERSERVICE_UUID) || advertisedDevice->getServiceUUID()(FLYWHEEL_UART_SERVICE_UUID) || - // advertisedDevice->getServiceUUID()(FITNESSMACHINESERVICE_UUID))) + } else { if (String(userConfig.getConnectedPowerMeter()) == "any") { SS2K_LOG(BLE_CLIENT_LOG_TAG, "PM String Matched Any"); // continue @@ -383,18 +436,18 @@ void MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *advertisedDevice) //} } } - void SpinBLEClient::scanProcess(int duration) { this->doScan = false; // Confirming we did the scan - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Scanning for BLE servers and putting them into a list..."); + SS2K_LOGW(BLE_CLIENT_LOG_TAG, "Scanning for BLE servers and putting them into a list..."); BLEScan *pBLEScan = BLEDevice::getScan(); - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallback()); - pBLEScan->setInterval(97); - pBLEScan->setWindow(67); + pBLEScan->setAdvertisedDeviceCallbacks(&myAdvertisedDeviceCallbacks); + pBLEScan->setInterval(49); // 97 + pBLEScan->setWindow(33); // 67 pBLEScan->setDuplicateFilter(true); pBLEScan->setActiveScan(true); BLEScanResults foundDevices = pBLEScan->start(duration, true); + this->dontBlockScan = false; // Load the scan into a Json String int count = foundDevices.getCount(); @@ -405,7 +458,7 @@ void SpinBLEClient::scanProcess(int duration) { for (int i = 0; i < count; i++) { BLEAdvertisedDevice d = foundDevices.getDevice(i); if (d.isAdvertisingService(CYCLINGPOWERSERVICE_UUID) || d.isAdvertisingService(HEARTSERVICE_UUID) || d.isAdvertisingService(FLYWHEEL_UART_SERVICE_UUID) || - d.isAdvertisingService(FITNESSMACHINESERVICE_UUID) || d.isAdvertisingService(ECHELON_DEVICE_UUID)) { + d.isAdvertisingService(FITNESSMACHINESERVICE_UUID) || d.isAdvertisingService(ECHELON_DEVICE_UUID) || d.isAdvertisingService(HID_SERVICE_UUID)) { device = "device " + String(i); devices[device]["address"] = d.getAddress().toString(); @@ -421,7 +474,7 @@ void SpinBLEClient::scanProcess(int duration) { String output; serializeJson(devices, output); - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Bluetooth Client Found Devices: %s", output.c_str()); + SS2K_LOGW(BLE_CLIENT_LOG_TAG, "Bluetooth Client Found Devices: %s", output.c_str()); #ifdef USE_TELEGRAM SEND_TO_TELEGRAM("Bluetooth Client Found Devices: " + output); #endif @@ -429,25 +482,14 @@ void SpinBLEClient::scanProcess(int duration) { pBLEScan = nullptr; // free up memory } -// This is the main server scan request process to use. +/*// This is the main server scan request process to use. void SpinBLEClient::serverScan(bool connectRequest) { + this->dontBlockScan = true; if (connectRequest) { this->scanRetries = MAX_SCAN_RETRIES; } this->doScan = true; -} - -// Shuts down all BLE processes. -void SpinBLEClient::disconnect() { - this->scanRetries = 0; - this->reconnectTries = 0; - intentionalDisconnect = true; - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Shutting Down all BLE services"); - if (NimBLEDevice::getInitialized()) { - NimBLEDevice::deinit(); - vTaskDelay(100 / portTICK_RATE_MS); - } -} +}*/ // remove the last connected BLE Power Meter void SpinBLEClient::removeDuplicates(NimBLEClient *pClient) { @@ -479,11 +521,12 @@ void SpinBLEClient::removeDuplicates(NimBLEClient *pClient) { } } -void SpinBLEClient::resetDevices() { - SpinBLEAdvertisedDevice tBLEd; +void SpinBLEClient::resetDevices(NimBLEClient *pClient) { for (size_t i = 0; i < NUM_BLE_DEVICES; i++) { - tBLEd = this->myBLEDevices[i]; - tBLEd.reset(); + if (pClient->getPeerAddress() == myBLEDevices[i].peerAddress) { + SS2K_LOGW(BLE_CLIENT_LOG_TAG, "Reset Client Slot: %d", i); + myBLEDevices[i].reset(); + } } } @@ -512,45 +555,34 @@ void SpinBLEClient::postConnect() { if (NimBLEDevice::getClientByPeerAddress(myBLEDevices[i].peerAddress)) { myBLEDevices[i].postConnected = true; NimBLEClient *pClient = NimBLEDevice::getClientByPeerAddress(myBLEDevices[i].peerAddress); - if ((this->myBLEDevices[i].charUUID == CYCLINGPOWERMEASUREMENT_UUID) || (this->myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) || - (this->myBLEDevices[i].charUUID == FLYWHEEL_UART_RX_UUID) || (this->myBLEDevices[i].charUUID == ECHELON_DATA_UUID) || - (this->myBLEDevices[i].charUUID == CYCLINGPOWERSERVICE_UUID)) { - this->connectedPM = true; - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered PM on Connect"); - - if (this->myBLEDevices[i].charUUID == ECHELON_DATA_UUID) { - NimBLERemoteCharacteristic *writeCharacteristic = pClient->getService(ECHELON_SERVICE_UUID)->getCharacteristic(ECHELON_WRITE_UUID); - if (writeCharacteristic == nullptr) { - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Failed to find Echelon write characteristic UUID: %s", ECHELON_WRITE_UUID.toString().c_str()); - pClient->disconnect(); - return; - } - // Enable device notifications - byte message[] = {0xF0, 0xB0, 0x01, 0x01, 0xA2}; - writeCharacteristic->writeValue(message, 5); - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Activated Echelon callbacks."); - rtConfig.setMinResistance(MIN_ECHELON_RESISTANCE); - rtConfig.setMaxResistance(MAX_ECHELON_RESISTANCE); + if (this->myBLEDevices[i].charUUID == ECHELON_DATA_UUID) { + NimBLERemoteCharacteristic *writeCharacteristic = pClient->getService(ECHELON_SERVICE_UUID)->getCharacteristic(ECHELON_WRITE_UUID); + if (writeCharacteristic == nullptr) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Failed to find Echelon write characteristic UUID: %s", ECHELON_WRITE_UUID.toString().c_str()); + pClient->disconnect(); + return; } + // Enable device notifications + byte message[] = {0xF0, 0xB0, 0x01, 0x01, 0xA2}; + writeCharacteristic->writeValue(message, 5); + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Activated Echelon callbacks."); + rtConfig.setMinResistance(MIN_ECHELON_RESISTANCE); + rtConfig.setMaxResistance(MAX_ECHELON_RESISTANCE); + } - if (this->myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) { - NimBLERemoteCharacteristic *writeCharacteristic = pClient->getService(FITNESSMACHINESERVICE_UUID)->getCharacteristic(FITNESSMACHINECONTROLPOINT_UUID); - if (writeCharacteristic == nullptr) { - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Failed to find FTMS control characteristic UUID: %s", FITNESSMACHINECONTROLPOINT_UUID.toString().c_str()); - return; - } - // Start Training - writeCharacteristic->writeValue(FitnessMachineControlPointProcedure::RequestControl, 1); - vTaskDelay(BLE_NOTIFY_DELAY / portTICK_PERIOD_MS); - writeCharacteristic->writeValue(FitnessMachineControlPointProcedure::StartOrResume, 1); - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Activated FTMS Training."); + if (this->myBLEDevices[i].charUUID == FITNESSMACHINEINDOORBIKEDATA_UUID) { + NimBLERemoteCharacteristic *writeCharacteristic = pClient->getService(FITNESSMACHINESERVICE_UUID)->getCharacteristic(FITNESSMACHINECONTROLPOINT_UUID); + if (writeCharacteristic == nullptr) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Failed to find FTMS control characteristic UUID: %s", FITNESSMACHINECONTROLPOINT_UUID.toString().c_str()); + return; } + // Start Training + writeCharacteristic->writeValue(FitnessMachineControlPointProcedure::RequestControl, 1); + vTaskDelay(BLE_NOTIFY_DELAY / portTICK_PERIOD_MS); + writeCharacteristic->writeValue(FitnessMachineControlPointProcedure::StartOrResume, 1); + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Activated FTMS Training."); + BLEDevice::getServer()->updateConnParams(pClient->getConnId(), 120, 120, 2, 1000); } - if ((this->myBLEDevices[i].charUUID == HEARTCHARACTERISTIC_UUID)) { - this->connectedHR = true; - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered HRM on Connect"); - } - BLEDevice::getServer()->updateConnParams(pClient->getConnId(), 400, 400, 2, 1000); } } } @@ -558,15 +590,6 @@ void SpinBLEClient::postConnect() { bool SpinBLEAdvertisedDevice::enqueueData(uint8_t *data, size_t length) { NotifyData notifyData; - // Serial.println("enqueue Called"); - if (!this->dataBufferQueue) { - // Serial.println("Creating queue"); - this->dataBufferQueue = xQueueCreate(6, sizeof(NotifyData)); - if (!this->dataBufferQueue) { - // Serial.println("Failed to create queue"); - return pdFALSE; - } - } if (!uxQueueSpacesAvailable(this->dataBufferQueue)) { // Serial.println("No space available in queue. Skipping enqueue of data."); @@ -612,21 +635,160 @@ void SpinBLEAdvertisedDevice::print() { logBufP += sprintf(logBufP, " Client ID: (%d)", connectedClientID); logBufP += sprintf(logBufP, " SerUUID: (%s)", serviceUUID.toString().c_str()); logBufP += sprintf(logBufP, " CharUUID: (%s)", charUUID.toString().c_str()); - logBufP += sprintf(logBufP, " HRM: (%s)", userSelectedHR ? "true" : "false"); - logBufP += sprintf(logBufP, " PM: (%s)", userSelectedPM ? "true" : "false"); - logBufP += sprintf(logBufP, " CSC: (%s)", userSelectedCSC ? "true" : "false"); - logBufP += sprintf(logBufP, " CT: (%s)", userSelectedCT ? "true" : "false"); + logBufP += sprintf(logBufP, " HRM: (%s)", isHRM ? "true" : "false"); + logBufP += sprintf(logBufP, " PM: (%s)", isPM ? "true" : "false"); + logBufP += sprintf(logBufP, " CSC: (%s)", isCSC ? "true" : "false"); + logBufP += sprintf(logBufP, " CT: (%s)", isCT ? "true" : "false"); logBufP += sprintf(logBufP, " doConnect: (%s)", doConnect ? "true" : "false"); strcat(logBufP, "|"); SS2K_LOG(BLE_CLIENT_LOG_TAG, "%s", String(logBuf)); } +void SpinBLEClient::connectBLE_HID(NimBLEClient *pClient) { + NimBLERemoteService *pSvc = nullptr; + NimBLERemoteCharacteristic *pChr = nullptr; + pSvc = pClient->getService(HID_SERVICE_UUID); + if (pSvc) { /** make sure it's not null */ + // This returns the HID report descriptor like this + // HID_REPORT_MAP 0x2a4b Value: 5,1,9,2,A1,1,9,1,A1,0,5,9,19,1,29,5,15,0,25,1,75,1, + // Copy and paste the value digits to http://eleccelerator.com/usbdescreqparser/ + // to see the decoded report descriptor. + /*pChr = pSvc->getCharacteristic(HID_REPORT_MAP_UUID); + if (pChr) { /** make sure it's not null */ + /* Serial.print("HID_REPORT_MAP "); + if (pChr->canRead()) { + std::string value = pChr->readValue(); + Serial.print(pChr->getUUID().toString().c_str()); + Serial.print(" Value: "); + uint8_t *p = (uint8_t *)value.data(); + for (size_t i = 0; i < value.length(); i++) { + Serial.print(p[i], HEX); + Serial.print(','); + } + Serial.println(); + } + } else { + Serial.println("HID REPORT MAP char not found."); + } +*/ + // Subscribe to characteristics HID_REPORT_DATA. + // One real device reports 2 with the same UUID but + // different handles. Using getCharacteristic() results + // in subscribing to only one. + std::vector *charVector; + charVector = pSvc->getCharacteristics(true); + for (auto &it : *charVector) { + if (it->getUUID() == NimBLEUUID(HID_REPORT_DATA_UUID)) { + Serial.println(it->toString().c_str()); + if (it->canNotify()) { + if (!it->subscribe(true, onNotify)) { + /** Disconnect if subscribe failed */ + Serial.println("subscribe notification failed"); + pClient->disconnect(); + return; // false; + } else { + Serial.println("subscribed"); + } + } + } + } + } + Serial.println("Done with this device!"); + return; // true; +} + +void SpinBLEClient::keepAliveBLE_HID(NimBLEClient *pClient) { + static int intervalTimer = millis(); + if ((millis() - intervalTimer) < 6000) { + return; + } + NimBLERemoteService *pSvc = nullptr; + NimBLERemoteCharacteristic *pChr = nullptr; + pSvc = pClient->getService(HID_SERVICE_UUID); + if (pSvc) { /** make sure it's not null */ + pChr = pSvc->getCharacteristic(HID_REPORT_MAP_UUID); + if (pChr) { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "BLE HID Keep Alive"); + pClient->setConnectionParams(12, 12, 0, 3200); + intervalTimer = millis(); + } else { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Keep Alive failed"); + } + } +} + +void SpinBLEClient::checkBLEReconnect() { + bool scan = false; + if ((String(userConfig.getConnectedHeartMonitor()) != "none") && !(spinBLEClient.connectedHRM)) { + scan = true; + } + if ((String(userConfig.getConnectedPowerMeter()) != "none") && !(spinBLEClient.connectedPM)) { + scan = true; + } + if ((String(userConfig.getConnectedRemote()) != "none") && !(spinBLEClient.connectedRemote)) { + scan = true; + } + if (scan) { + if (!NimBLEDevice::getScan()->isScanning()) { + spinBLEClient.scanProcess(BLE_RECONNECT_SCAN_DURATION); + Serial.println("scan"); + } + } +} + +void SpinBLEAdvertisedDevice::set(BLEAdvertisedDevice *device, int id, BLEUUID inServiceUUID, BLEUUID inCharUUID) { + advertisedDevice = device; + peerAddress = device->getAddress(); + connectedClientID = id; + serviceUUID = BLEUUID(inServiceUUID); + charUUID = BLEUUID(inCharUUID); + dataBufferQueue = xQueueCreate(4, sizeof(NotifyData)); + if (inServiceUUID == HEARTSERVICE_UUID) { + isHRM = true; + spinBLEClient.connectedHRM = true; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered HRM on Connect"); + } else if (inServiceUUID == CSCSERVICE_UUID) { + isCSC = true; + spinBLEClient.connectedCD = true; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered CSC on Connect"); + } else if (inServiceUUID == CYCLINGPOWERSERVICE_UUID || inServiceUUID == FITNESSMACHINESERVICE_UUID || inServiceUUID == FLYWHEEL_UART_SERVICE_UUID || + inServiceUUID == ECHELON_SERVICE_UUID || inServiceUUID == PELOTON_DATA_UUID) { + isPM = true; + spinBLEClient.connectedPM = true; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered PM on Connect"); + } else if (inServiceUUID == HID_SERVICE_UUID) { + isRemote = true; + spinBLEClient.connectedRemote = true; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Registered Remote on Connect"); + } else { + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Failed to set service!"); + } +} + +void SpinBLEAdvertisedDevice::reset() { + advertisedDevice = nullptr; + // NimBLEAddress peerAddress; + connectedClientID = BLE_HS_CONN_HANDLE_NONE; + serviceUUID = (uint16_t)0x0000; + charUUID = (uint16_t)0x0000; + isHRM = false; // Heart Rate Monitor + isPM = false; // Power Meter + isCSC = false; // Cycling Speed/Cadence + isCT = false; // Controllable Trainer + isRemote = false; // BLE Remote + doConnect = false; // Initiate connection flag + postConnected = false; // Has Cost Connect Been Run? + if (dataBufferQueue != nullptr) { + // Serial.println("Resetting queue"); + xQueueReset(dataBufferQueue); + } +} // Poll BLE devices for battCharacteristic if available and read value. void SpinBLEClient::handleBattInfo(NimBLEClient *pClient, bool updateNow=false) { static unsigned long last_battery_update = 0; if ((millis() - last_battery_update >= BATTERY_UPDATE_INTERVAL_MILLIS) || (last_battery_update == 0) || updateNow) { last_battery_update = millis(); - if (pClient->getService(HEARTSERVICE_UUID)) { // get battery level at first connect + if (pClient->getService(HEARTSERVICE_UUID) && pClient->getService(BATTERYSERVICE_UUID)) { // get battery level at first connect BLERemoteCharacteristic *battCharacteristic = pClient->getService(BATTERYSERVICE_UUID)->getCharacteristic(BATTERYCHARACTERISTIC_UUID); if (battCharacteristic != nullptr) { std::string value = battCharacteristic->readValue(); @@ -635,7 +797,7 @@ void SpinBLEClient::handleBattInfo(NimBLEClient *pClient, bool updateNow=false) } else { rtConfig.hr_batt.setValue(0); } - } else if (pClient->getService(CYCLINGPOWERMEASUREMENT_UUID) || pClient->getService(CYCLINGPOWERSERVICE_UUID)) { // get batterylevel at first connect + } else if ((pClient->getService(CYCLINGPOWERMEASUREMENT_UUID) || pClient->getService(CYCLINGPOWERSERVICE_UUID)) && pClient->getService(BATTERYSERVICE_UUID)) { // get batterylevel at first connect BLERemoteCharacteristic *battCharacteristic = pClient->getService(BATTERYSERVICE_UUID)->getCharacteristic(BATTERYCHARACTERISTIC_UUID); if (battCharacteristic != nullptr) { std::string value = battCharacteristic->readValue(); diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp index ad6e363a..1ea4e0e5 100644 --- a/src/BLE_Common.cpp +++ b/src/BLE_Common.cpp @@ -8,10 +8,12 @@ #include "Main.h" #include "SS2KLog.h" #include "BLE_Common.h" -#include +#include "Constants.h" + #include #include #include +#include bool hr2p = false; @@ -19,14 +21,17 @@ TaskHandle_t BLECommunicationTask; void BLECommunications(void *pvParameters) { for (;;) { + if (!spinBLEClient.dontBlockScan) { + NimBLEDevice::getScan()->stop(); // stop routine scans + } // **********************************Client*************************************** for (size_t x = 0; x < NUM_BLE_DEVICES; x++) { // loop through discovered devices if (spinBLEClient.myBLEDevices[x].connectedClientID != BLE_HS_CONN_HANDLE_NONE) { SS2K_LOGD(BLE_COMMON_LOG_TAG, "Address: (%s) Client ID: (%d) SerUUID: (%s) CharUUID: (%s) HRM: (%s) PM: (%s) CSC: (%s) CT: (%s) doConnect: (%s)", spinBLEClient.myBLEDevices[x].peerAddress.toString().c_str(), spinBLEClient.myBLEDevices[x].connectedClientID, spinBLEClient.myBLEDevices[x].serviceUUID.toString().c_str(), spinBLEClient.myBLEDevices[x].charUUID.toString().c_str(), - spinBLEClient.myBLEDevices[x].userSelectedHR ? "true" : "false", spinBLEClient.myBLEDevices[x].userSelectedPM ? "true" : "false", - spinBLEClient.myBLEDevices[x].userSelectedCSC ? "true" : "false", spinBLEClient.myBLEDevices[x].userSelectedCT ? "true" : "false", + spinBLEClient.myBLEDevices[x].isHRM ? "true" : "false", spinBLEClient.myBLEDevices[x].isPM ? "true" : "false", + spinBLEClient.myBLEDevices[x].isCSC? "true" : "false", spinBLEClient.myBLEDevices[x].isCT ? "true" : "false", spinBLEClient.myBLEDevices[x].doConnect ? "true" : "false"); if (spinBLEClient.myBLEDevices[x].advertisedDevice) { // is device registered? SpinBLEAdvertisedDevice myAdvertisedDevice = spinBLEClient.myBLEDevices[x]; @@ -36,12 +41,14 @@ void BLECommunications(void *pvParameters) { // Client connected with a valid UUID registered if ((myAdvertisedDevice.serviceUUID != BLEUUID((uint16_t)0x0000)) && (pClient->isConnected())) { BLERemoteCharacteristic *pRemoteBLECharacteristic = pClient->getService(myAdvertisedDevice.serviceUUID)->getCharacteristic(myAdvertisedDevice.charUUID); - // std::string data = pRemoteBLECharacteristic->getValue(); - // uint8_t *pData = reinterpret_cast(&data[0]); - // int length = data.length(); - // 250 == Data(60), Spaces(Data/2), Arrow(4), SvrUUID(37), Sep(3), ChrUUID(37), Sep(3), - // Name(10), Prefix(2), HR(8), SEP(1), CD(10), SEP(1), PW(8), SEP(1), SP(7), Suffix(2), Nul(1) - 225 rounded up + // Handle BLE HID Remotes + if (spinBLEClient.myBLEDevices[x].serviceUUID == HID_SERVICE_UUID) { + spinBLEClient.keepAliveBLE_HID(pClient); //keep alive doesn't seem to help :( + continue; // There is not data that needs to be dequeued for the remote, so got to the next device. + } + + // Dequeue sensor data we stored during notifications while (pdTRUE) { NotifyData incomingNotifyData = myAdvertisedDevice.dequeueData(); if (incomingNotifyData.length == 0) { @@ -53,7 +60,8 @@ void BLECommunications(void *pvParameters) { for (size_t i = 0; i < length; i++) { pData[i] = incomingNotifyData.data[i]; } - collectAndSet(pRemoteBLECharacteristic->getUUID(), myAdvertisedDevice.serviceUUID, pRemoteBLECharacteristic->getRemoteService()->getClient()->getPeerAddress(), pData, length); + collectAndSet(pRemoteBLECharacteristic->getUUID(), myAdvertisedDevice.serviceUUID, pRemoteBLECharacteristic->getRemoteService()->getClient()->getPeerAddress(), + pData, length); } spinBLEClient.handleBattInfo(pClient, false); @@ -74,8 +82,7 @@ void BLECommunications(void *pvParameters) { } // ***********************************SERVER************************************** - if ((spinBLEClient.connectedHR || rtConfig.hr.getSimulate()) && !spinBLEClient.connectedPM && !rtConfig.watts.getSimulate() && (rtConfig.hr.getValue() > 0) && - userPWC.hr2Pwr) { + if ((spinBLEClient.connectedHRM|| rtConfig.hr.getSimulate()) && !spinBLEClient.connectedPM && !rtConfig.watts.getSimulate() && (rtConfig.hr.getValue() > 0) && userPWC.hr2Pwr) { calculateInstPwrFromHR(); hr2p = true; } else { @@ -89,7 +96,7 @@ void BLECommunications(void *pvParameters) { rtConfig.cad.setValue(0); rtConfig.watts.setValue(0); } - if (!spinBLEClient.connectedHR && !rtConfig.hr.getSimulate()) { + if (!spinBLEClient.connectedHRM&& !rtConfig.hr.getSimulate()) { rtConfig.hr.setValue(0); } @@ -125,11 +132,6 @@ void BLECommunications(void *pvParameters) { } else { digitalWrite(LED_PIN, HIGH); } - if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0) && !NimBLEDevice::getScan()->isScanning()) { - spinBLEClient.scanRetries--; - SS2K_LOG(BLE_CLIENT_LOG_TAG, "Initiating Scan from Client Task:"); - spinBLEClient.scanProcess(); - } vTaskDelay((BLE_NOTIFY_DELAY) / portTICK_PERIOD_MS); #ifdef DEBUG_STACK Serial.printf("BLEComm: %d \n", uxTaskGetStackHighWaterMark(BLECommunicationTask)); diff --git a/src/BLE_Server.cpp b/src/BLE_Server.cpp index 185a2ad5..efca8d33 100644 --- a/src/BLE_Server.cpp +++ b/src/BLE_Server.cpp @@ -92,9 +92,9 @@ void logCharacteristic(char *buffer, const size_t bufferCapacity, const byte *da va_end(args); SS2K_LOG(BLE_SERVER_LOG_TAG, "%s", buffer); - #ifdef USE_TELEGRAM +#ifdef USE_TELEGRAM SEND_TO_TELEGRAM(String(buffer)); - #endif +#endif } void startBLEServer() { @@ -239,11 +239,11 @@ void updateIndoorBikeDataChar() { fitnessMachineIndoorBikeData->setValue(ftmsIndoorBikeData, 11); fitnessMachineIndoorBikeData->notify(); - //ftmsResistanceLevelRange[0] = (uint8_t)rtConfig.getMinResistance() & 0xff; - //ftmsResistanceLevelRange[1] = (uint8_t)rtConfig.getMinResistance() >> 8; - //ftmsResistanceLevelRange[2] = (uint8_t)rtConfig.getMaxResistance() & 0xff; - //ftmsResistanceLevelRange[3] = (uint8_t)rtConfig.getMaxResistance() >> 8; - //ftmsResistanceLevelRange.setValue(ftmsResistanceLevelRange, 6); + // ftmsResistanceLevelRange[0] = (uint8_t)rtConfig.getMinResistance() & 0xff; + // ftmsResistanceLevelRange[1] = (uint8_t)rtConfig.getMinResistance() >> 8; + // ftmsResistanceLevelRange[2] = (uint8_t)rtConfig.getMaxResistance() & 0xff; + // ftmsResistanceLevelRange[3] = (uint8_t)rtConfig.getMaxResistance() >> 8; + // ftmsResistanceLevelRange.setValue(ftmsResistanceLevelRange, 6); const int kLogBufCapacity = 200; // Data(30), Sep(data/2), Arrow(3), CharId(37), Sep(3), CharId(37), Sep(3), Name(10), Prefix(2), HR(7), SEP(1), CD(10), SEP(1), PW(8), // SEP(1), SD(7), Suffix(2), Nul(1), rounded up @@ -324,6 +324,12 @@ void MyServerCallbacks::onDisconnect(BLEServer *pServer) { BLEDevice::startAdvertising(); } +bool MyServerCallbacks::onConnParamsUpdateRequest(NimBLEClient *pClient, const ble_gap_upd_params *params) { + // Failing to accept parameters may result in the remote device + // disconnecting. + return true; +}; + void MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { FTMSWrite = pCharacteristic->getValue(); } void MyCallbacks::onSubscribe(NimBLECharacteristic *pCharacteristic, ble_gap_conn_desc *desc, uint16_t subValue) { @@ -581,7 +587,7 @@ void calculateInstPwrFromHR() { oldHR = newHR; // Copying HR from Last loop newHR = rtConfig.hr.getValue(); - delta = (newHR - oldHR) / (BLE_CLIENT_DELAY / 1000); + delta = (newHR - oldHR) / (BLE_CLIENT_DELAY / 1000) +1 ; // userConfig.setSimulatedWatts((s1Pwr*s2HR)-(s2Pwr*S1HR))/(S2HR-s1HR)+(userConfig.getSimulatedHr(*((s1Pwr-s2Pwr)/(s1HR-s2HR))); int avgP = ((userPWC.session1Pwr * userPWC.session2HR) - (userPWC.session2Pwr * userPWC.session1HR)) / (userPWC.session2HR - userPWC.session1HR) + diff --git a/src/BLE_Setup.cpp b/src/BLE_Setup.cpp index a2c645ff..55ad978a 100644 --- a/src/BLE_Setup.cpp +++ b/src/BLE_Setup.cpp @@ -22,16 +22,16 @@ void setupBLE() { // Common BLE setup for both client and server "BLECommunicationTask", /* name of task. */ 6000, /* Stack size of task*/ NULL, /* parameter of the task */ - 1, /* priority of the task*/ + 3, /* priority of the task*/ &BLECommunicationTask, /* Task handle to keep track of created task */ 1); /* pin task to core */ SS2K_LOG(BLE_SETUP_LOG_TAG, "BLE Notify Task Started"); - vTaskDelay(100 / portTICK_PERIOD_MS); + /*vTaskDelay(100 / portTICK_PERIOD_MS); if (strcmp(userConfig.getConnectedPowerMeter(), "none") != 0 || strcmp(userConfig.getConnectedHeartMonitor(), "none") != 0) { spinBLEClient.serverScan(true); SS2K_LOG(BLE_SETUP_LOG_TAG, "Scanning"); - } - SS2K_LOG(BLE_SETUP_LOG_TAG, "%s %s", userConfig.getConnectedPowerMeter(), userConfig.getConnectedHeartMonitor()); + }*/ + SS2K_LOG(BLE_SETUP_LOG_TAG, "%s %s %s", userConfig.getConnectedPowerMeter(), userConfig.getConnectedHeartMonitor(), userConfig.getConnectedRemote()); SS2K_LOG(BLE_SETUP_LOG_TAG, "End BLE Setup"); } diff --git a/src/HTTP_Server_Basic.cpp b/src/HTTP_Server_Basic.cpp index 725ffca1..fb163ef1 100644 --- a/src/HTTP_Server_Basic.cpp +++ b/src/HTTP_Server_Basic.cpp @@ -149,8 +149,8 @@ void HTTP_Server::start() { "Scanning for BLE Devices. Please wait " "15 seconds."; - spinBLEClient.resetDevices(); - spinBLEClient.serverScan(true); + // spinBLEClient.resetDevices(); + // spinBLEClient.serverScan(true); server.send(200, "text/html", response); }); @@ -294,7 +294,7 @@ void HTTP_Server::start() { }); server.on("/OTAIndex", HTTP_GET, []() { - spinBLEClient.disconnect(); + ss2k.stopTasks(); server.sendHeader("Connection", "close"); server.send(200, "text/html", OTAServerIndex); }); @@ -311,9 +311,8 @@ void HTTP_Server::start() { if (upload.filename == String("firmware.bin").c_str()) { if (upload.status == UPLOAD_FILE_START) { SS2K_LOG(HTTP_SERVER_LOG_TAG, "Update: %s", upload.filename.c_str()); - ss2k.stopTasks(); - if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { // start with max - // available size + if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) { // start with max + // available size Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { @@ -325,7 +324,30 @@ void HTTP_Server::start() { if (Update.end(true)) { // true to set the size to the // current progress server.send(200, "text/plain", "Firmware Uploaded Successfully. Rebooting..."); - vTaskDelay(2000 / portTICK_PERIOD_MS); + ESP.restart(); + } else { + Update.printError(Serial); + } + } + } else if (upload.filename == String("littlefs.bin").c_str()) { + if (upload.status == UPLOAD_FILE_START) { + SS2K_LOG(HTTP_SERVER_LOG_TAG, "Update: %s", upload.filename.c_str()); + if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) { // start with max + // available size + Update.printError(Serial); + } + } else if (upload.status == UPLOAD_FILE_WRITE) { + /* flashing firmware to ESP*/ + if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { + Update.printError(Serial); + } + } else if (upload.status == UPLOAD_FILE_END) { + if (Update.end(true)) { // true to set the size to the + // current progress + server.send(200, "text/plain", "Spiffs Uploaded Successfully. Rebooting..."); + userConfig.saveToLittleFS(); + userPWC.saveToLittleFS(); + vTaskDelay(100); ESP.restart(); } else { Update.printError(Serial); @@ -361,7 +383,7 @@ void HTTP_Server::start() { "webClientUpdate", /* name of task. */ 6000 + (DEBUG_LOG_BUFFER_SIZE * 2), /* Stack size of task Used to be 3000*/ NULL, /* parameter of the task */ - 2, /* priority of the task */ + 10, /* priority of the task */ &webClientTask, /* Task handle to keep track of created task */ 0); /* pin task to core */ @@ -506,6 +528,11 @@ void HTTP_Server::settingsProcessor() { } else if (wasSettingsUpdate) { userConfig.setUdpLogEnabled(false); } + if (!server.arg("logComm").isEmpty()) { + userConfig.setLogComm(true); + } else if (wasSettingsUpdate) { + userConfig.setLogComm(false); + } if (!server.arg("stealthChop").isEmpty()) { userConfig.setStealthChop(true); ss2k.updateStealthChop(); @@ -531,7 +558,7 @@ void HTTP_Server::settingsProcessor() { tString = server.arg("blePMDropdown"); if (tString != userConfig.getConnectedPowerMeter()) { userConfig.setConnectedPowerMeter(tString); - reboot = true; + reboot = true; } } else { userConfig.setConnectedPowerMeter("any"); @@ -550,6 +577,19 @@ void HTTP_Server::settingsProcessor() { userConfig.setConnectedHeartMonitor("any"); } } + if (!server.arg("bleRemoteDropdown").isEmpty()) { + wasBTUpdate = true; + if (server.arg("bleRemoteDropdown")) { + bool reset = false; + tString = server.arg("bleRemoteDropdown"); + if (tString != userConfig.getConnectedRemote()) { + reboot = true; + } + userConfig.setConnectedRemote(server.arg("bleRemoteDropdown")); + } else { + userConfig.setConnectedRemote("any"); + } + } if (!server.arg("session1HR").isEmpty()) { // Needs checking for unrealistic numbers. userPWC.session1HR = server.arg("session1HR").toInt(); } @@ -575,8 +615,8 @@ void HTTP_Server::settingsProcessor() { "Selections Saved!"; - spinBLEClient.resetDevices(); - spinBLEClient.serverScan(true); + // spinBLEClient.resetDevices(); + // spinBLEClient.serverScan(true); } else if (wasSettingsUpdate) { // Special Settings Page update response response += "Network settings will be applied at next reboot.
Everything " @@ -596,11 +636,11 @@ void HTTP_Server::settingsProcessor() { userPWC.saveToLittleFS(); userPWC.printFile(); if (reboot) { - response += + response += "Please wait while your settings are saved and SmartSpin2k reboots."; - server.send(200, "text/html", response); + server.send(200, "text/html", response); vTaskDelay(100 / portTICK_PERIOD_MS); ESP.restart(); } diff --git a/src/Main.cpp b/src/Main.cpp index 56533741..42fc3cb0 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -58,12 +58,25 @@ void SS2K::startTasks() { } void SS2K::stopTasks() { + spinBLEClient.reconnectTries = 0; + spinBLEClient.intentionalDisconnect = true; + SS2K_LOG(BLE_CLIENT_LOG_TAG, "Shutting Down all BLE services"); + if (NimBLEDevice::getInitialized()) { + NimBLEDevice::deinit(); + ss2k.stopTasks(); + } SS2K_LOG(MAIN_LOG_TAG, "Stop BLE + ERG Tasks"); if (BLECommunicationTask != NULL) { vTaskDelete(BLECommunicationTask); + BLECommunicationTask = NULL; } if (ErgTask != NULL) { vTaskDelete(ErgTask); + ErgTask = NULL; + } + if (BLEClientTask != NULL) { + vTaskDelete(BLEClientTask); + BLEClientTask = NULL; } } @@ -163,7 +176,7 @@ void setup() { xTaskCreatePinnedToCore(SS2K::maintenanceLoop, /* Task function. */ "maintenanceLoopFunction", /* name of task. */ - 4500, /* Stack size of task */ + 6500, /* Stack size of task */ NULL, /* parameter of the task */ 20, /* priority of the task */ &maintenanceLoopTask, /* Task handle to keep track of created task */ @@ -181,14 +194,14 @@ void SS2K::maintenanceLoop(void *pvParameters) { static bool isScanning = false; while (true) { - vTaskDelay(75 / portTICK_RATE_MS); + vTaskDelay(73 / portTICK_RATE_MS); ss2k.FTMSModeShiftModifier(); if (currentBoard.auxSerialTxPin) { ss2k.txSerial(); } - if ((millis() - intervalTimer) > 500) { // add check here for when to restart WiFi + if ((millis() - intervalTimer) > 2003) { // add check here for when to restart WiFi // maybe if in STA mode and 8.8.8.8 no ping return? // ss2k.restartWifi(); logHandler.writeLogs(); @@ -196,10 +209,10 @@ void SS2K::maintenanceLoop(void *pvParameters) { intervalTimer = millis(); } - if ((millis() - intervalTimer2) > 6000) { + if ((millis() - intervalTimer2) > 6007) { if (NimBLEDevice::getScan()->isScanning()) { // workaround to prevent occasional runaway scans if (isScanning == true) { - SS2K_LOG(MAIN_LOG_TAG, "Forcing Scan to stop."); + SS2K_LOGW(MAIN_LOG_TAG, "Forcing Scan to stop."); NimBLEDevice::getScan()->stop(); isScanning = false; } else { @@ -209,9 +222,8 @@ void SS2K::maintenanceLoop(void *pvParameters) { intervalTimer2 = millis(); } if (loopCounter > 10) { - ss2k.scanIfShiftersHeld(); ss2k.checkDriverTemperature(); - ss2k.checkBLEReconnect(); + // ss2k.checkBLEReconnect(); // SS2K_LOG(MAIN_LOG_TAG, "target %f current %f", rtConfig.getTargetIncline(), rtConfig.getCurrentIncline()); #ifdef DEBUG_STACK @@ -418,29 +430,6 @@ void SS2K::resetIfShiftersHeld() { } } -void SS2K::scanIfShiftersHeld() { - if ((digitalRead(currentBoard.shiftUpPin) == LOW) && (digitalRead(currentBoard.shiftDownPin) == LOW)) { // are both shifters held? - SS2K_LOG(MAIN_LOG_TAG, "Shifters Held %d", shiftersHoldForScan); - if (shiftersHoldForScan < 1) { // have they been held for enough loops? - SS2K_LOG(MAIN_LOG_TAG, "Shifters Held < 1 %d", shiftersHoldForScan); - if ((millis() - scanDelayStart) >= scanDelayTime) { // Has this already been done within 10 seconds? - scanDelayStart += scanDelayTime; - spinBLEClient.resetDevices(); - spinBLEClient.serverScan(true); - shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN; - digitalWrite(LED_PIN, LOW); - SS2K_LOG(MAIN_LOG_TAG, "Scan From Buttons"); - } else { - SS2K_LOG(MAIN_LOG_TAG, "Shifters Held but timer not up %d", (millis() - scanDelayStart) >= scanDelayTime); - shiftersHoldForScan = SHIFTERS_HOLD_FOR_SCAN; - return; - } - } else { - shiftersHoldForScan--; - } - } -} - void SS2K::setupTMCStepperDriver() { driver.begin(); driver.pdn_disable(true); @@ -538,10 +527,10 @@ void SS2K::txSerial() { // Serial.printf(" Before TX "); } } -void SS2K::pelotonConnected(){ -txCheck = TX_CHECK_INTERVAL; -rtConfig.setMinResistance(MIN_PELOTON_RESISTANCE); -rtConfig.setMaxResistance(MAX_PELOTON_RESISTANCE); +void SS2K::pelotonConnected() { + txCheck = TX_CHECK_INTERVAL; + rtConfig.setMinResistance(MIN_PELOTON_RESISTANCE); + rtConfig.setMaxResistance(MAX_PELOTON_RESISTANCE); } void SS2K::rxSerial(void) { @@ -560,36 +549,3 @@ void SS2K::rxSerial(void) { } } } - -void SS2K::checkBLEReconnect() { - static int bleCheck = 0; - if ((String(userConfig.getConnectedHeartMonitor()) == "none") && ((String(userConfig.getConnectedPowerMeter()) == "none"))) { // Exit immediately if "none" and "none" - bleCheck = 0; - return; - } - if ((spinBLEClient.connectedHR) && (spinBLEClient.connectedPM)) { // Exit if both are connected - bleCheck = 0; - return; - } - if (((String(userConfig.getConnectedPowerMeter()) == "none") && (spinBLEClient.connectedHR))) { // Exit if "none" PM and HR is connected - bleCheck = 0; - return; - } - if (((String(userConfig.getConnectedHeartMonitor()) == "none") && (spinBLEClient.connectedPM))) { // Exit if "none" HR and PM is connected - bleCheck = 0; - return; - } - if (bleCheck >= BLE_RECONNECT_INTERVAL) { - bleCheck = 0; - if (!NimBLEDevice::getScan()->isScanning()) { - SS2K_LOG(MAIN_LOG_TAG, "Scanning from Check BLE Reconnect %d", bleCheck); - spinBLEClient.resetDevices(); - spinBLEClient.scanProcess(BLE_RECONNECT_SCAN_DURATION); - } - } - if (NimBLEDevice::getScan()->isScanning()) { - bleCheck = 0; - } else { - bleCheck++; - } -} diff --git a/src/SensorCollector.cpp b/src/SensorCollector.cpp index f08f0abf..2e53b9e1 100644 --- a/src/SensorCollector.cpp +++ b/src/SensorCollector.cpp @@ -7,6 +7,7 @@ #include "Main.h" #include "SS2KLog.h" +#include "Constants.h" #include #include @@ -27,20 +28,28 @@ void collectAndSet(NimBLEUUID charUUID, NimBLEUUID serviceUUID, NimBLEAddress ad if (sensorData->hasHeartRate() && !rtConfig.hr.getSimulate()) { int heartRate = sensorData->getHeartRate(); rtConfig.hr.setValue(heartRate); - spinBLEClient.connectedHR |= true; + spinBLEClient.connectedHRM|= true; logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " HR(%d)", heartRate % 1000); } if (sensorData->hasCadence() && !rtConfig.cad.getSimulate()) { - float cadence = sensorData->getCadence(); - rtConfig.cad.setValue(cadence); - spinBLEClient.connectedCD |= true; - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " CD(%.2f)", fmodf(cadence, 1000.0)); + if ((charUUID == PELOTON_DATA_UUID) && !((String(userConfig.getConnectedPowerMeter()) == "none") || (String(userConfig.getConnectedPowerMeter()) == "any"))) { + // Peloton connected but using BLE Power Meter. So skip cad for Peloton UUID. + } else { + float cadence = sensorData->getCadence(); + rtConfig.cad.setValue(cadence); + spinBLEClient.connectedCD |= true; + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " CD(%.2f)", fmodf(cadence, 1000.0)); + } } if (sensorData->hasPower() && !rtConfig.watts.getSimulate()) { - int power = sensorData->getPower() * userConfig.getPowerCorrectionFactor(); - rtConfig.watts.setValue(power); - spinBLEClient.connectedPM |= true; - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " PW(%d)", power % 10000); + if ((charUUID == PELOTON_DATA_UUID) && !((String(userConfig.getConnectedPowerMeter()) == "none") || (String(userConfig.getConnectedPowerMeter()) == "any"))) { + // Peloton connected but using BLE Power Meter. So skip power for Peloton UUID. + } else { + int power = sensorData->getPower() * userConfig.getPowerCorrectionFactor(); + rtConfig.watts.setValue(power); + spinBLEClient.connectedPM |= true; + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " PW(%d)", power % 10000); + } } if (sensorData->hasSpeed()) { float speed = sensorData->getSpeed(); @@ -48,13 +57,21 @@ void collectAndSet(NimBLEUUID charUUID, NimBLEUUID serviceUUID, NimBLEAddress ad logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " SD(%.2f)", fmodf(speed, 1000.0)); } if (sensorData->hasResistance()) { - int resistance = sensorData->getResistance(); - rtConfig.resistance.setValue(resistance); - logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " RS(%d)", resistance % 1000); + if ((rtConfig.getMaxResistance() == MAX_PELOTON_RESISTANCE) && (charUUID != PELOTON_DATA_UUID)) { + // Peloton connected but using BLE Power Meter. So skip resistance for UUID's that aren't Peloton. + } else { + int resistance = sensorData->getResistance(); + rtConfig.resistance.setValue(resistance); + logBufLength += snprintf(logBuf + logBufLength, kLogBufMaxLength - logBufLength, " RS(%d)", resistance % 1000); + } } strncat(logBuf + logBufLength, " ]", kLogBufMaxLength - logBufLength); - SS2K_LOG(BLE_COMMON_LOG_TAG, "%s", logBuf); - #ifdef USE_TELEGRAM + if (userConfig.getLogComm()) { + SS2K_LOG(BLE_COMMON_LOG_TAG, "%s", logBuf); + } else { + SS2K_LOG(BLE_COMMON_LOG_TAG, "rx %s", sensorData->getId().c_str()); + } +#ifdef USE_TELEGRAM SEND_TO_TELEGRAM(String(logBuf)); - #endif +#endif } \ No newline at end of file diff --git a/src/SmartSpin_parameters.cpp b/src/SmartSpin_parameters.cpp index 5a4096ed..cc2d45f4 100644 --- a/src/SmartSpin_parameters.cpp +++ b/src/SmartSpin_parameters.cpp @@ -59,11 +59,13 @@ void userParameters::setDefaults() { password = DEFAULT_PASSWORD; connectedPowerMeter = CONNECTED_POWER_METER; connectedHeartMonitor = CONNECTED_HEART_MONITOR; + connectedRemote = CONNECTED_REMOTE; maxWatts = DEFAULT_MAX_WATTS; minWatts = DEFAULT_MIN_WATTS; stepperDir = true; shifterDir = true; udpLogEnabled = false; + logComm = false; } //--------------------------------------------------------------------------------- @@ -89,12 +91,14 @@ String userParameters::returnJSON() { doc["password"] = password; doc["connectedPowerMeter"] = connectedPowerMeter; doc["connectedHeartMonitor"] = connectedHeartMonitor; + doc["connectedRemote"] = connectedRemote; doc["foundDevices"] = foundDevices; doc["maxWatts"] = maxWatts; doc["minWatts"] = minWatts; doc["shifterDir"] = shifterDir; doc["stepperDir"] = stepperDir; doc["udpLogEnabled"] = udpLogEnabled; + doc["logComm"] = logComm; String output; serializeJson(doc, output); @@ -135,12 +139,14 @@ void userParameters::saveToLittleFS() { doc["password"] = password; doc["connectedPowerMeter"] = connectedPowerMeter; doc["connectedHeartMonitor"] = connectedHeartMonitor; + doc["connectedRemote"] = connectedRemote; doc["foundDevices"] = foundDevices; doc["maxWatts"] = maxWatts; doc["minWatts"] = minWatts; doc["shifterDir"] = shifterDir; doc["stepperDir"] = stepperDir; doc["udpLogEnabled"] = udpLogEnabled; + doc["logComm"] = logComm; // Serialize JSON to file if (serializeJson(doc, file) == 0) { @@ -205,12 +211,18 @@ void userParameters::loadFromLittleFS() { if (!doc["udpLogEnabled"].isNull()) { setUdpLogEnabled(doc["udpLogEnabled"]); } + if (!doc["logComm"].isNull()) { + setLogComm(doc["logComm"]); + } if (doc["powerCorrectionFactor"]) { setPowerCorrectionFactor(doc["powerCorrectionFactor"]); if ((getPowerCorrectionFactor() < MIN_PCF) || (getPowerCorrectionFactor() > MAX_PCF)) { setPowerCorrectionFactor(1); } } + if (doc["connectedRemote"]) { + setConnectedRemote(doc["connectedRemote"]); + } SS2K_LOG(CONFIG_LOG_TAG, "Config File Loaded: %s", configFILENAME); file.close();