2017/09/15

ESP8266 WiFiManager - Configuring the parameters of the sketch running on ESP8266

This post is about how to use WiFiManager to configure other parameters of the sketch running on ESP8266. By using this approach, there is no need to re-compile the sketch for configuration changes.

The Schematic

Connect a wire to GPIO 0. When the other end of the wire is connected to GND, WiFiManager will clear the saved ssid and password and put the module in AP mode (an "AutoConnectAP" will be spawned for user to connect to it).


Arduino Sketch

The original sketch can be found at the link below.
https://github.com/tzapu/WiFiManager/blob/master/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <FS.h>                   //this needs to be first, or it all crashes and burns...

#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino

//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager

#include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson

int wifi_reset_pin = 0;
int val = 1;

//define your default values here, if there are different values in config.json, they are overwritten.
char mqtt_server[40];
char mqtt_port[6] = "8080";
char blynk_token[34] = "YOUR_BLYNK_TOKEN";

//flag for saving data
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println();

  pinMode(wifi_reset_pin, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);                   // Initialize the LED_BUILTIN pin as an output
  digitalWrite(LED_BUILTIN, HIGH);                // Turn the LED off (Note that LOW is the voltage level

  //clean FS, for testing
  //SPIFFS.format();

  //read configuration from FS json
  Serial.println("mounting FS...");

  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed json");

          strcpy(mqtt_server, json["mqtt_server"]);
          strcpy(mqtt_port, json["mqtt_port"]);
          strcpy(blynk_token, json["blynk_token"]);

        } else {
          Serial.println("failed to load json config");
        }
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }
  //end read

  // The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  
  WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
  WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6);
  WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 32);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //set static ip
  //wifiManager.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
  
  //add all your parameters here
  wifiManager.addParameter(&custom_mqtt_server);
  wifiManager.addParameter(&custom_mqtt_port);
  wifiManager.addParameter(&custom_blynk_token);
  
  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
    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 :)");
  digitalWrite(LED_BUILTIN, LOW);                // Turn the LED on to indicate the ESP is now connected to AP  

  //read updated parameters
  strcpy(mqtt_server, custom_mqtt_server.getValue());
  strcpy(mqtt_port, custom_mqtt_port.getValue());
  strcpy(blynk_token, custom_blynk_token.getValue());

  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_server"] = mqtt_server;
    json["mqtt_port"] = mqtt_port;
    json["blynk_token"] = blynk_token;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

    json.printTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }

  Serial.print("\nLocal IP: ");
  Serial.println(WiFi.localIP());
  
}

void loop() {
    // put your main code here, to run repeatedly:
    
    val = digitalRead(wifi_reset_pin);
    if (val == LOW) {
        digitalWrite(LED_BUILTIN, HIGH);           // Turn the LED off to indicate the ESP is not connected to AP
        
        Serial.println("Disconnect WiFi to reset SSID and Password");
        WiFi.disconnect();                         // https://github.com/tzapu/WiFiManager/issues/142
                                                   // This will erase the stored ssid and password
        //wifiManager.resetSettings();             // Don't use this.
        
        Serial.println("Restart ESP");             // https://github.com/tzapu/WiFiManager/issues/142
        ESP.reset();                               // Be sure to add delay(1000) after this command.
        delay(1000);
    }  

}

IMPORTANT!!

Be sure to have the SPIFFS disk formatted before running the above sketch (the code above doesn't format the SPIFFS disk). If the SPIFFS disk is not formatted, use "SPIFFS.format()" command to format. For detail on how to use the command, refer to the example code (highlighted in red) at the link below http://wei48221.blogspot.tw/2017/09/esp8266-spiffs-examples.html.

The Result

The web page at the captive portal is the same.


Click on Configure WiFi.

On the bottom there are now three more fields for user to enter the settings for MQTT Server, Port Number, and Blynk Token.


After selecting the ssid to connect to and entering wifi password, and other configuration info., click the "Save" button to save the settings.


From the terminal window, you could see the configuration settings being read from the SPIFFS disk into the system.


After pressing the reset button to reset the module, the parameters still exist.


References:

https://github.com/tzapu/WiFiManager/blob/master/examples/AutoConnectWithFSParameters/AutoConnectWithFSParameters.ino

No comments:

Post a Comment