Variable refreshInterval / retrying

Hi All,

I’m brainstorming ideas for a problem right now, let me try explain:

Background
The Australian electricity market trades in 5 minute blocks - with pricing being finalised generally in the 1st 30 seconds of each interval. Each interval starts/finishes on the 5min (ie 9:00 - 9:05, 9:05 - 9:10, etc)

Problem Statement
The Amber API has a flag in the stanza for current pricing, indicating whether or not the price has been finalised, ie:

  {
    "type": "CurrentInterval",
    "date": "2025-06-07",
    "duration": 5,
    "startTime": "2025-06-07T07:10:01Z",
    "endTime": "2025-06-07T07:15:00Z",
    "nemTime": "2025-06-07T17:15:00+10:00",
    "perKwh": 32.51091,
    "renewables": 109.565,
    "spotPerKwh": 15.18,
    "channelType": "general",
    "spikeStatus": "none",
    "tariffInformation": {
      "period": "shoulder",
      "season": "default"
    },
    "descriptor": "veryLow",
    "estimate": false
  },

The problem is that until the price is finalises, the ‘Current’ price cannot be trusted for automations.

possible solution

  • Continue to refresh every 1 minute.
  • If current price has estimate == true, startup another scheduler for 15 second refresh and once estimate == false, cancel this scheduler

Any other ideas? The Amber API is ratelimited - so I need to be somewhat mindful of not hammering their API.

The other thought is some way to schedule refreshes around the 5 minute intervals, and sleeping once estimate == false until the next 5 minute interval starts?

I guess something like a loop with

Thread.sleep(10000); 

between retries could also work… Scheduler might be better though.

GitHub - psmedley/openhab-addons at amber-estimates has a potential solution.

TBD to check the number of loops - atm I’m assuming a 60 second refreshInterval so allowing for up to 5 retries.

Edit: this actually works better than I thought. the 10 second sleep helps ‘shift’ the refreshes:

2025-06-08 10:50:15.003 [INFO ] [ectric.internal.AmberElectricHandler] - Price estimated, sleep 10 seconds and try again.
2025-06-08 10:50:26.273 [INFO ] [ectric.internal.AmberElectricHandler] - Price not estimated, break out of loop.
2025-06-08 10:51:27.272 [INFO ] [ectric.internal.AmberElectricHandler] - Price not estimated, break out of loop.
2025-06-08 10:52:28.198 [INFO ] [ectric.internal.AmberElectricHandler] - Price not estimated, break out of loop.
2025-06-08 10:53:29.186 [INFO ] [ectric.internal.AmberElectricHandler] - Price not estimated, break out of loop.

So in the above snapshot, a single ‘sleep’ made a shift in the refresh time such that prices were ‘always’ non-estimates, and in the 3.5 hours since, no further sleep’s have been required :slight_smile:

I would need a bit more info to make my best recommendations on algorithms. How often does the price actually change significantly? Does it often go from high to low and vice versa between neighboring intervals, or is it generally a more gradual change. What kind of changes do you make in your system based on the price?

If the prices change gradually, then using the price from the previous interval for part of the time probably is negligible, but if they change significantly in some intervals then having the exact current intervals price is much more important.

The results you show above seem ok, but the big thing I notice is that they shift a second later within the minute every cycle. That may not seem like that big of a deal, but for something running around the clock it will gradually shift the query to the middle of the energy cycle and then gradually to the end. So your price value will be 2, 3, 4 minutes late until you eventually start querying in the time period where the price is just an estimate again.

If I didn’t care too much about a few seconds, I would probably just target 30 seconds after the interval starts with a cron type scheduler. If that works consistently and never gives estimated values, I’d leave it there and call it good enough.

If those 30 seconds are important, I’d do similar to what you did. Start querying at some point where it’s possible the price could be liked it. If you sometimes get locked results at 2 seconds, start there. Otherwise ease it back to 5,10, etc. If the first query doesn’t get it, repeated after an interval and then stop. The main difference from your algorithm is that I’d start at an exact number of seconds after the energy interval starts rather than basing it on an amount of time after you got it for the previous interval. The thing is, if you always are sure to get it at 30 seconds, a 10 second wait is not going to give you many additional queries before you’re guaranteed to get it. If you think 10 seconds is the right wait after the first try, maybe just hard code checks at 2, 10, 20, and 30 seconds after the interval start. For each of the checks after the first one, exit without making the api call if you already got a locked in value.

One other thing to think about is when the result is usually locked in. If it’s almost always locked by 7 seconds, you might try hard coding checks at 2, 5,6,7,8, then back off a bit, 10, 20, 30.

There are so many ways it could be done. I think the answers to some of the questions in my first paragraph can help guide the decisions you make as you think through it.

The price can change a LOT in 5 minutes. AEMO (The Australian Market regular) ‘caps’ prices at just under $20 AUD/kWh but they can also be as low as -$5 AUD/kWh. If there is a spike due to a shortage of generation, prices can easily jump from $0.10 AUD/kWh to being several dollars.

At the start of each period, the price is ‘estimated’ but once changed to ‘actual’ will be locked in for the remainder of that period.
In terms of automations, I use this pricing to determine whether to charge the battery or the car as well as influencing HVAC settings.

I’m currently polling every minute - so even with drift, at worst I’m 1 minute late - which is not ideal, but doable.

Edit: CronScheduler (openHAB Core 5.0.0-SNAPSHOT API) is probably a better solution. Running with ‘8 0/5 * * * ? *’ or something to run 8 seconds after the 5 minute and retry if estimate…

Edit2: Apparently “Actual prices are generally confirmed around 15 seconds into the interval, whereas forecast aren’t ready until around 45 into the interval.”