Arduino OTA Updates without hardcoding SSID and Password

Ok all, so first off this is not a cry for help but rather an update to a previous post about how amazing OTA updates are. Well yes they are BUT I did not want to have to hard code my SSID and Password into each sketch. So I did some searching and found this post which was amazing but not exactly what I was looking for. I continued to search for a way to implement this sketch but not have to hard code my SSID and Password to no avail; or least nothing that I could get to work.

I set out to find a way to combine the WiFiManager library and the ArduinoOTA library. After much trial and error, and mind you I an a novice programmer, I got it to work. Albeit with just a basic sketch, but it works. The below sketches are a combination of the code requirements of ArduinoOTA and WiFiManger. I have not added Blynk functionality to this sketch yet; that is my next step but I now know that I an create smart home widgets without providing an SSID and Password in the sketch.

Here is the initial sketch done on a NodeMCU 1.0 (ESP-12E Module). My assumption is that you have the appropriate version of python and all of the necessary libraries installed.

//Basic OTA updates (Initial) without hardcoding SSID and PASSWORD

//Common libraries
#include <ESP8266WiFi.h>

//WiFiManager specific libraries
#include <DNSServer.h>          //Local DNS server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h>   //Local WebServer used to serve as the configuration portal
#include <WiFiManager.h>        //Core library

//ArduinoOTA specific libraries
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

void setup()
{
  Serial.begin(115200);
  WiFi.disconnect();            //uncomment to clear SSID and PASSWORD from EEPROM
  WiFi.hostname("XXXX"); //uncomment to change hostname for device.  Replace XXXX with your own unique name
  WiFiManager wifi;             //WiFiManager local initialization

  //Attempt to get SSID and PASSWORD from EEPROM and connect to network
  //If it does not connect it creates an Access Point with the
  //Specified name
  wifi.autoConnect("XXXX");  //Replace XXXX with your own unique name

  ArduinoOTA.begin();
  
}

void loop()
{
  ArduinoOTA.handle();
}

Now after you upload this sketch you need to hard reset or remove power from your NodeMCU and then power back on via something other than your computer. It is not a requirement that it not be connected to your computer but it helps with your self esteem when you see the code update when the NodeMCU is in another room. Next you need to find and connect to the access point IP address for the NodeMCU so that you can provide the SSID and password. I think the default for all NodeMCU boards is 192.168.4.1. Once you enter that into the browser on your phone or computer, you will run through a series of prompts to provide the required information to connect to your network.

Once you are connected to your network, you will need to find the IP address assigned to the NodeMCU so that you can upload subsequent sketches. If should auto-populate in the Tools - Ports section of the Arduino IDE or you can go into your router and locate the IP address by finding the hostname your gave the NodeMCU. Once you have the IP address select it from the Tools - Ports menu and then upload the following sketch via wifi to verify that it works.

//Basic OTA updated (Subsequent Test) without hardcoding SSID and PASSWORD

//Common libraries
#include <ESP8266WiFi.h>

//WiFiManager specific libraries
#include <DNSServer.h>  //Local DNS server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h>  //Local WebServer used to serve as the configuration portal
#include <WiFiManager.h>  //Core library

//ArduinoOTA specific libraries
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const int ESP_BUILTIN_LED = 2;

void setup()
{
  Serial.begin(115200);
  //WiFi.disconnect();  //uncomment to clear SSID and PASSWORD from EEPROM
  WiFi.hostname("XXXX");  //uncomment to change hostname for device.  Replace XXXX with your own unique name
  WiFiManager wifi;  //WiFiManager local initialization

  //Attempt to get SSID and PASSWORD from EEPROM and connect to network
  //If it does not connect it starts creates an Access Point with the
  //Specified name
  wifi.autoConnect("XXXX");  //Replace XXXX with your own unique name

  ArduinoOTA.begin();
  pinMode(ESP_BUILTIN_LED, OUTPUT);
  
}

void loop()
{
  ArduinoOTA.handle();
  digitalWrite(ESP_BUILTIN_LED, LOW);
  delay(1000);
  digitalWrite(ESP_BUILTIN_LED, HIGH);
  delay(1000);
}

If all goes as it did for me, you should be seeing the onboard LED blynking on your NodeMCU.

One warning: if you are using a NodeMCU that has previously been connected to your network, be sure to uncomment

WiFi.disconnect();

on the initial upload so that you can run through all of the steps required from a fresh install. On the subsequent uploads, you can re-comment it back.

Finally, I look forward to comments and improvements. I am far from an expert so I welcome all forms of critique.

Happy Blynking.

Sean

2 Likes

You might find it useful to include the following line in your void setup:

ArduinoOTA.setHostname("Your Device Name");

The device name you specify then shows-up in the list of network ports in the Arduino IDE, followed by the IP address of the device. This makes life much easier to identify the correct device when you have multiple devices around the house.

I’m not really clear about why you don’t want to hard-code the Wi-Fi credentials in your sketch. It’s probably quicker to do an OTA update with new credentials than connect to each device using Wi-Fi manager and update the Wi-Fi credentials that way.
It’s handy if you’re giving devices to other people and providing them with a method of connecting to their Wi-Fi, but once the device is no longer connected to the same network as your PC then you can’t do OTA updates anyway. The only way aro7nd this is to use HTTP OTA, but that requires different code to what you’ve used.

I like the fact that you’ve rolled-up your sleeves and got this working by trial and error though - that’s the way to be a better and more confident coder.

Pete.

1 Like

Pete, thanks for the comments. Out of curiosity, how is

ArduinoOTA.setHostname("Your Device Name");

different from

WiFi.hostname("XXXX");  //Substitute XXXX for your unique name

I probably did a poor job of explaining this step. However, when I use the one I provided in the sketch it shows up in the list of network ports in the Arduino IDE.

My justification for not hard-coding the SSID and Password is exactly the reason you state. I am building a bunch of wireless outlet controllers for friends and family and I want them to have the convenience of the web-based prompts that WiFiManger has to allow them to provide their own SSID and password on deployment.

More to follow as I insert the code that will control my wireless outlets via the blynk app, hardware switch, and Alexa.

Thanks again, Sean

I’m not sure, it looks like they have the same effect. As you said, you didn’t really explain that you were seeing anything other than the device IP address in the list of ports.

I’m still not clear about why you’ve included the OTA firmware in your sketch. You need to hook the devices up via USB to flash them with the initial code and after that you’ll be passing them on to other people and you won’t be able to do OTA updates once they aren’t connected to your network.
You really should look at HTTP OTA and get your code to check for updates every day, and maybe add a Blynk button widget that triggers an OTA update at any time you want.

Pete.

What’s wrong with hardcoding the password into the code?
It’s compiled and you need to be on the same network or physically connected to it to download the compiled code.

The best way I found,
This might help you

Hello
I am new to BLYNK Community but not to blynk and nodemcu
I always like non-blocking codes, means if wifi is not there or internet connectivity is not there, the code in the " void loop() { } " should keep running smoothly as offline mode
I have a code to be used as template for all projects during development as below

// In the Blynk app, add an LED on V1

#include <ESP8266WiFi.h>          
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <BlynkSimpleEsp8266.h>

#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>       //https://github.com/tzapu/WiFiManager
#include <EEPROM.h>

//ArduinoOTA specific libraries
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

#include <SimpleTimer.h>

#define TRIGGER_PIN D1    // Input Definition, you may define any other way you like
const int ESP_BUILTIN_LED = 2; // Output Deifinition, you may define any other way you like
SimpleTimer T1;   // Soft timer used instead of delay() function 
int eeAddress;    // EEPROM used to save blynk_token
char blynk_token[34] = "blynk_token";
int n = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("\n Starting");  
  ArduinoOTA.begin();
  EEPROM.begin(512);
  T1.setInterval(1000,T1exe);

  pinMode(TRIGGER_PIN, INPUT_PULLUP);
  pinMode(ESP_BUILTIN_LED, OUTPUT);

  eeAddress = 70;
  EEPROM.get(eeAddress, blynk_token);
  Blynk.config(blynk_token);
  ArduinoOTA.setHostname("Your_Device_Name");
}


void loop() {
  // is configuration portal requested?
  if ( digitalRead(TRIGGER_PIN) == LOW ) 
  { OnDemandConfig(); }

  ArduinoOTA.handle();
  Blynk.run();
  T1.run();
  n++;
  
  // put your main code here, to run repeatedly:


}

void OnDemandConfig(){
    //WiFiManager
    //Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wifiManager;
    eeAddress = 70;
    EEPROM.get(eeAddress, blynk_token);
    WiFiManagerParameter custom_blynk_token("blynk", "Blynk_Auth_Token", blynk_token, 32);
    wifiManager.addParameter(&custom_blynk_token);  // More Parameters may be added as required

    //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(50); // beginers may increase it to 120 seconds for 2 minutes...

    //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("OnDemandAP","OptionalPassword")) {
      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);
    }

    strcpy(blynk_token, custom_blynk_token.getValue());  
    eeAddress = 70;   // eeprom memory address 70 is used to save blynk_token, change as per needs
    EEPROM.put(eeAddress, blynk_token);
    EEPROM.commit();
    
    //if you get here you have connected to the WiFi
    Serial.println("connected...yeey :)");

    Blynk.config(blynk_token);
    if(WiFi.status() == WL_CONNECTED) // if not connected to WiFi do not try connecting to Blynk, (It hangs here...)
    {
      Blynk.begin(blynk_token, WiFi.SSID().c_str(), WiFi.psk().c_str());
      //Serial.println("connecting blynk..."); 
     }    

  }


void T1exe()
{ static int a = 0;
  if (a==0) 
  { a=1; digitalWrite(ESP_BUILTIN_LED,HIGH); Blynk.virtualWrite(V1,255); }
  else  
  { a=0; digitalWrite(ESP_BUILTIN_LED,LOW); Blynk.virtualWrite(V1,0); }  
Serial.print("loop count : ");
Serial.println(n);
n=0;
}

The code combines : OTA, WiFiManager :: OnDemandConfig , Blynk

  1. OTA works in both AP Mode and Station Mode
  2. WiFi SSID, Password and even Blynk Token can be re-configured, NO HARD CODING
  3. Time-out from config.mode works well, Serial Monitor is also there for de-bugging

The code is working as expected but a few things i want to improve are as

  1. can/should i have void loop () running even in AP Mode ?
  2. even when h/w is connected to wi-fi network, AP Mode do not terminate ?
  3. when we have wi-fi without internet/data, blynk cloud could not be reached and it takes longer
    means the loop is no more being executed at the same rate…(NON-BLOCKING CODE purposed defeats to certain extent, though the interrupts keeps on working)

@VivekSaini please edit your post, using the pencil icon at the bottom, and add triple backticks at the beginning and end of your code so that it displays correctly.
Triple backticks look like this:
```

Pete.