Skip to content

Commit 5440eda

Browse files
authored
Merge pull request #652 from doudar/UpdatesFix
Fixed BLE and WiFI (App) updates
2 parents 8e69346 + fbee391 commit 5440eda

9 files changed

Lines changed: 100 additions & 56 deletions

.actrc

Whitespace-only changes.

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
### Changed
13+
14+
### Hardware
15+
16+
17+
## [25.7.29]
18+
19+
### Added
20+
1221
### Changed
1322
- Removed unused file.
1423
- Added license to test files.
1524
- Fixed unterminated comment.
25+
- Fixed BLE and WiFI updates.
1626

1727
### Hardware
1828

include/BLE_Common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void logCharacteristic(char* buffer, const size_t bufferCapacity, const byte* da
118118
void calculateInstPwrFromHR();
119119

120120
// BLE FIRMWARE UPDATER
121-
void BLEFirmwareSetup();
121+
void BLEFirmwareSetup(NimBLEServer* pServer);
122122

123123
// *****************************Client*****************************
124124

platformio.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ lib_deps =
7171
https://github.com/bblanchon/ArduinoJson/archive/refs/tags/v7.3.1.zip
7272
;https://github.com/gin66/FastAccelStepper/archive/refs/tags/0.31.2.zip
7373
https://github.com/doudar/FastAccelStepper/
74-
https://github.com/gilmaimon/ArduinoWebsockets/archive/refs/tags/0.5.4.zip
74+
;https://github.com/gilmaimon/ArduinoWebsockets/archive/refs/tags/0.5.4.zip
75+
https://github.com/doudar/ArduinoWebsockets/
7576
;https://github.com/Links2004/arduinoWebSockets
7677
;https://github.com/doudar/NimBLE-Arduino/
7778

sdkconfig.release.old

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ CONFIG_ARDUINO_SELECTIVE_HTTPClient=y
521521
CONFIG_ARDUINO_SELECTIVE_WebServer=y
522522
CONFIG_ARDUINO_SELECTIVE_WiFi=y
523523
CONFIG_ARDUINO_SELECTIVE_NetworkClientSecure=y
524-
CONFIG_ARDUINO_SELECTIVE_WiFiProv=y
524+
# default:
525+
# CONFIG_ARDUINO_SELECTIVE_WiFiProv is not set
525526
CONFIG_ARDUINO_SELECTIVE_BLE=y
526527
# default:
527528
# CONFIG_ARDUINO_SELECTIVE_BluetoothSerial is not set
@@ -539,8 +540,8 @@ CONFIG_ARDUINO_SELECTIVE_BLE=y
539540
# Compiler options
540541
#
541542
# CONFIG_COMPILER_OPTIMIZATION_DEBUG is not set
542-
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
543-
# CONFIG_COMPILER_OPTIMIZATION_PERF is not set
543+
# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set
544+
CONFIG_COMPILER_OPTIMIZATION_PERF=y
544545
# CONFIG_COMPILER_OPTIMIZATION_NONE is not set
545546
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
546547
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set

src/BLE_Client.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ void bleClientTask(void *pvParameters) {
146146

147147
// disconnect all connected servers if we're updating via BLE
148148
if (ss2k->isUpdating) {
149+
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Disconnecting all connected servers due to update.");
149150
for (auto &_BLEd : spinBLEClient.myBLEDevices) { // loop through discovered devices
150151
if (_BLEd.connectedClientID != BLE_HS_CONN_HANDLE_NONE) {
151152
if (_BLEd.advertisedDevice) { // is device registered?
@@ -160,15 +161,19 @@ void bleClientTask(void *pvParameters) {
160161
}
161162
while (ss2k->isUpdating) { // wait until the update is done
162163
delay(100);
164+
if(NimBLEDevice::getScan()->isScanning()) { // if we're scanning, stop it
165+
NimBLEDevice::getScan()->stop(); // stop scanning if we're updating
166+
}
163167
}
168+
SS2K_LOG(BLE_CLIENT_LOG_TAG, "Update complete, re-enabling BLE scanning.");
164169
}
165170

166171
// Post connect previously connected clients. This needs to be before connect, as it takes a while to complete the connection (let it loop once.)
167172
spinBLEClient.postConnect();
168173

169174
// Connect BLE Servers to this client
170175
for (int x = 0; x < NUM_BLE_DEVICES; x++) {
171-
if (spinBLEClient.myBLEDevices[x].doConnect == true && !ss2k->isUpdating) {
176+
if (spinBLEClient.myBLEDevices[x].doConnect == true) {
172177
// stop in process scans
173178
NimBLEScan *pBLEScan = NimBLEDevice::getScan();
174179
if (pBLEScan->isScanning()) {
@@ -186,9 +191,9 @@ void bleClientTask(void *pvParameters) {
186191

187192
// Scan for BLE devices that we should connect to this client
188193
static unsigned long scanDelay = millis();
189-
if ((millis() - scanDelay) > BLE_RECONNECT_SCAN_INTERVAL) {
194+
if (((millis() - scanDelay) > BLE_RECONNECT_SCAN_INTERVAL)) {
190195
spinBLEClient.checkBLEReconnect();
191-
if (spinBLEClient.doScan && (!ss2k->isUpdating)) {
196+
if (spinBLEClient.doScan) {
192197
spinBLEClient.scanProcess(DEFAULT_SCAN_DURATION);
193198
}
194199
scanDelay = millis();

src/BLE_Firmware_Update.cpp

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <NimBLEDevice.h>
1616
#include <BLE_Custom_Characteristic.h>
1717

18+
#define BLE_OTA_LOG_TAG "BLE_OTA"
19+
1820
/*------------------------------------------------------------------------------
1921
BLE instances & variables
2022
----------------------------------------------------------------------------*/
@@ -40,7 +42,7 @@ bool downloadFlag = false;
4042
----------------------------------------------------------------------------*/
4143

4244
class otaCallback : public BLECharacteristicCallbacks {
43-
void onWrite(BLECharacteristic *pCharacteristic, ble_gap_conn_desc *connDesc) {
45+
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override {
4446
std::string rxData = pCharacteristic->getValue();
4547
bufferCount++;
4648

@@ -52,33 +54,36 @@ class otaCallback : public BLECharacteristicCallbacks {
5254
// update the connection interval so that it provides enough time for the long writes
5355

5456
Serial.printf("1. BeginOTA");
55-
BLEDevice::getServer()->updateConnParams(connDesc->conn_handle, 12, 12, 0, 1000);
57+
BLEDevice::getServer()->updateConnParams(connInfo.getConnHandle(), 12, 12, 0, 1000);
5658
const esp_partition_t *configured = esp_ota_get_boot_partition();
5759
const esp_partition_t *running = esp_ota_get_running_partition();
5860

5961
if (configured != running) {
60-
Serial.printf("ERROR: Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", configured->address, running->address);
61-
Serial.printf("(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
62+
SS2K_LOG(BLE_OTA_LOG_TAG, "ERROR: Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", configured->address, running->address);
63+
SS2K_LOG(BLE_OTA_LOG_TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
6264
downloadFlag = false;
6365
esp_ota_end(otaHandler);
6466
} else {
65-
Serial.printf("2. Running partition type %d subtype %d (offset 0x%08x) \n", running->type, running->subtype, running->address);
67+
SS2K_LOG(BLE_OTA_LOG_TAG, "2. Running partition type %d subtype %d (offset 0x%08x) \n", running->type, running->subtype, running->address);
6668
}
6769

6870
update_partition = esp_ota_get_next_update_partition(NULL);
69-
assert(update_partition != NULL);
71+
if (update_partition == NULL) {
72+
SS2K_LOG(BLE_OTA_LOG_TAG, "ERROR: No valid partition found");
73+
downloadFlag = false;
74+
ss2k->rebootFlag = true;
75+
return;
76+
}
7077

71-
Serial.printf("3. Writing to partition subtype %d at offset 0x%x \n", update_partition->subtype, update_partition->address);
78+
SS2K_LOG(BLE_OTA_LOG_TAG, "3. Writing to partition subtype %d at offset 0x%x \n", update_partition->subtype, update_partition->address);
7279

7380
//------------------------------------------------------------------------------------------
7481
// esp_ota_begin can take a while to complete as it erase the flash partition (3-5 seconds)
7582
// so make sure there's no timeout on the client side (iOS) that triggers before that.
7683
//------------------------------------------------------------------------------------------
77-
esp_task_wdt_config_t wdt_config = {
78-
.timeout_ms = 10000, // 10 seconds
79-
.idle_core_mask = 0,
80-
.trigger_panic = false
81-
};
84+
esp_task_wdt_config_t wdt_config = {.timeout_ms = 20000, // 20 seconds
85+
.idle_core_mask = 0,
86+
.trigger_panic = false};
8287
esp_task_wdt_init(&wdt_config);
8388

8489
// if (BLECommunicationTask != NULL) {
@@ -97,26 +102,27 @@ class otaCallback : public BLECharacteristicCallbacks {
97102
// vTaskDelay(5);
98103

99104
if (esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &otaHandler) != ESP_OK) {
100-
downloadFlag = false;
101-
ss2k->isUpdating = false;
105+
downloadFlag = false;
106+
ss2k->isUpdating = false;
107+
SS2K_LOG(BLE_OTA_LOG_TAG, "OTA begin failed");
102108
return;
103109
}
104110
downloadFlag = true;
105111
}
106112

107113
if (bufferCount >= 1 || rxData.length() > 0) {
108114
if (esp_ota_write(otaHandler, (uint8_t *)rxData.c_str(), rxData.length()) != ESP_OK) {
109-
Serial.printf("Error: write to flash failed");
115+
SS2K_LOG(BLE_OTA_LOG_TAG, "Error: write to flash failed");
110116
downloadFlag = false;
111117
pTxCharacteristic->notify(0x04, 1);
118+
ss2k->rebootFlag = true;
112119
return;
113120
} else {
114121
bufferCount = 1;
115122
// Serial.printf("%d bytes", rxData.length());
116123
// Notify the iOS app so next batch can be sent
117124
Serial.printf(".");
118-
// pTxCharacteristic->setValue(0x02, sizeof(uint8_t));
119-
// pTxCharacteristic->notify();
125+
pTxCharacteristic->notify(0x02, sizeof(uint8_t));
120126
}
121127

122128
//-------------------------------------------------------------------
@@ -126,50 +132,54 @@ class otaCallback : public BLECharacteristicCallbacks {
126132
//-------------------------------------------------------------------
127133
if (rxData.length() < 512) // TODO Asumes at least 511 data bytes (@BLE 4.2).
128134
{
129-
Serial.printf("4. Final byte arrived");
135+
SS2K_LOG(BLE_OTA_LOG_TAG, "4. Final byte arrived");
130136
//-----------------------------------------------------------------
131137
// Final chunk arrived. Now check that
132138
// the length of total file is correct
133139
//-----------------------------------------------------------------
134140
if (esp_ota_end(otaHandler) != ESP_OK) {
135-
Serial.printf("OTA end failed ");
141+
SS2K_LOG(BLE_OTA_LOG_TAG, "OTA end failed ");
136142
downloadFlag = false;
137143
pTxCharacteristic->notify(0x04, sizeof(uint8_t));
144+
ss2k->rebootFlag = true;
138145
return;
139146
}
140147
pTxCharacteristic->notify(0x05, sizeof(uint8_t));
141148
//-----------------------------------------------------------------
142149
// Clear download flag and restart the ESP32 if the firmware
143150
// update was successful
144151
//-----------------------------------------------------------------
145-
Serial.printf("Set Boot partion");
152+
SS2K_LOG(BLE_OTA_LOG_TAG, "Set Boot partition");
146153
if (ESP_OK == esp_ota_set_boot_partition(update_partition)) {
147154
esp_ota_end(otaHandler);
148155
downloadFlag = false;
149-
Serial.printf("Restarting...");
156+
SS2K_LOG(BLE_OTA_LOG_TAG, "Restarting...");
150157
ss2k->rebootFlag = true;
151158
return;
152159
} else {
153160
//------------------------------------------------------------
154161
// Something went wrong, the upload was not successful
155162
//------------------------------------------------------------
156-
Serial.printf("Upload Error");
163+
SS2K_LOG(BLE_OTA_LOG_TAG, "Upload Error");
157164
pTxCharacteristic->notify(0x04, sizeof(uint8_t));
158165
downloadFlag = false;
159166
esp_ota_end(otaHandler);
167+
ss2k->rebootFlag = true;
160168
return;
161169
}
162170
}
163171
} else {
164-
ss2k->isUpdating = false;
165-
downloadFlag = false;
172+
SS2K_LOG(BLE_OTA_LOG_TAG, "Data Length < 1");
173+
ss2k->isUpdating = false;
174+
downloadFlag = false;
175+
ss2k->rebootFlag = true;
166176
}
167177
}
168178
};
169179

170-
void BLEFirmwareSetup() {
180+
void BLEFirmwareSetup(NimBLEServer *pServer) {
171181
// 3. Create BLE Service
172-
NimBLEService *pService = spinBLEServer.pServer->createService(FIRMWARE_SERVICE_UUID);
182+
NimBLEService *pService = pServer->createService(FIRMWARE_SERVICE_UUID);
173183

174184
// 4. Create BLE Characteristics inside the service(s)
175185
pTxCharacteristic = pService->createCharacteristic(FIRMWARE_CHARACTERISTIC_TX_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);

src/BLE_Server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void startBLEServer() {
5151
deviceInformationService.setupService(spinBLEServer.pServer);
5252
// wattbikeService.setupService(spinBLEServer.pServer); // No callback needed
5353
// sb20Service.begin();
54-
BLEFirmwareSetup();
54+
BLEFirmwareSetup(spinBLEServer.pServer);
5555

5656
// const std::string fitnessData = {0b00000001, 0b00100000, 0b00000000};
5757
// pAdvertising->setServiceData(FITNESSMACHINESERVICE_UUID, fitnessData);

src/HTTP_Server_Basic.cpp

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -310,61 +310,75 @@ void HTTP_Server::start() {
310310
server.send(200, "text/html", OTAServerIndex);
311311
});
312312

313-
/*handling uploading firmware file */
314313
server.on(
315314
"/update", HTTP_POST,
315+
// This is the onComplete callback. It is executed ONLY after the upload is fully finished.
316+
// This is the correct and only place to send the final response to the client.
316317
[]() {
317318
server.sendHeader("Connection", "close");
318-
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
319+
// Check if the Update process reported an error and send the final status.
320+
if (Update.hasError()) {
321+
// You can get more specific error information if you want
322+
// size_t len = Update.getErrorString(error_string_buffer, 128);
323+
// server.send(500, "text/plain", error_string_buffer);
324+
server.send(500, "text/plain", "FAIL");
325+
} else {
326+
server.send(200, "text/plain", "OK");
327+
// It's better to trigger the reboot after successfully notifying the client.
328+
ss2k->rebootFlag = true;
329+
}
319330
},
331+
// This is the onUpload callback. It handles the file data as it arrives.
332+
// It should not send any response to the client.
320333
[]() {
321334
HTTPUpload &upload = server.upload();
322335
if (upload.filename == String("firmware.bin").c_str()) {
323-
ss2k->isUpdating = true; // Set the updating flag to true
324336
if (upload.status == UPLOAD_FILE_START) {
325-
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Update: %s", upload.filename.c_str());
326-
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) { // start with max
327-
// available size
337+
ss2k->isUpdating = true; // Set the updating flag to true
338+
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Update Start: %s", upload.filename.c_str());
339+
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) {
328340
Update.printError(Serial);
329341
}
330342
} else if (upload.status == UPLOAD_FILE_WRITE) {
331343
/* flashing firmware to ESP*/
344+
Serial.printf(".");
332345
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
333346
Update.printError(Serial);
347+
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Upload Write Failed.");
334348
}
335349
} else if (upload.status == UPLOAD_FILE_END) {
336-
if (Update.end(true)) { // true to set the size to the
337-
// current progress
338-
server.send(200, "text/plain", "Firmware Uploaded Successfully. Rebooting...");
339-
ESP.restart();
350+
// Finalize the update. The true parameter tells it to flash the remaining buffer.
351+
// DO NOT send a response here.
352+
if (Update.end(true)) {
353+
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Firmware Upload Finished Successfully.");
340354
} else {
341355
Update.printError(Serial);
356+
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Unknown OTA issue on end.");
342357
}
358+
// The reboot will be triggered in the onComplete handler after the response.
343359
}
344-
ss2k->isUpdating = false; // Reset the updating flag
345360
} else if (upload.filename == String("littlefs.bin").c_str()) {
346361
if (upload.status == UPLOAD_FILE_START) {
347-
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Update: %s", upload.filename.c_str());
348-
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) { // start with max
349-
// available size
362+
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Update Start: %s", upload.filename.c_str());
363+
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) {
350364
Update.printError(Serial);
351365
}
352366
} else if (upload.status == UPLOAD_FILE_WRITE) {
353-
/* flashing firmware to ESP*/
367+
Serial.printf(".");
354368
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
355369
Update.printError(Serial);
356370
}
357371
} else if (upload.status == UPLOAD_FILE_END) {
358-
if (Update.end(true)) { // true to set the size to the
359-
// current progress
360-
server.send(200, "text/plain", "Littlefs Uploaded Successfully. Rebooting...");
372+
// Finalize the update.
373+
// DO NOT send a response here.
374+
if (Update.end(true)) {
375+
SS2K_LOG(HTTP_SERVER_LOG_TAG, "Littlefs Upload Finished Successfully.");
361376
userConfig->saveToLittleFS();
362-
ss2k->rebootFlag == true;
363377
} else {
364378
Update.printError(Serial);
365379
}
366380
}
367-
} else {
381+
} else { // Handles other file uploads to LittleFS
368382
if (upload.status == UPLOAD_FILE_START) {
369383
String filename = upload.filename;
370384
if (!filename.startsWith("/")) {
@@ -382,7 +396,10 @@ void HTTP_Server::start() {
382396
fsUploadFile.close();
383397
}
384398
SS2K_LOG(HTTP_SERVER_LOG_TAG, "handleFileUpload Size: %zu", upload.totalSize);
385-
server.send(200, "text/plain", String(upload.filename + " Uploaded Successfully."));
399+
// For non-firmware files, it's okay to send a response here,
400+
// but for consistency, it's better to let the onComplete handler do it.
401+
// For this example, we assume the main onComplete handler is for firmware.
402+
// A more robust solution would check which type of file was uploaded.
386403
}
387404
}
388405
});

0 commit comments

Comments
 (0)