bluerange-io / bluerange-mesh

BlueRange Mesh (formerly FruityMesh) - The first completely connection-based open source mesh on top of Bluetooth Low Energy (4.1/5.0 or higher)
https://bluerange.io/
Other
287 stars 109 forks source link

best way to save custom data permanent #153

Closed NilsMinor closed 3 years ago

NilsMinor commented 3 years ago

Hi,

I want to save custom data on my device (like two node ids and some settings). What is the best way to save this kind of data in the flash that is loaded on the module start?

Thanks, Nils

mariusheil commented 3 years ago

Hi,

take a look at the other modules. You should fill the xxxModuleConfiguration struct with the data types you need. Then, I am not sure where you will receive the data, if it is data that you receive over the mesh or just some data that you want to save at some point. Then you only need to call Conf::SaveConfigToFlash (you can give an optional listener if you want to and you can pass some optional identification data for that callback).

That's it, basically. The Configuration will automatically be loaded on startup in your struct and you can access it. Take a look here and play around with these commands to store and load the config over the mesh: https://www.bluerange.io/docs/fruitymesh/Modules.html#_module_configuration

This will be deprecated as it is better to set the module configuraton using single commands and not the generic set_config command. But it will help you understand the stuff.

Marius

NilsMinor commented 3 years ago

Hi Marius, thanks for your response. I tried your approach and I think it is exact what I want. I used the Configuration struct and added it with my two field like :

struct InukModuleConfiguration : ModuleConfiguration{
            //Insert more persistent config values here
            u16 previousLightId;
            u16 followingLightId;
        };

And I call this an module start :

InukModule::InukModule()
    : Module(ModuleId::INUK_MODULE, "inuk")
{
    //Register callbacks n' stuff

    //Save configuration to base class variables
    //sizeof configuration must be a multiple of 4 bytes
    configurationPointer = &configuration;
    configurationLength = sizeof(InukModuleConfiguration);

    logs("Partner IDs are previousLightId :[ %u ] followingLightId : [ %u ]" ,
        (u16) configuration.previousLightId, 
        (u16) configuration.followingLightId);

    //Set defaults
    ResetToDefaultConfiguration();

}

I was not able to use the Conf:: method but I tried to call it from GS:

void InukModule::setPartnerLights (u16 previousLightId, u16 followingLightId) {
    if (previousLightId) {
        configuration.previousLightId = previousLightId;
    }
    if (followingLightId) {
        configuration.followingLightId = followingLightId;
    }

    GS->config.SaveConfigToFlash(nullptr, 0, nullptr, 0);

    logs("Partner IDs are previousLightId : [ %u ] followingLightId : [ %u ]" ,
        (u16) configuration.previousLightId, 
        (u16) configuration.followingLightId);
}

I get this from my device so it seams to write the config to the flash:

[InukModule.cpp@182]: Partner IDs are previousLightId : [ 1111 ] followingLightId : [ 2222 ]
[FlashStorage.cpp@303 FLASH]: Flash operation success
[MeshAccessConnection.cpp@703 MACONN]: Decrypting FB:CE:56:03:F0:9B:B3:A9:33:83:F4:21:CF:64:A9:5B (16) with nonce 888532507
[MeshAccessConnection.cpp@761 MACONN]: Decrypted as FB:CE:56:03:F0:9B:B3:A9:33:83:F4:21 (12) micValid 1
[MeshAccessModule.cpp@656 MACONN]: Message auth is 1
[MeshAccessConnection.cpp@1092 MACONN]: Received data for local mesh 33:00:7D:F0:06:CD:00:02:57:04:AE:08 (12) from 3776 aka 3776
[RecordStorage.cpp@183 RS]: SaveRecord id 8, len 43
[InukModule.cpp@182]: Partner IDs are previousLightId : [ 1111 ] followingLightId : [ 2222 ]

Is this the right way to store config data btw. custom user data? Thanks, Nils

mariusheil commented 3 years ago

Hi,

yes, calling it from the Global state is correct, I just copy pasted the definition name of the method. This is the correct way to store data, you should see that the data is automatically loaded and then the ConfigurationLoadedHandler is called. You can always extend the struct later, but must never change the order or remove a variable. Otherwise you must increase the config version and migrate the data yourself

Marius

NilsMinor commented 3 years ago

Ok I understand that I should not change the struct order or I need to migrate my data. Mhh I just tested my code again, it seams to store the data correctly as it prints out Flash operation success but the data is not loaded in the configuration handler. I tried to print out the loaded message from the ConfigurationHandler and also InukIOModule() but the data is not loaded into my struct. Do I need to make other changes in order to save and load the configuration ? Thanks :)

mariusheil commented 3 years ago

Hi,

sorry, it looks like I pointed you to the wrong place, you should have used the Utility method "Utility::SaveModuleSettingsToFlash" for storing the config of your module. What you did was telling Config.cpp to store its own configuration to flash. That was not intended. We had this refactored some time ago.

Makr sure that the recordid that is saved "[RecordStorage.cpp@183 RS]: SaveRecord id %u, len %u" matches your moduleId, then it should be correct.

Marius

NilsMinor commented 3 years ago

@mariusheil like always, you great support solved my problem :) it is working now !