Faking an IR remote control using ESPHome

This is what I get in purple

`
[19:15:39][C][wifi:505]: WiFi:

[19:15:39][C][wifi:363]: Local MAC: [redacted]
[19:15:39][C][wifi:364]: SSID: [redacted]
[19:15:39][C][wifi:365]: IP Address: [redacted]
[19:15:39][C][wifi:367]: BSSID: [redacted]
[19:15:39][C][wifi:368]: Hostname: ‘ir-zender’
[19:15:39][C][wifi:370]: Signal strength: -73 dB ▂▄▆█
[19:15:39][C][wifi:374]: Channel: 1
[19:15:39][C][wifi:375]: Subnet: 255.255.255.0
[19:15:39][C][wifi:376]: Gateway: 192.168.2.254
[19:15:39][C][wifi:377]: DNS1: 0.0.0.0
[19:15:39][C][wifi:378]: DNS2: 0.0.0.0
[19:15:39][C][logger:301]: Logger:
[19:15:39][C][logger:302]: Level: DEBUG
[19:15:39][C][logger:303]: Log Baud Rate: 115200
[19:15:39][C][logger:305]: Hardware UART: UART0
[19:15:39][C][remote_transmitter:015]: Remote Transmitter…
[19:15:39][C][remote_transmitter:016]: Channel: 0
[19:15:39][C][remote_transmitter:017]: RMT memory blocks: 1
[19:15:39][C][remote_transmitter:018]: Clock divider: 80
[19:15:39][C][remote_transmitter:019]: Pin: GPIO19
[19:15:39][C][remote_transmitter:022]: Carrier Duty: 50%
[19:15:39][C][captive_portal:088]: Captive Portal:
[19:15:39][C][web_server:151]: Web Server:
[19:15:39][C][web_server:152]: Address: [redacted]:80
[19:15:39][C][mdns:108]: mDNS:
[19:15:39][C][mdns:109]: Hostname: ir-zender
[19:15:39][C][ota:093]: Over-The-Air Updates:
[19:15:39][C][ota:094]: Address: [redacted]:3232
[19:15:39][C][ota:097]: Using Password.
[19:15:39][C][api:138]: API Server:
[19:15:39][C][api:139]: Address: [redacted]:6053
[19:15:39][C][api:141]: Using noise encryption: YES`

But if I unplug the IR transmitter I get exactly the same…

Yes, the GPIO pin can’t detect if something is actually connected to it. YAML code?

#remote_receiver:
#  pin: 
#    number: GPIO19
#    inverted: true
#    mode: INPUT_PULLUP
#  dump: all

remote_transmitter:
  pin: GPIO19
  carrier_duty_percent: 50%


# Individual switches
button:
  - platform: template
    name: "On/Off JVC"
    on_press:
      - remote_transmitter.transmit_jvc:
          data: 0xC3E1
  - platform: template
    name: "On/Off LG"
    on_press:
      - remote_transmitter.transmit_lg:
          data: 0xC3E10700
          nbits: 32
  - platform: template
    name: "On/Off NEC"
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x87C3
          command: 0x00E0

I cannot find anything suspicious in your code.
What puzzles me is that there is no log entry whatsoever of the transmit commands.
My next step would be to add logging commands immediately before and after the transmit commands to see whether these make their way into the log.

Thanks. One last thing, on the specification page it says:

High drive currents needed to pull small;

Anything I can do for that in the Esphome code?
Otherwise I guess then the board is broken, will try to get a new emitter.

Not sure if I understand your question and the quote from the specs correctly. But your transmitter contains a driver transistor so the current that is draws from the GPIO is definitely small. GPIO can handle it.

And again: The code has no way to detect, if something is connected to a GPIO output, or of it’s connected but broken, or of the GPIO itself is damaged. The log line for the transmission should appear in all these cases. That’s what puzzles me about your problem. Hence the proposal to add logging commands before and after, to see if the on_press triggers and runs through.

Now this yaml

# Example configuration entry
remote_transmitter:
  pin: GPIO13
  carrier_duty_percent: 50%

# Individual switches
button:
  - platform: template
    name: "On/Off JVC"
    on_press:
      - logger.log: "Hello World"
      - remote_transmitter.transmit_jvc:
          data: 0xC3E1
      - logger.log: "Hello World 2"

Results in

11:00:17	[D]	[button:010] 'On/Off JVC' Pressed.
11:00:17	[D]	[main:280] Hello World
11:00:17	[D]	[main:286] Hello World 2

I’m about to give up. Tried another tranmitter, different GPIO’s etc. Only thing I can think of it’s the actual ESP32 board…

Yes, me too. I’m definitely running out of ideas here.

@gaz99 Did you ever try using the ESP8285? Any issues?

On my Sony device I add repeat: 5 to the transmit command with success.

      - remote_transmitter.transmit_sony:
          data: 0x00000A81
          nbits: 12
          repeat: 5

I have a rangehood that has an IR remote. I successfully copied all the buttons on the remote but wonder whether there are more commands the rangehood can respond to, for example, turn on or off instead of power toggle. Or a specific fan speed instead of using up and down. Is there any practical way to discover additional working codes?

This is an interesting question. The remote that I describe in the original guide also only has an on/off toggle. And I indeed tried to find dedicated on and off codes. But the number of possible combinations is to high and a web search also yielded no result. So I gave up.

@Jpsy I wonder whether it is possible, or rather easy, to cycle through all possible hex combination for the 4chr command. I need to figure out if esphome can do it… if it can, then I can watch the log while it does so to catch any undocumented commands.

IMHO the problem is not cycling through all commands. This could be easily done, i.e. in Node RED in HA. The difficult part is to automatically assess the outcome of each command. You could do this by attaching sensors to the controlled object that can detect some basic states. But the task becomes even more involved as some commands may change the results of following commands down the test chain. I.e. the power toggle command will ruin all following tests if it switches the target off. So you have to come up with a clever design of your command sequence and you might also have to feed back you sensor results into that sequence.

@Jpsy The rangehood vent only has 4 fan speeds, a light on/off and a power on/off. Other functions like clock are of no use. I am not sure how many commands would need to be sent, but I don’t expect there to be so many I can’t stand in front of the rangehood to see if it reacts. It also beeps very loudly when a command works.

I want to track the device state after pressing the remote.

I see, when the device is ON, it returns 2 lines of pronto and when its turned OFF, it returns 1 line.

[20:12:48][D][button:010]: 'On/Off Pioneer' Pressed.
[20:12:48][D][remote_transmitter:083]: Sending remote code...
[20:12:48][I][remote.pronto:237]: Received Pronto: data=0000 006D 0001 0000 0009 0181 06C3
[20:12:49][I][remote.pronto:237]: Received Pronto: data=0000 006D 0004 0000 0015 002E 00F5 0008 001A 0033 0056 0181 06C3

[20:13:32][D][button:010]: 'On/Off Pioneer' Pressed.
[20:13:32][D][remote_transmitter:083]: Sending remote code...
[20:13:32][I][remote.pronto:237]: Received Pronto: data=0000 006D 0001 0000 0005 0181 06C3

[20:14:19][D][button:010]: 'On/Off Pioneer' Pressed.
[20:14:19][D][remote_transmitter:083]: Sending remote code...
[20:14:19][I][remote.pronto:237]: Received Pronto: data=0000 006D 0001 0000 0006 0181 06C3
[20:14:20][I][remote.pronto:237]: Received Pronto: data=0000 006D 0002 0000 005A 0052 00DD 0181 06C3

Is there a way to make a binary sensor with this?

Yes sure. With the .on_pronto event automation of the remote_receiver you can catch any incoming data and react to it. If you cannot tell the on / off state from the data itself, but only from one or two returns, then I would do something like this:

  • In your toggle on/off button action reset a global counter variable to zero, transmit the IR sequence, and then start a delay of 2 seconds.
  • In receiver’s on_pronto increment that counter variable
  • After the delay check whether counter is 1 or 2 and set a binary template sensor to off or on accordingly.
1 Like

yes, I’m not able to distinguish the off action from the data returned. I think using the 2 returns are only option. Can you pls share an example how to increment the variable with on_pronto?
Here is my current code:


remote_receiver:
  id: receiver
  dump: all
  pin:
    number: GPIO8
    inverted: true
    mode: INPUT_PULLUP

remote_transmitter:
  id: transmitter
  pin: GPIO7
  carrier_duty_percent: 50%    


button:
  - platform: restart
    id: restart_button
    name: Restart

  - platform: safe_mode
    id: safe_mode_button
    name: Safe Mode

  - platform: template
    name: "TV On/Off"
    on_press:
      - remote_transmitter.transmit_pioneer:
          rc_code_1: 0x0212  

There is actually an example in the docs that shows you how to define and how to increment a global variable:

Please read, try and I will help, if you get stuck.

Thank you so much!
So I did this


binary_sensor:
  - platform: gpio
    id: reset_button
    pin: GPIO26

  - platform: template
    name: Device State Sensor
    id: device_state
    device_class: power
    lambda: |-
      if ( id(my_global_int)>1) {
        return true;
      } 
      else {
        return false;
      };
            

sensor:
  - platform: uptime
    name: Uptime

text_sensor: 
  - platform: wifi_info
    ip_address:
      id: ip_address
      name: IP Address

globals:
  - id: my_global_int
    type: int
    restore_value: no
    initial_value: '0'

remote_receiver:
  id: receiver
  dump: all
  pin:
    number: GPIO8
    inverted: true
    mode: INPUT_PULLUP
  on_pronto:
    then:
      - lambda: |-
          id(my_global_int) += 1;  
          ESP_LOGD("main", "Reset counter: %d", id(my_global_int));

remote_transmitter:
  id: transmitter
  pin: GPIO7
  carrier_duty_percent: 50%    



button:
  - platform: restart
    id: restart_button
    name: Restart

  - platform: safe_mode
    id: safe_mode_button
    name: Safe Mode

  - platform: template
    name: "TV On/Off"
    on_press:
      - remote_transmitter.transmit_pioneer:
          rc_code_1: 0x0212  
      - lambda: |-
          id(my_global_int) = 0;  
          ESP_LOGD("main", "Reset counter: %d", id(my_global_int));          
  

But the reset counter is not initializing! I coudn;t figure out how to add the delay, may be thats why. the Sensor stays on.

[17:31:55][I][ota:113]: Boot seems successful, resetting boot loop counter.
[17:31:55][D][lt.preferences:104]: Saving 1 preferences to flash...
[17:31:55][D][lt.preferences:132]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[17:32:28][D][main:082]: Reset counter: 1
[17:32:28][I][remote.jvc:049]: Received JVC: data=0x02FD
[17:32:28][I][remote.lg:054]: Received LG: data=0x02FD48B7, nbits=32
[17:32:28][I][remote.nec:070]: Received NEC: address=0xBF40, command=0xED12
[17:32:28][I][remote.pioneer:149]: Received Pioneer: rc_code_X=0x0212
[17:32:28][I][remote.pronto:237]: Received Pronto: data=0000 006D 0022 0000 0155 00AE 0015 0016 0015 0018 0015 0016 0017 0018 0013 0016 0013 0018 0014 0043 0015 0015 0016 0043 0015 0043 0016 0041 0015 0042 0016 0043 0016 0042 0015 0017 0015 0040 0017 0016 0014 0043 0016 0016 0017 0015
[17:32:28][I][remote.pronto:239]: 0015 0042 0016 0016 0016 0016 0015 0017 0015 0043 0016 0015 0016 0042 0016 0041 0015 0016 0015 0043 0015 0042 0015 0042 0016 0181 06C3
[17:32:29][W][component:204]: Component remote_receiver took a long time for an operation (0.06 s).
[17:32:29][W][component:205]: Components should block for at most 20-30ms.
[17:32:29][D][main:082]: Reset counter: 2
[17:32:29][I][remote.pronto:237]: Received Pronto: data=0000 006D 0002 0000 0159 0054 0016 0181 06C3
[17:32:29][D][binary_sensor:036]: 'Device State Sensor': Sending state ON
[17:32:29][D][main:082]: Reset counter: 3
[17:32:29][I][remote.pronto:237]: Received Pronto: data=0000 006D 0003 0000 0075 000B 0016 002F 0096 0181 06C3
[17:32:46][D][main:082]: Reset counter: 4
[17:32:46][I][remote.jvc:049]: Received JVC: data=0x02FD
[17:32:46][I][remote.lg:054]: Received LG: data=0x02FD48B7, nbits=32
[17:32:46][I][remote.nec:070]: Received NEC: address=0xBF40, command=0xED12
[17:32:46][I][remote.pioneer:149]: Received Pioneer: rc_code_X=0x0212
[17:32:46][I][remote.pronto:237]: Received Pronto: data=0000 006D 0022 0000 0155 00AE 0015 0016 0016 0015 0016 0016 0016 0016 0015 0017 0015 0015 0015 0044 0015 0016 0016 0041 0015 0042 0016 0042 0017 0042 0017 0041 0017 0041 0014 0015 0016 0042 0018 0014 0016 0041 0016 0018 0014 0016
[17:32:46][I][remote.pronto:239]: 0015 0042 0017 0016 0014 0018 0014 0018 0015 0043 0016 0016 0015 0043 0015 0043 0015 0017 0014 0043 0016 0041 0015 0042 0017 0181 06C3
[17:32:46][W][component:204]: Component remote_receiver took a long time for an operation (0.06 s).
[17:32:46][W][component:205]: Components should block for at most 20-30ms.
[17:32:46][D][main:082]: Reset counter: 5
[17:32:46][I][remote.pronto:237]: Received Pronto: data=0000 006D 0002 0000 0155 0057 0016 0181 06C3