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

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;
}
}