diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91ed6220..30d50fc9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added blocking for shifts above or below min/max set points.
- Added power scaler for new board.
- Added Main Index link to develop.html.
+- Added feature to automatically reconnect BLE devices if both are specified.
### Changed
- PowerTable values are now adjusted to 90 RPM cad on input.
diff --git a/data/bluetoothscanner.html b/data/bluetoothscanner.html
index f80cfb6b..403f4c48 100644
--- a/data/bluetoothscanner.html
+++ b/data/bluetoothscanner.html
@@ -123,7 +123,7 @@
var t_obj = JSON.parse(data.foundDevices)
{
for (var key in t_obj) {
- if (t_obj[key].UUID == '0x1818' || t_obj[key].UUID == '0x1826') {
+ if (t_obj[key].UUID == '0x1818' || t_obj[key].UUID == '0x1826' || t_obj[key].UUID == '6e400001-b5a3-f393-e0a9-e50e24dcca9e' || t_obj[key].UUID == '0bf669f0-45f2-11e7-9598-0800200c9a66') {
optionPM = document.createElement('option');
if (t_obj[key].name) {
optionPM.text = t_obj[key].name;
@@ -152,18 +152,24 @@
}
}
- optionPM = document.createElement('option');
- optionPM.text = 'none';
- PMDropdown.add(optionPM);
- optionHR = document.createElement('option');
- optionHR.text = 'none';
- HRDropdown.add(optionHR);
- let defaultOptionPM = document.createElement('option');
- defaultOptionPM.text = 'any';
- let defaultOptionHR = document.createElement('option');
- defaultOptionHR.text = 'any';
- PMDropdown.add(defaultOptionPM);
- HRDropdown.add(defaultOptionHR);
+ let connectedOptionPM = document.createElement('option');
+ connectedOptionPM.text = data.connectedPowerMeter;
+ let connectedOptionHR = document.createElement('option');
+ connectedOptionHR.text = data.connectedHeartMonitor;
+ PMDropdown.add(connectedOptionPM);
+ HRDropdown.add(connectedOptionHR);
+ let anyOptionPM = document.createElement('option');
+ anyOptionPM.text = 'any';
+ let anyOptionHR = document.createElement('option');
+ anyOptionHR.text = 'any';
+ PMDropdown.add(anyOptionPM);
+ HRDropdown.add(anyOptionHR);
+ let noneOptionPM = document.createElement('option');
+ noneOptionPM.text = 'none';
+ let noneOptionHR = document.createElement('option');
+ noneOptionHR.text = 'none';
+ PMDropdown.add(noneOptionPM);
+ HRDropdown.add(noneOptionHR);
document.getElementById("connectedPowerMeter").innerHTML = data.connectedPowerMeter;
document.getElementById("connectedHeartMonitor").innerHTML = data.connectedHeartMonitor;
document.getElementById("powerCorrectionFactorValue").innerHTML = data.powerCorrectionFactor;
diff --git a/include/BLE_Common.h b/include/BLE_Common.h
index 175075ce..b48b590e 100644
--- a/include/BLE_Common.h
+++ b/include/BLE_Common.h
@@ -212,7 +212,7 @@ class SpinBLEClient {
void start();
void serverScan(bool connectRequest);
bool connectToServer();
- void scanProcess();
+ void scanProcess(int duration = DEFAULT_SCAN_DURATION);
void disconnect();
// Check for duplicate services of BLEClient and remove the previously
// connected one.
diff --git a/include/Main.h b/include/Main.h
index 4c171b50..3e9919db 100644
--- a/include/Main.h
+++ b/include/Main.h
@@ -51,6 +51,7 @@ class SS2K {
void checkDriverTemperature();
void motorStop(bool releaseTension = false);
void checkSerial();
+ void checkBLEReconnect();
SS2K() {
targetPosition = 0;
diff --git a/include/SmartSpin_parameters.h b/include/SmartSpin_parameters.h
index c5cb6924..941e265d 100644
--- a/include/SmartSpin_parameters.h
+++ b/include/SmartSpin_parameters.h
@@ -126,8 +126,8 @@ class userParameters {
bool getAutoUpdate() { return autoUpdate; }
const char* getSsid() { return ssid.c_str(); }
const char* getPassword() { return password.c_str(); }
- const char* getconnectedPowerMeter() { return connectedPowerMeter.c_str(); }
- const char* getconnectedHeartMonitor() { return connectedHeartMonitor.c_str(); }
+ const char* getConnectedPowerMeter() { return connectedPowerMeter.c_str(); }
+ const char* getConnectedHeartMonitor() { return connectedHeartMonitor.c_str(); }
int getStepperPower() { return stepperPower; }
int getMaxWatts() { return maxWatts; }
int getMinWatts() { return minWatts; }
diff --git a/include/settings.h b/include/settings.h
index 9353e080..a096fa18 100644
--- a/include/settings.h
+++ b/include/settings.h
@@ -245,6 +245,15 @@
// If not receiving Peleton Messages, how long to wait before next TX attempt is
#define TX_CHECK_INTERVAL 20
+// If ble devices are both setup, how often to attempt a reconnect.
+#define BLE_RECONNECT_INTERVAL 40
+
+// Initial and web scan duration.
+#define DEFAULT_SCAN_DURATION 10
+
+// BLE automatic reconnect duration. Set this low to avoid interruption.
+#define BLE_RECONNECT_SCAN_DURATION 3
+
// Uncomment to enable sending Telegram debug messages back to the chat
// specified in telegram_token.h
// #define USE_TELEGRAM
@@ -253,8 +262,11 @@
//#define DEBUG_STACK
// Uncomment to enable HR->PWR debugging info. Always displays HR->PWR
-// Calculation. Never sets userConfig.setSimulatedPower(); #define
-// DEBUG_HR_TO_PWR
+// Calculation. Never sets userConfig.setSimulatedPower();
+// #define DEBUG_HR_TO_PWR
+
+// Uncomment to enable HR->PWR enhanced powertable debugging.
+// #define DEBUG_POWERTABLE
#ifdef USE_TELEGRAM
// Max number of telegram messages to send per session
diff --git a/src/BLE_Client.cpp b/src/BLE_Client.cpp
index 7a98829b..f8b543af 100644
--- a/src/BLE_Client.cpp
+++ b/src/BLE_Client.cpp
@@ -48,7 +48,7 @@ static void onNotify(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t
// BLE Client loop task
void bleClientTask(void *pvParameters) {
for (;;) {
- if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0)) {
+ if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0) && !NimBLEDevice::getScan()->isScanning()) {
spinBLEClient.scanRetries--;
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Initiating Scan from Client Task:");
spinBLEClient.scanProcess();
@@ -347,24 +347,24 @@ void MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *advertisedDevice)
// not specified.
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Matching Device Name: %s", aDevName.c_str());
if (advertisedDevice->getServiceUUID() == HEARTSERVICE_UUID) {
- if (String(userConfig.getconnectedHeartMonitor()) == "any") {
+ if (String(userConfig.getConnectedHeartMonitor()) == "any") {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "HR String Matched Any");
// continue
- } else if (aDevName != String(userConfig.getconnectedHeartMonitor()) || (String(userConfig.getconnectedHeartMonitor()) == "none")) {
- SS2K_LOG(BLE_CLIENT_LOG_TAG, "Skipping non-selected HRM |%s|%s", aDevName.c_str(), userConfig.getconnectedHeartMonitor());
+ } else if (aDevName != String(userConfig.getConnectedHeartMonitor()) || (String(userConfig.getConnectedHeartMonitor()) == "none")) {
+ SS2K_LOG(BLE_CLIENT_LOG_TAG, "Skipping non-selected HRM |%s|%s", aDevName.c_str(), userConfig.getConnectedHeartMonitor());
return;
- } else if (aDevName == String(userConfig.getconnectedHeartMonitor())) {
+ } 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)))
- if (String(userConfig.getconnectedPowerMeter()) == "any") {
+ if (String(userConfig.getConnectedPowerMeter()) == "any") {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "PM String Matched Any");
// continue
- } else if (aDevName != String(userConfig.getconnectedPowerMeter()) || (String(userConfig.getconnectedPowerMeter()) == "none")) {
- SS2K_LOG(BLE_CLIENT_LOG_TAG, "Skipping non-selected PM |%s|%s", aDevName.c_str(), userConfig.getconnectedPowerMeter());
+ } else if (aDevName != String(userConfig.getConnectedPowerMeter()) || (String(userConfig.getConnectedPowerMeter()) == "none")) {
+ SS2K_LOG(BLE_CLIENT_LOG_TAG, "Skipping non-selected PM |%s|%s", aDevName.c_str(), userConfig.getConnectedPowerMeter());
return;
- } else if (aDevName == String(userConfig.getconnectedPowerMeter())) {
+ } else if (aDevName == String(userConfig.getConnectedPowerMeter())) {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "PM String Matched %s", aDevName.c_str());
}
}
@@ -384,7 +384,7 @@ void MyAdvertisedDeviceCallback::onResult(BLEAdvertisedDevice *advertisedDevice)
}
}
-void SpinBLEClient::scanProcess() {
+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...");
@@ -394,7 +394,7 @@ void SpinBLEClient::scanProcess() {
pBLEScan->setWindow(67);
pBLEScan->setDuplicateFilter(true);
pBLEScan->setActiveScan(true);
- BLEScanResults foundDevices = pBLEScan->start(10, true);
+ BLEScanResults foundDevices = pBLEScan->start(duration, true);
// Load the scan into a Json String
int count = foundDevices.getCount();
@@ -507,13 +507,13 @@ void SpinBLEClient::postConnect(NimBLEClient *pClient) {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Activated Echelon callbacks.");
}
// spinBLEClient.removeDuplicates(pclient);
- BLEDevice::getServer()->updateConnParams(pClient->getConnId(), 400, 400, 0, 250);
+ BLEDevice::getServer()->updateConnParams(pClient->getConnId(), 400, 400, 2, 1000);
return;
}
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, 0, 250);
+ BLEDevice::getServer()->updateConnParams(pClient->getConnId(), 400, 400, 2, 1000);
return;
} else {
SS2K_LOG(BLE_CLIENT_LOG_TAG, "These did not match|%s|%s|", pClient->getPeerAddress().toString().c_str(), this->myBLEDevices[i].peerAddress.toString().c_str());
diff --git a/src/BLE_Common.cpp b/src/BLE_Common.cpp
index f440436b..f511fe29 100644
--- a/src/BLE_Common.cpp
+++ b/src/BLE_Common.cpp
@@ -123,7 +123,7 @@ void BLECommunications(void *pvParameters) {
} else {
digitalWrite(LED_PIN, HIGH);
}
- if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0)) {
+ if (spinBLEClient.doScan && (spinBLEClient.scanRetries > 0) && !NimBLEDevice::getScan()->isScanning()) {
spinBLEClient.scanRetries--;
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Initiating Scan from Client Task:");
spinBLEClient.scanProcess();
diff --git a/src/BLE_Setup.cpp b/src/BLE_Setup.cpp
index 178afb2e..a2c645ff 100644
--- a/src/BLE_Setup.cpp
+++ b/src/BLE_Setup.cpp
@@ -28,10 +28,10 @@ void setupBLE() { // Common BLE setup for both client and server
SS2K_LOG(BLE_SETUP_LOG_TAG, "BLE Notify Task Started");
vTaskDelay(100 / portTICK_PERIOD_MS);
- if (strcmp(userConfig.getconnectedPowerMeter(), "none") != 0 || strcmp(userConfig.getconnectedHeartMonitor(), "none") != 0) {
+ 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", userConfig.getConnectedPowerMeter(), userConfig.getConnectedHeartMonitor());
SS2K_LOG(BLE_SETUP_LOG_TAG, "End BLE Setup");
}
diff --git a/src/ERG_Mode.cpp b/src/ERG_Mode.cpp
index f779fb2c..7ae7273b 100644
--- a/src/ERG_Mode.cpp
+++ b/src/ERG_Mode.cpp
@@ -163,13 +163,17 @@ void PowerTable::newEntry(PowerBuffer& powerBuffer) {
cad = powerBuffer.powerEntry[i].cad;
continue;
}
+#ifdef DEBUG_POWERTABLE
SS2K_LOGW(POWERTABLE_LOG_TAG, "Buf[%d](%dw)(%dpos)(%dcad)", i, powerBuffer.powerEntry[i].watts, powerBuffer.powerEntry[i].targetPosition, powerBuffer.powerEntry[i].cad);
+#endif
// calculate average
watts = (watts + powerBuffer.powerEntry[i].watts) / 2;
targetPosition = (targetPosition + powerBuffer.powerEntry[i].targetPosition) / 2;
cad = (cad + powerBuffer.powerEntry[i].cad) / 2;
}
+#ifdef DEBUG_POWERTABLE
SS2K_LOG(POWERTABLE_LOG_TAG, "Avg:(%dw)(%dpos)(%dcad)", (int)watts, targetPosition, cad);
+#endif
// Done with powerBuffer
// To start working on the PowerTable, we need to calculate position in the table for the new entry
int i = round(watts / POWERTABLE_INCREMENT);
diff --git a/src/HTTP_Server_Basic.cpp b/src/HTTP_Server_Basic.cpp
index 8718b107..81108aae 100644
--- a/src/HTTP_Server_Basic.cpp
+++ b/src/HTTP_Server_Basic.cpp
@@ -436,6 +436,7 @@ void HTTP_Server::settingsProcessor() {
String tString;
bool wasBTUpdate = false;
bool wasSettingsUpdate = false;
+ bool reboot = false;
if (!server.arg("ssid").isEmpty()) {
tString = server.arg("ssid");
tString.trim();
@@ -528,7 +529,9 @@ void HTTP_Server::settingsProcessor() {
wasBTUpdate = true;
if (server.arg("blePMDropdown")) {
tString = server.arg("blePMDropdown");
- userConfig.setConnectedPowerMeter(server.arg("blePMDropdown"));
+ if (tString != userConfig.getConnectedPowerMeter()) {
+ reboot = true;
+ }
} else {
userConfig.setConnectedPowerMeter("any");
}
@@ -536,13 +539,16 @@ void HTTP_Server::settingsProcessor() {
if (!server.arg("bleHRDropdown").isEmpty()) {
wasBTUpdate = true;
if (server.arg("bleHRDropdown")) {
- tString = server.arg("bleHRDropdown");
+ bool reset = false;
+ tString = server.arg("bleHRDropdown");
+ if (tString != userConfig.getConnectedHeartMonitor()) {
+ reboot = true;
+ }
userConfig.setConnectedHeartMonitor(server.arg("bleHRDropdown"));
} else {
userConfig.setConnectedHeartMonitor("any");
}
}
-
if (!server.arg("session1HR").isEmpty()) { // Needs checking for unrealistic numbers.
userPWC.session1HR = server.arg("session1HR").toInt();
}
@@ -579,7 +585,7 @@ void HTTP_Server::settingsProcessor() {
} else { // Normal response
response +=
"Network settings will be applied at next reboot.
Everything "
- "else is availiable immediately.