Sample Sketch for ESP-12 w/ Integral Web Page Full Function
Posted: Thu Oct 29, 2015 2:22 pm
This Project is an Depuration and improvement of few similar projects I saw Here and There that hepme to learn ESP-Arduino.
It's Aimed at ESP8266-12 Dev Board (the One with Photo Resistors, Leds, and a bunch of GPIOs).
This Project lets you Control 4 Outputs from "buttons" on a web page, as well Continuously Monitor 2 Inputs and the ADC Input.
To monitor Inputs, its uses AJAX (javascript/html), so its hyper-efficient on bandwidt, no need to call to Comcast for Broader Internet, don worry its supported by most Phones and Every PC build from 1995
Works Well ( I debugged most of other project's pitfails ), Just Customize to your application.
I'm here learning as you, don't see me as a Guru, just promise me to doit better and share your work.
It's Aimed at ESP8266-12 Dev Board (the One with Photo Resistors, Leds, and a bunch of GPIOs).
This Project lets you Control 4 Outputs from "buttons" on a web page, as well Continuously Monitor 2 Inputs and the ADC Input.
To monitor Inputs, its uses AJAX (javascript/html), so its hyper-efficient on bandwidt, no need to call to Comcast for Broader Internet, don worry its supported by most Phones and Every PC build from 1995
Works Well ( I debugged most of other project's pitfails ), Just Customize to your application.
I'm here learning as you, don't see me as a Guru, just promise me to doit better and share your work.
Code: Select all
/*
* I just started with ESP8266 since I have few urgent IoT needs to fulfill, and its ideal for my purposes, but I find no useful samples
* to help me for such simple IoT solution I pursuit.
* then reading here and there I gathered the blocks to build my IoT ESP-12
* I home many people here sharing this need could find this project useful
* Dont give me credits, I Just Improved what I've find puting toghether in an single project which could be an
* start point for many others with similar need
*
* This work is an improvement on previous tutorials published here ot other webs
* Particular thanks to Rui Santos and its Arduino-Ethernet Shield tutorials from which tis the base for this work (and the CSS styleSheet is used here)
* Visit: http://randomnerdtutorials.com for more details
*
* Also the "Garage Door Opener V2 by SWilson http://www.esp8266.com/viewtopic.php?f=29&t=2696 provided most of the help
* very useful info needed to handle ajax html and other WEB-Related technologies can be found at http://www.w3schools.com/js/default.asp
*
* Fell free to copy/improve/etc onle compensation wanted is you share your ESP8266 projects here
*
* WARNING: this project is released "as is" with no warranty, you are responsible for it, use it as learning tool not as part for a commercial
* or production device.
*
* LICENSE: MIT (which means you can copy and if you like to share it again as you like, no snake GPL viral clauses.
*
* this project for testing uses an css style sheet read from Rui SantosÅ› examples "ethernetcss.css" you can find it at its Arduino-Ethernet sample
* my safety suggestion if you decide to use an CSS style sheet derived or no from 'santos, is you should host it at your own controlled server,
* this way minimizes DDoS Attacks or other Attacks on your IoT network.
* Preferable to use ths solution on an Intranet with VPN access from the exterior and not allow the IoT modules to receive externa connexions.
*
* I'don't speak English natively, I do may best effort to express here, sorry for any error
*
* Thanks
* J.A. Acosta
*
*/
#include <ESP8266WiFi.h>
#define serverPort 80
// define (map) GPIO to HTML Fields (buttons/Indicators), note: not using 0 as base index deliberately
#define input1 16
#define input2 14
#define statusLEDr 15
#define statusLEDg 12
#define statusLEDb 15
#define output1 4
#define output2 5
#define output3 2
#define output4 0
WiFiServer server(serverPort);
//*-- IoT Information
const char* _SSID = "yourNetworkSSID";
const char* _PASS = "yourNetworkPass";
const char* _passcode = "1234";//note: the field "passcode in the html form "frm1" must match the passcode lenght
char passcodeOK='0';//start Code is blank...
String readString;
int analogReadOut = 0;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
pinMode(output1, OUTPUT);
pinMode(output2, OUTPUT);
pinMode(output3, OUTPUT);
// avoid using pin0 while on development, cause is more difficult to upload code since ESP_COMM must be connected before owncode start
//pinMode(output4, OUTPUT); //uncomment to control output #4
pinMode(statusLEDr, OUTPUT);
pinMode(statusLEDg, OUTPUT);
pinMode(statusLEDb, OUTPUT);
pinMode(input1, INPUT);
pinMode(input2, INPUT);
delay(50);
Serial.print("Connecting to ");
Serial.println(_SSID);
WiFi.begin(_SSID, _PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected to:");
Serial.println(_SSID);
delay(1000);
ESP.wdtEnable(WDTO_4S);
//Start the server
server.begin();
Serial.println("Server started");
//Print the IP Address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.print(":");
Serial.print(serverPort);
Serial.println("/");
delay(1000);
}
void loop() {
//reset code for re-validation
passcodeOK='0';
// Create a client connection
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
}
// HTTP request has ended
if (c == '\n') {
if (readString.indexOf(String("sensorupdrq"))>0){//this branch purpose is to discriminate ajax update request from standad web request to, if you dont need
Serial.println("\r\najax sensor upd req:"); //comment the entire branch all '//<<<' lines
Serial.print(readString);//<<<
client.println("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: keep-alive"); // <<<
readInputs(client);//<<<
}//<<<
else//<<<
{
Serial.println("web request:");
Serial.print(readString);
if (readString.indexOf(String("passcode="))>0){
if (readString.indexOf(String(_passcode))>0) {
passcodeOK='1';
Serial.println("Password OK");
digitalWrite(statusLEDg, HIGH);
digitalWrite(statusLEDr, LOW);
}else{
passcodeOK='0';
Serial.println("Password NotOK");
digitalWrite(statusLEDg, LOW);
digitalWrite(statusLEDr, HIGH);
}
}
client.println("HTTP/1.1 200 OK\r\nContent-Type: text/html");
client.println("\r\n<HTML>");
client.println("<HEAD>");
client.println("<meta name=\"viewport\" content=\"width=380\">");
// Important, edit the Following line to match your CSS style sheet location, I suggest you to host at your own controlled server
client.println("<link rel='stylesheet' type='text/css' href='http://--PATH TO YOUR CSS--/ethernetcss.css' />");
client.println("<TITLE>FULL ESP8266-12 CONTROL DEMO</TITLE>");
// simple javascritp code to intercept anchor clientick and trick HREF field with the Button (or action) ID and add the password from the input field
client.println("\r\n<script>\r\nfunction SndCommand( obx,swtchNO ){ \r\nobx.href=\"button\"+swtchNO+\"&passcode=\"+document.getElementById(\"frm1\").elements[0].value;\r\n}\r\n</script>\r\n");
// not so simple script to allow sensor data to be automatically updated
client.println("\r\n<script>\r\nfunction GetSensorUpd() {\r\nnocache = \"&nocache=\" + Math.random() * 1000000;");
client.println("var ajaxreq = new XMLHttpRequest();");
client.println("ajaxreq.open(\"GET\", \"sensorupdrq\" + nocache, true);");
client.println("ajaxreq.onreadystatechange = function() {");
client.println("if (ajaxreq.readyState == 4 && ajaxreq.status == 200) {");
client.println("document.getElementById(\"readX\").innerHTML = ajaxreq.responseText;");
client.println("}\r\n}\r\najaxreq.send();");
client.println("setTimeout('GetSensorUpd()', 5000);\r\n}\r\n</script>\r\n");//updates each half second
client.println("</HEAD>");
client.println("<BODY onload=\"GetSensorUpd()\">");//comment thiss if you do not want automatic sensor update
// client.println("<BODY>");//uncomment this if yoy do not want auto update
client.println("<H1>Demo to Control Output<br />and<br />Sensor Read with ESP8266</H1>");
client.println("<br />");
client.print("<div id=\"passx\"><form id=\"frm1\">Password:<input name=\"passcode\" size=\"5\" maxlength=\"4\" type=\"password\" value=\"");
if (passcodeOK== '1') client.print(_passcode);
client.println("\" style='font-size:24pt'></form></div>");
client.print("<div id=\"readX\">");
readInputs(client);
client.println("</div>");
// first ON/OFF Buttons pair
client.println("<BR /><a href=\"\" onclick=\"SndCommand(this,11)\">Output 1 On</a>");
//SndCommand is a javascript code running on the clientiet (aka ajax) Parameters are outputIDx and State
client.println("<a href=\"\" onclick=\"SndCommand(this,10)\">Output 1 Off</a><br /><br />");
// then repeat for every gpio as output to control
client.println("<a href=\"\" onclick=\"SndCommand(this,21)\">Output 2 On</a>");
client.println("<a href=\"\" onclick=\"SndCommand(this,20)\">Output 2 Off</a><br /><br />");
client.println("<a href=\"\" onclick=\"SndCommand(this,31)\">Output 3 On</a>");
client.println("<a href=\"\" onclick=\"SndCommand(this,30)\">Output 3 Off</a><br /><br />");
client.println("<a href=\"\" onclick=\"SndCommand(this,41)\">Output 4 On</a>");
client.println("<a href=\"\" onclick=\"SndCommand(this,40)\">Output 4 Off</a><br /><br />");
client.println("</BODY>");
client.println("</HTML>");
//Processing client request
// Button0
if (readString.indexOf("button11") >0 && passcodeOK== '1'){
digitalWrite(output1, HIGH);
}
if (readString.indexOf("button10")>0 && passcodeOK== '1'){
digitalWrite(output1, LOW);
}
if (readString.indexOf("button21") >0 && passcodeOK== '1'){
digitalWrite(output2, HIGH);
}
if (readString.indexOf("button20")>0 && passcodeOK== '1'){
digitalWrite(output2, LOW);
}
if (readString.indexOf("button31") >0 && passcodeOK== '1'){
digitalWrite(output3, HIGH);
}
if (readString.indexOf("button30")>0 && passcodeOK== '1'){
digitalWrite(output3, LOW);
}
if (readString.indexOf("button41") >0 && passcodeOK== '1'){
digitalWrite(output4, HIGH);
}
if (readString.indexOf("button40")>0 && passcodeOK== '1'){
digitalWrite(output4, LOW);
}
}
delay(1);
client.stop();
delay(0);
//clean readString for next read
readString="";
digitalWrite(statusLEDg, LOW);
digitalWrite(statusLEDr, LOW);
}
}
}
}
}
// send back GPIO Data Refresh
void readInputs(WiFiClient cl) {
cl.println("\r\n<p>");//dont miss to wrap the request with some tag, mandatory for ajax to work properly
analogReadOut = analogRead(A0);
if (analogReadOut < 50){
cl.print("<p>Analog Reading:<span style='background-color:#00FF00; font-size:18pt'>");
cl.print(analogReadOut);
cl.println("</span></p>");
}else{
cl.print("<p>Analog Reading:<span style='background-color:#FF0000; font-size:18pt'>");
cl.print(analogReadOut);
cl.println("</span></p>");
}
cl.println("<br />");
if (digitalRead(input1)) {
cl.println("<p>Input ONE is: <span style='background-color:#00FF00; font-size:18pt'>ON</span></p>");
}else{
cl.println("<p>Input ONE is: <span style='background-color:#FF0000; font-size:18pt'>OFF</span></p>");
}
cl.println("<br />");
if (digitalRead(input2)) {
cl.println("<p>Input TWO is: <span style='background-color:#00FF00; font-size:18pt'>ON</span></p>");
}else{
cl.println("<p>Input TWO is: <span style='background-color:#FF0000; font-size:18pt'>OFF</span></p>");
}
cl.println("</p>");//this tag completes the request wrap
Serial.println("ajax sensor upd sent\r\n");
}