Install the binding http1 either in your addons.cfg file or using PaperUI
Configure an http cache in your http.cfg file:
Agile.url=https://api.octopus.energy/v1/products/AGILE-18-02-21/electricity-tariffs/E-1R-AGILE-18-02-21-B/standard-unit-rates/?page_size=48
Agile.updateInterval=14400000
You can do this without a cache but it will make multiple calls on the API; this method calls it once every four hours. You can’t specify a time to make the http call, only a refresh interval but this will call it at least once between 1600 and 0000 (the time between when it should be updated and when the current day’s data runs out.
Here’s a clunky way of populating a set of items by creating an item for each half hourly price:
Number AgilePrice2230 "Agile Price at 2230" { http="<[Agile:3600000:JSONPATH($.results[0].value_inc_vat)]" }
Number AgilePrice2200 "Agile Price at 2200" { http="<[Agile:3600000:JSONPATH($.results[1].value_inc_vat)]" }
Number AgilePrice2130 "Agile Price at 2130" { http="<[Agile:3600000:JSONPATH($.results[2].value_inc_vat)]" }
Number AgilePrice2100 "Agile Price at 2100" { http="<[Agile:3600000:JSONPATH($.results[3].value_inc_vat)]" }
Number AgilePrice2030 "Agile Price at 2030" { http="<[Agile:3600000:JSONPATH($.results[4].value_inc_vat)]" }
Number AgilePrice2000 "Agile Price at 2000" { http="<[Agile:3600000:JSONPATH($.results[5].value_inc_vat)]" }
Number AgilePrice1930 "Agile Price at 1930" { http="<[Agile:3600000:JSONPATH($.results[6].value_inc_vat)]" }
Number AgilePrice1900 "Agile Price at 1900" { http="<[Agile:3600000:JSONPATH($.results[7].value_inc_vat)]" }
Number AgilePrice1830 "Agile Price at 1830" { http="<[Agile:3600000:JSONPATH($.results[8].value_inc_vat)]" }
Number AgilePrice1800 "Agile Price at 1800" { http="<[Agile:3600000:JSONPATH($.results[9].value_inc_vat)]" }
Number AgilePrice1730 "Agile Price at 1730" { http="<[Agile:3600000:JSONPATH($.results[10].value_inc_vat)]" }
Number AgilePrice1700 "Agile Price at 1700" { http="<[Agile:3600000:JSONPATH($.results[11].value_inc_vat)]" }
Number AgilePrice1630 "Agile Price at 1630" { http="<[Agile:3600000:JSONPATH($.results[12].value_inc_vat)]" }
Number AgilePrice1600 "Agile Price at 1600" { http="<[Agile:3600000:JSONPATH($.results[13].value_inc_vat)]" }
Number AgilePrice1530 "Agile Price at 1530" { http="<[Agile:3600000:JSONPATH($.results[14].value_inc_vat)]" }
Number AgilePrice1500 "Agile Price at 1500" { http="<[Agile:3600000:JSONPATH($.results[15].value_inc_vat)]" }
Number AgilePrice1430 "Agile Price at 1430" { http="<[Agile:3600000:JSONPATH($.results[16].value_inc_vat)]" }
Number AgilePrice1400 "Agile Price at 1400" { http="<[Agile:3600000:JSONPATH($.results[17].value_inc_vat)]" }
Number AgilePrice1330 "Agile Price at 1330" { http="<[Agile:3600000:JSONPATH($.results[18].value_inc_vat)]" }
Number AgilePrice1300 "Agile Price at 1300" { http="<[Agile:3600000:JSONPATH($.results[19].value_inc_vat)]" }
Number AgilePrice1230 "Agile Price at 1230" { http="<[Agile:3600000:JSONPATH($.results[20].value_inc_vat)]" }
Number AgilePrice1200 "Agile Price at 1200" { http="<[Agile:3600000:JSONPATH($.results[21].value_inc_vat)]" }
Number AgilePrice1130 "Agile Price at 1130" { http="<[Agile:3600000:JSONPATH($.results[22].value_inc_vat)]" }
Number AgilePrice1100 "Agile Price at 1100" { http="<[Agile:3600000:JSONPATH($.results[23].value_inc_vat)]" }
Number AgilePrice1030 "Agile Price at 1030" { http="<[Agile:3600000:JSONPATH($.results[24].value_inc_vat)]" }
Number AgilePrice1000 "Agile Price at 1000" { http="<[Agile:3600000:JSONPATH($.results[25].value_inc_vat)]" }
Number AgilePrice0930 "Agile Price at 0930" { http="<[Agile:3600000:JSONPATH($.results[26].value_inc_vat)]" }
Number AgilePrice0900 "Agile Price at 0900" { http="<[Agile:3600000:JSONPATH($.results[27].value_inc_vat)]" }
Number AgilePrice0830 "Agile Price at 0830" { http="<[Agile:3600000:JSONPATH($.results[28].value_inc_vat)]" }
Number AgilePrice0800 "Agile Price at 0800" { http="<[Agile:3600000:JSONPATH($.results[29].value_inc_vat)]" }
Number AgilePrice0730 "Agile Price at 0730" { http="<[Agile:3600000:JSONPATH($.results[30].value_inc_vat)]" }
Number AgilePrice0700 "Agile Price at 0700" { http="<[Agile:3600000:JSONPATH($.results[31].value_inc_vat)]" }
Number AgilePrice0630 "Agile Price at 0630" { http="<[Agile:3600000:JSONPATH($.results[32].value_inc_vat)]" }
Number AgilePrice0600 "Agile Price at 0600" { http="<[Agile:3600000:JSONPATH($.results[33].value_inc_vat)]" }
Number AgilePrice0530 "Agile Price at 0530" { http="<[Agile:3600000:JSONPATH($.results[34].value_inc_vat)]" }
Number AgilePrice0500 "Agile Price at 0500" { http="<[Agile:3600000:JSONPATH($.results[35].value_inc_vat)]" }
Number AgilePrice0430 "Agile Price at 0430" { http="<[Agile:3600000:JSONPATH($.results[36].value_inc_vat)]" }
Number AgilePrice0400 "Agile Price at 0400" { http="<[Agile:3600000:JSONPATH($.results[37].value_inc_vat)]" }
Number AgilePrice0330 "Agile Price at 0330" { http="<[Agile:3600000:JSONPATH($.results[38].value_inc_vat)]" }
Number AgilePrice0300 "Agile Price at 0300" { http="<[Agile:3600000:JSONPATH($.results[39].value_inc_vat)]" }
Number AgilePrice0230 "Agile Price at 0230" { http="<[Agile:3600000:JSONPATH($.results[40].value_inc_vat)]" }
Number AgilePrice0200 "Agile Price at 0200" { http="<[Agile:3600000:JSONPATH($.results[41].value_inc_vat)]" }
Number AgilePrice0130 "Agile Price at 0130" { http="<[Agile:3600000:JSONPATH($.results[42].value_inc_vat)]" }
Number AgilePrice0100 "Agile Price at 0100" { http="<[Agile:3600000:JSONPATH($.results[43].value_inc_vat)]" }
Number AgilePrice0030 "Agile Price at 0030" { http="<[Agile:3600000:JSONPATH($.results[44].value_inc_vat)]" }
Number AgilePrice0000 "Agile Price at 0000" { http="<[Agile:3600000:JSONPATH($.results[45].value_inc_vat)]" }
Number AgilePrice2330 "Agile Price at 2330" { http="<[Agile:3600000:JSONPATH($.results[46].value_inc_vat)]" }
Number AgilePrice2300 "Agile Price at 2300" { http="<[Agile:3600000:JSONPATH($.results[47].value_inc_vat)]" }
The items are refreshed every hour so the maximum interval between the cached API return being updated and the item being updated is one hour. Once the API is updated with tomorrow’s values, this method will overwrite any remaining values for today with corresponding values for tomorrow.
There is no checking in this so it is dependent on the API always feeding the results in reverse order from the end of the day at 2300Z (=0000 CET, the time the electricity market day ends). If you specify a From and To time, you could potentially control the indexing (or create a situation where it is never right!)
You could then manipulate or read these items with rules or you could use a Group Function to get a minimum or average.
This method is way too clunky and error prone. I’m sure there’s a better way of doing this using rules on the whole JSON string returned from the API, including checking the “valid_from” date and time. The initial problem with that is that as from OpenHab 2.3.0, there’s a change to the JSONPATH transformation so you can’t grab multiple instances of “results” using JSONPATH ($.results) and extract individual results using indexing but you can grab the whole string using:
String AgilePrice "Agile Price JSON string" { http="<[Agile:14400000:NOTRANSFORMATION()]" }
It throws an error because NOTRANSFORMATION doesn’t exist but it then updates the item with the whole, untransformed string, which is what we want. You’ll get the error each time the item refreshes so every 4 hours in this example.
A bit more research required on the possibilities but I need to think about the use cases first to work out what to extract and how.