diff --git a/app/helpers/ReadingsMailer.rb b/app/helpers/ReadingsMailer.rb index ce8792b..26d6c18 100644 --- a/app/helpers/ReadingsMailer.rb +++ b/app/helpers/ReadingsMailer.rb @@ -26,10 +26,12 @@ class ReadingsMailer # Fetch today's usage usage_today = Reading.diff_on(date) consumption_today, production_today = Reading.consumed_and_produced_for_diff(usage_today) + net_consumption_high, net_consumption_low = Reading.net_consumed_high_and_low_for_diff(usage_today) # Calculate costs for oxxio and easy energy c = Cost.new - oxxio_cost = c.oxxio_energy_cost(date.to_s,usage_today[:total_kwh_consumed_high]-usage_today[:total_kwh_produced_high], usage_today[:total_kwh_consumed_low]-usage_today[:total_kwh_produced_low]) + oxxio_normaal_cost, oxxio_dal_cost = c.oxxio_energy_cost(date.to_s,net_consumption_high,net_consumption_low) + oxxio_cost = oxxio_normaal_cost+oxxio_dal_cost easy_cost = c.easy_energy_cost_barplot(date) # side effect: generates a PNG # rounding oxxio_cost = oxxio_cost.round(2) @@ -55,8 +57,8 @@ class ReadingsMailer html_part do content_type 'text/html; charset=UTF-8' body "
Total kWH electricity consumed: #{usage_today[:total_kwh_consumed_high] + usage_today[:total_kwh_consumed_low]}
" + - "Total kWH electricity produced: #{usage_today[:total_kwh_produced_high] + usage_today[:total_kwh_produced_low]}
" + + "Total kWH electricity consumed: #{consumption_today}
" + + "Total kWH electricity produced: #{production_today}
" + "Total m3 gas consumed: #{usage_today[:total_m3_gas_consumed]}
" + "" + "kWH cost (Oxxio): EUR #{ oxxio_cost}
" + @@ -70,5 +72,75 @@ class ReadingsMailer mail.deliver! end + + # default is current year + def deliver_for_month(month, year=nil) + return if (month <1 || month >12) + + year = Date.today.year unless year + date = Date.parse("%s%.2d01" % [year,month]) + date_str = date.strftime("%B %Y") + + # Read SMTP options from smtp.yml + smtp_opts = YAML::load(File.open('config/smtp.yml')).symbolize_keys + smtp_opts.merge!(SSL_OPTS) if smtp_opts[:ssl] && smtp_opts[:ssl_verify_mode].eql?("none") + + # Fetch today's usage + usage_month = Reading.diff_in_month(date) + consumption_month, production_month = Reading.consumed_and_produced_for_diff(usage_month) + net_consumption_normaal, net_consumption_dal = Reading.net_consumed_high_and_low_for_diff(usage_month) + + + # Calculate costs for oxxio and easy energy + c = Cost.new + vat = 1 + c.vat_at(date) + + # cost with VAT, but without energiebelasting. + oxxio_raw_cost = c.oxxio_energy_cost(date.to_s,net_consumption_normaal, net_consumption_dal, false).sum.round(2) + easy_energy_raw_cost = c.easy_energy_raw_cost_in_month(date).compact.sum.round(2) + + # cost with VAT and with energiebelasting + oxxio_cost = c.oxxio_energy_cost(date.to_s,net_consumption_normaal, net_consumption_dal).sum.round(2) + easy_energy_cost = c.easy_energy_cost_in_month(date).compact.sum.round(2) + + # opslag Easy Energy + easy_energy_opslag = (c.easy_energy_rate(date.to_s)*vat*(net_consumption_normaal + net_consumption_dal)).round(2) + + mail = Mail.new do + delivery_method :smtp, smtp_opts + to 'a.t.van.halteren@vu.nl' + from 'SmartMeterTotal kWH electricity consumed: #{consumption_month}
" + + "Total kWH electricity produced: #{production_month}
" + + "Total m3 gas consumed: #{usage_month[:total_m3_gas_consumed]}
" + + "" + + "Levering kWH cost (Oxxio): EUR #{ oxxio_raw_cost}
" + + "Levering kWH cost (EasyEnergy): EUR #{ easy_energy_raw_cost}
" + + "Total kWH cost (Oxxio): EUR #{ oxxio_cost}
" + + "Total kWH cost (EasyEnergy): EUR #{ easy_energy_cost} , inclusief opslag van EUR #{ easy_energy_opslag }
" + end + + end + + mail.deliver! + end end end \ No newline at end of file diff --git a/app/models/cost.rb b/app/models/cost.rb index 3a86cac..c7b377c 100644 --- a/app/models/cost.rb +++ b/app/models/cost.rb @@ -45,7 +45,9 @@ class Cost end # Assume: usage_kwh_cost, return_kwh_cost already includes vat - def add_tax(formatted_hour,usage_kwh,usage_kwh_cost,return_kwh, return_kwh_cost) + # calling this with only 'usage_kwh' parameter returns the tax amount for those kwh only. + # + def add_tax(formatted_hour,usage_kwh,usage_kwh_cost=0.0,return_kwh=0.0, return_kwh_cost=0.0) return nil if (usage_kwh.nil? || usage_kwh_cost.nil? || return_kwh.nil? || return_kwh_cost.nil?) vat = 1 + vat_at(Date.parse(formatted_hour)) @@ -117,6 +119,32 @@ class Cost g.write("plots/easy_tariff_%s.png" % date.strftime("%F")) end + # calculate the hourly cost (raw!) between start_hour and end_hour + # raw means: entsoe prices + VAT + def easy_energy_raw_hourly_cost_between(start_hour, end_hour) + begin_hour = start_hour + costs = [] + while(begin_hour < end_hour) do + # get usage_kwh/return_kwh for one hour + begin_hour_plus1 = begin_hour.end_of_hour + hour_readings = Reading.where("created_at > :begin AND created_at < :end", {:begin => begin_hour, :end => begin_hour_plus1}) + hour_diff = hour_readings.last ? hour_readings.last.diff(hour_readings.first) : UNKNOWN_READING + # helper to remove distiction between low/high tarif consumption + usage_kwh, return_kwh = Reading.consumed_and_produced_for_diff(hour_diff) + + formatted_hour = begin_hour.strftime("%F %H") + # calculate RAW price (entsoe price + VAT) + kwh_price = entsoe.price_at(formatted_hour)*(1+vat_at(Date.parse(formatted_hour))) + hour_cost = (usage_kwh.nil? || return_kwh.nil? || kwh_price.nil?) ? nil : ((usage_kwh-return_kwh)*kwh_price) + costs << hour_cost + + # do the next hour + begin_hour = begin_hour.advance(:hours => 1) + end + # give the result + costs + end + # calculate the hourly cost between start_hour and end_hour def easy_energy_hourly_cost_between(start_hour, end_hour) begin_hour = start_hour @@ -158,6 +186,26 @@ class Cost costs end + # calculate leveringskosten (entsoe prices + VAT) in one month + # date = arbitrary day for the month + def easy_energy_raw_cost_in_month(date) + hour_start = date.beginning_of_month.in_time_zone(zone).beginning_of_day + hour_end = date.end_of_month.in_time_zone(zone).end_of_day + # can't get cost for the future + hour_end = Time.now if hour_end > Time.now + + easy_energy_raw_hourly_cost_between(hour_start,hour_end) + end + + def easy_energy_cost_in_month(date) + hour_start = date.beginning_of_month.in_time_zone(zone).beginning_of_day + hour_end = date.end_of_month.in_time_zone(zone).end_of_day + # can't get cost for the future + hour_end = Time.now if hour_end > Time.now + + easy_energy_hourly_cost_between(hour_start,hour_end) + end + def easy_energy_hourly_cost_for(date) hour_start = date.in_time_zone(zone).beginning_of_day day_end = hour_start.advance(days: 1) @@ -204,8 +252,9 @@ class Cost high_tariff ? 0.47758 : 0.34165 end end - - def oxxio_energy_cost(formatted_hour, normaal_kwh, dal_kwh, year_shift=0) + + # Optional: raw! (tarif + VAT) cost + def oxxio_energy_cost(formatted_hour, normaal_kwh, dal_kwh, with_tax=true, year_shift=0) return nil if (normaal_kwh.nil? || dal_kwh.nil?) #year = Date.parse(formatted_hour).year+year_shift date = Date.parse(formatted_hour).advance(years: year_shift) @@ -236,16 +285,24 @@ class Cost normaal_kwh_cost = 0.47758*vat dal_kwh_cost = 0.34165*vat else + p "Not supported interval Oxxio for value: %d" % date.to_time.to_i # catch-all, incase 'formated_hour' is outside any of the cases normaal_kwh_cost = 0.0 dal_kwh_cost = 0.0 end - normaal_cost = add_tax(formatted_hour, normaal_kwh,normaal_kwh_cost,0,0) # return_kwh already accounted for - dal_cost = add_tax(formatted_hour, dal_kwh, dal_kwh_cost,0,0) + + if with_tax + normaal_cost = add_tax(formatted_hour, normaal_kwh,normaal_kwh_cost) # return_kwh already accounted for + dal_cost = add_tax(formatted_hour, dal_kwh, dal_kwh_cost) + else + normaal_cost = normaal_kwh*normaal_kwh_cost + dal_cost = dal_kwh*dal_kwh_cost + end + # result - normaal_cost + dal_cost + return normaal_cost, dal_cost end - + # # Entsoe # diff --git a/app/models/reading.rb b/app/models/reading.rb index 83a7325..66f9920 100644 --- a/app/models/reading.rb +++ b/app/models/reading.rb @@ -67,6 +67,16 @@ class Reading < ActiveRecord::Base def day(date) Reading.where("created_at > :begin AND created_at < :end", { :begin => date.to_date.beginning_of_day, :end => date.to_date.end_of_day}) end + + def in_month(date) + hour_start = date.beginning_of_month.beginning_of_day + hour_end = date.end_of_month.end_of_day + # can't get cost for the future + hour_end = Time.now if hour_end > Time.now + + Reading.where("created_at > :begin AND created_at < :end", { :begin => hour_start, :end => hour_end}) + + end def max_charge_kwh=(kwh) @@max_charge_kwh = kwh @@ -78,12 +88,19 @@ class Reading < ActiveRecord::Base # do not make distinction between high and low consumption/production def consumed_and_produced_for_diff(d) - usage_kwh = (d[:total_kwh_consumed_high].nil? || d[:total_kwh_consumed_low].nil?) ? nil : d[:total_kwh_consumed_high] + d[:total_kwh_consumed_low] return_kwh = (d[:total_kwh_produced_high].nil? || d[:total_kwh_produced_low].nil?) ? nil : d[:total_kwh_produced_high] + d[:total_kwh_produced_low] return usage_kwh, return_kwh end + + # calculate net_consumption (= consumption-production) + def net_consumed_high_and_low_for_diff(d) + net_consumed_high = (d[:total_kwh_consumed_high].nil? || d[:total_kwh_produced_high].nil?) ? nil : d[:total_kwh_consumed_high]-d[:total_kwh_produced_high] + net_consumed_low = (d[:total_kwh_consumed_low].nil? || d[:total_kwh_produced_low].nil?) ? nil : d[:total_kwh_consumed_low]-d[:total_kwh_produced_low] + + return net_consumed_high, net_consumed_low + end def diff_on(date) readings_on = day(date) @@ -106,5 +123,22 @@ class Reading < ActiveRecord::Base { :total_kwh_consumed_high => 0, :total_kwh_consumed_low => 0, :total_kwh_produced_high => 0, :total_kwh_produced_low => 0, :total_m3_gas_consumed => 0 } end end + + def diff_in_month(date) + hour_start = date.beginning_of_month.beginning_of_day + hour_end = date.end_of_month.end_of_day + # can't get cost for the future + hour_end = Time.now if hour_end > Time.now + + readings_in_month = Reading.where("created_at > :begin AND created_at < :end", { :begin => hour_start, :end => hour_end}) + last = readings_in_month.last + if last + last.diff(readings_in_month.first) + else + { :total_kwh_consumed_high => 0, :total_kwh_consumed_low => 0, :total_kwh_produced_high => 0, :total_kwh_produced_low => 0, :total_m3_gas_consumed => 0 } + end + + end + end end diff --git a/report_mailer.rb b/report_mailer.rb index e2ef47d..59b121a 100644 --- a/report_mailer.rb +++ b/report_mailer.rb @@ -12,6 +12,13 @@ connection_details = YAML::load(File.open('config/database.yml')) ActiveRecord::Base.establish_connection(connection_details) if __FILE__ == $0 - ReadingsMailer.deliver(Date.today.advance(days: -1)) + yesterday = Date.today.advance(days: -1) + ReadingsMailer.deliver(yesterday) + + # are we at the start of a month? + if (Date.today.beginning_of_month == Date.today) + # then also send report for previous month (and year) + ReadingsMailer.deliver_for_month(yesterday.month, yesterday.year) + end end #p sync