Athom IR Controller AR01 to ESPHOME

Nice little IR remote from Athom. Great price at 15$. Has USB C to serial, Comes stock with Tasmota, which I have never really used. So here is a ESPHOME config if you want to swap.

Tasmota to ESPHOME process Migrating from Tasmota

substitutions:
  name: "livingroom-infrared"
  friendly_name: "Livingroom infrared"

esphome:
  name: "${name}"
  friendly_name: "${friendly_name}"

esp8266:
  board: esp8285
  restore_from_flash: true

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret key


ota:
  password: !secret ota_password

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${friendly_name} AP"
    password: !secret wifi_ap_password

captive_portal:

web_server:
  port: 80

sensor:
  - platform: wifi_signal
    name: "${friendly_name} WiFi Signal"
    update_interval: 60s

  - platform: uptime
    name: "${friendly_name} Uptime"

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${friendly_name} IP Address"
      disabled_by_default: true
    ssid:
      name: "${friendly_name} SSID"
    bssid:
      name: "${friendly_name} BSSID"
    mac_address:
      name: "${friendly_name} Mac Wifi Address"
    scan_results:
      name: "${friendly_name} Latest Scan Results"

switch:
  - platform: restart
    name: "${friendly_name} restart"

binary_sensor:
  - platform: status
    name: "${friendly_name} IR Status"

  - platform: gpio
    pin: GPIO0
    id: physical_button

status_led:
  pin: GPIO13

remote_transmitter:
  pin:
    number: GPIO4
  carrier_duty_percent: 50%

remote_receiver:
  pin:
    number: GPIO5
    inverted: true
  dump: all
  
4 Likes

Add the following to your API settings in your config to create a HA service call to send IR commands from the HA UI or Automations.

Credit to

api:
  services:
    - service: send_ir
      variables:
        protocol: string
        code: string
        command: string
        repeats: string
      then:
        - lambda: 'ESP_LOGD("main", "Protocol: %s - Code: %s - Command: %s",  protocol.c_str(), code.c_str(), command.c_str() ); '
        - if:
            condition: # --=[ *** COOLIX *** ]=--
              lambda: 'return protocol == "COOLIX";'
            then:
              - logger.log: "Sending COOLIX data...!"
              - remote_transmitter.transmit_coolix:
                  data: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
        - if:
            condition: # --=[ *** DISH *** ]=--
              lambda: 'return protocol == "DISH";'
            then:
              - logger.log: "Sending DISH data...!"
              - remote_transmitter.transmit_dish:
                  address: !lambda |-
                        return std::stoi( code );
                  command: !lambda |-
                        return std::stoi( command );
        - if:
            condition: # --=[ *** JVC *** ]=--
              lambda: 'return protocol == "JVC";'
            then:
              - logger.log: "Sending JVC data...!"
              - remote_transmitter.transmit_jvc:
                  data: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;                      
        - if:
            condition: # --=[ *** LG *** ]=--
              lambda: 'return protocol == "LG";'
            then:
              - logger.log: "Sending LG data...!"
              - remote_transmitter.transmit_lg:
                  data: !lambda |-
                       int i;
                       sscanf(code.c_str(), "%x", &i );
                       return i;
                  nbits: !lambda |-
                        return std::stoi( command );
        - if:
            condition: # --=[ *** MAGIQUEST *** ]=--
              lambda: 'return protocol == "MAGIQUEST";'
            then:
              - logger.log: "Sending MAGIQUEST data...!"
              - remote_transmitter.transmit_magiquest:
                  wand_id: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
                  magnitude: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
        - if:
            condition: # --=[ *** NEC *** ]=--
              lambda: 'return protocol == "NEC";'
            then:
              - logger.log: "Sending NEC data...!"
              - remote_transmitter.transmit_nec:
                  address: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
                  command: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
                    
        - if:
            condition: # --=[ *** PANASONIC *** ]=--
              lambda: 'return protocol == "PANASONIC";'
            then:
              - logger.log: "Sending PANASONIC data...!"
              - remote_transmitter.transmit_panasonic:
                  address: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i; 
                  command: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
        - if:
            condition: # --=[ *** PIONEER *** ]=--
              lambda: 'return protocol == "PIONEER";'
            then:
              - logger.log: "Sending PIONEER data...!"
              - remote_transmitter.transmit_pioneer:
                  rc_code_1: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
                  rc_code_2: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
                  repeat:
                    times: !lambda |-
                        return std::stoi( repeats );
        - if:
            condition: # --=[ *** PRONTO *** ]=--
              lambda: 'return protocol == "PRONTO";'
            then:
              - logger.log: "Sending PRONTO data...!"
              - remote_transmitter.transmit_pronto:
                  data: !lambda |-
                      return code.c_str();
        - if:
            condition: # --=[ *** RC5 *** ]=--
              lambda: 'return protocol == "RC5";'
            then:
              - logger.log: "Sending RC5 data...!"
              - remote_transmitter.transmit_rc5:
                  address: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i; 
                  command: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
        - if:
            condition: # --=[ *** RC6 *** ]=--
              lambda: 'return protocol == "RC6";'
            then:
              - logger.log: "Sending RC6 data...!"
              - remote_transmitter.transmit_rc6:
                  address: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
                  command: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
        - if:
            condition: # --=[ *** SAMSUNG *** ]=--
              lambda: 'return protocol == "SAMSUNG";'
            then:
              - logger.log: "Sending SAMSUNG data...!"
              - remote_transmitter.transmit_samsung:
                  data: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i; 
                  nbits: !lambda |-
                        return std::stoi( command );   
        - if:
            condition: # --=[ *** SAMSUNG36 *** ]=--
              lambda: 'return protocol == "SAMSUNG36";'
            then:
              - logger.log: "Sending SAMSUNG36 data...!"
              - remote_transmitter.transmit_samsung36:
                  address: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
                  command: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;
        - if:
            condition: # --=[ *** SONY *** ]=--
              lambda: 'return protocol == "SONY";'
            then:
              - logger.log: "Sending SONY data...!"
              - remote_transmitter.transmit_sony:
                  data: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i; 
                  nbits: !lambda |-
                        return std::stoi( command );
        - if:
            condition: # --=[ *** TOSHIBA AC *** ]=--
              lambda: 'return protocol == "TOSHIBA_AC";'
            then:
              - logger.log: "Sending TOSHIBA data...!"
              - remote_transmitter.transmit_toshiba_ac:
                  rc_code_1: !lambda |-
                      int i;
                      sscanf( code.c_str(), "%x", &i );
                      return i;
                  rc_code_2: !lambda |-
                      int i;
                      sscanf( command.c_str(), "%x", &i );
                      return i;                        

2 Likes

This is exactly what i wanted.

How did you learn these codes?

I’m interested in controlling things like candles and cheap LED lights.

I ended up flashing tasmota back on the device, I like using mqtt more than native HA api. I just installed esphome on the device for fun. but the question above I credited the original code writer for the api service.

Hi @mrkricfalusi

Thanks for your work on this! I bought the exact same unit, just for playing around with it, as it was too cheap to just let it pass.

I was just curious on the setup in mqtt, compared to esphome: is it easier to setup, scan codes, add new ones etc? I’m just trying to avoid having to do work that’s easier in tasmota. Haven’t setup mosquito before might give it a try soon.

I already have esphome running for esp32-cams, dht temp sensors and BT bridge. So I am familiar with writing configs but seeing all these if/then in yaml makes me think that maybe this is not the best way of setting this up. I mean yaml is made for configs, and if/then makes it become a program.

Tnx!
Kurt

1 Like

MQTT is a :sauropod: in IT and turns 25 years next year :older_man:

Advantages over MQTT

The ESPHome native API has many advantages over using MQTT for communication with Home Automation software (currently only Home Assistant). But MQTT is a great protocol and will never be removed. Features of native API (vs. MQTT):

  • Much more efficient: ESPHome encodes all messages in a highly optimized format with protocol buffers - for example binary sensor state messages are about 1/10 of the size.
  • One-click configuration: ESPHome just needs one click to set up in Home Assistant - no more messing around with retained MQTT discovery messages and alike.
  • One less single point of failure: In the ESPHome native API each ESP is its own server. With MQTT, when the broker shuts off nothing can communicate anymore.
  • Stability: Since ESPHome has far more control over the protocol than with MQTT, it’s really easy for us to roll out stability improvements.
  • Low Latency: The native API is optimized for very low latency, usually this is only a couple of milliseconds and far less than can be noticed by the eye.

ESPHome actually supports both - the native api and mqtt. Tasmota is limited to the later afaik.

If you can avoid just don’t. :warning: Having to waste time with retained messages and other odds is a deep rabbit hole which IMHO is just not worth it if you are not forced (e.g. old device that only communicates via mqtt) to do it. Best day in my “smart home” career undoubtedly was when I turned the mqtt broker off maybe 3 years ago - suddenly much more spare time - to waste with other rabbit holes :hole::rabbit:

1 Like

Ok thanks for the heads up, I backed up the default tasmota flash, and I’ll setup esphome on it and give that a go

How did you guys flash from Tasmota to ESPHome ? I’m having a hell of a time. This is my first time using ESPHome. I have 4 of these IR receivers I need to convert.

See AtHom AR01 IR sensor - help needed - #6 by madbrain

Starting at v12, tasmota has a safeboot partition which is not compatible with esphome for ota.
So you’ll need to use serial method to flash it.

Thanks. The Tasmota is on v13, so I guess that’s the only way. I already tried the serial flashing method, and I am stuck at the the “Prepare for first use” step.

I’m not sure which one the “boot” button might be - maybe there is one inside the case, but I tried the lone button underneath the case and that didn’t help, except it changed the LED state from 1 to 2, and sometimes a 3rd LED blinks too. In any case, it won’t pass this initial preparation step. Any help would be greatly appreciated !

Can you try press and hold the button while plugging the usb cable?

Thanks. Tried that, but then ESPHome add-on fails to find a serial port.

Turns out I was plugging in the Athom device to the wrong machine. It needed to be attached to the machine running the browser, not the machine running HA. One of my PCs had an RS232 serial port of its own (non-USB, from the motherboard) and ESPHome tried to use that. It wrongly stated there was an ESP Device on it - there was nothing attached (I just removed my X10 interface a few days ago).
The other PC I tried it from had no serial port, and when I tried Chrome on it, it show the picture above with “No compatible devices” found. I detached the Athom device from the Raspberry Pi that was running HAOS, and attached it to one of the PCs, while holding the bottom button. Then, Chrome showed a USB-SERIAL interface. And the “prepare for first use” option worked !
I am able to connect to the esphome wifi SSID. I chose my Wifi AP’s SSID and entered the password.
And now, Home Assistant has detected the device over Wifi !

Thanks for the help. Now on to flashing the other 3 controllers, and figuring out how to use them in HA.

Were you only transmitting IR codes with ESPHome, or also receiving them ?
I more or less cloned your ESPHome config for my Athom IR controller. I don’t see any sensor that could be used to receive IR commands from, though.

That’s indeed the case if you choose “Plug into this computer” :point_down:

image

On the other hand you obviously could also use your serial port on the machine which is running the ESPHome Dashboard :point_up:

More or less looks like how exactly? :thinking:

Did you try the docs already?

Re: your first point, I wasn’t talking about this menu, but what comes up when using “new device” / “open ESPhome web”.

As far as my configuration, it looks like this :

substitutions:
  name: "ht-infrared"
  friendly_name: "Home theater infrared"

esphome:
  name: esphome-web-f996eb
  friendly_name: "${friendly_name}"

esp8266:
  board: esp8285
  restore_from_flash: true

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: <removed>

ota:

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esphome-Web-F996Eb"
    password: <removed>

captive_portal:

web_server:
  port: 80

sensor:
  - platform: wifi_signal
    name: "${friendly_name} WiFi Signal"
    update_interval: 60s

  - platform: uptime
    name: "${friendly_name} Uptime"

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${friendly_name} IP Address"
      disabled_by_default: true
    ssid:
      name: "${friendly_name} SSID"
    bssid:
      name: "${friendly_name} BSSID"
    mac_address:
      name: "${friendly_name} Mac Wifi Address"
    scan_results:
      name: "${friendly_name} Latest Scan Results"

switch:
  - platform: restart
    name: "${friendly_name} restart"

binary_sensor:
  - platform: status
    name: "${friendly_name} IR Status"

  - platform: gpio
    pin: GPIO0
    id: physical_button

status_led:
  pin: GPIO13

remote_transmitter:
  pin:
    number: GPIO4
  carrier_duty_percent: 50%

remote_receiver:
  pin:
    number: GPIO5
    inverted: true
  dump: all

I’d love to be able to change the hostname, but not sure how. If I change it in the config, the installation of the firmware cannot locate the device anymore. I guess I need to change it in another place on the device, too ?

As far as the Remote receiver docs, I did browse them. I see examples of automations, but they all assume you know the values/constants/types for the IR signal. What I don’t see described in the doc is the process to learn a signal from an IR remote to get the data for each button (there are about 8 I want to learn). I’m then looking to create automations for each of those learned buttons.

As so often the answer found in the documentation :open_book:

Isn’t that guide found on esphome.io useful to you? :thinking:

Setting up Infrared Devices

In this guide an infrared device will be set up with ESPHome. First, the remote code will be captured with an IR receiver module (like this one). We will use ESPHome’s dumping ability to output the decoded remote code directly.
[…]

It describes the process of learning IR signals in detail :man_shrugging:

Thanks. That was very helpful. I got the hostname changed, and I began the process of learning signals.

Here is a dump of what happens when I press one of the buttons on my remote :slight_smile:

07:12:13	[I]	[remote.jvc:049]	Received JVC: data=0x08E7

07:12:13	[I]	[remote.lg:054]	Received LG: data=0x08E76897, nbits=32

07:12:13	[I]	[remote.nec:070]	Received NEC: address=0xE710, command=0xE916

07:12:13	[I]	[remote.pronto:237]	Received Pronto: data=0000 006D 0022 0000 0159 00AC 0015 0017 0014 0017 0014 0017 0014 0017 0014 0042 0014 0017 0014 0017 0014 0017 0014 0042 0014 0042 0014 0042 0014 0017 0014 0017 0015 0041 0014 0042 0014 0042 0014 0017 0014 0042 0014 0042 0014 0016

07:12:13	[I]	[remote.pronto:239]	0015 0042 0014 0016 0015 0016 0016 0015 0015 0041 0015 0016 0016 0015 0016 0040 0015 0016 0016 0040 0016 0040 0016 0040 0016 0181 06C3

It looks like the remote is sending codes of 4 different types for a single button. But the doc says :
Remote code selection (exactly one of these has to be included):

How can I create one binary sensor that expects all 4 types ? Or should I just focus on one of them, such as the longest one ?

That can happen. You probably only need one of the commands, just try one out and if it works you can forget the others.

I think that’s why they choosed this wording in the docs:

Working with a protocol (like nec, jvc, …) is easier than with raw/pronto as the codes are much shorter :pinching_hand:

Thanks. I got my first controller fully setup now - for my home theater. I no longer need the Pi + FLIRC. I also setup a second controller for my bar. The ones for my guest room and master bedroom still await setup.

1 Like