Derek Ziegler
Derek Ziegler

Reputation: 11

Trouble with ESP32 Bluetooth LE Keystrokes: Not Working After Power Cycle or Deep Standby on Android TV

I'm working on a project to send keystrokes via Bluetooth LE from an ESP32 to an Android TV, but I've run into two problems that I can’t seem to solve.

The basic setup works as follows: for testing, I send a keystroke using a simple HTTP request (e.g., curl -X GET "http://<ESP-IP>/send?keycode=102"). This successfully sends a power on/off command to the Android TV box.

My Issues:

1.Reconnection after ESP32 Power Cycle:

If I power cycle the ESP32, it reconnects to the Android TV box, but keystrokes are no longer processed by the TV. The ESP32 logs indicate that the keystrokes are being sent, but nothing happens on the TV. To fix this, I have to unpair and re-pair both devices. After re-pairing, everything works fine—until the ESP32 is power cycled again. Deep Standby Mode on Android TV: When the Android TV enters deep standby, the Bluetooth connection to the ESP32 breaks, and I cannot send the power-on command. However, regular remote controls can still wake the box, even when it’s in deep standby. I’m unsure how to tackle these challenges and would greatly appreciate any advice or guidance. My code is attached for reference. I’m using PlatformIO with the Arduino framework.

2. Deep Standby Mode on Android TV:

When the Android TV enters deep standby, the Bluetooth connection to the ESP32 breaks, and I cannot send the power-on command. However, regular remote controls can still wake the box, even when it’s in deep standby. I’m unsure how to tackle these challenges and would greatly appreciate any advice or guidance. My code is attached for reference. I’m using PlatformIO with the Arduino framework.

I’m unsure how to tackle these challenges and would greatly appreciate any advice or guidance. My code is attached for reference. I’m using PlatformIO with the Arduino framework.

Thank you in advance for your help!

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEHIDDevice.h>
#include <HIDTypes.h>
#include <HIDKeyboardTypes.h>
#include <ESPAsyncWebServer.h>
#include <WiFi.h>

BLEHIDDevice* hid;
BLECharacteristic* input;
BLEServer* pServer;

const char* ssid = "MyAp";
const char* password = "1234";

AsyncWebServer server(80);

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    Serial.println("Gerät verbunden");
  }

  void onDisconnect(BLEServer* pServer) {
    Serial.println("Verbindung getrennt, starte Werbung neu...");
    pServer->startAdvertising();
  }
};

void setup() {
  Serial.begin(115200);
  Serial.println("Starte BLE HID Tastatur...");

  // WiFi-Verbindung herstellen
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Verbinde mit WiFi...");
  }
  Serial.println("WiFi verbunden");

  // BLE initialisieren
  BLEDevice::init("ESP32 Keyboard");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  hid = new BLEHIDDevice(pServer);
  input = hid->inputReport(1); // Report ID 1

  hid->manufacturer()->setValue("ESP32");

  uint8_t reportMap[] = {
    0x05, 0x01,                // Usage Page (Generic Desktop)
    0x09, 0x06,                // Usage (Keyboard)
    0xA1, 0x01,                // Collection (Application)
    0x85, 0x01,                // Report ID (1) - Keyboard Report
    0x05, 0x07,                // Usage Page (Key Codes)
    0x19, 0xE0,                // Usage Minimum (Left Control)
    0x29, 0xE7,                // Usage Maximum (Right Control)
    0x15, 0x00,                // Logical Minimum (0)
    0x25, 0x01,                // Logical Maximum (1)
    0x75, 0x01,                // Report Size (1)
    0x95, 0x08,                // Report Count (8)
    0x81, 0x02,                // Input (Data, Variable, Absolute) - Modifier byte
    0x95, 0x01,                // Report Count (1)
    0x75, 0x08,                // Report Size (8)
    0x81, 0x01,                // Input (Constant) - Reserved byte
    0x95, 0x05,                // Report Count (5)
    0x75, 0x01,                // Report Size (1)
    0x05, 0x08,                // Usage Page (LEDs)
    0x19, 0x01,                // Usage Minimum (Num Lock)
    0x29, 0x05,                // Usage Maximum (Kana)
    0x91, 0x02,                // Output (Data, Variable, Absolute) - LED report
    0x95, 0x01,                // Report Count (1)
    0x75, 0x03,                // Report Size (3)
    0x91, 0x01,                // Output (Constant) - LED report padding
    0x95, 0x06,                // Report Count (6)
    0x75, 0x08,                // Report Size (8)
    0x15, 0x00,                // Logical Minimum (0)
    0x25, 0xFF,                // Logical Maximum (101)
    0x05, 0x07,                // Usage Page (Key Codes)
    0x19, 0x00,                // Usage Minimum (0)
    0x29, 0xFF,                // Usage Maximum (255)
    0x81, 0x00,                // Input (Data, Array) - Key array (6 keys)
    0xC0                      // End Collection
  };

  hid->reportMap(reportMap, sizeof(reportMap));
  hid->startServices();

  BLEAdvertising* pAdvertising = pServer->getAdvertising();
  pAdvertising->setAppearance(HID_KEYBOARD);
  pAdvertising->addServiceUUID(hid->hidService()->getUUID());
  pAdvertising->start();

  Serial.println("BLE HID Tastatur gestartet, warte auf Verbindung...");

  // HTTP-Server konfigurieren
  server.on("/send", HTTP_GET, [](AsyncWebServerRequest *request){
    if (request->hasParam("keycode")) {
      String keycodeStr = request->getParam("keycode")->value();
      uint8_t keyCode[8] = {0};
      keyCode[2] = keycodeStr.toInt(); // Konvertiere String zu int
      input->setValue(keyCode, sizeof(keyCode));
      input->notify();
      Serial.println("Keycode gesendet: " + keycodeStr);
           // Taste loslassen
      delay(100); // Kurze Verzögerung
      memset(keyCode, 0, sizeof(keyCode));
      input->setValue(keyCode, sizeof(keyCode));
      input->notify();
      Serial.println("Taste losgelassen");

      request->send(200, "text/plain", "Keycode gesendet: " + keycodeStr);
    } else {
      request->send(400, "text/plain", "Fehlender Parameter: keycode");
    }
  });

  server.begin();
}

void loop() {
  // Keine Datenübertragung in der loop-Funktion
}

Upvotes: 0

Views: 41

Answers (0)

Related Questions