ESP8266 MQTT IR Transmitter for less than 10$ [Help Needed]

For quite a while I wanted to integrate wifi infrared device, that could control all my IR devices around the home. So I finally bought a IR transmitter(KY-005) and a IR receiver(KY-022). To use those modules I also bought a ESP8266 NodeMCU. This whole project cost less than 10$, and require minimal electronic experience. The IR transmitter can also be salvaged from old TV remotes or other IR devices, if you really wanna spare a few bucks.

Both modules works perfect for capturing and transmitting IR signals. They are very simple to use, along with the IRremoteESP8266 library.

With the: IRremoteESP8266/examples/IRrecvDumpV2, i started recording every single button press from our JVC LT-40E71(A) TV.

From every single IR signal it receives it recorded something like this:

Timestamp : 000015.615
 Encoding  : NEC
 Code      : 5FA38C7 (32 bits)
 Library   : v2.3.0
 
 Raw Timing[67]:
    +  9012, -  4506,    +   602, -   540,    +   590, -   538,    +   590, -   538, 
    +   590, -   538,    +   590, -   538,    +   554, -  1702,    +   588, -   540, 
    +   590, -  1670,    +   590, -  1670,    +   590, -  1666,    +   592, -  1668, 
    +   590, -  1668,    +   616, -  1642,    +   588, -   540,    +   592, -  1666, 
    +   590, -   538,    +   590, -   538,    +   588, -   538,    +   592, -  1666, 
    +   590, -  1668,    +   572, -  1688,    +   588, -   540,    +   588, -   540, 
    +   560, -   568,    +   590, -  1668,    +   560, -  1696,    +   590, -   540, 
    +   590, -   540,    +   618, -   510,    +   562, -  1696,    +   560, -  1696, 
    +   562, -  1696,    +   562
 
 uint16_t rawData[67] = {9012, 4506,  602, 540,  590, 538,  590, 538,  590, 538,  590, 538,  554, 1702,  588, 540,  590, 1670,  590, 1670,  590, 1666,  592, 1668,  590, 1668,  616, 1642,  588, 540,  592, 1666,  590, 538,  590, 538,  588, 538,  592, 1666,  590, 1668,  572, 1688,  588, 540,  588, 540,  560, 568,  590, 1668,  560, 1696,  590, 540,  590, 540,  618, 510,  562, 1696,  560, 1696,  562, 1696,  562};  // NEC 5FA38C7
 uint32_t address = 0xA0;
 uint32_t command = 0x1C;
 uint64_t data = 0x5FA38C7;

To transmit the same signal I sent the following code: 5FA38C7 in the function irsend.sendNEC(5FA38C7, 32);

After figuring out how to recieve and transmit IR codes I combined it with a modifed verson of MQTT Light for homeassistant by: “Samuel M.”(Correct me if I’m wrong), so I could send the IRcode over MQTT to my ESP8266, then make it transmit it. (My modifications aren’t the best, still have left over unused code from the original version)

 /*
    MQTT Light for Home-Assistant - NodeMCU (ESP8266)
    https://home-assistant.io/components/light.mqtt/
 
    Libraries :
     - ESP8266 core for Arduino : https://github.com/esp8266/Arduino
     - PubSubClient : https://github.com/knolleary/pubsubclient
 
    Sources :
     - File  Examples  ES8266WiFi  WiFiClient
     - File  Examples  PubSubClient  mqtt_auth
     - File  Examples  PubSubClient  mqtt_esp8266
 
    Schematic :
     - https://github.com/mertenats/open-home-automation/blob/master/ha_mqtt_light/Schematic.png
     - GND - LED - Resistor 220 Ohms - D1/GPIO5
 
    Configuration (HA) : 
     light:
       platform: mqtt
       name: Office light'
       state_topic: 'office/light1/status'
       command_topic: 'office/light1/switch'
       optimistic: false
 
    Samuel M. - v1.1 - 08.2016
    If you like this example, please add a star! Thank you!
    https://github.com/mertenats/open-home-automation
 */
 
 #include <ESP8266WiFi.h
 #include <PubSubClient.h
 #ifndef UNIT_TEST
 #include <Arduino.h
 #endif
 #include <IRremoteESP8266.h
 #include <IRsend.h
 
 
 
 #define MQTT_VERSION MQTT_VERSION_3_1_1
 
 // Wifi: SSID and password
 const char* WIFI_SSID = "*****";
 const char* WIFI_PASSWORD = "*****";
 
 // MQTT: ID, server IP, port, username and password
 const PROGMEM char* MQTT_CLIENT_ID = "IRBlaster";
 const PROGMEM char* MQTT_SERVER_IP = "192.168.0.5";
 const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
 const PROGMEM char* MQTT_USER = "******";
 const PROGMEM char* MQTT_PASSWORD = "******";
 
 // MQTT: topics
 const char* MQTT_LIGHT_STATE_TOPIC = "irblaster1/recieve";
 const char* MQTT_LIGHT_COMMAND_TOPIC = "irblast/send";
 
 WiFiClient wifiClient;
 PubSubClient client(wifiClient);
 IRsend irsend(4);  // An IR LED is controlled by GPIO pin 4 (D2)
 
 
 // function called when a MQTT message arrived
 void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
   // concat the payload into a string
   String payload;
   
   for (uint8_t i = 0; i < p_length; i++) {
     payload.concat((char)p_payload[i]);
   }
   
   // handle message topic
   if (String(MQTT_LIGHT_COMMAND_TOPIC).equals(p_topic)) {
     // test if the payload is equal to "ON" or "OFF"
     if (payload.equals(String(""))) {
     }
     else
     {
       
       Serial.print("payload:");
       Serial.println(payload);

       // Convert from String HEX to Hex long
       long hexCmd;
       hexCmd = strtol(&payload[0], NULL, 16);
       irsend.sendNEC(hexCmd, 32);
       
       Serial.print("INT:");
       Serial.println(hexCmd);
     }
   }
 }
 
 void reconnect() {
   // Loop until we're reconnected
   while (!client.connected()) {
     Serial.print("INFO: Attempting MQTT connection...");
     // Attempt to connect
     if (client.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD)) {
       Serial.println("INFO: connected");
       // Once connected, publish an announcement...
       //publishLightState();
       // ... and resubscribe
       client.subscribe(MQTT_LIGHT_COMMAND_TOPIC);
     } else {
       Serial.print("ERROR: failed, rc=");
       Serial.print(client.state());
       Serial.println("DEBUG: try again in 5 seconds");
       // Wait 5 seconds before retrying
       delay(5000);
     }
   }
 }
 
 void setup() {
   // init the serial
   //Serial.begin(115200);
   irsend.begin();
   Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
 
   
   // init the WiFi connection
   Serial.println();
   Serial.println();
   Serial.print("INFO: Connecting to ");
   WiFi.mode(WIFI_STA);
   Serial.println(WIFI_SSID);
   WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
 
   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
   }
 
   Serial.println("");
   Serial.println("INFO: WiFi connected");
   Serial.print("INFO: IP address: ");
   Serial.println(WiFi.localIP());
 
   // init the MQTT connection
   client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
   client.setCallback(callback);
 }
 
 void loop() {
   if (!client.connected()) {
     reconnect();
   }
   client.loop();
 }

To send MQTT messages to the ESP8266 I used this Home Assistant configuration:

 switch:    
   - platform: mqtt
     name: "TV Toggle"
     command_topic: "irblast/send"
     payload_on: "5FA38C7"
     optimistic: true
     qos: 0
     retain: true

Issues
- The first issue I have stumbled upon, during this small project is that the remote I’ve used, only have a Power Toggle button, which means it both turns the TV On and Off. Which makes it hard to fully automate it, since Home Assistant don’t know if it turns it OFF or ON. I’ve looked up IR codes for my TV, but all the results comes in raw data, but I rather have it in a simple HEX from like: “5FA38C7”.
I tried looking them up using: http://irdb.tk/db/, but the information I get is this:

"VOLUME UP","sendir,1:1,1,38000,1,37,319,160,20,60,20,60,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,60,20,60,20,60,20,60,20,20,20,20,20,20,20,898,20,60,20,60,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,60,20,60,20,60,20,60,20,20,20,20,20,20,20,898","0000 006D 0012 0011 013F 00A0 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 003C 0014 003C 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0382 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 003C 0014 003C 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0382",,

And I’ve no idea how to convert it to something like this: “5FA38C7”

- The second issue is that I can’t really find a single action button in Homeassistant that doesn’t have a toggle ON/OFF mode.
homeassistant button

I need a way to only have it show one state, also with some style. Something like this:
https://community-home-assistant-assets.s3-us-west-2.amazonaws.com/optimized/3X/b/1/b1c9881a27bcacd6239b446ffff00a126c80466b_1_417x500.png

Future Plans
I plan to expand the project, so that I also can receive IR signals and make them toggle certain events in homeautomation, like turn ON/OFF lights, or maybe keep track on the television states(when the normal remote is used) like volume/channel/mode, so I can from Home Assistant see what channel is being watch, when the TV last were being used.

Conclusion
I hope that some could use this to get started making their own, simple WIFI IR transmitter or get inspired to. My code isn’t great at all, this is nothing but my approach to this project.

4 Likes

Thanks for the share, looks like a cheap, efficient and easy way to control IR products :+1:

1 Like

Thanks for the share. I looked at something similar and managed to get a proof of concept up and running but it started to get a bit messy. Then I found the Broadlink RM Mini for about $15 and it took all the headache away as it integrates with Home Assistant nicely.

I also struggled with the lack of state data. Even if my TV had separate commands for on and off Home Assistant could still get out of sync if I used the actual remote. Now I just use scripts so that the UI isn’t confusing:

2 Likes

I’ve thought about buying something similar to the Broadlink RM Mini, but I like the idea of making it myself, so I can design it as I want with 3D printing and stuff, the problem is that usually doesn’t get that fare :sweat_smile: But you maybe I should consider something similar to your solution.

As I mentions my remote only has a power toggle button, but looking up on other similar models of the TV, they also have separate options. I was thinking maybe I could use those and hopefully the televison, works with them too, even though the remote doesn’t have it. Having the option to choose if it should be On or Off with 100% certainty that it’s actually doing it correct, would be practical for automations.

This is a code that I got from: Global Caché’s Control Tower that I assume would turn of the TV.

"POWER OFF","sendir,1:1,1,38000,1,37,319,160,20,60,20,60,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,60,20,20,20,60,20,60,20,20,20,20,20,20,20,898,20,60,20,60,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,60,20,20,20,60,20,60,20,20,20,20,20,20,20,898","0000 006D 0012 0011 013F 00A0 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 003C 0014 0014 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0382 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 0014 003C 0014 0014 0014 003C 0014 003C 0014 0014 0014 0014 0014 0014 0014 0382",,

But I have no idea how to use that data, and can’t really see how the Broadlink RM Mini would help me… If it would I no doubt take the shortcut, can buy it straight away!

I see that your switches on your Home Assitant frontend are nicely done and simple with only have a activate button, are there any way to get that, where a press instead would publish a MQTT message?

Hello,

You can use raw sending or global cache codes sending indeed, here is an example of implementation

The corresponding code is in the file ZgatewayIR.ino

1 Like

Awesome project, works great, although I made a small modification to make it even better :wink:

// Convert from String HEX to Hex long
       unsigned long hexCmd;
       hexCmd = strtoul(&payload[0], NULL, 16);

Using unsigned longs it can send all the codes , which you really want…

1 Like

have a look here http://sankios.imediabank.com/irremote-transmit-and-receiver

irsend.sendNEC(IRcode, numBits);
Send a code in NEC format.

irsend.sendSony(IRcode, numBits);
Send a code in Sony format.

irsend.sendRC5(IRcode, numBits);
Send a code in RC5 format.

irsend.sendRC6(IRcode, numBits);
Send a code in RC6

irsend.sendRaw(rawbuf, rawlen, frequency);
Send a raw code. Normally you would obtain the contents of rawbuf and rawlen by using the receiver many times and averaging the results. Some adjustments may be necessary for best performance. The frequency is the expected bandpass filter frequency at the receiver, where 38 is the most commonly used.

off the topic, is it possible to create buttons as you shown in remote control within hassio? if so what component supporting that?

@Gheotic, thank you for your post, i was trying to find out if KY-005 will even work with esp8266 and found your post. Looks like it should so I just made the purchase.

Not sure how much I can help you with your questions, but it looks like there is this file https://github.com/crankyoldgit/IRremoteESP8266/blob/master/tools/gc_decode.cpp which should help you decode Raw Codes, GlobalCache (GC) codes and ProntoHex codes