Use Case: Control TVs via IR from openHAB (Tasmota-flashed IR Blaster + MQTT)

Use case: In my setup (I have rather old but otherwise good TV with IR remote control, hooked up to a Yamaha YSP-2700 soundbar) getting from “I want to watch TV” to “TV actually running” typically took ~30 seconds, 2 very low-responsive and annoying remote controls and lots of buttons to be pressed. Not surprisingly, our household was not very happy with this.

Goal: “Alexa, start TV” should do all of this.

Hardware used: Raspi 3B+ running openHAB 3.3 and a Nivian NVS-SMARTIR-W2 IR blaster (which I bought on Amazon for ~16 € specifially for this).

Effort: Three good evenings of fun, tinkering and learning.

Step 1: Free the Nivian IR Blaster from Tuya and install Tasmota IR

I followed this great article on how to free the IR Blaster from Tuya and install Tasmota IR, to be able to control the IR blaster with openHAB.

Things that were not mentioned in the article / I had to figure out myself which might be helpful for others.

  1. I’m using a CH340C ESP PROG V1.0 programmer (< 5 € if bought online) which woked great for me.

  2. The soldering described in Blakadder’s article was way easier than anticipated. And I’m not a soldering pro, nor having expensive equipment.

  3. After the soldering was done, I found it way easier to connect the IR Blaster to the Programmer by using a breadboard (especially setting the flashing-cable, see below).

  4. Connect all wires from the markings on the IR Blaster (as seen in Blakadder’s article) to the same pins on the programmer.

  5. To bring the IR Blaster (as for every other ESP8266) into “flash-able” mode, connect the IO0-Pin (before plugging in the programmer into your computer) to 3,3V. This can easily be done if a breadboard is being used.

  6. For the actual flashing, either use the web tool under this link (also works under Linux, but both in Linux or Windows Chrome has to be used) or download and install Tasmotizer.

  7. After you’re done flashing, use Tasmotizer to send WiFi-details (SSID and Password) to the ESP.

  8. Afterwards you should be able to get the IP address of the IR Blaster either via your router or via Tasmotizer (“Get IP Address”).

  9. Now you should be able to access the IR Blaster / Tasmota GUI by entering the correct IP address into your browser. At this point you can remove the soldered wires and close the IR Blaster’s casing again.

  10. In the Tasmota GUI, go to “Configuration” → “Configure other” and paste the following code (from Blakadder’s article) into the top field (make sure “activate” is ticked). This configures Tasmota according to a template that allows it to receive / send IR signals:
    {"NAME":"Nivian NVS-SMARTIR-W2","GPIO":[0,3200,0,3232,320,1088,0,0,0,32,1056,0,0,0],"FLAG":0,"BASE":62}

  11. Afterwards things should look like this:

  12. You can easily test if the IR Blaster is working correctly by clicking on “Console” in Tasmota, pointing an IR remote at the IR blaster, press a button and see if there’s a new log entry in the console (see latest entry at the very bottom):

If the programming of the IR Blaster with Tasmota does not work, try…

  • using a different USB port on your computer
  • using a different USB cable (some cables only support power, not data)
  • switching from Tasmotizer to the web installer (or vice versa)
  • try switching the wiring from RX to TX: Even though I found instructions online that said that RX (Receiving) on the programmer needs to be connected to RX on the IR Blaster, and TX (Transmitting) to TX, in my case I had to do it the other way round (RX to TX and TX to RX). The fact that something was wrong was pretty obvious, as the flashing (both in Tasmotizer and the Web Tool) did not work.
  • check whether the driver of the programmer is missing (the web tool gives some advice).

Step 2: Figure out the right IR commands

You can…

  • either extract the commands by pointing your remotes at the blaster, pressing the respective buttons and save the commands (as described above).
  • or look up the respective values online.

In my case, my physical TV remote has only one button for on/off, which is rather cumbersome, because I’d want to have discreet commands for on or off to improve “fail-safe-ness” of my script. Thus I looked up the commands of my TV online.

What worked great for me: Searching for an existing command (the part shown in the “Data” block in the Tasmota console), since the Google hit typically links to a table with all the other commands in there as well.

You can test your commands by…

  1. Copying this part from the Tasmota console…
  2. Replace “IrReceived” with “IrSend”
  3. … and paste the result IrSend:{"Protocol":"NEC","Bits":32,"Data":"0x1EE1F807","DataLSB":"0x78871FE0","Repeat":0}
    into the console and press “Enter”.
  4. If the console then reads
10:27:40.724 CMD: IrSend:{"Protocol":"NEC","Bits":32,"Data":"0x1EE1F807","DataLSB":"0x78871FE0","Repeat":0}
10:27:40.841 MQT: stat/IRBlaster/RESULT = {"IRSend":"Done"}

… everything works as expected, and the IR Blaster imitated the physical remote correctly (your TV should then also have done what the Remote did before).

  1. Now construct all needed commands by replacing the entry in the “Data” block. Save them somewhere temporarily.

Step 3: Enable openHAB to send IR commands

Assuming that MQTT is already working on your openHAB installation (if not, here under #3 are some hints), the goal is to create an openHAB item to which you can send your IR commands (as test strings) via MQTT, which are then picked up and executed from Tasmota / the IR Blaster.

In addition to this openHAB item (to which the IR commands are being sent to), I also created an openHAB item where the WiFi status of the IR Blaster is being recorded (also as a good test for whether the connection is working).

  1. Create a thing for the IR Blaster and the two channels mentioned above (WiFi status and MQTT-string-receiver). In my case this finally looked like this. Please note that the ID of the MQTT-bridge (7519737e0f) needs to be replaced by the openHAB ID of your MQTT-bridge.
UID: mqtt:topic:7519737e0f:IRBlaster
label: IR Blaster
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:7519737e0f
location: Wohnzimmer
  - id: Signal
    channelTypeUID: mqtt:number
    label: Signal Strength (in db)
    description: null
      postCommand: false
      retained: false
      step: 1
      formatBeforePublish: "%s"
      stateTopic: tele/IRBlaster/STATE
      transformationPattern: JSONPATH:$.Wifi.Signal
  - id: MQTT_String
    channelTypeUID: mqtt:string
    label: MQTT String
    description: ""
      commandTopic: cmnd/IRBlaster/IRSEND
      stateTopic: tele/IRBlaster/STATE
      transformationPattern: JSONPATH:$.IRSEND

Please also note that the topic of your Tasmota device (in my case IRBlaster) has to match whatever you have configured in Tasmota under “Configuration” → “MQTT Parameters” → “Topic”.

  1. Afterwards you can use blockly to send the previously created IR commands to the item that expects the MQTT string:
  2. Please note that some TVs are really slow, so it might be needed to have waiting times in between different IR commands (e.g. in my case, switching on the TV takes ~10 seconds, so I’m only changing the input channel 12 seconds after switching it on, otherwise the commands are being ignored).

4. Execute the rule by Alexa

To be able to say “Alexa, switch on the TV” there appear to be multiple ways of doing it. I just used a “Custom Skills” as defined in the Alexa App. In short…

  1. I created a custom skill in the Alexa app (More → Blueprints → Your Skills) that, if I say “Alexa, switch on the TV” just says “Ok”.

The important part is that the sentence “Alexa, switch on the TV” is being recorded in the Echo item “Last Voice Command” of the Echo Binding, and that Alexa does not respond with some nonsense e.g. “I cannot complete your command.” It should just say “ok”.
2. So whenever the item “Last Voice Command” changes

3. … I check whether someone asked to switch on the TV by checking whether a certain keyword is in the string (not super robust, I know, but good enough for me)…

4. … and then execute a simple rule that switches on what’s not yet switched on, and changes the respective channels if needed.

Closing remarks

I only learned about all of this some days ago, so I’m not a pro. So in case there are errors in it or ways on how to do it better or easier, let me know.

From what I understood, there is also a non-MQTT-way of sending IR commands to the IR Blaster, by just sending them to the IR Blaster via http reqeusts. While the option described above (via MQTT) is probably way neater, it requires some experience with MQTT in openHAB. The http-request-option appears easier, but I did not find a way in blockly to actually send them. So if someone knows how to send http commands in blockly rules, the following has to be done to create them:

  1. Use the IR commands copied above from the Tasmota console…
  2. … and include / make them fit into the following format:
    http://<<IR Blaster's IP address>>/cm?cmnd=irsend {"Protocol": "NEC","Bits": 32,"Data": 551489775}
  3. You can test these new http requests by just entering it into your browser and press “Enter”. Afterwards, you should again see a positive confirmation in the Tasmota console.
    Note that your browser automatically converts the command to more “fail proof” syntax without the blanks:{%22Protocol%22:%20%22NEC%22,%22Bits%22:%2032,%22Data%22:%20551489775}


The path through the lastVoiceCommand currently Jan 2024) does not work anymore. Will try to update this post with the workaround if I get time to do so.


Oh man. This is why I love this community.
Excellent content, right here!

You wrote:

As far as I figured out GPIO0 has to be connected to GND and RX and TX have to be crossed.
Is that right?

To be entirely honest I‘m not 100% confident on the entire flashing of various ESP32‘s. Just today I flashed an ESP-01 via a programmer without doing anything the to the GPIO0, and it still worked perfectly fine.

And regarding your question: Yes, if I remember correctly you‘re right: TX and RX have to be crossed. Not sure anymore whether this was also mentioned in Blakadder‘s article.