diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a51b8f6..6a0a986b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Removed >0 watts requirement to compute ERG.
+- Removed sizes for JSON strings since they're dynamic now.
+- Added variable inactivity timeout.
- Filter cadence for crazy values. Only >0 && <250 now accepted.
- Filter watts for crazy values. Only >0 && <3000 now accepted.
- Fixed bug where scans may not happen even when configured devices aren't connected.
diff --git a/data/settings.html b/data/settings.html
index 836446cd..bd0bcac6 100644
--- a/data/settings.html
+++ b/data/settings.html
@@ -179,6 +179,15 @@
Reset to Defaults?
tooltip: 'Use cadence to calculate power output',
tooltipText: 'Use the PowerTable for Power instead of PM',
defaultValue: false
+ },
+ inactivityTimeout: {
+ type: 'slider',
+ title: 'Inactivity Reboot Timeout',
+ tooltip: 'Idle time before auto-reboot',
+ tooltipText: 'Automatically reboot if device is inactive (no power, HR, or cadence changes) for this duration. Minimum 1 minute, maximum 48 hours.',
+ min: 1, max: 2880, step: 15,
+ defaultValue: 30,
+ unit: 'min'
}
};
diff --git a/include/BLE_Custom_Characteristic.h b/include/BLE_Custom_Characteristic.h
index 441fe4ad..983f4901 100644
--- a/include/BLE_Custom_Characteristic.h
+++ b/include/BLE_Custom_Characteristic.h
@@ -63,6 +63,7 @@ const uint8_t BLE_hMax = 0x2B; // Maximum homing value
const uint8_t BLE_homingSensitivity = 0x2C; // Homing sensitivity value
const uint8_t BLE_pTab4Pwr = 0x2D; // Use power values for power table
const uint8_t BLE_UDPLogging = 0x2E; // Enable or disable UDP logging
+const uint8_t BLE_inactivityTimeout = 0x2F; // Inactivity reboot timeout in minutes
class BLE_ss2kCustomCharacteristic {
public:
diff --git a/include/SmartSpin_parameters.h b/include/SmartSpin_parameters.h
index 1fd58f1e..31ff7333 100644
--- a/include/SmartSpin_parameters.h
+++ b/include/SmartSpin_parameters.h
@@ -139,6 +139,7 @@ class userParameters {
int32_t hMax = INT32_MIN;
bool FTMSControlPointWrite = false;
int homingSensitivity = DEFAULT_HOMING_SENSITIVITY; // Use default from settings.h
+ int inactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT;
String ssid;
String password;
String connectedPowerMeter = CONNECTED_POWER_METER;
@@ -225,6 +226,18 @@ class userParameters {
void setHomingSensitivity(int sensitivity) { homingSensitivity = sensitivity; }
int getHomingSensitivity() { return homingSensitivity; }
+ void setInactivityTimeout(unsigned long timeout) {
+ // Clamp value between min and max
+ if (timeout < MIN_INACTIVITY_TIMEOUT) {
+ inactivityTimeout = MIN_INACTIVITY_TIMEOUT;
+ } else if (timeout > MAX_INACTIVITY_TIMEOUT) {
+ inactivityTimeout = MAX_INACTIVITY_TIMEOUT;
+ } else {
+ inactivityTimeout = timeout;
+ }
+ }
+ unsigned long getInactivityTimeout() { return inactivityTimeout; }
+
void setDefaults();
String returnJSON();
void saveToLittleFS();
diff --git a/include/settings.h b/include/settings.h
index afc2d535..2c619a44 100644
--- a/include/settings.h
+++ b/include/settings.h
@@ -103,6 +103,12 @@ const char* const DEFAULT_PASSWORD = "password";
// This is used to set the upper travel limit for the motor.
#define DEFAULT_MAX_WATTS 1000
+// Inactivity timeout for automatic reboot
+// Time in minutes before reboot when no activity is detected
+#define DEFAULT_INACTIVITY_TIMEOUT 30
+#define MIN_INACTIVITY_TIMEOUT 1
+#define MAX_INACTIVITY_TIMEOUT 2880 // 48 hours
+
// Minimum resistance on a Peloton Bike.
// This is used to set the lower travel limit for the motor.
#define MIN_PELOTON_RESISTANCE 5
@@ -264,15 +270,6 @@ constexpr const char* ANY = "any";
// The client will be disconnected.
#define BLE_CLIENT_DISCONNECT_TIMEOUT 5000
-#ifndef DEBUG_LOG_BUFFER_SIZE
-#define DEBUG_LOG_BUFFER_SIZE 600
-#endif
-
-// Max size of userconfig
-#define USERCONFIG_JSON_SIZE 2000 + DEBUG_LOG_BUFFER_SIZE
-
-#define RUNTIMECONFIG_JSON_SIZE 1000 + DEBUG_LOG_BUFFER_SIZE
-
// Uncomment to use guardrails for ERG mode in the stepper loop.
// #define ERG_GUARDRAILS
diff --git a/src/BLE_Custom_Characteristic.cpp b/src/BLE_Custom_Characteristic.cpp
index ecef6582..cd09e8dc 100644
--- a/src/BLE_Custom_Characteristic.cpp
+++ b/src/BLE_Custom_Characteristic.cpp
@@ -88,7 +88,7 @@ This characteristic allows for reading and writing various user configuration pa
#include
#include
-void BLE_ss2kCustomCharacteristic::setupService(NimBLEServer *pServer) {
+void BLE_ss2kCustomCharacteristic::setupService(NimBLEServer* pServer) {
pSmartSpin2kService = spinBLEServer.pServer->createService(SMARTSPIN2K_SERVICE_UUID);
smartSpin2kCharacteristic =
pSmartSpin2kService->createCharacteristic(SMARTSPIN2K_CHARACTERISTIC_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::INDICATE | NIMBLE_PROPERTY::NOTIFY);
@@ -99,17 +99,17 @@ void BLE_ss2kCustomCharacteristic::setupService(NimBLEServer *pServer) {
void BLE_ss2kCustomCharacteristic::update() {}
-void ss2kCustomCharacteristicCallbacks::onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) {
+void ss2kCustomCharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) {
std::string rxValue = pCharacteristic->getValue();
// SS2K_LOG(CUSTOM_CHAR_LOG_TAG, "Write from %s", connInfo.getAddress().toString().c_str());
BLE_ss2kCustomCharacteristic::process(rxValue);
}
-void ss2kCustomCharacteristicCallbacks::onSubscribe(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo, uint16_t subValue) {
+void ss2kCustomCharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue) {
SS2K_LOG(CUSTOM_CHAR_LOG_TAG, "Subscribe from %s", connInfo.getAddress().toString().c_str());
NimBLEDevice::setMTU(515);
}
-void ss2kCustomCharacteristicCallbacks::onStatus(NimBLECharacteristic *pCharacteristic, int code) {
+void ss2kCustomCharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, int code) {
// loop through and accumulate the data into a C++ string
#ifdef CUSTOM_CHAR_DEBUG
std::string characteristicValue = pCharacteristic->getValue();
@@ -137,8 +137,8 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
if (NimBLEDevice::getServer()->getServiceByUUID(SMARTSPIN2K_SERVICE_UUID) == nullptr) {
return;
}
- NimBLECharacteristic *pCharacteristic = NimBLEDevice::getServer()->getServiceByUUID(SMARTSPIN2K_SERVICE_UUID)->getCharacteristic(SMARTSPIN2K_CHARACTERISTIC_UUID);
- uint8_t *pData = reinterpret_cast(&rxValue[0]);
+ NimBLECharacteristic* pCharacteristic = NimBLEDevice::getServer()->getServiceByUUID(SMARTSPIN2K_SERVICE_UUID)->getCharacteristic(SMARTSPIN2K_CHARACTERISTIC_UUID);
+ uint8_t* pData = reinterpret_cast(&rxValue[0]);
#ifdef CUSTOM_CHAR_DEBUG
#define LOG_BUF_APPEND(...) logBufLength += snprintf(logBuf + logBufLength, kLogBufCapacity - logBufLength, __VA_ARGS__)
@@ -166,7 +166,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getFirmwareUpdateURL();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setFirmwareUpdateURL(str);
LOG_BUF_APPEND("(%s)", userConfig->getFirmwareUpdateURL());
@@ -257,7 +257,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getDeviceName();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setDeviceName(str);
LOG_BUF_APPEND("(%s)", userConfig->getDeviceName());
@@ -420,7 +420,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getSsid();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setSsid(str);
LOG_BUF_APPEND("(%s)", userConfig->getSsid());
@@ -434,7 +434,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getPassword();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setPassword(str);
LOG_BUF_APPEND("(%s)", "******");
@@ -448,7 +448,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getFoundDevices();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setFoundDevices(str);
LOG_BUF_APPEND("(%s)", userConfig->getFoundDevices());
@@ -462,7 +462,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getConnectedPowerMeter();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setConnectedPowerMeter(str);
LOG_BUF_APPEND("(%s)", userConfig->getConnectedPowerMeter());
@@ -476,7 +476,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
returnString = userConfig->getConnectedHeartMonitor();
} else if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- String str = (char *)pData;
+ String str = (char*)pData;
str.remove(0, 2);
userConfig->setConnectedHeartMonitor(str);
LOG_BUF_APPEND("(%s)", userConfig->getConnectedHeartMonitor());
@@ -758,7 +758,7 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
}
if (rxValue[0] == cc_write) {
returnValue[0] = cc_success;
- int32_t hMin = int32_t((uint8_t)(rxValue[2]) << 0 | (uint8_t)(rxValue[3]) << 8 | (uint8_t)(rxValue[4]) << 16 | (uint8_t)(rxValue[5]) << 24);
+ int32_t hMin = int32_t((uint8_t)(rxValue[2]) << 0 | (uint8_t)(rxValue[3]) << 8 | (uint8_t)(rxValue[4]) << 16 | (uint8_t)(rxValue[5]) << 24);
userConfig->setHMin(hMin);
rtConfig->setMinStep(hMin);
LOG_BUF_APPEND(" (%d)", hMin);
@@ -828,6 +828,25 @@ void BLE_ss2kCustomCharacteristic::process(std::string rxValue) {
}
break;
+ case BLE_inactivityTimeout: { // 0x2F
+ LOG_BUF_APPEND("<-inactivityTimeout");
+ int timeout = userConfig->getInactivityTimeout();
+ if (rxValue[0] == cc_read) {
+ returnValue[0] = cc_success;
+ returnValue[2] = (uint8_t)(timeout & 0xff);
+ returnValue[3] = (uint8_t)((timeout >> 8) & 0xff);
+ returnValue[4] = (uint8_t)((timeout >> 16) & 0xff);
+ returnValue[5] = (uint8_t)((timeout >> 24) & 0xff);
+ returnLength += 4;
+ }
+ if (rxValue[0] == cc_write) {
+ returnValue[0] = cc_success;
+ int newTimeout = rxValue[2] | (rxValue[3] << 8) | (rxValue[4] << 16) | (rxValue[5] << 24);
+ userConfig->setInactivityTimeout(newTimeout);
+ LOG_BUF_APPEND("(%d min)", userConfig->getInactivityTimeout());
+ }
+ } break;
+
default:
LOG_BUF_APPEND("<-Unknown Characteristic");
returnValue[0] = cc_error;
@@ -1015,4 +1034,9 @@ void BLE_ss2kCustomCharacteristic::parseNemit() {
BLE_ss2kCustomCharacteristic::notify(BLE_UDPLogging);
return;
}
+ if (userConfig->getInactivityTimeout() != _oldParams.getInactivityTimeout()) {
+ _oldParams.setInactivityTimeout(userConfig->getInactivityTimeout());
+ BLE_ss2kCustomCharacteristic::notify(BLE_inactivityTimeout);
+ return;
+ }
}
diff --git a/src/HTTP_Server_Basic.cpp b/src/HTTP_Server_Basic.cpp
index dbb14cc2..0bf76056 100644
--- a/src/HTTP_Server_Basic.cpp
+++ b/src/HTTP_Server_Basic.cpp
@@ -657,6 +657,12 @@ void HTTP_Server::settingsProcessor() {
userConfig->setPowerCorrectionFactor(powerCorrectionFactor);
}
}
+ if (!server.arg("inactivityTimeout").isEmpty()) {
+ uint64_t inactivityTimeout = server.arg("inactivityTimeout").toInt();
+ if (inactivityTimeout >= MIN_INACTIVITY_TIMEOUT && inactivityTimeout <= MAX_INACTIVITY_TIMEOUT) {
+ userConfig->setInactivityTimeout(inactivityTimeout);
+ }
+ }
if (!server.arg("blePMDropdown").isEmpty()) {
wasBTUpdate = true;
if (server.arg("blePMDropdown")) {
diff --git a/src/Main.cpp b/src/Main.cpp
index 5dd92226..ca82dde1 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -296,9 +296,9 @@ void SS2K::maintenanceLoop(void* pvParameters) {
static float _oldTargetIncline = 0.0f;
if (_oldHR == rtConfig->hr.getValue() && _oldWatts == rtConfig->watts.getValue() && _oldTargetIncline == rtConfig->getTargetIncline()) {
// Inactivity detected
- if (((millis() - rebootTimer) > 1800000)) {
+ if (((millis() - rebootTimer) > userConfig->getInactivityTimeout() * 60000)) {
// Timer expired
- SS2K_LOG(MAIN_LOG_TAG, "Rebooting due to inactivity.");
+ SS2K_LOG(MAIN_LOG_TAG, "Rebooting due to inactivity. Timeout: %d min", userConfig->getInactivityTimeout());
ss2k->rebootFlag = true;
logHandler.writeLogs();
webSocketAppender.Loop();
diff --git a/src/SmartSpin_parameters.cpp b/src/SmartSpin_parameters.cpp
index 25fe1c68..e3b63b26 100644
--- a/src/SmartSpin_parameters.cpp
+++ b/src/SmartSpin_parameters.cpp
@@ -71,6 +71,7 @@ void userParameters::setDefaults() {
hMin = INT32_MIN;
hMax = INT32_MIN;
homingSensitivity = DEFAULT_HOMING_SENSITIVITY;
+ inactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT;
}
//---------------------------------------------------------------------------------
@@ -108,6 +109,7 @@ String userParameters::returnJSON() {
doc["hMin"] = hMin;
doc["hMax"] = hMax;
doc["homingSensitivity"] = homingSensitivity;
+ doc["inactivityTimeout"] = inactivityTimeout;
String output;
serializeJson(doc, output);
@@ -160,6 +162,7 @@ void userParameters::saveToLittleFS() {
doc["hMin"] = hMin;
doc["hMax"] = hMax;
doc["homingSensitivity"] = homingSensitivity;
+ doc["inactivityTimeout"] = inactivityTimeout;
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
@@ -250,6 +253,9 @@ JsonDocument doc;
if (!doc["homingSensitivity"].isNull()) {
setHomingSensitivity(doc["homingSensitivity"]);
}
+ if (!doc["inactivityTimeout"].isNull()) {
+ setInactivityTimeout(doc["inactivityTimeout"]);
+ }
SS2K_LOG(CONFIG_LOG_TAG, "Config File Loaded: %s", configFILENAME);
file.close();