// ========================= // network_api.c // ========================= #include "network_api.h" #include "esp_log.h" #include "cJSON.h" #include "network.h" #include "mqtt.h" #include #include static const char *TAG = "network_api"; static bool mqtt_host_is_invalid(const char *host) { if (!host || host[0] == '\0') return true; if (strcmp(host, "localhost") == 0) return true; if (strcmp(host, "127.0.0.1") == 0) return true; if (strcmp(host, "0.0.0.0") == 0) return true; return false; } typedef struct { bool enabled; char ssid[33]; char password[65]; } wifi_task_data_t; static void wifi_apply_config_task(void *param) { wifi_task_data_t *data = (wifi_task_data_t *)param; ESP_LOGD("wifi_task", "Applying Wi-Fi config in background task"); wifi_set_config(data->enabled, data->ssid, data->password); free(data); vTaskDelete(NULL); } static esp_err_t wifi_get_handler(httpd_req_t *req) { ESP_LOGD(TAG, "Handling GET /api/v1/config/wifi"); httpd_resp_set_type(req, "application/json"); bool enabled = wifi_get_enabled(); char ssid[33] = {0}; char password[65] = {0}; wifi_get_ssid(ssid); wifi_get_password(password); cJSON *json = cJSON_CreateObject(); cJSON_AddBoolToObject(json, "enabled", enabled); cJSON_AddStringToObject(json, "ssid", ssid); cJSON_AddStringToObject(json, "password", password); char *response = cJSON_Print(json); httpd_resp_sendstr(req, response); free(response); cJSON_Delete(json); return ESP_OK; } static esp_err_t wifi_post_handler(httpd_req_t *req) { ESP_LOGD(TAG, "Handling POST /api/v1/config/wifi"); char buf[512]; int len = httpd_req_recv(req, buf, sizeof(buf) - 1); if (len <= 0) return ESP_FAIL; buf[len] = '\0'; cJSON *json = cJSON_Parse(buf); if (!json) return ESP_FAIL; bool enabled = false; const char *ssid = NULL; const char *password = NULL; cJSON *j_enabled = cJSON_GetObjectItem(json, "enabled"); if (cJSON_IsBool(j_enabled)) enabled = j_enabled->valueint; cJSON *j_ssid = cJSON_GetObjectItem(json, "ssid"); if (cJSON_IsString(j_ssid)) ssid = j_ssid->valuestring; cJSON *j_password = cJSON_GetObjectItem(json, "password"); if (cJSON_IsString(j_password)) password = j_password->valuestring; // Resposta imediata httpd_resp_sendstr(req, "Wi-Fi config atualizada com sucesso"); wifi_task_data_t *task_data = (wifi_task_data_t *)malloc(sizeof(wifi_task_data_t)); if (!task_data) { cJSON_Delete(json); ESP_LOGE(TAG, "Memory allocation failed for Wi-Fi task"); return ESP_ERR_NO_MEM; } task_data->enabled = enabled; // Copias seguras (garante null-termination) strncpy(task_data->ssid, ssid ? ssid : "", sizeof(task_data->ssid) - 1); task_data->ssid[sizeof(task_data->ssid) - 1] = '\0'; strncpy(task_data->password, password ? password : "", sizeof(task_data->password) - 1); task_data->password[sizeof(task_data->password) - 1] = '\0'; xTaskCreate( wifi_apply_config_task, "wifi_config_task", 4096, task_data, 3, NULL); cJSON_Delete(json); return ESP_OK; } static esp_err_t config_mqtt_get_handler(httpd_req_t *req) { ESP_LOGD(TAG, "Handling GET /api/v1/config/mqtt"); httpd_resp_set_type(req, "application/json"); bool enabled = mqtt_get_enabled(); char server[64] = {0}; char base_topic[32] = {0}; char username[32] = {0}; char password[64] = {0}; uint16_t periodicity = mqtt_get_periodicity(); mqtt_get_server(server); mqtt_get_base_topic(base_topic); mqtt_get_user(username); mqtt_get_password(password); ESP_LOGD(TAG, "MQTT Config:"); ESP_LOGD(TAG, " Enabled: %s", enabled ? "true" : "false"); ESP_LOGD(TAG, " Server: %s", server); ESP_LOGD(TAG, " Topic: %s", base_topic); ESP_LOGD(TAG, " Username: %s", username); ESP_LOGD(TAG, " Password: %s", password); ESP_LOGD(TAG, " Periodicity: %d", periodicity); cJSON *config = cJSON_CreateObject(); cJSON_AddBoolToObject(config, "enabled", enabled); cJSON_AddStringToObject(config, "host", server); cJSON_AddNumberToObject(config, "port", 1883); // fixo (se não usas no mqtt_set_config) cJSON_AddStringToObject(config, "username", username); cJSON_AddStringToObject(config, "password", password); cJSON_AddStringToObject(config, "topic", base_topic); cJSON_AddNumberToObject(config, "periodicity", periodicity); char *config_str = cJSON_Print(config); httpd_resp_sendstr(req, config_str); free(config_str); cJSON_Delete(config); return ESP_OK; } static esp_err_t config_mqtt_post_handler(httpd_req_t *req) { ESP_LOGD(TAG, "Handling POST /api/v1/config/mqtt"); char buf[512]; int len = httpd_req_recv(req, buf, sizeof(buf) - 1); if (len <= 0) { ESP_LOGE(TAG, "Failed to read request body"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body"); return ESP_FAIL; } buf[len] = '\0'; ESP_LOGD(TAG, "Received JSON: %s", buf); cJSON *json = cJSON_Parse(buf); if (!json) { ESP_LOGE(TAG, "Invalid JSON format"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON"); return ESP_FAIL; } // --- Ler config atual (para permitir "partial update" e evitar strings vazias) bool current_enabled = mqtt_get_enabled(); char current_host[64] = {0}; char current_topic[32] = {0}; char current_user[32] = {0}; char current_pass[64] = {0}; uint16_t current_periodicity = mqtt_get_periodicity(); mqtt_get_server(current_host); mqtt_get_base_topic(current_topic); mqtt_get_user(current_user); mqtt_get_password(current_pass); bool enabled = current_enabled; const char *host_in = NULL, *topic_in = NULL, *user_in = NULL, *pass_in = NULL; int periodicity = (int)current_periodicity; cJSON *j_enabled = cJSON_GetObjectItem(json, "enabled"); if (cJSON_IsBool(j_enabled)) enabled = j_enabled->valueint; cJSON *j_host = cJSON_GetObjectItem(json, "host"); if (cJSON_IsString(j_host)) host_in = j_host->valuestring; cJSON *j_topic = cJSON_GetObjectItem(json, "topic"); if (cJSON_IsString(j_topic)) topic_in = j_topic->valuestring; cJSON *j_user = cJSON_GetObjectItem(json, "username"); if (cJSON_IsString(j_user)) user_in = j_user->valuestring; cJSON *j_pass = cJSON_GetObjectItem(json, "password"); if (cJSON_IsString(j_pass)) pass_in = j_pass->valuestring; cJSON *j_periodicity = cJSON_GetObjectItem(json, "periodicity"); if (cJSON_IsNumber(j_periodicity)) periodicity = j_periodicity->valueint; const char *candidate_host = (host_in && host_in[0] != '\0') ? host_in : (current_host[0] != '\0') ? current_host : "mqtt.plixin.com"; const char *host = mqtt_host_is_invalid(candidate_host) ? "mqtt.plixin.com" : candidate_host; const char *topic = (topic_in && topic_in[0] != '\0') ? topic_in : (current_topic[0] != '\0') ? current_topic : ""; const char *username = (user_in && user_in[0] != '\0') ? user_in : (current_user[0] != '\0') ? current_user : ""; const char *password = (pass_in && pass_in[0] != '\0') ? pass_in : (current_pass[0] != '\0') ? current_pass : ""; if (periodicity <= 0) periodicity = (int)current_periodicity; if (periodicity <= 0) periodicity = 30; ESP_LOGD(TAG, "Applying MQTT config:"); ESP_LOGD(TAG, " Enabled: %s", enabled ? "true" : "false"); ESP_LOGD(TAG, " Host: %s", host); ESP_LOGD(TAG, " Topic: %s", topic); ESP_LOGD(TAG, " Username: %s", username); ESP_LOGD(TAG, " Password: %s", password); ESP_LOGD(TAG, " Periodicity: %d", periodicity); esp_err_t err = mqtt_set_config(enabled, host, topic, username, password, periodicity); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to apply MQTT config (code %d)", err); httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to apply config"); cJSON_Delete(json); return ESP_FAIL; } httpd_resp_sendstr(req, "Configuração MQTT atualizada com sucesso"); cJSON_Delete(json); return ESP_OK; } void register_network_handlers(httpd_handle_t server, void *ctx) { httpd_uri_t wifi_get = { .uri = "/api/v1/config/wifi", .method = HTTP_GET, .handler = wifi_get_handler, .user_ctx = ctx}; httpd_register_uri_handler(server, &wifi_get); httpd_uri_t wifi_post = { .uri = "/api/v1/config/wifi", .method = HTTP_POST, .handler = wifi_post_handler, .user_ctx = ctx}; httpd_register_uri_handler(server, &wifi_post); httpd_uri_t config_mqtt_get_uri = { .uri = "/api/v1/config/mqtt", .method = HTTP_GET, .handler = config_mqtt_get_handler, .user_ctx = ctx}; httpd_register_uri_handler(server, &config_mqtt_get_uri); httpd_uri_t config_mqtt_post_uri = { .uri = "/api/v1/config/mqtt", .method = HTTP_POST, .handler = config_mqtt_post_handler, .user_ctx = ctx}; httpd_register_uri_handler(server, &config_mqtt_post_uri); }