Controllin Arduino MKR or ESP with Json via MQTT

Controllin Arduino MKR or ESP with Json via MQTT © MIT

We'll manage to control the basic behaviour of Arduino (or ESP based boards) using MQTT and the Arduino Json Library.

  • 149 views
  • 0 comments
  • 0 respects

Components and supplies

Apps and online services

About this project

This is the following chapter of the basic Arduino <> MQTT tutorial we released some ago using Node-RED. Feel free to follow that tutorial because we are just working adding json to the payload we are sending to the Arduino board and we parse it using the Arduino Json Llibrary from Arduino.

This sketch / example is part of the Fluid Networks Workshop. Feel free to open issue and comment in the official repository of the course (ongoing)

Prepare the IDE

Install the Library from the Library Manager

We are adding few things on the previous sketch: import the library:

#include <Arduino_JSON.h>

add in the messageReceived functions several methods the library has to recognize ad parse specific keys of the json. In this case we are sending for different values, that will eventually control a Neopixel Strip (not in this tutorial yet, slow down, Joe :))

Our Json looks like (we are assuming you know about Json. There are TONS of tutorials on how and why JSON exists, please check them and come back here):

{
"name": "LED",
"status": "open",
"pin": 1,
"color": "red"
}

and this is how the parsing happens (based on the object example provided in the library)

void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
JSONVar myObject = JSON.parse(payload);
//Serial.println(JSON.typeof(myObject));

if (myObject.hasOwnProperty("name")) {
Serial.print("myObject[\"name\"] = ");

Serial.println((const char*) myObject["name"]);
}

if (myObject.hasOwnProperty("status")) {
Serial.print("myObject[\"status\"] = ");

Serial.println((const char*) myObject["status"]);
// Serial.println(myObject["status"]);

}

if (myObject.hasOwnProperty("pin")) {
Serial.print("myObject[\"pin\"] = ");

Serial.println((int) myObject["pin"]);
}

if (myObject.hasOwnProperty("color")) {
Serial.print("myObject[\"color\"] = ");

Serial.println((const char*) myObject["color"]);
}

On our Node-RED server we copy and paste this Flow

[{"id":"61481346.cd22fc","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"6f92601a.e14a38","type":"mqtt in","z":"61481346.cd22fc","name":"","topic":"#","qos":"0","datatype":"auto","broker":"5d5dc8e5.3afd88","x":270,"y":160,"wires":[["5d00fe9e.368b68"]]},{"id":"5d00fe9e.368b68","type":"debug","z":"61481346.cd22fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":570,"y":200,"wires":[]},{"id":"ed186795.9e4d08","type":"mqtt out","z":"61481346.cd22fc","name":"","topic":"","qos":"","retain":"","broker":"5d5dc8e5.3afd88","x":620,"y":320,"wires":[]},{"id":"5cd777f2.bf108","type":"mosca in","z":"61481346.cd22fc","mqtt_port":1883,"mqtt_ws_port":8080,"name":"","username":"user","password":"password","dburl":"","x":150,"y":60,"wires":[[]]},{"id":"755c3e07.1a24e","type":"inject","z":"61481346.cd22fc","name":"complete json string (open)","topic":"/hello","payload":"{\"name\":\"LED\",\"status\":\"open\",\"pin\":2,\"color\":\"red\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":240,"wires":[["ed186795.9e4d08"]]},{"id":"7817d3f0.f577dc","type":"inject","z":"61481346.cd22fc","name":"complete json string (closed)","topic":"/hello","payload":"{\"name\":\"LED\",\"status\":\"closed\",\"pin\":0,\"color\":\"red\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":280,"wires":[["ed186795.9e4d08"]]},{"id":"f75bbc63.c339d","type":"inject","z":"61481346.cd22fc","name":"json for status open","topic":"/hello","payload":"{    \"status\": \"open\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":340,"wires":[["ed186795.9e4d08"]]},{"id":"e4d35e49.5b693","type":"inject","z":"61481346.cd22fc","name":"json for pin 0","topic":"/hello","payload":"{    \"pin\": 0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":380,"wires":[["ed186795.9e4d08"]]},{"id":"5d5dc8e5.3afd88","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

The conditions

If everything works fine you should be able to see the json being printed in your serial monitor, while we added several conditions for you to toy around the different possibilities you have in changing the onboard behaviour based on the strings sent in the payload, throughout specific keys of the Json. In order to do that we have to cast these keys based on the need we have (in this exmaple we are just covering integers and strings.

if (topic == "/hello") {
if (String((const char*)myObject["status"]) == "open") {

Serial.println("open");
digitalWrite(LED_BUILTIN, HIGH);

} else if (String((const char*)myObject["status"]) == "closed") {

Serial.println("closed");
digitalWrite(LED_BUILTIN, LOW);

}


if ((int) myObject["pin"] == 1) {

Serial.println("open");
digitalWrite(LED_BUILTIN, HIGH);

} else if ((int) myObject["pin"] == 0) {

Serial.println("closed");
digitalWrite(LED_BUILTIN, LOW);

}

}

Code

Minimal Json communication via MQTT and Node-REDArduino
/* This example shows how to use MQTT on the main dev boards on the market
  HOW TO USE:
  under connect method, add your subscribe channels.
  under messageReceived (callback method) add actions to be done when a msg is received.
  to publish, call client.publish(topic,msg)
  in loop take care of using non-blocking method or it will corrupt.
  Alberto Perro & DG - Officine Innesto 2019

  Updated to be the minimal parsing example to to control
  the Arduino behaviour throughout a json string sent to topic #hello

  The payload can be either

  {
    "name": "LED",
    "status": "open",
    "pin": 1,
    "color": "red"
  }

  or

  {
    "name": "LED",
    "status": "closed",
    "pin": 0,
    "color": "red"
  }


*/
#define BROKER_IP    "192.168.1.0"
#define DEV_NAME     "mqttdevice"
#define MQTT_USER    "user"
#define MQTT_PW      "password"
const char ssid[] = "wifi_ssid";
const char pass[] = "wifi_password";
#include <MQTT.h>
#ifdef ARDUINO_SAMD_MKRWIFI1010
#include <WiFiNINA.h>
#elif ARDUINO_SAMD_MKR1000
#include <WiFi101.h>
#elif ESP8266
#include <ESP8266WiFi.h>
#else
#error unknown board
#endif
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;

#include <Arduino_JSON.h>

void connect() {
  Serial.print("checking wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.print("\nconnecting...");
  while (!client.connect(DEV_NAME, MQTT_USER, MQTT_PW)) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("\nconnected!");
  client.subscribe("/hello"); //SUBSCRIBE TO TOPIC /hello
}

void messageReceived(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);
  JSONVar myObject = JSON.parse(payload);
  //Serial.println(JSON.typeof(myObject));

  if (myObject.hasOwnProperty("name")) {
    Serial.print("myObject[\"name\"] = ");

    Serial.println((const char*) myObject["name"]);
  }

  if (myObject.hasOwnProperty("status")) {
    Serial.print("myObject[\"status\"] = ");

    Serial.println((const char*) myObject["status"]);
    //   Serial.println(myObject["status"]);

  }

  if (myObject.hasOwnProperty("pin")) {
    Serial.print("myObject[\"pin\"] = ");

    Serial.println((int) myObject["pin"]);
  }

  if (myObject.hasOwnProperty("color")) {
    Serial.print("myObject[\"color\"] = ");

    Serial.println((const char*) myObject["color"]);
  }

  if (topic == "/hello") {
    if (String((const char*)myObject["status"]) == "open") {
      
      Serial.println("open");
      digitalWrite(LED_BUILTIN, HIGH);
      
    } else if (String((const char*)myObject["status"]) == "closed") {

      Serial.println("closed");
      digitalWrite(LED_BUILTIN, LOW);
 
    }


    if ((int) myObject["pin"] == 1) {

      Serial.println("open");
      digitalWrite(LED_BUILTIN, HIGH);

    } else if ((int) myObject["pin"] == 0) {
 
      Serial.println("closed");
      digitalWrite(LED_BUILTIN, LOW);

    }

  }
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, pass);
  pinMode(LED_BUILTIN, OUTPUT);

  // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
  // You need to set the IP address directly.
  //
  // MQTT brokers usually use port 8883 for secure connections.
  client.begin(BROKER_IP, 1883, net);
  client.onMessage(messageReceived);
  connect();
}
void loop() {
  client.loop();
  if (!client.connected()) {
    connect();
  }
  // publish a message roughly every second.
  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    //  client.publish("/hello", "world"); //PUBLISH TO TOPIC /hello MSG world
  }
}
Minimal Json communication via MQTT and Node-RED

Comments

Add projectSign up / Login