fix ade7758

This commit is contained in:
2025-06-25 06:34:03 +01:00
parent a0b2e048d4
commit 84f106eee5
53 changed files with 7079 additions and 18456 deletions

View File

@@ -1,6 +1,5 @@
set(srcs
"src/protocols.c"
"src/rest.c"
"src/mqtt.c"
"src/date_time.c"
)

View File

@@ -1,14 +0,0 @@
#ifndef REST_H_
#define REST_H_
#include "esp_err.h"
/**
* @brief Initialize REST server
*
* @param base_path Path on the SPIFFS filesystem where static files reside
* @return ESP_OK on success, ESP_FAIL otherwise
*/
esp_err_t rest_init(const char *base_path);
#endif /* REST_H_ */

View File

@@ -31,31 +31,31 @@ static esp_err_t open_mqtt_nvs(nvs_handle_t *handle) {
static void subcribe_topics(void)
{
ESP_LOGI(TAG, "subcribe_topics");
ESP_LOGI(TAG, "[MQTT] Subscribing to topics");
char base[32];
mqtt_get_base_topic(base);
char topic[64];
mqtt_get_base_topic(topic);
strcat(topic, "/request/#");
snprintf(topic, sizeof(topic), "%s/request/#", base);
esp_mqtt_client_subscribe(client, topic, 0);
ESP_LOGI(TAG, "subscribed: %s", topic);
ESP_LOGI(TAG, " subscribed: %s", topic);
mqtt_get_base_topic(topic);
strcat(topic, "/set/config/#");
snprintf(topic, sizeof(topic), "%s/set/config/#", base);
esp_mqtt_client_subscribe(client, topic, 0);
ESP_LOGI(TAG, "subscribed: %s", topic);
ESP_LOGI(TAG, " subscribed: %s", topic);
mqtt_get_base_topic(topic);
strcat(topic, "/enable");
snprintf(topic, sizeof(topic), "%s/enable", base);
esp_mqtt_client_subscribe(client, topic, 0);
ESP_LOGI(TAG, "subscribed: %s", topic);
ESP_LOGI(TAG, " subscribed: %s", topic);
}
static void publish_message(const char* topic, cJSON* root)
{
char target_topic[64];
mqtt_get_base_topic(target_topic);
strcat(target_topic, topic);
strncat(target_topic, topic, sizeof(target_topic) - strlen(target_topic) - 1);
const char* json = cJSON_PrintUnformatted(root);
esp_mqtt_client_publish(client, target_topic, json, 0, 1, 0);
@@ -67,34 +67,51 @@ static void handle_message(const char* topic, const char* data)
char base_topic[32];
mqtt_get_base_topic(base_topic);
ESP_LOGI(TAG, "[MQTT] Message received");
ESP_LOGI(TAG, " > Topic: %s", topic);
ESP_LOGI(TAG, " > Payload: %s", data);
if (strncmp(topic, base_topic, strlen(base_topic)) == 0) {
const char* sub_topic = &topic[strlen(base_topic)];
ESP_LOGI(TAG, " > Subtopic detected: %s", sub_topic);
if (strcmp(sub_topic, "/request/config/evse") == 0) {
ESP_LOGI(TAG, " → Responding with EVSE configuration");
cJSON* root = json_get_evse_config();
publish_message("/response/config/evse", root);
cJSON_Delete(root);
} else {
ESP_LOGW(TAG, " ! Unknown command: %s", sub_topic);
}
// [Outros comandos omitidos para brevidade...]
} else {
ESP_LOGW(TAG, " ! Topic does not match base: %s", topic);
}
}
static void event_handler(void* handler_args, esp_event_base_t base, int32_t event_id, void* event_data)
{
esp_mqtt_event_handle_t event = event_data;
char topic[48], data[256];
switch (event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT conectado");
ESP_LOGI(TAG, "[MQTT] Connected to broker");
if (client_task) vTaskResume(client_task);
subcribe_topics();
break;
case MQTT_EVENT_DATA:
strncpy(topic, event->topic, MIN(event->topic_len, sizeof(topic)-1));
strncpy(data, event->data, MIN(event->data_len, sizeof(data)-1));
case MQTT_EVENT_DATA: {
char topic[64] = {0};
char data[256] = {0};
int tlen = MIN(event->topic_len, sizeof(topic) - 1);
int dlen = MIN(event->data_len, sizeof(data) - 1);
memcpy(topic, event->topic, tlen);
memcpy(data, event->data, dlen);
handle_message(topic, data);
break;
}
default:
break;
}
@@ -257,4 +274,4 @@ void mqtt_get_password(char* value)
uint16_t mqtt_get_periodicity(void)
{
return periodicity;
}
}

View File

@@ -1,907 +0,0 @@
/* HTTP Restful API Server
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <fcntl.h>
#include "esp_http_server.h"
#include "esp_chip_info.h"
#include "esp_random.h"
#include "esp_log.h"
#include "esp_vfs.h"
#include "cJSON.h"
#include "rest.h"
#include "evse_api.h"
#include "cJSON.h"
#include "esp_log.h"
#include "esp_http_server.h"
#include "auth.h"
static const char *REST_TAG = "esp-rest";
#define REST_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(REST_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
#define SCRATCH_BUFSIZE (10240)
typedef struct rest_server_context {
char base_path[ESP_VFS_PATH_MAX + 1];
char scratch[SCRATCH_BUFSIZE];
} rest_server_context_t;
#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, "", "", ""};
// 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 = {"", "", "", ""};
// Estrutura para armazenar as configurações de energia
static struct {
int currentLimit;
int powerLimit;
int energyLimit;
int chargingTimeLimit;
int temperatureLimit;
} settings_config = {0, 0, 0, 0, 0};
static struct {
char username[128];
} users[10] = {{"admin"}, {"user1"}};
static int num_users = 2; // Contador de usuários cadastrados
// 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)
{
const char *type = "text/plain";
if (CHECK_FILE_EXTENSION(filepath, ".html")) {
type = "text/html";
} else if (CHECK_FILE_EXTENSION(filepath, ".js")) {
type = "application/javascript";
} else if (CHECK_FILE_EXTENSION(filepath, ".css")) {
type = "text/css";
} else if (CHECK_FILE_EXTENSION(filepath, ".png")) {
type = "image/png";
} else if (CHECK_FILE_EXTENSION(filepath, ".ico")) {
type = "image/x-icon";
} else if (CHECK_FILE_EXTENSION(filepath, ".svg")) {
type = "text/xml";
}
return httpd_resp_set_type(req, type);
}
/* Send HTTP response with the contents of the requested file */
static esp_err_t rest_common_get_handler(httpd_req_t *req)
{
char filepath[FILE_PATH_MAX];
rest_server_context_t *rest_context = (rest_server_context_t *)req->user_ctx;
strlcpy(filepath, rest_context->base_path, sizeof(filepath));
if (req->uri[strlen(req->uri) - 1] == '/') {
strlcat(filepath, "/index.html", sizeof(filepath));
} else {
strlcat(filepath, req->uri, sizeof(filepath));
}
int fd = open(filepath, O_RDONLY, 0);
if (fd == -1) {
ESP_LOGW(REST_TAG, "Failed to open file : %s, redirecting to index", filepath);
/* Try to serve index.html for SPA routing */
strlcpy(filepath, rest_context->base_path, sizeof(filepath));
strlcat(filepath, "/index.html", sizeof(filepath));
fd = open(filepath, O_RDONLY, 0);
if (fd == -1) {
ESP_LOGE(REST_TAG, "Failed to open index file : %s", filepath);
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found");
return ESP_FAIL;
}
}
set_content_type_from_file(req, filepath);
char *chunk = rest_context->scratch;
ssize_t read_bytes;
do {
/* Read file in chunks into the scratch buffer */
read_bytes = read(fd, chunk, SCRATCH_BUFSIZE);
if (read_bytes == -1) {
ESP_LOGE(REST_TAG, "Failed to read file : %s", filepath);
} else if (read_bytes > 0) {
/* Send the buffer contents as HTTP response chunk */
if (httpd_resp_send_chunk(req, chunk, read_bytes) != ESP_OK) {
close(fd);
ESP_LOGE(REST_TAG, "File sending failed!");
/* Abort sending file */
httpd_resp_sendstr_chunk(req, NULL);
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
return ESP_FAIL;
}
}
} while (read_bytes > 0);
/* Close file after sending complete */
close(fd);
ESP_LOGI(REST_TAG, "File sending complete");
/* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;
}
// Manipulador para o endpoint GET /api/v1/config/electrical
static esp_err_t electrical_config_get_handler(httpd_req_t *req)
{
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;
}
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;
}
// 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;
}
// 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");
// 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;
}
// 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");
// 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;
}
// 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)
evse_set_max_charging_current(currentLimit->valueint);
//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)
evse_set_temp_threshold(temperatureLimit->valueint);
//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, "maxCurrentLimit", evse_get_max_charging_current());
cJSON_AddNumberToObject(config, "currentLimit", evse_get_max_charging_current());
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", evse_get_temp_threshold());
// 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;
}
/* Manipulador para o endpoint POST /api/v1/config/wifi */
static esp_err_t config_wifi_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 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;
}
/* Manipulador para o endpoint GET /api/v1/config/mqtt */
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;
}
/* Manipulador para o endpoint POST /api/v1/config/mqtt */
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;
}
// GET /api/v1/config/auth-methods
static esp_err_t config_auth_methods_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
cJSON *config = cJSON_CreateObject();
cJSON_AddBoolToObject(config, "RFID", auth_is_enabled());
cJSON_AddBoolToObject(config, "App", false);
cJSON_AddBoolToObject(config, "Password", false);
char *config_str = cJSON_PrintUnformatted(config);
httpd_resp_sendstr(req, config_str);
free(config_str);
cJSON_Delete(config);
return ESP_OK;
}
// POST /api/v1/config/auth-methods
static esp_err_t config_auth_methods_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, "Invalid request body");
return ESP_FAIL;
}
buf[len] = '\0';
cJSON *json = cJSON_Parse(buf);
if (!json) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL;
}
cJSON *RFID = cJSON_GetObjectItem(json, "RFID");
if (cJSON_IsBool(RFID)) {
auth_set_enabled(cJSON_IsTrue(RFID));
}
/*
cJSON *App = cJSON_GetObjectItem(json, "App");
if (cJSON_IsBool(App)) {
auth_methods.App = cJSON_IsTrue(App);
}
cJSON *Password = cJSON_GetObjectItem(json, "Password");
if (cJSON_IsBool(Password)) {
auth_methods.Password = cJSON_IsTrue(Password);
}*/
cJSON_Delete(json);
httpd_resp_sendstr(req, "Configurações de autenticação atualizadas com sucesso");
return ESP_OK;
}
// Manipulador para o endpoint GET /api/v1/config/users
static esp_err_t config_users_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com a lista de usuários
cJSON *config = cJSON_CreateObject();
cJSON *users_list = cJSON_CreateArray();
for (int i = 0; i < num_users; i++) {
cJSON *user = cJSON_CreateObject();
cJSON_AddStringToObject(user, "username", users[i].username);
cJSON_AddItemToArray(users_list, user);
}
cJSON_AddItemToObject(config, "users", users_list);
// 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/users
static esp_err_t config_users_post_handler(httpd_req_t *req)
{
char buf[128]; // Buffer para armazenar o nome do novo usuário
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
// Adicionar o novo usuário
if (num_users < 10) {
strlcpy(users[num_users].username, buf, sizeof(users[num_users].username));
num_users++;
httpd_resp_sendstr(req, "Usuário adicionado com sucesso");
} else {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Máximo de usuários atingido");
}
return ESP_OK;
}
// Manipulador para o endpoint DELETE /api/v1/config/users/{username}
static esp_err_t config_users_delete_handler(httpd_req_t *req)
{
char username[128]; // Nome do usuário a ser removido
if (httpd_req_get_url_query_str(req, username, sizeof(username)) == ESP_OK) {
// Verificar e remover o usuário
for (int i = 0; i < num_users; i++) {
if (strcmp(users[i].username, username) == 0) {
// Remover o usuário
for (int j = i; j < num_users - 1; j++) {
users[j] = users[j + 1];
}
num_users--;
httpd_resp_sendstr(req, "Usuário removido com sucesso");
return ESP_OK;
}
}
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Usuário não encontrado");
}
return ESP_FAIL;
}
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_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 = 30; // 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);
// Registrar manipuladores de URI para as configurações
httpd_uri_t config_load_balancing_get_uri = {
.uri = "/api/v1/config/load-balancing",
.method = HTTP_GET,
.handler = config_load_balancing_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_load_balancing_get_uri);
// URI handler for fetching OCPP status
httpd_uri_t ocpp_status_get_uri = {
.uri = "/api/v1/ocpp",
.method = HTTP_GET,
.handler = ocpp_status_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &ocpp_status_get_uri);
// 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 = config_ocpp_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_ocpp_post_uri);
// 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 for electrical configuration
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);
// Registrar manipuladores para as configurações de autenticação
httpd_uri_t config_auth_methods_get_uri = {
.uri = "/api/v1/config/auth-methods",
.method = HTTP_GET,
.handler = config_auth_methods_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_auth_methods_get_uri);
httpd_uri_t config_auth_methods_post_uri = {
.uri = "/api/v1/config/auth-methods",
.method = HTTP_POST,
.handler = config_auth_methods_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_auth_methods_post_uri);
// Registrar manipuladores para as configurações de usuários
httpd_uri_t config_users_get_uri = {
.uri = "/api/v1/config/users",
.method = HTTP_GET,
.handler = config_users_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_users_get_uri);
httpd_uri_t config_users_post_uri = {
.uri = "/api/v1/config/users",
.method = HTTP_POST,
.handler = config_users_post_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_users_post_uri);
httpd_uri_t config_users_delete_uri = {
.uri = "/api/v1/config/users",
.method = HTTP_DELETE,
.handler = config_users_delete_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &config_users_delete_uri);
// URI handler for getting web server files
httpd_uri_t common_get_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = rest_common_get_handler,
.user_ctx = rest_context
};
httpd_register_uri_handler(server, &common_get_uri);
*/
return ESP_OK;
}