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.

Script to track Day Ahead prices for electricity on the ENTSOE-E Platform
#4
Good work @tigi!  Cool

I usually add automatic group address creation on this kind of programs so when you copy code to a new LM, you can run this program within seconds.
Also edited line 151 (group address was hard coded) and removed Average, Min and Max price Group addresses because these gonna generated automatically...
Now you need basically edit only three group address:  StartGrpAddr,  StartGrpAddrPercent and objaddrCheckUpdateTime + activate "create_addresses" on first time when running the code.

I have some ideas to create controlling part (solar inverters and battery charging/discharging) on top of this code but let's see when I have time to do that. Gonna share the results then...
 
Code:
local fetchfortommorow = true -- true for tommorow, false for today local SecurityTokenAPI = 'your-api-key-in-here' -- your personal security token, get it at entsoe transparency platform local EntsoeDomain = '10Y1001A1001A39I' -- find your domain for the country you are living at https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html#_load_domain local StartGrpAddr = '60/1' -- group addresses used to store the €/MWh prices per hour, x/x/0 is 00:00 hour, x/x/1 is 01:00 hour local StartGrpAddrPercent = '60/2' -- group addresses to store calculated pecentages for the hours, x/x/0 is 00:00 hour local SecondsPastTillRefetch =  39600 -- seconds that must be past till new refetch will be done, default 39600 seconds, is 11 hours local StartTimeHours=13 -- start time in which fetching is allowed, used in function IsTimeBetween local StartTimeMinutes=00 -- start minutes in which fetching is allowed, used in function IsTimeBetween local StopTimeHours=23 -- stop time in which fetching is allowed, used in function IsTimeBetween local StopTimeMinutes=59 -- stop minutes in which fetching is allowed, used in function IsTimeBetween local objaddrCheckUpdateTime = '60/1/0' -- object to check last updated date from --local objaddrAverageprice = '60/1/25' -- object to store average value --local objaddrLowestprice = '60/1/26' -- object to store groupaddress of lowest price of the day --local objaddrHighestprice = '60/1/27' -- object to store groupaddress of highest price of the day local PrintLOG = false -- logging local create_addresses = false --**********CREATE GROUP ADDRESSES****************** function createga(groupaddress,datatype2,name2)   exist = grp.alias(groupaddress)   if exist == nil then     address = grp.create({     datatype = datatype2,     address = groupaddress,     name = name2,     comment = 'Automatically created object',     units = '',     tags = { },     })   end end if create_addresses then   for i= 0, 27, 1 do     if i < 24 then       createga(StartGrpAddr ..'/'..i,dt.float32,'Electric - Entsoe day ahead  ' .. i)       createga(StartGrpAddrPercent ..'/'..i,dt.uint16,'Electric - Entsoe day ahead  ' .. i .. ' Percent')     elseif    i==25 then       createga(StartGrpAddr ..'/'..i,dt.float32,'Electric - Entsoe day ahead Average')     elseif i == 26 then       createga(StartGrpAddr ..'/'..i,dt.string,'Electric - Entsoe day ahead Lowest GrpAddr')      elseif i == 27 then       createga(StartGrpAddr ..'/'..i,dt.string,'Electric - Entsoe day ahead Highest GrpAddr')     end   end   os.sleep(2) end   -- https://stackoverflow.com/questions/35402992/how-to-check-if-current-time-is-between-two-others   -- Function to check if current time is between 2 other defined times   -- Returns true if time is between 2 other times   local function getMinutes(hours, minutes)       return (hours*60)+minutes   end   local function IsTimeBetween(StartH, StartM, StopH, StopM, TestH, TestM)       if (StopH < StartH) then -- add 24 hours if endhours < starthours           local StopHOrg=StopH           StopH = StopH + 24           if (TestH <= StopHOrg) then -- if endhours has increased the currenthour should also increase               TestH = TestH + 24           end       end       local StartTVal = getMinutes(StartH, StartM)       local StopTVal = getMinutes(StopH, StopM)       local curTVal = getMinutes(TestH, TestM)       return (curTVal >= StartTVal and curTVal <= StopTVal)   end      local function IsNowBetween(StartH,StartM,StopH,StopM)     local time = os.date("*t")       if PrintLOG then     log(time.hour, time.min) --check if time is correct, if not change to os.date("!*t") for UTC time     end     return IsTimeBetween(StartH, StartM, StopH, StopM, time.hour, time.min)   end     if PrintLOG then       log(IsNowBetween(StartTimeHours, StartTimeMinutes, StopTimeHours, StopTimeMinutes))   end   -- https://stackoverflow.com/questions/35402992/how-to-check-if-current-time-is-between-two-others objectupdatedate = (grp.find(objaddrCheckUpdateTime).updatetime) -- get update date for chosen object diff = os.difftime(os.time(),objectupdatedate) -- difference between current time and objectupdatetime in seconds if diff > SecondsPastTillRefetch then --check if last run was more than x seconds ago https://www.google.com/search?q=seconds+to+hours       if PrintLOG then           log('more than '..SecondsPastTillRefetch..' seconds since last run')     end     if (IsNowBetween(StartTimeHours, StartTimeMinutes, StopTimeHours, StopTimeMinutes)) then --check if current time is between hours that data can be fetched         if PrintLOG then                log('data can be fetched')       end             -- https://forum.logicmachine.net/showthread.php?tid=4268&highlight=entsoe       if fetchfortommorow then         date = os.date('%Y%m%d', os.time() + 86400) -- date is tommorow, default setting       else         date = os.date('%Y%m%d') --date is today       end       periodstart = date .. '0000'       periodend = date .. '2300'       log(date)       url = 'https://web-api.tp.entsoe.eu/api?securityToken='..SecurityTokenAPI..'&' ..         'documentType=A44&in_Domain='..EntsoeDomain..'&out_Domain='..EntsoeDomain..         '&periodStart=' .. periodstart .. '&periodEnd=' .. periodend       data, code = require('socket.http').request(url)       if not data or code ~= 200 then         log('request failed', data, code)         return       end       prices = {}       key = 0       callbacks = {         StartElement = function(p, tag)           if tag == 'TimeSeries' then             key = key + 1             prices[ key ] = {}           elseif tag == 'position' then             state = 'position'           elseif tag == 'price.amount' then             state = 'price'           end         end,         EndElement = function(p, tag)           state = nil         end,         CharacterData = function(p, value)           value = value:trim()           if #value > 0 then             if state == 'position' then               position = tonumber(value)             elseif state == 'price' then               prices[ key ][ position ] = tonumber(value)             end           end         end       }       parser = require('lxp').new(callbacks)       parser:parse(data)       parser:close()       if key > 0 then         for i, price in pairs(prices[ 1 ]) do           j = i - 1 -- shifts the first key from 1 to 0, so the first groupaddress is x/x/0 for 00:00 hour, next is x/x/1 for 01:00 hour,etc...             grp.checkupdate(StartGrpAddr..'/' .. j, price) -- update objects with newest prices           --log('uur ' ..j..' prijs: ' ..price)         end                        -- https://stackoverflow.com/questions/69359710/how-to-get-the-smallest-number-in-a-table-with-lua                lowestprice = math.min(unpack(prices[ 1 ])) --lowest number in table                  highestprice = math.max(unpack(prices[ 1 ])) --highest number in table                   -- https://stackoverflow.com/questions/25835591/how-to-calculate-percentage-between-the-range-of-two-values-a-third-value-is                 --input = grp.getvalue('34/1/13')           for i, price in pairs(prices[ 1 ]) do          j = i - 1              percentage = ((price - lowestprice) * 100) / (highestprice - lowestprice)              --log('at hour '..j..':00 price is '..math.floor(percentage)..'% higher than lowest price today')         grp.checkupdate(StartGrpAddrPercent..'/' .. j, percentage) --update objects with newest percentages                   if lowestprice == price then               grp.checkupdate(StartGrpAddr .. '/26', StartGrpAddr..'/' .. j)           end           if highestprice == price then               grp.checkupdate(StartGrpAddr .. '/27', StartGrpAddr..'/' .. j)           end         end                 -- https://www.codegrepper.com/code-examples/lua/lua+calculate+average+number           function math.average(t)             local sum = 0                 for _,v in pairs(t) do -- Get the sum of all numbers in t               sum = sum + v             end             return sum / #t           end         grp.checkupdate(StartGrpAddr .. '/25', math.average((prices[ 1 ])))         end      -- https://forum.logicmachine.net/showthread.php?tid=4268&highlight=entsoe      else         if PrintLOG then             log('data cannot be fetched yet')       end       end  else   if PrintLOG then       log('data has already been fetched and updated, not necessary to re-fetch data')   end end
Reply


Messages In This Thread
RE: Script to track Day Ahead prices for electricity on the ENTSOE-E Platform - by fleeceable - 18.04.2023, 10:06

Forum Jump: