Skip to content

Instantly share code, notes, and snippets.

@dov
Created July 22, 2020 18:28
Show Gist options
  • Save dov/2a6dbb3fdb98b3245b121426f0dbb1e0 to your computer and use it in GitHub Desktop.
Save dov/2a6dbb3fdb98b3245b121426f0dbb1e0 to your computer and use it in GitHub Desktop.
A web server for sending raw IR codes
// This is as a web server library used for sending raw IR codes
// to an IR-Led.
//
// The raw string decoding code was borrowed from:
//
// https://github.com/crankyoldgit/IRremoteESP8266
//
//
// License: GLPL v2.1
//
// Setup: fill in the ssid and password below
// Connect the io pin 4 (D2) to the following circuit.
//
//
// 5V
// ^
// |
// IR-LED
// |
// /
// /--\/
// | /|
// | / | General purpose NPN transistor
// D2 -----< |
// | \ |
// | \
// \--/\
// |
// |
// --- GND
//
//
// Dov Grobgeld
// 2020-07-22 Wed
// Load Wi-Fi library
#include <ESP8266WiFi.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include "ir_Coolix.h"
// Replace with your network credentials
const char* ssid = "myssid";
const char* password = "mypw";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Assign output variables to GPIO pins
const int output5 = 5; // for debugging only
const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use for IR
void setup()
{
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output5, OUTPUT);
pinMode(kIrLed, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(kIrLed, LOW);
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
uint16_t countValuesInStr(const String str, char sep)
{
int16_t index = -1;
uint16_t count = 1;
do {
index = str.indexOf(sep, index + 1);
count++;
} while (index != -1);
return count;
}
// Dynamically allocate an array of uint16_t's.
// Args:
// size: Nr. of uint16_t's need to be in the new array.
// Returns:
// A Ptr to the new array. Restarts the ESP8266 if it fails.
uint16_t * newCodeArray(const uint16_t size)
{
uint16_t *result;
result = reinterpret_cast<uint16_t*>(malloc(size * sizeof(uint16_t)));
// Check we malloc'ed successfully.
if (result == NULL) { // malloc failed, so give up.
Serial.printf("\nCan't allocate %d bytes. (%d bytes free)\n",
size * sizeof(uint16_t), ESP.getFreeHeap());
Serial.println("Giving up & forcing a reboot.");
ESP.restart(); // Reboot.
delay(500); // Wait for the restart to happen.
return result; // Should never get here, but just in case.
}
return result;
}
// Parse a raw IR code received from the web client
bool parseStringAndSendRaw(const String str)
{
uint16_t count;
uint16_t freq = 38000; // Default to 38kHz.
uint16_t *raw_array;
// Find out how many items there are in the string.
count = countValuesInStr(str, ',');
// We expect the frequency as the first comma separated value, so we need at
// least two values. If not, bail out.
if (count < 2)
return false;
count--; // We don't count the frequency value as part of the raw array.
// Now we know how many there are, allocate the memory to store them all.
raw_array = newCodeArray(count);
// Grab the first value from the string, as it is the frequency.
int16_t index = str.indexOf(',', 0);
freq = str.substring(0, index).toInt();
uint16_t start_from = index + 1;
// Rest of the string are values for the raw array.
// Now convert the strings to integers and place them in raw_array.
count = 0;
do {
index = str.indexOf(',', start_from);
raw_array[count] = str.substring(start_from, index).toInt();
start_from = index + 1;
count++;
} while (index != -1);
IRsend irsend(kIrLed);
irsend.sendRaw(raw_array, count, freq); // All done. Send it.
free(raw_array); // Free up the memory allocated.
if (count > 0)
return true; // We sent something.
return false; // We probably didn't.
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
// values we parse
int pin=-1;
int output=-1;
String code="";
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Parse the query
int p = header.indexOf("?");
while (p>=0)
{
int peq=header.indexOf("=",p);
int np=header.indexOf("&",p+1);
int nsp=header.indexOf(" ",p+1);
// Check if this is a valid query string if so parse it
if (peq>0 && (np>0||nsp>0))
{
String key = header.substring(p+1,peq);
int val_end = np;
if (val_end < 0)
val_end = nsp;
if (val_end < 0)
// This shouldn't happen in a valid string
break;
String value = header.substring(peq+1,val_end);
// Here we parse
if (key=="pin")
pin = value.toInt();
else if (key=="output")
output = value.toInt();
else if (key=="code")
code=value;
Serial.println("kv: " + key + "->" + value);
}
p = np; // Progress to the next keyword entry
}
String message;
// Support the pin command for turning on pin 5. This
// is only for debugging.
if (pin == 5)
{
int onoff = int(output>0);
message += "Setting pin " + String(pin) + " to " + String(output);
pinMode(pin, OUTPUT);
digitalWrite(pin, output);
}
// Send a raw IR code
else if (code.length())
{
parseStringAndSendRaw(code);
message += "Sending raw code!";
}
else
message += "No request received!";
Serial.println(message);
client.print("<!DOCTYPE html><html>"
"<head>"
"<title>ESP8266 Web Server</title>\n"
"<meta charset=\"UTF-8\">"
"</head>"
"<body>"
"<h1>Web IR Server</h1>"
"This is a ESP8266 IR server. You control me by\n"
"sending raw IR codes through the command\n"
"<pre>\n"
" wget http://");
client.print(WiFi.localIP());
client.print("/?code=«raw code»"
"</pre>\n");
if (message.length())
{
client.print("<hr>message=" + message);
client.print("<br/>");
}
client.print("</body>"
"</html>");
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment