feat: create firmware skeleton and reproducible build

This commit is contained in:
2026-09-03 01:02:40 +03:00
parent dd16bc7ade
commit 9c274800b5
24 changed files with 827 additions and 31 deletions
+5
View File
@@ -0,0 +1,5 @@
idf_component_register(
SRCS "maze32_web.c"
INCLUDE_DIRS "include"
REQUIRES esp_http_server maze32_platform
)
@@ -0,0 +1,18 @@
#ifndef MAZE32_WEB_H
#define MAZE32_WEB_H
#include "esp_err.h"
#include "esp_http_server.h"
#include "maze32_health.h"
#ifdef __cplusplus
extern "C" {
#endif
esp_err_t maze32_web_start(httpd_handle_t *server, maze32_health_t *health);
#ifdef __cplusplus
}
#endif
#endif
+118
View File
@@ -0,0 +1,118 @@
#include "maze32_web.h"
#include <stdio.h>
#include "esp_log.h"
#define MAZE32_STATIC_CHUNK_SIZE 1024
static const char *TAG = "maze32_web";
static const char *INDEX_PATH = "/littlefs/index.html.gz";
static esp_err_t send_index(httpd_req_t *request)
{
FILE *file = fopen(INDEX_PATH, "rb");
if (file == NULL) {
ESP_LOGE(TAG, "Static asset is unavailable: %s", INDEX_PATH);
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR,
"Static application is unavailable");
return ESP_FAIL;
}
httpd_resp_set_type(request, "text/html; charset=utf-8");
httpd_resp_set_hdr(request, "Content-Encoding", "gzip");
httpd_resp_set_hdr(request, "Cache-Control", "no-cache");
char buffer[MAZE32_STATIC_CHUNK_SIZE];
size_t bytes_read;
esp_err_t result = ESP_OK;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
result = httpd_resp_send_chunk(request, buffer, bytes_read);
if (result != ESP_OK) {
break;
}
}
if (ferror(file) != 0) {
ESP_LOGE(TAG, "Failed while reading static asset: %s", INDEX_PATH);
result = ESP_FAIL;
}
fclose(file);
if (result == ESP_OK) {
result = httpd_resp_send_chunk(request, NULL, 0);
}
return result;
}
static esp_err_t send_health(httpd_req_t *request)
{
const maze32_health_t *health = request->user_ctx;
char response[192];
int length = snprintf(response, sizeof(response),
"{\"status\":\"%s\",\"healthy\":%s,\"version\":\"%s\",\"errorCode\":%d}",
maze32_health_state_name(health->state),
maze32_health_is_healthy(health) ? "true" : "false",
health->version, health->error_code);
if (length < 0 || (size_t)length >= sizeof(response)) {
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR,
"Health response exceeded its fixed buffer");
return ESP_FAIL;
}
httpd_resp_set_type(request, "application/json");
httpd_resp_set_hdr(request, "Cache-Control", "no-store");
return httpd_resp_send(request, response, length);
}
esp_err_t maze32_web_start(httpd_handle_t *server, maze32_health_t *health)
{
if (server == NULL || health == NULL) {
return ESP_ERR_INVALID_ARG;
}
httpd_config_t configuration = HTTPD_DEFAULT_CONFIG();
configuration.max_uri_handlers = 3;
configuration.max_open_sockets = 7;
configuration.lru_purge_enable = true;
esp_err_t result = httpd_start(server, &configuration);
if (result != ESP_OK) {
return result;
}
const httpd_uri_t root = {
.uri = "/",
.method = HTTP_GET,
.handler = send_index,
.user_ctx = NULL,
};
const httpd_uri_t index = {
.uri = "/index.html",
.method = HTTP_GET,
.handler = send_index,
.user_ctx = NULL,
};
const httpd_uri_t health_uri = {
.uri = "/health",
.method = HTTP_GET,
.handler = send_health,
.user_ctx = health,
};
result = httpd_register_uri_handler(*server, &root);
if (result == ESP_OK) {
result = httpd_register_uri_handler(*server, &index);
}
if (result == ESP_OK) {
result = httpd_register_uri_handler(*server, &health_uri);
}
if (result != ESP_OK) {
httpd_stop(*server);
*server = NULL;
return result;
}
ESP_LOGI(TAG, "HTTP server ready with static and health endpoints");
return ESP_OK;
}