IoT boilerplate

From MDD wiki
Revision as of 15:26, 31 August 2022 by Xiduzo (talk | contribs) (→‎Arduino: more ellaborate explenation for esp32 boards)
Jump to navigation Jump to search

About

This page will not explain how IoT works, but will give you examples on getting started. In the resource section of this page you will find more step-by-step tutorials

MDD-tardis IoT broker

The MDD has a server that is configured to be used for IoT applications. The server is using the mosquitto MQTT broker, which is irrelevant for starting users.

Connection info

server: mqtt.mdd-tardis.net or 37.97.203.138
port: 1883 / 9001 (when using websockets)
user: mdduser
pass: IoTMDD

When using platforms like Arduino or processing use port number 1883. In javascript use port number 9001.

Tools

There are some free tools out there that help you set up the connection to the MQTT broker

Arduino: https://github.com/256dpi/arduino-mqtt
Processing: https://github.com/256dpi/processing-mqtt
JavaScript: https://github.com/mqttjs/MQTT.js
Go: https://github.com/256dpi/gomqtt
Ruby: https://github.com/njh/ruby-mqtt
C: http://www.eclipse.org/paho/clients/c/
C++: http://www.eclipse.org/paho/clients/cpp
Java: http://www.eclipse.org/paho/clients/java
Python: http://www.eclipse.org/paho/clients/python

Get started code

Python

Using paho-mqtt to connect to our MQTT broker

The python source code is

import paho.mqtt.client as mqtt
import time

host="37.97.203.138"
user="mdduser"
pwd="IoTMDD"
clientID="LearningStudent"
topic="/testtopic"

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    code = str(rc)
    print(f'connected with result code {code}')

    # Subscribing in on_connect() means that if we lose the connection and
    # reconnect then subscriptions will be renewed.
    print(f'Subscribing to {topic}')
    client.subscribe(topic)

def on_disconnect(client, userdata, rc):
    code = str(rc)
    print(f'disconnected with result code {code}')

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    message = str(msg.payload)
    print(f'Message received from topic: {msg.topic}: {message}')

client = mqtt.Client(clientID)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message

print(f'connecting to {host} as {clientID}')
client.username_pw_set(user, pwd)
client.will_set(topic)
client.connect(host)


print(f'start loop')
client.loop_start()

while True:
    client.publish(topic, "test")
    time.sleep(1)

Javascript

When using javascript to connect to our MQTT broker, use port 9001 and a library like the Paho MQTT client

The HTML/js source code

<html>

   <head>
   	<!-- load the paho library -->
   	<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.2/mqttws31.min.js" type="text/javascript"></script>
   	<script type="text/javascript">
   		var host = "37.97.203.138";
   		var port = 9001;
   		var user = "mdduser";
   		var pass = "IoTMDD";
   		var clientID = "LearningStudent"
   		var topic = "/testtopic"
   		var client;

   		function init() {
   			println("Connecting to "+host+" as "+clientID);

   			client = new Paho.MQTT.Client(host, Number(port), clientID);
		    // Set callback handlers
		    client.onConnectionLost = onConnectionLost;
		    client.onMessageArrived = onMessageArrived;
		    // Connect the client, if successful, call onConnect function
		    client.connect({
                      userName: user,
                      password: pass,
                      onSuccess: onConnect,
                      useSSL: window.location.protocol === "https:",
                      onFailure: console.log,
		    });
   		}

   		// Called when the client connects
		function onConnect() {
		    println('connected.');
		    println('Subscribing to: ' + topic);

		    // Subscribe to the requested topic
		    client.subscribe(topic);

		    document.getElementById('sendButton').disabled = false;
		}

		function sendMessage() {
			client.send(topic, "Hello world!");
		}

   		function onConnectionLost(responseObject) {
		    println('Connection lost');
		    if (responseObject.errorCode !== 0) {
		        println('ERROR: ' + + responseObject.errorMessage);
		    }
		}

		// Called when a message arrives
		function onMessageArrived(message) {
		    console.log("onMessageArrived: " + message.payloadString);
		    println('Message received from topic: ' + message.destinationName + ': ' + message.payloadString);
		}

   		function println(msg) {
   			document.getElementById('messages').innerHTML+='<span>'+msg+'</span><br/>';
   		}

   	</script>
   </head>

   <body>
     <h1>Simple Paho MQTT demo</h1>
     <input type="button" id="connectButton" onclick="init();" value="connect" enabled/>
     <input type="button" id="sendButton" onclick="sendMessage();" value="send a message" disabled/>
     <p/>
     <div id="messages"></div>
   </body>

</html>

Processing

This processing example shows how to send and receive data on two different channels by subscribing and publishing to different channels:

Processing source code

import mqtt.*;

MQTTClient client;
String lastMessageKeyboard="";
String lastMessageMouse="";

void setup() {
  size(500, 200);
  // create MQTT Client, connect to our server and subscribe to two channels
  client = new MQTTClient(this);
  client.connect("mqtt://mdduser:IoTMDD@37.97.203.138:1883", "MDDStudent");
  client.subscribe("/testchannel/keyboard");
  client.subscribe("/testchannel/mouse");
}

void keyPressed() {
  client.publish("/testchannel/keyboard", ""+key);
}

void draw() {
  background(255);
  fill(0);
  text("type keyboard to send messages",10,20);
  text("Last received message on channel /testchannel/keyboard: "+lastMessageKeyboard,10,40);
  text("Move and click mouse to send messages",10,100);
  text("Last received message on channel /testchannel/mouse: "+lastMessageMouse,10,120);
}

void mousePressed() {
 client.publish("/testchannel/mouse", "mousePressed "+mouseX+" "+mouseY);
}
void mouseMoved() {
 client.publish("/testchannel/mouse", "mouseMoved "+mouseX+" "+mouseY);
}
void mouseDragged() {
 client.publish("/testchannel/mouse", "mouseDragged "+mouseX+" "+mouseY);
}
void mouseReleased() {
 client.publish("/testchannel/mouse", "mouseReleased "+mouseX+" "+mouseY);
}

void messageReceived(String topic, byte[] payload) {
  String message = new String(payload);
  println("new message: " + topic + " - " + message);
  
  if (topic.equals("/testchannel/keyboard")) {
    lastMessageKeyboard = message;
  }
  
  if (topic.equals("/testchannel/mouse")) {
    lastMessageMouse = message;
  }
}

Arduino

Arduino Yun

This code uses an Arduino Yún and the MQTT library.

// This example uses an Arduino Yun or a Yun-Shield

#include <Bridge.h>
#include <BridgeSSLClient.h>
#include <MQTT.h>

#define broker "37.97.203.138"
#define port 1883
#define user "mdduser"
#define pass "IoTMDD"
#define userID "StudentOnArduino"

BridgeClient net;
MQTTClient client;

unsigned long lastMillis = 0;

void setup() {
  Bridge.begin();
  Serial.begin(115200);

  // MQTT brokers usually use port 8883 for secure connections.
  client.begin(broker, port, net);
  client.onMessage(messageReceived);

  connect();
}

void connect() {
  Serial.print("connecting as ");
  Serial.print(userID);
  Serial.print(" to ");
  Serial.println(broker);
  while (!client.connect(userID, user, pass)) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("\nconnected!");
  client.subscribe("/testarduino");
  // client.unsubscribe("/hello");
}

void messageReceived(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);
}

void loop() {
  client.loop();

  if (!client.connected()) {
    connect();
  }

  // publish a message roughly every second.
  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    Serial.println("Sending message to broker...");
    client.publish("/testarduino", "hello from Arduino");
  }

}

Arduino ESP32 / ESP8266

This code uses a board that has an ESP32 or ESP8266 chip (like the adafruit feather ESP32)


In order to find some specific boards you'll need to add the following recoures, via Ardiuno > Preferences > Additional Boards Manager URLs:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 
https://arduino.esp8266.com/stable/package_esp8266com_index.json

Add the boards via Tools > Board > Boards manager... Search for "esp32" by espressif and "esp8266" by ESP8266 community

Install the esp32 driver & MQTT client

Install the adafruit esp32 driver: https://learn.adafruit.com/adafruit-huzzah32-esp32-feather/using-with-arduino-ide

Install the MQTT client: https://github.com/knolleary/pubsubclient

// This example uses an Adafruit arduino feather
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif

#include <PubSubClient.h>

WiFiClient espClient;
PubSubClient client(espClient);

// Wifi
const char *ssid = "iotroam";
const char *password = "loislane";

// MQTT
const char *mqtt_server = "37.97.203.138";
const int mqtt_port = 1883;
const char *mqtt_user = "mdd";
const char *mqtt_password = "loislane";
const String mqtt_identifier = "battle-bot";

// Data
unsigned long lastMillis = 0;

void setup() {
  Serial.begin(9600);

  setup_wifi();
  
  // Connect to the MQTT client
  client.setServer(mqtt_server, mqtt_port);
  // Receive data from the MQTT
  client.setCallback(callback);
}

void loop() {
  if (!client.connected())
  {
      digitalWrite(LED_BUILTIN, LOW);
      reconnect();
  }
  
  client.loop();
    
  // Publish a message roughly every second.
  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    Serial.println("Sending message to broker...");
    client.publish("/testarduino/send", "hello from Arduino");
  }
}

void setup_wifi()
{
    Serial.print("Board MAC Address:  ");
    Serial.println(WiFi.macAddress());

    delay(10);
    Serial.println();
    Serial.print("Connecting to ");
    Serial.print(ssid);
    
    // We start by connecting to a WiFi network
    WiFi.begin(ssid, password);

    // Wait untill the WiFi status is WL_CONNECTED (active internet connection)
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.println("");
    Serial.println("");
}

void reconnect()
{
    // Loop until we're reconnected again
    while (!client.connected())
    {
        // Create a unique identifier for this arduino
        char identifier[50];
        String unique_name = mqtt_identifier + "-" + String(random(0xffff), HEX);
        String(unique_name).toCharArray(identifier, String(mqtt_identifier).length() + 1);
        
        Serial.print("Connecting to MQTT...");

        // Trying to make a connection
        if (client.connect(identifier, mqtt_user, mqtt_password))
        {
            Serial.println("");
            Serial.println("");
            Serial.println("MQTT Connected");
            Serial.print("Identifier: ");
            Serial.println(identifier);
            Serial.println("");
            Serial.println("");
            digitalWrite(LED_BUILTIN, HIGH);

            // Subscribe to a topic
            client.subscribe("/testarduino/receive");
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}

void callback(char *topic, byte *message, unsigned int length)
{
    Serial.print("Received message on topic: ");
    Serial.print(topic);
    Serial.print(". Message: ");
    String messageTemp;

    for (int i = 0; i < length; i++)
    {
        Serial.print((char)message[i]);
        messageTemp += (char)message[i];
    }
    
    Serial.println();
}

Other resources

  • Adafruit has a great step-by-step tutorial for getting started with IoT.
  • Shiftr also hosts an easy-to-learn platform for getting started with IoT.