0

Endless loop on reconnecting to IO
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Endless loop on reconnecting to IO

by scottlinenberger on Tue Aug 20, 2019 3:25 pm

TLDR; How do you reset and re-connect to Adafruit IO when the WiFi connection gets interrupted?

Issue:
Is there a recommended way to re-connect to Adafruit IO without resetting the board if the connection fails?

Whenever WiFi signal is weak or temporarily drops off, logic gets stuck in an infinite loop while attempting to reconnect to Adafruit IO using the same logic that successfully connects to Adafruit IO on device start up. For example, if I connect my board to Adafruit IO via WiFi, then restart my router, the board gets stuck in an infinite loop blocking the rest of my logic requiring me to reset the board to re-establish a WiFi connection.

I've had the same re-connect infinite loop issue with the ESP32 and Huzzah feathers.

Homework:
I've been searching through the Adafruit IO source on Github and the forums looking for advice on reconnecting, but haven't managed to come up with anything. I've also looked through the Adafruit IO source, examples and documentation but haven't found much in terms of recommended code for checking and maintaining the IO connection AFTER connecting to Adafruit IO.

Skills:
I'm a developer, but particularly strong in C++. My background is more in Java/Javascript and OOP.

Code:
Code: Select all | TOGGLE FULL SIZE
#include "Config.h"
#include "./Button.h"
#include "AdafruitIO_WiFi.h"

/* init Adafruit IO */
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);

/* Adafruit IO feeds */
AdafruitIO_Feed *feed = io.feed(FEED_CONTROL_BOX);

/* button state change flag */
boolean hasStateChanged = true;

/* relay state - defaults to OFF */
boolean stateRelay1 = true;
boolean stateRelay2 = true;
boolean stateRelay3 = true;
boolean stateRelay4 = true;

/* button setup */
Button button1 = Button(
  PIN_BUTTON_1,
  TIMEOUT_BUTTON_DEBOUNCE,
  TIMEOUT_BUTTON_PRESS,
  BUTTON_TRIGGERED_STATE
);

Button button2 = Button(
  PIN_BUTTON_2,
  TIMEOUT_BUTTON_DEBOUNCE,
  TIMEOUT_BUTTON_PRESS,
  BUTTON_TRIGGERED_STATE
);

Button button3 = Button(
  PIN_BUTTON_3,
  TIMEOUT_BUTTON_DEBOUNCE,
  TIMEOUT_BUTTON_PRESS,
  BUTTON_TRIGGERED_STATE
);

Button button4 = Button(
  PIN_BUTTON_4,
  TIMEOUT_BUTTON_DEBOUNCE,
  TIMEOUT_BUTTON_PRESS,
  BUTTON_TRIGGERED_STATE
);

void setup() {
  /* start serial for debugging */
  Serial.begin(9600);

  /* init pins */
  initPins();

  /* init state */
  writeState();

  /* connect to Adafruit IO */
  connectToIO();
}

void loop() {
  handleButtonPresses();

  /* keep our Adafruit IO connection up */
  if (io.status() < AIO_CONNECTED) {
    connectToIO();
  }

  if (hasStateChanged == true) {
    writeState();
  }

  io.run();
}

void initPins() {
  /* led pins */

  /* button pins */
  pinMode(PIN_BUTTON_1, INPUT);
  pinMode(PIN_BUTTON_2, INPUT);
  pinMode(PIN_BUTTON_3, INPUT);
  pinMode(PIN_BUTTON_4, INPUT);

  /* relay pins */
  pinMode(PIN_RELAY_1, OUTPUT);
  pinMode(PIN_RELAY_2, OUTPUT);
  pinMode(PIN_RELAY_3, OUTPUT);
  pinMode(PIN_RELAY_4, OUTPUT);

  /* LED pins */
  pinMode(PIN_LED_1, OUTPUT);
  pinMode(PIN_LED_2, OUTPUT);
  pinMode(PIN_LED_3, OUTPUT);
  pinMode(PIN_LED_4, OUTPUT);
  pinMode(PIN_ONBOARD_LED, OUTPUT);
}

void connectToIO() {
  Serial.println("Connecting to Adafruit IO...");
  io.connect();

  /* handle incoming messages */
  feed->onMessage(handleIncomingMessage);

  /* set a flag for toggling the LED */
  boolean isOn = true;

  /* wait for the connection */
  while (io.status() < AIO_CONNECTED) {
    Serial.print(".");
    isOn = !isOn;
    digitalWrite(PIN_ONBOARD_LED, isOn);
    delay(500);
  }

  /* connected! */
  Serial.println();
  Serial.println(io.statusText());

  /* keep the blue LED on */
  digitalWrite(PIN_ONBOARD_LED, HIGH);
}

void handleIncomingMessage(AdafruitIO_Data *data) {
  /* parse the response to an integer */
  String value = String(data->value());
  int intValue = value.toInt();

  Serial.print("Incoming Adafruit IO data! --> ");
  Serial.println(intValue);

  switch(intValue) {
    /* all channels off */
    case 0:
      stateRelay1 = STATE_RELAY_OFF;
      stateRelay2 = STATE_RELAY_OFF;
      stateRelay3 = STATE_RELAY_OFF;
      stateRelay4 = STATE_RELAY_OFF;

      hasStateChanged = true;
      break;

    case 1:
      stateRelay1 = !stateRelay1;
      hasStateChanged = true;
      break;

    case 2:
      stateRelay2 = !stateRelay2;
      hasStateChanged = true;
      break;

    case 3:
      stateRelay3 = !stateRelay3;
      hasStateChanged = true;
      break;

    case 4:
      stateRelay4 = !stateRelay4;
      hasStateChanged = true;
      break;

    /* all channels on */
    case 5:
      stateRelay1 = !STATE_RELAY_OFF;
      stateRelay2 = !STATE_RELAY_OFF;
      stateRelay3 = !STATE_RELAY_OFF;
      stateRelay4 = !STATE_RELAY_OFF;

      hasStateChanged = true;
      break;

    default:
      break;
  }
}

void writeState() {
  digitalWrite(PIN_RELAY_1, stateRelay1);
  digitalWrite(PIN_LED_1, !stateRelay1);

  digitalWrite(PIN_RELAY_2, stateRelay2);
  digitalWrite(PIN_LED_2, !stateRelay2);

  digitalWrite(PIN_RELAY_3, stateRelay3);
  digitalWrite(PIN_LED_3, !stateRelay3);

  digitalWrite(PIN_RELAY_4, stateRelay4);
  digitalWrite(PIN_LED_4, !stateRelay4);

  hasStateChanged = false;
}

void handleButtonPresses() {
  /* if button is pressed */ 
  if (button1.isPressed() == true) {
    Serial.println("Button 1 Pressed!");
    /* flag the change */
    hasStateChanged = true;
    /* toggle corresponding relay state */
    stateRelay1 = !stateRelay1;
  }

  /* repeat */
  if (button2.isPressed() == true) {
    Serial.println("Button 2 Pressed!");
    hasStateChanged = true;
    stateRelay2 = !stateRelay2;
  }

  if (button3.isPressed() == true) {
    Serial.println("Button 3 Pressed!");
    hasStateChanged = true;
    stateRelay3 = !stateRelay3;
  }

  if (button4.isPressed() == true) {
    Serial.println("Button 4 Pressed!");
    hasStateChanged = true;
    stateRelay4 = !stateRelay4;
  }
}
Attachments
controller-compressed.jpeg
controller-compressed.jpeg (140.35 KiB) Viewed 104 times

scottlinenberger
 
Posts: 2
Joined: Sun Mar 06, 2016 9:05 pm

Re: Endless loop on reconnecting to IO

by brubell on Wed Aug 21, 2019 5:16 pm

Do you know where your code gets stuck after your router gets reset?

What is the call to connectToIO(); doing? Could you paste that function below?

brubell
 
Posts: 496
Joined: Fri Jul 17, 2015 10:33 pm

Re: Endless loop on reconnecting to IO

by scottlinenberger on Wed Aug 21, 2019 5:20 pm

The full source is posted. You may need to scroll a bit. The code gets stuck in the function you referenced. Works on the first connection, won't work after that if WiFi gets interrupted.

scottlinenberger
 
Posts: 2
Joined: Sun Mar 06, 2016 9:05 pm

Re: Endless loop on reconnecting to IO

by brubell on Thu Aug 22, 2019 10:07 am

While Adafruit IO Arduino doesn't currently handle network reconnections (it'd be difficult for multiple boards, each module is different), I'll try to assist.

The ESP32's initial connection (along with constructors for WiFiClient, mqtt client and http client) is handled within wifi/AdafruitIO_ESP32:
https://github.com/adafruit/Adafruit_IO ... 32.cpp#L33

You may want to start by adding a function to query the WiFi module's status (https://github.com/adafruit/Adafruit_IO ... 32.cpp#L43) and attempt to reconnect the WiFi module (WiFi.begin()) if the module returns WL_CONNECT_FAILED.

brubell
 
Posts: 496
Joined: Fri Jul 17, 2015 10:33 pm

Please be positive and constructive with your questions and comments.