On-demand save to flash

I’ve been wrestling with a particular esphome challenge for about a week now on and off, and haven’t found a good answer.

I’m developing a display that’s intended to be connected to, configured once, then disconnected/powered off and moved to a remote location immediately. This means that I have two classes of configuration:

  • Configuration that will be set once (or very infrequently), and wants to be immediately written to flash when changed (so as not to be lost when the device is powered off immediately after configuration).
  • Configuration that will change regularly as a user interacts with the device, but which can be lazy-written to flash as per flash_write_interval.

I’m utterly failing at finding a way to accomplish this. If I set flash_write_interval to say 1s, then the first type of configuration will be taken care of, but I’ll wear out the flash pretty quickly with the second while the user is interacting normally with the device.

Alternatively, I have to live with a 60s flash_write_interval, but then a user has to wait up to 1 minute after making a configuration change before they can power off the device; this is a very poor UX for something I hope to productise.

Is there a way that I’ve missed of either:

  • Changing flash_write_interval on a per-variable basis?
  • Providing a template button that can trigger an on-demand flash write from the web interface?

Because of the nature of the device, I don’t want to depend on the assumption that I can save some state in homeassistant - all state must be saved on the device itself.

Many thanks

What’s your math for that? Or is that just some some assumption?
Independently what your interval is, flash is written only if there’s something to write.

Are you waiting for the interval to expire before the flash write occurs? Why?

Any reason why you have to write to internal flash?

No code, no user case, not much except guessing. Post some code [correctly formatted for forum </> readability please] and tell us what you really want to do and we may be able to make suggestions.

If I set the update threshold to be 1s, then the flash will wear out 60x faster than with it set to 60s.

If I assume that the internal flash endurance is 100k cycles (this is what espressif spec it as), then my product will last 100k seconds powered on; this is about 30h, which is unacceptable. Even if I assume that a write is only made if some persistent variable has changed, then I’ll still be talking a write every 5 seconds in the worst case (up to every 5 seconds, something that will want to be persistent will be updated in normal use).

So I cannot just set the flash_write_interval to be really short.

I’m not sure what you mean. ESPHome allows one to set a flash write interval, which means that changes to entities are only written after an interval rather than immediately. This is essential, as I have many things that I want to be mostly persistent (i.e. I don’t care if the thing that comes back up after a power cycle is slightly out of date, but I don’t want to lose all the state).

Because I only have internal flash available.

I have no idea what code I could post that would be useful; I have described exactly and fully what I am trying to achieve - a way to store a snapshot of the current state to flash on demand. Is there anything you think I could post that would further enlighten you?

Sorry, have absolutely no idea what you are trying to do, so can offer no help.

Not even sure if you are asking a question or just documenting your voyage of discovery as to why writing to flash very often may not be a very good idea.

You may have trust issues with your data, or making the wrong assumptions. HomeAssistant may be where you should be storing those fleeting data values, rather than flash.
I will leave it to the other crystal ballers to assist you.

So you expect that with defautl 60s interval your esp would die in 60x30h, in two months and half?
Fortunately it doesn’t go like this and even with 1s interval you get several years. NVS is 24kB if I remember well, writing 4bytes variable there 6000 times would make one cycle. Over simplified example, it’s pretty complicated system.
Anyway if you manage to destroy your flash, let us know. I have not heard of one case here yet.

In any case if the value is identical to the stored value, it doesn’t get re-written, so if the value changes infrequently the flash gets written infrequently regardless of the interval.

2 Likes

As far as I can tell, I’ve been pretty clear what I want to achieve, and what I have tried already.

As I said, I can make no assumption that HA will be available, I cannot use HA to store any state.

I don’t understand what additional information you think I could give you that would be useful.

Perhaps you feel that way, but clearly others do not.

Which esp are you using? The answer likely differs based on the chip esp8266 vs esp32 (and possibly the other variants)

You answered your own question.

I believe you are confused about 1s means. @clydebarrow said the flash is only written when something changes. This is where the rest of what you are doing matters. If you are taking readings every second AND they change every second AND you have many of them THEN yes maybe you will wear out the flash too quickly.

I have found nothing documented about how to initiate the save to flash, but I suspect there is a function call that does it. Since this is open source it is easy enough to search and find it. Then it might be possible to have a button that calls a lambda function to call that function to save to flash right now so you can resolve your 1st case configuration need and keep the flash write interval for normal use at a more likely to survive for a long time.

So, exactly which problem do you need help with? There is nothing documented that does what you asked in the question above. So the answer to it is, “you are correct, there is no documented way to have two different flash write intervals and no way to specify what gets which interval”.

Assuming (always a bad idea) that flash interval works for your normal case, there is no documented way to say “save to flash now”. But, I suspect with some research it probably is possible to get something that might work in some cases.

line 42-47

  /**
   * Commit pending writes to flash.
   *
   * @return true if write is successful.
   */
  virtual bool sync() = 0;

global_preferences->sync();
might work here…