Thursday, December 17, 2015

ESP8266 as IR remote control

Today I've managed to make the ESP8266 to work as IR remote control over MQTT for my TV.

Range is now only 1m, but I am planning to increase it. Next step is to update the Android app to support TV, AC etc.

To test the code the JSON can be used:

mosquitto_pub -h broker_ip -p port -t "/62/ir/command" -m  "{\"device_name\":\"ESP_47106\", \"type\":\"ir\", \"value\":\"ON\"}"

Every minute the module will report its status with a JSON over MQTT

{"device_name":"ESP_470106","type":"ir","ipaddress":"192.168.8.150","bgn":3,"sdk":"1.3.0","version":"1","uptime":"1"}


#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
#include <IRremoteESP8266.h>
#include <Timer.h>

#define PanasonicAddress      0x4004     // Panasonic address (Pre data) 
#define PanasonicPower        0x100BCBD  // Panasonic Power button

#define wifi_ssid "WLAN_62"
#define wifi_password "........"

#define mqtt_server "......."
#define mqtt_user "CATA"
#define mqtt_password "CATA"
#define mqtt_port 1880
#define IR_PIN 14

#define ir_topic "/62/ir/command"
#define device_status_topic "/62/device/status"
// Callback function header
void rx_mqtt_callback(char* topic, byte* payload, unsigned int length);

#define DEBUG false
#define Serial if(DEBUG)Serial
#define DEBUG_OUTPUT Serial

IRsend irsend(IR_PIN); //an IR led is connected to GPIO pin
WiFiClient espClient;
PubSubClient client(mqtt_server, mqtt_port, rx_mqtt_callback,espClient);
Timer t;
StaticJsonBuffer<512> jsonDeviceStatus;
JsonObject& jsondeviceStatus = jsonDeviceStatus.createObject();

char dev_name[50]; 
char json_buffer_status[512];
char my_ip_s[16];

void setup_wifi() 
{
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect(dev_name, mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void sendMQTTUpdate()
{
  IPAddress my_ip_addr = WiFi.localIP();
  sprintf(my_ip_s, "%d.%d.%d.%d", my_ip_addr[0],my_ip_addr[1],my_ip_addr[2],my_ip_addr[3]);
  jsondeviceStatus ["device_name"] = dev_name;
  jsondeviceStatus["type"] = "ir"; 
  jsondeviceStatus["ipaddress"] = String(my_ip_s).c_str();
  jsondeviceStatus["bgn"] = 3;
  jsondeviceStatus["sdk"] = ESP.getSdkVersion();//"1.4.0";
  jsondeviceStatus["version"] = "1";
  jsondeviceStatus["uptime"] = "1";//ESP.getVcc();
  
  jsondeviceStatus.printTo(json_buffer_status, sizeof(json_buffer_status));  
  client.publish(device_status_topic, json_buffer_status , false);
  Serial.println(json_buffer_status);

}

void rx_mqtt_callback(char* topic, byte* payload, unsigned int length)
{
  //reserve space for incomming message
  StaticJsonBuffer<256> jsonRxMqttBuffer;
  int i = 0;
  char rxj[256];
  Serial.println(dev_name); Serial.print("Topic:");Serial.println(topic);
  for(i=0;i<length;i++)
  {
    rxj[i] = payload[i];
  }

  Serial.println(rxj);
  JsonObject& root = jsonRxMqttBuffer.parseObject(rxj);
  if (!root.success())
  {
    Serial.println("parseObject() failed");
    return;
  }

  const char* device_name  = root["device_name"];
  const char* type         = root["type"];
  const char* value        = root["value"];

  Serial.println(device_name); 
  Serial.println(type); Serial.println(value);

  //if( (type == "ir") && ((value == "ON") || (value == "OFF")))
  //{
   /* DO A SANITIZE ON THE MESSAGE AND IF IS CLEAN SEND IR*/
       sendIR();
  //} 
  Serial.println("<=rx_mqtt_callback");
  return;
}

void sendIR()
{
    int i = 0;
    Serial.print("sendIR for 2 sec");
    for(i=0;i<20; i++)
    {      
      irsend.sendPanasonic(PanasonicAddress,PanasonicPower); // This should turn your TV on and off
      delay(100);
    }
}
void setup() 
{
  delay(1000);
  irsend.begin();
  Serial.begin(115200); 
  sprintf(dev_name, "ESP_%d", ESP.getChipId());
  setup_wifi();
  client.setServer(mqtt_server, 1880);
  client.connect(dev_name, mqtt_user, mqtt_password);
  client.subscribe(ir_topic);
  if (!client.connected()) 
  {
    reconnect();
  }
  t.every(60 * 1000 , sendMQTTUpdate);
  
}

void loop() {
  client.loop();
  t.update();
}


https://github.com/bcatalin/ESP8266-Infrared-Panasonic/

8 comments:

  1. hi , nice project !
    I was just wondering where you got Timer.h from ??

    cheers
    Rico

    ReplyDelete
  2. Hi Rico,

    Time.h is from a library called Timer. You can find more details about this library on this link: http://srmonk.blogspot.com/2012/01/arduino-timer-library.html

    ReplyDelete
  3. Hi,

    This is just what I've been looking for. Quick question if you don't mind? I understand that I need to change the definition for Panasonicpower to fit my needs but what is Panasonicaddress? Thanks

    ReplyDelete
    Replies
    1. Not anymore. Just use the above code. It has the Panasonic address in place #define PanasonicAddress 0x4004 // Panasonic address (Pre data)

      Delete
  4. Hi

    Can I use the code above to control a led lamp via mqtt?

    Thanks

    ReplyDelete
    Replies
    1. Yes, you can, just replace the ir part with a gpio command.

      Delete
  5. His

    Thanks for your reply.

    Can you please guide me on how to do that?

    Thanks.

    ReplyDelete
  6. I enjoyed reading your article :) PLease continue publishing helpful topics like this. Regards, from Let's get gadget, a company whose into selling
    remote extender

    ReplyDelete