From 99337c6045aa0834309f498e5784a4e89f8d6c25 Mon Sep 17 00:00:00 2001 From: Aart van Halteren Date: Wed, 19 Jan 2022 15:52:20 +0100 Subject: [PATCH] Adds timezone to Entsoe prices --- app/models/entsoe.rb | 29 ++++++++++++++++++++--------- db/migrate/003_creates_prices.rb | 10 ++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 db/migrate/003_creates_prices.rb diff --git a/app/models/entsoe.rb b/app/models/entsoe.rb index a7f78e2..be62b5e 100644 --- a/app/models/entsoe.rb +++ b/app/models/entsoe.rb @@ -10,30 +10,32 @@ class Entsoe URL = 'https://transparency.entsoe.eu' - attr_accessor :no_grid_charge_months + attr_accessor :no_grid_charge_months, :zone attr_reader :storage_cost - def initialize(storage_cost = 0.05, api_key = "c2287e07-0c26-4950-b430-22b7f75a8f2e") + def initialize(zone = "Amsterdam", storage_cost = 0.05, api_key = "c2287e07-0c26-4950-b430-22b7f75a8f2e") @api_key = api_key @kwh_prices = {} @storage_cost = storage_cost # how much does it cost to store 1 kwh in battery @no_grid_charge_months = [5,6,7] # months where we assume there is enough surplus from sun power + @zone = zone end def price_at(formatted_hour) unless @kwh_prices.key?(formatted_hour) p "Fetching Entsoe tariffs for %s" % formatted_hour - @kwh_prices.merge!(query_day_ahead_prices(Date.parse(formatted_hour))) + prices = query_day_ahead_prices(Date.parse(formatted_hour)) + @kwh_prices.merge!(hourly_format(prices)) end @kwh_prices[formatted_hour] end def prices_at(date) - hour_start = date.beginning_of_day + hour_start = date.beginning_of_day.in_time_zone(@zone) day_end = hour_start.advance(days: 1) result = {} while(hour_start < day_end) do - formatted_hour = hour_start.strftime("%F-%H") + formatted_hour = hour_start.strftime("%F %H") result.merge!({ formatted_hour => price_at(formatted_hour)}) hour_start = hour_start.advance(:hours => 1) end @@ -79,6 +81,11 @@ class Entsoe private + def hourly_format(prices) + # in memory hash @kwh_prices is in @zone timezone + prices.to_a.map{|p| [p[0].in_time_zone(@zone).strftime("%F %H"),p[1]]}.to_h + end + # get position and amount from XML snippet # # 1 @@ -88,16 +95,20 @@ class Entsoe # convert price to EUR per kwh, including VAT (21%) # def parse_point(xml) - return xml.children[1].text.to_i, ((xml.children[3].text.to_f/1000)*1.21).round(5) + return xml.xpath(".//xmlns:position").text.to_i, ((xml.xpath(".//xmlns:price.amount").text.to_f/1000)*1.21).round(5) end def base_request(date, url) formatted_date = date.strftime("%F") doc = Nokogiri::XML(URI.open(url)) - prices = doc.xpath('.//xmlns:Point').map{|p| parse_point(p)} - #returns a hash with keys formatted "yyyy-mm-dd-hr" and values price (per kwh) - prices.map{|p| ["%s-%02d" % [formatted_date,(p[0]-1)], p[1]]}.to_h + prices = doc.xpath('.//xmlns:Point').map{|p| parse_point(p)} + # get start_time (in UTC) from XML docment + start_time = DateTime.parse(doc.xpath('.//xmlns:period.timeInterval//xmlns:start').text) + + #returns a hash with keys formatted "yyyy-mm-dd hr" and values price (per kwh) + # tag runs from 1-24. We need hours from 00-23, therefore substracting 1 + prices.map{|p| [start_time.advance(hours: (p[0]-1)), p[1]]}.to_h end end diff --git a/db/migrate/003_creates_prices.rb b/db/migrate/003_creates_prices.rb new file mode 100644 index 0000000..97cd471 --- /dev/null +++ b/db/migrate/003_creates_prices.rb @@ -0,0 +1,10 @@ +class CreatesPrices << ActiveRecord::Migration[4.2] + def change + create_table :prices do |t| + t.datetime :hour + t.float :usage_kwh + t.timestamps + end + + add_index :prices, :hour +end