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.

REST API to KNX groups
#1
Hello,

I'm working on a script to control my heatpump based on actual prices on the electrical market!
So far I have managed to fetch data to the LM but now I don't know how to continue Big Grin

The result contains 24 values, each for every hour of the day.
The response is in EUR/MWh so to convert it to SEK öre/kWh take the price in EUR/MWh (e.g. 11.75) times the currency exchange rate for SEK/EUR (e.g. 10.36) and then we need to divide it with 1000 to get kWh from MWh and again take it times 100 to get öre insted of SEK. We can shorten the MWh->kWh and öre->SEK by instead divide the result by ten (as divided by 1000, times 100 equals out to divided by 10), so e.g. 11.75 EUR/MWh * 10.36 / 10 = 12.173 öre/kWh.

My groupadress 5/5/6 is intended to keep the currency exchange.

I would want every read hour to be sent to a separate KNX group adress.
position 1 = 1/1/1
position 2 = 1/1/2
position 3 = 1/1/3
....
...

Code:
1234567891011
currency  = grp.getvalue('5/5/6') http = require('socket.http') ltn12 = require('ltn12') res, code = http.request({   url = 'https://web-api.tp.entsoe.eu/api?securityToken=XXXXXXXXXX&documentType=A44&in_Domain=10Y1001A1001A46L&out_Domain=10Y1001A1001A46L&periodStart=202209270000&periodEnd=202209272300',   method = 'GET', }) log(res, code)

The output in the log is:


Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
* arg: 1   * string: <?xml version="1.0" encoding="UTF-8"?> <Publication_MarketDocument xmlns="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0"> <mRID>5fad2c86f6644f35bfdde1c325b766bf</mRID> <revisionNumber>1</revisionNumber> <type>A44</type> <sender_MarketParticipant.mRID codingScheme="A01">10X1001A1001A450</sender_MarketParticipant.mRID> <sender_MarketParticipant.marketRole.type>A32</sender_MarketParticipant.marketRole.type> <receiver_MarketParticipant.mRID codingScheme="A01">10X1001A1001A450</receiver_MarketParticipant.mRID> <receiver_MarketParticipant.marketRole.type>A33</receiver_MarketParticipant.marketRole.type> <createdDateTime>2022-09-27T14:43:39Z</createdDateTime> <period.timeInterval> <start>2022-09-26T22:00Z</start> <end>2022-09-28T22:00Z</end> </period.timeInterval> <TimeSeries> <mRID>1</mRID> <businessType>A62</businessType> <in_Domain.mRID codingScheme="A01">10Y1001A1001A46L</in_Domain.mRID> <out_Domain.mRID codingScheme="A01">10Y1001A1001A46L</out_Domain.mRID> <currency_Unit.name>EUR</currency_Unit.name> <price_Measure_Unit.name>MWH</price_Measure_Unit.name> <curveType>A01</curveType> <Period> <timeInterval> <start>2022-09-26T22:00Z</start> <end>2022-09-27T22:00Z</end> </timeInterval> <resolution>PT60M</resolution> <Point> <position>1</position> <price.amount>13.93</price.amount> </Point> <Point> <position>2</position> <price.amount>13.00</price.amount> </Point> <Point> <position>3</position> <price.amount>12.66</price.amount> </Point> <Point> <position>4</position> <price.amount>12.97</price.amount> </Point> <Point> <position>5</position> <price.amount>14.32</price.amount> </Point> <Point> <position>6</position> <price.amount>16.20</price.amount> </Point> <Point> <position>7</position> <price.amount>24.72</price.amount> </Point> <Point> <position>8</position> <price.amount>59.41</price.amount> </Point> <Point> <position>9</position> <price.amount>90.16</price.amount> </Point> <Point> <position>10</position> <price.amount>69.95</price.amount> </Point> <Point> <position>11</position> <price.amount>69.29</price.amount> </Point> <Point> <position>12</position> <price.amount>68.76</price.amount> </Point> <Point> <position>13</position> <price.amount>62.06</price.amount> </Point> <Point> <position>14</position> <price.amount>60.86</price.amount> </Point> <Point> <position>15</position> <price.amount>58.48</price.amount> </Point> <Point> <position>16</position> <price.amount>57.42</price.amount> </Point> <Point> <position>17</position> <price.amount>58.05</price.amount> </Point> <Point> <position>18</position> <price.amount>62.05</price.amount> </Point> <Point> <position>19</position> <price.amount>66.33</price.amount> </Point> <Point> <position>20</position> <price.amount>65.16</price.amount> </Point> <Point> <position>21</position> <price.amount>60.39</price.amount> </Point> <Point> <position>22</position> <price.amount>52.37</price.amount> </Point> <Point> <position>23</position> <price.amount>46.10</price.amount> </Point> <Point> <position>24</position> <price.amount>34.73</price.amount> </Point> </Period> </TimeSeries> <TimeSeries> <mRID>2</mRID> <businessType>A62</businessType> <in_Domain.mRID codingScheme="A01">10Y1001A1001A46L</in_Domain.mRID> <out_Domain.mRID codingScheme="A01">10Y1001A1001A46L</out_Domain.mRID> <currency_Unit.name>EUR</currency_Unit.name> <price_Measure_Unit.name>MWH</price_Measure_Unit.name> <curveType>A01</curveType> <Period> <timeInterval> <start>2022-09-27T22:00Z</start> <end>2022-09-28T22:00Z</end> </timeInterval> <resolution>PT60M</resolution> <Point> <position>1</position> <price.amount>45.57</price.amount> </Point> <Point> <position>2</position> <price.amount>45.17</price.amount> </Point> <Point> <position>3</position> <price.amount>45.81</price.amount> </Point> <Point> <position>4</position> <price.amount>46.70</price.amount> </Point> <Point> <position>5</position> <price.amount>47.04</price.amount> </Point> <Point> <position>6</position> <price.amount>50.63</price.amount> </Point> <Point> <position>7</position> <price.amount>56.48</price.amount> </Point> <Point> <position>8</position> <price.amount>69.02</price.amount> </Point> <Point> <position>9</position> <price.amount>76.26</price.amount> </Point> <Point> <position>10</position> <price.amount>77.24</price.amount> </Point> <Point> <position>11</position> <price.amount>76.49</price.amount> </Point> <Point> <position>12</position> <price.amount>76.34</price.amount> </Point> <Point> <position>13</position> <price.amount>76.09</price.amount> </Point> <Point> <position>14</position> <price.amount>76.43</price.amount> </Point> <Point> <position>15</position> <price.amount>76.81</price.amount> </Point> <Point> <position>16</position> <price.amount>76.88</price.amount> </Point> <Point> <position>17</position> <price.amount>72.22</price.amount> </Point> <Point> <position>18</position> <price.amount>75.92</price.amount> </Point> <Point> <position>19</position> <price.amount>75.72</price.amount> </Point> <Point> <position>20</position> <price.amount>75.61</price.amount> </Point> <Point> <position>21</position> <price.amount>76.76</price.amount> </Point> <Point> <position>22</position> <price.amount>70.25</price.amount> </Point> <Point> <position>23</position> <price.amount>70.00</price.amount> </Point> <Point> <position>24</position> <price.amount>60.17</price.amount> </Point> </Period> </TimeSeries> </Publication_MarketDocument> * arg: 2   * number: 200

One other thing, I would want the following string in the adress to be dynamic and also always be the date of tomorrow, but the time should be static.
"periodStart=202209270000&periodEnd=202209272300"
Reply
#2
Try this:
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
date = os.date('%Y%m%d') periodstart = date .. '0000' periodend = date .. '2300' url = 'https://web-api.tp.entsoe.eu/api?securityToken=XXXXXXXXXX&' ..   'documentType=A44&in_Domain=10Y1001A1001A46L&out_Domain=10Y1001A1001A46L&' ..   '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   rate = grp.getvalue('5/5/6')   for i, price in pairs(prices[ 1 ]) do     grp.checkupdate('1/1/' .. i, price * rate / 10)   end end
Reply
#3
Thanks!

If I would want to manipulate the "date = os.date('%Y%m%d')" to be tomorrows date, would be a simple adjustment?
In example, September is only 30 days, if plussing 1 it shouldn't be 31, instead October 1st.

Also I'm thinking maybe the REST API with all the currency exchanges would be a little bit advanced.
I've found a JSON API with currency and power units already correct.

https://www.vattenfall.se/api/price/spot...-09-28/SN3
Reply
#4
Use this to calculate tomorrow's date:
Code:
1
date = os.date('%Y%m%d', os.time() + 86400)
Reply
#5
Thanks Admin,

I went with the JSON API from Vattenfall instead, I have made the code to work. However not the prettiest code Big Grin
I would want that, if the Vattenfall homepage is not responding or something goes wrong fetching info, set all the group adresses to "0"
How should I think when writing that code!?


Also, the timestamp format is YYYY-MM--DD while the DTP 11 is DD-MM-YYYY, so the value in my groupadress is "00-00-2000" after writing.

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
require('json') https = require 'ssl.https' date = os.date('%Y-%m-%d') url = 'https://www.vattenfall.se/api/price/spot/pricearea/' .. date .. '/' .. date .. '/SN3' status = ssl.https.request(url) data = json.decode(status) timestamp = data[1].TimeStampDay     grp.checkupdate('5/5/28', timestamp) price1 = data[1].Value     grp.checkupdate('5/5/1', price1) price2 = data[2].Value     grp.checkupdate('5/5/2', price2) price3 = data[3].Value     grp.checkupdate('5/5/3', price3) price4 = data[4].Value     grp.checkupdate('5/5/4', price4) price5 = data[5].Value     grp.checkupdate('5/5/5', price5) price6 = data[6].Value     grp.checkupdate('5/5/6', price6) price7 = data[7].Value     grp.checkupdate('5/5/7', price7) price8 = data[8].Value     grp.checkupdate('5/5/8', price8) price9 = data[9].Value     grp.checkupdate('5/5/9', price9) price10 = data[10].Value     grp.checkupdate('5/5/10', price10) price11 = data[11].Value     grp.checkupdate('5/5/11', price11) price12 = data[12].Value     grp.checkupdate('5/5/12', price12) price13 = data[13].Value     grp.checkupdate('5/5/13', price13) price14 = data[14].Value     grp.checkupdate('5/5/14', price14) price15 = data[15].Value     grp.checkupdate('5/5/15', price15) price16 = data[16].Value     grp.checkupdate('5/5/16', price16) price17 = data[17].Value     grp.checkupdate('5/5/17', price17) price18 = data[18].Value     grp.checkupdate('5/5/18', price18) price19 = data[19].Value     grp.checkupdate('5/5/19', price19) price20 = data[20].Value     grp.checkupdate('5/5/20', price20) price21 = data[21].Value     grp.checkupdate('5/5/21', price21) price22 = data[22].Value     grp.checkupdate('5/5/22', price22) price23 = data[23].Value     grp.checkupdate('5/5/23', price23) price24 = data[24].Value     grp.checkupdate('5/5/24', price24) medelpris = price1+price2+price3+price4+price5+price6+price7+price8+price9+price10+price11+price12+price13+price14+price15+price16+price17+price18+price19+price20+price21+price22+price23+price24 medelpris = medelpris / 24     grp.checkupdate('5/5/25', medelpris) maxpris = math.max(price1, price2, price3, price4, price5, price6, price7, price8, price9, price10, price11, price12, price13, price14, price15, price16, price17, price18, price19, price20, price21, price22, price23, price24)     grp.checkupdate('5/5/26', maxpris) minpris = math.min(price1, price2, price3, price4, price5, price6, price7, price8, price9, price10, price11, price12, price13, price14, price15, price16, price17, price18, price19, price20, price21, price22, price23, price24)     grp.checkupdate('5/5/27', minpris) log(price1,price2)
Reply
#6
A for loop makes the code more compact and can't cause copy-paste errors. DPT 11 expects a table with year/month/day, not a string.
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142
require('json') https = require 'ssl.https' date = os.date('%Y-%m-%d') url = 'https://www.vattenfall.se/api/price/spot/pricearea/' .. date .. '/' .. date .. '/SN3' status = ssl.https.request(url) data = json.decode(status) if type(data) ~= 'table' then   return end ts = data[ 1 ].TimeStampDay if type(ts) == 'string' then   ts = ts:split('-')   grp.checkupdate('5/5/28', {     year = tonumber(ts[1]),     month = tonumber(ts[2]),     day = tonumber(ts[3])   }) end min = math.huge max = -math.huge cnt = 0 sum = 0 for i, item in ipairs(data) do   price = item.Value   min = math.min(min, price)   max = math.max(max, price)   sum = sum + price   cnt = cnt + 1   grp.checkupdate('5/5/' .. i, price) end grp.checkupdate('5/5/25', sum / cnt) grp.checkupdate('5/5/26', max) grp.checkupdate('5/5/27', min)
Reply


Forum Jump: