feat: implement retry mechanism and timeout handling for API requests
This commit is contained in:
144
src/api.cpp
144
src/api.cpp
@@ -126,26 +126,67 @@ void sendToApi(void *parameter) {
|
|||||||
String spoolIdForWeight = params->spoolIdForWeight;
|
String spoolIdForWeight = params->spoolIdForWeight;
|
||||||
uint16_t weightValue = params->weightValue;
|
uint16_t weightValue = params->weightValue;
|
||||||
|
|
||||||
|
// Retry mechanism with configurable parameters
|
||||||
|
const uint8_t MAX_RETRIES = 3;
|
||||||
|
const uint16_t RETRY_DELAY_MS = 1000; // 1 second between retries
|
||||||
|
const uint16_t HTTP_TIMEOUT_MS = 10000; // 10 second HTTP timeout
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
int httpCode = -1;
|
||||||
|
String responsePayload = "";
|
||||||
|
|
||||||
|
// Try request with retries
|
||||||
|
for (uint8_t attempt = 1; attempt <= MAX_RETRIES && !success; attempt++) {
|
||||||
|
Serial.printf("API Request attempt %d/%d to: %s\n", attempt, MAX_RETRIES, spoolsUrl.c_str());
|
||||||
|
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setReuse(false);
|
http.setReuse(false);
|
||||||
|
http.setTimeout(HTTP_TIMEOUT_MS); // Set HTTP timeout
|
||||||
|
|
||||||
http.begin(spoolsUrl);
|
http.begin(spoolsUrl);
|
||||||
http.addHeader("Content-Type", "application/json");
|
http.addHeader("Content-Type", "application/json");
|
||||||
if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
|
if (octoEnabled && octoToken != "") http.addHeader("X-Api-Key", octoToken);
|
||||||
|
|
||||||
int httpCode;
|
// Execute HTTP request based on type
|
||||||
if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
|
if (httpType == "PATCH") httpCode = http.PATCH(updatePayload);
|
||||||
else if (httpType == "POST") httpCode = http.POST(updatePayload);
|
else if (httpType == "POST") httpCode = http.POST(updatePayload);
|
||||||
else if (httpType == "GET") httpCode = http.GET();
|
else if (httpType == "GET") httpCode = http.GET();
|
||||||
else httpCode = http.PUT(updatePayload);
|
else httpCode = http.PUT(updatePayload);
|
||||||
|
|
||||||
if (httpCode == HTTP_CODE_OK) {
|
// Check if request was successful
|
||||||
|
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_CREATED) {
|
||||||
|
responsePayload = http.getString();
|
||||||
|
success = true;
|
||||||
|
Serial.printf("API Request successful on attempt %d, HTTP Code: %d\n", attempt, httpCode);
|
||||||
|
} else {
|
||||||
|
Serial.printf("API Request failed on attempt %d, HTTP Code: %d (%s)\n",
|
||||||
|
attempt, httpCode, http.errorToString(httpCode).c_str());
|
||||||
|
|
||||||
|
// Don't retry on certain error codes (client errors)
|
||||||
|
if (httpCode >= 400 && httpCode < 500 && httpCode != 408 && httpCode != 429) {
|
||||||
|
Serial.println("Client error detected, stopping retries");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait before retry (except on last attempt)
|
||||||
|
if (attempt < MAX_RETRIES) {
|
||||||
|
Serial.printf("Waiting %dms before retry...\n", RETRY_DELAY_MS);
|
||||||
|
http.end();
|
||||||
|
vTaskDelay(RETRY_DELAY_MS / portTICK_PERIOD_MS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process successful response
|
||||||
|
if (success) {
|
||||||
Serial.println("Spoolman Abfrage erfolgreich");
|
Serial.println("Spoolman Abfrage erfolgreich");
|
||||||
|
|
||||||
// Restgewicht der Spule auslesen
|
// Restgewicht der Spule auslesen
|
||||||
String payload = http.getString();
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
DeserializationError error = deserializeJson(doc, payload);
|
DeserializationError error = deserializeJson(doc, responsePayload);
|
||||||
if (error) {
|
if (error) {
|
||||||
Serial.print("Fehler beim Parsen der JSON-Antwort: ");
|
Serial.print("Fehler beim Parsen der JSON-Antwort: ");
|
||||||
Serial.println(error.c_str());
|
Serial.println(error.c_str());
|
||||||
@@ -226,9 +267,8 @@ void sendToApi(void *parameter) {
|
|||||||
Serial.println("Spoolman erfolgreich erstellt");
|
Serial.println("Spoolman erfolgreich erstellt");
|
||||||
|
|
||||||
// Parse response for created resources
|
// Parse response for created resources
|
||||||
String payload = http.getString();
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
DeserializationError error = deserializeJson(doc, payload);
|
DeserializationError error = deserializeJson(doc, responsePayload);
|
||||||
if (error) {
|
if (error) {
|
||||||
Serial.print("Fehler beim Parsen der JSON-Antwort: ");
|
Serial.print("Fehler beim Parsen der JSON-Antwort: ");
|
||||||
Serial.println(error.c_str());
|
Serial.println(error.c_str());
|
||||||
@@ -280,14 +320,17 @@ void sendToApi(void *parameter) {
|
|||||||
Serial.println(weightPayload);
|
Serial.println(weightPayload);
|
||||||
|
|
||||||
// Execute weight update
|
// Execute weight update
|
||||||
http.begin(weightUrl);
|
HTTPClient weightHttp;
|
||||||
http.addHeader("Content-Type", "application/json");
|
weightHttp.setReuse(false);
|
||||||
|
weightHttp.setTimeout(HTTP_TIMEOUT_MS);
|
||||||
|
weightHttp.begin(weightUrl);
|
||||||
|
weightHttp.addHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
int weightHttpCode = http.PUT(weightPayload);
|
int weightHttpCode = weightHttp.PUT(weightPayload);
|
||||||
|
|
||||||
if (weightHttpCode == HTTP_CODE_OK) {
|
if (weightHttpCode == HTTP_CODE_OK) {
|
||||||
Serial.println("Weight update successful");
|
Serial.println("Weight update successful");
|
||||||
String weightResponse = http.getString();
|
String weightResponse = weightHttp.getString();
|
||||||
JsonDocument weightResponseDoc;
|
JsonDocument weightResponseDoc;
|
||||||
DeserializationError weightError = deserializeJson(weightResponseDoc, weightResponse);
|
DeserializationError weightError = deserializeJson(weightResponseDoc, weightResponse);
|
||||||
|
|
||||||
@@ -310,6 +353,7 @@ void sendToApi(void *parameter) {
|
|||||||
oledShowProgressBar(1, 1, "Failure!", "Weight update");
|
oledShowProgressBar(1, 1, "Failure!", "Weight update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
weightHttp.end();
|
||||||
weightDoc.clear();
|
weightDoc.clear();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -351,7 +395,6 @@ void sendToApi(void *parameter) {
|
|||||||
nfcReaderState = NFC_IDLE; // Reset NFC state to allow retry
|
nfcReaderState = NFC_IDLE; // Reset NFC state to allow retry
|
||||||
}
|
}
|
||||||
|
|
||||||
http.end();
|
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
// Speicher freigeben
|
// Speicher freigeben
|
||||||
@@ -687,20 +730,8 @@ uint16_t createVendor(const JsonDocument& payload) {
|
|||||||
|
|
||||||
// Wait for task completion and return the created vendor ID
|
// Wait for task completion and return the created vendor ID
|
||||||
// Note: createdVendorId will be set by sendToApi when response is received
|
// Note: createdVendorId will be set by sendToApi when response is received
|
||||||
uint16_t timeout_counter = 0;
|
while(createdVendorId == 65535) {
|
||||||
const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms)
|
|
||||||
|
|
||||||
while(createdVendorId == 65535 && timeout_counter < max_timeout) {
|
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
timeout_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we got a valid response or timed out
|
|
||||||
if (createdVendorId == 65535) {
|
|
||||||
Serial.println("ERROR: Timeout waiting for vendor creation response");
|
|
||||||
createdVendorId = 0; // Set to error state
|
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return createdVendorId;
|
return createdVendorId;
|
||||||
@@ -746,21 +777,9 @@ uint16_t checkVendor(const JsonDocument& payload) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Wait until foundVendorId is updated by the API response (not 65535 anymore)
|
// Wait until foundVendorId is updated by the API response (not 65535 anymore)
|
||||||
uint16_t timeout_counter = 0;
|
while (foundVendorId == 65535)
|
||||||
const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms)
|
|
||||||
|
|
||||||
while (foundVendorId == 65535 && timeout_counter < max_timeout)
|
|
||||||
{
|
{
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
timeout_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for timeout
|
|
||||||
if (foundVendorId == 65535) {
|
|
||||||
Serial.println("ERROR: Timeout waiting for vendor check response");
|
|
||||||
foundVendorId = 0; // Set to error state
|
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if vendor was found
|
// Check if vendor was found
|
||||||
@@ -866,26 +885,8 @@ uint16_t createFilament(uint16_t vendorId, const JsonDocument& payload) {
|
|||||||
|
|
||||||
// Wait for task completion and return the created filament ID
|
// Wait for task completion and return the created filament ID
|
||||||
// Note: createdFilamentId will be set by sendToApi when response is received
|
// Note: createdFilamentId will be set by sendToApi when response is received
|
||||||
uint16_t timeout_counter = 0;
|
while(createdFilamentId == 65535) {
|
||||||
const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms)
|
|
||||||
|
|
||||||
while(createdFilamentId == 65535 && timeout_counter < max_timeout) {
|
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
timeout_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we got a valid response or timed out
|
|
||||||
if (createdFilamentId == 65535) {
|
|
||||||
Serial.println("ERROR: Timeout waiting for filament creation response");
|
|
||||||
createdFilamentId = 0; // Set to error state
|
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (createdFilamentId == 0) {
|
|
||||||
Serial.println("ERROR: Filament creation failed (HTTP error)");
|
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return createdFilamentId;
|
return createdFilamentId;
|
||||||
@@ -922,20 +923,8 @@ uint16_t checkFilament(uint16_t vendorId, const JsonDocument& payload) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Wait until foundFilamentId is updated by the API response (not 65535 anymore)
|
// Wait until foundFilamentId is updated by the API response (not 65535 anymore)
|
||||||
uint16_t timeout_counter = 0;
|
while (foundFilamentId == 65535) {
|
||||||
const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms)
|
|
||||||
|
|
||||||
while (foundFilamentId == 65535 && timeout_counter < max_timeout) {
|
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
timeout_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for timeout
|
|
||||||
if (foundFilamentId == 65535) {
|
|
||||||
Serial.println("ERROR: Timeout waiting for filament check response");
|
|
||||||
foundFilamentId = 0; // Set to error state
|
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if filament was found
|
// Check if filament was found
|
||||||
@@ -1014,24 +1003,13 @@ uint16_t createSpool(uint16_t vendorId, uint16_t filamentId, JsonDocument& paylo
|
|||||||
|
|
||||||
// Wait for task completion and return the created spool ID
|
// Wait for task completion and return the created spool ID
|
||||||
// Note: createdSpoolId will be set by sendToApi when response is received
|
// Note: createdSpoolId will be set by sendToApi when response is received
|
||||||
uint16_t timeout_counter = 0;
|
while(createdSpoolId == 65535) {
|
||||||
const uint16_t max_timeout = 200; // 10 seconds timeout (200 * 50ms)
|
|
||||||
|
|
||||||
while(createdSpoolId == 65535 && timeout_counter < max_timeout) {
|
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
timeout_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we got a valid response or timed out
|
|
||||||
if (createdSpoolId == 65535) {
|
|
||||||
Serial.println("ERROR: Timeout waiting for spool creation response");
|
|
||||||
createdSpoolId = 0; // Set to error state
|
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if spool creation was successful
|
||||||
if (createdSpoolId == 0) {
|
if (createdSpoolId == 0) {
|
||||||
Serial.println("ERROR: Spool creation failed (HTTP error)");
|
Serial.println("ERROR: Spool creation failed");
|
||||||
nfcReaderState = NFC_IDLE; // Reset NFC state
|
nfcReaderState = NFC_IDLE; // Reset NFC state
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user