[Feature Request] Using ESPHome to emulate a usb keyboard

I saw this project for a WiFi Duck where you can use a small esp8266 as a usb keyboard to send keyboard commands to a computer using ducky script. I thought maybe this functionality to use an esp8266 as a usb HID keyboard could eventually be implemented in ESPHome. Combined with AutoHotKey, this could create some really powerful automations on your computer.

There is already this software to control a Windows PC over MQTT but the downside is that you have to install it on the PC and there are some limitations on what you can run or execute.

What are some cool automations or use-cases for a USB keyboard emulator can you think of?

1 Like

You have the situation entirely wrong IMHO.

esphome speaks to home assistant. home assistant controls other stuff. There is little use in just sending a HID keyboard code to home assistant.

What you probably want is autohotkey support in home assistant.

I know this a pretty old thread but I’d also love to see this request implemented to ESPHome. Imho you @nickrout got the situation wrong, not @LUNZ. The purpose would not be to connect such a “WiFi Duck” to the device running Home Assistant, which, yes would be pretty pointless. You could however have full control over any computer, no matter what kind of OS it runs on. Sou you would not send a keyboard codet to home assistant but instead from home assistant to any other device. To give some real use cases:

  • You could unlock your computer from Home Assistant, e.g. by placing a rfid tag on a reader (the WiFi Duck would only have to enter the correct password)
  • You have full control over wall mounted tablets, and that’s something I’m searching a solution for since days. I have two old Microsoft Surfaces 3, which I’m planning to mount as a HA Dashboard on the wall. The problem is that I can’t find any way to turn the tablets on remotly. They of course use WiFi so Wake on Lan does not work and any local script will stop working as soon as I bring the tablets to sleep as the CPU turns off. The only way to wake them is using the power button, OR - and here comes the feature request in - using a USB keyboard.

And controlling power is not the only thing you could do with it on a wall mounted tablet:

  • You could automatically open VLC to open the stream of a camera based on a motion sensor or the door bell, which espically on slow devices works way better than using lovelace based streams
  • The browser can be controlled, e.g. opening a news page at a specific time or simply reload the Home Assistant interface if it ever should get stuck (happened a few times to me)

Edit:
Here is a project which does almost exactly what I want: Use an ESP8266 as USB HID Device. Having espusb integrated to ESPHome would be awesome. I managed to run espusb on one of my ESP’s and the example programm worked perfect, you can control the Keyboard using a webinterface on any other device. However I could not find a way to integrate this into Home Assistant to automate stuff

4 Likes

You should be able to use a commandline switch or rest switch to run it. What do the web urls look like?

Bottom line, yes an esp can easily emulate an hid keyboard. There are arduino libraries that make it easy to do. Not sure if they have been ported to esphome, but you could always do the arduino code yourself and use mqtt instead.

Another complicated alternative if esphome is needed (and no ported libs available) is hook an arduino nano up with uart to the esp. Nanos are the easiest arduino to setup as an hid device (using arduino libraries). Then use esphome UART to send keys to a serial port on the nano board, which is hooked to your surface usb port and will appear just like a keyboard to windows.

1 Like

Or possibly using the libraries in an esphome custom component.

Anyway, github is the place for esphome feature requests.

Yes, at the end of the day github is the final stage for feature adds. So might as well start there to fast forward the process a bit. This idea does sound like it would have popular applications. So would be nice to see an official esphome component for it, vs custom components and how to guides.

1 Like

That was also my thought, however espusb uses websockets for communication between the webinterface and the backend. So sadly it’s not as easy.

No, the Arduino HID librariers only work an Arduino Boards based on the Atmega32u4, such as the Leonardo, as they need access to the specific Hardware Features of this microcontroller. That’s why it also can’t work on a Nano. espusb doesn’t need those specific hardware features as it completely emualtes the usb interface using bitbanging (if I got it right).

That’s what makes the whole thing that complicated. Also I realized espusb sadly seems kind of abandoned and to compile it you need a specific old version of the esp sdk. That makes it probably very hard if not impossible to add it as ESPHome component…

That’s probably the only alternative, when wanting to use ESPHome but it would require an Atmega32u4 Board as described above.

Also I just found out that the Raspberry Pi Zero seems to have HID capabilities. I’ll give it a try tomorrow

1 Like

No, github is the starting point for esphome feature requests.

Shoot, did I say nano? I meant micro lol. You knew what I meant anyways. :slight_smile:

1 Like

One option would be to emulate a bluetooth keyboard, and skip the USB altogether. This device made me think of it Bluefruit EZ-Key - 12 Input Bluetooth HID Keyboard Controller - v1.2 - discontinued, but they probably make something else now.

1 Like

Another option is to get the chip out of a disused USB keyboard. They are simply a matrix - you could wire that to an esp.

1 Like

I’ve earlier used an ESP32 with BLE Keyboard code, using MQTT to communicate with HA. This way I could send keystrokes to the ESP32 which again control my satellite receiver (support BT remote).

1 Like

Wow that’s a great idea!

A quick google search shows that someone was using this to remotely unlock their iPad. I’m sure there are some other interesting use cases too

@TheStigh can you share a link to the project that you used that has mqtt support?

@LUNZ Can see if I find the Arduino project and share it with you :slight_smile:

1 Like

This version I’ve kept the debugging versions.
Using a WEMOS D1 MINI ESP32
Than letting my remote pair to this ESP as a remote.
Sending MQTT messages to what channel you want to switch to… :slight_smile:

#include <PubSubClient.h>
#include <WiFi.h>
#include <BleKeyboard.h>

#define BLETOPIC "BLE/command"
#define SERVICETOPIC "SERVICE/service"

int STATUS_PIN = 2;

WiFiClient client;
BleKeyboard bleKeyboard("ESP32 BT Remote", "Espressif", 100);



char *ssid      = "<WIFI>";
char *password  = "<PASSWORD>";
const char* mqtt_server = "<IP>";
const char* mqtt_user = "<USER>";
const char* mqtt_password = "<PASSWORD>";
unsigned long previousMillis = 0;
unsigned long interval = 30000;


void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
//  Serial.print(". Message: ");
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
//    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  } 
  Serial.println();
  Serial.print("Changing to channel : ");
  Serial.print(messageTemp);
  bleKeyboard.print(messageTemp);
  Serial.println();
  Serial.println("-----------------------");
//  Serial.print("Sending Enter key...");
//  bleKeyboard.write(KEY_RETURN);
//  Serial.println();
//  Serial.println();
}

PubSubClient mqtt(mqtt_server, 1883, callback, client);

void setup() {

  Serial.begin(115200);
  
  pinMode(STATUS_PIN, OUTPUT);
  digitalWrite(STATUS_PIN, HIGH);

  Serial.println();
  Serial.println("Connecting to WiFi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin (ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.println(WiFi.localIP());
  Serial.println();
  Serial.println("WiFi connected");

  connectMQTT();

  Serial.println();
  Serial.println("Starting BLE...");
  bleKeyboard.begin();


  Serial.println();
  Serial.println("Setup Done!");
}

void loop() {
//  if (bleKeyboard.isConnected()) {
//    Serial.println("BLE OK!");
//  }

  unsigned long currentMillis = millis();
  // if WiFi is down, try reconnecting
  if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >=interval)) {
    Serial.print(millis());
    Serial.println("Reconnecting to WiFi...");
    WiFi.disconnect();
    WiFi.reconnect();
    previousMillis = currentMillis;
  }

  mqtt.loop();

}


/******************************************************************************
 ****                                                                      ****
 ****                         connectMQTT                                  ****
 ****                                                                      ****
 *****************************************************************************/

void connectMQTT() {
  while (!mqtt.connected()) {
    Serial.println("Attempting MQTT connection...");
    if (mqtt.connect("ESP32 BT Remote", mqtt_user, mqtt_password)) {
      Serial.println("connected");
      mqtt.publish(SERVICETOPIC, "ESP32 BT Remote are now Live");
      Serial.println("Connection information sent to MQTT broker!");
      mqtt.subscribe(BLETOPIC,1);
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqtt.state());
      Serial.println(" try again in 2 seconds");
      // Wait 2 seconds before retrying
      delay(2000);

    }
  }
}


/******************************************************************************
 ****                                                                      ****
 ****                         publishMQTT                                  ****
 ****                                                                      ****
 *****************************************************************************/
 
void publishMQTT(String topic, String message) {
  if (!mqtt.connected()) {
    reconnectMQTT();
  }
  mqtt.publish(topic.c_str(), message.c_str());
}


/******************************************************************************
 ****                                                                      ****
 ****                        reconnectMQTT                                 ****
 ****                                                                      ****
 *****************************************************************************/
 
void reconnectMQTT() {
  // Loop until we're reconnected
  while (!mqtt.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqtt.connect("ESP32 BT Remote")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      mqtt.publish(SERVICETOPIC, "ESP32 BT Remote are Live again");
      // ... and resubscribe
      mqtt.subscribe(BLETOPIC,1);
    } else {
      Serial.print("failed, rc = ");
      Serial.print(mqtt.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

Have you seen this?
It creates an Esphome project which can read IR codes and sends BLE HID keyboard keys.
The project includes the YAML file and the custom BLE component as a header file for the BLE HID keyboard. It uses the well-known library https://github.com/T-vK/ESP32-BLE-Keyboard

3 Likes

Collected based on my firmware: GitHub - dmamontov/esphome-blekeyboard: ESPHome BLE Keyboard
I think this is what will suit you.

4 Likes

I think here:

 libraries:
    - ESP32 BLE Arduino@>=1.0.1
    - https://github.com/T-vK/ESP32-BLE-Keyboard/releases/download/0.3.0/ESP32-BLE-Keyboard.zip  

That’s looking for something else to include called “sdkconfig.h” which doesn’t have an external URL or anything.
I wonder if we can find out what that is and move all of these libraries to the ESPHome folder.
I got out of Arduino stuff for this reason lol

I think you should update both ESPHome and pio. On the most recent version, everything is definitely fine.