Why is persistence.lastUpdate() not always working

Hi everyone,

I’m encountering an issue with the persistence.lastUpdate() function not returning the expected result. I have the following setup:

  • Item: Illuminance_Garden_MiFlora1 is persisted, and I can see the data in the persistence store:
ItemId  ItemName
59      Illuminance_Garden_MiFlora1

Time                      Value
2025-01-24 00:00:01.375    115

In my script, I have:

let itemNames = ["Illuminance_Garden_MiFlora1"];
let itemNamesPresence = ["Switch_Garden_MiFlora1_Presence"];

for (let i = 0; i < itemNames.length; i++) {
    var itemName = itemNames[i];  // Item to monitor
    var itemNamePresence = itemNamesPresence[i];
    
    var last10Minute = time.ZonedDateTime.now().minusMinutes(10);
    var lastUpdateTime = items.getItem(itemName).persistence.lastUpdate();

    console.log("Testlastupdate" + lastUpdateTime);
}

However, when I check the logs, I see:

[ab.automation.script.file.miflora.js] - Testlastupdate null

My question: Why is persistence.lastUpdate() returning null in this case? The item Illuminance_Garden_MiFlora1 is correctly persisted, and I can see the timestamp and value in the persistence store.

I also noticed that if I add the following persistence strategy to Illuminance_Garden_MiFlora1:

Illuminance_Garden_MiFlora1: strategy = everyChange, everyMinute, everyDay, restoreOnStartup

then persistence.lastUpdate() works as expected and doesn’t return null.

or reference, my standard persistence rule is:

*: strategy = everyDay, restoreOnStartup

Has anyone encountered a similar issue or knows why this might be happening? I’d appreciate any help!

Thanks in advance!

If your persistence service is rrd4j, you must use everyMinute strategy, otherwise rrd4j does not work properly.

In the current logic, the persistence.lastUpdate() call will return null if the current state of the item is different from the last persisted state. The logic is that there must have been a state update since, but it has not been persisted, so rather than giving a wrong answer, null is given as an answer.

items.getItem(itemName).persistence.persistedState(time.ZonedDateTime.now()) should always give you the answer.

By persisting on everyChange you would avoid the problem in most cases, because every change will be written in persistence. There could still be a timing issue due, if a new state didn’t finish persisting before the lastUpdate() call, so still resulting in null.

This has heavily been debated before. There is a PR to make a getLastStateUpdate method available directly on the item state without requiring persistence. That would allow to revert this implicit assumption in persistence, and would be a better way to get the last update of an item, without relying on persistence.
See Add `getLastStateChange`, `getLastStateUpdate`, and `getLastState` to GenericItem by jimtng · Pull Request #4351 · openhab/openhab-core · GitHub

3 Likes

Is actually previousState() the same like persistedState(time.ZonedDateTime.now())?

No, it’s not. previousState is the state before the current State. It will look back until it finds a State different from the current one.

And persistedState(time.ZonedDateTime.now()) is the last persisted one, but it could be different to the current state?

Is there an easier way to get the last persisted state instead persistedState(time.ZonedDateTime.now()) ?

This will solve the issue,??

With this and a related change, getLastUpdate() will again return the last update from persistence, not trying to interpret for the persisted state being different from the current state. This has been merged and will be in OH 5.
At the same time, the item object has been enhanced so it is possible to directly get the last update without relying on persistence for it. This is much more reliable.

The PR referenced only builds on that already merged work, also making it available in events.

1 Like

Do you know how to get the current and last persisted state in OH4? Not the non-persisted value, which might be different to the persisted one.

Current state is the item state, last persisted state would be persistedState(time.ZonedDateTime.now()).