MQTT (JSON) Client - Arduino I/O to Domoticz MQTT gateway (Mosquitto)

In this subforum you can show projects you have made, or you are busy with. Please create your own topic.

Moderator: leecollings

Post Reply
mjchrist
Posts: 2
Joined: Monday 12 November 2018 12:05
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

MQTT (JSON) Client - Arduino I/O to Domoticz MQTT gateway (Mosquitto)

Post by mjchrist »

In response to the Domoticz WIKI "MQTT - Arduino, Needed! Please Help." I'm using the sketch below.
It's a project that is still growing, but I hope it helps users along the way.

The advantage of the sketch below is that you only need Mosquitto as a broker and that NodeRED does not have to be installed.

The project uses the ArduinoJson library. On the ArduinoJson site you can find more information about the library and how to use it.

Code: Select all

/**
 * Arduino MEGA 2560 with Ethernet shield
 * MQTT MEGA I/O for Domoticz (JSON)
 * Created by M.J. Christ
 */

#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>
#include <Bounce2.h>

#include "arduino_secrets.h" // Header file containing settings for sketch

// Network settings
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // This must be unique
EthernetClient ethernetClient;
MqttClient mqttClient(ethernetClient);

char broker_user[] = BROKER_USER;
char broker_pass[] = BROKER_PASS;

// MQTT settings
const char broker[]   = "192.168.10.30";
int port = 1883;
const char inTopic[]  = "domoticz/in";  // Default incoming topic in Domoticz is domoticz/in
const char outTopic[] = "domoticz/out"; // Default outgoing topic in Domoticz is domoticz/in
char myOutput[512];

// Interval settings
unsigned long previousMillis = 0;     // Store last time
const long interval          = 60000; // interval (milliseconds)

// Input settings
#define numberInputs 2
const int idx_inputArray[numberInputs] = {18, 19};
const int inputArray[8]                = {22, 23, 24, 25, 26, 27, 28, 29}; // GPIO input pins
const int invertArray[8]               = {0,  1,  0,  0,  0,  0,  0,  0 }; // Invert input pins

#define inputOn 0  // GPIO value input on
#define inputOff 1 // GPIO value input off

// Debouncer settings
Bounce debouncer[numberInputs];
bool lastCycle[numberInputs]; // = {false};
unsigned long debounceDelay = 50; // Debounce time (milliseconds)

// Output settings
#define numberOutputs 4
const char switchType[] = "On/Off";
const int idx_outputArray[numberOutputs] = {18, 19, 20, 21};
const int outputArray[8]                 = {30, 31, 32, 33, 34, 35, 36, 37}; // GPIO output pins
#define outputOn 0  // GPIO value output on
#define outputOff 1 // GPIO value output off


void setup() {
  // Initialize serial for debug
  Serial.begin(9600);
  
  // Set input pins
  for (int pin = 0; pin < numberInputs; pin++) {
    pinMode(inputArray[pin], INPUT_PULLUP);
    debouncer[pin] = Bounce();
    debouncer[pin].attach(inputArray[pin]);
    debouncer[pin].interval(debounceDelay);
    lastCycle[pin] = debouncer[pin].read() ? inputOn : inputOff; 
  }
    
  // Set output pins
  for (int pin = 0; pin < numberOutputs; pin++) {
    pinMode(outputArray[pin], OUTPUT);
    digitalWrite(outputArray[pin], outputOff);
  }
      
  // Set MQTT client
  mqttClient.setUsernamePassword(broker_user, broker_pass);
  mqttClient.onMessage(onMqttMessage);
  mqttClient.subscribe(outTopic); 
}


void loop(){
  // If not connected to the broker, try to connect
  while (!mqttClient.connected()) {
    startBroker();
  }

  // Interval request all output states
  unsigned long currentMillis = millis();
  bool requestStates = false;
  DynamicJsonDocument doc(256);
  if (currentMillis - previousMillis >= interval) {
    // Save the last time
    previousMillis = currentMillis;
    requestStates = true;
    Serial.println("Request all states");
      for (int pin = 0; pin < numberOutputs; pin++) {
      // Serialize the message
      doc.clear();
      doc["command"] = "getdeviceinfo";
      doc["idx"] = idx_outputArray[pin];
      // Send the message
      mqttClient.beginMessage(inTopic);
      serializeJson(doc, mqttClient);
      mqttClient.endMessage();
      // show serialization message
      serializeJsonPretty(doc, myOutput);
      Serial.println(myOutput);
    }
  }
    
  // (Interval) request all input states
  bool thisCycle[numberInputs];
  for (int pin = 0; pin < numberInputs; pin++) {
    debouncer[pin].update() ;
    thisCycle[pin] = debouncer[pin].read() ? inputOn : inputOff;
    if (((requestStates) && (thisCycle[pin] != lastCycle[pin]))|| (thisCycle[pin] != lastCycle[pin])) {
      lastCycle[pin] = thisCycle[pin];
      // Invert input
      if (invertArray[pin]) {
        thisCycle[pin] = !thisCycle[pin];
      }
      // Serialize the message (input state)
      doc.clear();
      doc["command"] = "switchlight";
      doc["idx"] = idx_inputArray[pin];
      if (thisCycle[pin]) {
        doc["switchcmd"] = "On";
      } else {
        doc["switchcmd"] = "Off";
      }
      // Send the message   
      mqttClient.beginMessage(inTopic);
      serializeJson(doc, mqttClient);
      mqttClient.endMessage();
      // show serialization message
      serializeJsonPretty(doc, myOutput);
      Serial.println(myOutput);
      // Serialize the message (output state) 
      doc.clear();
      doc["command"] = "getdeviceinfo";
      doc["idx"] = idx_inputArray[pin];
      // Send the message        
      mqttClient.beginMessage(inTopic);
      serializeJson(doc, mqttClient);
      mqttClient.endMessage();
      // show serialization message
      serializeJsonPretty(doc, myOutput);
      Serial.println(myOutput);
    }
  }
  mqttClient.poll();
}


void onMqttMessage(int messageSize) {
  // we received a message
  Serial.print("Received a message with topic: '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length: ");
  Serial.print(messageSize);
  Serial.println(" bytes:");
  // deserialize the message
  DynamicJsonDocument doc(messageSize);
  DeserializationError err = deserializeJson(doc, mqttClient);
  if (err) {
    Serial.print("deserializeJson() failed with code: ");
    Serial.println(err.f_str());
  } else {
    // show deserialization message
    serializeJsonPretty(doc, myOutput);
    Serial.println(myOutput);
    // change output state
    for (int pin = 0; pin < numberOutputs; pin++) {
      if ((idx_outputArray[pin] == doc["idx"]) and (doc["switchType"] == switchType)) {
        Serial.print("Incoming change for: ");
        Serial.print((char*)doc["name"]);
        Serial.print(" (idx: ");
        Serial.print((int)doc["idx"]);
        Serial.print("), new status: ");
        Serial.println((int)doc["nvalue"]);
        digitalWrite(outputArray[pin], doc["nvalue"] ? outputOn : outputOff);
        break;
      }
    }
  }
}


void startEthernet() {
  // Initialize network
  ethernetClient.stop();
  Serial.println("Attempting to connect to network: ");
  while (Ethernet.begin(mac) == 0) {
    Serial.print(".");
    delay(5000); // Wait 5 seconds, and try again
  }
  Serial.println("Connected to network");
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());
}

void startBroker () {
  // Initialize broker
  mqttClient.stop();
  Serial.println("Attempting to connect to broker");
  unsigned int mqttConnection = 0;
  while (!mqttClient.connect(broker, port)) {
    Serial.print(".");
    delay(5000); // Wait 5 seconds, and try again
    mqttConnection +=1;
    if (mqttConnection >= 5) {
      Serial.print("MQTT connection failed! Error code = ");
      Serial.println(mqttClient.connectError());
      startEthernet();
      return false;
    }    
  }
  Serial.println("Connected to broker");
  mqttClient.subscribe(outTopic);
  return true;
}
Last edited by mjchrist on Wednesday 02 March 2022 19:51, edited 3 times in total.
User avatar
waltervl
Posts: 5792
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: MQTT (JSON) Client - Arduino I/O to Domoticz MQTT gateway (Mosquitto)

Post by waltervl »

Thank you. I have added this topic to the Wiki https://www.domoticz.com/wiki/MQTT#Arduino
Also added some additional examples.
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest