Device ID & credential obtained from EEPROM

I’m just wondering - is there any easy solution, how to save respective device credentials not directly into the code as constant, but read them from device’s EEPROM? I mean I have a pool of devices, which I want to load with the same firmware and their respective specific parameters (device id, credential, OTA update address, wifi ssid, wifi password…) load from each device’s EEPROM.

Thank for advices!

Hi @Tomas, this is possible, and it fact it is actually done inside the ThingerWebConfig when the user configures the device id and credential from a web page. Take a look on this code from the library. But the code is basically the following. It is using the filesystem from ESP8266 and writing a pson file, so you can store any data you want easily. Hope this helps!

class pson_spiffs_decoder : public protoson::pson_decoder{
public:
    pson_spiffs_decoder(File& file) : file_(file)
    {
    }

protected:
    virtual bool read(void* buffer, size_t size){
        size_t read = file_.readBytes((char*)buffer, size);
        protoson::pson_decoder::read(buffer, read);
        return read == size;
    }

private:
    File& file_;
};

class pson_spiffs_encoder : public protoson::pson_encoder{
public:
    pson_spiffs_encoder(File& file) : file_(file)
    {
    }

protected:
    virtual bool write(const void* buffer, size_t size){
        size_t wrote = file_.write((const uint8_t*)buffer, size);
        protoson::pson_encoder::write(buffer, wrote);
        return wrote == size;
    }

private:
    File& file_;
};

// reading config from file system
THINGER_DEBUG("_CONFIG", "Mounting FS...");
if (SPIFFS.begin()) {
    THINGER_DEBUG("_CONFIG", "FS Mounted!");
    if (SPIFFS.exists(CONFIG_FILE)) {
        //file exists, reading and loading
        THINGER_DEBUG("_CONFIG", "Opening Config File...");
        File configFile = SPIFFS.open("/config.pson", "r");
        if(configFile){
            THINGER_DEBUG("_CONFIG", "Config File is Open!");
            pson_spiffs_decoder decoder(configFile);
            pson config;
            decoder.decode(config);
            configFile.close();

            THINGER_DEBUG("_CONFIG", "Config File Decoded!");
            strcpy(user, config["user"]);
            strcpy(device, config["device"]);
            strcpy(device_credential, config["credential"]);

            thingerCredentials = true;

            THINGER_DEBUG_VALUE("_CONFIG", "User: ", user);
            THINGER_DEBUG_VALUE("_CONFIG", "Device: ", device);
            THINGER_DEBUG_VALUE("_CONFIG", "Credential: ", device_credential);
        }else{
            THINGER_DEBUG("_CONFIG", "Config File is Not Available!");
        }
    }
    // close SPIFFS
    SPIFFS.end();
} else {
    THINGER_DEBUG("_CONFIG", "Failed to Mount FS!");
}

// writing config file
THINGER_DEBUG("_CONFIG", "Updating Device Info...");
if (SPIFFS.begin()) {
    File configFile = SPIFFS.open(CONFIG_FILE, "w");
    if (configFile) {
        pson config;
        config["user"] = (const char *) user;
        config["device"] = (const char *) device;
        config["credential"] = (const char *) device_credential;
        pson_spiffs_encoder encoder(configFile);
        encoder.encode(config);
        configFile.close();
        THINGER_DEBUG("_CONFIG", "Done!");
    } else {
        THINGER_DEBUG("_CONFIG", "Failed to open config file for writing!");
    }
    SPIFFS.end();
}

Thank you for your swift reply @alvarolb ! This part I basically have done, just don’t know what to do next - how to call the thinger init with my parameters in variables before I can use

thing.add_wifi(SSID_NAME, SSID_PASSWORD);

At this moment, the easiest thing is to modify the ThingerClient.h, adding a new method, like:

public:
    void set_credentials(const char* username, const char* device_id, const char* device_password){
        username_ = username;
        device_id_ = device_id;
        device_password_ = device_password;
    }

You can just initialize the device with empty strings:

ThingerESP8266 thing("", "", "");

and just call the set_credentials in setup:

thing.set_credentials(user, device, device_credential);

I think that this can be an interesting use case, so I can add this feature to the library in further updates with support for empty constructors.

Notice that you should keep now the credentials read from eeprom in some global variables. You can just define them in your sketch like the following, as it is done in the ThingerWebConfig.

char user[40];
char device[40];
char device_credential[40];
3 Likes

Wow, that’s exactly what I needed! Thanks a lot!