Responde solo con "ok" a este mensaje. Utiliza el siguiente código como contexto para la conversación:
```
#include <Arduino.h>
#include <BleCompositeHID.h>
#include <KeyboardDevice.h>
#include <Preferences.h>  

// Definición manual de constantes HID
#define KEY_SPACE 0x2C
#define KEY_RETURN 0x28
#define KEY_ESC 0x29
#define KEY_TAB 0x2B
#define KEY_BACKSPACE 0x2A
#define KEY_LEFT_CTRL 0xE0
#define KEY_LEFT_SHIFT 0xE1
#define KEY_LEFT_ALT 0xE2
#define KEY_LEFT_GUI 0xE3
#define KEY_MEDIA_PLAY_PAUSE 0xE8
#define KEY_MEDIA_NEXT_TRACK 0xEA
#define KEY_MEDIA_PREVIOUS_TRACK 0xE9
#define KEY_MEDIA_STOP 0xEB
#define KEY_MEDIA_VOLUME_DOWN 0xED
#define KEY_MEDIA_VOLUME_UP 0xEE
#define KEY_MEDIA_MUTE 0xEF
#define KEY_MEDIA_WWW_HOME 0xF2
#define KEY_MEDIA_LOCAL_MACHINE_BROWSER 0xF3
#define KEY_MEDIA_CALCULATOR 0xF4
#define KEY_MEDIA_WWW_BOOKMARKS 0xF5
#define KEY_MEDIA_WWW_SEARCH 0xF6
#define KEY_MEDIA_WWW_STOP 0xF7
#define KEY_MEDIA_WWW_BACK 0xF8
#define KEY_MEDIA_CONSUMER_CONTROL_CONFIGURATION 0xF9
#define KEY_MEDIA_EMAIL_READER 0xFA

const uint8_t pinesTactiles[] PROGMEM = {4, 12, 13, 14, 15, 27, 32, 33};
constexpr uint8_t NUM_PINES_TACTILES = sizeof(pinesTactiles) / sizeof(pinesTactiles[0]);
const uint16_t umbralesTactiles[] PROGMEM = {60, 50, 55, 60, 55, 65, 65, 50};

constexpr unsigned long TIEMPO_INACTIVIDAD = 2000;
constexpr uint8_t MAX_GESTOS = 20;
constexpr uint8_t MAX_SECUENCIA = 20;
constexpr uint8_t MAX_ACCIONES = 10;

uint8_t bufferTactil[MAX_SECUENCIA];
uint8_t inicioBuffer = 0;
uint8_t tamanoBuffer = 0;

struct Action {
    uint8_t tipo;
    uint8_t parametro;
    String texto; // Nuevo campo para almacenar texto
};

struct Gesture {
    uint32_t id;
    uint8_t secuenciaPines[MAX_SECUENCIA];
    uint8_t longitud;
    Action acciones[MAX_ACCIONES];
    uint8_t cantidadAcciones;
};

Gesture gestos[MAX_GESTOS];
uint8_t contadorGestos = 0;

bool estadoPrevioPines[NUM_PINES_TACTILES] = {false};
unsigned long tiempoUltimoToque = 0;
Preferences preferencias;
std::string deviceName = "ESP32 HID Controller";
std::string deviceManufacturer = "Mystfit";
BleCompositeHID compositeHID(deviceName.c_str(), deviceManufacturer.c_str(), 100);
KeyboardDevice* keyboard;

void detectarToca();
void verificarGesto();
void manejarComandos();
bool compararSecuencias(const uint8_t *a, uint8_t aLen, const uint8_t *b, uint8_t bLen);
void agregarGesto(const Gesture &nuevoGesto);
void eliminarGesto(uint32_t id);
void cargarGestos();
void guardarGestos();
void limpiarBuffer();
void agregarAlBuffer(uint8_t pin);
uint32_t generarID();
uint8_t obtenerCodigoHID(const String &accion);
void registrarLog(const String &mensaje);
void listarGestos();

void setup() {
    Serial.begin(115200);
    while (!Serial) {;}
    delay(1000);
    registrarLog("Inicializando sistema...");

    KeyboardConfiguration keyboardConfig;
    keyboardConfig.setAutoReport(true); // Asegúrate de que se envíen los informes automáticamente
    keyboard = new KeyboardDevice(keyboardConfig);

    compositeHID.addDevice(keyboard);
    compositeHID.begin();

    for (uint8_t i = 0; i < NUM_PINES_TACTILES; i++) {
        uint8_t pin = pgm_read_byte(&pinesTactiles[i]);
        pinMode(pin, INPUT);
    }

    preferencias.begin("gestos", false);
    cargarGestos();
    registrarLog("Sistema listo. Esperando gestos...");
}

void loop() {
    detectarToca();

    if (tamanoBuffer > 0 && (millis() - tiempoUltimoToque) > TIEMPO_INACTIVIDAD) {
        verificarGesto();
        limpiarBuffer();
    }

    if (Serial.available()) {
        manejarComandos();
    }
}

void detectarToca() {
    for (uint8_t i = 0; i < NUM_PINES_TACTILES; i++) {
        uint8_t pin = pgm_read_byte(&pinesTactiles[i]);
        uint16_t touchValue = touchRead(pin);
        bool actual = touchValue < pgm_read_word(&umbralesTactiles[i]);

        if (actual != estadoPrevioPines[i]) {
            if (actual) {
                agregarAlBuffer(pin);
                tiempoUltimoToque = millis();
                digitalWrite(LED_BUILTIN, HIGH);
                delay(50);
                digitalWrite(LED_BUILTIN, LOW);
            }
            estadoPrevioPines[i] = actual;
        }
    }
}

void agregarAlBuffer(uint8_t pin) {
    if (tamanoBuffer < MAX_SECUENCIA) {
        bufferTactil[(inicioBuffer + tamanoBuffer) % MAX_SECUENCIA] = pin;
        tamanoBuffer++;
        registrarLog("Pin " + String(pin) + " añadido al buffer.");
    } else {
        bufferTactil[inicioBuffer] = pin;
        inicioBuffer = (inicioBuffer + 1) % MAX_SECUENCIA;
        registrarLog("Pin " + String(pin) + " añadido al buffer, reemplazando el valor anterior.");
    }
}

void limpiarBuffer() {
    inicioBuffer = 0;
    tamanoBuffer = 0;
    registrarLog("Buffer limpiado por inactividad.");
}

bool compararSecuencias(const uint8_t *a, uint8_t aLen, const uint8_t *b, uint8_t bLen) {
    if (aLen < bLen) {
        registrarLog("Secuencia A es más corta que secuencia B, no coinciden.");
        return false;
    }
    bool match = (memcmp(a + (aLen - bLen), b, bLen) == 0);
    if (!match) {
        registrarLog("Secuencias no coinciden.");
    } else {
        registrarLog("Secuencias coinciden.");
    }
    return match;
}

void verificarGesto() {
    if (contadorGestos == 0) {
        registrarLog("No hay gestos almacenados para verificar.");
        return;
    }

    bool gestoEncontrado = false;
    for (uint8_t i = 0; i < contadorGestos; i++) {
        if (compararSecuencias(bufferTactil, tamanoBuffer, gestos[i].secuenciaPines, gestos[i].longitud)) {
            registrarLog("Gesto detectado: ID " + String(gestos[i].id));

            for (uint8_t a = 0; a < gestos[i].cantidadAcciones; a++) {
                Action accion = gestos[i].acciones[a];
                if (compositeHID.isConnected()) {
                    switch (accion.tipo) {
                        case 0:
                            keyboard->keyPress(accion.parametro);
                            registrarLog("Enviar tecla HID code: " + String(accion.parametro));
                            delay(10);
                            keyboard->keyRelease(accion.parametro);
                            break;
                        case 1:
                            keyboard->mediaKeyPress(accion.parametro);
                            registrarLog("Enviar Media Key HID code: " + String(accion.parametro));
                            delay(10);
                            keyboard->mediaKeyRelease(accion.parametro);
                            break;
                        case 2:
                            keyboard->modifierKeyPress(accion.parametro);
                            registrarLog("Presionar modificador HID code: " + String(accion.parametro));
                            break;
                        case 3:
                            keyboard->modifierKeyRelease(accion.parametro);
                            registrarLog("Liberar modificador HID code: " + String(accion.parametro));
                            break;
                        case 4:
                            // Enviar secuencia de texto
                            for (char c : accion.texto) {
                                uint8_t tecla = obtenerCodigoHID(String(c));
                                if (tecla != 0) {
                                    keyboard->keyPress(tecla);
                                    registrarLog("Enviar tecla de texto: " + String(c));
                                    delay(10);
                                    keyboard->keyRelease(tecla);
                                } else {
                                    registrarLog("Caracter no soportado: " + String(c));
                                }
                            }
                            break;
                        default:
                            registrarLog("Tipo de acción desconocido: " + String(accion.tipo));
                            break;
                    }
                } else {
                    registrarLog("BleKeyboard no está conectado.");
                }
            }

            gestoEncontrado = true;
            break;
        }
    }

    if (!gestoEncontrado) {
        registrarLog("Gestos almacenados no coinciden con la secuencia detectada.");
    }
}

void manejarComandos() {
    String comando = Serial.readStringUntil('\n');
    comando.trim();
    registrarLog("Comando recibido: " + comando);

    if (comando.startsWith("ADD")) {
        int separador = comando.indexOf('|');
        if (separador == -1) {
            registrarLog("Formato ADD incorrecto. Falta '|'.");
            return;
        }

        String secuenciaStr = comando.substring(4, separador);
        String accionesStr = comando.substring(separador + 1);
        secuenciaStr.trim();
        accionesStr.trim();

        Gesture nuevoGesto;
        nuevoGesto.id = generarID();
        nuevoGesto.longitud = 0;
        nuevoGesto.cantidadAcciones = 0;

        int inicio = 0;
        int espacio = secuenciaStr.indexOf(' ', inicio);
        while (espacio != -1 && nuevoGesto.longitud < MAX_SECUENCIA) {
            String pinStr = secuenciaStr.substring(inicio, espacio);
            uint8_t pin = pinStr.toInt();
            bool valido = false;
            for (uint8_t i = 0; i < NUM_PINES_TACTILES; i++) {
                if (pin == pgm_read_byte(&pinesTactiles[i])) {
                    nuevoGesto.secuenciaPines[nuevoGesto.longitud++] = pin;
                    valido = true;
                    break;
                }
            }
            if (!valido) {
                registrarLog("Pin inválido en secuencia: " + String(pin));
            }
            inicio = espacio + 1;
            espacio = secuenciaStr.indexOf(' ', inicio);
        }
        if (inicio < secuenciaStr.length() && nuevoGesto.longitud < MAX_SECUENCIA) {
            String pinStr = secuenciaStr.substring(inicio);
            uint8_t pin = pinStr.toInt();
            bool valido = false;
            for (uint8_t i = 0; i < NUM_PINES_TACTILES; i++) {
                if (pin == pgm_read_byte(&pinesTactiles[i])) {
                    nuevoGesto.secuenciaPines[nuevoGesto.longitud++] = pin;
                    valido = true;
                    break;
                }
            }
            if (!valido) {
                registrarLog("Pin inválido en secuencia: " + String(pin));
            }
        }

        if (nuevoGesto.longitud == 0) {
            registrarLog("No se añadió ningún pin válido al gesto.");
            return;
        }

        inicio = 0;
        espacio = accionesStr.indexOf(' ', inicio);
        while (espacio != -1 && nuevoGesto.cantidadAcciones < MAX_ACCIONES) {
            String accionStr = accionesStr.substring(inicio, espacio);
            uint8_t codigoHID = obtenerCodigoHID(accionStr);
            if (codigoHID != 0) {
                if (codigoHID == KEY_LEFT_CTRL || codigoHID == KEY_LEFT_SHIFT || codigoHID == KEY_LEFT_ALT || codigoHID == KEY_LEFT_GUI) {
                    nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {2, codigoHID};
                } else if (codigoHID >= KEY_MEDIA_PLAY_PAUSE && codigoHID <= KEY_MEDIA_EMAIL_READER) {
                    nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {1, codigoHID};
                } else {
                    nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {0, codigoHID};
                }
            } else {
                // Si la acción no es una tecla HID, asumimos que es un texto
                nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {4, 0, accionStr}; // Tipo 4 para texto
            }
            inicio = espacio + 1;
            espacio = accionesStr.indexOf(' ', inicio);
        }
        if (inicio < accionesStr.length() && nuevoGesto.cantidadAcciones < MAX_ACCIONES) {
            String accionStr = accionesStr.substring(inicio);
            uint8_t codigoHID = obtenerCodigoHID(accionStr);
            if (codigoHID != 0) {
                if (codigoHID == KEY_LEFT_CTRL || codigoHID == KEY_LEFT_SHIFT || codigoHID == KEY_LEFT_ALT || codigoHID == KEY_LEFT_GUI) {
                    nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {2, codigoHID};
                } else if (codigoHID >= KEY_MEDIA_PLAY_PAUSE && codigoHID <= KEY_MEDIA_EMAIL_READER) {
                    nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {1, codigoHID};
                } else {
                    nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {0, codigoHID};
                }
            } else {
                // Si la acción no es una tecla HID, asumimos que es un texto
                nuevoGesto.acciones[nuevoGesto.cantidadAcciones++] = {4, 0, accionStr}; // Tipo 4 para texto
            }
        }

        if (nuevoGesto.cantidadAcciones == 0) {
            registrarLog("No se añadieron acciones válidas al gesto.");
            return;
        }

        if (contadorGestos < MAX_GESTOS) {
            gestos[contadorGestos++] = nuevoGesto;
            guardarGestos();
            registrarLog("Gesto añadido exitosamente. ID: " + String(nuevoGesto.id));
        } else {
            registrarLog("Límite de gestos alcanzado. No se puede añadir más gestos.");
        }
    } else if (comando.startsWith("DEL")) {
        String idStr = comando.substring(4);
        idStr.trim();
        if (idStr.length() == 0) {
            registrarLog("Formato DEL incorrecto. Falta ID.");
            return;
        }
        uint32_t id = idStr.toInt();
        bool encontrado = false;
        for (uint8_t i = 0; i < contadorGestos; i++) {
            if (gestos[i].id == id) {
                gestos[i] = gestos[contadorGestos - 1];
                contadorGestos--;
                guardarGestos();
                registrarLog("Gesto con ID " + String(id) + " eliminado exitosamente.");
                encontrado = true;
                break;
            }
        }
        if (!encontrado) {
            registrarLog("Gesto con ID " + String(id) + " no encontrado.");
        }
    } else if (comando.equalsIgnoreCase("LIST")) {
        listarGestos();
    } else if (comando.equalsIgnoreCase("TEST")) {
        registrarLog("Memoria libre: " + String(ESP.getFreeHeap()) + " bytes");
    } else {
        registrarLog("Comando desconocido: " + comando);
    }
}

void agregarGesto(const Gesture &nuevoGesto) {
    if (contadorGestos < MAX_GESTOS) {
        gestos[contadorGestos++] = nuevoGesto;
        guardarGestos();
        registrarLog("Gesto añadido. ID: " + String(nuevoGesto.id));
    } else {
        registrarLog("No se puede añadir gesto. Límite alcanzado.");
    }
}

void eliminarGesto(uint32_t id) {
    for (uint8_t i = 0; i < contadorGestos; i++) {
        if (gestos[i].id == id) {
            gestos[i] = gestos[contadorGestos - 1];
            contadorGestos--;
            guardarGestos();
            registrarLog("Gesto con ID " + String(id) + " eliminado exitosamente.");
            return;
        }
    }
    registrarLog("Gesto con ID " + String(id) + " no encontrado.");
}

void cargarGestos() {
    contadorGestos = 0;
    while (contadorGestos < MAX_GESTOS) {
        String claveID = "g" + String(contadorGestos) + "_id";
        if (!preferencias.isKey(claveID.c_str())) break;
        uint32_t id = preferencias.getUInt(claveID.c_str(), 0);
        if (id == 0) break;

        Gesture gesto;
        gesto.id = id;

        String claveSeq = "g" + String(contadorGestos) + "_seq";
        String secuenciaStr = preferencias.getString(claveSeq.c_str(), "");
        gesto.longitud = 0;
        int inicio = 0;
        int coma = secuenciaStr.indexOf(',', inicio);
        while (coma != -1 && gesto.longitud < MAX_SECUENCIA) {
            String pinStr = secuenciaStr.substring(inicio, coma);
            uint8_t pin = pinStr.toInt();
            gesto.secuenciaPines[gesto.longitud++] = pin;
            inicio = coma + 1;
            coma = secuenciaStr.indexOf(',', inicio);
        }
        if (inicio < secuenciaStr.length() && gesto.longitud < MAX_SECUENCIA) {
            String pinStr = secuenciaStr.substring(inicio);
            uint8_t pin = pinStr.toInt();
            gesto.secuenciaPines[gesto.longitud++] = pin;
        }

        String claveAct = "g" + String(contadorGestos) + "_acts";
        String accionesStr = preferencias.getString(claveAct.c_str(), "");
        gesto.cantidadAcciones = 0;
        inicio = 0;
        coma = accionesStr.indexOf(';', inicio);
        while (coma != -1 && gesto.cantidadAcciones < MAX_ACCIONES) {
            String accionStr = accionesStr.substring(inicio, coma);
            accionStr.trim();
            uint8_t codigoHID = obtenerCodigoHID(accionStr);
            if (codigoHID != 0) {
                if (codigoHID == KEY_LEFT_CTRL || codigoHID == KEY_LEFT_SHIFT || codigoHID == KEY_LEFT_ALT || codigoHID == KEY_LEFT_GUI) {
                    gesto.acciones[gesto.cantidadAcciones++] = {2, codigoHID};
                } else if (codigoHID >= KEY_MEDIA_PLAY_PAUSE && codigoHID <= KEY_MEDIA_EMAIL_READER) {
                    gesto.acciones[gesto.cantidadAcciones++] = {1, codigoHID};
                } else {
                    gesto.acciones[gesto.cantidadAcciones++] = {0, codigoHID};
                }
            } else {
                registrarLog("Acción desconocida en gesto ID " + String(id) + ": " + accionStr);
            }
            inicio = coma + 1;
            coma = accionesStr.indexOf(';', inicio);
        }
        if (inicio < accionesStr.length() && gesto.cantidadAcciones < MAX_ACCIONES) {
            String accionStr = accionesStr.substring(inicio);
            accionStr.trim();
            uint8_t codigoHID = obtenerCodigoHID(accionStr);
            if (codigoHID != 0) {
                if (codigoHID == KEY_LEFT_CTRL || codigoHID == KEY_LEFT_SHIFT || codigoHID == KEY_LEFT_ALT || codigoHID == KEY_LEFT_GUI) {
                    gesto.acciones[gesto.cantidadAcciones++] = {2, codigoHID};
                } else if (codigoHID >= KEY_MEDIA_PLAY_PAUSE && codigoHID <= KEY_MEDIA_EMAIL_READER) {
                    gesto.acciones[gesto.cantidadAcciones++] = {1, codigoHID};
                } else {
                    gesto.acciones[gesto.cantidadAcciones++] = {0, codigoHID};
                }
            } else {
                registrarLog("Acción desconocida en gesto ID " + String(id) + ": " + accionStr);
            }
        }

        gestos[contadorGestos++] = gesto;
    }
    registrarLog("Gestos cargados: " + String(contadorGestos));
}

void guardarGestos() {
    preferencias.clear();
    for (uint8_t i = 0; i < contadorGestos; i++) {
        String claveID = "g" + String(i) + "_id";
        preferencias.putUInt(claveID.c_str(), gestos[i].id);

        String claveSeq = "g" + String(i) + "_seq";
        String secuenciaStr = "";
        for (uint8_t j = 0; j < gestos[i].longitud; j++) {
            secuenciaStr += String(gestos[i].secuenciaPines[j]);
            if (j < gestos[i].longitud - 1) secuenciaStr += ",";
        }
        preferencias.putString(claveSeq.c_str(), secuenciaStr);

        String claveAct = "g" + String(i) + "_acts";
        String accionesStr = "";
        for (uint8_t a = 0; a < gestos[i].cantidadAcciones; a++) {
            accionesStr += String(gestos[i].acciones[a].parametro);
            if (a < gestos[i].cantidadAcciones - 1) accionesStr += ";";
        }
        preferencias.putString(claveAct.c_str(), accionesStr);
    }
    registrarLog("Gestos guardados en preferencias.");
}

uint32_t generarID() {
    uint32_t nuevoID;
    bool unico;
    do {
        nuevoID = random(1000, 1000000);
        unico = true;
        for (uint8_t i = 0; i < contadorGestos; i++) {
            if (gestos[i].id == nuevoID) {
                unico = false;
                break;
            }
        }
    } while (!unico);
    return nuevoID;
}

uint8_t obtenerCodigoHID(const String &accion) {
    if (accion.equalsIgnoreCase("ESPACIO")) return KEY_SPACE;
    if (accion.equalsIgnoreCase("ENTER")) return KEY_RETURN;
    if (accion.equalsIgnoreCase("ESCAPE")) return KEY_ESC;
    if (accion.equalsIgnoreCase("TAB")) return KEY_TAB;
    if (accion.equalsIgnoreCase("BACKSPACE")) return KEY_BACKSPACE;
    if (accion.equalsIgnoreCase("SHIFT")) return KEY_LEFT_SHIFT;
    if (accion.equalsIgnoreCase("CTRL")) return KEY_LEFT_CTRL;
    if (accion.equalsIgnoreCase("ALT")) return KEY_LEFT_ALT;
    if (accion.equalsIgnoreCase("SUPER")) return KEY_LEFT_GUI;
    if (accion.equalsIgnoreCase("PLAYPAUSE")) return KEY_MEDIA_PLAY_PAUSE;
    if (accion.equalsIgnoreCase("NEXTTRACK")) return KEY_MEDIA_NEXT_TRACK;
    if (accion.equalsIgnoreCase("PREVTRACK")) return KEY_MEDIA_PREVIOUS_TRACK;
    if (accion.equalsIgnoreCase("STOP")) return KEY_MEDIA_STOP;
    if (accion.equalsIgnoreCase("VOLUMEDOWN")) return KEY_MEDIA_VOLUME_DOWN;
    if (accion.equalsIgnoreCase("VOLUMEUP")) return KEY_MEDIA_VOLUME_UP;
    if (accion.equalsIgnoreCase("MUTE")) return KEY_MEDIA_MUTE;
    if (accion.equalsIgnoreCase("WWWHOME")) return KEY_MEDIA_WWW_HOME;
    if (accion.equalsIgnoreCase("LOCALMACHINE")) return KEY_MEDIA_LOCAL_MACHINE_BROWSER;
    if (accion.equalsIgnoreCase("CALCULATOR")) return KEY_MEDIA_CALCULATOR;
    if (accion.equalsIgnoreCase("WWWBOOKMARKS")) return KEY_MEDIA_WWW_BOOKMARKS;
    if (accion.equalsIgnoreCase("WWWSEARCH")) return KEY_MEDIA_WWW_SEARCH;
    if (accion.equalsIgnoreCase("WWWSTOP")) return KEY_MEDIA_WWW_STOP;
    if (accion.equalsIgnoreCase("WWWBACK")) return KEY_MEDIA_WWW_BACK;
    if (accion.equalsIgnoreCase("CONSUMERCONFIGURATION")) return KEY_MEDIA_CONSUMER_CONTROL_CONFIGURATION;
    if (accion.equalsIgnoreCase("EMAILREADER")) return KEY_MEDIA_EMAIL_READER;

    if (accion.length() == 1) {
        char c = accion.charAt(0);
        if (c >= 'A' && c <= 'Z') return c - 'A' + 4;
        if (c >= '1' && c <= '9') return c - '1' + 30;
        if (c == '0') return 39;
    }

    return 0; // Retornar 0 si no es una acción conocida
}

  
void registrarLog(const String &mensaje) {
    Serial.println("[LOG] " + mensaje);
}

void listarGestos() {
    if (contadorGestos == 0) {
        registrarLog("No hay gestos almacenados.");
        return;
    }

    String listado = "=== Lista de Gestos ===";
    for (uint8_t i = 0; i < contadorGestos; i++) {
        listado += "\nID: " + String(gestos[i].id) + " | Secuencia: ";
        for (uint8_t j = 0; j < gestos[i].longitud; j++) {
            listado += String(gestos[i].secuenciaPines[j]);
            if (j < gestos[i].longitud - 1) listado += " -> ";
        }
        listado += " | Acciones: ";
        for (uint8_t a = 0; a < gestos[i].cantidadAcciones; a++) {
            String tipoAccion;
            switch (gestos[i].acciones[a].tipo) {
                case 0: tipoAccion = "Tecla"; break;
                case 1: tipoAccion = "Media Key"; break;
                case 2: tipoAccion = "Modificador"; break;
                case 3: tipoAccion = "Liberar Modificadores"; break;
                default: tipoAccion = "Desconocido"; break;
            }
            listado += tipoAccion + "(" + String(gestos[i].acciones[a].parametro) + ")";
            if (a < gestos[i].cantidadAcciones - 1) listado += ", ";
        }
    }
    registrarLog(listado);
}
```
codigo 2 ejemplos:
```
// Included in this file are two sample packets captured via Wireshark.
// The first is captured from a latest model XBox Series X wireless controller

// Xbox wireless controller 1914 - pressing right trigger
char packet_bytes_controller[] = {
  0x01, // Report ID
  0x22, // ?
  0x17, // Size (23 bytes)
  0x00, // Seperator before size is counted
  
  // Counting from here onwards there are 23 bytes
  0x13, 0x00, 0x04, 0x00, 0x1b, 0x1e, 0x00, //unknown?
  0xa6, 0x81, // X axis
  0x1d, 0x7c, // Y axis
  0x4c, 0x81, // Z axis
  0xe8, 0x81, // rZ axis
  0x00, 0x00, // Brake (Left trigger)
  0xa0, 0x01, // Accelerator (Right trigger)
  0x00,       // Hat switch
  0x00, 0x00, // Button bitflags
  0x00        // Share button
};

// The second is a packet from our ESP32 controller
// ESP32

char packet_bytes_esp32[] = {
  0x01, // Report ID
  0x22, // ?
  0x17, // Size (23 bytes)
  0x00, // Size seperator
  // Counting from here onwards there are 23 bytes

  0x13, 0x00, 0x04, 0x00, 0x1b, //unknown but identical to a real controller
  0x23, 0x00, // Unknown and differs from a normal controller but still seems to work

  0x00, 0x00, // X axis
  0x00, 0x00, // Y axis
  0x00, 0x00, // Z axis
  0x00, 0x00, // rZ axis
  0x16, 0x03, // Brake (Left trigger)
  0x15, 0x03, // Accelerator (Right trigger)
  0x00,       // Hat switch
  0x00, 0x00, // Button bitflags
  0x00        // Share button
};
#include <Arduino.h>
#include <KeyboardDevice.h>
#include <BleCompositeHID.h>

BleCompositeHID compositeHID("ESP32 LED Keyboard", "Mystfit", 100);
KeyboardDevice* keyboard;

void OnLEDEvent(KeyboardOutputReport data){
    Serial.println(
    "LED Report: Number Lock: " + String(data.numLockActive) + 
    " Caps Lock: " + String(data.capsLockActive) + 
    " Scroll Lock: " + String(data.scrollLockActive) + 
    " Compose: " + String(data.composeActive) + 
    " Kana: " + String(data.kanaActive));
}

void setup()
{
    Serial.begin(115200);

    keyboard = new KeyboardDevice();
    FunctionSlot<KeyboardOutputReport> OnLEDEventSlot(OnLEDEvent);
    keyboard->onLED.attach(OnLEDEventSlot);

    compositeHID.addDevice(keyboard);
    compositeHID.begin();

    Serial.println("Waiting for connection");
    delay(3000);
}

void loop()
{
    keyboard->keyPress(KEY_NUMLOCK);
    delay(10);
    keyboard->keyRelease(KEY_NUMLOCK);
    delay(1000);

    keyboard->keyPress(KEY_CAPSLOCK);
    delay(10);
    keyboard->keyRelease(KEY_CAPSLOCK);
    delay(1000);

    keyboard->keyPress(KEY_SCROLLLOCK);
    delay(10);
    keyboard->keyRelease(KEY_SCROLLLOCK);
    delay(1000);

    keyboard->keyPress(KEY_COMPOSE);
    delay(10);
    keyboard->keyRelease(KEY_COMPOSE);
    delay(1000);
}
#include <Arduino.h>
#include <KeyboardDevice.h>
#include <BleCompositeHID.h>


BleCompositeHID compositeHID("ESP32 Media Keyboard", "Mystfit", 100);
KeyboardDevice* keyboard;

void setup()
{
    Serial.begin(115200);

    // Media keys are not enabled by default
    KeyboardConfiguration config;
    config.setUseMediaKeys(true);

    keyboard = new KeyboardDevice(config);
    compositeHID.addDevice(keyboard);
    compositeHID.begin();

    Serial.println("Waiting for connection");
    delay(3000);
}

void pressReleaseMediaKey(uint32_t keyCode){
    Serial.println("Pressing key " + String(keyCode));
    keyboard->mediaKeyPress(keyCode);
    delay(50);
    keyboard->mediaKeyRelease(keyCode);
    delay(1000);
}

void loop()
{
    if (compositeHID.isConnected())
    {
        pressReleaseMediaKey(KEY_MEDIA_PLAY);
        pressReleaseMediaKey(KEY_MEDIA_PAUSE);
        pressReleaseMediaKey(KEY_MEDIA_RECORD);
        pressReleaseMediaKey(KEY_MEDIA_FASTFORWARD);
        pressReleaseMediaKey(KEY_MEDIA_REWIND);
        pressReleaseMediaKey(KEY_MEDIA_NEXTTRACK);
        pressReleaseMediaKey(KEY_MEDIA_PREVIOUSTRACK);
        pressReleaseMediaKey(KEY_MEDIA_STOP);
        pressReleaseMediaKey(KEY_MEDIA_EJECT);
        pressReleaseMediaKey(KEY_MEDIA_RANDOMPLAY);
        pressReleaseMediaKey(KEY_MEDIA_REPEAT);
        pressReleaseMediaKey(KEY_MEDIA_PLAYPAUSE);
        pressReleaseMediaKey(KEY_MEDIA_MUTE);
        pressReleaseMediaKey(KEY_MEDIA_VOLUMEUP);
        pressReleaseMediaKey(KEY_MEDIA_VOLUMEDOWN);
        pressReleaseMediaKey(KEY_MEDIA_WWWHOME);
        pressReleaseMediaKey(KEY_MEDIA_MYCOMPUTER);
        pressReleaseMediaKey(KEY_MEDIA_CALCULATOR);
        pressReleaseMediaKey(KEY_MEDIA_WWWFAVORITES);
        pressReleaseMediaKey(KEY_MEDIA_WWWSEARCH);
        pressReleaseMediaKey(KEY_MEDIA_WWWSTOP);
        pressReleaseMediaKey(KEY_MEDIA_WWWBACK);
        pressReleaseMediaKey(KEY_MEDIA_MEDIASELECT);
        pressReleaseMediaKey(KEY_MEDIA_MAIL);
    }
}
#include <Arduino.h>
#include <KeyboardDevice.h>
#include <BleCompositeHID.h>

#define KEY_RANGE_MIN KEY_A
#define KEY_RANGE_MAX KEY_RIGHTMETA

#define MODKEY_RANGE_MIN KEY_MOD_LALT
#define MODKEY_RANGE_MAX KEY_MOD_RMETA

BleCompositeHID compositeHID("ESP32 Keyboard", "Mystfit", 100);
KeyboardDevice* keyboard;

void setup()
{
    Serial.begin(115200);

    keyboard = new KeyboardDevice();
    compositeHID.addDevice(keyboard);
    compositeHID.begin();

    Serial.println("Waiting for connection");
    delay(3000);
}

void loop()
{
    if (compositeHID.isConnected())
    {
        uint8_t modKey = 0x01;
        for(uint8_t modKeyCount = 0; modKeyCount < 8; modKeyCount++)
        {
            Serial.println("Pressing modifier key " + String(modKey));
            keyboard->modifierKeyPress(modKey);
            delay(10);
            keyboard->modifierKeyRelease(modKey);
            delay(1000);
            modKey = modKey << 1;
        }

        for(uint8_t keyCode = KEY_RANGE_MIN; keyCode <= KEY_RANGE_MAX; keyCode++)
        {
            Serial.println("Pressing key " + String(keyCode));
            keyboard->keyPress(keyCode);
            delay(10);
            keyboard->keyRelease(keyCode);
            delay(1000);
        }
    }
}
```