-
-
Notifications
You must be signed in to change notification settings - Fork 428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow sending historic states and forecasts #3597
Conversation
This pull request has been mentioned on openHAB Community. There might be relevant details there: |
@openhab/core-maintainers and especially @kaikreuzer (since we discussed about this issue in the other PR), I have some questions:
|
e347f51
to
9633490
Compare
Hey @J-N-K, thanks for picking up this topic.
|
|
|
My idea was to make it as comfortable as possible for users:
In both cases all values will be persisted (if possible), without checking if they are in the past or the future. That probably depends on the persistence service. Regarding replacing single values and keeping others: We should have a look at the possible use-cases
What would in your opinion be a case where we would have the mixed case and need replace single values while keeping others? |
It might be that I haven't yet fully understood the technical difficulties that there are with storing values for timestamps, when there is already a persisted value for this timestamp. My hope was that it should be possible with every db to simply update existing values, which then essentially results in an "update or add if not existent" functionality. |
If we use
So the real benefit of
a) Currently difficult, because there is no way for a binding to get access to historical data (Edit: Thinking about it this is not possible at all. Persistence is done on an item and bindings do not have any knowledge about items. Reading channels from bindings is not possible, because several items could be linked to the same channel). But I don't see an issue here, let's say we have (timestamp/value)
The value 115/1000 is clearly an outlier. With the current implementation storing a time-series with REPLACE policy and a value set of
will result in
which is probably the expected result. This works, because the first value in the "update" has a timestamp 110, the last one has 125. Before persisting the values, all values with timestamps in this range are removed (because the policy is REPLACE). b) See above: If the new forecast only includes values for tomorrow, the day after tomorrow stays the same, because REPLACE only affects the time-range of the enclosed time-series. The difficulty is that this heavily depends on the service itself how and if values can be updated/replaced. For MySQL Replacing by |
@jlaur Since you are working on a binding that sends forecasts, do you think this is working for you? |
@openhab/add-ons-maintainers I would like to hear your thoughts on this. |
I started getting back to this topic and also had an initial look on some of the code. If I understand it correctly, the scope and objective (for now) is to provide a way for bindings to publish historic/future states in order to persist them, and nothing else - correct? For openhab/openhab-addons#14376 this would mean that it will be possible to persist future prices. This would allow users to see graphs in the future. Again, if I understand it correctly, only persistence will gain "access" to them, so until something like #3478 is implemented, this is the scope. So for now they cannot be used for calculations, for example - in rules or anywhere else, right? I'm not making any points, just trying to establish the scope for my own understanding. 🙂 I would need to add the time series update to the binding, but I should keep the hourly job for updating current price, so this is still pushed to the event bus. With persistency strategy everyUpdate, items will be persisted in advance by time series, but also each hour as the prices become actual? Example - now is 20.05.2023 13:15. Time series update of spot price:
Hourly job is the triggered at for example 14:00:00.030 and will update:
So I will now have this persisted:
(whereas today the end result would be only 20.05.2023 14:00:00.030: -0.00067) But this can be prevented by using the forecast policy, correct?
Can you elaborate a bit here? I don't fully understand the criteria for accepting to persist, i.e. the "if the system time is equivalent to a previously send timestamp" part.
I'm not sure I understand the purpose of the policy. Why would we need anything but REPLACE? If I update the state normally (not as time series), the latest value will always replace the previous value. I would intuitively expect the same for states having a timestamp, i.e. time series.
I'm not sure, but perhaps if it would be simpler and safer to remove all values >= the first received timestamp? Replacing something "in the middle" could be tricky. For example, weather forecast 1:
Now, weather forecast 2:
With the second forecast, the expected temperature decreased by 1 °C, but the increase was moved forward from 13:00 to 12:00. This is now the full amount of information. So this is wrong:
|
Rules should be able to use them, you should be able to use something like Using them in charts is also already possible (with the default chart provider), at least if you set begin/end dates. "period" needs an extensions, so we know if "1D" is [now-1d,now] or [now,now+1d]. I'm not sure about the best syntax for that. @lolodomo since you are more familiar with sitemaps: any good idea?
No, with Only the
For forecasts always
As @kaikreuzer pointed out above: What if we have a forecast for a week and then receive a "better" forecast for tomorrow. If we replace all future values, we'll add information for tomorrow, but lose the information for the day after tomorrow. IMO the way it is now is more flexible. |
I guess there could be a need to extend
👍
Okay, so I misunderstood. For the EDS binding I could then completely remove the hourly job updating current prices, since state updates will automatically be pushed to the event bus as they become current? One question, though: Will this require persistence, or will time series be stored in memory also? If not, then I think I would still update states manually as they become current so that the channels can be used without persistence. There is some redundancy here, but I think it would be needed. Users would then either not configure any persistence and just get current values provided by the binding, or they would configure persistence with the
OK, so this is to prevent overwrites after being unsynchronized?
Perhaps we could consider a method overload to control this behavior? I guess the desired behavior can vary. @kaikreuzer's scenario sounds like a mix of a 1 day forecast and a week forecast. I'm not into weather services, but from the weather web UI's I can remember, the short-term and long-term forecasts are two different things. So if mixing them, yes, the short-term forecast could overwrite the long-term forecast. |
There was a PR for that, that was unfortunately closed: #3466
Exactly.
This requires persistence, but I think this can be noted in the documentation. I was already thinking about some sort of "in-memory-persistence" service, that could be used to achieve that.
Exactly. An example would be a network-attached energy meter. The binding could then send missed data as
How do you imagine that to work? The problem is that a binding can never know what was configured by the user. The user could link two channels (the one with daily forecasts and the one with hourly forecasts) to the same channel, in that case "replace the future" would be wrong. |
The only issue I see here is that in any case this would require the user to configure persistence in order to use the basic and most important channels in the binding. But it can be easily worked around by just keeping the hourly update job in the binding and still update the state the old-fashioned way for backwards compatibility and "out of the box" functionality without persistence configured. The data is already cached in the binding anyway to reduce network calls and to be used by calculations. I'm now also thinking about an interesting case for time series, namely the update of electricity taxes and net transmission tariffs, since this data is very static in nature. Here I may push a time series with very few states valid months into the future. Example: {
"total": 2,
"filters": "{\"ChargeType\":[\"D03\"],\"GLN_Number\":[\"5790000432752\"],\"Note\":[\"Elafgift\"]}",
"dataset": "DatahubPricelist",
"records": [
{
"ValidFrom": "2023-07-01T00:00:00",
"ValidTo": null,
"ChargeTypeCode": "EA-001",
"Price1": 0.697,
"Price2": null,
"Price3": null,
"Price4": null,
"Price5": null,
"Price6": null,
"Price7": null,
"Price8": null,
"Price9": null,
"Price10": null,
"Price11": null,
"Price12": null,
"Price13": null,
"Price14": null,
"Price15": null,
"Price16": null,
"Price17": null,
"Price18": null,
"Price19": null,
"Price20": null,
"Price21": null,
"Price22": null,
"Price23": null,
"Price24": null
},
{
"ValidFrom": "2023-01-01T00:00:00",
"ValidTo": "2023-07-01T00:00:00",
"ChargeTypeCode": "EA-001",
"Price1": 0.008,
"Price2": null,
"Price3": null,
"Price4": null,
"Price5": null,
"Price6": null,
"Price7": null,
"Price8": null,
"Price9": null,
"Price10": null,
"Price11": null,
"Price12": null,
"Price13": null,
"Price14": null,
"Price15": null,
"Price16": null,
"Price17": null,
"Price18": null,
"Price19": null,
"Price20": null,
"Price21": null,
"Price22": null,
"Price23": null,
"Price24": null
}
]
} In the binding this will cause the channel to be updated from 0.008 to 0.697 on 2023-06-30T22:00:00Z.
Just out of curiosity, what would be the harm in using REPLACE in this case?
I imagined assuming each channel in the binding to have a specific purpose so that the code would make that decision. But I get the point, if users would mix such channels into the same item, it can't work. But it also means we'll have no bullet-proof way of invaliding all future states, or did I miss something? |
IMO an example configuration for persistence would be fine. I don't think it's a good idea to mix hourly updates and forecasts on the same channel. If you want to keep that, you should probably add two channels one "forecast" and a second one "current". You can the update "current" every hour, and send the time-series to "forecast", with a note in the doc that this requires persistence. The user can then choose which one to use, but only "forecast" supports charting in the future.
This should be fine. I think we should probably add methods to send time-series from rules, so a simple HTTP request can be converted to a time-series.
That depends on the configuration. Maybe not in that case, but if you have an
Yes, I think we can't cover all cases. One thing we could do is allowing manually setting |
That would introduce a complete parallel universe where states differing only in timestamp (now vs. historic/future timestamp) cannot co-exist. I don't really like my own proposal to still have the redundant hourly job updating current prices, this would only be a (hopefully temporary) work-around because of the current dependency to persistence for publishing future states on the event bus when they become current. Ideally this would happen automatically without requiring persistence, but I didn't want to push for this now as it would extend the scope and required work. But I would like to hear your opinion about this. It would be like your "in-memory persistence" proposal, except it would be integrated and work independently of persistence configurations. It's not only a matter of requiring more configuration by the user, which of course can be documented. It's also the actual dependency, which feels strange if the user doesn't need persistence at all. It's still possible to display current prices and even perform useful calculations (within near past and until tomorrow) without any persistence. I even prepared for this with commit openhab/openhab-addons@3506e60. For me the channels are exactly the same, except that this PR makes it possible to update states ahead of time. There is no conceptual difference, it's just different ways of updating the same state - which of course also unlocks new possibilities. Keeping only the same set of channels, with the hourly job, my understanding is it would work like this (having duplicated state updates, i.e. hourly + time series): Non-persisted items or items configured with any policy other than
Persisted items with policy
I really think we should try to make this just another dimension of states and try to eliminate redundancy rather than adding more of it. Just a side note: I'm now also thinking about the "normalization" of prices. Let's say hourly tariffs will be A from 17:00-20:00 and B for all remaining hours - and this is valid for the next three months. That means that I actually have just one record for this three month period, but I'm pushing a state update two times per day, i.e. 17:00 (value A) and 20:00 (value B). Currently this is done by the hourly job, so it's not an issue. But if I would do this for three months ahead, it would be approximately 180 future state updates. I think in this case I would not do this, but limit the binding to only push time series until the end of tomorrow. You can't make much use of the tariffs anyway without also having the spot prices.
Wouldn't that result in the same problem where the short-term forecast would overwrite the long-term forecast if the user linked the two sets of channels to the same items? |
This pull request has been mentioned on openHAB Community. There might be relevant details there: |
Regarding persistence: I don't think that the requirement to configure persistence is too high. With #2871 we added core support for managing persistence from UI and we can provide example configurations in the respective binding doc (similar to the .things, .items, ... examples). With the proposed With my latest commit I also added support for sending |
Those methods are part of the |
Thanks! |
@J-N-K - congrats on the merge! 🚀 I was writing some documentation and considered linking to the persistence documentation. The And you are probably the best to describe it. 🙂 When running some tests I noticed mixed updates when using strategy
This was expected. However, after publishing new time series starting before and ending after this, this "odd" timestamp row was still present. In this case I probably expected it to be replaced by the time series. However, after then changing strategy to |
This pull request has been mentioned on openHAB Community. There might be relevant details there: https://community.openhab.org/t/best-approach-for-energy-consumption-usage-queries/151393/23 |
Is there already a complete documentation for this feature available? What I'm looking for is a InMemoryPersistenceService, a persistence service what is available only in RAM. |
@shikousa Please have a look here: openhab/openhab-addons#15063 What documentation would you expect? |
I think there will be in the future functions like this what can be used in Rules .store(ZonedDateTime,State) Should this be here? What I did not found is a function like .removePersistenceData(). Is this available? |
Implement time series support introduced by openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
Implement time series support introduced by openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
Refs openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
Refs openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
I'm not 100% sure. May I ask if we can use the InMemoryPersistenceService in rules and also add values with timestamps to it? |
Implement time series support introduced by openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
…5963) Implement time series support introduced by openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
…enhab#15963) Implement time series support introduced by openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]> Signed-off-by: Jørgen Austvik <[email protected]>
…enhab#15963) Implement time series support introduced by openhab/openhab-core#3597. Signed-off-by: Florian Hotze <[email protected]>
Fixes #844
Supersedes #3000
This is the implementation of the discussion results of #3000.
TimeSeries
which contains a collection of timestamp/state pairs and a policy (REPLACE, ADD). Timestamps can be anywhere in time (past and future).BaseThingHandler
has a new methodsendTimeSeries(ChannelUID, TimeSeries)
that can be used by bindings to send time series to items.TimeSeriesProfile
has been introduced, it extends theStateProfile
with a new methods to pass the time series to the item. Profiles that do not implementTimeSeriesProfile
do not pass time-series to the item, a warning is logged.GenericItem
has been extended with a newsetTimeSeries
method. The same logic that is used before a single state is set viasetState
is applied to each single value in the time series. Time series that do contain states that are invalid for the given item are discarded, otherwise listeners are notified and aItemTimeSeriesUpdatedEvent
is issued (similar to theItemStateUpdatedEvent
).everyUpdate
accept time series updates and persist them, when the service supports it (i.e. it implementsModifiablePersistenceService
). Even if the values are in the future, they are only persisted.forecast
has been added. Configurations with that strategy ONLY accept time series updates and set the item's state to the value if the system time is equivalent to a previously send timestamp. If this strategy is applied for a service that does not implementModifiablePersistenceService
, a warning is logged.