Faking an IR remote control using ESPHome

Many thanks to OP and all the other contributions in here :heart:
Thanks to you guys I was able to create a light abstraction for some IR-only lights, and it works perfectly now :tada:

I have created a simple GitHub repo to document my progess. The code specifically replicates the IR Remote that came with the lights I wanted to control, but it should be relatively straight forward to adapt it to some other remote that you got. Feel free to give it a look :smiling_face:

1 Like

Hi everyone,

I’d like to introduce a new project I’ve been working on: the RGB Strip Remote IR Card for Home Assistant!

This custom card replicates the functionality of the original 44-key RGB strip remote, allowing you to fully control your RGB strip lights directly from Home Assistant. It works seamlessly with an ESPHome-configured IR transmitter, sending the exact same IR signals as the original remote, giving you full access to all the RGB modes, colors, and effects.

Here’s a quick overview of what it does:

  • Complete Control: Includes buttons for power, color presets, DIY modes, and transition effects (fade, jump).
  • Easy Setup: Simple installation by adding a few lines to your Home Assistant Lovelace UI and configuring an ESPHome device.
  • Works with Any RGB Strip: As long as you have an IR receiver and the appropriate ESPHome setup, this card should work with your RGB strip.

Features:

  • Emulates the original remote with the same button layout and functionality.
  • Control your RGB strip’s colors, brightness, and transitions directly from Home Assistant.
  • Integrates perfectly with ESPHome.

If you’re looking for a user-friendly solution to control your RGB strips with IR signals from Home Assistant, check out the project here: rgb_strip_remote_ir_card

Capture

Feel free to give it a try and let me know what you think. I’d love to hear your feedback!

1 Like

Thanks, very useful thread.

For the sake of anyone trying to do what I was doing, there’s a really useful resource for Sony IR codes here:

https://www.righto.com/2010/03/understanding-sony-ir-remote-codes-lirc.html

And a list of reference codes here:

http://www.hifi-remote.com/sony/
http://www.hifi-remote.com/sony/Sony_rcvr.htm for my specific device.

You can sniff codes as detailed in this post, but some Sony commands (e.g. explicit power on and power off) are not exposed on any remote control, so you need to convert them from the list above, which is detailed in the first link:

To work through a 20-bit example, if I have a Sony VCR/DVD Combo with a device code of 26.83, the site tells me that the code for “power” is 21. Convert 21 to a 7 bit binary value, 26 to a 5 bit binary value, and 83 to a 8 bit binary value. Then reverse and concatenate the bits: binary 1010100 + 01011 + 11001010, which is a8bca in hex.

Oh, and don’t forget that Sony devices expect each command to be repeated three times, so use repeat: times: 3 in your esphome config!

Once you get your head around it, it’s very simple but it cost me a couple of hours last night so this is here for the next person who wants to fiddle with Sony stuff.

1 Like

Very useful thread, thanks. But I need some help please!

I’ve got the IR receiver and transmitter working, each attached to a separate ESP8266, and integrated into Home Assistant. I’ve recorded the IR codes from my Logitech Harmony remote control - itself set up for Dynaudio Xeo 3 active loudspeakers - and can see what look like the right codes coming up.
e.g. Power On

[15:58:27][I][remote.jvc:049]: Received JVC: data=0x00FF
[15:58:27][I][remote.lg:054]: Received LG: data=0x00FF00FF, nbits=32
[15:58:27][I][remote.nec:097]: Received NEC: address=0xFF00, command=0xFF00 command_repeats=1
[15:58:27][I][remote.pioneer:149]: Received Pioneer: rc_code_X=0x0000

plus various lines of pronto codes.

Power Off

[16:18:28][I][remote.jvc:049]: Received JVC: data=0x00FF
[16:18:28][I][remote.lg:054]: Received LG: data=0x00FF28D7, nbits=32
[16:18:28][I][remote.nec:097]: Received NEC: address=0xFF00, command=0xEB14 command_repeats=1
[16:18:28][I][remote.pioneer:149]: Received Pioneer: rc_code_X=0x0014

plus various lines of pronto codes.

This and the others seem to align with the Dynaudio guidance here.

I have put the codes into the ESPHome script for the transmitter and can successfully send the signal to the receiver, where it is decoded correctly. (The range is about 30cm, which is a bit feeble, but as I’m going to tape the transmitter to the loudspeaker IR sensor, I don’t think that will matter.)

button:
  - platform: template
    name: "On NEC"
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0xFF00
          command: 0xFF00
  - platform: template
    name: "Off NEC"
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0xFF00
          command: 0xEB14
  - platform: template
    name: "On Pioneer"
    on_press:
      - remote_transmitter.transmit_pioneer:
          rc_code_1: 0x0000
  - platform: template
    name: "Off Pioneer"
    on_press:
      - remote_transmitter.transmit_pioneer:
          rc_code_1: 0x0014  

All good so far. The problem is that the loudspeakers fail to respond at all to the signals sent from the IR transmitter, even when they are right together. I’ve been tending to use the NEC codes because the Dynaudio guidance refers to the NEC protocol. However that guidance only gives 2 digit codes, whereas the actual NEC codes are of the form 0x0014 etc. I also see the guidance states that the “Vendor Code” is 00FF. I don’t know what this is so I’ve done nothing with it.

I also noticed, when writing the yaml for the transmitter that the Pioneer syntax required rc_code_1 to make it work but it shows up as rc_code_X on the receiver logs. It wouldn’t compile unless I used the rc_code_1

Does anyone have any advice on what to do now? As it all seems to be set up to mimic the same codes as the Logitech Harmony remote correctly, I am flummoxed about why it won’t operate the actual speakers.

Embarrassingly, I think I have already found the problem. It seems the IR led I’m using is highly directional and has a very narrow beam, as well as being low power. It does make the speakers change settings when positioned close and at a certain angle. I’ll need to find some more powerful LEDs from somewhere.

I spoke too soon. Rigged up with the transmitter as close as possible to the sensor on the loudspeakers I am getting some commands to work, but most not. I can adjust volume up and down and two out of three inputs, but on, off, mute, and one input channel don’t work.

I’ve rescanned the codes from the (working perfectly with the loudspeakers) Logitech Harmony remote and checked that I have put in the same NEC commands into the transmitter yaml that show up.

button:
 - platform: template
   name: "On NEC"
   on_press:
     - remote_transmitter.transmit_nec:
         address: 0xFF00
         command: 0xFF00
 - platform: template
   name: "Off NEC"
   on_press:
     - remote_transmitter.transmit_nec:
         address: 0xFF00
         command: 0xEB14
 - platform: template
   name: "Volume Up NEC"
   on_press:
     - remote_transmitter.transmit_nec:
         address: 0xFF00
         command: 0xF906
 - platform: template
   name: "Volume Down NEC"
   on_press:
     - remote_transmitter.transmit_nec:
         address: 0xFF00
         command: 0xFB04

The first two of these don’t work - the second two do. Is there any subtly I don’t know about the syntax of NEC codes in the yaml? I’ve just plugged in the address and command values that have come off the IR sniffer logs. I’m unsure where the values after the 0x come from or mean as they are all different and not mentioned in the Dynaudio guidance (linked in the original post)

Is it possible that the LED you are using has a different infrared wavelength than your loud speakers?
Most remotes use a wavelength of 940 nm but you might have bought a LED with 850 nm.

Thanks for this, helped me to get my lights from toom hardware store to night light mode and back to normal

1 Like

Thanks and sorry to be slow replying- I have been travelling. The transmitter I currently have is a rx/tx pair I bought off Amazon and I was hoping for the best with respect to compatibility, but the wavelength isn’t specified.

I’ve now got some 940nm ones on order from a reputable shop which I will try out and report back on later

1 Like

Hi.

I’m adding a comment here because I appreciate the hardware suggestions but as a first-time ESPHome flasher, I ran into some confusion setting up the HiLetgo 2pcs ESP8285 ESP-01M IR Infrared Transmitter Receiver Module Digital Infrared Transceiver Sensor WiFi Remote Control Switch and HiLetgo CP2102 USB 2.0 to TTL Module Serial Converter Adapter Module USB to TTL Downloader with Jumper Wires. I’m posting this in case it might help other noobs like me.

The trouble involved two problematic steps:

  • ESPHome Web Installer error: wifi not found after initialization.
  • Not understanding that the ESP8285 ESP-01M needs the jumper removed after initialization.

ESPHome is super cool but this wifi error after initialization makes it seem like I did something wrong. Nothing is actually wrong and this probably shouldn’t show as an error. I will write something on the ESPHome site about that but I’m only saying it here to point out to others that it’s not you!! :slight_smile:

With this particular device, after the initialization step (which does NOT need the device to be connect to the HA instance) you then need to remove the double jumper (see photos).


In the end, I successfully set up a Toto Washlet remote transmitter. For completeness, here is my YAML for the Toto:

esphome:
  name: "toto-washlet-ir-521cbe"
  friendly_name: Toto Washlet IR ESPHome 521cbe
  min_version: 2024.11.0
  name_add_mac_suffix: false

esp8266:
  board: esp01_1m

# Enable logging
logger:
  level: VERBOSE

# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

remote_receiver:
  pin:
    number: GPIO14
    inverted: true
#  dump: all
  dump: toto

remote_transmitter:
  pin: GPIO4
  carrier_duty_percent: 50%

button:

  - platform: template
    name: "Stop"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0x0  # Stop
          rc_code_1: 0x0
          rc_code_2: 0x0

  - platform: template
    name: "Rear"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0xA8  # Rear
          rc_code_1: 0x6
          rc_code_2: 0x2

  - platform: template
    name: "User 1"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0x95  # User
          rc_code_1: 0x6
          rc_code_2: 0x1 # User 2?

  - platform: template
    name: "User 2"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0x95  # User
          rc_code_1: 0x6
          rc_code_2: 0x2 # User 2?

  - platform: template
    name: "Oscillate"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0x60  # Oscillate
          rc_code_1: 0x0
          rc_code_2: 0x0

  - platform: template
    name: "Puslate"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0xE0  # Pulsate
          rc_code_1: 0x0
          rc_code_2: 0x0

  - platform: template
    name: "Ron Special"
    on_press:
      - remote_transmitter.transmit_toto:
          command: 0xA8  # Rear
          rc_code_1: 0x6
          rc_code_2: 0x2
      - remote_transmitter.transmit_toto:
          command: 0x95  # User
          rc_code_1: 0x6
          rc_code_2: 0x2 # User 2?
      - remote_transmitter.transmit_toto:
          command: 0x60  # Oscillate
          rc_code_1: 0x0
          rc_code_2: 0x0
1 Like

Or maybe it IS you. This is from the product page you linked: