smartermeter 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.2 (March 29, 2011)
4
+ * Added support for Brighter Planet's Electricity API.
5
+ * Fixed encryption of passwords that had lengths other than multiples of
6
+ 8.
7
+ * Added more extensive documentation of the library.
8
+
3
9
  ## 0.3.1 (March 15th, 2011)
4
10
  * Changed name from "Smartermeter" to "SmarterMeter"
5
11
  * Updated the .detect\_charset monkeypatch for the newer mechanize
data/Gemfile CHANGED
@@ -2,5 +2,6 @@ source :rubygems
2
2
  gemspec
3
3
 
4
4
  # Used only in the Java client, which isn't distributed as a gem
5
- gem "profligacy"
6
- gem "jruby-openssl"
5
+ gem "nokogiri", ">= 1.4.4", :platforms => :jruby
6
+ gem "profligacy", :platforms => :jruby
7
+ gem "jruby-openssl", :platforms => :jruby
data/README.md CHANGED
@@ -15,6 +15,25 @@ Getting Started
15
15
  gem install smartermeter
16
16
  smartermeter
17
17
 
18
+ Manipulating the data
19
+ ---------------------
20
+
21
+ After you've successfully downloaded one set of data, you should be able
22
+ to manipulate it using ruby like so:
23
+
24
+ require 'rubygems'
25
+ require 'smartermeter'
26
+
27
+ config = YAML.load_file(File.expand_path("~/.smartermeter"))
28
+ csv_file = Dir.glob(File.join(config[:data_dir], "*.csv")).last
29
+
30
+ samples = SmarterMeter::Samples.parse_csv(csv_file)
31
+ kwh_used = samples.total_kwh
32
+ api = SmarterMeter::Services::BrighterPlanet.new
33
+ puts api.calculate_kg_carbon(kwh_used)
34
+
35
+ For futher information see the [API docs][rdoc]
36
+
18
37
  Google PowerMeter
19
38
  -----------------
20
39
 
@@ -44,7 +63,7 @@ In order to build the self contained binaries, you'll need Java 1.6 and
44
63
  apt-get install nsis sun-java6-jre
45
64
  git clone git://github.com/mcolyer/smartermeter.git
46
65
  cd smartermeter
47
- bundle install --path vendor/gems --without test
66
+ bundle install --path vendor/gems
48
67
  rake package
49
68
 
50
69
  The installer will be generated in pkg/
@@ -76,3 +95,4 @@ part of their [Fellowship Program][3]
76
95
  [1]: http://nsis.sourceforge.net/
77
96
  [2]: http://brighterplanet.com/
78
97
  [3]: http://brighterplanet.github.com/fellowship.html
98
+ [rdoc]: http://rdoc.info/github/mcolyer/smartermeter/master/frames
data/Rakefile CHANGED
@@ -48,7 +48,7 @@ task :default => :test
48
48
  require 'rake/testtask'
49
49
  Rake::TestTask.new(:test) do |test|
50
50
  test.libs << 'lib' << 'test'
51
- test.pattern = 'specs/**/*_spec.rb'
51
+ test.pattern = 'spec/**/*_spec.rb'
52
52
  test.verbose = true
53
53
  end
54
54
 
@@ -122,6 +122,10 @@ task :package_gems do
122
122
  specifications.reject! { |s| s.include? "rspec" }
123
123
  specifications.reject! { |s| s.include? "minitar" }
124
124
  specifications.reject! { |s| s.include? "ruby-debug" }
125
+ specifications.reject! { |s| s.include? "addressable" }
126
+ specifications.reject! { |s| s.include? "diff-lcs" }
127
+ specifications.reject! { |s| s.include? "vcr" }
128
+ specifications.reject! { |s| s.include? "webmock" }
125
129
  dest_dir = File.join(File.dirname(__FILE__), "pkg", "base", "gems", "specifications")
126
130
  FileUtils.rm_rf(dest_dir)
127
131
  FileUtils.mkdir_p(dest_dir)
@@ -131,6 +135,10 @@ task :package_gems do
131
135
  gems.reject! { |s| s.include? "rspec" }
132
136
  gems.reject! { |s| s.include? "minitar" }
133
137
  gems.reject! { |s| s.include? "ruby-debug" }
138
+ gems.reject! { |s| s.include? "addressable" }
139
+ gems.reject! { |s| s.include? "diff-lcs" }
140
+ gems.reject! { |s| s.include? "vcr" }
141
+ gems.reject! { |s| s.include? "webmock" }
134
142
  dest_dir = File.join(File.dirname(__FILE__), "pkg", "base", "gems", "gems")
135
143
  FileUtils.rm_rf(dest_dir)
136
144
  FileUtils.mkdir_p(dest_dir)
@@ -4,6 +4,7 @@ require 'yaml'
4
4
  require 'date'
5
5
 
6
6
  module SmarterMeter
7
+ # @private
7
8
  class Daemon
8
9
 
9
10
  def initialize(interface)
@@ -63,6 +64,8 @@ module SmarterMeter
63
64
 
64
65
  # Takes the unencrypted password and encrypts it.
65
66
  def password=(unencrypted)
67
+ padding_length = 8 - (unencrypted.bytesize % 8)
68
+ unencrypted = unencrypted + ("\0" * padding_length)
66
69
  @config[:password] = cipher.encrypt_block(unencrypted)
67
70
  end
68
71
 
@@ -70,7 +73,7 @@ module SmarterMeter
70
73
  def password
71
74
  password = @config.fetch(:password, nil)
72
75
  if password
73
- cipher.decrypt_block(password)
76
+ cipher.decrypt_block(password).gsub("\0", "")
74
77
  else
75
78
  password
76
79
  end
@@ -180,7 +183,7 @@ module SmarterMeter
180
183
  next if data.empty?
181
184
 
182
185
  @ui.log.info("Verifying #{date}")
183
- samples = Sample.parse_csv(data).values.first
186
+ samples = Samples.parse_csv(data).values.first
184
187
  first_sample = samples.first
185
188
 
186
189
  if first_sample.kwh
@@ -207,7 +210,7 @@ module SmarterMeter
207
210
  case @config[:transport]
208
211
  when :google_powermeter
209
212
  @ui.log.info("Uploading #{date} to Google PowerMeter")
210
- transport = SmarterMeter::Transports::GooglePowerMeter.new(@config[:google_powermeter])
213
+ transport = SmarterMeter::Services::GooglePowerMeter.new(@config[:google_powermeter])
211
214
  if transport.upload(samples)
212
215
  @ui.log.info("Upload for #{date} complete")
213
216
  else
@@ -3,6 +3,7 @@ require 'profligacy/swing'
3
3
  require 'profligacy/lel'
4
4
 
5
5
  module SmarterMeter
6
+ # @private
6
7
  module Interfaces
7
8
  class Swing
8
9
  include_package "java.awt"
@@ -147,6 +148,7 @@ module SmarterMeter
147
148
  end
148
149
  end
149
150
 
151
+ # @private
150
152
  class Wizard
151
153
  include_package "javax.swing"
152
154
  include_package "java.awt"
@@ -2,67 +2,40 @@ require 'date'
2
2
  require 'time'
3
3
 
4
4
  module SmarterMeter
5
+ # Represents a single hourly sample taken from the PG&E hourly electricity
6
+ # data. It's the most basic data unit of SmarterMeter.
5
7
  class Sample
6
8
  attr_accessor :time, :kwh
7
9
 
8
- # Parses the CSV returned by PG&E
10
+ # Creates a new Sample.
9
11
  #
10
- # data - The string containing the CSV returned by PG&E
11
- #
12
- # Returns a Hash of with keys as Date objects and values of Arrays of samples.
13
- def self.parse_csv(data)
14
- samples = {}
15
- date_re = /([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/
16
-
17
- # Apparently they felt the need to put a = outside of the correct place
18
- data = data.gsub('=','')
19
-
20
- hour_increment = 60*60
21
- CSV.parse(data) do |row|
22
- next unless row.length > 0 and date_re.match row[0]
23
-
24
- month, day, year = date_re.match(row[0]).captures
25
- month = month.to_i
26
- day = day.to_i
27
- year = year.to_i
28
-
29
- timestamp = Time.local(year, month, day, 0) - hour_increment
30
- next if row[1].include? "$"
31
- hourly_samples = row[1..24].map do |v|
32
- if v == "-"
33
- kwh = nil
34
- else
35
- kwh = v.to_f
36
- end
37
-
38
- timestamp = timestamp + hour_increment
39
- Sample.new(timestamp, kwh)
40
- end
41
- samples[Date.new(year, month, day)] = hourly_samples
42
- end
43
- samples
44
- end
45
-
12
+ # @param [Time] time the start of the sample period.
13
+ # @param [Float] kwh the number of killowatt hours used during the period of this sample.
14
+ # @return [Sample] the new Sample.
46
15
  def initialize(time, kwh)
47
16
  @time = time
48
17
  @kwh = kwh
49
18
  end
50
19
 
51
- # Public: The start time of this measurement
20
+ # The start time of this measurement in UTC.
52
21
  #
53
- # Returns the time in the format of 2011-01-06T09:00:00.000Z
22
+ # @return [String] the time in the format of 2011-01-06T09:00:00.000Z
54
23
  def utc_start_time
55
24
  @time.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
56
25
  end
57
26
 
58
- # Public: The stop time of this measurement, it's assumed to be 1 hour after
59
- # the start.
27
+ # The stop time of this measurement in UTC. It's assumed to be 1 hour after
28
+ # the start as that is the current resolution of PG&E's data.
60
29
  #
61
- # Returns the time in the format of 2011-01-06T09:00:00.000Z
30
+ # @return [String] the time in the format of 2011-01-06T09:00:00.000Z
62
31
  def utc_stop_time
63
- (@time + 60*60).utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
32
+ one_hour = 60*60
33
+ (@time + one_hour).utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
64
34
  end
65
35
 
36
+ # Interrogates the current state of the Sample.
37
+ #
38
+ # Returns [String] a compact representation of the Sample.
66
39
  def inspect
67
40
  "<Sample #{@time} #{@kwh}>"
68
41
  end
@@ -0,0 +1,65 @@
1
+ require 'date'
2
+ require 'time'
3
+
4
+ module SmarterMeter
5
+ # Represents a collection of samples. In some cases it's useful to operate on
6
+ # groups of samples and this class provides that functionality.
7
+ class Samples < Hash
8
+ # Parses the CSV returned by PG&E and creates a Samples collection.
9
+ #
10
+ # @param [String] data the string containing the CSV returned by PG&E
11
+ # @return [Samples] creates a Samples collection from the given data.
12
+ def self.parse_csv(data)
13
+ samples = Samples.new
14
+ date_re = /([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/
15
+
16
+ # Apparently they felt the need to put a = outside of the correct place
17
+ data = data.gsub('=','')
18
+
19
+ hour_increment = 60*60
20
+ CSV.parse(data) do |row|
21
+ next unless row.length > 0 and date_re.match row[0]
22
+
23
+ month, day, year = date_re.match(row[0]).captures
24
+ month = month.to_i
25
+ day = day.to_i
26
+ year = year.to_i
27
+
28
+ timestamp = Time.local(year, month, day, 0) - hour_increment
29
+ next if row[1].include? "$"
30
+ hourly_samples = row[1..24].map do |v|
31
+ if v == "-"
32
+ kwh = nil
33
+ else
34
+ kwh = v.to_f
35
+ end
36
+
37
+ timestamp = timestamp + hour_increment
38
+ Sample.new(timestamp, kwh)
39
+ end
40
+ samples[Date.new(year, month, day)] = hourly_samples
41
+ end
42
+ samples
43
+ end
44
+
45
+ # Calculates the total number of kilowatt hours for all samples.
46
+ #
47
+ # @return [Float] the sum of kilowatt hours for all samples within this collection. If no samples are found 0 is returned.
48
+ def total_kwh
49
+ self.keys.reduce(0) { |sum, d| sum + total_kwh_on(d) }
50
+ end
51
+
52
+ # Calculates the total number of kilowatt hours
53
+ #
54
+ # @param [Date] date The date of the samples to include within the total.
55
+ #
56
+ # @return [Float] the sum of kilowatt hours for samples made of the given day. If none are found 0 is returned.
57
+ def total_kwh_on(date)
58
+ if self[date]
59
+ self[date].reduce(0) { |sum, s| sum + (s.kwh or 0) }
60
+ else
61
+ 0
62
+ end
63
+ end
64
+ end
65
+ end
@@ -2,12 +2,21 @@ require 'mechanize'
2
2
  require 'csv'
3
3
 
4
4
  module SmarterMeter
5
+ # Provides access to the PG&E SmartMeter data through a ruby interface. This
6
+ # class depends on the PG&E website to function the same that it does today,
7
+ # so if something stops working its likely that something changed on PG&E's
8
+ # site and this class will need to be adapted.
5
9
  class Service
6
10
  LOGIN_URL = "http://www.pge.com/myhome/"
7
11
  OVERVIEW_URL = "https://www.pge.com/csol/actions/login.do?aw"
8
12
  ENERGYGUIDE_AUTH_URL = "https://www.energyguide.com/LoadAnalysis/LoadAnalysis.aspx?Referrerid=154"
9
13
 
14
+ # Provides access to the last page retrieved by mechanize. Useful for
15
+ # debugging and reporting errors.
10
16
  attr_reader :last_page
17
+
18
+ # Provides access to the last exception thrown while accessing PG&E's site.
19
+ # Useful for debugging/error reporting.
11
20
  attr_reader :last_exception
12
21
 
13
22
  def initialize
@@ -16,7 +25,10 @@ module SmarterMeter
16
25
  }
17
26
  end
18
27
 
19
- # Returns true upon succesful login and false otherwise
28
+ # Authenticates to the PG&E's website. Only needs to be performed once per
29
+ # instance of this class.
30
+ #
31
+ # @return [Boolean] true upon succesful login and false otherwise
20
32
  def login(username, password)
21
33
  begin
22
34
  @agent.get(LOGIN_URL) do |page|
@@ -61,6 +73,15 @@ module SmarterMeter
61
73
  end
62
74
  end
63
75
 
76
+ # Downloads a CSV containing hourly date on that date. Up to a week worth
77
+ # of other data will be included depending on which day of the week that
78
+ # you request.
79
+ #
80
+ # PG&E compiles this data on a weekly schedule so if you ask for Monday
81
+ # you'll get the previous Sunday and the following days upto the next
82
+ # Sunday.
83
+ #
84
+ # @return [String] the CSV data.
64
85
  def fetch_csv(date)
65
86
  raise RuntimeException, "login must be called before fetch_csv" unless @authenticated
66
87
 
@@ -0,0 +1,59 @@
1
+ require 'restclient'
2
+ require 'json'
3
+ require 'erb'
4
+
5
+ module SmarterMeter
6
+ module Services
7
+ # Allows users to calculate the carbon produced by their energy usage by
8
+ # accessing the Brighter Planet CM1 Electricity API.
9
+ #
10
+ # More details can be found here:
11
+ # http://carbon.brighterplanet.com/models/electricity_use
12
+ #
13
+ # Example:
14
+ # api = SmarterMeter::Services::BrighterPlanet.new
15
+ # puts api.calculate_kg_carbon(10.1)
16
+ #
17
+ # Prints:
18
+ # 0.6460529833458619
19
+ #
20
+ class BrighterPlanet
21
+ # The api key required for commericial access to the API. For more detail see:
22
+ # http://carbon.brighterplanet.com/pricing
23
+ attr_accessor :api_key
24
+
25
+ # Initializes the Brigher Planet CM1 Electricity API.
26
+ #
27
+ # Example:
28
+ #
29
+ # SmarterMeter::Services::BrighterPlanet.new do |c|
30
+ # c.api_key = "key"
31
+ # end
32
+ #
33
+ # @return [BrighterPlanet]
34
+ def initialize
35
+ yield self if block_given?
36
+ end
37
+
38
+ # Calculates the number of kilograms of carbon produced from the given
39
+ # electrical energy usage.
40
+ #
41
+ # Note: this is an estimate and depends on many factors, to improve
42
+ # accuracy include an optional zipcode of where this energy was consumed.
43
+ #
44
+ # @param [Float] kwh the number of kilowatt hours consumed.
45
+ # @params [Hash] opts can include `:zip_code` and/or `:date` to increase the accuracy of the estimate. `:date` should be in the following form: YYYY-MM-DD.
46
+ # @return [Float] kilograms of carbon produced by this much energy.
47
+ def calculate_kg_carbon(kwh, opts={})
48
+ allowed_keys = [:zip_code, :date]
49
+ non_permitted_keys = opts.keys.reject { |k| allowed_keys.include? k }
50
+ raise ArgumentError, "opts contains keys not found in #{allowed_keys}" unless non_permitted_keys.empty?
51
+
52
+ params = {:energy => kwh}
53
+ params.merge!(opts)
54
+ response = RestClient.get 'http://carbon.brighterplanet.com/electricity_uses.json', :params => params
55
+ JSON.parse(response.body)["emission"]
56
+ end
57
+ end
58
+ end
59
+ end
@@ -2,7 +2,7 @@ require 'net/https'
2
2
  require 'erb'
3
3
 
4
4
  module SmarterMeter
5
- module Transports
5
+ module Services
6
6
  class GooglePowerMeter
7
7
  def initialize(config)
8
8
  @config = config
data/lib/smartermeter.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'smartermeter/sample'
2
+ require 'smartermeter/samples'
2
3
  require 'smartermeter/service'
3
4
  require 'smartermeter/daemon'
4
- require 'smartermeter/transports/google_powermeter'
5
+ require 'smartermeter/services/google_powermeter'
6
+ require 'smartermeter/services/brighterplanet'
5
7
  require 'smartermeter/interfaces/cli'
6
8
 
7
9
  module SmarterMeter
8
- VERSION = "0.3.1"
10
+ VERSION = "0.3.2"
9
11
  end
data/smartermeter.gemspec CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'smartermeter'
16
- s.version = '0.3.1'
17
- s.date = '2011-03-15'
16
+ s.version = '0.3.2'
17
+ s.date = '2011-03-29'
18
18
  s.rubyforge_project = 'smartermeter'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -49,11 +49,15 @@ Gem::Specification.new do |s|
49
49
  ## List your runtime dependencies here. Runtime dependencies are those
50
50
  ## that are needed for an end user to actually USE your code.
51
51
  s.add_dependency('mechanize', ["= 1.0.0"])
52
- s.add_dependency('crypt', ["= 1.1.4"])
52
+ s.add_dependency('crypt19', ["= 1.2.1"])
53
+ s.add_dependency('rest-client', ["= 1.6.1"])
54
+ s.add_dependency('json_pure', ["= 1.5.1"])
53
55
 
54
56
  ## List your development dependencies here. Development dependencies are
55
57
  ## those that are only needed during development
56
- s.add_development_dependency('rspec', ["~> 2.4.0"])
58
+ s.add_development_dependency('rspec', ["~> 2.5.0"])
59
+ s.add_development_dependency('vcr', ["~> 1.7.0"])
60
+ s.add_development_dependency('webmock', ["~> 1.6.2"])
57
61
  s.add_development_dependency('minitar', ["~> 0.5.2"])
58
62
 
59
63
  ## Leave this section as-is. It will be automatically generated from the
@@ -79,21 +83,26 @@ Gem::Specification.new do |s|
79
83
  lib/smartermeter/interfaces/cli.rb
80
84
  lib/smartermeter/interfaces/swing.rb
81
85
  lib/smartermeter/sample.rb
86
+ lib/smartermeter/samples.rb
82
87
  lib/smartermeter/service.rb
83
- lib/smartermeter/transports/cacert.pem
84
- lib/smartermeter/transports/google_powermeter.erb
85
- lib/smartermeter/transports/google_powermeter.rb
88
+ lib/smartermeter/services/brighterplanet.rb
89
+ lib/smartermeter/services/cacert.pem
90
+ lib/smartermeter/services/google_powermeter.erb
91
+ lib/smartermeter/services/google_powermeter.rb
86
92
  smartermeter.gemspec
87
- specs/fixtures/data.csv
88
- specs/fixtures/expected_google_request.xml
89
- specs/sample_spec.rb
90
- specs/service_spec.rb
91
- specs/spec_helper.rb
92
- specs/transports/google_powermeter_spec.rb
93
+ spec/fixtures/data.csv
94
+ spec/fixtures/expected_google_request.xml
95
+ spec/fixtures/vcr_cassettes/brighterplanet.yml
96
+ spec/sample_spec.rb
97
+ spec/samples_spec.rb
98
+ spec/service_spec.rb
99
+ spec/services/brighterplanet_spec.rb
100
+ spec/services/google_powermeter_spec.rb
101
+ spec/spec_helper.rb
93
102
  ]
94
103
  # = MANIFEST =
95
104
 
96
105
  ## Test files will be grabbed from the file list. Make sure the path glob
97
106
  ## matches what you actually use.
98
- s.test_files = s.files.select { |path| path =~ /^specs\/*_spec.rb/ }
107
+ s.test_files = s.files.select { |path| path =~ /^spec\/*_spec.rb/ }
99
108
  end
File without changes
@@ -0,0 +1,106 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://carbon.brighterplanet.com:80/electricity_uses.json?energy=1
6
+ body:
7
+ headers:
8
+ accept:
9
+ - "*/*; q=0.5, application/xml"
10
+ accept-encoding:
11
+ - gzip, deflate
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ server:
18
+ - nginx/0.6.35
19
+ date:
20
+ - Sat, 19 Mar 2011 18:49:12 GMT
21
+ content-type:
22
+ - application/json; charset=utf-8
23
+ transfer-encoding:
24
+ - chunked
25
+ status:
26
+ - 200 OK
27
+ etag:
28
+ - "\"f8891da38901f85f0b33fdd539c84199\""
29
+ cache-control:
30
+ - max-age=0, private, must-revalidate
31
+ x-ua-compatible:
32
+ - IE=Edge,chrome=1
33
+ x-runtime:
34
+ - "0.174617"
35
+ body: "{\"timeframe\":\"2011-01-01/2012-01-01\",\"emission\":0.6460529833458619,\"emission_units\":\"kilograms\",\"errors\":[],\"reports\":[{\"committee\":{\"name\":\"emission\",\"quorums\":[{\"name\":\"from date, emission factor, loss factor and energy\",\"requirements\":[\"date\",\"emission_factor\",\"loss_factor\",\"energy\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.6460529833458619,\"quorum\":{\"name\":\"from date, emission factor, loss factor and energy\",\"requirements\":[\"date\",\"emission_factor\",\"loss_factor\",\"energy\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"emission_factor\",\"quorums\":[{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.606076,\"quorum\":{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"loss_factor\",\"quorums\":[{\"name\":\"from eGRID region\",\"requirements\":[\"egrid_region\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.0618788,\"quorum\":{\"name\":\"from eGRID region\",\"requirements\":[\"egrid_region\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"egrid_region\",\"quorums\":[{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":{\"egrid_region\":{\"loss_factor\":0.0618788,\"name\":\"US\"}},\"quorum\":{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"egrid_subregion\",\"quorums\":[{\"name\":\"from zip code\",\"requirements\":[\"zip_code\"],\"appreciates\":[],\"complies\":[]},{\"name\":\"default\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":{\"egrid_subregion\":{\"abbreviation\":\"US\",\"egrid_region_name\":\"US\",\"electricity_ch4_emission_factor\":0.000309198,\"electricity_ch4_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_co2_biogenic_emission_factor\":0.0,\"electricity_co2_biogenic_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_co2_emission_factor\":0.602982,\"electricity_co2_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_emission_factor\":0.606076,\"electricity_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_n2o_emission_factor\":0.00278485,\"electricity_n2o_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"name\":\"United States\",\"nerc_abbreviation\":\"US\",\"net_generation\":4056440000.0,\"net_generation_units\":\"megawatt_hours\"}},\"quorum\":{\"name\":\"default\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"date\",\"quorums\":[{\"name\":\"from timeframe\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":\"2011-01-01\",\"quorum\":{\"name\":\"from timeframe\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}}],\"methodology\":\"http://carbon.brighterplanet.com/electricity_uses.html?energy=1&timeframe=2011-01-01%2F2012-01-01\",\"execution_id\":\"cd84d18a392c2782e8b0a114dd65a225184823a4be28aea4896d2d6c01d18dae959051b2a26b06b6\",\"compliance\":[],\"scope\":null,\"energy\":1.0,\"date\":\"2011-01-01\",\"egrid_subregion\":{\"egrid_subregion\":{\"abbreviation\":\"US\",\"egrid_region_name\":\"US\",\"electricity_ch4_emission_factor\":0.000309198,\"electricity_ch4_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_co2_biogenic_emission_factor\":0.0,\"electricity_co2_biogenic_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_co2_emission_factor\":0.602982,\"electricity_co2_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_emission_factor\":0.606076,\"electricity_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_n2o_emission_factor\":0.00278485,\"electricity_n2o_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"name\":\"United States\",\"nerc_abbreviation\":\"US\",\"net_generation\":4056440000.0,\"net_generation_units\":\"megawatt_hours\"}},\"egrid_region\":{\"egrid_region\":{\"loss_factor\":0.0618788,\"name\":\"US\"}},\"loss_factor\":0.0618788,\"emission_factor\":0.606076}"
36
+ http_version: "1.1"
37
+ - !ruby/struct:VCR::HTTPInteraction
38
+ request: !ruby/struct:VCR::Request
39
+ method: :get
40
+ uri: http://carbon.brighterplanet.com:80/electricity_uses.json?energy=1&zip_code=94110
41
+ body:
42
+ headers:
43
+ accept:
44
+ - "*/*; q=0.5, application/xml"
45
+ accept-encoding:
46
+ - gzip, deflate
47
+ response: !ruby/struct:VCR::Response
48
+ status: !ruby/struct:VCR::ResponseStatus
49
+ code: 200
50
+ message: OK
51
+ headers:
52
+ server:
53
+ - nginx/0.6.35
54
+ date:
55
+ - Sat, 19 Mar 2011 19:15:01 GMT
56
+ content-type:
57
+ - application/json; charset=utf-8
58
+ transfer-encoding:
59
+ - chunked
60
+ status:
61
+ - 200 OK
62
+ etag:
63
+ - "\"91afe2c319e60d06dd3b10f60c90a15d\""
64
+ cache-control:
65
+ - max-age=0, private, must-revalidate
66
+ x-ua-compatible:
67
+ - IE=Edge,chrome=1
68
+ x-runtime:
69
+ - "0.041468"
70
+ body: "{\"timeframe\":\"2011-01-01/2012-01-01\",\"emission\":0.3484751557886446,\"emission_units\":\"kilograms\",\"errors\":[],\"reports\":[{\"committee\":{\"name\":\"emission\",\"quorums\":[{\"name\":\"from date, emission factor, loss factor and energy\",\"requirements\":[\"date\",\"emission_factor\",\"loss_factor\",\"energy\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.3484751557886446,\"quorum\":{\"name\":\"from date, emission factor, loss factor and energy\",\"requirements\":[\"date\",\"emission_factor\",\"loss_factor\",\"energy\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"emission_factor\",\"quorums\":[{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.32989,\"quorum\":{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"loss_factor\",\"quorums\":[{\"name\":\"from eGRID region\",\"requirements\":[\"egrid_region\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.0533328,\"quorum\":{\"name\":\"from eGRID region\",\"requirements\":[\"egrid_region\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"egrid_region\",\"quorums\":[{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":{\"egrid_region\":{\"loss_factor\":0.0533328,\"name\":\"W\"}},\"quorum\":{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"egrid_subregion\",\"quorums\":[{\"name\":\"from zip code\",\"requirements\":[\"zip_code\"],\"appreciates\":[],\"complies\":[]},{\"name\":\"default\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":{\"egrid_subregion\":{\"abbreviation\":\"CAMX\",\"egrid_region_name\":\"W\",\"electricity_ch4_emission_factor\":0.000342876,\"electricity_ch4_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_co2_biogenic_emission_factor\":0.0,\"electricity_co2_biogenic_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_co2_emission_factor\":0.328455,\"electricity_co2_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_emission_factor\":0.32989,\"electricity_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_n2o_emission_factor\":0.00109161,\"electricity_n2o_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"name\":\"WECC California\",\"nerc_abbreviation\":\"WECC\",\"net_generation\":219612000.0,\"net_generation_units\":\"megawatt_hours\"}},\"quorum\":{\"name\":\"from zip code\",\"requirements\":[\"zip_code\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"date\",\"quorums\":[{\"name\":\"from timeframe\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":\"2011-01-01\",\"quorum\":{\"name\":\"from timeframe\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}}],\"methodology\":\"http://carbon.brighterplanet.com/electricity_uses.html?energy=1&timeframe=2011-01-01%2F2012-01-01&zip_code=94110\",\"execution_id\":\"863c7b45fcba5ba36bb2389f518b51be1665166db5f6a3c8d7ce3a3950c38d7e07d551fad2e7f4e7\",\"compliance\":[],\"scope\":null,\"energy\":1.0,\"zip_code\":{\"zip_code\":{\"climate_division_name\":\"CA4\",\"description\":\"San Francisco\",\"egrid_subregion_abbreviation\":\"CAMX\",\"latitude\":\"37.74873\",\"longitude\":\"-122.41545\",\"name\":\"94110\",\"state_postal_abbreviation\":\"CA\"}},\"date\":\"2011-01-01\",\"egrid_subregion\":{\"egrid_subregion\":{\"abbreviation\":\"CAMX\",\"egrid_region_name\":\"W\",\"electricity_ch4_emission_factor\":0.000342876,\"electricity_ch4_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_co2_biogenic_emission_factor\":0.0,\"electricity_co2_biogenic_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_co2_emission_factor\":0.328455,\"electricity_co2_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_emission_factor\":0.32989,\"electricity_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_n2o_emission_factor\":0.00109161,\"electricity_n2o_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"name\":\"WECC California\",\"nerc_abbreviation\":\"WECC\",\"net_generation\":219612000.0,\"net_generation_units\":\"megawatt_hours\"}},\"egrid_region\":{\"egrid_region\":{\"loss_factor\":0.0533328,\"name\":\"W\"}},\"loss_factor\":0.0533328,\"emission_factor\":0.32989}"
71
+ http_version: "1.1"
72
+ - !ruby/struct:VCR::HTTPInteraction
73
+ request: !ruby/struct:VCR::Request
74
+ method: :get
75
+ uri: http://carbon.brighterplanet.com:80/electricity_uses.json?date=2011-03-29&energy=1
76
+ body:
77
+ headers:
78
+ accept:
79
+ - "*/*; q=0.5, application/xml"
80
+ accept-encoding:
81
+ - gzip, deflate
82
+ response: !ruby/struct:VCR::Response
83
+ status: !ruby/struct:VCR::ResponseStatus
84
+ code: 200
85
+ message: OK
86
+ headers:
87
+ server:
88
+ - nginx/0.6.35
89
+ date:
90
+ - Tue, 29 Mar 2011 15:36:35 GMT
91
+ content-type:
92
+ - application/json; charset=utf-8
93
+ transfer-encoding:
94
+ - chunked
95
+ status:
96
+ - 200 OK
97
+ etag:
98
+ - "\"642c6acc898b96f4017bc27c2f321ee4\""
99
+ cache-control:
100
+ - max-age=0, private, must-revalidate
101
+ x-ua-compatible:
102
+ - IE=Edge,chrome=1
103
+ x-runtime:
104
+ - "0.026969"
105
+ body: "{\"timeframe\":\"2011-01-01/2012-01-01\",\"emission\":0.6460529833458619,\"emission_units\":\"kilograms\",\"errors\":[],\"reports\":[{\"committee\":{\"name\":\"emission\",\"quorums\":[{\"name\":\"from date, emission factor, loss factor and energy\",\"requirements\":[\"date\",\"emission_factor\",\"loss_factor\",\"energy\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.6460529833458619,\"quorum\":{\"name\":\"from date, emission factor, loss factor and energy\",\"requirements\":[\"date\",\"emission_factor\",\"loss_factor\",\"energy\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"emission_factor\",\"quorums\":[{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.606076,\"quorum\":{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"loss_factor\",\"quorums\":[{\"name\":\"from eGRID region\",\"requirements\":[\"egrid_region\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":0.0618788,\"quorum\":{\"name\":\"from eGRID region\",\"requirements\":[\"egrid_region\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"egrid_region\",\"quorums\":[{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":{\"egrid_region\":{\"loss_factor\":0.0618788,\"name\":\"US\"}},\"quorum\":{\"name\":\"from eGRID subregion\",\"requirements\":[\"egrid_subregion\"],\"appreciates\":[],\"complies\":[]}},{\"committee\":{\"name\":\"egrid_subregion\",\"quorums\":[{\"name\":\"from zip code\",\"requirements\":[\"zip_code\"],\"appreciates\":[],\"complies\":[]},{\"name\":\"default\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}]},\"conclusion\":{\"egrid_subregion\":{\"abbreviation\":\"US\",\"egrid_region_name\":\"US\",\"electricity_ch4_emission_factor\":0.000309198,\"electricity_ch4_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_co2_biogenic_emission_factor\":0.0,\"electricity_co2_biogenic_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_co2_emission_factor\":0.602982,\"electricity_co2_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_emission_factor\":0.606076,\"electricity_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_n2o_emission_factor\":0.00278485,\"electricity_n2o_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"name\":\"United States\",\"nerc_abbreviation\":\"US\",\"net_generation\":4056440000.0,\"net_generation_units\":\"megawatt_hours\"}},\"quorum\":{\"name\":\"default\",\"requirements\":[],\"appreciates\":[],\"complies\":[]}}],\"methodology\":\"http://carbon.brighterplanet.com/electricity_uses.html?date=2011-03-29&energy=1&timeframe=2011-01-01%2F2012-01-01\",\"execution_id\":\"dec9aeca7a2b8750494fdd452337a4b6d8ca3649a7aebafce76d3976f91b0943e4669cf580a7a225\",\"compliance\":[],\"scope\":null,\"date\":\"2011-03-29\",\"energy\":1.0,\"egrid_subregion\":{\"egrid_subregion\":{\"abbreviation\":\"US\",\"egrid_region_name\":\"US\",\"electricity_ch4_emission_factor\":0.000309198,\"electricity_ch4_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_co2_biogenic_emission_factor\":0.0,\"electricity_co2_biogenic_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_co2_emission_factor\":0.602982,\"electricity_co2_emission_factor_units\":\"kilograms_per_kilowatt_hour\",\"electricity_emission_factor\":0.606076,\"electricity_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"electricity_n2o_emission_factor\":0.00278485,\"electricity_n2o_emission_factor_units\":\"kilograms_co2e_per_kilowatt_hour\",\"name\":\"United States\",\"nerc_abbreviation\":\"US\",\"net_generation\":4056440000.0,\"net_generation_units\":\"megawatt_hours\"}},\"egrid_region\":{\"egrid_region\":{\"loss_factor\":0.0618788,\"name\":\"US\"}},\"loss_factor\":0.0618788,\"emission_factor\":0.606076}"
106
+ http_version: "1.1"
@@ -0,0 +1,8 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'spec_helper'
3
+
4
+ describe SmarterMeter::Sample do
5
+ before(:all) do
6
+ @data = File.read(File.join($FIXTURES_DIR, 'data.csv'))
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe SmarterMeter::Samples do
4
+ before(:all) do
5
+ @data = File.read(File.join($FIXTURES_DIR, 'data.csv'))
6
+ @date_present = Date.new(2009, 9, 27)
7
+ end
8
+
9
+ subject { SmarterMeter::Samples.parse_csv(@data) }
10
+
11
+ it "can calculate the total number of kilowatt hours used" do
12
+ subject.total_kwh.should be_within(0.1).of(43.72)
13
+ end
14
+
15
+ it "can calculate the total number of kilowatt hours used on a specific day" do
16
+ subject.total_kwh_on(Date.new(2009, 9, 27)).should be_within(0.1).of(16.65)
17
+ end
18
+
19
+ it "can calculate the total number of kilowatt hours used on a day not given" do
20
+ subject.total_kwh_on(Date.new(2010, 9, 27)).should == 0
21
+ end
22
+
23
+ it "can access samples for a given day" do
24
+ subject.length.should == 7
25
+ subject.keys.should include(@date_present)
26
+ subject[@date_present].length.should == 24
27
+ subject[@date_present].each{|s| s.should be_kind_of(SmarterMeter::Sample)}
28
+ end
29
+
30
+ it "can handle an incomplete sample" do
31
+ subject[@date_present][0].kwh.should == nil
32
+ subject[@date_present][0].time.should == Time.local(2009, 9, 27, 0)
33
+ end
34
+
35
+ it "can handle a complete sample" do
36
+ subject[@date_present][1].kwh.should == 0.205
37
+ subject[@date_present][1].time.should == Time.local(2009, 9, 27, 1)
38
+ end
39
+ end
@@ -1,4 +1,3 @@
1
- $:.unshift File.join(File.dirname(__FILE__))
2
1
  require 'spec_helper'
3
2
 
4
3
  describe SmarterMeter::Service do
@@ -0,0 +1,26 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..")
2
+ require 'spec_helper'
3
+
4
+ describe SmarterMeter::Services::BrighterPlanet do
5
+ it "can determine kilograms of carbon produced from the number of killowatt hours" do
6
+ VCR.use_cassette('brighterplanet', :record => :new_episodes) do
7
+ subject.calculate_kg_carbon(1).should be_within(0.1).of(0.64)
8
+ end
9
+ end
10
+
11
+ it "can query for electricity from a specific zipcode" do
12
+ VCR.use_cassette('brighterplanet', :record => :new_episodes) do
13
+ subject.calculate_kg_carbon(1, :zip_code => "94110").should be_within(0.1).of(0.34)
14
+ end
15
+ end
16
+
17
+ it "can query for electricity on a specific date" do
18
+ VCR.use_cassette('brighterplanet', :record => :new_episodes) do
19
+ subject.calculate_kg_carbon(1, :date => "2011-03-29").should be_within(0.1).of(0.64)
20
+ end
21
+ end
22
+
23
+ it "doesn't allow electricity queries to include keys other than those specified" do
24
+ expect { subject.calculate_kg_carbon(1, :energy => 2) }.to raise_error(ArgumentError)
25
+ end
26
+ end
@@ -1,12 +1,12 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..")
2
2
  require 'spec_helper'
3
3
 
4
- describe SmarterMeter::Transports::GooglePowerMeter do
4
+ describe SmarterMeter::Services::GooglePowerMeter do
5
5
  before(:each) do
6
- @subject = SmarterMeter::Transports::GooglePowerMeter.new(:token => "secret",
7
- :variable => "/path")
6
+ @subject = SmarterMeter::Services::GooglePowerMeter.new(:token => "secret",
7
+ :variable => "/path")
8
8
  data = File.read(File.join($FIXTURES_DIR, 'data.csv'))
9
- @results = SmarterMeter::Sample.parse_csv(data)
9
+ @results = SmarterMeter::Samples.parse_csv(data)
10
10
  end
11
11
 
12
12
  it "can format a request for the API" do
@@ -2,8 +2,14 @@ require 'rubygems'
2
2
  require 'bundler/setup'
3
3
  Bundler.require(:default)
4
4
  require 'rspec'
5
+ require 'vcr'
5
6
 
6
7
  $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
7
8
  require 'smartermeter'
8
9
 
9
10
  $FIXTURES_DIR = File.expand_path(File.join(File.dirname(__FILE__), "fixtures"))
11
+
12
+ VCR.config do |c|
13
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
14
+ c.stub_with :webmock
15
+ end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartermeter
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 1
9
- version: 0.3.1
4
+ prerelease:
5
+ version: 0.3.2
10
6
  platform: ruby
11
7
  authors:
12
8
  - Matt Colyer
@@ -14,65 +10,97 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-03-15 00:00:00 -07:00
13
+ date: 2011-03-29 00:00:00 -07:00
18
14
  default_executable: smartermeter
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
21
17
  name: mechanize
22
18
  prerelease: false
23
19
  requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
24
21
  requirements:
25
22
  - - "="
26
23
  - !ruby/object:Gem::Version
27
- segments:
28
- - 1
29
- - 0
30
- - 0
31
24
  version: 1.0.0
32
25
  type: :runtime
33
26
  version_requirements: *id001
34
27
  - !ruby/object:Gem::Dependency
35
- name: crypt
28
+ name: crypt19
36
29
  prerelease: false
37
30
  requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
38
32
  requirements:
39
33
  - - "="
40
34
  - !ruby/object:Gem::Version
41
- segments:
42
- - 1
43
- - 1
44
- - 4
45
- version: 1.1.4
35
+ version: 1.2.1
46
36
  type: :runtime
47
37
  version_requirements: *id002
48
38
  - !ruby/object:Gem::Dependency
49
- name: rspec
39
+ name: rest-client
50
40
  prerelease: false
51
41
  requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - "="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.6.1
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: json_pure
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - "="
56
+ - !ruby/object:Gem::Version
57
+ version: 1.5.1
58
+ type: :runtime
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: rspec
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
52
65
  requirements:
53
66
  - - ~>
54
67
  - !ruby/object:Gem::Version
55
- segments:
56
- - 2
57
- - 4
58
- - 0
59
- version: 2.4.0
68
+ version: 2.5.0
60
69
  type: :development
61
- version_requirements: *id003
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: vcr
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: 1.7.0
80
+ type: :development
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: webmock
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ version: 1.6.2
91
+ type: :development
92
+ version_requirements: *id007
62
93
  - !ruby/object:Gem::Dependency
63
94
  name: minitar
64
95
  prerelease: false
65
- requirement: &id004 !ruby/object:Gem::Requirement
96
+ requirement: &id008 !ruby/object:Gem::Requirement
97
+ none: false
66
98
  requirements:
67
99
  - - ~>
68
100
  - !ruby/object:Gem::Version
69
- segments:
70
- - 0
71
- - 5
72
- - 2
73
101
  version: 0.5.2
74
102
  type: :development
75
- version_requirements: *id004
103
+ version_requirements: *id008
76
104
  description: Fetches SmartMeter data from PG&E and can upload to Google PowerMeter
77
105
  email: matt.removethis@nospam.colyer.name
78
106
  executables:
@@ -100,17 +128,22 @@ files:
100
128
  - lib/smartermeter/interfaces/cli.rb
101
129
  - lib/smartermeter/interfaces/swing.rb
102
130
  - lib/smartermeter/sample.rb
131
+ - lib/smartermeter/samples.rb
103
132
  - lib/smartermeter/service.rb
104
- - lib/smartermeter/transports/cacert.pem
105
- - lib/smartermeter/transports/google_powermeter.erb
106
- - lib/smartermeter/transports/google_powermeter.rb
133
+ - lib/smartermeter/services/brighterplanet.rb
134
+ - lib/smartermeter/services/cacert.pem
135
+ - lib/smartermeter/services/google_powermeter.erb
136
+ - lib/smartermeter/services/google_powermeter.rb
107
137
  - smartermeter.gemspec
108
- - specs/fixtures/data.csv
109
- - specs/fixtures/expected_google_request.xml
110
- - specs/sample_spec.rb
111
- - specs/service_spec.rb
112
- - specs/spec_helper.rb
113
- - specs/transports/google_powermeter_spec.rb
138
+ - spec/fixtures/data.csv
139
+ - spec/fixtures/expected_google_request.xml
140
+ - spec/fixtures/vcr_cassettes/brighterplanet.yml
141
+ - spec/sample_spec.rb
142
+ - spec/samples_spec.rb
143
+ - spec/service_spec.rb
144
+ - spec/services/brighterplanet_spec.rb
145
+ - spec/services/google_powermeter_spec.rb
146
+ - spec/spec_helper.rb
114
147
  has_rdoc: true
115
148
  homepage: http://github.com/mcolyer/smartermeter
116
149
  licenses: []
@@ -121,23 +154,21 @@ rdoc_options: []
121
154
  require_paths:
122
155
  - lib
123
156
  required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
124
158
  requirements:
125
159
  - - ">="
126
160
  - !ruby/object:Gem::Version
127
- segments:
128
- - 0
129
161
  version: "0"
130
162
  required_rubygems_version: !ruby/object:Gem::Requirement
163
+ none: false
131
164
  requirements:
132
165
  - - ">="
133
166
  - !ruby/object:Gem::Version
134
- segments:
135
- - 0
136
167
  version: "0"
137
168
  requirements: []
138
169
 
139
170
  rubyforge_project: smartermeter
140
- rubygems_version: 1.3.6
171
+ rubygems_version: 1.5.0
141
172
  signing_key:
142
173
  specification_version: 2
143
174
  summary: Fetches SmartMeter data from PG&E
data/specs/sample_spec.rb DELETED
@@ -1,24 +0,0 @@
1
- $:.unshift File.join(File.dirname(__FILE__))
2
- require 'spec_helper'
3
-
4
- describe SmarterMeter::Sample do
5
- before(:all) do
6
- @data = File.read(File.join($FIXTURES_DIR, 'data.csv'))
7
- end
8
-
9
- it "should be able to parse csv data returned by the api" do
10
- date = Date.new(2009, 9, 27)
11
- results = SmarterMeter::Sample.parse_csv(@data)
12
-
13
- results.length.should == 7
14
- results.keys.should include(date)
15
- results[date].length.should == 24
16
- results[date].each{|s| s.should be_kind_of(SmarterMeter::Sample)}
17
-
18
- results[date][0].kwh.should == nil
19
- results[date][0].time.should == Time.local(2009, 9, 27, 0)
20
-
21
- results[date][1].kwh.should == 0.205
22
- results[date][1].time.should == Time.local(2009, 9, 27, 1)
23
- end
24
- end