smartermeter 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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