Removed specific mentions of protobuf for endpoints

Also removed features unused json endpoint data
This commit is contained in:
Niklas Jensen
2026-01-30 22:06:24 +01:00
committed by nikguin04
parent 07f5ffd5a7
commit f04e97443d
12 changed files with 38 additions and 149 deletions
+6 -12
View File
@@ -5,14 +5,13 @@
#include <vector>
#include <string>
#include <map>
#include <ArduinoJson.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include <platform_shared/api.pb.h>
#include <semphr.h>
using HttpGetHandler = std::function<esp_err_t(httpd_req_t*)>;
using HttpPostHandler = std::function<esp_err_t(httpd_req_t*, JsonVariant&)>;
using HttpProtoHandler = std::function<esp_err_t(httpd_req_t*, api_Request*)>;
using HttpPostHandler = std::function<esp_err_t(httpd_req_t*, api_Request*)>;
using WsFrameHandler = std::function<esp_err_t(httpd_req_t*, httpd_ws_frame_t*)>;
using WsOpenHandler = std::function<void(httpd_req_t*)>;
using WsCloseHandler = std::function<void(int)>;
@@ -21,7 +20,7 @@ using WsCloseHandler = std::function<void(int)>;
// Usage: STAITC_PROTO_POST_ENDPOINT(server, "/api/files/delete", file_delete_request, FileSystem::handleDelete)
// Handler signature: esp_err_t handleDelete(httpd_req_t* req, const api_FileDeleteRequest& payload)
#define STAITC_PROTO_POST_ENDPOINT(server_ref, uri, payload_type, handler) \
(server_ref).onProto(uri, HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) { \
(server_ref).on(uri, HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) { \
if (protoReq->which_payload != api_Request_##payload_type##_tag) { \
return WebServer::sendError(request, 400, "Invalid request payload"); \
} \
@@ -33,7 +32,6 @@ struct HttpRoute {
httpd_method_t method;
HttpGetHandler getHandler;
HttpPostHandler postHandler;
HttpProtoHandler protoHandler; // For proto handlers that don't need JSON parsing
bool isWebsocket;
};
@@ -48,7 +46,6 @@ class WebServer {
void on(const char* uri, httpd_method_t method, HttpGetHandler handler);
void on(const char* uri, httpd_method_t method, HttpPostHandler handler);
void onProto(const char* uri, httpd_method_t method, HttpProtoHandler handler);
void onWsFrame(WsFrameHandler handler);
void onWsOpen(WsOpenHandler handler);
@@ -65,15 +62,12 @@ class WebServer {
httpd_handle_t getHandle() { return server_; }
static esp_err_t sendJson(httpd_req_t* req, int status, const char* json);
static esp_err_t sendJson(httpd_req_t* req, int status, JsonDocument& doc);
static esp_err_t sendError(httpd_req_t* req, int status, const char* message);
static esp_err_t sendOk(httpd_req_t* req);
static esp_err_t sendOkProto(httpd_req_t* req);
static esp_err_t sendProto(httpd_req_t* req, int status, const uint8_t* data, size_t len);
static esp_err_t send(httpd_req_t* req, int status, const uint8_t* data, size_t len);
template <typename T>
static esp_err_t sendProto(httpd_req_t* req, int status, const T& msg, const pb_msgdesc_t* fields) {
static esp_err_t send(httpd_req_t* req, int status, const T& msg, const pb_msgdesc_t* fields) {
size_t size = 0;
if (!pb_get_encoded_size(&size, fields, &msg)) {
return sendError(req, 500, "Failed to calculate proto size");
@@ -90,7 +84,7 @@ class WebServer {
return sendError(req, 500, "Failed to encode proto");
}
esp_err_t result = sendProto(req, status, buffer, stream.bytes_written);
esp_err_t result = send(req, status, buffer, stream.bytes_written);
free(buffer);
return result;
}
-4
View File
@@ -65,10 +65,6 @@ namespace feature_service {
void printFeatureConfiguration();
void features(JsonObject& root);
void features_request(const socket_message_FeaturesDataRequest& fd_req, socket_message_FeaturesDataResponse& fd_res);
esp_err_t getFeatures(httpd_req_t* request);
} // namespace feature_service
+1 -1
View File
@@ -9,7 +9,7 @@
#define ESP_FS LittleFS
#define FS_CONFIG_DIRECTORY "/config"
#define DEVICE_CONFIG_FILE "/config/peripheral.json"'
#define DEVICE_CONFIG_FILE "/config/peripheral.json"
#define CAMERA_SETTINGS_FILE "/config/cameraSettings.pb"
#define AP_SETTINGS_FILE "/config/apSettings.pb"
#define MDNS_SETTINGS_FILE "/config/mdnsSettings.pb"
@@ -95,7 +95,7 @@ class StatefulProtoEndpoint {
_statefulService->read([this, &protoState](const T& settings) { _stateReader(settings, protoState); });
_responseAssigner(res, protoState);
return WebServer::sendProto(request, 200, res, api_Response_fields);
return WebServer::send(request, 200, res, api_Response_fields);
}
/** Sends error wrapped in Response */
@@ -103,7 +103,7 @@ class StatefulProtoEndpoint {
api_Response res = api_Response_init_zero;
res.status_code = statusCode;
res.error_message = (char*)message;
return WebServer::sendProto(request, statusCode == 200 ? 200 : 400, res, api_Response_fields);
return WebServer::send(request, statusCode == 200 ? 200 : 400, res, api_Response_fields);
}
};
+1 -1
View File
@@ -24,7 +24,7 @@ esp_err_t APService::getStatusProto(httpd_req_t *request) {
res.status_code = 200;
res.which_payload = api_Response_ap_status_tag;
statusProto(res.payload.ap_status);
return WebServer::sendProto(request, 200, res, api_Response_fields);
return WebServer::send(request, 200, res, api_Response_fields);
}
void APService::statusProto(api_APStatus &proto) {
+5 -84
View File
@@ -73,7 +73,7 @@ esp_err_t WebServer::httpHandler(httpd_req_t* req) {
if (route.getHandler) {
return route.getHandler(req);
}
if (route.protoHandler) {
if (route.postHandler) {
size_t contentLen = req->content_len;
if (contentLen == 0 || contentLen > 4096) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid content length");
@@ -111,48 +111,7 @@ esp_err_t WebServer::httpHandler(httpd_req_t* req) {
return ESP_FAIL;
}
return route.protoHandler(req, &protoReq);
}
if (route.postHandler) {
char* content = nullptr;
size_t contentLen = req->content_len;
if (contentLen > 0) {
content = (char*)malloc(contentLen + 1);
if (!content) {
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Memory allocation failed");
return ESP_FAIL;
}
int received = 0;
int remaining = contentLen;
while (remaining > 0) {
int ret = httpd_req_recv(req, content + received, remaining);
if (ret <= 0) {
free(content);
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
httpd_resp_send_err(req, HTTPD_408_REQ_TIMEOUT, "Request timeout");
}
return ESP_FAIL;
}
received += ret;
remaining -= ret;
}
content[contentLen] = '\0';
}
JsonDocument doc;
if (content && contentLen > 0) {
DeserializationError error = deserializeJson(doc, content, contentLen);
free(content);
if (error) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
}
JsonVariant json = doc.as<JsonVariant>();
return route.postHandler(req, json);
return route.postHandler(req, &protoReq);
}
}
}
@@ -228,7 +187,6 @@ void WebServer::on(const char* uri, httpd_method_t method, HttpGetHandler handle
route.method = method;
route.getHandler = handler;
route.postHandler = nullptr;
route.protoHandler = nullptr;
route.isWebsocket = false;
routes_.push_back(route);
@@ -243,22 +201,6 @@ void WebServer::on(const char* uri, httpd_method_t method, HttpPostHandler handl
route.method = method;
route.getHandler = nullptr;
route.postHandler = handler;
route.protoHandler = nullptr;
route.isWebsocket = false;
routes_.push_back(route);
if (server_) {
registerRoute(route);
}
}
void WebServer::onProto(const char* uri, httpd_method_t method, HttpProtoHandler handler) {
HttpRoute route;
route.uri = uri;
route.method = method;
route.getHandler = nullptr;
route.postHandler = nullptr;
route.protoHandler = handler;
route.isWebsocket = false;
routes_.push_back(route);
@@ -284,7 +226,6 @@ void WebServer::registerWebsocket(const char* uri) {
route.method = HTTP_GET;
route.getHandler = nullptr;
route.postHandler = nullptr;
route.protoHandler = nullptr;
route.isWebsocket = true;
routes_.push_back(route);
@@ -336,33 +277,13 @@ esp_err_t WebServer::wsSendAll(const uint8_t* data, size_t len) {
return ESP_OK;
}
esp_err_t WebServer::sendJson(httpd_req_t* req, int status, const char* json) {
httpd_resp_set_status(req, status == 200 ? "200 OK"
: status == 400 ? "400 Bad Request"
: status == 404 ? "404 Not Found"
: status == 500 ? "500 Internal Server Error"
: "200 OK");
httpd_resp_set_type(req, "application/json");
return httpd_resp_send(req, json, strlen(json));
}
esp_err_t WebServer::sendJson(httpd_req_t* req, int status, JsonDocument& doc) {
std::string json;
serializeJson(doc, json);
return sendJson(req, status, json.c_str());
}
esp_err_t WebServer::sendError(httpd_req_t* req, int status, const char* message) {
JsonDocument doc;
doc["error"] = message;
return sendJson(req, status, doc);
return send(req, status, (uint8_t*) message, strlen(message));
}
esp_err_t WebServer::sendOk(httpd_req_t* req) { return sendJson(req, 200, "{\"status\":\"ok\"}"); }
esp_err_t WebServer::sendOk(httpd_req_t* req) { return send(req, 200, nullptr, 0); }
esp_err_t WebServer::sendOkProto(httpd_req_t* req) { return sendProto(req, 200, nullptr, 0); }
esp_err_t WebServer::sendProto(httpd_req_t* req, int status, const uint8_t* data, size_t len) {
esp_err_t WebServer::send(httpd_req_t* req, int status, const uint8_t* data, size_t len) {
httpd_resp_set_status(req, status == 200 ? "200 OK"
: status == 202 ? "202 Accepted"
: status == 400 ? "400 Bad Request"
-22
View File
@@ -41,27 +41,5 @@ void features_request(const socket_message_FeaturesDataRequest& fd_req, socket_m
fd_res.variant = const_cast<char*>(KINEMATICS_VARIANT_STR);
}
void features(JsonObject& root) {
root["camera"] = USE_CAMERA ? true : false;
root["imu"] = (USE_MPU6050 || USE_BNO055) ? true : false;
root["mag"] = (USE_HMC5883 || USE_BNO055) ? true : false;
root["bmp"] = USE_BMP180 ? true : false;
root["sonar"] = USE_USS ? true : false;
root["servo"] = USE_PCA9685 ? true : false;
root["ws2812"] = USE_WS2812 ? true : false;
root["mdns"] = USE_MDNS ? true : false;
root["embed_www"] = EMBED_WEBAPP ? true : false;
root["firmware_version"] = APP_VERSION;
root["firmware_name"] = APP_NAME;
root["firmware_built_target"] = BUILD_TARGET;
root["variant"] = KINEMATICS_VARIANT_STR;
}
esp_err_t getFeatures(httpd_req_t* request) {
JsonDocument doc;
JsonObject root = doc.to<JsonObject>();
features(root);
return WebServer::sendJson(request, 200, doc);
}
} // namespace feature_service
+4 -4
View File
@@ -84,7 +84,7 @@ esp_err_t getFilesProto(httpd_req_t *request) {
allocatedEntries.push_back(res.payload.file_list.entries);
res.payload.file_list.entries[0] = rootEntry;
esp_err_t result = WebServer::sendProto(request, 200, res, api_Response_fields);
esp_err_t result = WebServer::send(request, 200, res, api_Response_fields);
freeAllocatedEntries(); // Clean up after sending
return result;
@@ -125,7 +125,7 @@ esp_err_t handleDelete(httpd_req_t *request, const api_FileDeleteRequest &req) {
if (deleteFile(req.path)) {
res.status_code = 200;
res.which_payload = api_Response_empty_message_tag;
return WebServer::sendProto(request, 200, res, api_Response_fields);
return WebServer::send(request, 200, res, api_Response_fields);
} else {
return WebServer::sendError(request, 500, "Delete failed");
}
@@ -138,7 +138,7 @@ esp_err_t handleEdit(httpd_req_t *request, const api_FileEditRequest &req) {
if (editFile(req.path, req.content->bytes, req.content->size)) {
res.status_code = 200;
res.which_payload = api_Response_empty_message_tag;
return WebServer::sendProto(request, 200, res, api_Response_fields);
return WebServer::send(request, 200, res, api_Response_fields);
} else {
return WebServer::sendError(request, 500, "Edit failed");
}
@@ -192,7 +192,7 @@ esp_err_t mkdir(httpd_req_t *request, const api_FileMkdirRequest &req) {
if (ESP_FS.mkdir(req.path)) {
res.status_code = 200;
res.which_payload = api_Response_empty_message_tag;
return WebServer::sendProto(request, 200, res, api_Response_fields);
return WebServer::send(request, 200, res, api_Response_fields);
} else {
return WebServer::sendError(request, 500, "mkdir failed");
}
+10 -10
View File
@@ -42,11 +42,11 @@ void setupServer() {
server.config(50 + WWW_ASSETS_COUNT, 32768);
server.listen(80);
server.onProto("/api/system/reset", HTTP_POST,
server.on("/api/system/reset", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) { return system_service::handleReset(request); });
server.onProto("/api/system/restart", HTTP_POST,
server.on("/api/system/restart", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) { return system_service::handleRestart(request); });
server.onProto("/api/system/sleep", HTTP_POST,
server.on("/api/system/sleep", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) { return system_service::handleSleep(request); });
#if USE_CAMERA
server.on("/api/camera/still", HTTP_GET, [&](httpd_req_t *request) { return cameraService.cameraStill(request); });
@@ -54,19 +54,19 @@ void setupServer() {
[&](httpd_req_t *request) { return cameraService.cameraStream(request); });
server.on("/api/camera/settings", HTTP_GET,
[&](httpd_req_t *request) { return cameraService.protoEndpoint.getState(request); });
server.onProto("/api/camera/settings", HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) {
server.on("/api/camera/settings", HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) {
return cameraService.protoEndpoint.handleStateUpdate(request, protoReq);
});
#endif
server.on("/api/servo/config", HTTP_GET,
[&](httpd_req_t *request) { return servoController.protoEndpoint.getState(request); });
server.onProto("/api/servo/config", HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) {
server.on("/api/servo/config", HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) {
return servoController.protoEndpoint.handleStateUpdate(request, protoReq);
});
server.on("/api/wifi/sta/settings", HTTP_GET,
[&](httpd_req_t *request) { return wifiService.protoEndpoint.getState(request); });
server.onProto("/api/wifi/sta/settings", HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) {
server.on("/api/wifi/sta/settings", HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) {
return wifiService.protoEndpoint.handleStateUpdate(request, protoReq);
});
server.on("/api/wifi/scan", HTTP_GET, [&](httpd_req_t *request) { return wifiService.handleScan(request); });
@@ -77,26 +77,26 @@ void setupServer() {
server.on("/api/ap/status", HTTP_GET, [&](httpd_req_t *request) { return apService.getStatusProto(request); });
server.on("/api/ap/settings", HTTP_GET,
[&](httpd_req_t *request) { return apService.protoEndpoint.getState(request); });
server.onProto("/api/ap/settings", HTTP_POST,
server.on("/api/ap/settings", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) {
return apService.protoEndpoint.handleStateUpdate(request, protoReq);
});
server.on("/api/peripherals/settings", HTTP_GET,
[&](httpd_req_t *request) { return peripherals.protoEndpoint.getState(request); });
server.onProto("/api/peripherals/settings", HTTP_POST,
server.on("/api/peripherals/settings", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) {
return peripherals.protoEndpoint.handleStateUpdate(request, protoReq);
});
#if FT_ENABLED(USE_MDNS)
server.on("/api/mdns/settings", HTTP_GET, [&](httpd_req_t *request) { return mdnsService.protoEndpoint.getState(request); });
server.onProto("/api/mdns/settings", HTTP_POST,
server.on("/api/mdns/settings", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) {
return mdnsService.protoEndpoint.handleStateUpdate(request, protoReq);
});
server.on("/api/mdns/status", HTTP_GET, [&](httpd_req_t *request) { return mdnsService.getStatus(request); });
server.onProto("/api/mdns/query", HTTP_POST,
server.on("/api/mdns/query", HTTP_POST,
[&](httpd_req_t *request, api_Request *protoReq) {
return mdnsService.queryServices(request, protoReq);
});
+2 -2
View File
@@ -92,7 +92,7 @@ esp_err_t MDNSService::getStatus(httpd_req_t *request) {
status.global_txt_records[i] = state().global_txt_records[i];
}
return WebServer::sendProto(request, 200, response, api_Response_fields);
return WebServer::send(request, 200, response, api_Response_fields);
}
esp_err_t MDNSService::queryServices(httpd_req_t *request, api_Request *protoReq) {
@@ -120,5 +120,5 @@ esp_err_t MDNSService::queryServices(httpd_req_t *request, api_Request *protoReq
queryResp.services[i].port = MDNS.port(i);
}
return WebServer::sendProto(request, 200, response, api_Response_fields);
return WebServer::send(request, 200, response, api_Response_fields);
}
+3 -3
View File
@@ -7,17 +7,17 @@ static const char *TAG = "SystemService";
esp_err_t handleReset(httpd_req_t *request) {
reset();
return WebServer::sendOkProto(request);
return WebServer::sendOk(request);
}
esp_err_t handleRestart(httpd_req_t *request) {
restart();
return WebServer::sendOkProto(request);
return WebServer::sendOk(request);
}
esp_err_t handleSleep(httpd_req_t *request) {
sleep();
return WebServer::sendOkProto(request);
return WebServer::sendOk(request);
}
void reset() {
+4 -4
View File
@@ -51,7 +51,7 @@ esp_err_t WiFiService::handleScan(httpd_req_t *request) {
api_Response response = api_Response_init_zero;
response.status_code = 202;
response.which_payload = api_Response_empty_message_tag;
return WebServer::sendProto(request, 202, response, api_Response_fields);
return WebServer::send(request, 202, response, api_Response_fields);
}
esp_err_t WiFiService::getNetworks(httpd_req_t *request) {
@@ -61,7 +61,7 @@ esp_err_t WiFiService::getNetworks(httpd_req_t *request) {
api_Response response = api_Response_init_zero;
response.status_code = 202;
response.which_payload = api_Response_empty_message_tag;
return WebServer::sendProto(request, 202, response, api_Response_fields);
return WebServer::send(request, 202, response, api_Response_fields);
} else if (numNetworks < -1) {
return handleScan(request);
}
@@ -86,7 +86,7 @@ esp_err_t WiFiService::getNetworks(httpd_req_t *request) {
response.payload.wifi_network_list.networks = networks;
response.payload.wifi_network_list.networks_count = count;
return WebServer::sendProto(request, 200, response, api_Response_fields);
return WebServer::send(request, 200, response, api_Response_fields);
}
void WiFiService::setupMDNS(const char *hostname) {
@@ -125,7 +125,7 @@ esp_err_t WiFiService::getNetworkStatus(httpd_req_t *request) {
}
}
return WebServer::sendProto(request, 200, response, api_Response_fields);
return WebServer::send(request, 200, response, api_Response_fields);
}
void WiFiService::manageSTA() {