ESP8266 NodeMCU LED Busy Server

I built a Slack status light because it looked awesome and simple, and at that time I knew nothing about DIY electronics. As I learned more, I outlined how to build a cheaper one on a Raspberry Pi. Then my friend then informed me that you can do it even cheaper with an ESP32 NodeMCU board. He was right. Here’s how I built a IoT busy light for around $5.

For this example, I opted for the older ESP8266 ESP12-E NodeMCU board, it is only $2.65 + 1.73 shipping and has everything needed. Pair that with a cheap RGB shared cathode LED $0.50-$2.00, and a few cents for resistors, for a grand total of around $5* in parts.

I won’t go into the details on the boards, but if unfamiliar it, the tl;dr is you write some C/Lua code using the Ardunio IDE, include WIFI for ESP8266 and Web Server libraries (here’s hello world example code and a great setup video) and add some handlers to toggle the GPIO pins on certain requests, then flash that code onto the board over USB. If never used before, I assure you it’s not as hard or complicated as it may sound or appear. When the board is plugged in, it fires up, the code executes, connecting to WIFI, and this tiny board becomes a server in your local network.

Here’s the wiring I did:

& here’s the code I flashed onto it (note you will need to add your WIFI credentials):

/* ESP8266 NodeMCU RGB LED Busy Server
 *  
 * Set an RGB LED to current status via web request 
 * 
 * 1. Flash this file to a ESP-12E
 * 2. Open Serial to get the IP address of board
 * 3. Optionally set a dedicated DHCP reservation at the router level to ensure same IP address is used
 * 4. Connect common anode or common cathode RGB LED (see pins below)
 * 5. Make `GET` request to `http://<IP>/<status>`
 *
 * Statuses:
 *
 * - 🔴 `/busy`
 * - 🟢 `/available`
 * - 🟡 `/away`
 * - ⚫️ `/offline`
 * 
 * @see https://davidsword.ca/esp8266-busy-server/
 */
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

// @see https://github.com/BretStateham/RGBLED
// must install this library in Arduino IDE
#include <RGBLED.h>

uint8_t red_led   = 16; // D0
uint8_t green_led = 5;  // D1
uint8_t blue_led  = 4;  // D2

ESP8266WebServer server;
RGBLED rgbLed( red_led, green_led, blue_led, COMMON_CATHODE ); // or `COMMON_ANODE` if using common anode RGB LED instead

char* ssid        = ""; // <<< enter your WIFI network name
char* password    = ""; // <<< enter your WIFI password

void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid,password);
  while(WiFi.status()!=WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  
  digitalWrite(BUILTIN_LED, LOW);
  rgbLed.writeRGB(255,255,255);

  server.on("/",[](){server.send(200,"text/plain","see readme");});
  // @TODO can output current state on /status requests
    // server.on("/status",[](){server.send(200,"text/plain", "(r,g,b)=(" + String(rgbLed.redValue) + "," + String(rgbLed.greenValue) + "," + String(rgbLed.blueValue) + ")" });
  server.on("/busy",setBusy);
  server.on("/available",setAvailable);
  server.on("/away",setAway);
  server.on("/offline",setOffline);
  server.on("/off",setOffline);
  server.begin();
}

void loop()
{
  server.handleClient();
}

void setBusy()
{
  rgbLed.writeRGB(50,0,0); // red. not using the full `255` in an attempt to reduce brightness.
  server.send(204,"");
}
void setAvailable()
{
  rgbLed.writeRGB(0,25,0); // green
  server.send(204,"");
}
void setAway()
{
  rgbLed.writeRGB(100,25,0); // yellow. mix wasn't 50/50 red/green as expected. this might be different for each make of LED.
  server.send(204,"");
}
void setOffline()
{
  rgbLed.turnOff();
  server.send(204,"");
}

From there, I added a simple CURL request into my app that’s currently handling the updating of my other busy light based on a polling of Slack status.

I placed this downstairs in my kitchen as a sort of satellite Slack Busy Light, so my family could check in on my status while not in our upstairs hallway:

If you have a common anode RGB LED, be aware the mixing of colours (on startup and when ‘away’) probably won’t work out of the box. Mixing colours on a common anode RGB requires some sort of pulsing frequency – can probably Google for more info on this or a library. Also the script will need to be edited, changing LOWs to HIGHs and OUTPUTs to INPUTs, and vice versa. I’ve updated the script to use a library to get the mixed colours more accurate for both common anode and common cathode.

* despite this low cost, I personally didn’t want to wait for shipping overseas, so instead I went with a Canadian supplier and bought a pre-wired no soldering RGB LED for $3.95 and the board for $9.98 (on sale). There was a $12 shipping fee, but I order a lot from them so that cost is hardly noticed. Even so, that’s just $14 (+ $12 shipping). Amazon and many other stores also has low prices for these parts.

Leave a Reply

Your email address will not be published. Required fields are marked *