Led Control

This tutorial presents how Beebotte can be used to control a led connected to an Arduino board. We will use MQTT protocol to connect Arduino to Beebotte to subscribe to messages to turn ON or OFF the led.
This tutorial assumes that you have successfully registered to Beebotte and obtained your API and Secret keys.

Tutorial contents:

Required Hardware

We need the following hardware in order to complete this tutorial:

  • Arduino UNO board or equivalent
  • Arduino Ethernet Shield to connect to the Internet
  • Breadboard (tiny one is enough)
  • LED
  • 220 Ω resistance
  • Jumper wires

Required Software and libraries

We will use the Arduino IDE to write our code, compile it and upload it to the board. We will use community provided Arduino libraries for MQTT connectivity and JSON parsing/decoding:

Open your Arduino IDE, click on Sketch tab and go to Include Library to install PubSubClient and ArduinoJson libraries.

Wiring

Follow the following wiring diagram to setup your hardware:


Create a Channel

In your account home page, click on Create New and follow the instructions to create your channel.

For the purpose of this tutorial, we will create a channel named Arduino and add a resource led with type boolean. We will enable the Send on Subscribe (SoS) option on the resource. When enabled, this option allows the most recent persistent value to be automatically sent over when a client subscribes to the resource. This is particularly useful to set the LED to the corresponding state after a disconnection.


Subscribing to led control messages

Include dependencies:

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

Set constants and definitions and MQTT client

#define LEDPIN            2         // Pin which is connected to LED.

#define BBT "mqtt.beebotte.com"     // Domain name of Beebotte MQTT service
#define TOKEN "token:XXXXXXXXXX"    // Set your channel token here

#define CHANNEL "Arduino"          // Replace with your device name
#define LED_RESOURCE "led"

EthernetClient ethClient;
PubSubClient client(ethClient);

// Enter a MAC address of your shield
// It might be printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// to track delay since last reconnection
long lastReconnectAttempt = 0;

The Sketch setup function

void setup()
{
  pinMode(LEDPIN, OUTPUT);

  client.setServer(BBT, 1883);
  // Set the on message callback
  // onMesage function will be called
  // every time the client received a message
  client.setCallback(onMessage);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // try to congifure using static IP address instead of DHCP:
    // Feel free to change this according to your network settings
    IPAddress ip(192, 168, 0, 177);
    Ethernet.begin(mac, ip);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");
  lastReconnectAttempt = 0;
}

MQTT on message callback function. This will be called every time a message is received

void onMessage(char* topic, byte* payload, unsigned int length) {
  // decode the JSON payload
  StaticJsonBuffer<128> jsonInBuffer;
  JsonObject& root = jsonInBuffer.parseObject(payload);

  // Test if parsing succeeds.
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }

  // led resource is a boolean read it accordingly
  bool data = root["data"];

  // Set the led pin to high or low
  digitalWrite(LEDPIN, data ? HIGH : LOW);

  // Print the received value to serial monitor for debugging
  Serial.print("Received message of length ");
  Serial.print(length);
  Serial.println();
  Serial.print("data ");
  Serial.print(data);
  Serial.println();
}

A utility function to generate random ID for the MQTT connection

const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
char id[17];

const char * generateID()
{
  randomSeed(analogRead(0));
  int i = 0;
  for(i = 0; i < sizeof(id) - 1; i++) {
    id[i] = chars[random(sizeof(chars))];
  }
  id[sizeof(id) -1] = '\0';

  return id;
}

The Sketch's loop and MQTT reconnect function in case connection to Beebotte is lost:

// reconnects to Beebotte MQTT server
boolean reconnect() {
  if (client.connect(generateID(), TOKEN, "")) {
    char topic[64];
    sprintf(topic, "%s/%s", CHANNEL, LED_RESOURCE);
    client.subscribe(topic);

    Serial.println("Connected to Beebotte MQTT");
  }
  return client.connected();
}

void loop()
{
  if (!client.connected()) {
    long now = millis();
    if (now - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = now;
      // Attempt to reconnect
      if (reconnect()) {
        lastReconnectAttempt = 0;
      }
    }
  } else {
    // Client connected
    delay(50);
    client.loop();
  }
}

The complete code along with other Arduino examples can be accessed on Github.

Creating a Dashboard with a control widget

In your account page, go to My Dashboards and click Create Dashboard; enter a friendly name and a short description for your dashboard then add an ON/OFF Widget. Indicate the channel and resource you want to control with this widget. Voilà.

You need to log in to your Beebotte account in order to control your LED with the ON/Off widget. This is to restrict control widgets like On/Off to authenticated users.