ESP8266 and LEDs

After the short excurse with Blynk in the previous post I wanted to do the same without a company between. After all, controlling an LED is rather simple.

So back to basics: MQTT it is. Got a Mosquitto instance on the Internet with the following docker-compose.yml definition:

version: '2'
services:
  mqtt:
    image: toke/mosquitto
    ports:
      - "1883:1883"
    volumes:
      - "./mqtt/config:/mqtt/config"
      - "./mqtt/log:/mqtt/log"
      - "./mqtt/data:/mqtt/data"
    restart: always

Very basic configuration. No TLS, but I defined a user. Not secure, but good enough for now.

The Espruino program running on the ESP8266 is simple (slightly updated as I found out that properly reconnecting/re-subscribing is critical):

np=require("neopixel");

var debug=false;

var mqtt = require("MQTT").connect({
  host: "mqtt.my.domain.org",
  username: "MY_USERNAME",
  password: "MY_PASSWORD",
});

var myPixel=[0, 0, 0];
const ledPin=D2;

function updateLED(v) {
  np.write(ledPin, v);
}

// s: RxxxGxxxBxxx with xxx=0..255
// All valid: R0G0B0, G255R0B0, G10, G80B80R

function getRGB(s) {
    var rgb=[-1, -1, -1];
    var currentIndex=-1;

    for (let i=0; i<s.length; ++i) {
        switch(s[i]) {
            case 'r':
            case 'R': currentIndex=0; rgb[currentIndex]=0; break;
            case 'g':
            case 'G': currentIndex=1; rgb[currentIndex]=0; break;
            case 'b':
            case 'B': currentIndex=2; rgb[currentIndex]=0; break;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                if (currentIndex!=-1) {
                rgb[currentIndex]=rgb[currentIndex]*10+s.charCodeAt(i)-48;
                break;
            }
        }

    }
    var res={};
    if (rgb[0]!=-1) { res.r=Math.min(rgb[0], 255); }
    if (rgb[1]!=-1) { res.g=Math.min(rgb[1], 255); }
    if (rgb[2]!=-1) { res.b=Math.min(rgb[2], 255); }
    return res;
}

function setLED(s) {
  let values=getRGB(s);
  if (values.hasOwnProperty('r')) myPixel[1]=values.r;
  if (values.hasOwnProperty('g')) myPixel[0]=values.g;
  if (values.hasOwnProperty('b')) myPixel[2]=values.b;
  updateLED(myPixel);
}

function log(s) {
  if (debug) {
    console.log(s);
  }
}

// Program starts here

updateLED([20,0,0]);

mqtt.on("connected", () => {
  log("Subscribing to LED");
  mqtt.subscribe("LED");
});

mqtt.on('disconnected', () => {
  log("Disconnected...");
  updateLED([0,20,0]);
  //setInterval(()=>{
  //  updateLED([0,20,0]);
  //  setTimeout(()=>{updateLED([0,0,0]);},50);
  //}, 500);
  setTimeout(()=>{
    log("reconnecting...");
    mqtt.connect();
  }, 1000);
});

mqtt.on('error', (err) => {
  log("Got error: "+error);
  updateLED([0,20,0]);
});

mqtt.on('publish', function (pub) {
  log("topic: "+pub.topic);
  log("message: "+pub.message);
  setLED(pub.message);
});


mqtt.on('subscribed', () => {
  log("Subscription successful");
});

mqtt.on('subscribed_fail', () => {
  log("Subscription failed");
});

mqtt.on('unsubscribed', () => {
  log("unsubscribed received");
});

mqtt.on('ping_reply', () => {
  log("ping_reply received");
});

mqtt.on('puback', () => {
  log("puback received");
});

mqtt.on('pubcomp', () => {
  log("pubcomp received");
});

Test via plumber:

❯ plumber write mqtt --topic="LED" --client-id="Plumber-1" --address="tcp://MY_USERNAME:MY_PASSWORD@mqtt.my.domain.org:1883" --input-data "R200G0B200"

Testing also works with MQTTlens.

And there we go: An Internet controllable LED! Total costs: Wemos D1 mini: $3, WS2812B LED module: $1.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Create your website with WordPress.com
Get started
%d bloggers like this: