Thank you for your feedback. I have read your arguments and the ones in the open issues I linked previously and there are all valid concerns. I am aware that there are some workarounds as well some of which I am using myself at the moment.
I have compiled some use cases below, workarounds with current OH, some issues with these workarounds and some potential solutions (probably a separate post would be better).
Task: Access the item lastUpdated timestamp
Why:
- Reason about whether the virtual state reflects the real physical state of a sensor.
- In the UI: Show NULL/UNDEF (âunknownâ) instead of the last stalled state the system received from the sensor or show the last update timestamp so that the users reason themselves.
- In rules:
- Take a different decision based on the time passed since the last update (e.g. due to low confidence that this is the real state at this moment).
- Attempt to refetch the state (if the binding/api provides an on-demand âpullâ method)
How to achieve with OH3
- If the item update is the reason of a rule trigger, then assume it just updated/changed ânowâ. This may be some milliseconds off which in most cases is not an issue.
- Enable persistence services with an everyUpdate strategy. Then you can use persistence extensions such as
<item>.lastUpdate
and <item>.updatedSince(ZonedDateTime)
- For the UI, I am not aware of a solution to show NULL/UNDEF (âunknownâ) instead of the last stalled state (use the âexpireâ profile maybe?). In order to show the lastUpdate from persistence so the users can reason themselves, is it possible to show it with a custom widget?
Issues with the current approaches
- Issues with solution 1
- This does not work if you want to reason about the state of an item which is not part of the rule trigger (rules that run on schedule, or rules that are triggered by a different item change or multiple items).
- Issues with solution 2
- OpenHAB is already a âstatefulâ framework which keeps the Items registry and their state in memory. You shouldnât need persistence services enabled in order to access just the last updated timestamp of an item. If the timestamps were stored in-memory together with the state you could just access them by .lastUpdate or a similar interface.
- Persistence services have an overhead (disk space, disk writes, query latency to access the timestamp) which may be an issue in some use cases such as with high frequency updates or high frequence checks for the state. You have to enable âonEveryUpdateâ strategy in order to be able to retrieve the last update timestamp which increases the overhead of the persistence service.
Proposed solution
- Save lastChange and lastUpdate in-memory along with the Item state so it is available in rules and the UI without persistence queries.
Task: Ingest the real lastUpdate/lastChange timestamp from a binding or the REST API.
Why:
- a binding/script may be configured to send the last state change/update to OH on schedule (e.g. every hour). The same binding may have access to the real timestamp of the last change/update (e.g. a specific timestamp within the previous hour).
- For the use-cases mentioned in the previous row (what to show in UI and what decision to take on rules) it would be helpful if the real timestamp was available instead of âingestion/systemâ time.
Use-cases:
- Battery-powered devices or devices with data-caps (e.g. NarrowBand, special SIM cards for trackers etc.) may be configured in this way to save battery or data transmission volume.
- mobile devices that keep the last state in a buffer until network connection becomes available.
How to achieve with OH3
- Use a different channel and different item to retrieve and store the value of this timestamp. E.g. a DateTime-type Item named ârealLastChangeâ could be used if such a channel is made available by the binding (or with the REST API from a rule if this info is available by other means).
- Use the REST API
/persistence
endpoint along with a ModifiablePersistenceService to store the state with the real lastUpdate/lastChange timestamp in the database. This is also available in Habapp (uses the same endpoint).
Issues with the current approaches
- Issues with solution 1
- Multiple items for attributes of the same state update/change which may not update atomically and are saved with different timestamps in the persistence database. You have to perform a 2nd persistence query to retrieve the DateTime item state but this is not guaranteed to have the same timestamp with the primary item so it is difficult to join reliably.
- Issues with solution 2
- The state kept in the OH in-memory registry does not reflect the state stored in the database since OH was bypassed in order to save the correct timestamp in the database. Therefore, the last value shown in a chart may be different that what is shown in an Item card. If you attempt to also send a postUpdate or sendCommand to an item, then duplicates will be written to the database (one with the real timestamp and another with the system time).
- Another issue is that currently this can only be used with the REST API and not with an official OH interface used by the bindings (the argument is that bindings, by design, should only update things and channels and not items).
Proposed solution
- Allow bindings (and optionally rules) to send the real timestamp of lastChange and lastUpdate to OH through standard interfaces (e.g. extra argument in postUpdate or similar methods).
- Store these timestamps in-memory along with the Item state
- use these real timestamps instead of ânow()â in persistence services that support ModifiablePersistenceService.
Questions:
- What to do if the new timestamp is before the currently stored lastUpdate/lastChange timestamp?
- Only persist: I would choose to persist this timestamp,state pair but I would not update the current state of the item.
- What to do when the new timestamp is in the future?
- Only persist: I would choose to persist the value in the DB but as above I would not update the current state of the item.
Therefore, if newMsg.lastUpdate <= item.lastUpdate || newMsg.lastUpdate > now
then just persist, otherwise both persist and update the current state (and timestamps).
Task: Ingest multiple historical states from a binding or the REST API.
Why: (extension of the previous use-case)
- A mobile device has lost internet connection but in the meanwhile it is able to read the state from connected sensors (e.g. GPS). It has the capability to keep these states in a local buffer and send them to OH when the network is available. It would be helpful to be able to send these updates to OH and persist them in the database in order to:
- visualize in the UI
- troubleshoot by having access to the whole measurements history (through the logs or the database)
- use in advanced rules that take into account multiple historical states (e.g. train/extrapolate).
How to achieve with OH3
- Use the REST API /persistence endpoint along with a ModifiablePersistenceService to store the historical states with the real lastUpdate/lastChange timestamp in the database. This is also available in Habapp (uses the same endpoint).
Issues with the current approaches
Same issues as previously but mainly for the last value:
The state kept in OH in-memory registry does not reflect the state stored in the database since OH was bypassed in order to save the correct timestamps in the database. If you attempt to also send a postUpdate or sendCommand to an item (for the last âcurrentâ state) then duplicates will be written to the database (one with the real timestamp and another with the system time).
Another issue is that currently this can only be used with the REST API and not with an official OH interface used by the bindings (the argument is that bindings, by design, should only update things and channels and not items).
Proposed solution
Same as the proposed solution for the previous task.
Task: Ingest future states from a binding or the REST API.
Use cases:
- Next day/week hourly electricity prices which can be used to schedule activities with the lowest cost
- Predictions from bindings or rules
How to achieve with OH3
- Use the REST API /persistence endpoint along with a ModifiablePersistenceService to store the future states in the database.
Issues with the current approach
This can only be used with the REST API and not with an official OH interface used by the bindings.
Proposed solution
Same as the proposed solution in the previous 2 tasks (just persist if timestamp is in the future).
Apologies for the long post, it would probably be better to make a separate thread.