tzapu / WiFiManager

ESP8266 WiFi Connection manager with web captive portal
http://tzapu.com/esp8266-wifi-connection-manager-library-arduino-ide/
MIT License
6.64k stars 1.98k forks source link

Exception28 after loading stored custom parameters with FS after reset #1363

Open zeile42 opened 2 years ago

zeile42 commented 2 years ago

Hello to all,

sorry for my bad englisch...

My problem is, that wenn i use Wifimanger libary and want so set custom parameter after resetting the ESP8266, the parameter which i wrote in the captive portal, can not be loaded.

This is my code:

#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
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define S0 16   //D0                             /* Assign Multiplexer pin S0 connect to pin D0 of NodeMCU */
#define S1 5    //D1                             /* Assign Multiplexer pin S1 connect to pin D1 of NodeMCU */
#define S2 4    //D2                             /* Assign Multiplexer pin S2 connect to pin D2 of NodeMCU */
#define S3 0    //D3                            /* Assign Multiplexer pin S3 connect to pin D3 of NodeMCU */
#define SIG A0                            /* Assign SIG pin as Analog output for all 16 channels of Multiplexer to pin A0 of NodeMCU */

int decimal = 2;                          // Decimal places of the sensor value outputs
int sensor0;                            /* Assign the name "sensor0" as analog output value from Channel C0 */
int sensor1;                            /* Assign the name "sensor1" as analog output value from Channel C1 */
int sensor2;                            /* Assign the name "sensor2" as analog output value from Channel C2 */
int sensor3;                            /* Assign the name "sensor3" as analog output value from Channel C3 */
int sensor4;                            /* Assign the name "sensor4" as analog output value from Channel C4 */
int sensor5;                            /* Assign the name "sensor5" as analog output value from Channel C5 */
int sensor6;                            /* Assign the name "sensor6" as analog output value from Channel C6 */
int sensor7;                            /* Assign the name "sensor7" as analog output value from Channel C7 */
int sensor8;                            /* Assign the name "sensor8" as analog output value from Channel C8 */
int sensor9;                            /* Assign the name "sensor9" as analog output value from Channel C9 */
int sensor10;                           /* Assign the name "sensor10" as analog output value from Channel C10 */
int sensor11;                           /* Assign the name "sensor11" as analog output value from Channel C11 */
int sensor12;                           /* Assign the name "sensor12" as analog output value from Channel C12 */
int sensor13;                           /* Assign the name "sensor13" as analog output value from Channel C13 */
int sensor14;                           /* Assign the name "sensor14" as analog output value from Channel C14 */
int sensor15;                           /* Assign the name "sensor15" as analog output value from Channel C15 */

#define DHTPIN 12 //D6    // Digital pin connected to the DHT sensor 
#define MoisturePin sensor0  // used for Arduino and ESP8266
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.
#define rainAnalog sensor1
#define rainDigital 13 //D7
#define ONE_WIRE_BUS 2    //D4

// Uncomment the type of sensor in use:
#define DHTTYPE    DHT11     // DHT 11
//#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

char configFileName[] = "/config.json";

//define your default values here, if there are different values in config.json, they are overwritten.
//char mqtt_server[40];
#define mqtt_server       "mqtt_server"
#define mqtt_port         "mqtt_port"
#define mqtt_topic        "mqtt_topic"
#define mqtt_ID           "mqtt_ID"
#define mqtt_user         "mqtt_user"
#define mqtt_pass         "mqtt_pass"

unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE  (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

float wet = 905;
float dry = 420;
float MoistureDeconnect = 18;
int percentageHumididy = 0;

uint32_t delayMS;

//flag for saving data
bool shouldSaveConfig = false;

DHT_Unified dht(DHTPIN, DHTTYPE);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

WiFiClient espClient;
PubSubClient client(espClient);
WiFiManager wifiManager;

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

void reset_setting() {
  // Reset Wifi settings for testing
  wifiManager.resetSettings();
  //clean FS for testing
  SPIFFS.format();
}

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

  // Reset settings for testing
  reset_setting();

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

  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists(configFileName)) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open(configFileName, "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);

#ifdef ARDUINOJSON_VERSION_MAJOR >= 6
        DynamicJsonDocument json(1024);
        auto deserializeError = deserializeJson(json, buf.get());
        serializeJson(json, Serial);
        if ( ! deserializeError ) {
#else
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
#endif
          Serial.println("\nparsed json");
          strcpy(mqtt_server, json["mqtt_server"]);
          strcpy(mqtt_port, json["mqtt_port"]);
          strcpy(mqtt_topic, json["mqtt_topic"]);
          strcpy(mqtt_ID, json["mqtt_ID"]);
          strcpy(mqtt_user, json["mqtt_user"]);
          strcpy(mqtt_pass, json["mqtt_pass"]);
        } else {
          Serial.println("failed to load json config");
        }
        configFile.close();
      }
    }
  } 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_mqtt_topic("topic", "mqtt topic", mqtt_topic, 20);
  WiFiManagerParameter custom_mqtt_ID("ID", "mqtt ID", mqtt_ID, 8);
  WiFiManagerParameter custom_mqtt_user("user", "mqtt user", mqtt_user, 20);
  WiFiManagerParameter custom_mqtt_pass("pass", "mqtt pass", mqtt_pass, 20);

  //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_mqtt_topic);
  wifiManager.addParameter(&custom_mqtt_ID);
  wifiManager.addParameter(&custom_mqtt_user);
  wifiManager.addParameter(&custom_mqtt_pass);

  //set minimum quality of signal so it ignores AP's under that quality
  //defaults to 8%
  //wifiManager.setMinimumSignalQuality();

  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  //wifiManager.setTimeout(120);

  //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 to: )");
  String ssid = WiFi.SSID();
  String password = WiFi.psk();
  Serial.print(ssid);
  Serial.println(" ; ");
  Serial.println(password);

  //read updated parameters
  strcpy(mqtt_server, custom_mqtt_server.getValue());
  strcpy(mqtt_port, custom_mqtt_port.getValue());
  strcpy(mqtt_topic, custom_mqtt_topic.getValue());
  strcpy(mqtt_ID, custom_mqtt_ID.getValue());
  strcpy(mqtt_user, custom_mqtt_user.getValue());
  strcpy(mqtt_pass, custom_mqtt_pass.getValue());
  // strcpy(blynk_token, custom_blynk_token.getValue());

  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");
#ifdef ARDUINOJSON_VERSION_MAJOR >= 6
    DynamicJsonDocument json(1024);
#else
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
#endif
    json["mqtt_server"] = mqtt_server;
    json["mqtt_port"] = mqtt_port;
    json["mqtt_topic"] = mqtt_topic;
    json["mqtt_ID"] = mqtt_ID;
    json["mqtt_user"] = mqtt_user;
    json["mqtt_pass"] = mqtt_pass;

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

#ifdef ARDUINOJSON_VERSION_MAJOR >= 6
    serializeJson(json, Serial);
    serializeJson(json, configFile);
#else
    json.printTo(Serial);
    json.printTo(configFile);
#endif
    configFile.close();
    //end save
  }

  Serial.println("local ip");
  Serial.println(WiFi.localIP());
  //  client.setServer(mqtt_server, 12025);
  String mqtt_prt_x_s(mqtt_port);
  const uint16_t mqtt_port_x = strtol(mqtt_prt_x_s.c_str(), NULL, 10);
  const char* mqtt_server_conn = mqtt_server;
  client.setServer(mqtt_server_conn, mqtt_port_x);
  Serial.println("MQTT Server startet with: ");
  Serial.print(mqtt_server_conn);
  Serial.print(" ; ");
  Serial.println(mqtt_port_x);
  client.setCallback(callback);

  pinMode(S0, OUTPUT);                      /* Define digital signal pin as output to the Multiplexer pin SO */
  pinMode(S1, OUTPUT);                      /* Define digital signal pin as output to the Multiplexer pin S1 */
  pinMode(S2, OUTPUT);                      /* Define digital signal pin as output to the Multiplexer pin S2 */
  pinMode(S3, OUTPUT);                      /* Define digital signal pin as output to the Multiplexer pin S3 */
  pinMode(SIG, INPUT);                      /* Define analog signal pin as input or receiver from the Multiplexer pin SIG */
  pinMode(rainDigital, INPUT);

  dht.begin();
  Serial.println(F("DHTxx Unified Sensor Example"));
  // Print temperature sensor details.
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  Serial.println(F("------------------------------------"));
  Serial.println(F("Temperature Sensor"));
  Serial.print  (F("Sensor Type: ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:  ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:   ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:   ")); Serial.print(sensor.max_value); Serial.println(F("°C"));
  Serial.print  (F("Min Value:   ")); Serial.print(sensor.min_value); Serial.println(F("°C"));
  Serial.print  (F("Resolution:  ")); Serial.print(sensor.resolution); Serial.println(F("°C"));
  Serial.println(F("------------------------------------"));
  // Print humidity sensor details.
  dht.humidity().getSensor(&sensor);
  Serial.println(F("Humidity Sensor"));
  Serial.print  (F("Sensor Type: ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:  ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:   ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:   ")); Serial.print(sensor.max_value); Serial.println(F("%"));
  Serial.print  (F("Min Value:   ")); Serial.print(sensor.min_value); Serial.println(F("%"));
  Serial.print  (F("Resolution:  ")); Serial.print(sensor.resolution); Serial.println(F("%"));
  Serial.println(F("------------------------------------"));
  // Set delay between sensor readings based on sensor details.
  delayMS = sensor.min_delay / 1000;

  Serial.println("Dallas Temperature IC Control Library Demo");
  sensors.begin();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      //client.publish("test1", "hello world");
      // ... and resubscribe
      //client.subscribe("Moisture_in");
    } else {
      client.setCallback(callback);
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void callback(char* topic, byte * payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    String message = message + (char) payload[i];  // convert *byte to string
    Serial.print(message);
  }
  Serial.println();
}
String topic_string(mqtt_topic);
String t_DTH11_out_s = topic_string + "/t_DTH11_out";
String m_DTH11_out_s = topic_string + "/m_DTH11_out";
String m_val_out_s = topic_string + "/m_val_out";
String m_perc_out_s = topic_string + "/m_perc_out";
String rain_dig_out_s = topic_string + "/rain_dig_out";
String rain_analog_out_s = topic_string + "/rain_analog_out";
String t_plant_out_s = topic_string + "/t_plant_out";

const char *t_DTH11_out = t_DTH11_out_s.c_str();
const char *m_DTH11_out = m_DTH11_out_s.c_str();
const char *m_val_out = m_val_out_s.c_str();
const char *m_perc_out = m_perc_out_s.c_str();
const char *rain_dig_out = rain_dig_out_s.c_str();
const char *rain_analog_out = rain_analog_out_s.c_str();
const char *t_plant_out = t_plant_out_s.c_str();

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // Delay between measurements.
  delay(delayMS);
  // Get temperature event and print its value.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
    client.publish(t_DTH11_out, "Error reading temperature!");
  }
  else {
    Serial.print(F("Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("°C"));
    float Temp_DHT11_f = event.temperature;
    char Temp_DHT11[10];
    dtostrf(Temp_DHT11_f, 9, 2, Temp_DHT11);
    client.publish(t_DTH11_out, Temp_DHT11);
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println(F("Error reading humidity!"));
    client.publish(m_DTH11_out, "Error reading humidity!");
  }
  else {
    Serial.print(F("Humidity: "));
    Serial.print(event.relative_humidity);
    Serial.println(F("%"));
    float Mois_DHT11_f = event.relative_humidity;
    char Mois_DHT11[10];
    dtostrf(Mois_DHT11_f, 9, 2, Mois_DHT11);
    client.publish(m_DTH11_out, Mois_DHT11);
  }

  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);
  float MoistureVal = analogRead(MoisturePin);
  Serial.print("Moisture Sensor Raw Value = ");
  Serial.println(MoistureVal);
  percentageHumididy = (MoistureVal - wet) * (100 - 0) / (dry - wet) + 0;
  Serial.print("Humidity Moisture Sensor = ");
  Serial.print(percentageHumididy);
  Serial.println("%");
  char Moisture[10];
  dtostrf(MoistureVal, 9, 2, Moisture);
  client.publish(m_val_out, Moisture);
  char Moisture_percent[10];
  dtostrf(percentageHumididy, 9, 2, Moisture_percent);
  client.publish(m_perc_out, Moisture_percent);

  int rainDigitalVal = digitalRead(rainDigital);
  Serial.print(F("Rain digital: "));
  Serial.println(rainDigitalVal);
  char RAIN_DIG[10];
  dtostrf(rainDigitalVal, 9, 2, RAIN_DIG);
  client.publish(rain_dig_out, RAIN_DIG);

  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);
  int rainAnalogVal = analogRead(rainAnalog);
  Serial.print(F("Rain analog: "));
  Serial.println(rainAnalogVal);
  char RAIN_ANALOG[10];
  dtostrf(rainAnalogVal, 9, 2, RAIN_ANALOG);
  client.publish(rain_analog_out, RAIN_ANALOG);

  sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0);
  // Check if reading was successful
  if (tempC != DEVICE_DISCONNECTED_C)
  {
    Serial.print("Temperature for the device 1 (index 0) is: ");
    Serial.println(tempC);
    char Temp_Plant[10];
    dtostrf(tempC, 9, 2, Temp_Plant);
    client.publish(t_plant_out, Temp_Plant);
  }
  else
  {
    Serial.println("Error: Could not read temperature data");
    client.publish(t_plant_out, "Error: Could not read temperature data");
  }
}

If i load the code on the esp8266 for the first time, everything is ok and working, but if i reset the esp8266 the stored parameters can not be loaded again and the programm crashes. The error what i get:

`)⸮ ⸮@H⸮LH⸮mounting FS... mounted file system reading config file opened config file {"10.0.0.43":"10.0.0.43","1883":"1883","Test1":"Test1","mqtt_I":"mqtt_I","mqtt_user":"mqtt_user","mqtt_pass":"mqtt_pass"} parsed json --------------- CUT HERE FOR EXCEPTION DECODER --------------- Exception (28): epc1=0x40222bdc epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

stack>>> ctx: cont sp: 3ffffc70 end: 3fffffc0 offset: 0190 3ffffe00: 3ffef55c 3fff1004 3ffef55c 40201aa4 3ffffe10: 3ffe89af 3fff1004 3ffef55c 40202daf 3ffffe20: 3fff1064 3fff105a feefef01 3fff107d 3ffffe30: feef007d 3ffffe88 feefeffe feefeffe 3ffffe40: feefeffe feefeffe feefeffe feefeffe 3ffffe50: feefeffe feefeffe feefeffe feefeffe 3ffffe60: feefeffe feefeffe feefeffe feefeffe 3ffffe70: feefeffe feefeffe 00000000 feefeffe 3ffffe80: feefeffe feefeffe 3fff1084 3fff1084 3ffffe90: 3fff1424 3fff1484 feefef00 feefeffe 3ffffea0: 3fff1474 3fff1424 feefef20 feefeffe 3ffffeb0: 4021d884 00000000 000003e8 4020f358 3ffffec0: 00000000 3fff0fc0 3fff0fb4 4021290c 3ffffed0: 00000000 00000000 3ffef724 feefeffe 3ffffee0: feefeffe feefeffe feefeffe feefeffe 3ffffef0: feefeffe feefeffe feefeffe feefeffe 3fffff00: feefeffe feefeffe feefeffe feefeffe 3fffff10: feefeffe feefeffe feefeffe feefeffe 3fffff20: feefeffe feefeffe feefeffe feefeffe 3fffff30: feefeffe feefeffe feefeffe feefeffe 3fffff40: feefeffe feefeffe feefeffe feefeffe 3fffff50: feefeffe feefeffe feefeffe feefeffe 3fffff60: feefeffe feefeffe feefeffe feefeffe 3fffff70: feefeffe feefeffe feefeffe feefeffe 3fffff80: feefeffe feefeffe feefeffe feefeffe 3fffff90: feefeffe feefeffe feefeffe 3ffef6a0 3fffffa0: 3fffdad0 00000000 3ffef68c 40211728 3fffffb0: feefeffe feefeffe 3ffe85f4 40100d0d <<<stack<<<`

Can the problem be the Flashe Size? My setting is: Flash Size: 4MB (FS:2MB OTA: 1019kB)

This is what i get in the consol when i load the scetch to the esp8266 board:

Chip is ESP8266EX Features: WiFi Crystal is 26MHz MAC: c4:5b:be:54:d9:82 Uploading stub... Running stub... Stub running... Configuring flash size... Auto-detected Flash size: 4MB Flash params set to 0x0340 Compressed 402144 bytes to 284578...

Also i saw, that the parameter which i changed in the captive portal also the names are changed:

{"10.0.0.43":"10.0.0.43","1883":"1883","Test1":"Test1","mqtt_ID":"mqtt_ID","mqtt_user":"mqtt_user","mqtt_pass":"mqtt_pass"}

Should it not be like:

{"mqtt_server":"10.0.0.43","mqtt_port":"1883","mqtt_topic":"Test1","mqtt_ID":"mqtt_ID","mqtt_user":"mqtt_user","mqtt_pass":"mqtt_pass"}

So that the name mqtt_server is not changed to the value i give it in the captive portal?

Has anybody an idea what the problem is and can help me?

Thanks for the help

mfg

tablatronix commented 2 years ago

you mean this ?

#define mqtt_server "mqtt_server"

Thats not a variable, thats a definition, so that is why they are all still strings