Refactor rest server

This commit is contained in:
2025-06-07 11:40:44 +01:00
parent 5577d590bd
commit 18911c5f1f
247 changed files with 620 additions and 116 deletions

0
components/protocols/include/modbus_tcp.h Normal file → Executable file
View File

View File

@@ -37,6 +37,23 @@ typedef struct rest_server_context {
#define CHECK_FILE_EXTENSION(filename, ext) (strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
// Estruturas para armazenar as configurações
static struct {
bool enabled;
char ssid[128];
char password[128];
} wifi_config = {false, "", ""};
static struct {
bool enabled;
char host[256];
int port;
char username[128];
char password[128];
char topic[128];
} mqtt_config = {false, "", 1883, "", "", ""};
/* Set HTTP response content type according to file extension */
static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filepath)
{
@@ -107,110 +124,584 @@ static esp_err_t rest_common_get_handler(httpd_req_t *req)
return ESP_OK;
}
/* Simple handler for light brightness control */
static esp_err_t light_brightness_post_handler(httpd_req_t *req)
// Manipulador para o endpoint GET /api/v1/config/electrical
static esp_err_t electrical_config_get_handler(httpd_req_t *req)
{
int total_len = req->content_len;
int cur_len = 0;
char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;
int received = 0;
if (total_len >= SCRATCH_BUFSIZE) {
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com as configurações de rede elétrica
cJSON *config = cJSON_CreateObject();
cJSON *monitor = cJSON_CreateObject();
cJSON_AddStringToObject(monitor, "voltage", "230");
cJSON_AddStringToObject(monitor, "current", "10");
cJSON_AddStringToObject(monitor, "quality", "1");
cJSON_AddItemToObject(config, "monitor", monitor);
cJSON_AddBoolToObject(config, "alerts", true);
// Adicionar mais configurações (security, loadBalancing, solar) no objeto config
// ...
// Enviar a resposta
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str);
// Liberar memória
free((void *)config_str);
cJSON_Delete(config);
return ESP_OK;
}
// Manipulador para o endpoint POST /api/v1/config/electrical
static esp_err_t electrical_config_post_handler(httpd_req_t *req)
{
char buf[512];
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
if (len <= 0) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Request body is empty");
return ESP_FAIL;
}
while (cur_len < total_len) {
received = httpd_req_recv(req, buf + cur_len, total_len);
if (received <= 0) {
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
return ESP_FAIL;
}
cur_len += received;
buf[len] = '\0'; // Garantir que a string esteja terminada
// Parse JSON recebido
cJSON *json = cJSON_Parse(buf);
if (json == NULL) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
buf[total_len] = '\0';
cJSON *root = cJSON_Parse(buf);
int red = cJSON_GetObjectItem(root, "red")->valueint;
int green = cJSON_GetObjectItem(root, "green")->valueint;
int blue = cJSON_GetObjectItem(root, "blue")->valueint;
ESP_LOGI(REST_TAG, "Light control: red = %d, green = %d, blue = %d", red, green, blue);
cJSON_Delete(root);
httpd_resp_sendstr(req, "Post control value successfully");
// Processar os dados recebidos e atualizar as configurações (monitor, alerts, etc.)
// Exemplo de configuração:
cJSON *monitor = cJSON_GetObjectItem(json, "monitor");
if (monitor) {
// Atualizar configurações do monitor
// ...
}
// Atualizar outras configurações...
// Responder com sucesso
httpd_resp_sendstr(req, "Configuração gravada com sucesso!");
cJSON_Delete(json);
return ESP_OK;
}
/* Simple handler for getting system handler */
static esp_err_t system_info_get_handler(httpd_req_t *req)
// Manipulador para o endpoint /api/v1/config/load-balancing
static esp_err_t config_load_balancing_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
cJSON *root = cJSON_CreateObject();
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
cJSON_AddStringToObject(root, "version", IDF_VER);
cJSON_AddNumberToObject(root, "cores", chip_info.cores);
const char *sys_info = cJSON_Print(root);
httpd_resp_sendstr(req, sys_info);
free((void *)sys_info);
cJSON_Delete(root);
// Criar objeto JSON de configuração
cJSON *config = cJSON_CreateObject();
// Configuração de load balancing
cJSON_AddBoolToObject(config, "enabled", true); // Exemplo: load balancing ativado
cJSON_AddNumberToObject(config, "maxChargingCurrent", 32); // Exemplo: corrente máxima de 32A
// Lista de dispositivos disponíveis
cJSON *devices = cJSON_CreateArray();
cJSON_AddItemToArray(devices, cJSON_CreateString("Device 1")); // Exemplo de dispositivo
cJSON_AddItemToArray(devices, cJSON_CreateString("Device 2")); // Outro exemplo de dispositivo
cJSON_AddItemToObject(config, "devices", devices);
// Convertendo para string e enviando a resposta
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str);
// Liberando a memória
free((void *)config_str);
cJSON_Delete(config);
return ESP_OK;
}
/* Simple handler for getting temperature data */
static esp_err_t temperature_data_get_handler(httpd_req_t *req)
// Estrutura para armazenar as configurações OCPP em memória
static struct {
char url[256];
char chargeBoxId[128];
char certificate[256];
char privateKey[256];
} ocpp_config = {"", "", "", ""};
// Manipulador para o endpoint GET /api/v1/ocpp (Status do OCPP)
static esp_err_t ocpp_status_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
cJSON *root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "raw", esp_random() % 20);
const char *sys_info = cJSON_Print(root);
httpd_resp_sendstr(req, sys_info);
free((void *)sys_info);
cJSON_Delete(root);
// Criar objeto JSON de status
cJSON *status = cJSON_CreateObject();
cJSON_AddStringToObject(status, "status", "connected"); // Status de exemplo, você pode adaptar conforme sua lógica
// Convertendo para string e enviando a resposta
const char *status_str = cJSON_Print(status);
httpd_resp_sendstr(req, status_str);
// Liberando a memória
free((void *)status_str);
cJSON_Delete(status);
return ESP_OK;
}
// Manipulador para o endpoint GET /api/v1/config/ocpp (Configuração OCPP)
static esp_err_t config_ocpp_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com as configurações do OCPP
cJSON *config = cJSON_CreateObject();
cJSON_AddStringToObject(config, "url", ocpp_config.url);
cJSON_AddStringToObject(config, "chargeBoxId", ocpp_config.chargeBoxId);
cJSON_AddStringToObject(config, "certificate", ocpp_config.certificate);
cJSON_AddStringToObject(config, "privateKey", ocpp_config.privateKey);
// Convertendo para string e enviando a resposta
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str);
// Liberando a memória
free((void *)config_str);
cJSON_Delete(config);
return ESP_OK;
}
// Manipulador para o endpoint POST /api/v1/config/ocpp (Salvar configuração OCPP)
static esp_err_t config_ocpp_post_handler(httpd_req_t *req)
{
char buf[512]; // Buffer para armazenar a requisição
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
if (len <= 0) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
return ESP_FAIL;
}
buf[len] = '\0'; // Garantir que a string esteja terminada
// Parse JSON recebido
cJSON *json = cJSON_Parse(buf);
if (json == NULL) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
// Atualizando as configurações OCPP
cJSON *url = cJSON_GetObjectItem(json, "url");
if (url) strlcpy(ocpp_config.url, url->valuestring, sizeof(ocpp_config.url));
cJSON *chargeBoxId = cJSON_GetObjectItem(json, "chargeBoxId");
if (chargeBoxId) strlcpy(ocpp_config.chargeBoxId, chargeBoxId->valuestring, sizeof(ocpp_config.chargeBoxId));
cJSON *certificate = cJSON_GetObjectItem(json, "certificate");
if (certificate) strlcpy(ocpp_config.certificate, certificate->valuestring, sizeof(ocpp_config.certificate));
cJSON *privateKey = cJSON_GetObjectItem(json, "privateKey");
if (privateKey) strlcpy(ocpp_config.privateKey, privateKey->valuestring, sizeof(ocpp_config.privateKey));
cJSON_Delete(json);
// Responder com uma mensagem de sucesso
httpd_resp_sendstr(req, "Configuração OCPP atualizada com sucesso");
return ESP_OK;
}
// Estrutura para armazenar as configurações
static struct {
int currentLimit;
int powerLimit;
int energyLimit;
int chargingTimeLimit;
int temperatureLimit;
} settings_config = {32, 0, 0, 0, 60};
// Manipulador para o endpoint POST /api/v1/config/settings
static esp_err_t config_settings_post_handler(httpd_req_t *req)
{
char buf[512]; // Buffer para armazenar a requisição
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
if (len <= 0) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
return ESP_FAIL;
}
buf[len] = '\0'; // Garantir que a string esteja terminada
// Parse JSON recebido
cJSON *json = cJSON_Parse(buf);
if (json == NULL) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
// Atualizando as configurações
cJSON *currentLimit = cJSON_GetObjectItem(json, "currentLimit");
if (currentLimit) settings_config.currentLimit = currentLimit->valueint;
cJSON *powerLimit = cJSON_GetObjectItem(json, "powerLimit");
if (powerLimit) settings_config.powerLimit = powerLimit->valueint;
cJSON *energyLimit = cJSON_GetObjectItem(json, "energyLimit");
if (energyLimit) settings_config.energyLimit = energyLimit->valueint;
cJSON *chargingTimeLimit = cJSON_GetObjectItem(json, "chargingTimeLimit");
if (chargingTimeLimit) settings_config.chargingTimeLimit = chargingTimeLimit->valueint;
cJSON *temperatureLimit = cJSON_GetObjectItem(json, "temperatureLimit");
if (temperatureLimit) settings_config.temperatureLimit = temperatureLimit->valueint;
cJSON_Delete(json);
// Responder com uma mensagem de sucesso
httpd_resp_sendstr(req, "Configurações de energia atualizadas com sucesso");
return ESP_OK;
}
// Manipulador para o endpoint GET /api/v1/config/settings
static esp_err_t config_settings_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON para enviar as configurações atuais
cJSON *config = cJSON_CreateObject();
cJSON_AddNumberToObject(config, "currentLimit", settings_config.currentLimit);
cJSON_AddNumberToObject(config, "powerLimit", settings_config.powerLimit);
cJSON_AddNumberToObject(config, "energyLimit", settings_config.energyLimit);
cJSON_AddNumberToObject(config, "chargingTimeLimit", settings_config.chargingTimeLimit);
cJSON_AddNumberToObject(config, "temperatureLimit", settings_config.temperatureLimit);
// Convertendo para string e enviando a resposta
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str);
// Liberando a memória
free((void *)config_str);
cJSON_Delete(config);
return ESP_OK;
}
// Manipulador para o endpoint GET /api/v1/dashboard
static esp_err_t dashboard_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com os dados do Dashboard
cJSON *dashboard = cJSON_CreateObject();
// Status do sistema
cJSON_AddStringToObject(dashboard, "status", "Ativo");
// Carregadores (exemplo)
cJSON *chargers = cJSON_CreateArray();
cJSON *charger1 = cJSON_CreateObject();
cJSON_AddNumberToObject(charger1, "id", 1);
cJSON_AddStringToObject(charger1, "status", "Ativo");
cJSON_AddNumberToObject(charger1, "current", 12);
cJSON_AddNumberToObject(charger1, "power", 2200);
cJSON_AddItemToArray(chargers, charger1);
cJSON_AddItemToObject(dashboard, "chargers", chargers);
// Consumo de energia
cJSON_AddNumberToObject(dashboard, "energyConsumed", 50.3);
// Tempo de carregamento
cJSON_AddNumberToObject(dashboard, "chargingTime", 120);
// Alertas
cJSON *alerts = cJSON_CreateArray();
cJSON_AddItemToArray(alerts, cJSON_CreateString("Aviso: Carregador 1 está com erro."));
cJSON_AddItemToObject(dashboard, "alerts", alerts);
// Convertendo para string e enviando a resposta
const char *dashboard_str = cJSON_Print(dashboard);
httpd_resp_sendstr(req, dashboard_str);
// Liberando a memória
free((void *)dashboard_str);
cJSON_Delete(dashboard);
return ESP_OK;
}
static esp_err_t config_wifi_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com as configurações de Wi-Fi
cJSON *config = cJSON_CreateObject();
cJSON_AddBoolToObject(config, "enabled", wifi_config.enabled);
cJSON_AddStringToObject(config, "ssid", wifi_config.ssid);
cJSON_AddStringToObject(config, "password", wifi_config.password);
// Convertendo para string e enviando a resposta
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str);
// Liberando a memória
free((void *)config_str);
cJSON_Delete(config);
return ESP_OK;
}
static esp_err_t config_wifi_post_handler(httpd_req_t *req)
{
char buf[256]; // Buffer para armazenar a requisição
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
if (len <= 0) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
return ESP_FAIL;
}
buf[len] = '\0'; // Garantir que a string esteja terminada
// Parse JSON recebido
cJSON *json = cJSON_Parse(buf);
if (json == NULL) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
// Atualizando as configurações Wi-Fi
cJSON *enabled = cJSON_GetObjectItem(json, "enabled");
if (enabled) wifi_config.enabled = enabled->valueint;
cJSON *ssid = cJSON_GetObjectItem(json, "ssid");
if (ssid) strlcpy(wifi_config.ssid, ssid->valuestring, sizeof(wifi_config.ssid));
cJSON *password = cJSON_GetObjectItem(json, "password");
if (password) strlcpy(wifi_config.password, password->valuestring, sizeof(wifi_config.password));
cJSON_Delete(json);
// Responder com uma mensagem de sucesso
httpd_resp_sendstr(req, "Configuração Wi-Fi atualizada com sucesso");
return ESP_OK;
}
static esp_err_t config_mqtt_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com as configurações de MQTT
cJSON *config = cJSON_CreateObject();
cJSON_AddBoolToObject(config, "enabled", mqtt_config.enabled);
cJSON_AddStringToObject(config, "host", mqtt_config.host);
cJSON_AddNumberToObject(config, "port", mqtt_config.port);
cJSON_AddStringToObject(config, "username", mqtt_config.username);
cJSON_AddStringToObject(config, "password", mqtt_config.password);
cJSON_AddStringToObject(config, "topic", mqtt_config.topic);
// Convertendo para string e enviando a resposta
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str);
// Liberando a memória
free((void *)config_str);
cJSON_Delete(config);
return ESP_OK;
}
static esp_err_t config_mqtt_post_handler(httpd_req_t *req)
{
char buf[512]; // Buffer para armazenar a requisição
int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
if (len <= 0) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
return ESP_FAIL;
}
buf[len] = '\0'; // Garantir que a string esteja terminada
// Parse JSON recebido
cJSON *json = cJSON_Parse(buf);
if (json == NULL) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
// Atualizando as configurações MQTT
cJSON *enabled = cJSON_GetObjectItem(json, "enabled");
if (enabled) mqtt_config.enabled = enabled->valueint;
cJSON *host = cJSON_GetObjectItem(json, "host");
if (host) strlcpy(mqtt_config.host, host->valuestring, sizeof(mqtt_config.host));
cJSON *port = cJSON_GetObjectItem(json, "port");
if (port) mqtt_config.port = port->valueint;
cJSON *username = cJSON_GetObjectItem(json, "username");
if (username) strlcpy(mqtt_config.username, username->valuestring, sizeof(mqtt_config.username));
cJSON *password = cJSON_GetObjectItem(json, "password");
if (password) strlcpy(mqtt_config.password, password->valuestring, sizeof(mqtt_config.password));
cJSON *topic = cJSON_GetObjectItem(json, "topic");
if (topic) strlcpy(mqtt_config.topic, topic->valuestring, sizeof(mqtt_config.topic));
cJSON_Delete(json);
// Responder com uma mensagem de sucesso
httpd_resp_sendstr(req, "Configuração MQTT atualizada com sucesso");
return ESP_OK;
}
esp_err_t rest_init(const char *base_path)
{
REST_CHECK(base_path, "wrong base path", err);
rest_server_context_t *rest_context = calloc(1, sizeof(rest_server_context_t));
REST_CHECK(rest_context, "No memory for rest context", err);
REST_CHECK(rest_context, "No memory for rest context", err_start);
strlcpy(rest_context->base_path, base_path, sizeof(rest_context->base_path));
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.max_uri_handlers = 20; // Ajuste conforme necessário
config.uri_match_fn = httpd_uri_match_wildcard;
ESP_LOGI(REST_TAG, "Starting HTTP Server");
REST_CHECK(httpd_start(&server, &config) == ESP_OK, "Start server failed", err_start);
/* URI handler for fetching system info */
httpd_uri_t system_info_get_uri = {
.uri = "/api/v1/system/info",
/* URI handler for getting load balancing config */
httpd_uri_t config_load_balancing_get_uri = {
.uri = "/api/v1/config/load-balancing",
.method = HTTP_GET,
.handler = system_info_get_handler,
.handler = config_load_balancing_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &system_info_get_uri);
httpd_register_uri_handler(server, &config_load_balancing_get_uri);
/* URI handler for fetching temperature data */
httpd_uri_t temperature_data_get_uri = {
.uri = "/api/v1/temp/raw",
// URI handler for fetching OCPP status
httpd_uri_t ocpp_status_get_uri = {
.uri = "/api/v1/ocpp",
.method = HTTP_GET,
.handler = temperature_data_get_handler,
.handler = ocpp_status_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &temperature_data_get_uri);
httpd_register_uri_handler(server, &ocpp_status_get_uri);
/* URI handler for light brightness control */
httpd_uri_t light_brightness_post_uri = {
.uri = "/api/v1/light/brightness",
// URI handler for fetching OCPP config
httpd_uri_t config_ocpp_get_uri = {
.uri = "/api/v1/config/ocpp",
.method = HTTP_GET,
.handler = config_ocpp_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_ocpp_get_uri);
// URI handler for posting OCPP config
httpd_uri_t config_ocpp_post_uri = {
.uri = "/api/v1/config/ocpp",
.method = HTTP_POST,
.handler = light_brightness_post_handler,
.handler = config_ocpp_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &light_brightness_post_uri);
httpd_register_uri_handler(server, &config_ocpp_post_uri);
/* URI handler for getting web server files */
// Manipulador para o endpoint POST /api/v1/config/settings
httpd_uri_t config_settings_post_uri = {
.uri = "/api/v1/config/settings",
.method = HTTP_POST,
.handler = config_settings_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_settings_post_uri);
// Manipulador para o endpoint GET /api/v1/config/settings
httpd_uri_t config_settings_get_uri = {
.uri = "/api/v1/config/settings",
.method = HTTP_GET,
.handler = config_settings_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_settings_get_uri);
// Manipulador para o endpoint GET /api/v1/dashboard
httpd_uri_t dashboard_get_uri = {
.uri = "/api/v1/dashboard",
.method = HTTP_GET,
.handler = dashboard_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &dashboard_get_uri);
/* Register URI Handlers */
httpd_uri_t electrical_config_get_uri = {
.uri = "/api/v1/config/electrical",
.method = HTTP_GET,
.handler = electrical_config_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &electrical_config_get_uri);
httpd_uri_t electrical_config_post_uri = {
.uri = "/api/v1/config/electrical",
.method = HTTP_POST,
.handler = electrical_config_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &electrical_config_post_uri);
// URI handler for getting Wi-Fi config
httpd_uri_t config_wifi_get_uri = {
.uri = "/api/v1/config/wifi",
.method = HTTP_GET,
.handler = config_wifi_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_wifi_get_uri);
// URI handler for posting Wi-Fi config
httpd_uri_t config_wifi_post_uri = {
.uri = "/api/v1/config/wifi",
.method = HTTP_POST,
.handler = config_wifi_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_wifi_post_uri);
// URI handler for getting MQTT config
httpd_uri_t config_mqtt_get_uri = {
.uri = "/api/v1/config/mqtt",
.method = HTTP_GET,
.handler = config_mqtt_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_mqtt_get_uri);
// URI handler for posting MQTT config
httpd_uri_t config_mqtt_post_uri = {
.uri = "/api/v1/config/mqtt",
.method = HTTP_POST,
.handler = config_mqtt_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_mqtt_post_uri);
/* URI handler for getting web server files */
httpd_uri_t common_get_uri = {
.uri = "/*",
.method = HTTP_GET,
@@ -219,9 +710,11 @@ esp_err_t rest_init(const char *base_path)
};
httpd_register_uri_handler(server, &common_get_uri);
return ESP_OK;
err_start:
free(rest_context);
err:
return ESP_FAIL;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,12 +4,20 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<!-- <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet"> -->
<!-- Remover link para tailwind.min.css -->
<!-- <link href="/tailwind.min.css" rel="stylesheet"> -->
<style>
body {
font-family: 'Arial', 'Helvetica', 'sans-serif'; /* Usando fontes genéricas do sistema */
}
</style>
<title>Vite + React</title>
<script type="module" crossorigin src="/assets/index-FEzsI7yf.js"></script>
<script type="module" crossorigin src="/assets/index-Ciq1ghIH.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DYy5HJdF.css">
</head>
<body>
<div id="root"></div>
<!-- Adicionar o link para o seu arquivo CSS com o Tailwind configurado -->
</body>
</html>