Skip to content

Workable Alternatives

Kyle Johnson edited this page Mar 5, 2024 · 4 revisions

If building and compiling code it's your thing, here are some alternatives:

Similar Thing with a Raspberry Pi

I first wrote this as a Python script running on a Raspberry Pi. It's a bit less work to get it running and should mostly do the same thing.

https://github.com/pkscout/rpi-keyboard-to-mqtt

Doing This Only in Home Assistant

If you can plug the USB device in to your Home Assistant setup, you can use the Keyboard Remote integration. This is really only useful if you have one remote and it will be close enough for the RF signal to get to your HA setup. In my case I can still use the remote anywhere in our 1200 sqft apartment. If you want multiple remotes it's going to get harder and more confusing to setup, but I suppose it's possible.

The Connection

If you're using the Home Assistant OS or one of their hardware boxes, this should be "plug and play." If you're running Docker (like I am on a Synology NAS), you need to add a few things to the Docker compose file. It's a few lines related to dev/input and device/device groups. Here's my complete file:

version: '3'
services:
  homeassistant:
    container_name: homeassistant
    volumes:
      - '/volume1/configs/homeassistant/config:/config'
      - '/dev/input:/dev/input'
    environment:
      - TZ=America/New_York
    image: 'homeassistant/home-assistant:latest'
    restart: unless-stopped
    privileged: true
    security_opt:
      - apparmor=unconfined
    network_mode: host
    device_cgroup_rules:
      - 'c 13:* rmw'
    devices:
      - '/dev/input/'

Setting Up the Keyboard Remote Integration

Currently you can only configure this integration in YAML. There are some instructions on the page I linked above. In typical HA fashion, they're only really useful if you already know what you're doing... Anyway, I found my remote was pushing things on both event1 and event2, so I had to configure two remotes thusly in configuration.yaml:

keyboard_remote:
  - device_descriptor: '/dev/input/event1'
    type:
      - 'key_up'
      - 'key_down'
  - device_descriptor: '/dev/input/event2'
    type:
      - 'key_up'
      - 'key_down'

and then create a trigger based binary sensor that would be off when a key is up and on when a key is down. Where you put it depends a bit on how you've organized things. Basically it has to go in the templates section. For me I have this line in my config:

template: !include_dir_merge_list template

So the trigger template below is in a file called remote.yaml in the template folder. This binary sensor has some attributes with the key code pressed appended with either -L or -S depending on whether it was a long or short press (inspired by this post from The Helpful Idiot).

- trigger:
  - platform: event
    event_type: keyboard_remote_command_received
    event_data:
      type: key_down
    id: "on"
  - platform: event
    event_type: keyboard_remote_command_received
    event_data:
      type: key_up
    id: "off"
  binary_sensor:
    - name: remote_button_press
      state: "{{ trigger.id }}"
      attributes:
        timestamp_up: >
          {% if trigger.id == 'off' %}
            {{ as_timestamp( trigger.event.time_fired, none)|float(0) }}
          {% else %}
            {{ this.attributes.timestamp_up|float(0) }}
          {% endif %}
        timestamp_down: >
          {% if trigger.id == 'on' %}
            {{ as_timestamp( trigger.event.time_fired, none)|float(0) }}
          {% else %}
            {{ this.attributes.timestamp_down|float(0) }}
          {% endif %}
        pressed_duration: >
          {% if trigger.id == 'on' %}
            0
          {% else %}
            {{ as_timestamp( trigger.event.time_fired, none)|float(0) - (this.attributes.timestamp_down)|float(0) }}
          {% endif %}
        code: >
          {% if trigger.id == 'on' %}
            {{ trigger.event.data.key_code }}
          {% elif (as_timestamp( trigger.event.time_fired, none)|float(0) - (this.attributes.timestamp_down)|float(0)) > 0.3 %}
            {{ trigger.event.data.key_code }}-L
          {% else %}
            {{ trigger.event.data.key_code }}-S
          {% endif %}

Once you do all that, you can trigger it in an automation like this (it triggers on button release):

trigger:
  - platform: state
    entity_id:
      - binary_sensor.remote_button_press
    from: "on"
    to: "off"

The rest of the automation is mostly like the example on this wiki, except the condition is a bit different (uses trigger.to_state.attributes.code instead of trigger.to_state.state:

      - conditions:
          - condition: template
            value_template: "{{ trigger.to_state.attributes.code == '1-S' }}"
        sequence:
          - service: script.uc_general_power
            metadata: {}
            data: {}