greenbutton 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +29 -0
- data/Rakefile +2 -0
- data/Readme.md +10 -0
- data/greenbutton.gemspec +18 -0
- data/lib/greenbutton.rb +60 -0
- data/lib/greenbutton/gb_classes.rb +361 -0
- data/lib/greenbutton/helpers.rb +58 -0
- data/license.txt +20 -0
- data/pkg/greenbutton-0.0.1.gem +0 -0
- data/spec/fixtures/sample_greenbutton_data.xml +2728 -0
- data/spec/helper_spec.rb +46 -0
- data/spec/parser_spec.rb +183 -0
- data/spec/spec_helper.rb +23 -0
- metadata +111 -0
data/spec/helper_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe :translate do
|
4
|
+
it "correctly parses :ServiceKind" do
|
5
|
+
expect(Helper.translate(:ServiceKind, '7')).to eq(:rates)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "fails gracefully if it can't find the :serviceKind" do
|
9
|
+
expect(Helper.translate(:ServiceKind, '100')).to eq('100')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "correctly parses :integer" do
|
13
|
+
expect(Helper.translate(:integer, '2343')).to eq(2343)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "correctly parses :datetime" do
|
17
|
+
expect(Helper.translate(:datetime, '2012-10-24T00:00:00Z')).to eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "correctly parses :unixtime" do
|
21
|
+
expect(Helper.translate(:unix_time, '1293868800')).to eq(Time.at(1293868800).utc)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe :pluralize do
|
26
|
+
it "pluralizes words correctly" do
|
27
|
+
expect(Helper.pluralize('crock')).to eq('crocks')
|
28
|
+
expect(Helper.pluralize('utility')).to eq('utilities')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe :underscored do
|
33
|
+
it "underscores camelcased words correctly" do
|
34
|
+
expect(Helper.underscore('yourAvgUtility')).to eq('your_avg_utility')
|
35
|
+
expect(Helper.underscore('YourAvgUtility')).to eq('your_avg_utility')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe Helper::Rule do
|
40
|
+
it "should have a attribute name" do
|
41
|
+
rule = Helper::Rule.new(:attr_name,"xpath",:DateTime)
|
42
|
+
expect(rule.attr_name).to eq :attr_name
|
43
|
+
expect(rule.xpath).to eq "xpath"
|
44
|
+
expect(rule.type).to eq :DateTime
|
45
|
+
end
|
46
|
+
end
|
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GreenButton do
|
4
|
+
it "has web and file loading methods" do
|
5
|
+
expect(GreenButton).to respond_to(:load_xml_from_file)
|
6
|
+
expect(GreenButton).to respond_to(:load_xml_from_web)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe GreenButton::Parser do
|
10
|
+
let(:gb){ GreenButton.load_xml_from_file('spec/fixtures/sample_greenbutton_data.xml') }
|
11
|
+
|
12
|
+
it "should initialize" do
|
13
|
+
expect(gb).to be_a(GreenButton::Parser)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :usage_point do
|
17
|
+
let(:usage_point){ gb.usage_points.first }
|
18
|
+
subject { usage_point }
|
19
|
+
it "should have at least one usage_point" do
|
20
|
+
expect(gb.usage_points.first.class).to eq GreenButtonClasses::UsagePoint
|
21
|
+
expect(gb.usage_points.count).to be > 0
|
22
|
+
end
|
23
|
+
|
24
|
+
its(:service_kind){ should eq(:electricity) }
|
25
|
+
its(:id){ should eq("urn:uuid:4217A3D3-60E0-46CD-A5AF-2A2D091F397E") }
|
26
|
+
its(:customer_id){ should eq("9b6c7063") }
|
27
|
+
its(:href){ should eq("RetailCustomer/9b6c7063/UsagePoint/01") }
|
28
|
+
its(:parent_href){ should eq("RetailCustomer/9b6c7063/UsagePoint") }
|
29
|
+
its(:title){ should eq("Coastal Single Family") }
|
30
|
+
its(:date_published){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
31
|
+
its(:date_updated){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
32
|
+
|
33
|
+
it "knows its related hrefs" do
|
34
|
+
expect(usage_point.related_hrefs).to include "RetailCustomer/9b6c7063/UsagePoint/01/MeterReading"
|
35
|
+
expect(usage_point.related_hrefs).to include "RetailCustomer/9b6c7063/UsagePoint/01/ElectricPowerUsageSummary"
|
36
|
+
expect(usage_point.related_hrefs).to include "LocalTimeParameters/01"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has defined local_time_parameters" do
|
40
|
+
expect(usage_point.local_time_parameters).to be_a(GreenButtonClasses::LocalTimeParameters)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "has one electric power usage summary" do
|
44
|
+
expect(usage_point.electric_power_usage_summaries.length).to eq(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "has no electric power quality summaries" do
|
48
|
+
expect(usage_point.electric_power_quality_summaries.length).to eq(0)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "has one meter reading" do
|
52
|
+
expect(usage_point.meter_readings.length).to eq(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
describe :local_time_parameters do
|
56
|
+
let(:local_time_parameters) { usage_point.local_time_parameters }
|
57
|
+
subject{ local_time_parameters }
|
58
|
+
|
59
|
+
its(:id){ should eq("urn:uuid:FE317A0A-F7F5-4307-B158-28A34276E862") }
|
60
|
+
its(:href){ should eq("LocalTimeParameters/01") }
|
61
|
+
its(:parent_href){ should eq("LocalTimeParameters") }
|
62
|
+
its(:title){ should eq("DST For North America") }
|
63
|
+
its(:date_published){ should eq(DateTime.parse("2012-10-24T00:00:00Z").to_time.utc) }
|
64
|
+
its(:date_updated){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
65
|
+
its(:dst_end_rule){ should eq("B40E2000") }
|
66
|
+
its(:dst_offset){ should eq(3600) }
|
67
|
+
its(:dst_start_rule){ should eq("360E2000") }
|
68
|
+
its(:tz_offset){ should eq(-28800) }
|
69
|
+
end
|
70
|
+
|
71
|
+
describe :electric_power_usage_summary do
|
72
|
+
let(:electric_power_usage_summary) { usage_point.electric_power_usage_summaries.first }
|
73
|
+
subject{ electric_power_usage_summary }
|
74
|
+
|
75
|
+
['billLastPeriod', 'billToDate', 'costAdditionalLastPeriod', 'currency',
|
76
|
+
'qualityOfReading', 'statusTimeStamp']
|
77
|
+
|
78
|
+
it{ should be_a GreenButtonClasses::ElectricPowerUsageSummary }
|
79
|
+
its(:id){ should eq("urn:uuid:429EAE17-A8C7-4E7F-B101-D66173B2166C") }
|
80
|
+
its(:href){ should eq("RetailCustomer/9b6c7063/ElectricPowerUsageSummary/01") }
|
81
|
+
its(:parent_href){ should eq("RetailCustomer/9b6c7063/UsagePoint/01/ElectricPowerUsageSummary") }
|
82
|
+
its(:title){ should eq("Usage Summary") }
|
83
|
+
its(:date_published){ should eq(DateTime.parse("2012-10-24T00:00:00Z").to_time.utc) }
|
84
|
+
its(:date_updated){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
85
|
+
its(:bill_duration){ should eq(2592000) }
|
86
|
+
its(:bill_start){ should eq(Time.at(1320130800).utc) }
|
87
|
+
its(:last_power_ten){ should eq(nil) }
|
88
|
+
its(:last_uom){ should eq(nil) }
|
89
|
+
its(:last_value){ should eq(nil) }
|
90
|
+
its(:current_power_ten){ should eq(0) }
|
91
|
+
its(:current_uom){ should eq(72) }
|
92
|
+
its(:current_value){ should eq(610314) }
|
93
|
+
its(:current_timestamp){ should eq(Time.at(1325401200).utc) }
|
94
|
+
end
|
95
|
+
|
96
|
+
describe :meter_reading do
|
97
|
+
let(:meter_reading) { usage_point.meter_readings[0] }
|
98
|
+
subject{ meter_reading }
|
99
|
+
it { should be_a(GreenButtonClasses::MeterReading) }
|
100
|
+
|
101
|
+
its(:id){ should eq("urn:uuid:9BCDAB06-6690-46A3-9253-A451AF4077D8") }
|
102
|
+
its(:href){ should eq("RetailCustomer/9b6c7063/UsagePoint/01/MeterReading/01") }
|
103
|
+
its(:parent_href){ should eq("RetailCustomer/9b6c7063/UsagePoint/01/MeterReading") }
|
104
|
+
its(:title){ should eq("Hourly Electricity Consumption") }
|
105
|
+
its(:date_published){ should eq(DateTime.parse("2012-10-24T00:00:00Z").to_time.utc) }
|
106
|
+
its(:date_updated){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
107
|
+
|
108
|
+
it "has one ReadingType" do
|
109
|
+
expect(meter_reading.reading_type).to be_a(GreenButtonClasses::ReadingType)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "has one IntervalBlock" do
|
113
|
+
expect(meter_reading.interval_blocks.length).to eq(1)
|
114
|
+
end
|
115
|
+
|
116
|
+
describe :reading_type do
|
117
|
+
let(:reading_type) { meter_reading.reading_type }
|
118
|
+
subject{ reading_type }
|
119
|
+
|
120
|
+
its(:id){ should eq("urn:uuid:BEB04FF1-6294-4916-95AC-5597070C95D4") }
|
121
|
+
its(:href){ should eq("ReadingType/07") }
|
122
|
+
its(:parent_href){ should eq("ReadingType") }
|
123
|
+
its(:title){ should eq("Energy Delivered (kWh)") }
|
124
|
+
its(:date_published){ should eq(DateTime.parse("2012-10-24T00:00:00Z").to_time.utc) }
|
125
|
+
its(:date_updated){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
126
|
+
its(:accumulation_behaviour){ should eq(4) }
|
127
|
+
its(:commodity){ should eq(1) }
|
128
|
+
its(:currency){ should eq(840) }
|
129
|
+
its(:data_qualifier){ should eq(12) }
|
130
|
+
its(:flow_direction){ should eq(1) }
|
131
|
+
its(:kind){ should eq(12) }
|
132
|
+
its(:phase){ should eq(769) }
|
133
|
+
its(:power_of_ten_multiplier){ should eq(0) }
|
134
|
+
its(:time_attribute){ should eq(0) }
|
135
|
+
its(:uom){ should eq(72) }
|
136
|
+
end
|
137
|
+
|
138
|
+
describe :interval_block do
|
139
|
+
let(:interval_block) { meter_reading.interval_blocks[0] }
|
140
|
+
subject{ interval_block }
|
141
|
+
|
142
|
+
it { should be_a(GreenButtonClasses::IntervalBlock) }
|
143
|
+
its(:id){ should eq("urn:uuid:EE0EC179-2726-43B1-BFE2-40ACC6A8901B") }
|
144
|
+
its(:href){ should eq("RetailCustomer/9b6c7063/UsagePoint/01/MeterReading/01/IntervalBlock/0173") }
|
145
|
+
its(:parent_href){ should eq("RetailCustomer/9b6c7063/UsagePoint/01/MeterReading/01/IntervalBlock") }
|
146
|
+
its(:title){ should eq("") }
|
147
|
+
its(:date_published){ should eq(DateTime.parse("2012-10-24T00:00:00Z").to_time.utc) }
|
148
|
+
its(:date_updated){ should eq(DateTime.parse('2012-10-24T00:00:00Z').to_time.utc) }
|
149
|
+
its(:start_time){ should eq(Time.at(1293868800).utc) }
|
150
|
+
its(:duration){ should eq(2678400) }
|
151
|
+
its(:end_time){ should eq(Time.at(1293868800+2678400).utc) }
|
152
|
+
|
153
|
+
it "calculates correct total" do
|
154
|
+
expect(interval_block.total).to eq(291018.0)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "calculates correct average" do
|
158
|
+
expect(interval_block.average_interval_value).to eq(291018.0/362.0)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "calculates correct sum over time interval" do
|
162
|
+
date1 = Time.at(1293915600).utc
|
163
|
+
date2 = Time.at(1293922800).utc
|
164
|
+
expect(interval_block.sum(date1, date2)).to eq(852+798)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "returns correct value at given time" do
|
168
|
+
expect(interval_block.value_at_time(Time.at(1293919600).utc)).to eq(798)
|
169
|
+
end
|
170
|
+
|
171
|
+
describe :interval_reading do
|
172
|
+
let(:interval_reading){ interval_block.reading_at_time(Time.at(1293919600).utc) }
|
173
|
+
subject{ interval_reading }
|
174
|
+
its(:duration){ should eq(3600) }
|
175
|
+
its(:start_time){ should eq(Time.at(1293919200).utc) }
|
176
|
+
its(:end_time){ should eq(Time.at(1293919200+3600).utc) }
|
177
|
+
its(:value){ should eq(798) }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'bundler/setup'
|
9
|
+
Bundler.setup
|
10
|
+
|
11
|
+
require 'greenbutton'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
config.filter_run :focus
|
17
|
+
|
18
|
+
# Run specs in random order to surface order dependencies. If you find an
|
19
|
+
# order dependency and want to debug it, you can fix the order by providing
|
20
|
+
# the seed, which is printed after each run.
|
21
|
+
# --seed 1234
|
22
|
+
config.order = 'random'
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: greenbutton
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Charles Worthington
|
8
|
+
- Eric Hulburd
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.6'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.6'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.5'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.5'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.14'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.14'
|
56
|
+
description: This parser programmatically creates a Ruby object from a GreenButton
|
57
|
+
data file. See https://collaborate.nist.gov/twiki-sggrid/bin/view/SmartGrid/GreenButtonSDK
|
58
|
+
for more information on GreenButton. It is under active development and participation
|
59
|
+
is encouraged. It is not yet stable.
|
60
|
+
email:
|
61
|
+
- c.e.worthington@gmail.com
|
62
|
+
- eric@arbol.org
|
63
|
+
executables: []
|
64
|
+
extensions: []
|
65
|
+
extra_rdoc_files: []
|
66
|
+
files:
|
67
|
+
- ".gitignore"
|
68
|
+
- ".rspec"
|
69
|
+
- ".ruby-gemset"
|
70
|
+
- ".ruby-version"
|
71
|
+
- Gemfile
|
72
|
+
- Gemfile.lock
|
73
|
+
- Rakefile
|
74
|
+
- Readme.md
|
75
|
+
- greenbutton.gemspec
|
76
|
+
- lib/greenbutton.rb
|
77
|
+
- lib/greenbutton/gb_classes.rb
|
78
|
+
- lib/greenbutton/helpers.rb
|
79
|
+
- license.txt
|
80
|
+
- pkg/greenbutton-0.0.1.gem
|
81
|
+
- spec/fixtures/sample_greenbutton_data.xml
|
82
|
+
- spec/helper_spec.rb
|
83
|
+
- spec/parser_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
homepage: https://github.com/cew821/greenbutton
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.2.1
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: Ruby parser for the GreenButton data standard.
|
109
|
+
test_files:
|
110
|
+
- spec/helper_spec.rb
|
111
|
+
- spec/parser_spec.rb
|