0

Hey all I am having some issues with the SPIFFS for this Wemos D1 mini ESP8266 controller.

This is my Arduino sketch:

#include <FS.h>
#include <ArduinoJson.h>

struct RGBLA {
  uint8_t R;
  uint8_t G;
  uint8_t B;
  uint8_t L;
  uint8_t A;
};

void setup() {
  if (!SPIFFS.begin()) {
    Serial.println("error while mounting filesystem!");
  } else {    
    // put your setup code here, to run once:
    RGBLA returnedVars = readSPIFFS();

    Serial.begin(115200);
    Serial.println();
    Serial.println("Starting...");

    Serial.println("readSPIFFS 1");
    Serial.print("R: ");
    Serial.println(returnedVars.R);
    Serial.print("G: ");
    Serial.println(returnedVars.G);
    Serial.print("B: ");
    Serial.println(returnedVars.B);
    Serial.print("L: ");
    Serial.println(returnedVars.L);
    Serial.print("AmbientLight: ");
    Serial.println(returnedVars.A);

    Serial.println("==================================");

    returnedVars = saveToSPIFFS(25,77, 107, 250, 155, false);  
    Serial.println("saveToSPIFFS #1");
    Serial.print("R: ");
    Serial.println(returnedVars.R);
    Serial.print("G: ");
    Serial.println(returnedVars.G);
    Serial.print("B: ");
    Serial.println(returnedVars.B);
    Serial.print("L: ");
    Serial.println(returnedVars.L);
    Serial.print("AmbientLight: ");
    Serial.println(returnedVars.A);

    Serial.println("==================================");

    returnedVars = saveToSPIFFS(205,17, 68, 50, 15, true);
    Serial.println("saveToSPIFFS #2");
    Serial.print("R: ");
    Serial.println(returnedVars.R);
    Serial.print("G: ");
    Serial.println(returnedVars.G);
    Serial.print("B: ");
    Serial.println(returnedVars.B);
    Serial.print("L: ");
    Serial.println(returnedVars.L);
    Serial.print("AmbientLight: ");
    Serial.println(returnedVars.A);

    returnedVars = readSPIFFS();
    Serial.println("readSPIFFS 2");
    Serial.print("R: ");
    Serial.println(returnedVars.R);
    Serial.print("G: ");
    Serial.println(returnedVars.G);
    Serial.print("B: ");
    Serial.println(returnedVars.B);
    Serial.print("L: ");
    Serial.println(returnedVars.L);
    Serial.print("AmbientLight: ");
    Serial.println(returnedVars.A);

    Serial.println();
    Serial.println("END!");
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

RGBLA saveToSPIFFS(uint8_t R, uint8_t G, uint8_t B, uint8_t L, uint8_t A, bool saveA) {
  File configFile = SPIFFS.open("/config.json", "w+");

  if (configFile.size() > 3072) {
    Serial.println("Config file size is too large.");
  } else {
    Serial.print("Writing json to Config file...");

    StaticJsonBuffer<200> jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();

    //Get the old value and save it
    RGBLA returnedVars = readSPIFFS();

    Serial.println("Old Values?");
    Serial.print("R: ");
    Serial.println(returnedVars.R);
    Serial.print("G: ");
    Serial.println(returnedVars.G);
    Serial.print("B: ");
    Serial.println(returnedVars.B);
    Serial.print("L: ");
    Serial.println(returnedVars.L);
    Serial.print("AmbientLight: ");
    Serial.println(returnedVars.A);

    if (saveA) {
      //Save Ambient Light data
      json["R"] = returnedVars.R;
      json["G"] = returnedVars.G;
      json["B"] = returnedVars.B;
      json["L"] = returnedVars.L;
      json["A"] = A;

      //Now save the new data
      returnedVars.A = A;
    } else {
      //Save RGBL data
      json["R"] = R;
      json["G"] = G;
      json["B"] = B;
      json["L"] = L;   
      json["A"] = returnedVars.A;

      //Now save the new data
      returnedVars.R = R;
      returnedVars.G = G;
      returnedVars.B = B;
      returnedVars.L = L;
    }

    json.printTo(configFile);
    configFile.close();

    //Read new saved values into struct
    //returnedVars = readSPIFFS();
    return returnedVars;
  }
}

RGBLA readSPIFFS() {
  bool exist = SPIFFS.exists("/config.json");

  if (exist) {
    Serial.println("YAY!");
  } else {
    Serial.println("Boo!");
  }

  File configFile = SPIFFS.open("/config.json", "r");
  std::unique_ptr<char[]> buf(new char[configFile.size()]);
  configFile.readBytes(buf.get(), configFile.size());
  DynamicJsonBuffer jsonBuffer;
  JsonObject& json = jsonBuffer.parseObject(buf.get());  
  RGBLA returnedVars;

  String debugLogData;
  json.printTo(debugLogData);

  Serial.println("===============");
  Serial.println(debugLogData);
  Serial.println("===============");
  returnedVars.R = json["R"];
  returnedVars.G = json["G"];
  returnedVars.B = json["B"];
  returnedVars.L = json["L"];
  returnedVars.A = json["A"];

  configFile.close();

  return returnedVars;
}

And this is the console output:

Starting...
readSPIFFS 1
R: 0
G: 0
B: 0
L: 0
AmbientLight: 25
==================================
Writing json to Config file...YAY!
===============
{}
===============
Old Values?
R: 0
G: 0
B: 0
L: 0
AmbientLight: 0
saveToSPIFFS #1
R: 25
G: 77
B: 107
L: 250
AmbientLight: 0
==================================
Writing json to Config file...YAY!
===============
{}
===============
Old Values?
R: 0
G: 0
B: 0
L: 0
AmbientLight: 0
saveToSPIFFS #2
R: 0
G: 0
B: 0
L: 0
AmbientLight: 25
YAY!
===============
{"R":0,"G":0,"B":0,"L":0,"A":25}
===============
readSPIFFS 2
R: 0
G: 0
B: 0
L: 0
AmbientLight: 25

END!

As you can see, the first old values has all 0's which is incorrect. AmbientLight should be 25 at that point since readSPIFFS 1 has 25. So this should read:

Old Values?
R: 0
G: 0
B: 0
L: 0
AmbientLight: 25

saveToSPIFFS #1 is sending values 25, 77, 107, 250, 155 and false which then outputs correctly as:

R: 25
G: 77
B: 107
L: 250
AmbientLight: 0

But this time AmbientLight should still be 25 since it was sent false. It should have taken the old value (25) and placed it into the newer save.

R: 25
G: 77
B: 107
L: 250
AmbientLight: 25

Moving on to saveToSPIFFS #2 the values again are incorrect. The AmbientLight however is correct here. Instead of this output:

R: 0
G: 0
B: 0
L: 0
AmbientLight: 25

it should be gathering the 4 previous old values:

R: 25
G: 77
B: 107
L: 250
AmbientLight: 25

The json after this should not be this:

{"R":0,"G":0,"B":0,"L":0,"A":25}

It should be this:

{"R":250,"G":77,"B":107,"L":250,"A":25}

And lastly, the output of readSPIFFS 2:

R: 0
G: 0
B: 0
L: 0
AmbientLight: 25

Is incorrect. It should output:

R: 25
G: 77
B: 107
L: 250
AmbientLight: 25

Then after a reset it should have that and not the below for readSPIFFS 1:

R: 0
G: 0
B: 0
L: 0
AmbientLight: 25

So, where am I messing up here?

UPDATE

struct RGBLA {
  uint8_t R;
  uint8_t G;
  uint8_t B;
  uint8_t L;
  uint8_t A;
};

void setup() {
   RGBLA returnedValues = readSPIFFS();

   Serial.println("readSPIFFS 1");
   Serial.print("R: ");
   Serial.println(returnedVars.R);
   Serial.print("G: ");
   Serial.println(returnedVars.G);
   Serial.print("B: ");
   Serial.println(returnedVars.B);
   Serial.print("L: ");
   Serial.println(returnedVars.L);
   Serial.print("AmbientLight: ");
   Serial.println(returnedVars.A);

   returnedValues = saveToSPIFFS(205, 17, 68, 50, 15, false);

   Serial.println("saveToSPIFFS 1");
   Serial.print("R: ");
   Serial.println(returnedVars.R);
   Serial.print("G: ");
   Serial.println(returnedVars.G);
   Serial.print("B: ");
   Serial.println(returnedVars.B);
   Serial.print("L: ");
   Serial.println(returnedVars.L);
   Serial.print("AmbientLight: ");
   Serial.println(returnedVars.A);
}

RGBLA readSPIFFS() {    
   RGBLA returnedVars;
   File configFile = SPIFFS.open("/config.json", "r");

   if (configFile ) {
     Serial.println("YAY!");
     configFile.readBytes((byte*) &returnedValues, sizeof(RGBLA));
     configFile.close();
   } else {
     Serial.println("Boo!");
   }

   return returnedValues;
}

RGBLA saveToSPIFFS() {    
   File configFile = SPIFFS.open("/config.json", "w+");

   if (configFile.size() > 3072) {
     Serial.println("Config file size is too large.");
   } else {
     Serial.print("Writing to Config file...");

     //Get the old value and save it
     RGBLA returnedVars = readSPIFFS();

     Serial.println("Old Values:");
     Serial.print("R: ");
     Serial.println(returnedVars.R);
     Serial.print("G: ");
     Serial.println(returnedVars.G);
     Serial.print("B: ");
     Serial.println(returnedVars.B);
     Serial.print("L: ");
     Serial.println(returnedVars.L);
     Serial.print("AmbientLight: ");
     Serial.println(returnedVars.A);

     if (saveA) {
       //Save Ambient Light data
       returnedVars.A = A;
     } else {
       //Save RGBL data
       returnedVars.R = R;
       returnedVars.G = G;
       returnedVars.B = B;
       returnedVars.L = L;
     }

     configFile.write((byte*) &returnedVars, sizeof(RGBLA));
     configFile.close();

     return returnedVars;
}
  • why do you save it as JSON? simple file.write((byte*) rgbla, sizeof (RGBLA)) and file.read((byte*) rgbla, sizeof (RGBLA)) would work – Juraj Sep 30 '18 at 12:43
  • @Juraj can you put that as a potential answer and provide an example? – StealthRT Oct 1 '18 at 2:28
  • if it will be only one instance of the RGBLA struct and one file to save it, then create one global instance of the struct and rather return a succes state from functions – Juraj Oct 1 '18 at 16:00
1

You can write a struct to file as binary data. This example is from my project.

global data:

struct Stats {
  int heatingTime; // minutes
  int consumedPower; // watts
};

Stats statsData;

snippet from setup():

  File file = SPIFFS.open(STATS_FILENAME, "r");
  if (file) {
    file.readBytes((byte*) &statsData, sizeof(statsData));
    file.close();
  }

snippet from statsSave() function:

  File file = SPIFFS.open(STATS_FILENAME, "w");
  if (file) {
    file.write((byte*) &statsData, sizeof(statsData));
    file.close();
  }

your updated readSPIFFS should be:

RGBLA readSPIFFS() {

  RGBLA returnedVars;
  File configFile = SPIFFS.open("/config.json", "r");
  if (configFile ) {
    Serial.println("YAY!");
    configFile.readBytes((byte*) &returnedValues, sizeof(RGBLA));
    configFile.close();
  } else {
    Serial.println("Boo!");
  }
  return returnedValues;
}
  • So I can still return RGBLA like RGBLA returnedVars = readSPIFFS();? – StealthRT Oct 1 '18 at 14:32
  • Check out my updated OP. – StealthRT Oct 1 '18 at 14:41
  • configFile.readBytes((byte*) &returnedValues, sizeof(returnedValues)); or configFile.readBytes((byte*) &returnedValues, sizeof(RGBLA)); – Juraj Oct 1 '18 at 14:43
  • Alright corrected that in the update. Do I still need to use return returnedVars; or is it already populating the strut? – StealthRT Oct 1 '18 at 14:47
  • what is configFile["R"]? – Juraj Oct 1 '18 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.