This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

NordPool prices in LogicMachine
#1
Hi!

Has anyone had any experience with getting (integrating) NordPool prices into LogicMachine?

Tried different versions but nothing worked. 

What about this one? 

https://dashboard.elering.ee/en/nps/pric...59:59.999Z
https://dashboard.elering.ee/api/nps/pri...%3A00.999Z

Anyone had any luck or experience? Can you please share scripts for getting NordPool prices into logic machine?
Reply
#2
Hi!

Here is a script, that gives six objects 1.current_time; 2.current_price; 3.cheapest_hour; 4.cheapest_price; 5.costly_hour; 6.costly_price

Code:
https = require('ssl.https')
json = require('json')
ltn12 = require('ltn12')

country = 'lv' -- Latvia
--country = 'fi' -- Finland
--country = 'lt' -- Lithuania
--country = 'ee' -- Estonia

obj_current_time = grp.create({ datatype = dt.time, address = '35/5/11', name = 'current_time'})
obj_current_price = grp.create({ datatype = dt.float32, address = '35/5/12', name = 'current_price'})
obj_cheapest_hour = grp.create({ datatype = dt.time, address = '35/5/13', name = 'cheapest_hour'})
obj_cheapest_hour_price = grp.create({ datatype = dt.float32, address = '35/5/14', name = 'cheapest_price'})
obj_costly_hour = grp.create({ datatype = dt.time, address = '35/5/15', name = 'costly_hour'})
obj_costly_hour_price = grp.create({ datatype = dt.float32, address = '35/5/16', name = 'costly_price'})

--[[]]
current_date = os.date('*t')

previous_date = os.date('*t', os.time()-24*60*60)
--log(previous_date)

if previous_date.month < 10 then
  previous_date.month = '0' .. previous_date.month
end

if previous_date.day < 10 then
  previous_date.day = '0' .. previous_date.day
end

previous_date_str = previous_date.year .. '-' .. previous_date.month .. '-' .. previous_date.day

--log(previous_date_str)

next_date = os.date('*t', os.time() + 24*60*60)
--log(next_date)

if next_date.month < 10 then
  next_date.month = '0' .. next_date.month
end

if next_date.day < 10 then
  next_date.day = '0' .. next_date.day
end

next_date_str = next_date.year .. '-' .. next_date.month .. '-' .. next_date.day

--log(next_date_str)

url = 'https://dashboard.elering.ee/api/nps/price?start='.. previous_date_str ..'T00%3A00%3A00.999Z&end=' .. next_date_str ..'T00%3A00%3A00.999Z'

--log(url)

mac = 0
io.readfile('/sys/class/net/eth0/address'):gsub('%x%x', function(v)
  mac = mac * 256 + tonumber(v, 16)
end)

response = {}

res, code = https.request({
  url = url,
  protocol = 'tlsv12',
  headers = {
    ['user-agent'] = 'LM ' .. mac
  },
  sink = ltn12.sink.table(response)
})

if res and code == 200 then
  data = json.pdecode(table.concat(response))
else
  log('request error', res, code)
end

--log(data)

--log(data['data'][country])

min_price = 99999
max_price = -1
min_price_hour = -1
max_price_hour = -1

for i = 23, 47, 1 do -- 23 is 00:00 for GMT+0200 (Eastern European Standard Time)
  if data['data'][country][i] then 
    price = data['data'][country][i]['price']
   
    if price < min_price then
      min_price = price -- EUR/MegaWatt*hour
      min_price_hour = i - 23 -- get hour for GMT+0200 (Eastern European Standard Time)
    end
   
    if price > max_price then
      max_price = price -- EUR/MegaWatt*hour
      max_price_hour = i - 23 -- get hour for GMT+0200 (Eastern European Standard Time)
    end
   
  end
end


--log(min_price_hour)
--log(min_price)
--log(max_price_hour)
--log(max_price)


curr_day_time = {}

if current_date['wday'] > 1 then
  current_date['wday'] = current_date['wday'] - 1 -- 1 is Monday, 2 is Tuesday
else
  current_date['wday'] = 7 -- 7 is Sunday
end
 
curr_day_time['day'] = current_date['wday']
curr_day_time['hour'] = current_date['hour']
curr_day_time['minute'] = current_date['min']

grp.write(obj_current_time, curr_day_time) -- 3 byte time day

current_price = data['data'][country][ current_date['hour'] + 23 ]['price'] -- EUR/MegaWatt*hour

--[[
timestamp = data['data'][country][ current_date['hour'] + 23 ]['timestamp']
log(timestamp)
temp = os.date("*t", timestamp)
log(temp)
--]]

grp.write(obj_current_price, current_price) -- float


cheapest_day_time = {}
cheapest_day_time['day'] = current_date['wday']
cheapest_day_time['hour'] = min_price_hour
grp.write(obj_cheapest_hour, cheapest_day_time) -- 3 byte time day
grp.write(obj_cheapest_hour_price, min_price) -- float

costly_day_time = {}
costly_day_time['day'] = current_date['wday']
costly_day_time['hour'] = max_price_hour
grp.write(obj_costly_hour, costly_day_time) -- 3 byte time day
grp.write(obj_costly_hour_price, max_price) -- float
--]]

Attached Files
.lua   elering_v03.lua (Size: 4.02 KB / Downloads: 21)
Reply
#3
Hi!

We have rewritten script (old script will not work properly), because of a change
in time intervals (previously electricity price was per hour, now per 15 minutes).

Here is a new script:

Code:
https = require('ssl.https')
json = require('json')
ltn12 = require('ltn12')

country = 'lv' -- Latvia
--country = 'fi' -- Finland
--country = 'lt' -- Lithuania
--country = 'ee' -- Estonia

current_price_addr = '40/1/18'
cheapest_hour_addr = '40/1/16'
cheapest_hour_price_addr = '40/1/17'
costliest_hour_addr = '40/1/19'
cosltiest_hour_price_addr = '40/1/20'
cheapest_time_addr = '40/1/14'
cheapest_price_addr = '40/1/15'
costliest_time_addr = '40/1/21'
costliest_price_addr = '40/1/22'

current_date = os.date('*t')

local day_start_ts = os.time({year = current_date.year, month = current_date.month, day = current_date.day, hour = 0, min = 0, sec = 0})
local day_end_ts = os.time({year = current_date.year, month = current_date.month, day = current_date.day, hour = 23, min = 59, sec = 59})
local current_ts = os.time()

previous_date = os.date('%F', os.time() - 24*60*60)
next_date = os.date('%F', os.time() + 24*60*60)

url = 'https://dashboard.elering.ee/api/nps/price?start='.. previous_date ..'T00%3A00%3A00.999Z&end=' .. next_date ..'T00%3A00%3A00.999Z'

mac = 0
io.readfile('/sys/class/net/eth0/address'):gsub('%x%x', function(v)
  mac = mac * 256 + tonumber(v, 16)
end)

response = {}
res, code = https.request({
  url = url,
  protocol = 'tlsv12',
  headers = {
    ['user-agent'] = 'LM ' .. mac
  },
  sink = ltn12.sink.table(response)
})

if res and code == 200 then
  data = json.pdecode(table.concat(response))
else
  log('request error', res, code)
  return
end


min_price = 99999
max_price = -1
min_price_timestamp = 0
max_price_timestamp = 0
current_price = nil


hourly_prices = {}
for h = 0, 23 do
  hourly_prices[h] = { sum = 0, count = 0 }
end

if not data or not data.data or not data.data[country] then
  log('No data for country: ' .. country)
  return
end

for _, record in ipairs(data.data[country]) do
  local timestamp = record.timestamp
  local price = record.price

  if timestamp >= day_start_ts and timestamp <= day_end_ts then
   
    if price < min_price then
      min_price = price
      min_price_timestamp = timestamp
    end
   
    if price > max_price then
      max_price = price
      max_price_timestamp = timestamp
    end

    local record_time = os.date('*t', timestamp)
    local hour = record_time.hour
    if hourly_prices[hour] then
      hourly_prices[hour].sum = hourly_prices[hour].sum + price
      hourly_prices[hour].count = hourly_prices[hour].count + 1
    end
  end
 
  if current_ts >= timestamp and current_ts < (timestamp + 15 * 60) then
    current_price = price
  end
end

--log('--- Current Status ---')
if current_price then
  --log('Current 15-min price: ' .. current_price .. ' EUR/MWh')
  grp.write(current_price_addr, current_price) -- float
else
  log('Could not determine current price')
end


min_avg_price = 99999
max_avg_price = -1
cheapest_hour = -1
costliest_hour = -1

for hour, data in pairs(hourly_prices) do
  if data.count > 0 then
    local avg_price = data.sum / data.count
    --log(string.format("Hour %02d:00 - Avg Price: %.2f", hour, avg_price))
   
    if avg_price < min_avg_price then
      min_avg_price = avg_price
      cheapest_hour = hour
    end

    if avg_price > max_avg_price then
      max_avg_price = avg_price
      costliest_hour = hour
    end
  end
end

cheapest_hour_time = {}
cheapest_hour_time['wday'] = current_date['wday']

--log('--- Cheapest Hour Today ---')
if cheapest_hour ~= -1 then
  --log(string.format('Hour: %02d:00 - %02d:59', cheapest_hour, cheapest_hour))
  --log(string.format('Average Price: %.2f EUR/MWh', min_avg_price))
  cheapest_hour_time['hour'] = cheapest_hour
  grp.write(cheapest_hour_addr, cheapest_hour_time)
  grp.write(cheapest_hour_price_addr, min_avg_price)
else
  log('Could not calculate the cheapest hour.')
end

costliest_hour_time = {}
costliest_hour_time['wday'] = current_date['wday']

--log('--- Costliest Hour Today ---')
if costliest_hour ~= -1 then
  --log(string.format('Hour: %02d:00 - %02d:59', costliest_hour, costliest_hour))
  --log(string.format('Average Price: %.2f EUR/MWh', max_avg_price))
  costliest_hour_time['hour'] = costliest_hour
  grp.write(costliest_hour_addr, costliest_hour_time)
  grp.write(cosltiest_hour_price_addr, max_avg_price)
else
  log('Could not calculate the costliest hour.')
end

cheapest_time = {}
cheapest_time['wday'] = current_date['wday']

--log('--- Cheapest 15-min Interval Today ---')
if min_price_timestamp > 0 then
  local min_price_time = os.date('*t', min_price_timestamp)
  --log('Price: ' .. min_price .. ' EUR/MWh')
  --log('Time: ' .. string.format('%02d:%02d', min_price_time.hour, min_price_time.min))
  cheapest_time['hour'] = min_price_time.hour
  cheapest_time['minute'] = min_price_time.min
  grp.write(cheapest_time_addr, cheapest_time)
  grp.write(cheapest_price_addr, min_price)
else
  log('Could not find minimum price for today')
end

costliest_time = {}
costliest_time['wday'] = current_date['wday']

--log('--- Costliest 15-min Interval Today ---')
if max_price_timestamp > 0 then
  local max_price_time = os.date('*t', max_price_timestamp)
  --log('Price: ' .. max_price .. ' EUR/MWh')
  --log('Time: ' .. string.format('%02d:%02d', max_price_time.hour, max_price_time.min))
  costliest_time['hour'] = max_price_time.hour
  costliest_time['minute'] = max_price_time.min
  grp.write(costliest_time_addr, costliest_time)
  grp.write(costliest_price_addr, max_price)
else
  log('Could not find maximum price for today')
end

Attached Files
.lua   electricity_price_20251006_04.lua (Size: 5.5 KB / Downloads: 4)
Reply
#4
(06.10.2025, 12:51)RomansP Wrote: Hi!

We have rewritten script (old script will not work properly), because of a change
in time intervals (previously electricity price was per hour, now per 15 minutes).

Here is a new script:

Code:
https = require('ssl.https')
json = require('json')
ltn12 = require('ltn12')

country = 'lv' -- Latvia
--country = 'fi' -- Finland
--country = 'lt' -- Lithuania
--country = 'ee' -- Estonia

current_price_addr = '40/1/18'
cheapest_hour_addr = '40/1/16'
cheapest_hour_price_addr = '40/1/17'
costliest_hour_addr = '40/1/19'
cosltiest_hour_price_addr = '40/1/20'
cheapest_time_addr = '40/1/14'
cheapest_price_addr = '40/1/15'
costliest_time_addr = '40/1/21'
costliest_price_addr = '40/1/22'

current_date = os.date('*t')

local day_start_ts = os.time({year = current_date.year, month = current_date.month, day = current_date.day, hour = 0, min = 0, sec = 0})
local day_end_ts = os.time({year = current_date.year, month = current_date.month, day = current_date.day, hour = 23, min = 59, sec = 59})
local current_ts = os.time()

previous_date = os.date('%F', os.time() - 24*60*60)
next_date = os.date('%F', os.time() + 24*60*60)

url = 'https://dashboard.elering.ee/api/nps/price?start='.. previous_date ..'T00%3A00%3A00.999Z&end=' .. next_date ..'T00%3A00%3A00.999Z'

mac = 0
io.readfile('/sys/class/net/eth0/address'):gsub('%x%x', function(v)
  mac = mac * 256 + tonumber(v, 16)
end)

response = {}
res, code = https.request({
  url = url,
  protocol = 'tlsv12',
  headers = {
    ['user-agent'] = 'LM ' .. mac
  },
  sink = ltn12.sink.table(response)
})

if res and code == 200 then
  data = json.pdecode(table.concat(response))
else
  log('request error', res, code)
  return
end


min_price = 99999
max_price = -1
min_price_timestamp = 0
max_price_timestamp = 0
current_price = nil


hourly_prices = {}
for h = 0, 23 do
  hourly_prices[h] = { sum = 0, count = 0 }
end

if not data or not data.data or not data.data[country] then
  log('No data for country: ' .. country)
  return
end

for _, record in ipairs(data.data[country]) do
  local timestamp = record.timestamp
  local price = record.price

  if timestamp >= day_start_ts and timestamp <= day_end_ts then
   
    if price < min_price then
      min_price = price
      min_price_timestamp = timestamp
    end
   
    if price > max_price then
      max_price = price
      max_price_timestamp = timestamp
    end

    local record_time = os.date('*t', timestamp)
    local hour = record_time.hour
    if hourly_prices[hour] then
      hourly_prices[hour].sum = hourly_prices[hour].sum + price
      hourly_prices[hour].count = hourly_prices[hour].count + 1
    end
  end
 
  if current_ts >= timestamp and current_ts < (timestamp + 15 * 60) then
    current_price = price
  end
end

--log('--- Current Status ---')
if current_price then
  --log('Current 15-min price: ' .. current_price .. ' EUR/MWh')
  grp.write(current_price_addr, current_price) -- float
else
  log('Could not determine current price')
end


min_avg_price = 99999
max_avg_price = -1
cheapest_hour = -1
costliest_hour = -1

for hour, data in pairs(hourly_prices) do
  if data.count > 0 then
    local avg_price = data.sum / data.count
    --log(string.format("Hour %02d:00 - Avg Price: %.2f", hour, avg_price))
   
    if avg_price < min_avg_price then
      min_avg_price = avg_price
      cheapest_hour = hour
    end

    if avg_price > max_avg_price then
      max_avg_price = avg_price
      costliest_hour = hour
    end
  end
end

cheapest_hour_time = {}
cheapest_hour_time['wday'] = current_date['wday']

--log('--- Cheapest Hour Today ---')
if cheapest_hour ~= -1 then
  --log(string.format('Hour: %02d:00 - %02d:59', cheapest_hour, cheapest_hour))
  --log(string.format('Average Price: %.2f EUR/MWh', min_avg_price))
  cheapest_hour_time['hour'] = cheapest_hour
  grp.write(cheapest_hour_addr, cheapest_hour_time)
  grp.write(cheapest_hour_price_addr, min_avg_price)
else
  log('Could not calculate the cheapest hour.')
end

costliest_hour_time = {}
costliest_hour_time['wday'] = current_date['wday']

--log('--- Costliest Hour Today ---')
if costliest_hour ~= -1 then
  --log(string.format('Hour: %02d:00 - %02d:59', costliest_hour, costliest_hour))
  --log(string.format('Average Price: %.2f EUR/MWh', max_avg_price))
  costliest_hour_time['hour'] = costliest_hour
  grp.write(costliest_hour_addr, costliest_hour_time)
  grp.write(cosltiest_hour_price_addr, max_avg_price)
else
  log('Could not calculate the costliest hour.')
end

cheapest_time = {}
cheapest_time['wday'] = current_date['wday']

--log('--- Cheapest 15-min Interval Today ---')
if min_price_timestamp > 0 then
  local min_price_time = os.date('*t', min_price_timestamp)
  --log('Price: ' .. min_price .. ' EUR/MWh')
  --log('Time: ' .. string.format('%02d:%02d', min_price_time.hour, min_price_time.min))
  cheapest_time['hour'] = min_price_time.hour
  cheapest_time['minute'] = min_price_time.min
  grp.write(cheapest_time_addr, cheapest_time)
  grp.write(cheapest_price_addr, min_price)
else
  log('Could not find minimum price for today')
end

costliest_time = {}
costliest_time['wday'] = current_date['wday']

--log('--- Costliest 15-min Interval Today ---')
if max_price_timestamp > 0 then
  local max_price_time = os.date('*t', max_price_timestamp)
  --log('Price: ' .. max_price .. ' EUR/MWh')
  --log('Time: ' .. string.format('%02d:%02d', max_price_time.hour, max_price_time.min))
  costliest_time['hour'] = max_price_time.hour
  costliest_time['minute'] = max_price_time.min
  grp.write(costliest_time_addr, costliest_time)
  grp.write(costliest_price_addr, max_price)
else
  log('Could not find maximum price for today')
end

What about Denmark Smile
Reply
#5
Hi,

We will prepare script for Denmark, Sweden, Norway and Germany
Reply
#6
Hello,

We have prepared script for electricity prices for Denmark, Norway, Sweden and Germany

Code:
price_area = 'DK1' -- west Denmark DK1 grid region
--price_area = 'DK2' -- east Denmark DK2 grid region
--price_area = 'DE' -- Germany
--price_area = 'NO2' -- southern and southwestern Norway
--price_area = 'SE3' -- north Sweden
--price_area = 'SE4' -- south Sweden

current_price_addr = '40/1/18' -- 14. 4 byte floating point
cheapest_hour_addr = '40/1/16' -- 10. 3 byte time / day
cheapest_hour_price_addr = '40/1/17' -- 14. 4 byte floating point
costliest_hour_addr = '40/1/19' -- 10. 3 byte time / day
costliest_hour_price_addr = '40/1/20' -- 14. 4 byte floating point

start_date = os.date('%Y-%m-%d')
end_date = os.date('%Y-%m-%d', os.time() + 48 * 60 * 60)

url = 'https://api.energidataservice.dk/dataset/DayAheadPrices?start=' ..
      start_date .. '&end=' .. end_date ..
      '&filter={"PriceArea":["' .. price_area .. '"]}'
resp, code = require('socket.http').request(url)

if resp and code == 200 then
  data = require('json').pdecode(resp)
else
  log('request error', resp, code)
  return
end

if not data or not data.records then
  log('No data for price area: ' .. price_area)
  return
end

curr_day = tonumber(os.date('%u'))
next_day = curr_day == 7 and 1 or (curr_day + 1)
curr_date = os.date('%Y%m%d')
curr_hour_str = curr_date .. os.date('%H')
curr_hour = tonumber(curr_hour_str)
curr_min = math.floor(tonumber(os.date('%M')) / 15) * 15
curr_ts = curr_hour_str .. string.format('%02d', curr_min)

prices = {}

for _, record in ipairs(data.records) do
  ts = record.TimeDK:gsub('%-', ''):gsub('T', ''):gsub(':', '')
  hour = tonumber(ts:sub(1, 10))
  price = record.DayAheadPriceEUR

  if hour >= curr_hour then
    store = prices[ hour ] or { sum = 0, count = 0 }
    store.sum = store.sum + price
    store.count = store.count + 1
    prices[ hour ] = store
  end

  if ts:sub(1, 12) == curr_ts then
    curr_price = price
  end
end

hourly = {}

for hour, store in pairs(prices) do
  price = store.sum / store.count
  hourly[ #hourly + 1 ] = {
    hour = hour,
    price = price
  }
end

table.sort(hourly, function(a, b)
  return a.price > b.price
end)

function update(store, hour_addr, price_addr)
  local hour = tostring(store.hour)
  local date = hour:sub(1, 8)
  local day = date == curr_date and curr_day or next_day

  grp.checkupdate(hour_addr, { day = day, hour = hour:sub(9, 10) })
  grp.checkupdate(price_addr, store.price)
end

grp.checkupdate(current_price_addr, curr_price)
update(hourly[1], costliest_hour_addr, costliest_hour_price_addr)
update(hourly[#hourly], cheapest_hour_addr, cheapest_hour_price_addr)

Attached Files
.lua   electricity_price_dk_20251013.lua (Size: 2.49 KB / Downloads: 1)
Reply
#7
(19.12.2022, 18:08)martins.neibergs@gmail.com Wrote: Hi!

Has anyone had any experience with getting (integrating) NordPool prices into LogicMachine?

Tried different versions but nothing worked. 

What about this one? 

https://dashboard.elering.ee/en/nps/pric...59:59.999Z
https://dashboard.elering.ee/api/nps/pri...%3A00.999Z

Anyone had any luck or experience? Can you please share scripts for getting NordPool prices into logic machine?

Hi!
I do two scripts
Both "Scheduled"
Script 1 -
Collecting electric price from API. running 4 times/day hour 17,18,21,23 amd minute 5.
Code:
CODE
-- API-skript (spara per datum)
local json = require("json")
local ltn12 = require("ltn12")
local http = require("socket.http")

local DECIMALS = 5
local PRISKLASS = "SE2"

local function fetch_prices(date_timestamp)
    local year = os.date("%Y", date_timestamp)
    local month_day = os.date("%m-%d", date_timestamp)
    local url = string.format("https://www.elprisetjustnu.se/api/v1/prices/%s/%s_%s.json", year, month_day, PRISKLASS)

    local resp = {}
    local res, code = http.request({url = url, method = "GET", sink = ltn12.sink.table(resp)})

    if code == 200 then
        local decoded = json.pdecode(table.concat(resp))
        if decoded then
            local prices = {}
            for i,v in ipairs(decoded) do
                local time_start = v.time_start -- "2025-09-10T21:15:00+02:00"
                local hh = string.sub(time_start, 12, 13)
                local mm = string.sub(time_start, 15, 16)
                local val = tonumber(string.format("%." .. DECIMALS .. "f", v.SEK_per_kWh))

                if mm == "00" then
                    -- timpris: duplicera till kvart
                    for _, q in ipairs({"00","15","30","45"}) do
                        prices[hh .. ":" .. q] = val
                    end
                else
                    prices[hh .. ":" .. mm] = val
                end
            end
            return prices
        end
    end
    return nil
end

local function save_prices()
    local now = os.time()
    -- idag och imorgon som timestamps (midnatt)
    local t = os.date("*t", now)
    t.hour, t.min, t.sec = 0,0,0
    local idag_ts = os.time(t)
    local imorgon_ts = idag_ts + 86400

    -- Spara dagens priser i storage med datumnyckel
    local ds_idag = os.date("%Y-%m-%d", idag_ts)
    local p_idag = fetch_prices(idag_ts)
    if p_idag then
        storage.set("elpris_" .. ds_idag, json.encode(p_idag))
        log("Sparade elpriser för " .. ds_idag)
    else
        log("️ Kunde inte hämta priser för " .. ds_idag)
    end

    -- Spara morgondagens priser (förutsatt kl 18+ eller när du vill hämta)
    if tonumber(os.date("%H", now)) >= 18 then
        local ds_im = os.date("%Y-%m-%d", imorgon_ts)
        local p_im = fetch_prices(imorgon_ts)
        if p_im then
            storage.set("elpris_" .. ds_im, json.encode(p_im))
            log("Sparade elpriser för " .. ds_im)
        else
            log("️ Kunde inte hämta priser för " .. ds_im)
        end
    end

    -- Rensa gamla nycklar (behåll t.ex. -3..+2 dagar)
    for i = 4, 30 do
        local old = os.date("%Y-%m-%d", idag_ts - i*86400)
        storage.set("elpris_" .. old, nil)
    end
end

save_prices()


Script 2
Writing current electrical price to KNX address
Running as scheduled minute 0,15,30,45
Code:
local json = require("json")
local GA_ELPRIS = "34/4/99"

local function round_to_quarter()
    local now = os.time()
    local hh = tonumber(os.date("%H", now))
    local min = tonumber(os.date("%M", now))
    min = math.floor(min / 15) * 15
    return string.format("%02d:%02d", hh, min)
end

-- försök hitta pris i dataset för en specifik datumnyckel
local function find_in_date(date_str, hhmm)
    local key = "elpris_" .. date_str
    local j = storage.get(key)
    if not j then return nil end
    local prices = json.decode(j)
    if not prices then return nil end
    local p = prices[hhmm]
    if p then return p, key end

    -- fallback: sök närmaste tidigare kvart inom detta dataset
    local hh = tonumber(string.sub(hhmm,1,2))
    local mm = tonumber(string.sub(hhmm,4,5))
    local kvart_list = {0,15,30,45}
    for h = hh, 0, -1 do
        for i = #kvart_list, 1, -1 do
            local q = kvart_list[i]
            if (h < hh) or (q <= mm) then
                local try = string.format("%02d:%02d", h, q)
                if prices[try] then
                    return prices[try], key, try
                end
            end
        end
    end
    return nil
end

-- Huvudfunktion som provar datum i prioriterad ordning
local function get_price_for_quarter()
    local now = os.time()
    local hhmm = round_to_quarter()

    local date_today = os.date("%Y-%m-%d", now)
    local date_tomorrow = os.date("%Y-%m-%d", now + 86400)
    local date_yesterday = os.date("%Y-%m-%d", now - 86400)

    local candidates = {date_today, date_tomorrow, date_yesterday}

    for _, d in ipairs(candidates) do
        local p, used_key, used_q = find_in_date(d, hhmm)
        if p then
            -- used_q kan vara nil om exakt hhmm träffade; annars är used_q den kvarten vi använde
            local used = used_q or hhmm
            return p, used, used_key
        end
    end

    return nil, hhmm, nil
end

-- Anropa och skriv till KNX
local pris, used_hhmm, used_key = get_price_for_quarter()
if pris then
    local pris_5dec = string.format("%.5f", pris)
    log(string.format("Skriver elpris kl %s (från %s): %s kr/kWh", used_hhmm, used_key or "ingen", pris_5dec))
    grp.write(GA_ELPRIS, tonumber(pris_5dec))
else
    log("️ Ingen elprisinformation hittades för " .. used_hhmm)
end
Reply


Forum Jump: