WiFiManager and fauxmoESP Help for NOOB

New to the forum and can use some help with my home brew project for a garage door with sensor.

My code using FauxmoESP works (Alexa discover devices, turns on / off, etc.). I would like to include wifi provisioning to eliminate the hard coding of an SSSID, and password with the use of the WifiManager. I can make them work independently of each other, but not together in my implementation. If I include the WifiManager, then my devices are no longer discoverable by Alexa.

I must be missing something, and could use some help. Thanks in advance.

Board: NodeMCU 1.0 (ESP-12E Module)
IwIP Variant: v1.4 Higher Bandwidth
FauxmoESP: 3.1.0
WifiManager: 0.14.0

#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager
#include "fauxmoESP.h"

String wifiSSID;
String wifiPassword;

fauxmoESP fauxmo;
#define SERIAL_BAUDRATE     115200

typedef struct _device {
    String        sName;
    uint8_t       relayPin;
    uint8_t       relayMode;
    unsigned long relayMillis;
    uint8_t       sensorPin;
    uint8_t       sensorMode;
} Device;

#define NUM_DEVICES   2
Device devices[NUM_DEVICES] = { {.sName = "Denice's Garage Door",  .relayPin = D5, .relayMode = OUTPUT, .relayMillis = millis(), .sensorPin = D1, .sensorMode = INPUT_PULLUP},
                                {.sName = "Kitchen Garage Door", .relayPin = D6, .relayMode = OUTPUT, .relayMillis = millis(), .sensorPin = D2, .sensorMode = INPUT_PULLUP}
                              };

/*  D1  5   GPI05   INPUT_PULLUP
 *  D2  4   GPI04   INPUT_PULLUP
 *  D5  14  GPI014  OUTPUT
 *  D6  12  GPI12   OUTPUT
 *  
 *  LOW ON OUTPUT PIN CONTINUITY ACROSS NORMALLY CLOSED AND COMMON
 *  HIGH ON OUTPUT PIN CONTINUITY ACROSS NORMALLY OPEN AND COMMON
 */

const char* getPinNumber (uint8_t pin) {
    switch (pin) {
        case 4:
            return("D2");
        case 5:
            return("D1");
        case 14:
            return("D5");
        case 12:
            return("D6");
        default:
            return("ERROR");
    }
}
const char* getPinMode (uint8_t pin) {
    switch (pin) {
        case INPUT:
            return("INPUT");
        case INPUT_PULLUP:
            return("INPUT_PULLUP");
        case OUTPUT:
            return("OUTPUT");
        default:
            return("ERROR");
    }
}

void dumpDevices () {
    for (int cCnt = 0; cCnt < (sizeof devices / sizeof devices[0]); cCnt++) {
        Serial.printf("[dumpDevices]   .sName[%s], .relayPin[%s], .relayMode[%s], .relayState[%s], .relayMillis[%lu], .sensorPin[%s%], .sensorMode[%s], .sensorState[%s]\n",
            devices[cCnt].sName.c_str(),
            getPinNumber(devices[cCnt].relayPin),
            getPinMode(devices[cCnt].relayMode),
            digitalRead(devices[cCnt].relayPin) ? "HIGH" : "LOW",
            devices[cCnt].relayMillis,
            getPinNumber(devices[cCnt].sensorPin),
            getPinMode(devices[cCnt].sensorMode),
            digitalRead(devices[cCnt].sensorPin) ? "HIGH" : "LOW");
    }
}

void onSetStateDevices(const char * device_name, bool state) {
    // Alexa ON = OPEN = LOW
    // Alexa OFF = CLOSE = HIGH
    
    // connect Device sensors and relays
    for (int cCnt = 0; cCnt < (sizeof devices / sizeof devices[0]); cCnt++) {
        if (strcmp(device_name, devices[cCnt].sName.c_str()) == 0) {
            // close the garage if it is open    
            if (state == LOW) {
                // only close the Device if it is open
                if (digitalRead(devices[cCnt].sensorPin) == HIGH) {
                    Serial.printf("[onSetStateDevices] Closed: %s\n", devices[cCnt].sName.c_str());
                    digitalWrite(devices[cCnt].relayPin, LOW);
                    devices[cCnt].relayMillis = millis();
                }
            }
            // open the garage if it is closed
            else {
                // only open the Device if it is closed
                if (digitalRead(devices[cCnt].sensorPin) == LOW) {
                    Serial.printf("[onSetStateDevices] Open: %s\n", devices[cCnt].sName.c_str());
                    digitalWrite(devices[cCnt].relayPin, LOW);
                    devices[cCnt].relayMillis = millis();
                }
            }
            return;
        }
    }
}

void setupDevices () {
    Serial.println("[setupDevices]");
    
    // connect Device sensors and relays
    for (int cCnt = 0; cCnt < (sizeof devices / sizeof devices[0]); cCnt++) {
      
        pinMode(devices[cCnt].relayPin, devices[cCnt].relayMode);
        digitalWrite(devices[cCnt].relayPin, HIGH);  // don't do anything on startup
        
        pinMode(devices[cCnt].sensorPin, devices[cCnt].sensorMode);
        
        fauxmo.addDevice(devices[cCnt].sName.c_str());
    }
    dumpDevices();
}

void setupWifiConfig () {
    //WiFiManager
    //Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wifiManager;
    
    //reset settings - for testing
    //wifiManager.resetSettings();
    
    //sets timeout until configuration portal gets turned off
    //useful to make it all retry or go to sleep
    //in seconds
    //wifiManager.setTimeout(120);
    
    //it starts an access point with the specified name
    //here  "AutoConnectAP"
    //and goes into a blocking loop awaiting configuration
    
    //WITHOUT THIS THE AP DOES NOT SEEM TO WORK PROPERLY WITH SDK 1.5 , update to at least 1.5.1
    //WiFi.mode(WIFI_STA);
    if (!wifiManager.startConfigPortal("myGarage", "linkster")) {
        Serial.println("failed to connect and hit timeout");
        delay(3000);
        //reset and try again, or maybe put it to deep sleep
        ESP.reset();
        delay(5000);
    }
    
    //if you get here you have connected to the WiFi
    Serial.println("connected...yeey :)");
    
    wifiSSID = WiFi.SSID();
    wifiPassword = WiFi.psk();
    
    Serial.printf("[setupWifiConfig] wifiSSID[%s]\n", wifiSSID.c_str());
    Serial.printf("[setupWifiConfig] wifiPassword[%s]\n", wifiPassword.c_str());
}

void wifiSetup() {
Serial.println("[wifiSetup]");

    // Set WIFI module to STA mode
    WiFi.mode(WIFI_STA);
    
    // Connect
    Serial.printf("[WIFI] Connecting to %s ", wifiSSID.c_str());
    WiFi.begin(wifiSSID, wifiPassword);
    
    // Wait
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.println();
    
    // Connected!
    Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
}

void setup() {

    // Init serial port and clean garbage
    Serial.begin(SERIAL_BAUDRATE);
    Serial.println();
    Serial.println();
    Serial.println("[setup]");

    // get wifi ssid and password
    setupWifiConfig();

    // Wifi
    wifiSetup();

    fauxmo.createServer(true); // not needed, this is the default value
    fauxmo.setPort(80); // This is required for gen3 devices

    fauxmo.enable(true);

    setupDevices();

    fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state, unsigned char value) {
        
        Serial.printf("[MAIN] Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value);

        onSetStateDevices(device_name, state);

    });

}

void loop() {

    fauxmo.handle();

    for (int cCnt = 0; cCnt < (sizeof devices / sizeof devices[0]); cCnt++) {
        if (digitalRead(devices[cCnt].relayPin) == LOW) {
            if (millis() - devices[cCnt].relayMillis > 2000) {
                devices[cCnt].relayMillis = millis();
                digitalWrite(devices[cCnt].relayPin, HIGH);
                Serial.printf("[loop] Reset %s %s[HIGH]\n", devices[cCnt].sName.c_str(), getPinNumber(devices[cCnt].relayPin));
            }
        }
    }

    // fauxmo.setState(ID_YELLOW, true, 255);
}

myGarage_2.0.ino (10.1 KB)

Please do not cross-post. Other thread removed.

  1. read config from the drive
  2. if wifi provisioning is required, wifi manager
  3. wifi manager complete, write config to the drive
  4. ESP.reset

Update: there is an AsyncWifiManager, and a AsyncWebServer that seem to work without resetting.