#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char *ssid = "xxx";
const char *pass = "xxx";
IPAddress server(192, 168, 0, 113);
#define TOPBIT 0x80000000
#define SAMSUNG_HDR_MARK 4500
#define SAMSUNG_HDR_SPACE 4500
#define SAMSUNG_BIT_MARK 560
#define SAMSUNG_ONE_SPACE 1690
#define SAMSUNG_ZERO_SPACE 560
#define SAMSUNG_RPT_SPACE 46000
#define MOTO_HDR_MARK 2640 // t*8
#define MOTO_HDR_SPACE 1980 // t*6
#define MOTO_T1 330 // t
#define MOTO_T2 660 //t*2
#define MOTO_REPEAT_MASK 0x800008
#define MOTO_GAP 73800
float cycle_duration; // The duration of one cycle in us
#define codesCount 74
unsigned int remoteCodes[] =
{
//////// SAMSUNG TV /////////
0xE0E040BF, // POWER [0]
0xE0E0807F, // SOURCE [1]
0xE0E0D12E, // HDMI [2]
0xE0E020DF, // 1 [3]
0xE0E0A05F, // 2 [4]
0xE0E0609F, // 3 [5]
0xE0E010EF, // 4 [6]
0xE0E0906F, // 5 [7]
0xE0E050AF, // 6 [8]
0xE0E030CF, // 7 [9]
0xE0E0B04F, // 8 [10]
0xE0E0708F, // 9 [11]
0xE0E08877, // 0 [12]
0xE0E034CB, // TTX/MIX [13]
0xE0E0C837, // PRE-CH [14]
0xE0E0F00F, // MUTE [15]
0xE0E0E01F, // VOL + [16]
0xE0E0D02F, // VOL - [17]
0xE0E048B7, // CH + [18]
0xE0E008F7, // CH - [19]
0xE0E0D629, // CH-LIST [20]
0xE0E09E62, // SMART HUB [21]
0xE0E058A7, // MENU [22]
0xE0E0F20D, // GUIDE [23]
0xE0E0D22D, // TOOLS [24]
0xE0E0F807, // INFO [25]
0xE0E01AE6, // RETURN [26]
0xE0E0B44B, // EXIT [27]
0xE0E0A659, // LEFT [28]
0xE0E046B9, // RIGHT [29]
0xE0E006F9, // UP [30]
0xE0E08679, // DOWN [31]
0xE0E016E9, // OK [32]
0xE0E036C9, // A [33]
0xE0E028D7, // B [34]
0xE0E0A857, // C [35]
0xE0E06897, // D [36]
0xE0E014EB, // P.MODE [37]
0xE0E07689, // SRS [38]
0xE0E000FF, // DUAL I-II [39]
0xE0E0FC04, // E-MANUAL [40]
0xE0E07C83, // P.SIZE [41]
0xE0E0A45B, // AD/SUBT [42]
0xE0E0A25D, // REW [43]
0xE0E012ED, // FWD [44]
0xE0E052AD, // PAUSE [45]
0xE0E0926D, // REC [46]
0xE0E0E21D, // PLAY [47]
0xE0E0629D, // STOP [48]
///// MOTOROLA VIP-1003 //////
0x1000085e, // POWER [49]
0x10003d56, // VOL- [50]
0x10004d57, // VOL+ [51]
0x10006b57, // MUTE [52]
0x10001d54, // 0 [53]
0x10005954, // 1 [54]
0x10006955, // 2 [55]
0x10007956, // 3 [56]
0x10001c53, // 4 [57]
0x10002c54, // 5 [58]
0x10003c55, // 6 [59]
0x10004c56, // 7 [60]
0x10005c57, // 8 [61]
0x10006c58, // 9 [62]
0x10005b56, // BACK [63]
0x10004852, // CH- [64]
0x10003851, // CH+ [65]
0x10006a56, // EPG [66]
0x10007c59, // INFO [67] - jāpārbauda, nesakrīt checksum
0x10005853, // LEFT [68]
0x10006854, // RIGHT [69]
0x10000f55, // OK [70]
0x10002f57 // PORTAL [71]
};
unsigned int digitCodes[] =
{
0x10001d54, // 0
0x10005954, // 1
0x10006955, // 2
0x10007956, // 3
0x10001c53, // 4
0x10002c54, // 5
0x10003c55, // 6
0x10004c56, // 7
0x10005c57, // 8
0x10006c58, // 9
};
typedef struct
{
String cmdName;
byte cmdLength;
byte idx;
void (*ir_exeCmd)(byte id);
} remoteCmd;
remoteCmd cmd[codesCount]
{
/////////// SAMSUNG TV ///////////
{"tvpower", 7, 0, ir_exeCmdSamsung},
{"tvsource", 8, 1, ir_exeCmdSamsung},
{"tvhdmi", 6, 2, ir_exeCmdSamsung},
{"tv1", 3, 3, ir_exeCmdSamsung},
{"tv2", 3, 4, ir_exeCmdSamsung},
{"tv3", 3, 5, ir_exeCmdSamsung},
{"tv4", 3, 6, ir_exeCmdSamsung},
{"tv5", 3, 7, ir_exeCmdSamsung},
{"tv6", 3, 8, ir_exeCmdSamsung},
{"tv7", 3, 9, ir_exeCmdSamsung},
{"tv8", 3, 10, ir_exeCmdSamsung},
{"tv9", 3, 11, ir_exeCmdSamsung},
{"tv0", 3, 12, ir_exeCmdSamsung},
{"tvttxmix", 8, 13, ir_exeCmdSamsung},
{"tvprech", 7, 14, ir_exeCmdSamsung},
{"tvmute", 6, 15, ir_exeCmdSamsung},
{"tvvol+", 6, 16, ir_exeCmdSamsung},
{"tvvol-", 6, 17, ir_exeCmdSamsung},
{"tvch+", 5, 18, ir_exeCmdSamsung},
{"tvch-", 5, 19, ir_exeCmdSamsung},
{"tvchlist", 8, 20, ir_exeCmdSamsung},
{"tvsmarthub", 10, 21, ir_exeCmdSamsung},
{"tvmenu", 6, 22, ir_exeCmdSamsung},
{"tvguide", 7, 23, ir_exeCmdSamsung},
{"tvtools", 7, 24, ir_exeCmdSamsung},
{"tvinfo", 6, 25, ir_exeCmdSamsung},
{"tvreturn", 8, 26, ir_exeCmdSamsung},
{"tvexit", 6, 27, ir_exeCmdSamsung},
{"tvleft", 6, 28, ir_exeCmdSamsung},
{"tvright", 7, 29, ir_exeCmdSamsung},
{"tvup", 4, 30, ir_exeCmdSamsung},
{"tvdown", 6, 31, ir_exeCmdSamsung},
{"tvok", 4, 32, ir_exeCmdSamsung},
{"tva", 3, 33, ir_exeCmdSamsung},
{"tvb", 3, 34, ir_exeCmdSamsung},
{"tvc", 3, 35, ir_exeCmdSamsung},
{"tvd", 3, 36, ir_exeCmdSamsung},
{"tvpmode", 7, 37, ir_exeCmdSamsung},
{"tvsrs", 5, 38, ir_exeCmdSamsung},
{"tvdual", 6, 39, ir_exeCmdSamsung},
{"tvemanual", 9, 40, ir_exeCmdSamsung},
{"tvpsize", 7, 41, ir_exeCmdSamsung},
{"tvadsubt", 8, 42, ir_exeCmdSamsung},
{"tvrew", 5, 43, ir_exeCmdSamsung},
{"tvfwd", 5, 44, ir_exeCmdSamsung},
{"tvpause", 7, 45, ir_exeCmdSamsung},
{"tvrec", 5, 46, ir_exeCmdSamsung},
{"tvplay", 6, 47, ir_exeCmdSamsung},
{"tvstop", 6, 48, ir_exeCmdSamsung},
//////// MOTOROLA STB VIP-1003 /////////
{"stbpower", 8, 49, ir_exeCmdMotorola},
{"stbvol-", 7, 50, ir_exeCmdMotorola},
{"stbvol+", 7, 51, ir_exeCmdMotorola},
{"stbmute", 7, 52, ir_exeCmdMotorola},
{"stb0", 4, 53, ir_exeCmdMotorola},
{"stb1", 4, 54, ir_exeCmdMotorola},
{"stb2", 4, 55, ir_exeCmdMotorola},
{"stb3", 4, 56, ir_exeCmdMotorola},
{"stb4", 4, 57, ir_exeCmdMotorola},
{"stb5", 4, 58, ir_exeCmdMotorola},
{"stb6", 4, 59, ir_exeCmdMotorola},
{"stb7", 4, 60, ir_exeCmdMotorola},
{"stb8", 4, 61, ir_exeCmdMotorola},
{"stb9", 4, 62, ir_exeCmdMotorola},
{"stbback", 7, 63, ir_exeCmdMotorola},
{"stbch+", 6, 64, ir_exeCmdMotorola},
{"stbch-", 6, 65, ir_exeCmdMotorola},
{"stbepg", 6, 66, ir_exeCmdMotorola},
{"stbinfo", 7, 67, ir_exeCmdMotorola},
{"stbleft", 7, 68, ir_exeCmdMotorola},
{"stbright", 8, 69, ir_exeCmdMotorola},
{"stbok", 5, 70, ir_exeCmdMotorola},
{"stbportal", 9, 71, ir_exeCmdMotorola},
{"powerall", 8, 0, ir_exeCmdPowerBoth}
};
void callback(const MQTT::Publish& pub) {
String command = pub.payload_string();
byte cmdLen = pub.payload_len();
byte i;
int digit;
if(cmdLen > 0)
{
if(command.startsWith("ch"))
{
String channel = command.substring(2);
for(i=0; i < channel.length();i++)
{
digit = channel.substring(i, i+1).toInt();
sendMotorola(digitCodes[digit]);
}
}
else
{
for(i=0; i < codesCount; i++)
{
if(cmdLen == cmd[i].cmdLength)
{
if(cmd[i].cmdName == command)
{
cmd[i].ir_exeCmd(cmd[i].idx);
break;
}
}
}
}
}
Serial.print(pub.topic());
Serial.print(" => ");
Serial.println(pub.payload_string());
}
PubSubClient client(server);
void bitbangOutput(int time)
{
int loops = round(time/(cycle_duration));
float half_cycle = cycle_duration/2;
int i=0;
for(i=0; i<loops; i++)
{
digitalWrite(2, LOW);
delayMicroseconds(half_cycle);
digitalWrite(2, HIGH);
delayMicroseconds(half_cycle);
}
}
void ir_exeCmdSamsung(byte idx)
{
sendSamsung(remoteCodes[idx]);
}
void ir_exeCmdMotorola(byte idx)
{
sendMotorola(remoteCodes[idx]);
}
void ir_exeCmdPowerBoth(byte idx)
{
sendSamsung(remoteCodes[0]);
sendMotorola(remoteCodes[49]);
}
void mark(int time)
{
bitbangOutput(time);
}
void space(int time)
{
delayMicroseconds(time);
}
void sendMotorola(unsigned int data)
{
cycle_duration=(float)1000/36;
unsigned int tmpData = 0;
byte r;
byte i;
for (r = 0; r < 3; r++)
{
if (r == 2)
{
tmpData = data + MOTO_REPEAT_MASK;
}
else
{
tmpData = data;
}
mark(MOTO_HDR_MARK); // pre-bit "1"
space(MOTO_HDR_SPACE); // pre-bit "0"
mark(MOTO_T2); // start-bit "1"
for (i = 0; i < 32; i++) // 32 baiti
{
if (tmpData & TOPBIT) // 1 is mark, then space
{
mark(MOTO_T1);
space(MOTO_T1);
}
else // 0 is space, then mark
{
space(MOTO_T1);
mark(MOTO_T1);
}
tmpData <<= 1;
}
space(MOTO_GAP);
}
}
void sendSamsung(unsigned int data)
{
cycle_duration=(float)1000/38;
unsigned int tmpData = 0;
byte r;
byte i;
for (r = 0; r < 2; r++)
{
tmpData = data;
mark(SAMSUNG_HDR_MARK);
space(SAMSUNG_HDR_SPACE);
for (i = 0; i < 32; i++)
{
if (tmpData & TOPBIT)
{
mark(SAMSUNG_BIT_MARK);
space(SAMSUNG_ONE_SPACE);
}
else
{
mark(SAMSUNG_BIT_MARK);
space(SAMSUNG_ZERO_SPACE);
}
tmpData <<= 1;
}
mark(SAMSUNG_BIT_MARK);
space(SAMSUNG_RPT_SPACE);
}
}
void setup()
{
Serial.begin(115200);
delay(10);
Serial.println();
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
client.set_callback(callback);
WiFi.begin(ssid, pass);
int retries = 0;
while ((WiFi.status() != WL_CONNECTED) && (retries < 10)) {
retries++;
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
}
if (client.connect("tvremoteClient")) {
Serial.println("Connected to MQTT broker");
client.subscribe("remote/cmd");
}else{
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}
void loop()
{
client.loop();
}