|
3 | 3 | require 'csv'
|
4 | 4 | require 'time'
|
5 | 5 |
|
| 6 | +require 'aemo/nem12/data_stream_suffix' |
| 7 | +require 'aemo/nem12/quality_method' |
| 8 | +require 'aemo/nem12/reason_codes' |
| 9 | +require 'aemo/nem12/record_indicators' |
| 10 | +require 'aemo/nem12/transaction_code_flags' |
| 11 | +require 'aemo/nem12/unit_of_measurement' |
| 12 | + |
6 | 13 | module AEMO
|
7 | 14 | # Namespace for classes and modules that handle AEMO Gem NEM12 interactions
|
8 | 15 | # @since 0.1.4
|
9 | 16 | class NEM12
|
10 |
| - # As per AEMO NEM12 Specification |
11 |
| - # http://www.aemo.com.au/Consultations/National-Electricity-Market/Open/~/media/ |
12 |
| - # Files/Other/consultations/nem/Meter% 20Data% 20File% 20Format% 20Specification% 20 |
13 |
| - # NEM12_NEM13/MDFF_Specification_NEM12_NEM13_Final_v102_clean.ashx |
14 |
| - RECORD_INDICATORS = { |
15 |
| - 100 => 'Header', |
16 |
| - 200 => 'NMI Data Details', |
17 |
| - 300 => 'Interval Data', |
18 |
| - 400 => 'Interval Event', |
19 |
| - 500 => 'B2B Details', |
20 |
| - 900 => 'End' |
21 |
| - }.freeze |
22 |
| - |
23 |
| - TRANSACTION_CODE_FLAGS = { |
24 |
| - 'A' => 'Alteration', |
25 |
| - 'C' => 'Meter Reconfiguration', |
26 |
| - 'G' => 'Re-energisation', |
27 |
| - 'D' => 'De-energisation', |
28 |
| - 'E' => 'Forward Estimate', |
29 |
| - 'N' => 'Normal Read', |
30 |
| - 'O' => 'Other', |
31 |
| - 'S' => 'Special Read', |
32 |
| - 'R' => 'Removal of Meter' |
33 |
| - }.freeze |
34 |
| - |
35 |
| - UOM = { |
36 |
| - 'MWh' => { name: 'Megawatt Hour', multiplier: 1e6 }, |
37 |
| - 'kWh' => { name: 'Kilowatt Hour', multiplier: 1e3 }, |
38 |
| - 'Wh' => { name: 'Watt Hour', multiplier: 1 }, |
39 |
| - 'MW' => { name: 'Megawatt', multiplier: 1e6 }, |
40 |
| - 'kW' => { name: 'Kilowatt', multiplier: 1e3 }, |
41 |
| - 'W' => { name: 'Watt', multiplier: 1 }, |
42 |
| - 'MVArh' => { name: 'Megavolt Ampere Reactive Hour', multiplier: 1e6 }, |
43 |
| - 'kVArh' => { name: 'Kilovolt Ampere Reactive Hour', multiplier: 1e3 }, |
44 |
| - 'VArh' => { name: 'Volt Ampere Reactive Hour', multiplier: 1 }, |
45 |
| - 'MVAr' => { name: 'Megavolt Ampere Reactive', multiplier: 1e6 }, |
46 |
| - 'kVAr' => { name: 'Kilovolt Ampere Reactive', multiplier: 1e3 }, |
47 |
| - 'VAr' => { name: 'Volt Ampere Reactive', multiplier: 1 }, |
48 |
| - 'MVAh' => { name: 'Megavolt Ampere Hour', multiplier: 1e6 }, |
49 |
| - 'kVAh' => { name: 'Kilovolt Ampere Hour', multiplier: 1e3 }, |
50 |
| - 'VAh' => { name: 'Volt Ampere Hour', multiplier: 1 }, |
51 |
| - 'MVA' => { name: 'Megavolt Ampere', multiplier: 1e6 }, |
52 |
| - 'kVA' => { name: 'Kilovolt Ampere', multiplier: 1e3 }, |
53 |
| - 'VA' => { name: 'Volt Ampere', multiplier: 1 }, |
54 |
| - 'kV' => { name: 'Kilovolt', multiplier: 1e3 }, |
55 |
| - 'V' => { name: 'Volt', multiplier: 1 }, |
56 |
| - 'kA' => { name: 'Kiloampere', multiplier: 1e3 }, |
57 |
| - 'A' => { name: 'Ampere', multiplier: 1 }, |
58 |
| - 'pf' => { name: 'Power Factor', multiplier: 1 } |
59 |
| - }.freeze |
60 |
| - |
61 |
| - UOM_NON_SPEC_MAPPING = { |
62 |
| - 'MWH' => 'MWh', |
63 |
| - 'KWH' => 'kWh', |
64 |
| - 'WH' => 'Wh', |
65 |
| - 'MW' => 'MW', |
66 |
| - 'KW' => 'kW', |
67 |
| - 'W' => 'W', |
68 |
| - 'MVARH' => 'MVArh', |
69 |
| - 'KVARH' => 'kVArh', |
70 |
| - 'VARH' => 'VArh', |
71 |
| - 'MVAR' => 'MVAr', |
72 |
| - 'KVAR' => 'kVAr', |
73 |
| - 'VAR' => 'VAr', |
74 |
| - 'MVAH' => 'MVAh', |
75 |
| - 'KVAH' => 'kVAh', |
76 |
| - 'VAH' => 'VAh', |
77 |
| - 'MVA' => 'MVA', |
78 |
| - 'KVA' => 'kVA', |
79 |
| - 'VA' => 'VA', |
80 |
| - 'KV' => 'kV', |
81 |
| - 'V' => 'V', |
82 |
| - 'KA' => 'kA', |
83 |
| - 'A' => 'A', |
84 |
| - 'PF' => 'pf' |
85 |
| - }.freeze |
86 |
| - |
87 |
| - QUALITY_FLAGS = { |
88 |
| - 'A' => 'Actual Data', |
89 |
| - 'E' => 'Forward Estimated Data', |
90 |
| - 'F' => 'Final Substituted Data', |
91 |
| - 'N' => 'Null Data', |
92 |
| - 'S' => 'Substituted Data', |
93 |
| - 'V' => 'Variable Data' |
94 |
| - }.freeze |
95 |
| - |
96 |
| - METHOD_FLAGS = { |
97 |
| - 11 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Check', description: '' }, |
98 |
| - 12 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Calculated', description: '' }, |
99 |
| - 13 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'SCADA', description: '' }, |
100 |
| - 14 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Like Day', description: '' }, |
101 |
| - 15 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Average Like Day', description: '' }, |
102 |
| - 16 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Agreed', description: '' }, |
103 |
| - 17 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Linear', description: '' }, |
104 |
| - 18 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Alternate', description: '' }, |
105 |
| - 19 => { type: %w[SUB], installation_type: [1, 2, 3, 4], short_descriptor: 'Zero', description: '' }, |
106 |
| - 51 => { type: %w[EST SUB], installation_type: 5, short_descriptor: 'Previous Year', description: '' }, |
107 |
| - 52 => { type: %w[EST SUB], installation_type: 5, short_descriptor: 'Previous Read', description: '' }, |
108 |
| - 53 => { type: %w[SUB], installation_type: 5, short_descriptor: 'Revision', description: '' }, |
109 |
| - 54 => { type: %w[SUB], installation_type: 5, short_descriptor: 'Linear', description: '' }, |
110 |
| - 55 => { type: %w[SUB], installation_type: 5, short_descriptor: 'Agreed', description: '' }, |
111 |
| - 56 => { type: %w[EST SUB], installation_type: 5, short_descriptor: 'Prior to First Read - Agreed', description: '' }, |
112 |
| - 57 => { type: %w[EST SUB], installation_type: 5, short_descriptor: 'Customer Class', description: '' }, |
113 |
| - 58 => { type: %w[EST SUB], installation_type: 5, short_descriptor: 'Zero', description: '' }, |
114 |
| - 61 => { type: %w[EST SUB], installation_type: 6, short_descriptor: 'Previous Year', description: '' }, |
115 |
| - 62 => { type: %w[EST SUB], installation_type: 6, short_descriptor: 'Previous Read', description: '' }, |
116 |
| - 63 => { type: %w[EST SUB], installation_type: 6, short_descriptor: 'Customer Class', description: '' }, |
117 |
| - 64 => { type: %w[SUB], installation_type: 6, short_descriptor: 'Agreed', description: '' }, |
118 |
| - 65 => { type: %w[EST], installation_type: 6, short_descriptor: 'ADL', description: '' }, |
119 |
| - 66 => { type: %w[SUB], installation_type: 6, short_descriptor: 'Revision', description: '' }, |
120 |
| - 67 => { type: %w[SUB], installation_type: 6, short_descriptor: 'Customer Read', description: '' }, |
121 |
| - 68 => { type: %w[EST SUB], installation_type: 6, short_descriptor: 'Zero', description: '' }, |
122 |
| - 71 => { type: %w[SUB], installation_type: 7, short_descriptor: 'Recalculation', description: '' }, |
123 |
| - 72 => { type: %w[SUB], installation_type: 7, short_descriptor: 'Revised Table', description: '' }, |
124 |
| - 73 => { type: %w[SUB], installation_type: 7, short_descriptor: 'Revised Algorithm', description: '' }, |
125 |
| - 74 => { type: %w[SUB], installation_type: 7, short_descriptor: 'Agreed', description: '' }, |
126 |
| - 75 => { type: %w[EST], installation_type: 7, short_descriptor: 'Existing Table', description: '' } |
127 |
| - }.freeze |
128 |
| - |
129 |
| - REASON_CODES = { |
130 |
| - 0 => 'Free Text Description', |
131 |
| - 1 => 'Meter/Equipment Changed', |
132 |
| - 2 => 'Extreme Weather/Wet', |
133 |
| - 3 => 'Quarantine', |
134 |
| - 4 => 'Savage Dog', |
135 |
| - 5 => 'Meter/Equipment Changed', |
136 |
| - 6 => 'Extreme Weather/Wet', |
137 |
| - 7 => 'Unable To Locate Meter', |
138 |
| - 8 => 'Vacant Premise', |
139 |
| - 9 => 'Meter/Equipment Changed', |
140 |
| - 10 => 'Lock Damaged/Seized', |
141 |
| - 11 => 'In Wrong Walk', |
142 |
| - 12 => 'Locked Premises', |
143 |
| - 13 => 'Locked Gate', |
144 |
| - 14 => 'Locked Meter Box', |
145 |
| - 15 => 'Access - Overgrown', |
146 |
| - 16 => 'Noxious Weeds', |
147 |
| - 17 => 'Unsafe Equipment/Location', |
148 |
| - 18 => 'Read Below Previous', |
149 |
| - 19 => 'Consumer Wanted', |
150 |
| - 20 => 'Damaged Equipment/Panel', |
151 |
| - 21 => 'Switched Off', |
152 |
| - 22 => 'Meter/Equipment Seals Missing', |
153 |
| - 23 => 'Meter/Equipment Seals Missing', |
154 |
| - 24 => 'Meter/Equipment Seals Missing', |
155 |
| - 25 => 'Meter/Equipment Seals Missing', |
156 |
| - 26 => 'Meter/Equipment Seals Missing', |
157 |
| - 27 => 'Meter/Equipment Seals Missing', |
158 |
| - 28 => 'Damaged Equipment/Panel', |
159 |
| - 29 => 'Relay Faulty/Damaged', |
160 |
| - 30 => 'Meter Stop Switch On', |
161 |
| - 31 => 'Meter/Equipment Seals Missing', |
162 |
| - 32 => 'Damaged Equipment/Panel', |
163 |
| - 33 => 'Relay Faulty/Damaged', |
164 |
| - 34 => 'Meter Not In Handheld', |
165 |
| - 35 => 'Timeswitch Faulty/Reset Required', |
166 |
| - 36 => 'Meter High/Ladder Required', |
167 |
| - 37 => 'Meter High/Ladder Required', |
168 |
| - 38 => 'Unsafe Equipment/Location', |
169 |
| - 39 => 'Reverse Energy Observed', |
170 |
| - 40 => 'Timeswitch Faulty/Reset Required', |
171 |
| - 41 => 'Faulty Equipment Display/Dials', |
172 |
| - 42 => 'Faulty Equipment Display/Dials', |
173 |
| - 43 => 'Power Outage', |
174 |
| - 44 => 'Unsafe Equipment/Location', |
175 |
| - 45 => 'Readings Failed To Validate', |
176 |
| - 46 => 'Extreme Weather/Hot', |
177 |
| - 47 => 'Refused Access', |
178 |
| - 48 => 'Timeswitch Faulty/Reset Required', |
179 |
| - 49 => 'Wet Paint', |
180 |
| - 50 => 'Wrong Tariff', |
181 |
| - 51 => 'Installation Demolished', |
182 |
| - 52 => 'Access - Blocked', |
183 |
| - 53 => 'Bees/Wasp In Meter Box', |
184 |
| - 54 => 'Meter Box Damaged/Faulty', |
185 |
| - 55 => 'Faulty Equipment Display/Dials', |
186 |
| - 56 => 'Meter Box Damaged/Faulty', |
187 |
| - 57 => 'Timeswitch Faulty/Reset Required', |
188 |
| - 58 => 'Meter Ok - Supply Failure', |
189 |
| - 59 => 'Faulty Equipment Display/Dials', |
190 |
| - 60 => 'Illegal Connection/Equipment Tampered', |
191 |
| - 61 => 'Meter Box Damaged/Faulty', |
192 |
| - 62 => 'Damaged Equipment/Panel', |
193 |
| - 63 => 'Illegal Connection/Equipment Tampered', |
194 |
| - 64 => 'Key Required', |
195 |
| - 65 => 'Wrong Key Provided', |
196 |
| - 66 => 'Lock Damaged/Seized', |
197 |
| - 67 => 'Extreme Weather/Wet', |
198 |
| - 68 => 'Zero Consumption', |
199 |
| - 69 => 'Reading Exceeds Estimate', |
200 |
| - 70 => 'Probe Reports Tampering', |
201 |
| - 71 => 'Probe Read Error', |
202 |
| - 72 => 'Meter/Equipment Changed', |
203 |
| - 73 => 'Low Consumption', |
204 |
| - 74 => 'High Consumption', |
205 |
| - 75 => 'Customer Read', |
206 |
| - 76 => 'Communications Fault', |
207 |
| - 77 => 'Estimation Forecast', |
208 |
| - 78 => 'Null Data', |
209 |
| - 79 => 'Power Outage Alarm', |
210 |
| - 80 => 'Short Interval Alarm', |
211 |
| - 81 => 'Long Interval Alarm', |
212 |
| - 82 => 'CRC Error', |
213 |
| - 83 => 'RAM Checksum Error', |
214 |
| - 84 => 'ROM Checksum Error', |
215 |
| - 85 => 'Data Missing Alarm', |
216 |
| - 86 => 'Clock Error Alarm', |
217 |
| - 87 => 'Reset Occurred', |
218 |
| - 88 => 'Watchdog Timeout Alarm', |
219 |
| - 89 => 'Time Reset Occurred', |
220 |
| - 90 => 'Test Mode', |
221 |
| - 91 => 'Load Control', |
222 |
| - 92 => 'Added Interval (Data Correction)', |
223 |
| - 93 => 'Replaced Interval (Data Correction)', |
224 |
| - 94 => 'Estimated Interval (Data Correction)', |
225 |
| - 95 => 'Pulse Overflow Alarm', |
226 |
| - 96 => 'Data Out Of Limits', |
227 |
| - 97 => 'Excluded Data', |
228 |
| - 98 => 'Parity Error', |
229 |
| - 99 => 'Energy Type (Register Changed)' |
230 |
| - }.freeze |
231 |
| - |
232 |
| - DATA_STREAM_SUFFIX = { |
233 |
| - # Averaged Data Streams |
234 |
| - 'A' => { stream: 'Average', description: 'Import', units: 'kWh' }, |
235 |
| - 'D' => { stream: 'Average', description: 'Export', units: 'kWh' }, |
236 |
| - 'J' => { stream: 'Average', description: 'Import', units: 'kVArh' }, |
237 |
| - 'P' => { stream: 'Average', description: 'Export', units: 'kVArh' }, |
238 |
| - 'S' => { stream: 'Average', description: '', units: 'kVAh' }, |
239 |
| - # Master Data Streams |
240 |
| - 'B' => { stream: 'Master', description: 'Import', units: 'kWh' }, |
241 |
| - 'E' => { stream: 'Master', description: 'Export', units: 'kWh' }, |
242 |
| - 'K' => { stream: 'Master', description: 'Import', units: 'kVArh' }, |
243 |
| - 'Q' => { stream: 'Master', description: 'Export', units: 'kVArh' }, |
244 |
| - 'T' => { stream: 'Master', description: '', units: 'kVAh' }, |
245 |
| - 'G' => { stream: 'Master', description: 'Power Factor', units: 'PF' }, |
246 |
| - 'H' => { stream: 'Master', description: 'Q Metering', units: 'Qh' }, |
247 |
| - 'M' => { stream: 'Master', description: 'Par Metering', units: 'parh' }, |
248 |
| - 'V' => { stream: 'Master', description: 'Volts or V2h or Amps or A2h', units: '' }, |
249 |
| - # Check Meter Streams |
250 |
| - 'C' => { stream: 'Check', description: 'Import', units: 'kWh' }, |
251 |
| - 'F' => { stream: 'Check', description: 'Export', units: 'kWh' }, |
252 |
| - 'L' => { stream: 'Check', description: 'Import', units: 'kVArh' }, |
253 |
| - 'R' => { stream: 'Check', description: 'Export', units: 'kVArh' }, |
254 |
| - 'U' => { stream: 'Check', description: '', units: 'kVAh' }, |
255 |
| - 'Y' => { stream: 'Check', description: 'Q Metering', units: 'Qh' }, |
256 |
| - 'W' => { stream: 'Check', description: 'Par Metering Path', units: '' }, |
257 |
| - 'Z' => { stream: 'Check', description: 'Volts or V2h or Amps or A2h', units: '' }, |
258 |
| - # Net Meter Streams |
259 |
| - # AEMO: NOTE THAT D AND J ARE PREVIOUSLY DEFINED |
260 |
| - # 'D' => { stream: 'Net', description: 'Net', units: 'kWh' }, |
261 |
| - # 'J' => { stream: 'Net', description: 'Net', units: 'kVArh' } |
262 |
| - }.freeze |
263 |
| - |
264 | 17 | @file_contents = nil
|
265 | 18 | @header = nil
|
266 | 19 | @nmi_data_details = []
|
|
0 commit comments