aemo 0.2.1 → 0.3.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/aemo/nmi.rb CHANGED
@@ -4,315 +4,39 @@ require 'csv'
4
4
  require 'json'
5
5
  require 'time'
6
6
  require 'ostruct'
7
+
7
8
  module AEMO
9
+ # [AEMO::NMI]
10
+ #
8
11
  # AEMO::NMI acts as an object to simplify access to data and information
9
- # about a NMI and provide verification of the NMI value
12
+ # about a NMI and provide verification of the NMI value
13
+ #
14
+ # @author Joel Courtney
15
+ # @abstract Model for a National Metering Identifier.
16
+ # @since 2014-12-05
10
17
  class NMI
11
18
  # Operational Regions for the NMI
12
- REGIONS = { 'ACT' => 'Australian Capital Territory',
13
- 'NSW' => 'New South Wales',
14
- 'QLD' => 'Queensland',
15
- 'SA' => 'South Australia',
16
- 'TAS' => 'Tasmania',
17
- 'VIC' => 'Victoria',
18
- 'WA' => 'Western Australia',
19
- 'NT' => 'Northern Territory' }.freeze
20
-
21
- # NMI_ALLOCATIONS as per AEMO Documentation at
22
- # https://www.aemo.com.au/-/media/Files/Electricity/NEM/Retail_and_Metering/
23
- # Metering-Procedures/NMI-Allocation-List.pdf
24
- # Last accessed 2017-08-01
25
- NMI_ALLOCATIONS = {
26
- 'ACTEWP' => {
27
- title: 'Actew Distribution Ltd and Jemena Networks (ACT) Pty Ltd',
28
- friendly_title: 'ACTEWAgl',
29
- state: AEMO::Region.new('ACT'),
30
- type: 'electricity',
31
- includes: [/^(NGGG[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
32
- /^(7001\d{6})$/],
33
- excludes: []
34
- },
35
- 'CNRGYP' => {
36
- title: 'Essential Energy',
37
- friendly_title: 'Essential Energy',
38
- state: AEMO::Region.new('NSW'),
39
- type: 'electricity',
40
- includes: [/^(NAAA[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
41
- /^(NBBB[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
42
- /^(NDDD[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
43
- /^(NFFF[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
44
- /^(4001\d{6})$/,
45
- /^(4508\d{6})$/,
46
- /^(4204\d{6})$/,
47
- /^(4407\d{6})$/],
48
- excludes: []
49
- },
50
- 'ENERGYAP' => {
51
- title: 'Ausgrid',
52
- friendly_title: 'Ausgrid',
53
- state: AEMO::Region.new('NSW'),
54
- type: 'electricity',
55
- includes: [/^(NCCC[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
56
- /^(410[234]\d{6})$/],
57
- excludes: []
58
- },
59
- 'INTEGP' => {
60
- title: 'Endeavour Energy',
61
- friendly_title: 'Endeavour Energy',
62
- state: AEMO::Region.new('NSW'),
63
- type: 'electricity',
64
- includes: [/^(NEEE[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
65
- /^(431\d{7})$/],
66
- excludes: []
67
- },
68
- 'TRANSGP' => {
69
- title: 'TransGrid',
70
- friendly_title: 'TransGrid',
71
- state: AEMO::Region.new('NSW'),
72
- type: 'electricity',
73
- includes: [/^(NTTT[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
74
- /^(460810[0-8]\d{3})$/],
75
- excludes: []
76
- },
77
- 'SNOWY' => {
78
- title: 'Snowy Hydro Ltd',
79
- friendly_title: 'Snowy Hydro',
80
- state: AEMO::Region.new('NSW'),
81
- type: 'electricity',
82
- includes: [/^(4708109\d{3})$/],
83
- excludes: []
84
- },
85
- 'NT_RESERVED' => {
86
- title: 'Northern Territory Reserved Block',
87
- friendly_title: 'Northern Territory Reserved Block',
88
- state: AEMO::Region.new('NT'),
89
- type: 'electricity',
90
- includes: [/^(250\d{7})$/],
91
- excludes: []
92
- },
93
- 'ERGONETP' => {
94
- title: 'Ergon Energy Corporation',
95
- friendly_title: 'Ergon Energy',
96
- state: AEMO::Region.new('QLD'),
97
- type: 'electricity',
98
- includes: [/^(QAAA[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
99
- /^(QCCC[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
100
- /^(QDDD[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
101
- /^(QEEE[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
102
- /^(QFFF[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
103
- /^(QGGG[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
104
- /^(30\d{8})$/],
105
- excludes: []
106
- },
107
- 'ENERGEXP' => {
108
- title: 'ENERGEX Limited',
109
- friendly_title: 'Energex',
110
- state: AEMO::Region.new('QLD'),
111
- type: 'electricity',
112
- includes: [/^(QB\d{2}[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
113
- /^(31\d{8})$/],
114
- excludes: []
115
- },
116
- 'PLINKP' => {
117
- title: 'Qld Electricity Transmission Corp (Powerlink)',
118
- friendly_title: 'Powerlink',
119
- state: AEMO::Region.new('QLD'),
120
- type: 'electricity',
121
- includes: [/^(Q[A-HJ-NP-Z\d]{3}W[A-HJ-NP-Z\d]{5})$/,
122
- /^(320200\d{4})$/],
123
- excludes: []
124
- },
125
- 'UMPLP' => {
126
- title: 'SA Power Networks',
127
- friendly_title: 'SA Power Networks',
128
- state: AEMO::Region.new('SA'),
129
- type: 'electricity',
130
- includes: [/^(SAAA[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
131
- /^(SASMPL[\d]{4})$/,
132
- /^(200[12]\d{6})$/],
133
- excludes: []
134
- },
135
- 'ETSATP' => {
136
- title: 'ElectraNet SA',
137
- friendly_title: 'ElectraNet SA',
138
- state: AEMO::Region.new('SA'),
139
- type: 'electricity',
140
- includes: [/^(S[A-HJ-NP-Z\d]{3}W[A-HJ-NP-Z\d]{5})$/,
141
- /^(210200\d{4})$/],
142
- excludes: []
143
- },
144
- 'AURORAP' => {
145
- title: 'TasNetworks',
146
- friendly_title: 'TasNetworks',
147
- state: AEMO::Region.new('TAS'),
148
- type: 'electricity',
149
- includes: [/^(T000000(([0-4]\d{3})|(500[01])))$/,
150
- /^(8000\d{6})$/,
151
- /^(8590[23]\d{5})$/],
152
- excludes: []
153
- },
154
- 'TRANSEND' => {
155
- title: 'TasNetworks',
156
- friendly_title: 'TasNetworks',
157
- state: AEMO::Region.new('TAS'),
158
- type: 'electricity',
159
- includes: [/^(T[A-HJ-NP-Z\d]{3}W[A-HJ-NP-Z\d]{5})$/],
160
- excludes: []
161
- },
162
- 'CITIPP' => {
163
- title: 'CitiPower',
164
- friendly_title: 'CitiPower',
165
- state: AEMO::Region.new('VIC'),
166
- type: 'electricity',
167
- includes: [/^(VAAA[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
168
- /^(610[23]\d{6})$/],
169
- excludes: []
170
- },
171
- 'EASTERN' => {
172
- title: 'SP AusNet',
173
- friendly_title: 'SP AusNet DNSP',
174
- state: AEMO::Region.new('VIC'),
175
- type: 'electricity',
176
- includes: [/^(VBBB[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
177
- /^(630[56]\d{6})$/],
178
- excludes: []
179
- },
180
- 'POWCP' => {
181
- title: 'PowerCor Australia',
182
- friendly_title: 'PowerCor',
183
- state: AEMO::Region.new('VIC'),
184
- type: 'electricity',
185
- includes: [/^(VCCC[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
186
- /^(620[34]\d{6})$/],
187
- excludes: []
188
- },
189
- 'SOLARISP' => {
190
- title: 'Jemena Electricity Networks (VIC)',
191
- friendly_title: 'Jemena',
192
- state: AEMO::Region.new('VIC'),
193
- type: 'electricity',
194
- includes: [/^(VDDD[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
195
- /^(6001\d{6})$/],
196
- excludes: []
197
- },
198
- 'UNITED' => {
199
- title: 'United Energy Distribution',
200
- friendly_title: 'United Energy',
201
- state: AEMO::Region.new('VIC'),
202
- type: 'electricity',
203
- includes: [/^(VEEE[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
204
- /^(640[78]\d{6})$/],
205
- excludes: []
206
- },
207
- 'GPUPP' => {
208
- title: 'SP AusNet TNSP',
209
- friendly_title: 'SP AusNet TNSP',
210
- state: AEMO::Region.new('VIC'),
211
- type: 'electricity',
212
- includes: [/^(V[A-HJ-NP-Z\d]{3}W[A-HJ-NP-Z\d]{5})$/,
213
- /^(650900\d{4})$/],
214
- excludes: []
215
- },
216
- 'WESTERNPOWER' => {
217
- title: 'Western Power',
218
- friendly_title: 'Western Power',
219
- state: AEMO::Region.new('WA'),
220
- type: 'electricity',
221
- includes: [/^(WAAA[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
222
- /^(800[1-9]\d{6})$/,
223
- /^(801\d{7})$/,
224
- /^(8020\d{6})$/],
225
- excludes: []
226
- },
227
- 'HORIZONPOWER' => {
228
- title: 'Horizon Power',
229
- friendly_title: 'Horizon Power',
230
- state: AEMO::Region.new('WA'),
231
- type: 'electricity',
232
- includes: [/^(8021\d{6})$/],
233
- excludes: []
234
- },
235
- 'GAS_NSW' => {
236
- title: 'GAS NSW',
237
- friendly_title: 'GAS NSW',
238
- state: AEMO::Region.new('NSW'),
239
- type: 'gas',
240
- includes: [/^(52\d{8})$/],
241
- excludes: []
242
- },
243
- 'GAS_VIC' => {
244
- title: 'GAS VIC',
245
- friendly_title: 'GAS VIC',
246
- state: AEMO::Region.new('VIC'),
247
- type: 'gas',
248
- includes: [/^(53\d{8})$/],
249
- excludes: []
250
- },
251
- 'GAS_QLD' => {
252
- title: 'GAS QLD',
253
- friendly_title: 'GAS QLD',
254
- state: AEMO::Region.new('QLD'),
255
- type: 'gas',
256
- includes: [/^(54\d{8})$/],
257
- excludes: []
258
- },
259
- 'GAS_SA' => {
260
- title: 'GAS SA',
261
- friendly_title: 'GAS SA',
262
- state: AEMO::Region.new('SA'),
263
- type: 'gas',
264
- includes: [/^(55\d{8})$/],
265
- excludes: []
266
- },
267
- 'GAS_WA' => {
268
- title: 'GAS WA',
269
- friendly_title: 'GAS WA',
270
- state: AEMO::Region.new('WA'),
271
- type: 'gas',
272
- includes: [/^(56\d{8})$/],
273
- excludes: []
274
- },
275
- 'GAS_TAS' => {
276
- title: 'GAS TAS',
277
- friendly_title: 'GAS TAS',
278
- state: AEMO::Region.new('TAS'),
279
- type: 'gas',
280
- includes: [/^(57\d{8})$/],
281
- excludes: []
282
- },
283
- 'FEDAIRPORTS' => {
284
- title: 'Federal Airports Corporation (Sydney Airport)',
285
- friendly_title: 'Sydney Airport',
286
- state: AEMO::Region.new('NSW'),
287
- type: 'electricity',
288
- includes: [/^(NJJJNR[A-HJ-NP-Z\d]{4})$/],
289
- excludes: []
290
- },
291
- 'EXEMPTNETWORKS' => {
292
- title: 'Exempt Networks - various',
293
- friendly_title: 'Exempt Networks - various',
294
- state: '',
295
- type: 'electricity',
296
- includes: [/^(NKKK[A-HJ-NP-VX-Z\d][A-HJ-NP-Z\d]{5})$/,
297
- /^(7102\d{6})$/],
298
- excludes: []
299
- },
300
- 'AEMORESERVED' => {
301
- title: 'AEMO Reserved',
302
- friendly_title: 'AEMO Reserved',
303
- state: '',
304
- type: 'electricity',
305
- includes: [/^(880[1-5]\d{6})$/,
306
- /^(9\d{9})$/],
307
- excludes: []
308
- }
19
+ REGIONS = {
20
+ 'ACT' => 'Australian Capital Territory',
21
+ 'NSW' => 'New South Wales',
22
+ 'QLD' => 'Queensland',
23
+ 'SA' => 'South Australia',
24
+ 'TAS' => 'Tasmania',
25
+ 'VIC' => 'Victoria',
26
+ 'WA' => 'Western Australia',
27
+ 'NT' => 'Northern Territory'
309
28
  }.freeze
29
+
310
30
  # Transmission Node Identifier Codes are loaded from a json file
311
31
  # Obtained from http://www.nemweb.com.au/
312
32
  #
313
33
  # See /lib/data for further data manipulation required
314
- TNI_CODES = JSON.parse(File.read(File.join(File.dirname(__FILE__), '..',
315
- 'data', 'aemo-tni.json'))).freeze
34
+ TNI_CODES = JSON.parse(
35
+ File.read(
36
+ File.join(File.dirname(__FILE__), '..', 'data', 'aemo-tni.json')
37
+ )
38
+ ).freeze
39
+
316
40
  # Distribution Loss Factor Codes are loaded from a json file
317
41
  # Obtained from MSATS, matching to DNSP from file
318
42
  # https://www.aemo.com.au/-/media/Files/Electricity/NEM/
@@ -321,8 +45,11 @@ module AEMO
321
45
  #
322
46
  # Last accessed 2017-08-01
323
47
  # See /lib/data for further data manipulation required
324
- DLF_CODES = JSON.parse(File.read(File.join(File.dirname(__FILE__), '..',
325
- 'data', 'aemo-dlf.json'))).freeze
48
+ DLF_CODES = JSON.parse(
49
+ File.read(
50
+ File.join(File.dirname(__FILE__), '..', 'data', 'aemo-dlf.json')
51
+ )
52
+ ).freeze
326
53
 
327
54
  # [String] National Meter Identifier
328
55
  @nmi = nil
@@ -344,6 +71,38 @@ module AEMO
344
71
  :jurisdiction_code, :classification_code, :status, :address,
345
72
  :meters, :roles, :data_streams
346
73
 
74
+ class << self
75
+ # A function to validate the NMI provided
76
+ #
77
+ # @param [String] nmi the nmi to be checked
78
+ # @return [Boolean] whether or not the nmi is valid
79
+ def valid_nmi?(nmi)
80
+ ((nmi.length == 10) && !nmi.match(/^([A-HJ-NP-Z\d]{10})/).nil?)
81
+ end
82
+
83
+ # A function to calculate the checksum value for a given National Meter
84
+ # Identifier
85
+ #
86
+ # @param [String] nmi the NMI to check the checksum against
87
+ # @param [Integer] checksum_value the checksum value to check against the
88
+ # current National Meter Identifier's checksum value
89
+ # @return [Boolean] whether or not the checksum is valid
90
+ def valid_checksum?(nmi, checksum_value)
91
+ nmi = AEMO::NMI.new(nmi)
92
+ nmi.valid_checksum?(checksum_value)
93
+ end
94
+
95
+ # Find the Network for a given NMI
96
+ #
97
+ # @param [String] nmi NMI
98
+ # @returns [AEMO::NMI::Allocation] The Network information
99
+ def network(nmi)
100
+ AEMO::NMI::Allocation.find_by_nmi(nmi)
101
+ end
102
+
103
+ alias allocation network
104
+ end
105
+
347
106
  # Initialize a NMI file
348
107
  #
349
108
  # @param [String] nmi the National Meter Identifier (NMI)
@@ -354,9 +113,7 @@ module AEMO
354
113
  def initialize(nmi, options = {})
355
114
  raise ArgumentError, 'NMI is not a string' unless nmi.is_a?(String)
356
115
  raise ArgumentError, 'NMI is not 10 characters' unless nmi.length == 10
357
- unless AEMO::NMI.valid_nmi?(nmi)
358
- raise ArgumentError, 'NMI is not constructed with valid characters'
359
- end
116
+ raise ArgumentError, 'NMI is not constructed with valid characters' unless AEMO::NMI.valid_nmi?(nmi)
360
117
 
361
118
  @nmi = nmi
362
119
  @meters = []
@@ -381,6 +138,8 @@ module AEMO
381
138
  AEMO::NMI.network(@nmi)
382
139
  end
383
140
 
141
+ alias allocation network
142
+
384
143
  # A function to calculate the checksum value for a given
385
144
  # National Meter Identifier
386
145
  #
@@ -412,9 +171,7 @@ module AEMO
412
171
  #
413
172
  # @return [Hash] MSATS NMI Detail data
414
173
  def raw_msats_nmi_detail(options = {})
415
- unless AEMO::MSATS.can_authenticate?
416
- raise ArgumentError, 'MSATS has no authentication credentials'
417
- end
174
+ raise ArgumentError, 'MSATS has no authentication credentials' unless AEMO::MSATS.can_authenticate?
418
175
  AEMO::MSATS.nmi_detail(@nmi, options)
419
176
  end
420
177
 
@@ -530,54 +287,18 @@ module AEMO
530
287
 
531
288
  # The current annual load in MWh
532
289
  #
290
+ # @todo Use TimeDifference for more accurate annualised load
533
291
  # @return [Integer] the current annual load for the meter in MWh
534
292
  def current_annual_load
535
293
  (current_daily_load * 365.2425 / 1000).to_i
536
294
  end
537
295
 
538
- # A function to validate the NMI provided
539
- #
540
- # @param [String] nmi the nmi to be checked
541
- # @return [Boolean] whether or not the nmi is valid
542
- def self.valid_nmi?(nmi)
543
- ((nmi.length == 10) && !nmi.match(/^([A-HJ-NP-Z\d]{10})/).nil?)
544
- end
545
-
546
- # A function to calculate the checksum value for a given National Meter
547
- # Identifier
548
- #
549
- # @param [String] nmi the NMI to check the checksum against
550
- # @param [Integer] checksum_value the checksum value to check against the
551
- # current National Meter Identifier's checksum value
552
- # @return [Boolean] whether or not the checksum is valid
553
- def self.valid_checksum?(nmi, checksum_value)
554
- nmi = AEMO::NMI.new(nmi)
555
- nmi.valid_checksum?(checksum_value)
556
- end
557
-
558
- # Find the Network for a given NMI
559
- #
560
- # @param [String] nmi NMI
561
- # @returns [Hash] The Network information
562
- def self.network(nmi)
563
- network = nil
564
- AEMO::NMI::NMI_ALLOCATIONS.each_pair do |identifier, details|
565
- details[:includes].each do |pattern|
566
- if nmi.match(pattern)
567
- network = { identifier => details }
568
- break
569
- end
570
- end
571
- end
572
- network
573
- end
574
-
575
296
  # A function to return the distribution loss factor value for a given date
576
297
  #
577
298
  # @param [DateTime, Time] datetime the date for the distribution loss factor
578
299
  # value
579
300
  # @return [nil, float] the distribution loss factor value
580
- def dlfc_value(datetime = DateTime.now)
301
+ def dlfc_value(datetime = Time.now)
581
302
  if @dlf.nil?
582
303
  raise 'No DLF set, ensure that you have set the value either via the' \
583
304
  'update_from_msats! function or manually'
@@ -585,8 +306,8 @@ module AEMO
585
306
  raise 'DLF is invalid' unless DLF_CODES.keys.include?(@dlf)
586
307
  raise 'Invalid date' unless [DateTime, Time].include?(datetime.class)
587
308
  possible_values = DLF_CODES[@dlf].select do |x|
588
- DateTime.parse(x['FromDate']) <= datetime &&
589
- DateTime.parse(x['ToDate']) >= datetime
309
+ Time.parse(x['FromDate']) <= datetime &&
310
+ Time.parse(x['ToDate']) >= datetime
590
311
  end
591
312
  if possible_values.empty?
592
313
  nil
@@ -600,13 +321,16 @@ module AEMO
600
321
  # @param [DateTime, Time] start the date for the distribution loss factor value
601
322
  # @param [DateTime, Time] finish the date for the distribution loss factor value
602
323
  # @return [Array(Hash)] array of hashes of start, finish and value
603
- def dlfc_values(start = DateTime.now, finish = DateTime.now)
604
- raise 'No DLF set, ensure that you have set the value either via the update_from_msats! function or manually' if @dlf.nil?
324
+ def dlfc_values(start = Time.now, finish = Time.now)
325
+ if @dlf.nil?
326
+ raise 'No DLF set, ensure that you have set the value either via the '\
327
+ 'update_from_msats! function or manually'
328
+ end
605
329
  raise 'DLF is invalid' unless DLF_CODES.keys.include?(@dlf)
606
330
  raise 'Invalid start' unless [DateTime, Time].include?(start.class)
607
331
  raise 'Invalid finish' unless [DateTime, Time].include?(finish.class)
608
332
  raise 'start cannot be after finish' if start > finish
609
- DLF_CODES[@dlf].reject { |x| start > DateTime.parse(x['ToDate']) || finish < DateTime.parse(x['FromDate']) }
333
+ DLF_CODES[@dlf].reject { |x| start > Time.parse(x['ToDate']) || finish < Time.parse(x['FromDate']) }
610
334
  .map { |x| { 'start' => x['FromDate'], 'finish' => x['ToDate'], 'value' => x['Value'].to_f } }
611
335
  end
612
336
 
@@ -614,13 +338,16 @@ module AEMO
614
338
  #
615
339
  # @param [DateTime, Time] datetime the date for the distribution loss factor value
616
340
  # @return [nil, float] the transmission node identifier loss factor value
617
- def tni_value(datetime = DateTime.now)
618
- raise 'No TNI set, ensure that you have set the value either via the update_from_msats! function or manually' if @tni.nil?
341
+ def tni_value(datetime = Time.now)
342
+ if @tni.nil?
343
+ raise 'No TNI set, ensure that you have set the value either via the '\
344
+ 'update_from_msats! function or manually'
345
+ end
619
346
  raise 'TNI is invalid' unless TNI_CODES.keys.include?(@tni)
620
347
  raise 'Invalid date' unless [DateTime, Time].include?(datetime.class)
621
- possible_values = TNI_CODES[@tni].select { |x| DateTime.parse(x['FromDate']) <= datetime && datetime <= DateTime.parse(x['ToDate']) }
348
+ possible_values = TNI_CODES[@tni].select { |x| Time.parse(x['FromDate']) <= datetime && datetime <= Time.parse(x['ToDate']) }
622
349
  return nil if possible_values.empty?
623
- possible_values = possible_values.first['mlf_data']['loss_factors'].select { |x| DateTime.parse(x['start']) <= datetime && datetime <= DateTime.parse(x['finish']) }
350
+ possible_values = possible_values.first['mlf_data']['loss_factors'].select { |x| Time.parse(x['start']) <= datetime && datetime <= Time.parse(x['finish']) }
624
351
  return nil if possible_values.empty?
625
352
  possible_values.first['value'].to_f
626
353
  end
@@ -630,14 +357,21 @@ module AEMO
630
357
  # @param [DateTime, Time] start the date for the distribution loss factor value
631
358
  # @param [DateTime, Time] finish the date for the distribution loss factor value
632
359
  # @return [Array(Hash)] array of hashes of start, finish and value
633
- def tni_values(start = DateTime.now, finish = DateTime.now)
634
- raise 'No TNI set, ensure that you have set the value either via the update_from_msats! function or manually' if @tni.nil?
360
+ def tni_values(start = Time.now, finish = Time.now)
361
+ if @tni.nil?
362
+ raise 'No TNI set, ensure that you have set the value either via the '\
363
+ 'update_from_msats! function or manually'
364
+ end
635
365
  raise 'TNI is invalid' unless TNI_CODES.keys.include?(@tni)
636
366
  raise 'Invalid start' unless [DateTime, Time].include?(start.class)
637
367
  raise 'Invalid finish' unless [DateTime, Time].include?(finish.class)
638
368
  raise 'start cannot be after finish' if start > finish
639
- possible_values = TNI_CODES[@tni]
640
- .reject { |x| start > DateTime.parse(x['ToDate']) || finish < DateTime.parse(x['FromDate']) }
369
+
370
+ possible_values = TNI_CODES[@tni].reject do |tni_code|
371
+ start > Time.parse(tni_code['ToDate']) ||
372
+ finish < Time.parse(tni_code['FromDate'])
373
+ end
374
+
641
375
  return nil if possible_values.empty?
642
376
  possible_values.map { |x| x['mlf_data']['loss_factors'] }
643
377
  end
data/lib/aemo/version.rb CHANGED
@@ -24,7 +24,7 @@
24
24
  # @author Joel Courtney <euphemize@gmail.com>
25
25
  module AEMO
26
26
  # aemo version
27
- VERSION = '0.2.1'.freeze
27
+ VERSION = '0.3.0-rc1'
28
28
 
29
29
  # aemo version split amongst different revisions
30
30
  MAJOR_VERSION, MINOR_VERSION, REVISION = VERSION.split('.').map(&:to_i)
data/lib/aemo.rb CHANGED
@@ -11,9 +11,11 @@ require 'aemo/market/node.rb'
11
11
  require 'aemo/meter.rb'
12
12
  require 'aemo/nem12.rb'
13
13
  require 'aemo/nmi.rb'
14
+ require 'aemo/nmi/allocation.rb'
14
15
  require 'aemo/msats.rb'
15
16
  require 'aemo/register.rb'
16
17
  require 'aemo/version.rb'
18
+ require 'aemo/exceptions/invalid_nmi_allocation_type.rb'
17
19
 
18
20
  # AEMO Module to encapsulate all AEMO classes
19
21
  module AEMO
@@ -24,8 +24,8 @@ CSV.parse(file_contents, headers: true, converters: :numeric).each do |row|
24
24
  row.headers.select { |x| x =~ /^FY\d{2}$/ }.sort.reverse.each do |fin_year|
25
25
  year = "20#{fin_year.match(/FY(\d{2})/)[1]}".to_i
26
26
  @mlf_data[row['TNI']][:loss_factors] << {
27
- start: DateTime.parse("#{year - 1}-07-01T00:00:00+1000"),
28
- finish: DateTime.parse("#{year}-07-01T00:00:00+1000"),
27
+ start: Time.parse("#{year - 1}-07-01T00:00:00+1000"),
28
+ finish: Time.parse("#{year}-07-01T00:00:00+1000"),
29
29
  value: row[fin_year]
30
30
  }
31
31
  end
@@ -62,8 +62,8 @@ end
62
62
  unless @mlf_data[code].nil?
63
63
  output_data_instance[:mlf_data] = @mlf_data[code].deep_dup
64
64
  output_data_instance[:mlf_data][:loss_factors].reject! do |x|
65
- DateTime.parse(output_data_instance['ToDate']) < x[:start] ||
66
- DateTime.parse(output_data_instance['FromDate']) >= x[:finish]
65
+ Time.parse(output_data_instance['ToDate']) < x[:start] ||
66
+ Time.parse(output_data_instance['FromDate']) >= x[:finish]
67
67
  end
68
68
  puts 'output_data_instance[:mlf_data][:loss_factors]: ' \
69
69
  "#{output_data_instance[:mlf_data][:loss_factors].inspect}"
@@ -16,14 +16,14 @@ describe AEMO::Market::Interval do
16
16
  expect { AEMO::Market::Interval.new('2016-03-01T00:30:00', 'REGION' => 'NSW', 'TOTALDEMAND' => 1000.23, 'RRP' => 76.54, 'PERIODTYPE' => 'TRADING') }.not_to raise_error
17
17
  end
18
18
  it 'has a trailing datetime' do
19
- expect(@interval.datetime).to eq(DateTime.parse('2016-03-01T00:30:00+1000'))
19
+ expect(@interval.datetime).to eq(Time.parse('2016-03-01T00:30:00+1000'))
20
20
  end
21
21
  it 'has a leading datetime' do
22
- expect(@interval.datetime(false)).to eq(DateTime.parse('2016-03-01T00:00:00+1000'))
22
+ expect(@interval.datetime(false)).to eq(Time.parse('2016-03-01T00:00:00+1000'))
23
23
  end
24
24
  it 'has a leading datetime for dispatch' do
25
25
  @interval = AEMO::Market::Interval.new('2016-03-01T00:30:00', 'REGION' => 'NSW', 'TOTALDEMAND' => 1000.23, 'RRP' => 76.54, 'PERIODTYPE' => '')
26
- expect(@interval.datetime(false)).to eq(DateTime.parse('2016-03-01T00:25:00+1000'))
26
+ expect(@interval.datetime(false)).to eq(Time.parse('2016-03-01T00:25:00+1000'))
27
27
  end
28
28
  it 'has an interval length' do
29
29
  expect(@interval.interval_length).to eq(Time.at(300))
@@ -48,15 +48,11 @@ describe AEMO::MSATS do
48
48
  end
49
49
 
50
50
  it 'should return a hash of information' do
51
- expect(AEMO::MSATS.c4('4001234567', DateTime.now, DateTime.now, DateTime.now)).to be_a(Hash)
51
+ expect(AEMO::MSATS.c4('4001234567', Time.now, Time.now, Time.now)).to be_a(Hash)
52
52
  end
53
53
  it 'should raise an error for a bad nmi' do
54
54
  expect { AEMO::MSATS.c4('BOBISAFISH') }.to raise_error(ArgumentError)
55
55
  end
56
- it 'should return a hash of information' do
57
- # AEMO::MSATS.c4('4001234566', DateTime.now, DateTime.now, DateTime.now)
58
- # TODO workout what the different errors are here...
59
- end
60
56
  end
61
57
 
62
58
  describe 'invalid MSATS account' do
@@ -67,9 +63,9 @@ describe AEMO::MSATS do
67
63
  it 'should return response' do
68
64
  expect(AEMO::MSATS.c4(
69
65
  '4001234567',
70
- DateTime.now,
71
- DateTime.now,
72
- DateTime.now
66
+ Time.now,
67
+ Time.now,
68
+ Time.now
73
69
  ).class).to eq(HTTParty::Response)
74
70
  end
75
71
  end