Mqtt Connection - Loop working without connection

Hey all, Thanks to this forum I've been able to get this code working.

I'm sure this is an easy thing to do but what would be the correct wait to tell the Arduino to move past connecting the Mqtt broker if it can't after 30 second and make the code in the loop work after?

Thanks!

Here is the code I'm working with.

/*
  Arduino MQTT Prototype
*/
#include <ezButton.h>
#include <ArduinoMqttClient.h>
#include <WiFiNINA.h> // for MKR1000 change to: #include <WiFi101.h>
//#include <WiFi101.h>
#include <Ethernet.h>
#include <SPI.h>
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate
//    flashed in the WiFi module.

String msg1 ;
const char broker[] = "192.168.1.123"; // Address of the MQTT server
int        port     = 1883;
const char topic[]  = "mqtt/main";
const char subtopic[]  = "mqtt/one";

const long interval = 1000;
unsigned long previousMillis = 0;
int Enet = 0; //0 = Ethernet connection is not available

int status = false;
int led = 1;
int led2 = 2;

WiFiClient wifiClient;
EthernetClient ethernetClient;
MqttClient *mqttClient;


ezButton button(A1);  // create ezButton object that attach to pin A1;

String subMessage = "";

void setup() {
  //Initialize serial
  Serial.begin(9600);
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  digitalWrite(led2, LOW);
  
  if (Ethernet.linkStatus() == LinkON) {
  Serial.print("Ethernet cable is connected.");
  Enet == 1; }
  else { Serial.print("Ethernet cable is not connected.");
  Enet == 0; }
  // attempt to connect to Wifi network:
  if (Enet == 0) {
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
 }
  Serial.println("You're connected to the network");
  Serial.println();
  //If Ethernet is not availabe
  if (Enet == 1) {
  mqttClient = new MqttClient(ethernetClient);
} else {
  mqttClient = new MqttClient(wifiClient);
}
  // You can provide a unique client ID, if not set the library uses Arduino-millis()
  // Each client must have a unique client ID
   mqttClient->setId("one");

  // You can provide a username and password for authentication
  // mqttClient.setUsernamePassword("user", "password");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  while (!mqttClient->connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient->connectError());
  }

  Serial.println("You're connected to the MQTT broker!");
  Serial.println();
    // set the message receive callback

  mqttClient->onMessage(onMqttMessage);

  // subscribe to a topic
 mqttClient->subscribe(subtopic);

}

void loop() {
  button.loop(); // MUST call the loop() function first
// call poll() regularly to allow the library to send MQTT keep alives which
  // avoids being disconnected by the broker
  mqttClient->poll();
  mqttClient->loop();
  if(button.isPressed()) {
    Serial.println("The button is pressed");

    // toggle state of LED
    status = !status;

    // control LED arccoding to the toggleed sate
    digitalWrite(led, status); 
  
    if (status==true){
    ON();
    }
    if (status==false){
    OFF();
    }
    }
    
  
}

void onMqttMessage(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.println("Received a message with topic '");
  Serial.print(mqttClient->messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient->available()) {
    msg1 +=(char)mqttClient->read();
    Serial.println(msg1);
  }
  if (msg1 == "ON"){
  digitalWrite(led, true);
  }
  if (msg1 == "OFF"){
  digitalWrite(led, false);
  }
  msg1="";
}
void ON(){
    mqttClient->beginMessage(topic);
    mqttClient->print("on1");
    mqttClient->endMessage();
    Serial.println("Sent MQTT message.");
}
void OFF(){
    mqttClient->beginMessage(topic);
    mqttClient->print("off1");
    mqttClient->endMessage();
    Serial.println("Sent MQTT message."); 
}

consider

const byte PinBut = A1;

void
loop (void)
{
    Serial.println ("timer started, press button to interrupt");
#define TimeOut  10000
    bool timeout = true;
    unsigned long msecLst = millis ();
    while (millis() - msecLst < TimeOut)  {
        if (LOW == digitalRead (PinBut))  {
            timeout = false;
            break;
        }
    }

    Serial.println (timeout);
    delay (2000);
}

void
setup (void)
{
    Serial.begin (9600);
    pinMode (PinBut, INPUT_PULLUP);
}

Adding that code doesn't help with my issue.

Why? Help us understand what you want

I could be wrong, I by no means am great at this. But when the Arduino is trying to connect to the Mqtt broker it won’t allow the loop to start which doesn’t allow the push button to activate the relay.

So when I add this code it doesn’t change that, maybe I did it wrong? Would you be willing to add it in my code where you would recommend?

this doesn't sound like you want a 30 second timeout, that you want to be able to recognize a button pressed while waiting to connect to the Mqtt broker.

so which is it?

could have shown how you added the code to your code

Either or,
There are times that the MQTT broker is not online and I need to turn the relay on.

So I don’t know what the best way to do it. That’s why I’m asking for help.

I’ll have to redo the code last if you would like me to post what I did. I tried it and made multi adjustments then had to go back to the working code. I didn’t save a copy of what didn’t work.

looks like you want to support several different interfaces: ethernet, WiFi-Mqtt, buttons.

i would have sub-function (even files) for each interface .. clearly separate each, as well as a sub-function to deal with the relay that can be used from any interface. hopefully you see that each sub-function serves a single purpose ("coherence") and minimizes coupling.

loop() would call the sub-functions for each input interface.

the Mqtt interfaces can be state driven where the initial state checks that the interface is up/connected, whether it uses ethernet or WiFi (can switch back and forth)

do you see what i'm suggesting?

Ok, ya I think that makes sense, I get the reasoning for it.
I don’t think I know how to even start doing that but I’ll try and see what happens, I guess.

looks thru this code that i simulated on a laptop, in particular mqttService

skip the stuff up on top used to simulate the various library functions

#include <stdio.h>
#include <stdlib.h>

// -------------------------------------
// Arduino environment
typedef unsigned char byte;

enum { INPUT, INPUT_PULLUP, OUTPUT };
void pinMode (byte pin, int mode) { }

enum { LOW, HIGH };
void digitalWrite (byte pin, int state) {
    printf (" %s: %d %d\n", __func__, pin, state);
}

int  digitalRead (byte pin) {
    printf (" %s: %d\n", __func__, pin);
    return 0;
}

void delay (unsigned long n) { }

// -----------------------------------------------------------------------------
#define MyHW
#ifdef MyHW

enum {
    FL_ETH   = 1,
    FL_WIFI  = 2,
    FL_MQ    = 4,
};

int flag;

// -------------------------------------
enum { LinkON = 1};
struct  {
    int linkStatus (void)  { return flag & FL_ETH ? LinkON : 0; }
} Ethernet;

struct EthernetClient {
    EthernetClient (void)  { }
    int linkStatus (void)  { return LinkON; }
};

// -------------------------------------
enum { A1 };
struct ezButton {
    byte _pin;
    byte _pressed;

    ezButton (int pin)  {
        _pin = pin;
        pinMode (_pin, INPUT_PULLUP);
    }

    int  isPressed (void)          {
        if (_pressed)  {
            _pressed = 0;
            return 1;
        }
        return 0;
    }
    void loop (void)               {
    }
    void poll (void)               { }
    void setDebounceTime (int ms)  { }
};

// -------------------------------------
struct {
    void begin (int bps)  { }
    void print (const char *s) { printf (s); };
    void print (int i)         { printf ("%d", i); };

    void println (void)          { printf ("\n"); };
    void println (const char *s) { printf ("%s\n", s); };
    void println (int i)         { printf ("%d\n", i); };
} Serial;

// -------------------------------------
enum { WL_CONNECTED = 1 };
struct {
    int begin (char *s, char *p) { return 0; }
    int status (void) { return flag & FL_WIFI ?  WL_CONNECTED : 0; }
} WiFi;

struct WiFiClient {
    WiFiClient (void)   { }
    int begin (char *s, char *p) { return WL_CONNECTED; }
};

// -------------------------------------
struct MqttClient {
    MqttClient (EthernetClient e)  { }
    MqttClient (WiFiClient w)      { }

    int available (void)                     { return 0; }
    int beginMessage (const char *topic)     { return 0; }
    int connect (const char *brkr, int port) { return flag & FL_MQ; }
    int connectError (void)                  { return 0; }
    int endMessage (void)                    { return 0; }
    int messageTopic (void)                  { return 0; }
    int subscribe (const char *s)            { return 0; }
    int onMessage (void (*f) (int))          { return 0; }
    void poll (void)                         { }
    void loop (void)                         { }
    void print (const char *s)     { printf (" %s: %s\n", __func__, s); }
    char *read (void)                        { return (char*)""; }
    void setId (const char *s)               { }
};

// ---------------------------------------------------------
#else
# include <ezButton.h>
# include <ArduinoMqttClient.h>
# include <WiFiNINA.h> // for MKR1000 change to: #include <WiFi101.h>
//# include <WiFi101.h>
# include <Ethernet.h>
# include <SPI.h>
# include "arduino_secrets.h"
#endif

// -----------------------------------------------------------------------------
char ssid[] = "mySSID";
char pass[] = "myPassword";

const char broker[]   = "192.168.1.123"; // Address of the MQTT server
int        port       = 1883;
const char topic[]    = "mqtt/main";
const char subtopic[] = "mqtt/one";

const long interval = 1000;
unsigned long previousMillis = 0;
int Enet = 0; //0 = Ethernet connection is not available
int status = false;
int led = 1;
int led2 = 2;
WiFiClient wifiClient;
EthernetClient ethernetClient;
MqttClient *mqttClient;
ezButton button (A1);  // create ezButton object that attach to pin A1;

// -----------------------------------------------------------------------------
void onMqttMessage (int messageSize) {
    // we received a message, print out the topic and contents
    Serial.println ("Received a message with topic '");
    Serial.print (mqttClient->messageTopic ());
    Serial.print ("', length ");
    Serial.print (messageSize);
    Serial.println (" bytes:");
    // use the Stream interface to print the contents
    char *msg1;
    while (mqttClient->available ()) {
        msg1 = mqttClient->read ();
        Serial.println (msg1);
    }
    if (msg1 == "ON"){
        digitalWrite (led, true);
    }
    if (msg1 == "OFF"){
        digitalWrite (led, false);
    }
}

void ON (){
    mqttClient->beginMessage (topic);
    mqttClient->print ("on1");
    mqttClient->endMessage ();
    Serial.println ("Sent MQTT message.");
}

void OFF (){
    mqttClient->beginMessage (topic);
    mqttClient->print ("off1");
    mqttClient->endMessage ();
    Serial.println ("Sent MQTT message.");
}

// -----------------------------------------------------------------------------
enum { MQ_NUL, MQ_WIFI, MQ_CON, MQ_UP };
int mqState = MQ_NUL;

const char *mqStateStr [] = {
    "MQ_NUL",
    "MQ_WIFI",
    "MQ_CON",
    "MQ_UP",
    
};

void
mqttService (void)
{
    printf ("%s: %d %s\n", __func__, mqState, mqStateStr [mqState]);

    switch (mqState) {
    case MQ_NUL:
        if (Ethernet.linkStatus () == LinkON)  {
            mqttClient = new MqttClient(ethernetClient);
            mqttClient->setId ("one");
            mqState    = MQ_CON;
            mqttService ();
        }
        else
            printf (" %s: no ethernet\n");
            WiFi.begin (ssid, pass);
            mqState = MQ_WIFI;
            mqttService ();
        break;

    case MQ_WIFI:
        if (WL_CONNECTED == WiFi.status ())  {
            mqttClient = new MqttClient (wifiClient);
            mqttClient->setId ("one");
            mqState    = MQ_CON;
            mqttService ();
        }
        break;

    case MQ_CON:
        if (! mqttClient->connect (broker, port)) {
            Serial.print ("MQTT connection failed! Error code = ");
            Serial.println (mqttClient->connectError ());
        }
        else  {
            mqttClient->onMessage (onMqttMessage);
            mqttClient->subscribe (subtopic);
            mqState    = MQ_UP;
            mqttService ();
        }
        break;

    case MQ_UP:
        mqttClient->poll ();
        mqttClient->loop ();
        break;
    }
}

// -----------------------------------------------------------------------------
void
buttonService (void)
{
    button.loop (); // MUST call the loop () function first
    if (button.isPressed ()) {
        Serial.println ("The button is pressed");

        // toggle state of LED
        status = !status;
        // control LED arccoding to the toggleed sate
        digitalWrite (led, status);
        if (status==true){
            ON ();
        }
        if (status==false){
            OFF ();
        }
    }
}

// -----------------------------------------------------------------------------
void loop ()
{
    // simulated event thru keyboard
    printf ("> ");
    switch (getchar ())  {
    case 'b':
        break;

    case 'E':
        flag |= FL_ETH;
        break;

    case 'M':
        flag |= FL_MQ;
        break;

    case 'W':
        flag |= FL_WIFI;
        break;

    case 'q':
        printf (" exit\n");
        exit (0);
        break;

    default:
        break;
    }

    buttonService ();
    mqttService ();
}

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

    button.setDebounceTime (50);

    pinMode (led,  OUTPUT);
    pinMode (led2, OUTPUT);
    digitalWrite (led2, LOW);
}

// -----------------------------------------------------------------------------
int main ()
{
    setup ();
    while (1)
        loop ();
    return 0;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.