WM Config Portal using BlynkSimpleEsp32/8266_WM.h

Continuing my hunt, @khoih in your software.

I will EMBRACE your philosophy on the Config Portal. It only gets activated when WM cannot connect to Blynk.

Will test DYNAMIC_PARAMETERS next, then DRD.

Glad to see additional interest in your work!

1 Like

Hi @khoih

Having difficulty grabbing the updated values of DYNAMIC_PARAMETERS set in the Config Portal. The updated values from the standard Config Portal fields all work perfectly!

In my code
Lines 89-110 define 4 DYNAMIC_PARAMETERS and give default values.
I am using these parameters to set Virtual pin numbers and widget labels to generalize Sonoff applications.

I am expecting to find the values of these four char variables (controlVpin, controlLabel, heartbeatVpin, heartbeatLabel) to be reset by Config Portal.
The print statements in BLYNK_CONNECTED and in BLYNK_WRITE_DEFAULT show the default values set in the code, do not appear to be changed when modified in the Config Portal.

If I change the values in Config Portal, I do not see these 4 char variables take on the updated values in the runtime program.

Thoughts?

My code:

#define SERIAL_SPEED 230400
#define PROGRAM_NAME "AAA-Blynk WiFiMgr Demo_ESP32_ESP8266"
// Uses ESP32 and ESP8266 to select compile choices


//BLYNK Stuff here
#define BLYNK_PRINT Serial

#define USE_SSL true // to easily select SSL or not
//#define USE_SSL false // to easily select SSL or not

#define USE_WM true   // to easily select WiFi Manager or not
//#define USE_WM false   // to easily select WiFi Manager or not
// REMEMBER: not using _WM means we manage our own initial WiFi connection


#if USE_WM
  #define USE_SPIFFS false  // Choosing EEPROM over SPIFFS here

  #if (!USE_SPIFFS)
    // EEPROM_SIZE must be <= 2048 and >= CONFIG_DATA_SIZE (currently 172 bytes)
    #define EEPROM_SIZE    (2 * 1024)
    // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE
    #define EEPROM_START   512
  #endif

 
  // Force some params in Blynk, only valid for library version 1.0.1 and later
  // (from the Github doc)
  #define TIMEOUT_RECONNECT_WIFI                    10000L
  #define RESET_IF_CONFIG_TIMEOUT                   true
  #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET    5
#endif


#if USE_SSL
  #ifdef ESP8266
    #if USE_WM
      #include <BlynkSimpleEsp8266_SSL_WM.h>
    #else
      #include <BlynkSimpleEsp8266_SSL.h>
    #endif
  #endif
  #ifdef ESP32
    #if USE_WM
      #include <BlynkSimpleEsp32_SSL_WM.h> 
    #else
      #include <BlynkSimpleEsp32_SSL.h>
    #endif
  #endif
  
#else // NOT using SSL
  #ifdef ESP8266
    #if USE_WM
      #include <BlynkSimpleEsp8266_WM.h>
    #else
      #include <BlynkSimpleEsp8266.h>
    #endif
  #endif
  #ifdef ESP32
    #if USE_WM
      #include <BlynkSimpleEsp32_WM.h>
    #else
      #include <BlynkSimpleEsp32.h>
    #endif
  #endif
#endif


#if USE_WM
  #define USE_DYNAMIC_PARAMETERS true

  //Defined in <BlynkSimpleEsp8266_WM.h> and <BlynkSimpleEsp8266_SSL_WM.h>
  /**************************************
    #define MAX_ID_LEN                5
    #define MAX_DISPLAY_NAME_LEN      16

    typedef struct
    {
    char id             [MAX_ID_LEN + 1];
    char displayName    [MAX_DISPLAY_NAME_LEN + 1];
    char *pdata;
    uint8_t maxlen;
    } MenuItem;
  ************************************* */

  #if USE_DYNAMIC_PARAMETERS
    // DEFINE THE DYNAMIC PARAMETERS FOR THE CONFIG PORTAL
    #define CONTROL_VPIN_LENGTH 5 
    char controlVpin [ CONTROL_VPIN_LENGTH + 1 ] = "";

    #define CONTROL_LABEL_LENGTH 18
    char controlLabel [ CONTROL_LABEL_LENGTH + 1 ] = "Clr Config Data";

    #define HEARTBEAT_VPIN_LENGTH 5
    char heartbeatVpin [ HEARTBEAT_VPIN_LENGTH + 1 ] = "";  

    #define HEARTBEAT_LABEL_LENGTH 26
    char heartbeatLabel [ HEARTBEAT_LABEL_LENGTH + 1 ] = "WiFi_Mgr_Demo_Heartbeat";  

    // HAVE NOT FIGURED OUT HOW TO CHANGE THESE
    //#define MAX_ID_LEN                6  // is 5 including terminating 0
    //#define MAX_DISPLAY_NAME_LEN      33 // is 16 including terminating 0
    MenuItem myMenuItems [] =
    { // 1234    123456789012345
      { "cvpn", "Ctrl VPin (#)",  controlVpin,    CONTROL_VPIN_LENGTH },
      { "clab", "Ctrl Label",     controlLabel,   CONTROL_LABEL_LENGTH },
      { "hvpn", "Hbeat VPin (#)", heartbeatVpin,  HEARTBEAT_VPIN_LENGTH },
      { "hlab", "Hbeat Label",    heartbeatLabel, HEARTBEAT_LABEL_LENGTH },
    };

    // Automatically calculates the # of menu items
    uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem);  //MenuItemSize;
  #else // not using USE_DYNAMIC_PARAMETERS
    MenuItem myMenuItems [] = {};

    uint16_t NUM_MENU_ITEMS = 0;
  #endif // end USE_DYNAMIC_PARAMETERS    


// IS THIS NOW NECESSARY FOR ANYONE USING DYNAMIC_PARAMETERS?  

  /////////// Start Default Config Data /////////////
  bool LOAD_DEFAULT_CONFIG_DATA = true;
  //bool LOAD_DEFAULT_CONFIG_DATA = false;

  Blynk_WM_Configuration defaultConfig =
  {
    //char header[16], dummy, not used
    #if USE_SSL  
      "SSL",
    #else
      "NonSSL",
    #endif
    //WiFi_Credentials  WiFi_Creds  [NUM_WIFI_CREDENTIALS]
    //WiFi_Creds.wifi_ssid and WiFi_Creds.wifi_pw
    "SSID2", "password2",
    "Baloney", "Baloney",
    // Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS];
    // Blynk_Creds.blynk_server and Blynk_Creds.blynk_token
    "account.duckdns.org",  "token1", 
    "blynk-cloud.com",     "<<my real Blynk auth>>",
    //int  blynk_port;
    #if USE_SSL
      9443,
    #else
      8080,
    #endif
    //char board_name     [24];
    "Air-Control",
    // terminate the list
    //int  checkSum, dummy, not used
    0
    /////////// End Default Config Data /////////////
  };
#endif // USE_WM


#if ! USE_WM
  char blynkAuth[] = "<my auth>"; // BLYNK Auth 

  char WiFiSSID[] = "<my ssid";  // network SSID (name)
  char WiFiPass[] = "<my passcode>";  // network password
#endif


BlynkTimer myTimer;
// Blynk timers to blink a heartbeat LED on and off
int heartbeatLEDinterval = 3000; // interval between heartbeats for onboard and Blynk Virtual LED in millisec 
int heartbeatLEDtimerID; 

int heartbeatLEDduration = 750; // duraction of each blink in millisec (set as an interval timer)
int heartbeatLEDdurationTimerID;
bool heartbeatLEDon = false; // this lets me use the same routine for the turn-on timer and the turn-off interval

#define BLYNK_HEARTBEAT_LED_VPIN V2
WidgetLED heartbeatLED( BLYNK_HEARTBEAT_LED_VPIN );  // want a blinking LED on the display to show we're live

#define BLYNK_RESET_CONFIG_INFO_VPIN V3  // Uses BLYNK_WRITE_DEFAULT 




/* setup
 *  Set up WiFi, Blynk & Blynk timers 
 *  Set up Blue LED on board
 */
void setup() 
{
  Serial.begin ( SERIAL_SPEED );
  delay ( 500 );  
  Serial.println ( "\n\n=======================================" );
  Serial.print ( PROGRAM_NAME ); 
  #if USE_SSL
    Serial.println ( " ** Using SSL ** \n" );  
  #endif
  Serial.println();
  
  connectToLANandBlynk();  

  // Initialize Onboard LED 
  pinMode ( LED_BUILTIN, OUTPUT );  
  digitalWrite ( LED_BUILTIN, LOW ); 
    
  // Set Blynk Virtual LED OFF
  heartbeatLED.off(); // Blynk Virtual LED
  heartbeatLEDblink(); // first heartbeat 
  
  Serial.println ( "\nSetup complete \n" );    
  
} //end setup





void loop()
{
  Blynk.run();
  myTimer.run();  
} 





// BLYNK_WRITE_DEFAULT GETS CALLED WHEN THERE IS NO SPECIFIC BLYNK_WRITE FOR THAT PIN
// This makes it a flexible receiver
BLYNK_WRITE_DEFAULT() 
{
  Serial.print ( "\nRECEIVED BLYNK SIGNAL FROM V");
    
  int writeVpin = request.pin; 
  Serial.print ( writeVpin );
  Serial.println ( ": " );
  // Print all parameter values
  for ( auto i = param.begin(); i < param.end(); ++i ) 
  {
    Serial.print ( "* " ); 
    Serial.println ( i.asString() );
  }
  Serial.println ( "***" );  
  
  if ( writeVpin == BLYNK_RESET_CONFIG_INFO_VPIN )
  {
    Serial.println ( "Yes, we hit the RESET button." );  
    #if USE_WM
      //****************************************
      Serial.println ( "HIT CONFIG DATA RESET BUTTON" );  
      Blynk.clearConfigData();
      //****************************************
    #endif
  }

  Serial.print ( "controlVpin=<" ); Serial.print ( controlVpin ); 
    Serial.print ( ">, label=<" ); Serial.print ( controlLabel ); 
  Serial.print ( ">, heartbeatVpin=<" ); Serial.print ( heartbeatVpin ); 
    Serial.print ( ">, label=<" ); Serial.print ( heartbeatLabel ); Serial.println ( ">" );  
}





void connectToLANandBlynk()
{
  // Setup WLAN and Blynk
  Serial.print ( "\nSetting up WLAN and Blynk " );  
  #if USE_WM
    Serial.println ( "WITH WiFiManager" ); 
  #else
    Serial.println ( "WITHOUT WiFiManager" );  
  #endif
  
  #if USE_WM
    Serial.println ( "Starting Blynk.begin (with WM)" );  

    Blynk.setConfigPortal ( "TestPortal", "123" );
    Serial.println ( "Blynk.setConfigPortal(TestPortal, 123);" );  

    Blynk.setConfigPortalIP ( IPAddress ( 192, 168, 220, 1 ) );  
    //Blynk.config ( blynkAuth );
    Blynk.begin ( "Blynk-Configurator" ); 
    
  #else//NOT using WM
    Serial.println ( "Starting WiFi.begin (no WM)" );  
    WiFi.begin ( WiFiSSID, WiFiPass );
    Serial.println ( "... waiting a few seconds for WiFi ..." );    
    delay ( 7000 );  // For esp8266, it needs a delay to realize it has connected
    
    // REBOOT if we do not have a good WiFi connection
    if ( WiFi.status() != WL_CONNECTED )
    {
      Serial.println ( "Resetting in a few seconds..." );
      delay ( 3000 );  
      ESP.restart();
    } 
    
    // Configure and launch Blynk
    Blynk.config ( blynkAuth );
    Blynk.connect ( 2500 ); // Don't get stuck hanging for more than 2500 millis.
  #endif // using WM
  
  if ( Blynk.connected() ) Serial.println ( "Blynk connected just fine\n" ); 
  else Serial.println ( "Blynk NOT CONNECTED \n\n" );  

  #if USE_WM
    #if USE_SPIFFS
      Serial.println("\nBlynk using SPIFFS connected. Board Name : " + Blynk.getBoardName());
    #else
      Serial.println("\nBlynk using EEPROM connected. Board Name : " + Blynk.getBoardName());
      Serial.printf("EEPROM size = %d bytes, EEPROM start address = %d / 0x%X\n", EEPROM_SIZE, EEPROM_START, EEPROM_START);
    #endif
  #endif


  Serial.println ( "Setting up Blynk timer" );  
  // Interval timer for heartbeatLED (Blynk LED and onboard LED
  heartbeatLEDtimerID = myTimer.setInterval ( heartbeatLEDinterval, heartbeatLEDblink );  

  Serial.println ( "..Blynk config and timers setup complete\n" );  
} //end connectToBlynk




void heartbeatLEDblink()
/* Blink the on-board LED AND the Virtual Blynk LED
 * First time called, it turne the LEDs on, then sets a timer to turn LED off
 * When the timer triggers, same routine turns the LEDs off
 */
{
  if ( heartbeatLEDon ) // if LED is on, turn it off and vice cersa
  {
    heartbeatLED.off(); // Blynk Virtual LED
    
    digitalWrite ( LED_BUILTIN, LOW ); // On-board LED
    
    Serial.println ( " ..." );
  } else
  {
    heartbeatLED.on();      // Blynk Virtual LED
    
    digitalWrite ( LED_BUILTIN, HIGH );  // On-board LED
    
    // Set the timer to turn off the LEDs in a bit  
    heartbeatLEDdurationTimerID = myTimer.setTimeout ( heartbeatLEDduration, heartbeatLEDblink ); 
    
    Serial.print ( "... heartbeat of " ); Serial.print ( PROGRAM_NAME ); 
    Serial.print ( " WiFi.status() = " ); Serial.print ( WiFi.status() );  
  }
  
  heartbeatLEDon = ! heartbeatLEDon; // flip status
} //end heartbeatLEDblink




// CALLED WHEN CONNECTING TO BLYNK SERVERS
// GETS CALLED IMMEDIATELY ON FIRST CONNECT
BLYNK_CONNECTED()
{
  Serial.println ( "\nBLYNK_CONNECTED..." );  

  Serial.print ( "controlVpin=<" ); Serial.print ( controlVpin ); 
    Serial.print ( ">, label=<" ); Serial.print ( controlLabel ); 
  Serial.print ( ">, heartbeatVpin=<" ); Serial.print ( heartbeatVpin ); 
    Serial.print ( ">, label=<" ); Serial.print ( heartbeatLabel ); Serial.println ( ">" );    
}
1 Like

Dear @thorathome

Thanks so much for finding the bug, which is an good example of my coffee-lacking, hasty, sleep-lacking status. :sleepy:

I put a comment / template to add code into, then forget to follow.

Temporarily, please test change the lib codes as follows, in two places, for each of all 4 WM files

From the buggy one

bool getConfigData()
{
  ....
      if (LOAD_DEFAULT_CONFIG_DATA)
      {
        // Load default Credentials and assume it's OK
        //  loadCredentials();    <==== missing this "Load default Credentials" action,  ;-[
        credDataValid = true;   <=== only do this "assume it's OK"  ;-[
      }
      else
      {           
        credDataValid = loadCredentials();  
      }  

to

bool getConfigData()
{

      .....
      if (LOAD_DEFAULT_CONFIG_DATA)
      {
        // Load default Credentials and assume it's OK
        loadCredentials();        // add this line <=====
        credDataValid = true;
      }
      else
      {           
        credDataValid = loadCredentials();  
      }  

That’s why your help is so important and appreciated to find and kill bugs.

PS: I’ll post the fix in Master late today. You can wait or just continue by modifying the code yourself

Already post pre-Release Version v1.0.13a. Pls use it.
You can have more debugging msgs by adding a line in your code as follows:

//BLYNK Stuff here
#define BLYNK_PRINT       Serial
#define BLYNK_WM_DEBUG    3         <====== this line will turn on lots of dbg msgs

Victory @khoih

Thanks for the super quick responses to my bug hunting. I downloaded your zip and installed 1.0.13a using Arduino IDE. All is right with the world. Updated DYNAMIC_PARAMETERS are now accessible.

To get this far, I used your handy Blynk.clearConfigData(); connected to a virtual ‘reset’ button. I hit the reset button which clears the config data, then manually reboot the ESP8266 to get the Config Portal.

I will start tomorrow looking at drd.

And I’ll use #define BLYNK_WM_DEBUG 3

Two “it would be nice” things (of course!)

  1. When I copy the four /src files over to the master Blynk /src folder, Arduino IDE gives me an error message that we have duplicate libraries. If I empty the Blynk_WiFiManager/src folder after copying to the Blynk /src folder, I also get an error message from Arduino IDE that the WiFiManager /src folder is empty. So I left one of the 4 files duplicated in that folder. It Would Be Nice if I didn’t have to screw around with this. No big deal, but it impacts usability.

  2. Even if LOAD_DEFAULT_CONFIG_DATA = false, I still have to specify the
    Blynk_WM_Configuration defaultConfig = { … } data structure. It Would Be Nice if the sketchwriter didn’t have to do all that when LOAD_DEFAULT_CONFIG_DATA = false.

Again, nice work. Back at it tomorrow, I expect.

  1. When I copy the four /src files over to the master Blynk /src folder, Arduino IDE gives me an error message that we have duplicate libraries. If I empty the Blynk_WiFiManager/src folder after copying to the Blynk /src folder, I also get an error message from Arduino IDE that the WiFiManager /src folder is empty. So I left one of the 4 files duplicated in that folder. It Would Be Nice if I didn’t have to screw around with this. No big deal, but it impacts usability.

That’s why you’d better follow the installation guide (still waiting for you to improve)

Installation

The suggested way to install is to:

  1. Navigate to Blynk_WM page.
  2. Download the latest release Blynk_WM-master.zip.
  3. Extract the zip file to Blynk_WM-master directory
  4. Copy whole Blynk_WM-master/src folder to Arduino libraries’ src directory such as ~/Arduino/libraries/Blynk/src so that you can use SSL without compile error

This way you don’t copy the whole directory into ./libraries directory, but just leave Blynk-WM-v1.xx.xx where you downloaded it.

You can also do this another way

Another way is to use Arduino Library Manager.

  1. Search for Blynk_WiFiManager, then select to install the latest version.
  2. You can also use this link arduino-library-badge for more detailed instructions.
  3. Then move the 2 files BlynkSimpleEsp8266_SSL_WM.h and BlynkSimpleEsp32_SSL_WM.h from directory ~/Arduino/libraries/Blynk_WiFiManager/src into Blynk libraries src directory (normally ~/Arduino/libraries/Blynk/src

But the best way can be (not in README yet)

Easier way is to use Arduino Library Manager.

  1. Search for Blynk_WiFiManager, then select to install the latest version.
  2. You can also use this link arduino-library-badge for more detailed instructions.
  3. Then copy the whole ~/Arduino/libraries/Blynk/src/certs directory into ~/Arduino/libraries/Blynk_WiFiManager/src/certs

Just remember to delete the old library directory, if it still exists.

  1. Even if LOAD_DEFAULT_CONFIG_DATA = false, I still have to specify the
    Blynk_WM_Configuration defaultConfig = { … } data structure. It Would Be Nice if the sketchwriter didn’t have to do all that when LOAD_DEFAULT_CONFIG_DATA = false.

You can just, in the sketch, replace the code as follow

// IS THIS NOW NECESSARY FOR ANYONE USING DYNAMIC_PARAMETERS?

/////////// Start Default Config Data /////////////
#define TO_LOAD_DEFAULT_CONFIG_DATA      true

#if TO_LOAD_DEFAULT_CONFIG_DATA

bool LOAD_DEFAULT_CONFIG_DATA = true;

Blynk_WM_Configuration defaultConfig =
{
  //char header[16], dummy, not used
#if USE_SSL
  "SSL",
#else
  "NonSSL",
#endif
  //WiFi_Credentials  WiFi_Creds  [NUM_WIFI_CREDENTIALS]
  //WiFi_Creds.wifi_ssid and WiFi_Creds.wifi_pw
  "SSID2", "password2",
  "Baloney", "Baloney",
  // Blynk_Credentials Blynk_Creds [NUM_BLYNK_CREDENTIALS];
  // Blynk_Creds.blynk_server and Blynk_Creds.blynk_token
  "account.duckdns.org",  "token1",
  "blynk-cloud.com",     "<<my real Blynk auth>>",
  //int  blynk_port;
#if USE_SSL
  9443,
#else
  8080,
#endif
  //char board_name     [24];
  "Air-Control",
  // terminate the list
  //int  checkSum, dummy, not used
  0
  /////////// End Default Config Data /////////////
};

#else

bool LOAD_DEFAULT_CONFIG_DATA = false;

Blynk_WM_Configuration defaultConfig;

#endif    // TO_LOAD_DEFAULT_CONFIG_DATA

or just leave it as dummy one if you don’t need the feature

bool LOAD_DEFAULT_CONFIG_DATA = false;

Blynk_WM_Configuration defaultConfig;

To get this far, I used your handy Blynk.clearConfigData() ; connected to a virtual ‘reset’ button. I hit the reset button which clears the config data, then manually reboot the ESP8266 to get the Config Portal.

Try DRD (pressing RESET, wait for booting, then 1 more RESET within 10s), the Config Portal will run right away.

1 Like

Hi @khoih

All good here. I am using v1.0.13a. DYMANIC_PARAMETERS work as advertised now, thanks.

I have tested DRD and it also certainly works. Very handy feature.

Regarding Blynk_WMManager v1.0.13a, I found Arduino IDE’s Library manager does not know about v1.0.13a. I downloaded the zip file from Github and use Arduino IDE to load it from the zip. I then CUT & PASTEd the entire /src folder from Blynk_WiFiManager over to the Blynk main library as you recommend.

I do get this repeated error message from Arduino IDE. Not sure why. (The <…> notation below is mine.) It is loading 1.0.13a, though, in spite of the error message - everything works.

Invalid version '1.0.13a' for library in: <…>\Arduino\My New Sketchbook\libraries\Blynk_WM-master

Invalid library found in <…>\Arduino\My New Sketchbook\libraries\Blynk_WM-master: no headers files (.h) found in <…>\Arduino\My New Sketchbook\libraries\Blynk_WM-master

I’ll work on the Installation description and other areas that I see. Plus, I want to contribute an example or two, am restructuring my example code now that (I think) I understand how WMManager works.

Powerful tools, these. Thanks for all the work and coffee.

It’s good you’re moving fast and efficiently.

Regarding Blynk_WMManager v1.0.13a, I found Arduino IDE’s Library manager does not know about v1.0.13a

Because this is just a pre-release, not official, just for internal testing. You have to install it manually as you have done.

Invalid library found in <…>\Arduino\My New Sketchbook\libraries\Blynk_WM-master: no headers files (.h) found in <…>\Arduino\My New Sketchbook\libraries\Blynk_WM-master

After cutting / pasting away all the files, you have to delete the library folder or move it elsewhere outside of \Arduino\My New Sketchbook\libraries\ directory, or Arduino will complain as no-source-code “invalid library”

The best way to start is just download Blynk_WM-master or Blynk_WM-1.0.13a to a directory *outside of of \Arduino\My New Sketchbook\libraries* directory. Then cut / copy and paste the same way.

I’ll work on the Installation description and other areas that I see. Plus, I want to contribute an example or two, am restructuring my example code now that (I think) I understand how WMManager works.

Great and I’d appreciate your help and contribution. More examples are always good. Bug findings and killings are absolutely necessary.

Powerful tools, these. Thanks for all the work and coffee.

Thanks and encouraged that you’d like it. Many more improvised Blynk-WM-related libraries are still waiting for your golden touch, certainly if you’re interested.

The current list in Platform.io:

Dear @thorathome

Release v1.0.14 has been published on GitHub.
Besides the bug fix you knew for dynamicParams, the new features in v1.0.14 are:

  1. If dynamicParams data stored in SPIFFS/ EEPROM is invalid, the default dynamicParams from sketch will take over and be loaded into the Config Portal.
  2. If the stored data is invalid, then default data from sketch will be loaded into Config Portal.

Please have a look at this release and help find / kill bugs.

After upgrade Blynk not work.

Is your DDNS account still pointing to your current public IP address?

Pete.

I do not know.
How to check it?

Log in to your DDNS account (No-IP ?) and check.

Pete.

On DDNS everything is okay.

duckdns.org
It’s the same.

You can see your board is trying to connect to account.duckdns.org and I think that’s not your server DDNS.

You have to change that, using Config Portal

Please reread and follow the instruction there to input your correct server IP or Blynk Cloud name

How-it-works