Is it perfect? No. Is it fast? No. Does it have super low latency? No. Is it energy efficient? Yes, very much so. And it helps you to connect 2 (or more) ESP8266 wireless modules with just a couple lines of code. The code can be modified and uploaded with Arduino IDE. If you connect multiple clients (max 3 using ESP8266WiFi.h) to one server, overloading the server resulting in a Denial of Service / reset can occur. Now go on and have fun with it!

To check in on your Server module, connect your smartphone’s wireless to ESPap, and use the login code “thereisnospoon”. A yellow web site with 2 buttons (red and black) appears when you navigate to Leg GPIO5 (D1) of your ESP8266-12E will alternate from 3V3 to 0 volts every second. Just connect an LED with a series resistor of 100 Ohms to ground and you’re good to go!


2 ESP8266 modules, NodeMCU 12E version is preferred since it incorporates the wiring, reset buttons and FTDI module in one convenient PCB.

Arduino IDE 1.6.5, since for no obvious reason this code doesn’t work on 1.6.7. There are some issues with the libraries, in respect that in the newer version the libraries are in a different location.

Quick start:

Set the Arduino IDE according to:

  • Install Arduino 1.6.5 from the Arduino website.
  • Start Arduino and open Preferences window.
  • Enter into Additional Board Manager URLs field. You can add multiple URLs, separating them with commas.
  • Open Boards Manager from Tools > Board menu and install esp8266 platform (and don’t forget to select your ESP8266 board from Tools > Board menu after installation).

Server code

// code for this example was gratefully “borrowed” from: and and and modified.

// Go to in a web browser connected to this access point to see the web page you generated.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h> // serves only one client at a time

const int ANALOG_PIN = A0; // The only analogue pin
const int DIGITAL_PIN = 4; // Digital pin to be read – corresponds to GPIO4, or D2 on an ESP8266-12E.

// Set these to your desired credentials.
const char *ssid = “ESPap”;
const char *password = “thereisnospoon”;
ESP8266WebServer server(80); // webserver on port 80, you can exclude this line if the port number is 80. It is the standard http port.

void handleRoot() {
String out = “<html><head><title>Wifi light</title></head>”;
out += “<body style=’background-color:yellow’>”;
out += “<span style=’display:block; width:100%; font-size:2em; font-family:Verdana; text-align:center’>Choose color</span><br/>”;
out += “<a href=’red’><span style=’display:block; background-color:red; width:100%; height:6em;’></span></a><br/>”;
out += “<a href=’black’><span style=’display:block; background-color:black; width:100%; height:6em;’></span></a><br/>”;
out += “<h1>Analog Pin = <h1>”;
out += String(analogRead(ANALOG_PIN));
out += “<br>”; // Go to the next line.
out += “<h1>Digital Pin 4 = <h1>”;
out += String(digitalRead(DIGITAL_PIN));
out += “</body>”;
out += “</html>”;
server.send ( 200, “text/html”, out );

void setup() {
Serial.print(“Configuring access point…”);
WiFi.softAP(ssid, password); // You can remove the password parameter if you want the AP to be open. Doesn’t work too great on all mobile phones.
// while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(“.”); } // this line gives you dots as long is there is no connection. Just comment it out.


IPAddress myIP = WiFi.softAPIP();
Serial.print(“AP IP address: “);
server.on(“/”, handleRoot);
Serial.println(“HTTP server started”);

// this handles the input coming from connected devices. It parses the commands /red and /black and toggles GPIO5 accordingly.
server.on ( “/”, []() {handleRoot();} );
server.on ( “/red”, []() {handleRoot(); Serial.println(“red”); digitalWrite (5,1);} );
server.on ( “/black”, []() {handleRoot(); Serial.println(“black”); digitalWrite (5,0);} );

void loop() {

Client code

(automatically presses the Red and Black buttons for you every second)

// code for this example was gratefully “borrowed” from the sites below:
// Arduino libraries
// … and of course modified 🙂

#include <ESP8266WiFi.h>

const char* ssid = “ESPap”;
const char* password = “thereisnospoon”;
const char* host = “”;

void setup() {

// We start by connecting to the ESPap WiFi network

Serial.print(“Connecting to “);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

Serial.println(“WiFi connected”);
Serial.println(“IP address: “);

int value = 0;

void loop() {
WiFiClient client; //Use WiFiClient class to create TCP connections

// The piece of code below makes sure you have an actual live connection.
IPAddress server(192,168,4,1);
if (client.connect(server, 80)) {

// We now create a URI for the request
String url = “”;
Serial.print(“Requesting URL: “);

client.print(String(“GET /red HTTP/1.1rnHost: closernrn”)); // HTTP GET request
if (client.connect(server, 80)) {
client.print(String(“GET /black HTTP/1.1rnHost: closernrn”)); // HTTP GET request


Wish list:

  • Change the IP address of the hosted web-site from to whatever you want.


#define SOFTAP_IF 0x01
struct ip_info ipinfo;
if(wifi_get_ip_info(SOFTAP_IF, &ipinfo))
IP4_ADDR(&ipinfo.ip, 192, 168, 1, 1);
IP4_ADDR(&, 192, 168, 1, 1);
IP4_ADDR(&ipinfo.netmask, 255, 255, 255, 0);
if(!wifi_set_ip_info(SOFTAP_IF, &ipinfo))
os_printf(“CTRL not set IP config!rn”);
} else {
os_printf(“CONFIGURATION WEB SERVER IP: ” IPSTR “rn”, IP2STR(&ipinfo.ip));

  • Now, only simple commands can be transferred. If you need to send the value of a variable, you’ll be in trouble. Send AJAX or JSON objects and parse them.
  • Modify the code from standard HTTP to Websockets, so you don’t have to refresh the whole site after pressing a button. Faster and more efficient when you are continuously sending data using AJAX or JSON.
  • Over The Air (OTA) updates: program a bootloader just once and update your code without manually resetting the ESP8266. Seriously easy going…
  • Oscope (ColorChord) and GPIO readout
  • Message Queueing Telemetry Transport (MQTT) implementation