diff --git a/Gemfile b/Gemfile index 182522b..a847c88 100644 --- a/Gemfile +++ b/Gemfile @@ -8,3 +8,7 @@ gem 'rufus-scheduler' gem 'daemons' gem 'mail' gem 'nokogiri' +gem 'ruby-gr' +gem 'gr-plot' +gem 'histogram' +gem 'numo-narray' diff --git a/Gemfile.lock b/Gemfile.lock index 940edce..b9cfff9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,9 +15,13 @@ GEM daemons (1.4.1) et-orbi (1.2.6) tzinfo + fiddle (1.1.0) fugit (1.5.2) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.4) + gr-plot (0.0.1) + ruby-gr + histogram (0.2.4.1) i18n (1.8.11) concurrent-ruby (~> 1.0) mail (2.7.1) @@ -29,8 +33,14 @@ GEM nokogiri (1.13.0) mini_portile2 (~> 2.7.0) racc (~> 1.4) + numo-narray (0.9.2.1) + pkg-config (1.4.9) raabro (1.4.0) racc (1.6.0) + ruby-gr (0.66.0.0) + fiddle + numo-narray + pkg-config rufus-scheduler (3.8.0) fugit (~> 1.1, >= 1.1.6) serialport (1.3.2) @@ -44,9 +54,13 @@ PLATFORMS DEPENDENCIES activerecord daemons + gr-plot + histogram mail mysql2 nokogiri + numo-narray + ruby-gr rufus-scheduler serialport state_pattern diff --git a/app/models/cost.rb b/app/models/cost.rb index 238eb13..41d616d 100644 --- a/app/models/cost.rb +++ b/app/models/cost.rb @@ -1,4 +1,5 @@ require 'open-uri' +require 'gr/plot' EASY_ENERGY_TARIFFS = {} # See https://www.belastingdienst.nl/wps/wcm/connect/bldcontentnl/belastingdienst/zakelijk/overige_belastingen/belastingen_op_milieugrondslag/tarieven_milieubelastingen/tabellen_tarieven_milieubelastingen @@ -50,65 +51,48 @@ class Cost end ###################################################### - # Easy Energy API (proprietary) - better to use entsoe + # Easy Energy - makes use of entsoe, adds EasyEnergy opslag ###################################################### - # returns a hash with keys formatted "yyyy-mm-dd-hr" and values [usage, return] - # e.g. { 2021-12-16-06"=>[0.36058, 0.298] } - def easy_energy_tariffs(date) - p "Fetching EasyEnergy tariffs for %s" % date.strftime("%F-%H") - - # calculate offset (date is in UTC, and we want to have tariffs in Amsterdam zone) - zone = 'Amsterdam' - offset = DateTime.now.in_time_zone(zone).utc_offset - date = date.beginning_of_day.advance(seconds: offset) - - url = "https://mijn.easyenergy.com/nl/api/tariff/getapxtariffs?startTimestamp=%s&endTimestamp=%s&grouping=" % [date.strftime("%F %T"),date.advance(:hours => 24).strftime("%F %T")] - #p urlvandaag - json = JSON.load(URI::open(url)) - # advancing with 1 hrs (to offset for something?) - json.map{|t| [DateTime.parse(t["Timestamp"]).strftime("%F-%H"), [t["TariffUsage"], t["TariffReturn"]]]}.to_h - end - def easy_energy_rate(formatted_hour) - unless EASY_ENERGY_TARIFFS.key?(formatted_hour) - EASY_ENERGY_TARIFFS.merge!(easy_energy_tariffs(Date.parse(formatted_hour))) - end - EASY_ENERGY_TARIFFS[formatted_hour] + year = Date.parse(formatted_hour).year + case year + when 2020..2022 + # opslag, zonder BTW + 0.00800 + end end def easy_energy_cost(formatted_hour, usage_kwh, return_kwh) return nil if (usage_kwh.nil? || return_kwh.nil?) - usage_kwh_cost, return_kwh_cost = easy_energy_rate(formatted_hour) + usage_kwh_cost = return_kwh_cost = (entsoe.price_at(formatted_hour)+easy_energy_rate(formatted_hour))*(1+vat_at(Date.parse(formatted_hour))) add_tax(formatted_hour, usage_kwh, usage_kwh_cost, return_kwh, return_kwh_cost) end - def easy_energy_high_low(date) - hour_start = date.beginning_of_day + def easy_energy_hours(date) + hour_start = date.in_time_zone(zone).beginning_of_day day_end = hour_start.advance(days: 1) - max_rate = 0.0 - min_rate = 100.0 - min_hour = nil - max_hour = nil + result = [] while(hour_start < day_end) do - easy_usage_rate, easy_return_rate = easy_energy_rate(hour_start.strftime("%F-%H")) - unless easy_usage_rate.nil? - # determine max - if easy_usage_rate > max_rate - max_rate = easy_usage_rate - max_hour = hour_start.strftime("%F-%H") - end - # determine min - if easy_usage_rate < min_rate - min_rate = easy_usage_rate - min_hour = hour_start.strftime("%F-%H") - end - end + formatted_hour = hour_start.strftime("%F %H") + result << easy_energy_cost(formatted_hour, 1, 0) hour_start = hour_start.advance(:hours => 1) - end - return min_hour,max_hour + end + result end + + def easy_energy_barplot(date) + hours = (0..23).to_a + costs = easy_energy_hours(date) + GR.barplot(hours,costs) + # make sure you have set GKS_WSTYPE=100 in the environment (for headless setup) + title = "Kosten per kwH (incl. belastingen en BTW) - %s" % date.strftime("%A, %e %B %Y") + xlabel = "uur" + ylabel = "EUR" + GR.savefig("easy_%s.png" % date.strftime("%F"), title: title, xlabel: xlabel, ylabel: ylabel) + end + ###################################################### # Oxxio rates and cost @@ -174,7 +158,7 @@ class Cost ###################################################### def hours(date, year_shift=0) - hour_start = date.in_time_zone("Amsterdam").beginning_of_day + hour_start = date.in_time_zone(zone).beginning_of_day day_end = hour_start.advance(days: 1) result = [] lowest_hour, highest_hour,high_hours = entsoe.high_low_hours(date.advance(years: year_shift)) @@ -190,7 +174,7 @@ class Cost return_kwh = hour_diff[:total_kwh_produced_high] + hour_diff[:total_kwh_produced_low] rescue nil formatted_hour = hour_start.advance(years: year_shift).strftime("%F %H") - entsoe_cost = entsoe_energy_cost(formatted_hour, usage_kwh, return_kwh) # without battery use + easy_cost = easy_energy_cost(formatted_hour, usage_kwh, return_kwh) # without battery use # # Make battery work @@ -210,7 +194,7 @@ class Cost end end end - entsoe_cost_with_battery = entsoe_energy_cost(formatted_hour, usage_kwh, return_kwh) # with battery use + easy_cost_with_battery = easy_energy_cost(formatted_hour, usage_kwh, return_kwh) # with battery use # # end of battery work @@ -230,8 +214,8 @@ class Cost return_kwh, battery.battery_kwh, entsoe.price_at(formatted_hour), # entsoe rate - entsoe_cost_with_battery, - entsoe_cost, + easy_cost_with_battery, + easy_cost, oxxio_rate, oxxio_cost] diff --git a/ar-no-rails.rb b/ar-no-rails.rb index 60a853c..4f93e91 100644 --- a/ar-no-rails.rb +++ b/ar-no-rails.rb @@ -2,6 +2,8 @@ require "rubygems" require "bundler/setup" require "active_record" require "open-uri" +require 'gr/plot' +require 'histogram' project_root = File.dirname(File.absolute_path(__FILE__)) Dir.glob(project_root + "/app/models/*.rb").each{|f| require f} @@ -9,7 +11,6 @@ Dir.glob(project_root + "/app/models/*.rb").each{|f| require f} connection_details = YAML::load(File.open('config/database.yml')) ActiveRecord::Base.establish_connection(connection_details) - if __FILE__ == $0 puts "Count of Pages: #{Page.count}" end