|
|
@@ -14,11 +14,20 @@
|
|
|
#include "sdmmc_cmd.h"
|
|
|
#include "ssd1306.h"
|
|
|
#include <driver/i2c_master.h>
|
|
|
+#include "math.h"
|
|
|
+#include "string.h"
|
|
|
+#include "esp_wifi.h"
|
|
|
+#include "esp_netif.h"
|
|
|
+#include "esp_event.h"
|
|
|
+#include "esp_http_server.h"
|
|
|
+#include "lwip/inet.h"
|
|
|
+#include "sys/stat.h"
|
|
|
|
|
|
const char *DHT_TAG = "DHT22";
|
|
|
const char *GPS_TAG = "GPS_PARSER";
|
|
|
const char *SD_TAG = "SD_CARD";
|
|
|
const char *OLED_TAG = "SSD1306OLED";
|
|
|
+const char *GEN_TAG = "General";
|
|
|
|
|
|
#define MOUNT_POINT "/sdcard"
|
|
|
|
|
|
@@ -30,12 +39,17 @@ const char *OLED_TAG = "SSD1306OLED";
|
|
|
#define PIN_NUM_SDA CONFIG_PIN_SDA
|
|
|
#define PIN_NUM_SCL CONFIG_PIN_SCL
|
|
|
|
|
|
+#define PIN_TX GPIO_NUM_17
|
|
|
+#define PIN_RX GPIO_NUM_16
|
|
|
+
|
|
|
//definicion de tiempos de pulsacion
|
|
|
#define PULSACION_LARGA_MS 2000
|
|
|
#define DURACION_WATCHDOG_MS 10000
|
|
|
|
|
|
#define MEASUREMENT_INTERVAL_S 1
|
|
|
|
|
|
+#define DEG2RAD (M_PI/180.0)
|
|
|
+
|
|
|
const int uart_buffer_size = (1024 * 2);
|
|
|
int length = 0;
|
|
|
|
|
|
@@ -43,18 +57,20 @@ uint8_t data;
|
|
|
|
|
|
static gps_parser_t gps;
|
|
|
|
|
|
-void uart_configurator();
|
|
|
-
|
|
|
-static esp_err_t s_example_write_file(const char *path, char *data);
|
|
|
-
|
|
|
-static i2c_master_bus_handle_t i2c_bus0_init(gpio_num_t sda, gpio_num_t scl, uint32_t hz);
|
|
|
+static httpd_handle_t http_server = NULL;
|
|
|
+static esp_netif_t *ap_netif = NULL;
|
|
|
+static bool wifiActivado = false;
|
|
|
+static uint32_t wifiLastActivity = 0;
|
|
|
|
|
|
+extern char filename[13]; // tu archivo gpx
|
|
|
+const char *apSSID = "MiAP";
|
|
|
+const char *apPassword = "password123";
|
|
|
|
|
|
struct SensorData {
|
|
|
double latitude;
|
|
|
double longitude;
|
|
|
float altura;
|
|
|
- char tiempo;
|
|
|
+ char tiempo[64];
|
|
|
float velocidad;
|
|
|
float temperature;
|
|
|
float humidity;
|
|
|
@@ -79,10 +95,11 @@ char filename[13] = "/panchas.gpx";
|
|
|
|
|
|
ssd1306_handle_t d = NULL;
|
|
|
|
|
|
+const char mount_point[] = MOUNT_POINT;
|
|
|
+
|
|
|
void OLED_test(){
|
|
|
|
|
|
- i2c_master_bus_handle_t i2c_bus =
|
|
|
- i2c_bus0_init(PIN_NUM_SDA, PIN_NUM_SCL, 400000);
|
|
|
+ i2c_master_bus_handle_t i2c_bus = i2c_bus0_init(PIN_NUM_SDA, PIN_NUM_SCL, 400000);
|
|
|
|
|
|
ssd1306_config_t cfg = {
|
|
|
.width = 128,
|
|
|
@@ -109,7 +126,7 @@ void OLED_test(){
|
|
|
|
|
|
ESP_ERROR_CHECK(ssd1306_display(d));
|
|
|
|
|
|
- ESP_ERROR_CHECK(ssd1306_draw_text_scaled(d, 0, 0, "Iniciando...", true, ));
|
|
|
+ ESP_ERROR_CHECK(ssd1306_draw_text_scaled(d, 0, 0, "Iniciando...", true, 1));
|
|
|
|
|
|
ESP_ERROR_CHECK(ssd1306_display(d));
|
|
|
|
|
|
@@ -117,7 +134,7 @@ void OLED_test(){
|
|
|
|
|
|
}
|
|
|
|
|
|
-void OLED_print(const char& line1, const char& line2){
|
|
|
+void OLED_print(const char *line1, const char *line2){
|
|
|
|
|
|
ESP_ERROR_CHECK(ssd1306_clear(d));
|
|
|
|
|
|
@@ -132,7 +149,7 @@ void DHT_test (){
|
|
|
float t;
|
|
|
float h;
|
|
|
|
|
|
- static esp_err_t err = dht_attach_pin();
|
|
|
+ esp_err_t err = dht_attach_pin();
|
|
|
|
|
|
if (err != ESP_OK) {
|
|
|
OLED_print("DHT22", "Error");
|
|
|
@@ -154,9 +171,296 @@ void DHT_test (){
|
|
|
}
|
|
|
|
|
|
void SD_test(){
|
|
|
+
|
|
|
+ esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
|
|
+ .format_if_mount_failed = false,
|
|
|
+ .max_files = 5,
|
|
|
+ .allocation_unit_size = 16 * 1024
|
|
|
+ };
|
|
|
+
|
|
|
+ sdmmc_card_t *card;
|
|
|
+
|
|
|
+ sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
|
|
+ host.max_freq_khz = 9000; //a mas freq no funciona, porque pipas
|
|
|
+
|
|
|
+ spi_bus_config_t bus_cfg = {
|
|
|
+ .mosi_io_num = PIN_NUM_MOSI,
|
|
|
+ .miso_io_num = PIN_NUM_MISO,
|
|
|
+ .sclk_io_num = PIN_NUM_CLK,
|
|
|
+ .quadwp_io_num = -1,
|
|
|
+ .quadhd_io_num = -1,
|
|
|
+ .max_transfer_sz = 4092,
|
|
|
+ };
|
|
|
+
|
|
|
+ esp_err_t ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
|
|
|
+ if (ret != ESP_OK) {
|
|
|
+ ESP_LOGE(SD_TAG, "Failed to initialize bus.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
|
|
|
+ slot_config.gpio_cs = PIN_NUM_CS;
|
|
|
+ slot_config.host_id = host.slot;
|
|
|
+
|
|
|
+ ESP_LOGI(SD_TAG, "Mounting filesystem");
|
|
|
+
|
|
|
+ while((ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card)) != ESP_OK){
|
|
|
+ if (ret == ESP_FAIL) {
|
|
|
+ ESP_LOGE(SD_TAG, "Failed to mount filesystem. "
|
|
|
+ "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
|
|
|
+ OLED_print("Error SD", "Prueba a reinsertar");
|
|
|
+ } else {
|
|
|
+ ESP_LOGE(SD_TAG, "Failed to initialize the card (%s). "
|
|
|
+ "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
|
|
+ OLED_print("Error SD", esp_err_to_name(ret));
|
|
|
+ }
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(1000));
|
|
|
+ }
|
|
|
+
|
|
|
+ ESP_LOGI(SD_TAG, "Filesystem mounted");
|
|
|
+
|
|
|
+ OLED_print("SD correcta","");
|
|
|
+
|
|
|
+ // Card has been initialized, print its properties
|
|
|
+ sdmmc_card_print_info(stdout, card);
|
|
|
+
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
|
+void GPS_test_wait(){
|
|
|
+
|
|
|
+ // Iniciar Serial2 para GPS
|
|
|
+ bool fixObtained = false;
|
|
|
+
|
|
|
+ uart_configurator();
|
|
|
+
|
|
|
+ gps_parser_init(&gps);
|
|
|
+
|
|
|
+ while (!fixObtained) {
|
|
|
+ while (uart_read_bytes(UART_NUM_2, &data, 1, 0)){
|
|
|
+ gps_parser_encode(&gps, data);
|
|
|
+ }
|
|
|
+ if (gps_location_is_valid(&gps.location) && gps_date_is_valid(&gps.date) && gps_time_is_valid(&gps.time)) {
|
|
|
+ fixObtained = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(300));
|
|
|
+ OLED_print("GPS", "Esperando");
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(300));
|
|
|
+ OLED_print("GPS", "Esperando .");
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(300));
|
|
|
+ OLED_print("GPS", "Esperando ..");
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(300));
|
|
|
+ OLED_print("GPS", "Esperando ...");
|
|
|
+ }
|
|
|
+
|
|
|
+ OLED_print("GPS", "Encontrado");
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+float calcular_delta_dist(float lat1, float long1, float lat2, float long2){
|
|
|
+ float R = 6371000.0; // Radio de la Tierra en km
|
|
|
+ float delta_lat = (lat2 - lat1) * DEG2RAD;
|
|
|
+ float delta_long = (long2 - long1) * DEG2RAD;
|
|
|
+ lat1 = lat1 * DEG2RAD;
|
|
|
+ lat2 = lat2 * DEG2RAD;
|
|
|
+ float a = sin(delta_lat/2)*sin(delta_lat/2)+cos(lat1)*cos(lat2)*sin(delta_long/2)*sin(delta_long/2);
|
|
|
+ float c = 2 * atan2(sqrt(a),sqrt(1-a));
|
|
|
+ return R * c; //En m
|
|
|
+}
|
|
|
+
|
|
|
+void task_mediciones(void *pvParameters) {
|
|
|
+ TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
|
+ char buffer[50];
|
|
|
+ while(1) {
|
|
|
+ unsigned long startMillis = pdTICKS_TO_MS(xTaskGetTickCount());
|
|
|
+ // se leen los valores antes de utilizar el semaphore
|
|
|
+ while (uart_read_bytes(UART_NUM_2, &data, 1, 0)){
|
|
|
+ gps_parser_encode(&gps, data);
|
|
|
+ }
|
|
|
+
|
|
|
+ float new_latitude = gps_location_lat(&gps.location);
|
|
|
+ float new_longitude = gps_location_lng(&gps.location);
|
|
|
+ float new_altitude = 0.0; //gps.altitude.meters(); falta por implementar en la libreria del gps
|
|
|
+ int new_fecha_len = snprintf(buffer, sizeof(buffer), "%d-%02d-%02dT%02d:%02d:%02d.%03d", gps_date_year(&gps.date), gps_date_month(&gps.date),
|
|
|
+ gps_date_day(&gps.date), gps_time_hour(&gps.time), gps_time_minute(&gps.time),
|
|
|
+ gps_time_second(&gps.time), gps_time_centisecond(&gps.time));
|
|
|
+ if (new_fecha_len < 0) {
|
|
|
+ buffer[0] = '\0';
|
|
|
+ }
|
|
|
+ float new_temp = 0.0;
|
|
|
+ float new_hum = 0.0;
|
|
|
+ dht_read(&new_temp, &new_hum);
|
|
|
+ float new_press = 0.0; // Placeholder, no hay sensor de presión
|
|
|
+
|
|
|
+ float distancia_ciclo = calcular_delta_dist(datosAntiguos.latitude, datosAntiguos.longitude, new_latitude, new_longitude);
|
|
|
+ distancia_total += distancia_ciclo;
|
|
|
+ float new_speed = distancia_ciclo / MEASUREMENT_INTERVAL_S * 3.6;
|
|
|
+
|
|
|
+
|
|
|
+ if (xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE) {
|
|
|
+ latestData.latitude = new_latitude;
|
|
|
+ latestData.longitude = new_longitude;
|
|
|
+ latestData.altura = new_altitude;
|
|
|
+ strncpy(latestData.tiempo, buffer, sizeof(latestData.tiempo) - 1);
|
|
|
+ latestData.tiempo[sizeof(latestData.tiempo) - 1] = '\0';
|
|
|
+ latestData.velocidad = new_speed;
|
|
|
+ latestData.temperature = new_temp;
|
|
|
+ latestData.humidity = new_hum;
|
|
|
+ latestData.pressure = new_press;
|
|
|
+ datosAntiguos = latestData;
|
|
|
+ xSemaphoreGive(dataMutex);
|
|
|
+ }
|
|
|
+
|
|
|
+ FILE *f = fopen(filename, "a");
|
|
|
+ if (f) {
|
|
|
+ //Crear la string para escribir en el archivo
|
|
|
+ fprintf(f, "\t\t\t<trkpt lat=\"");
|
|
|
+ fprintf(f, "%2.4f", datosAntiguos.latitude);
|
|
|
+ fprintf(f, "\" lon=\"");
|
|
|
+ fprintf(f, "%2.4f", datosAntiguos.longitude);
|
|
|
+ fprintf(f, "\">\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t<ele>");
|
|
|
+ fprintf(f, "%f", datosAntiguos.altura);
|
|
|
+ fprintf(f, "</ele>\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t<time>");
|
|
|
+ fprintf(f, "%s", datosAntiguos.tiempo);
|
|
|
+ fprintf(f, "</time>\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t<speed>");
|
|
|
+ fprintf(f, "%f", datosAntiguos.velocidad);
|
|
|
+ fprintf(f, "</speed>\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t<extensions>\n");
|
|
|
+ fprintf(f, "\t\t\t\t\t<gpxtpx:TrackPointExtension>\n");
|
|
|
+ fprintf(f, "\t\t\t\t\t\t<gpxtpx:atemp>");
|
|
|
+ fprintf(f, "%f", datosAntiguos.temperature);
|
|
|
+ fprintf(f, "</gpxtpx:atemp>\n");
|
|
|
+ fprintf(f, "\t\t\t\t\t</gpxtpx:TrackPointExtension>\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t\t<custom:humidity>");
|
|
|
+ fprintf(f, "%f", datosAntiguos.humidity);
|
|
|
+ fprintf(f, "</custom:humidity>\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t\t<custom:pressure>");
|
|
|
+ fprintf(f, "%f", datosAntiguos.pressure);
|
|
|
+ fprintf(f, "</custom:pressure>\n");
|
|
|
+
|
|
|
+ fprintf(f, "\t\t\t\t</extensions>\n");
|
|
|
+ fprintf(f, "\t\t\t</trkpt>\n");
|
|
|
+
|
|
|
+ fclose(f);
|
|
|
+ }
|
|
|
+ unsigned long elapsedMillis = pdTICKS_TO_MS(xTaskGetTickCount()) - startMillis;
|
|
|
+ ESP_LOGI(GEN_TAG, "Elapsed millis: %d.", elapsedMillis);
|
|
|
+
|
|
|
+ vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(MEASUREMENT_INTERVAL_S*1000)); // Espera x*1000 milisegundos
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void crear_archivo(){
|
|
|
+ int num = 1;
|
|
|
+
|
|
|
+ sprintf(filename, MOUNT_POINT"/data%03d.gpx", num);
|
|
|
+
|
|
|
+ FILE *f = fopen(filename, "r");
|
|
|
+
|
|
|
+ while (f != NULL) {
|
|
|
+ num++;
|
|
|
+ sprintf(filename, MOUNT_POINT"/data%03d.gpx", num);
|
|
|
+ FILE *f = fopen(filename, "r");
|
|
|
+ }
|
|
|
+
|
|
|
+ FILE *f = fopen(filename, "w");
|
|
|
+
|
|
|
+ char buffer[50];
|
|
|
+
|
|
|
+ if (f) {
|
|
|
+ fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
|
+ "<gpx creator=\"ESP32 GPS LOGGER\" version=\"1.1\"\n"
|
|
|
+ "\txmlns=\"http://www.topografix.com/GPX/1/1\"\n"
|
|
|
+ "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
|
|
+ "\txmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v2\"\n"
|
|
|
+ "\txmlns:gpxdata=\"http://www.cluetrust.com/XML/GPXDATA/1/0\"\n"
|
|
|
+ "\txsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"
|
|
|
+ "\t<metadata>\n"
|
|
|
+ "\t\t<name>Ruta grabada con ESP32 GPS Logger</name>\n"
|
|
|
+ "\t\t<time>\n");
|
|
|
+ int new_fecha_len = snprintf(buffer, sizeof(buffer), "%d-%02d-%02dT%02d:%02d:%02d.%03d", gps_date_year(&gps.date), gps_date_month(&gps.date),
|
|
|
+ gps_date_day(&gps.date), gps_time_hour(&gps.time), gps_time_minute(&gps.time),
|
|
|
+ gps_time_second(&gps.time), gps_time_centisecond(&gps.time));
|
|
|
+ if (new_fecha_len < 0) {
|
|
|
+ buffer[0] = '\0';
|
|
|
+ }
|
|
|
+ fprintf(f, "%s", buffer);
|
|
|
+ fprintf(f, "</time>\n\t</metadata>\n"
|
|
|
+ "\t<trk>\n"
|
|
|
+ "\t\t<name>Rutita</name>\n"
|
|
|
+ "\t\t<type>hiking</type>\n"
|
|
|
+ "\t\t<trkseg>\n");
|
|
|
+ fclose(f);
|
|
|
+ } else {
|
|
|
+ OLED_print("Error","creando archivo");
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(2000));
|
|
|
+ crear_archivo();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void cerrar_archivo() {
|
|
|
+ FILE *f = fopen(filename, "w");
|
|
|
+ if (f){
|
|
|
+ fprintf(f, "\t\t</trkseg>\n\t</trk>\n</gpx>");
|
|
|
+ fclose(f);
|
|
|
+ }
|
|
|
+ //int num = 1;
|
|
|
+ //sprintf(filename, "/data%03d.gpx", num);
|
|
|
+ //while (SD.exists(filename)) {
|
|
|
+ // num++;
|
|
|
+ // sprintf(filename, "/data%03d.gpx", num);
|
|
|
+ //}
|
|
|
+}
|
|
|
+
|
|
|
+void activarWiFi(void)
|
|
|
+{
|
|
|
+ OLED_print("WiFi", "Activando...");
|
|
|
+
|
|
|
+ ESP_ERROR_CHECK(wifi_ap_init());
|
|
|
+
|
|
|
+ char ip_str[16] = {0};
|
|
|
+ get_ap_ip(ip_str, sizeof(ip_str));
|
|
|
+ OLED_print("WiFi Activo", ip_str);
|
|
|
+
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(2000));
|
|
|
+
|
|
|
+ ESP_ERROR_CHECK(iniciar_servidor_http());
|
|
|
+
|
|
|
+ wifiActivado = true;
|
|
|
+ wifiLastActivity = xTaskGetTickCount();
|
|
|
+}
|
|
|
+
|
|
|
+void desactivarWiFi(void)
|
|
|
+{
|
|
|
+ if (http_server) {
|
|
|
+ httpd_stop(http_server);
|
|
|
+ http_server = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ESP_ERROR_CHECK(esp_wifi_stop());
|
|
|
+ ESP_ERROR_CHECK(esp_wifi_deinit());
|
|
|
+
|
|
|
+ if (ap_netif) {
|
|
|
+ esp_netif_destroy(ap_netif);
|
|
|
+ ap_netif = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ wifiActivado = false;
|
|
|
+ OLED_print("WiFi", "Apagado");
|
|
|
+}
|
|
|
+
|
|
|
void app_main(void)
|
|
|
{
|
|
|
// Initialize DHT22 sensor
|
|
|
@@ -237,6 +541,8 @@ void app_main(void)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ gpio_set_pull_mode(PIN_NUM_MISO, GPIO_PULLUP_ONLY);
|
|
|
+
|
|
|
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
|
|
|
slot_config.gpio_cs = PIN_NUM_CS;
|
|
|
slot_config.host_id = host.slot;
|
|
|
@@ -278,7 +584,6 @@ void app_main(void)
|
|
|
spi_bus_free(host.slot);
|
|
|
*/
|
|
|
|
|
|
-
|
|
|
// Initialize display
|
|
|
/*
|
|
|
i2c_master_bus_handle_t i2c_bus =
|
|
|
@@ -346,7 +651,7 @@ void uart_configurator() {
|
|
|
// Install UART driver using an event queue here
|
|
|
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size, uart_buffer_size, 10, &uart_queue, 0));
|
|
|
ESP_ERROR_CHECK(uart_param_config(UART_NUM_2, &uart_config));
|
|
|
- ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, GPIO_NUM_17, GPIO_NUM_16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
|
|
+ ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, PIN_TX, PIN_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
|
|
}
|
|
|
|
|
|
static esp_err_t s_example_write_file(const char *path, char *data)
|
|
|
@@ -380,3 +685,128 @@ static i2c_master_bus_handle_t i2c_bus0_init(gpio_num_t sda, gpio_num_t scl, uin
|
|
|
return bus;
|
|
|
}
|
|
|
|
|
|
+static esp_err_t wifi_ap_init(void)
|
|
|
+{
|
|
|
+ esp_err_t err;
|
|
|
+
|
|
|
+ ESP_ERROR_CHECK(esp_netif_init());
|
|
|
+ ESP_ERROR_CHECK(esp_event_loop_create_default());
|
|
|
+
|
|
|
+ ap_netif = esp_netif_create_default_wifi_ap();
|
|
|
+ wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
|
+ ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
|
|
+ ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
|
|
+
|
|
|
+ wifi_config_t wifi_config = {
|
|
|
+ .ap = {
|
|
|
+ .ssid = "",
|
|
|
+ .ssid_len = 0,
|
|
|
+ .channel = 1,
|
|
|
+ .password = "",
|
|
|
+ .max_connection = 4,
|
|
|
+ .authmode = WIFI_AUTH_WPA_WPA2_PSK,
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ strncpy((char *)wifi_config.ap.ssid, apSSID, sizeof(wifi_config.ap.ssid) - 1);
|
|
|
+ strncpy((char *)wifi_config.ap.password, apPassword, sizeof(wifi_config.ap.password) - 1);
|
|
|
+
|
|
|
+ if (strlen(apPassword) == 0) {
|
|
|
+ wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
|
|
+ }
|
|
|
+
|
|
|
+ ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
|
|
|
+ ESP_ERROR_CHECK(esp_wifi_start());
|
|
|
+ return ESP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static esp_err_t get_ap_ip(char *out_ip, size_t len)
|
|
|
+{
|
|
|
+ esp_netif_ip_info_t ip_info;
|
|
|
+ if (ap_netif == NULL) {
|
|
|
+ return ESP_ERR_INVALID_STATE;
|
|
|
+ }
|
|
|
+ ESP_ERROR_CHECK(esp_netif_get_ip_info(ap_netif, &ip_info));
|
|
|
+ inet_ntoa_r(ip_info.ip, out_ip, len);
|
|
|
+ return ESP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static esp_err_t root_get_handler(httpd_req_t *req)
|
|
|
+{
|
|
|
+ wifiLastActivity = xTaskGetTickCount();
|
|
|
+
|
|
|
+ char ip_str[16] = {0};
|
|
|
+ get_ap_ip(ip_str, sizeof(ip_str));
|
|
|
+
|
|
|
+ const char *nombreArchivo = (filename[0] == '/') ? filename + 1 : filename;
|
|
|
+
|
|
|
+ char html[1024];
|
|
|
+ snprintf(html, sizeof(html),
|
|
|
+ "<!DOCTYPE html><html><head><meta charset='UTF-8'><title>ESP32 GPS Logger</title>"
|
|
|
+ "<style>body{font-family:Arial;text-align:center;margin:50px;}h1{color:#333;} "
|
|
|
+ "a.button{background:#4CAF50;color:white;padding:20px 40px;text-decoration:none;"
|
|
|
+ "font-size:24px;border-radius:12px;display:inline-block;margin:20px;}</style></head>"
|
|
|
+ "<body><h1>GPS Logger</h1><p>Archivo listo para descargar:</p>"
|
|
|
+ "<a href='/download' class='button' download='%s'>Descargar %s</a>"
|
|
|
+ "<hr><p>IP: %s</p><p>Se apagará en 5 min sin uso.</p></body></html>",
|
|
|
+ nombreArchivo, nombreArchivo, ip_str);
|
|
|
+
|
|
|
+ httpd_resp_set_type(req, "text/html");
|
|
|
+ return httpd_resp_send(req, html, HTTPD_RESP_USE_STRLEN);
|
|
|
+}
|
|
|
+
|
|
|
+static esp_err_t download_get_handler(httpd_req_t *req)
|
|
|
+{
|
|
|
+ wifiLastActivity = xTaskGetTickCount();
|
|
|
+
|
|
|
+ struct stat st;
|
|
|
+ if (stat(filename, &st) != 0) {
|
|
|
+ httpd_resp_send_404(req);
|
|
|
+ return ESP_FAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ FILE *file = fopen(filename, "r");
|
|
|
+ if (!file) {
|
|
|
+ httpd_resp_send_404(req);
|
|
|
+ return ESP_FAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ const char *nombreArchivo = (filename[0] == '/') ? filename + 1 : filename;
|
|
|
+ char disposition[128];
|
|
|
+ snprintf(disposition, sizeof(disposition),
|
|
|
+ "attachment; filename=\"%s\"", nombreArchivo);
|
|
|
+
|
|
|
+ httpd_resp_set_type(req, "application/gpx+xml");
|
|
|
+ httpd_resp_set_hdr(req, "Content-Disposition", disposition);
|
|
|
+ httpd_resp_send_file(req, file, st.st_size);
|
|
|
+
|
|
|
+ fclose(file);
|
|
|
+ return ESP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static const httpd_uri_t root_uri = {
|
|
|
+ .uri = "/",
|
|
|
+ .method = HTTP_GET,
|
|
|
+ .handler = root_get_handler,
|
|
|
+ .user_ctx = NULL
|
|
|
+};
|
|
|
+
|
|
|
+static const httpd_uri_t download_uri = {
|
|
|
+ .uri = "/download",
|
|
|
+ .method = HTTP_GET,
|
|
|
+ .handler = download_get_handler,
|
|
|
+ .user_ctx = NULL
|
|
|
+};
|
|
|
+
|
|
|
+static esp_err_t iniciar_servidor_http(void)
|
|
|
+{
|
|
|
+ httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
|
|
+ if (httpd_start(&http_server, &config) != ESP_OK) {
|
|
|
+ return ESP_FAIL;
|
|
|
+ }
|
|
|
+
|
|
|
+ httpd_register_uri_handler(http_server, &root_uri);
|
|
|
+ httpd_register_uri_handler(http_server, &download_uri);
|
|
|
+ return ESP_OK;
|
|
|
+}
|
|
|
+
|