LogicMachine Forum
NordPool prices in LogicMachine - Printable Version

+- LogicMachine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: NordPool prices in LogicMachine (/showthread.php?tid=4456)



NordPool prices in LogicMachine - martins.neibergs@gmail.com - 19.12.2022

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/price?interval=minute&period=days&start=2022-07-25T21:00:00.000Z&end=2022-07-26T20:59:59.999Z
https://dashboard.elering.ee/api/nps/price?start=2022-07-25T22%3A00%3A00.999Z&end=2022-07-26T22%3A00%3A00.999Z

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


RE: NordPool prices in LogicMachine - RomansP - 20.12.2022

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 --]]



RE: NordPool prices in LogicMachine - RomansP - 06.10.2025

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



RE: NordPool prices in LogicMachine - Novodk - 07.10.2025

(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


RE: NordPool prices in LogicMachine - RomansP - 08.10.2025

Hi,

We will prepare script for Denmark, Sweden, Norway and Germany


RE: NordPool prices in LogicMachine - RomansP - 13.10.2025

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)



RE: NordPool prices in LogicMachine - jerryhenke - 05.11.2025

(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/price?interval=minute&period=days&start=2022-07-25T21:00:00.000Z&end=2022-07-26T20:59:59.999Z
https://dashboard.elering.ee/api/nps/price?start=2022-07-25T22%3A00%3A00.999Z&end=2022-07-26T22%3A00%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



RE: NordPool prices in LogicMachine - RomansP - 02.02.2026

Hello,

Here is a new script for a hourly pricing for Latvia, Finland, Lithuania, Estonia

Code:
country = 'lv' -- Latvia --country = 'fi' -- Finland --country = 'lt' -- Lithuania --country = 'ee' -- Estonia current_hour_price_addr = '43/1/2' cheapest_hour_addr = '43/1/3' cheapest_hour_price_addr = '43/1/4' costliest_hour_addr = '43/1/5' costliest_hour_price_addr = '43/1/6' local 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 previous_date = os.date('%F', os.time() - 24 * 60 * 60) local next_date = os.date('%F', os.time() + 24 * 60 * 60) local url = 'https://dashboard.elering.ee/api/nps/price?start=' .. previous_date .. 'T00%3A00%3A00.999Z&end=' .. next_date .. 'T00%3A00%3A00.999Z' --log(url) local res, code = require('socket.http').request(url) if not (res and code == 200) then   log('request error: ', res, code)   return end local data = require('json').pdecode(res) if not data or not data.data or not data.data[country] then   log('No data for country: ' .. country)   return end local hourly_prices = {} for h = 0, 23 do   hourly_prices[h] = { sum = 0, count = 0 } 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     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 end local min_avg_price = 99999 local max_avg_price = -1 local cheapest_hour = -1 local costliest_hour = -1 local current_hour_avg_price = nil for hour, price_data in pairs(hourly_prices) do   if price_data.count > 0 then     local avg_price = price_data.sum / price_data.count     log(string.format("Average price per hour %02d:00 - %.2f EUR/MWh", 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         if hour == current_date.hour then       current_hour_avg_price = avg_price     end   end end if current_hour_avg_price then   log(string.format('Price for current hour (%02d:00): %.2f EUR/MWh', current_date.hour, current_hour_avg_price))   grp.write(current_hour_price_addr, current_hour_avg_price) end if cheapest_hour ~= -1 then   log(string.format('Cheapest hour: %02d:00, Price: %.2f EUR/MWh', cheapest_hour, min_avg_price))   local cheapest_hour_time = { wday = current_date.wday, 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 if costliest_hour ~= -1 then   log(string.format('Costliest hour: %02d:00, Price: %.2f EUR/MWh', costliest_hour, max_avg_price))   local costliest_hour_time = { wday = current_date.wday, hour = costliest_hour }   grp.write(costliest_hour_addr, costliest_hour_time)   grp.write(costliest_hour_price_addr, max_avg_price) else   log('Could not calculate the costliest hour.') end