Wgranie zmian do repozytorium

This commit is contained in:
2026-05-10 16:46:04 +02:00
commit f171113450
1607 changed files with 254616 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
#include "APIClient.h"
#include <WiFiClient.h>
#include <base64.h>
static const char *TAG_API = "API";
APIClient::APIClient() {}
bool APIClient::uploadMeasurement(const String &filePath) {
if (WiFi.status() != WL_CONNECTED) {
ESP_LOGE(TAG_API, "No WiFi connection.");
return false;
}
File file = SD.open(filePath, FILE_READ);
if (!file) {
ESP_LOGE(TAG_API, "Failed to open file %s", filePath.c_str());
return false;
}
// Wyciągnij samą nazwę pliku (bez ścieżki)
String filename = filePath;
int slashIndex = filename.lastIndexOf('/');
if (slashIndex >= 0) {
filename = filename.substring(slashIndex + 1);
}
// multipart/form-data boundary
String boundary = "----ESP32WMTBoundary";
String head = "--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"" +
filename + "\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
String tail = "\r\n--" + boundary + "--\r\n";
size_t fileSize = file.size();
size_t totalLength = head.length() + fileSize + tail.length();
// Połączenie z hostem
WiFiClient client;
String host = String(config.restURL);
int port = config.restPort;
// Usuń prefiks protokołu z hosta
host.replace("http://", "");
host.replace("https://", "");
ESP_LOGI(TAG_API, "Connecting to %s:%d for upload", host.c_str(), port);
if (!client.connect(host.c_str(), port)) {
ESP_LOGE(TAG_API, "Connection failed to host %s:%d", host.c_str(), port);
file.close();
return false;
}
ESP_LOGI(TAG_API, "Uploading %s (%d bytes)", filePath.c_str(), fileSize);
// --- HTTP Request ---
// Endpoint wg dokumentacji API IoT
client.println("POST /api/v1/measurements/measurements/upload HTTP/1.1");
client.println("Host: " + host + ":" + String(port));
// Basic Auth: base64(serial:password)
String auth = String(config.restUser) + ":" + String(config.restPass);
String authBase64 = base64::encode(auth);
client.println("Authorization: Basic " + authBase64);
client.println("Content-Length: " + String(totalLength));
client.println("Content-Type: multipart/form-data; boundary=" + boundary);
client.println("Connection: close");
client.println();
// Multipart body: head + file data + tail
client.print(head);
uint8_t buffer[2048];
while (file.available()) {
size_t len = file.read(buffer, sizeof(buffer));
client.write(buffer, len);
Watchdog::feed();
}
client.print(tail);
file.close();
// --- Parsowanie odpowiedzi ---
int httpCode = 0;
String responseLine;
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 15000) {
if (client.available()) {
responseLine = client.readStringUntil('\n');
responseLine.trim();
if (responseLine.startsWith("HTTP/1.1 ")) {
httpCode = responseLine.substring(9, 12).toInt();
}
if (responseLine.length() == 0)
break;
}
Watchdog::feed();
}
String responseBody = "";
while (client.available()) {
responseBody += client.readString();
}
client.stop();
// --- Obsługa kodów odpowiedzi wg dokumentacji API ---
if (httpCode == 201) {
ESP_LOGI(TAG_API, "Upload successful: 201 Created");
return true;
} else if (httpCode == 401) {
ESP_LOGE(TAG_API, "Unauthorized 401: Wrong serial or password!");
} else if (httpCode == 403) {
ESP_LOGE(TAG_API, "Forbidden 403: Device not authorized or user tried upload.");
} else if (httpCode == 400) {
ESP_LOGE(TAG_API, "Bad Request 400: %s", responseBody.c_str());
} else {
ESP_LOGE(TAG_API, "Upload failed with code %d. Response: %s", httpCode,
responseBody.c_str());
}
return false;
}