openstudio-metadata 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,574 @@
1
+ ########################################################################################################################
2
+ # Copyright (c) 2008-2018, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5
+ # following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
8
+ # disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
11
+ # disclaimer in the documentation and/or other materials provided with the distribution.
12
+ #
13
+ # (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
14
+ # derived from this software without specific prior written permission from the respective party.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
19
+ # STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21
+ # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
+ ########################################################################################################################
25
+
26
+ require 'json'
27
+ require_relative 'resources/openstudio-metadata-gem/lib/openstudio/metadata'
28
+
29
+ # start the measure
30
+ class Haystack < OpenStudio::Ruleset::ModelUserScript
31
+ # human readable name
32
+ def name
33
+ return 'Haystack'
34
+ end
35
+
36
+ # human readable description
37
+ def description
38
+ return 'This measure will find economizers on airloops and add haystack tags.'
39
+ end
40
+
41
+ # human readable description of modeling approach
42
+ def modeler_description
43
+ return 'This measure loops through the existing airloops, looking for loops that have outdoor airsystems with economizers'
44
+ end
45
+
46
+ # define the arguments that the user will input
47
+ def arguments(model)
48
+ args = OpenStudio::Ruleset::OSArgumentVector.new
49
+
50
+ local_test = OpenStudio::Ruleset::OSArgument.makeBoolArgument('local_test', false)
51
+ local_test.setDisplayName('Local Test')
52
+ local_test.setDescription('Use EMS for Local Testing')
53
+ local_test.setDefaultValue(true)
54
+ args << local_test
55
+
56
+ return args
57
+ end # end the arguments method
58
+
59
+ # define what happens when the measure is run
60
+ def run(model, runner, user_arguments)
61
+ super(model, runner, user_arguments)
62
+
63
+ # Use the built-in error checking
64
+ if !runner.validateUserArguments(arguments(model), user_arguments)
65
+ return false
66
+ end
67
+
68
+ local_test = runner.getBoolArgumentValue('local_test', user_arguments)
69
+ runner.registerInfo("local_test = #{local_test}")
70
+
71
+ # initialize tagger
72
+ tagger = OpenStudio::Metadata::Tagger.new(model)
73
+
74
+ # Global Vars
75
+ report_freq = 'timestep'
76
+
77
+ # initialize variables
78
+ haystack_json = []
79
+ mapping_json = []
80
+ num_economizers = 0
81
+ airloops = []
82
+
83
+ # Master Enable
84
+ if local_test == false
85
+ # External Interface version
86
+ runner.registerInitialCondition('Initializing ExternalInterface')
87
+ master_enable = OpenStudio::Model::ExternalInterfaceVariable.new(model, 'MasterEnable', 1)
88
+ # TODO: uncomment out for real use
89
+ externalInterface = model.getExternalInterface
90
+ externalInterface.setNameofExternalInterface('PtolemyServer')
91
+ else
92
+ # EMS Version
93
+ runner.registerInitialCondition('Initializing EnergyManagementSystem')
94
+ master_enable = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'MasterEnable')
95
+ end
96
+
97
+ # initialization program
98
+ program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
99
+ program.setName('Master_Enable')
100
+ program.addLine("SET #{master_enable.handle} = 1")
101
+
102
+ pcm = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
103
+ pcm.setName('Master_Enable_Prgm_Mgr')
104
+ pcm.setCallingPoint('BeginNewEnvironment')
105
+ pcm.addProgram(program)
106
+
107
+ # Site and WeatherFile Data
108
+ if model.weatherFile.is_initialized
109
+
110
+ wf = model.weatherFile.get
111
+ building = model.getBuilding
112
+ simCon = model.getSimulationControl
113
+
114
+ # Define the site, weather, and floor for haystack
115
+ tagger.tag_site
116
+ tagger.tag_weather
117
+ tagger.tag_thermal_zones
118
+ tagger.tag_air_loop_fans
119
+
120
+ end
121
+
122
+ ## Add tags to the time-variable outputs
123
+ # #output_vars = model.getOutputVariables
124
+ # output_vars = model.getEnergyManagementSystemOutputVariables
125
+ # output_vars_sorted = output_vars.sort_by{ |m| [ m.nameString.downcase]}
126
+ # output_vars_sorted.each do |outvar|
127
+ # #if (outvar.keyValue.to_s == "*")
128
+ # #print outvar
129
+ # print "\n The haystack tag is beding added to time-variables!!!"
130
+ # haystack_temp_json, temp_uuid = tagger.create_point_timevars(outvar, model.getBuilding.handle)
131
+ # haystack_json << haystack_temp_json
132
+ # temp_mapping = tagger.create_mapping_timevars(outvar,temp_uuid)
133
+ # mapping_json << temp_mapping
134
+ # #end
135
+ #
136
+ # end # end of do loop
137
+
138
+ # Export all user defined OutputVariable objects
139
+ # as haystack sensor points
140
+ building = model.getBuilding
141
+ output_vars = model.getOutputVariables
142
+ output_vars.each do |outvar|
143
+ if outvar.exportToBCVTB
144
+
145
+ user_defined_sensor_point = tagger.tag_sensor(outvar.handle, outvar.nameString, building.handle)
146
+ haystack_json << user_defined_sensor_point
147
+
148
+ uuid = tagger.haystack_format_as_ref(outvar.handle)
149
+ var_map_json = {}
150
+ var_map_json[:id] = uuid
151
+ var_map_json[:source] = 'EnergyPlus'
152
+ var_map_json[:type] = outvar.variableName
153
+ var_map_json[:name] = outvar.keyValue
154
+ var_map_json[:variable] = ''
155
+ mapping_json << var_map_json
156
+ end
157
+ end
158
+
159
+ # Tag thermal zones
160
+
161
+ # Tag fans
162
+
163
+ # Export all user defined EnergyManagementSystemGlobalVariable objects
164
+ # as haystack writable points
165
+ global_vars = model.getEnergyManagementSystemGlobalVariables
166
+ global_vars.each do |globalvar|
167
+ if globalvar.exportToBCVTB
168
+ uuid = tagger.haystack_format_as_ref(globalvar.handle)
169
+ if !globalvar.nameString.end_with?('_Enable')
170
+ user_defined_writable_point = tagger.tag_writable_point(globalvar.nameString, building.handle, uuid)
171
+ haystack_json << user_defined_writable_point
172
+ end
173
+
174
+ var_mapping_json = {}
175
+ var_mapping_json[:id] = uuid
176
+ var_mapping_json[:source] = 'Ptolemy'
177
+ var_mapping_json[:name] = ''
178
+ var_mapping_json[:type] = ''
179
+ var_mapping_json[:variable] = globalvar.nameString
180
+ mapping_json << var_mapping_json
181
+ end
182
+ end
183
+
184
+ # loop through air loops and find economizers
185
+ model.getAirLoopHVACs.each do |airloop|
186
+ supply_components = airloop.supplyComponents
187
+ # find AirLoopHVACOutdoorAirSystem on loop
188
+ supply_components.each do |supply_component|
189
+ sc = supply_component.to_AirLoopHVACOutdoorAirSystem
190
+ if sc.is_initialized
191
+ sc = sc.get
192
+ # get ControllerOutdoorAir
193
+ controller_oa = sc.getControllerOutdoorAir
194
+ # log initial economizer type
195
+ if controller_oa.getEconomizerControlType != 'NoEconomizer'
196
+ runner.registerInfo("found economizer on airloop #{airloop.name}")
197
+ # puts "found economizer on airloop #{airloop.name.to_s}"
198
+ num_economizers += 1
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ # loop through economizer loops and find fans and cooling coils
205
+ model.getAirLoopHVACs.each do |airloop|
206
+ ahu_json = tagger.create_ahu(airloop.handle, airloop.name.to_s, building.handle, simCon.handle)
207
+
208
+ # AHU discharge sensors
209
+ # discharge air node
210
+ discharge_air_node = airloop.supplyOutletNode
211
+ # Tag Temp, Pressure, Humidity, and Flow Sensors
212
+ discharge_temp_sensor, discharge_temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Discharge Air Temp Sensor", building.handle, airloop.handle, simCon.handle, 'discharge', 'air', 'temp', 'Number', 'C')
213
+ discharge_pressure_sensor, discharge_pressure_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Discharge Air Pressure Sensor", building.handle, airloop.handle, simCon.handle, 'discharge', 'air', 'pressure', 'Number', 'Pa')
214
+ discharge_humidity_sensor, discharge_humidity_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Discharge Air Humidity Sensor", building.handle, airloop.handle, simCon.handle, 'discharge', 'air', 'humidity', 'Number', '%')
215
+ discharge_flow_sensor, discharge_flow_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Discharge Air Flow Sensor", building.handle, airloop.handle, simCon.handle, 'discharge', 'air', 'flow', 'Number', 'Kg/s')
216
+ haystack_json.push(discharge_temp_sensor, discharge_pressure_sensor, discharge_humidity_sensor, discharge_flow_sensor)
217
+
218
+ # Controls Definitions and assignments
219
+ discharge_air_temp_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Temperature', discharge_air_node, "#{airloop.name} Discharge Air Temp Sensor", discharge_temp_uuid, report_freq, model)
220
+ mapping_json << temp_json
221
+ discharge_air_pressure_sensor = tagger.create_EMS_sensor('System Node Pressure', discharge_air_node, "#{airloop.name} Discharge Air Pressure Sensor", report_freq, model)
222
+ discharge_air_humidity_sensor = tagger.create_EMS_sensor('System Node Relative Humidity', discharge_air_node, "#{airloop.name} Discharge Air Humidity Sensor", report_freq, model)
223
+ discharge_air_flow_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Mass Flow Rate', discharge_air_node, "#{airloop.name} Discharge Air Flow Sensor", discharge_flow_uuid, report_freq, model)
224
+ mapping_json << temp_json
225
+
226
+ supply_components = airloop.supplyComponents
227
+
228
+ # find fan, cooling coil and heating coil on loop
229
+ supply_components.each do |sc|
230
+ # get economizer on outdoor air system
231
+ if sc.to_AirLoopHVACOutdoorAirSystem.is_initialized
232
+ sc = sc.to_AirLoopHVACOutdoorAirSystem.get
233
+ # get ControllerOutdoorAir
234
+ controller_oa = sc.getControllerOutdoorAir
235
+ # create damper sensor and cmd points
236
+ damper_command = tagger.create_ems_str("#{airloop.name} Outside Air Damper CMD")
237
+ damper_command_enable = tagger.create_ems_str("#{airloop.name} Outside Air Damper CMD Enable")
238
+ damper_position = tagger.create_ems_str("#{airloop.name} Outside Air Damper Sensor position")
239
+ # Damper Sensor
240
+ haystack_temp_json, temp_uuid = tagger.create_point2_uuid('sensor', 'position', damper_position, building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'damper', 'Number', '%')
241
+ haystack_json << haystack_temp_json
242
+ outside_air_damper_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('Air System Outdoor Air Flow Fraction', airloop, "#{airloop.name} Outside Air Damper Sensor", temp_uuid, report_freq, model)
243
+ mapping_json << temp_json
244
+
245
+ # add EMS Actuator for Damper
246
+ damper_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(controller_oa, 'Outdoor Air Controller', 'Air Mass Flow Rate')
247
+ damper_actuator.setName(tagger.create_ems_str("#{airloop.name} Outside Air Mass Flow Rate"))
248
+ # Variable to read the Damper CMD
249
+ if local_test == false
250
+ # ExternalInterfaceVariables
251
+ damper_variable_enable = OpenStudio::Model::ExternalInterfaceVariable.new(model, damper_command_enable, 1)
252
+ mapping_json << tagger.create_mapping_output_uuid(damper_command_enable, damper_variable_enable.handle)
253
+ damper_variable = OpenStudio::Model::ExternalInterfaceVariable.new(model, damper_command, 0.5)
254
+ mapping_json << tagger.create_mapping_output_uuid(damper_command, damper_variable.handle)
255
+ # Damper CMD
256
+ haystack_temp_json = tagger.create_controlpoint2('cmd', 'writable', damper_command, damper_variable.handle, building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'damper', 'Number', '%')
257
+ haystack_json << haystack_temp_json
258
+ else
259
+ # EnergyManagementSystemVariables
260
+ damper_variable_enable = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, damper_command_enable.to_s)
261
+ mapping_json << tagger.create_mapping_output_uuid(damper_command_enable, damper_variable_enable.handle)
262
+ damper_variable = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, damper_command.to_s)
263
+ mapping_json << tagger.create_mapping_output_uuid(damper_command, damper_variable.handle)
264
+ # Damper CMD
265
+ haystack_temp_json = tagger.create_controlpoint2('cmd', 'writable', damper_command, damper_variable.handle, building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'damper', 'Number', '%')
266
+ haystack_json << haystack_temp_json
267
+ # initialization program
268
+ program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
269
+ program.setName("#{damper_command}_Prgm_init")
270
+ # Turn off for now
271
+ program.addLine("SET #{damper_variable_enable.handle} = 0")
272
+ program.addLine("SET #{damper_variable.handle} = 0.5")
273
+
274
+ pcm = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
275
+ pcm.setName("#{damper_command}_Prgm_Mgr_init")
276
+ pcm.setCallingPoint('BeginNewEnvironment')
277
+ pcm.addProgram(program)
278
+ end
279
+ # mixed air node
280
+ if sc.mixedAirModelObject.is_initialized
281
+ # AHU mixed sensors
282
+ # mixed air node
283
+ mix_air_node = sc.mixedAirModelObject.get.to_Node.get
284
+ runner.registerInfo("found mixed air node #{mix_air_node.name} on airloop #{airloop.name}")
285
+ # Temp Sensor
286
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Mixed Air Temp Sensor", building.handle, airloop.handle, simCon.handle, 'mixed', 'air', 'temp', 'Number', 'C')
287
+ haystack_json << haystack_temp_json
288
+ mixed_air_temp_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Temperature', mix_air_node, "#{airloop.name} Mixed Air Temp Sensor", temp_uuid, report_freq, model)
289
+ mapping_json << temp_json
290
+ # Pressure Sensor
291
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Mixed Air Pressure Sensor", building.handle, airloop.handle, simCon.handle, 'mixed', 'air', 'pressure', 'Number', 'Pa')
292
+ haystack_json << haystack_temp_json
293
+ mixed_air_pressure_sensor = tagger.create_EMS_sensor('System Node Pressure', mix_air_node, "#{airloop.name} Mixed Air Pressure Sensor", report_freq, model)
294
+ # Humidity Sensor
295
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Mixed Air Humidity Sensor", building.handle, airloop.handle, simCon.handle, 'mixed', 'air', 'humidity', 'Number', '%')
296
+ haystack_json << haystack_temp_json
297
+ mixed_air_humidity_sensor = tagger.create_EMS_sensor('System Node Relative Humidity', mix_air_node, "#{airloop.name} Mixed Air Humidity Sensor", report_freq, model)
298
+ # Flow Sensor
299
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Mixed Air Flow Sensor", building.handle, airloop.handle, simCon.handle, 'mixed', 'air', 'flow', 'Number', 'Kg/s')
300
+ haystack_json << haystack_temp_json
301
+ mixed_air_flow_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Mass Flow Rate', mix_air_node, "#{airloop.name} Mixed Air Flow Sensor", temp_uuid, report_freq, model)
302
+ mapping_json << temp_json
303
+ end
304
+ # outdoor air node
305
+ if sc.outdoorAirModelObject.is_initialized
306
+ # AHU outside sensors
307
+ # outdoor air node
308
+ outdoor_air_node = sc.outdoorAirModelObject.get.to_Node.get
309
+ runner.registerInfo("found outdoor air node #{outdoor_air_node.name} on airloop #{airloop.name}")
310
+ # Temp Sensor
311
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Outside Air Temp Sensor", building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'temp', 'Number', 'C')
312
+ haystack_json << haystack_temp_json
313
+ outside_air_temp_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Temperature', outdoor_air_node, "#{airloop.name} Outside Air Temp Sensor", temp_uuid, report_freq, model)
314
+ mapping_json << temp_json
315
+ # Pressure Sensor
316
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Outside Air Pressure Sensor", building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'pressure', 'Number', 'Pa')
317
+ haystack_json << haystack_temp_json
318
+ outside_air_pressure_sensor = tagger.create_EMS_sensor('System Node Pressure', outdoor_air_node, "#{airloop.name} Outside Air Pressure Sensor", report_freq, model)
319
+ # Humidity Sensor
320
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Outside Air Humidity Sensor", building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'humidity', 'Number', '%')
321
+ haystack_json << haystack_temp_json
322
+ outside_air_humidity_sensor = tagger.create_EMS_sensor('System Node Relative Humidity', outdoor_air_node, "#{airloop.name} Outside Air Humidity Sensor", report_freq, model)
323
+ # Flow Sensor
324
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Outside Air Flow Sensor", building.handle, airloop.handle, simCon.handle, 'outside', 'air', 'flow', 'Number', 'Kg/s')
325
+ haystack_json << haystack_temp_json
326
+ outside_air_flow_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Mass Flow Rate', outdoor_air_node, "#{airloop.name} Outside Air Flow Sensor", temp_uuid, report_freq, model)
327
+ mapping_json << temp_json
328
+ end
329
+ # return air node
330
+ if sc.returnAirModelObject.is_initialized
331
+ # AHU return sensors
332
+ # return air node
333
+ return_air_node = sc.returnAirModelObject.get.to_Node.get
334
+ runner.registerInfo("found return air node #{return_air_node.name} on airloop #{airloop.name}")
335
+ # Temp Sensor
336
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Return Air Temp Sensor", building.handle, airloop.handle, simCon.handle, 'return', 'air', 'temp', 'Number', 'C')
337
+ haystack_json << haystack_temp_json
338
+ return_air_temp_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Temperature', return_air_node, "#{airloop.name} Return Air Temp Sensor", temp_uuid, report_freq, model)
339
+ mapping_json << temp_json
340
+ # Pressure Sensor
341
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Return Air Pressure Sensor", building.handle, airloop.handle, simCon.handle, 'return', 'air', 'pressure', 'Number', 'Pa')
342
+ haystack_json << haystack_temp_json
343
+ return_air_pressure_sensor = tagger.create_EMS_sensor('System Node Pressure', return_air_node, "#{airloop.name} Return Air Pressure Sensor", report_freq, model)
344
+ # Humidity Sensor
345
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Return Air Humidity Sensor", building.handle, airloop.handle, simCon.handle, 'return', 'air', 'humidity', 'Number', '%')
346
+ haystack_json << haystack_temp_json
347
+ return_air_humidity_sensor = tagger.create_EMS_sensor('System Node Relative Humidity', return_air_node, "#{airloop.name} Return Air Humidity Sensor", report_freq, model)
348
+ # Flow Sensor
349
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Return Air Flow Sensor", building.handle, airloop.handle, simCon.handle, 'return', 'air', 'flow', 'Number', 'Kg/s')
350
+ haystack_json << haystack_temp_json
351
+ return_air_flow_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Mass Flow Rate', return_air_node, "#{airloop.name} Return Air Flow Sensor", temp_uuid, report_freq, model)
352
+ mapping_json << temp_json
353
+ end
354
+ # relief air node
355
+ if sc.reliefAirModelObject.is_initialized
356
+ # AHU exhaust sensors
357
+ # exhaust air node
358
+ exhaust_air_node = sc.reliefAirModelObject.get.to_Node.get
359
+ runner.registerInfo("found relief air node #{exhaust_air_node.name} on airloop #{airloop.name}")
360
+ # Temp Sensor
361
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Exhaust Air Temp Sensor", building.handle, airloop.handle, simCon.handle, 'exhaust', 'air', 'temp', 'Number', 'C')
362
+ haystack_json << haystack_temp_json
363
+ exhaust_air_temp_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Temperature', exhaust_air_node, "#{airloop.name} Exhaust Air Temp Sensor", temp_uuid, report_freq, model)
364
+ mapping_json << temp_json
365
+ # Pressure Sensor
366
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Exhaust Air Pressure Sensor", building.handle, airloop.handle, simCon.handle, 'exhaust', 'air', 'pressure', 'Number', 'Pa')
367
+ haystack_json << haystack_temp_json
368
+ exhaust_air_pressure_sensor = tagger.create_EMS_sensor('System Node Pressure', exhaust_air_node, "#{airloop.name} Exhaust Air Pressure Sensor", report_freq, model)
369
+ # Humidity Sensor
370
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Exhaust Air Humidity Sensor", building.handle, airloop.handle, simCon.handle, 'exhaust', 'air', 'humidity', 'Number', '%')
371
+ haystack_json << haystack_temp_json
372
+ exhaust_air_humidity_sensor = tagger.create_EMS_sensor('System Node Relative Humidity', exhaust_air_node, "#{airloop.name} Exhaust Air Humidity Sensor", report_freq, model)
373
+ # Flow Sensor
374
+ haystack_temp_json, temp_uuid = tagger.create_point_uuid('sensor', "#{airloop.name} Exhaust Air Flow Sensor", building.handle, airloop.handle, simCon.handle, 'exhaust', 'air', 'flow', 'Number', 'Kg/s')
375
+ haystack_json << haystack_temp_json
376
+ exhaust_air_flow_sensor, temp_json = tagger.create_EMS_sensor_bcvtb('System Node Mass Flow Rate', exhaust_air_node, "#{airloop.name} Exhaust Air Flow Sensor", temp_uuid, report_freq, model)
377
+ mapping_json << temp_json
378
+ end
379
+
380
+ # Program to set the Damper Position
381
+ program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
382
+ program.setName("#{damper_command}_Prgm")
383
+ program.addLine("SET #{damper_actuator.handle} = Null")
384
+ program.addLine("IF #{master_enable.handle} == 1")
385
+ program.addLine(" SET DampPos = #{damper_variable.handle}")
386
+ program.addLine(" SET MixAir = #{mixed_air_flow_sensor.handle}")
387
+ program.addLine(" IF #{damper_variable_enable.handle} == 1")
388
+ program.addLine(" SET #{damper_actuator.handle} = DampPos*MixAir")
389
+ program.addLine(' ENDIF')
390
+ program.addLine('ENDIF')
391
+
392
+ pcm = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
393
+ pcm.setName("#{damper_command}_Prgm_Mgr")
394
+ pcm.setCallingPoint('AfterPredictorAfterHVACManagers')
395
+ pcm.addProgram(program)
396
+
397
+ # its a UnitarySystem so get sub components
398
+ elsif sc.to_AirLoopHVACUnitarySystem.is_initialized
399
+ sc = sc.to_AirLoopHVACUnitarySystem.get
400
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
401
+ ahu_json[:rooftop] = 'm:'
402
+ fan = sc.supplyFan
403
+ if fan.is_initialized
404
+ # AHU FAN equip
405
+ if fan.get.to_FanVariableVolume.is_initialized
406
+ runner.registerInfo("found VAV #{fan.get.name} on airloop #{airloop.name}")
407
+ ahu_json[:variableVolume] = 'm:'
408
+ haystack_json << tagger.create_fan(fan.get.handle, fan.get.name.to_s, building.handle, airloop.handle, simCon.handle, true)
409
+ else
410
+ runner.registerInfo("found CAV #{fan.get.name} on airloop #{airloop.name}")
411
+ ahu_json[:constantVolume] = 'm:'
412
+ haystack_json << tagger.create_fan(fan.get.handle, fan.get.name.to_s, building.handle, airloop.handle, simCon.handle, false)
413
+ end
414
+ end
415
+ cc = sc.coolingCoil
416
+ if cc.is_initialized
417
+ if cc.get.to_CoilCoolingWater.is_initialized || cc.get.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized
418
+ runner.registerInfo("found WATER #{cc.get.name} on airloop #{airloop.name}")
419
+ ahu_json[:chilledWaterCool] = 'm:'
420
+ if cc.get.plantLoop.is_initialized
421
+ pl = cc.get.plantLoop.get
422
+ ahu_json[:chilledWaterPlantRef] = tagger.haystack_format_as_ref(pl.handle)
423
+ end
424
+ if cc.get.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized
425
+ ahu_json[:heatPump] = 'm:'
426
+ end
427
+ else
428
+ runner.registerInfo("found DX #{cc.get.name} on airloop #{airloop.name}")
429
+ ahu_json[:dxCool] = 'm:'
430
+ end
431
+ end
432
+ hc = sc.heatingCoil
433
+ if hc.is_initialized
434
+ if hc.get.to_CoilHeatingElectric.is_initialized
435
+ runner.registerInfo("found ELECTRIC #{hc.get.name} on airloop #{airloop.name}")
436
+ ahu_json[:elecHeat] = 'm:'
437
+ elsif hc.get.to_CoilHeatingGas.is_initialized
438
+ runner.registerInfo("found GAS #{hc.get.name} on airloop #{airloop.name}")
439
+ ahu_json[:gasHeat] = 'm:'
440
+ elsif hc.get.to_CoilHeatingWater.is_initialized || hc.get.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized
441
+ runner.registerInfo("found WATER #{hc.get.name} on airloop #{airloop.name}")
442
+ ahu_json[:hotWaterHeat] = 'm:'
443
+ if hc.get.plantLoop.is_initialized
444
+ pl = hc.get.plantLoop.get
445
+ ahu_json[:hotWaterPlantRef] = tagger.haystack_format_as_ref(pl.handle)
446
+ end
447
+ if hc.get.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized
448
+ ahu_json[:heatPump] = 'm:'
449
+ end
450
+ end
451
+ end
452
+ # END UnitarySystem
453
+ elsif sc.to_FanConstantVolume.is_initialized
454
+ sc = sc.to_FanConstantVolume.get
455
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
456
+ ahu_json[:constantVolume] = 'm:'
457
+ haystack_json << tagger.create_fan(sc.handle, sc.name.to_s, building.handle, airloop.handle, simCon.handle, false)
458
+ elsif sc.to_FanVariableVolume.is_initialized
459
+ sc = sc.to_FanVariableVolume.get
460
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
461
+ ahu_json[:variableVolume] = 'm:'
462
+ haystack_json << tagger.create_fan(sc.handle, sc.name.to_s, building.handle, airloop.handle, simCon.handle, true)
463
+ elsif sc.to_FanOnOff.is_initialized
464
+ sc = sc.to_FanOnOff.get
465
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
466
+ ahu_json[:constantVolume] = 'm:'
467
+ haystack_json << tagger.create_fan(sc.handle, sc.name.to_s, building.handle, airloop.handle, simCon.handle, false)
468
+ elsif sc.to_CoilCoolingWater.is_initialized
469
+ sc = sc.to_CoilCoolingWater.get
470
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
471
+ ahu_json[:chilledWaterCool] = 'm:'
472
+ if sc.plantLoop.is_initialized
473
+ pl = sc.plantLoop.get
474
+ ahu_json[:chilledWaterPlantRef] = tagger.haystack_format_as_ref(pl.handle)
475
+ end
476
+ elsif sc.to_CoilHeatingWater.is_initialized
477
+ sc = sc.to_CoilHeatingWater.get
478
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
479
+ ahu_json[:hotWaterHeat] = 'm:'
480
+ if sc.plantLoop.is_initialized
481
+ pl = sc.plantLoop.get
482
+ ahu_json[:hotWaterPlantRef] = tagger.haystack_format_as_ref(pl.handle)
483
+ end
484
+ elsif sc.to_CoilHeatingElectric.is_initialized
485
+ sc = sc.to_CoilHeatingElectric.get
486
+ runner.registerInfo("found #{sc.name} on airloop #{airloop.name}")
487
+ ahu_json[:elecHeat] = 'm:'
488
+ end
489
+ end # end supplycomponents
490
+
491
+ demand_components = airloop.demandComponents
492
+ demand_components.each do |dc|
493
+ if dc.to_ThermalZone.is_initialized
494
+ tz = dc.to_ThermalZone.get
495
+ # create sensor points
496
+ zone_json_temp, dummyvar = tagger.create_point_uuid('sensor', "#{tz.name} Zone Air Temp Sensor", building.handle, airloop.handle, simCon.handle, 'zone', 'air', 'temp', 'Number', 'C')
497
+ zone_json_humidity, dummyvar = tagger.create_point_uuid('sensor', "#{tz.name} Zone Air Humidity Sensor", building.handle, airloop.handle, simCon.handle, 'zone', 'air', 'humidity', 'Number', '%')
498
+
499
+ if tz.thermostatSetpointDualSetpoint.is_initialized
500
+ if tz.thermostatSetpointDualSetpoint.get.coolingSetpointTemperatureSchedule.is_initialized
501
+ cool_thermostat = tz.thermostatSetpointDualSetpoint.get.coolingSetpointTemperatureSchedule.get
502
+ runner.registerInfo("found #{cool_thermostat.name} on airloop #{airloop.name} in thermalzone #{tz.name}")
503
+ zone_json_cooling, dummyvar = tagger.create_point_uuid('sp', "#{tz.name} Zone Air Cooling sp", building.handle, airloop.handle, simCon.handle, 'zone', 'air', 'temp', 'Number', 'C')
504
+ zone_json_cooling[:cooling] = 'm:'
505
+ end
506
+ if tz.thermostatSetpointDualSetpoint.get.heatingSetpointTemperatureSchedule.is_initialized
507
+ heat_thermostat = tz.thermostatSetpointDualSetpoint.get.heatingSetpointTemperatureSchedule.get
508
+ runner.registerInfo("found #{heat_thermostat.name} on airloop #{airloop.name} in thermalzone #{tz.name}")
509
+ zone_json_heating, dummyvar = tagger.create_point_uuid('sp', "#{tz.name} Zone Air Heating sp", building.handle, airloop.handle, simCon.handle, 'zone', 'air', 'temp', 'Number', 'C')
510
+ zone_json_heating[:heating] = 'm:'
511
+ end
512
+ end
513
+ zone_json_temp[:area] = tagger.haystack_format_as_num(tz.floorArea)
514
+ if tz.volume.is_initialized
515
+ zone_json_temp[:volume] = tagger.haystack_format_as_num(tz.volume)
516
+ else
517
+ zone_json_temp[:volume] = tagger.haystack_format_as_num(0)
518
+ end
519
+ zone_json_humidity[:area] = tagger.haystack_format_as_num(tz.floorArea)
520
+ if tz.volume.is_initialized
521
+ zone_json_humidity[:volume] = tagger.haystack_format_as_num(tz.volume)
522
+ else
523
+ zone_json_humidity[:volume] = tagger.haystack_format_as_num(0)
524
+ end
525
+
526
+ tz.equipment.each do |equip|
527
+ if equip.to_AirTerminalSingleDuctVAVReheat.is_initialized
528
+ zone_json_temp[:vav] = 'm:'
529
+ zone_json_humidity[:vav] = 'm:'
530
+ zone_json_cooling[:vav] = 'm:'
531
+ zone_json_heating[:vav] = 'm:'
532
+ ahu_json[:vavZone] = 'm:'
533
+
534
+ vav_json = tagger.create_vav(equip.handle, equip.name.to_s)
535
+
536
+ haystack_json << vav_json
537
+ # entering and discharge sensors
538
+ entering_node = equip.to_AirTerminalSingleDuctVAVReheat.get.inletModelObject.get.to_Node
539
+ haystack_json_temp, temp_uuid = tagger.create_point_uuid('sensor', "#{equip.name} Entering Air Temp Sensor", building.handle, equip.handle, simCon.handle, 'entering', 'air', 'temp', 'Number', 'C')
540
+ haystack_json << haystack_json_temp
541
+ discharge_node = equip.to_AirTerminalSingleDuctVAVReheat.get.outletModelObject.get.to_Node
542
+ haystack_json_temp, temp_uuid = tagger.create_point_uuid('sensor', "#{equip.name} Discharge Air Temp Sensor", building.handle, equip.handle, simCon.handle, 'discharge', 'air', 'temp', 'Number', 'C')
543
+ haystack_json << haystack_json_temp
544
+ avail_sch = discharge_node = equip.to_AirTerminalSingleDuctVAVReheat.get.availabilitySchedule
545
+ # TODO: 'reheat cmd'
546
+ elsif equip.to_AirTerminalSingleDuctUncontrolled.is_initialized
547
+ ahu_json[:directZone] = 'm:'
548
+ end
549
+ end
550
+ haystack_json << zone_json_temp
551
+ haystack_json << zone_json_humidity
552
+ haystack_json << zone_json_cooling
553
+ haystack_json << zone_json_heating
554
+ end # end thermalzone
555
+ end # end demandcomponents
556
+ haystack_json << ahu_json
557
+ end # end airloops
558
+
559
+ runner.registerFinalCondition("The building has #{num_economizers} economizers")
560
+ # write out the haystack json
561
+ File.open('./report_haystack.json', 'w') do |f|
562
+ f.write(haystack_json.to_json)
563
+ end
564
+ # write out the mapping json
565
+ File.open('./report_mapping.json', 'w') do |f|
566
+ f.write(mapping_json.to_json)
567
+ end
568
+
569
+ return true
570
+ end # end the run method
571
+ end # end the measure
572
+
573
+ # register the measure to be used by the application
574
+ Haystack.new.registerWithApplication
@@ -0,0 +1,83 @@
1
+ <measure>
2
+ <schema_version>3.0</schema_version>
3
+ <name>haystack</name>
4
+ <uid>a3201f8c-bc3d-4fe1-a945-4a4f22471c06</uid>
5
+ <version_id>967b2a78-232e-479d-bf84-f21e146f6737</version_id>
6
+ <version_modified>20180109T180541Z</version_modified>
7
+ <xml_checksum>A9D5932A</xml_checksum>
8
+ <class_name>Haystack</class_name>
9
+ <display_name>Haystack</display_name>
10
+ <description>This measure will find economizers on airloops and add haystack tags.</description>
11
+ <modeler_description>This measure loops through the existing airloops, looking for loops that have outdoor airsystems with economizers</modeler_description>
12
+ <arguments>
13
+ <argument>
14
+ <name>local_test</name>
15
+ <display_name>Local Test</display_name>
16
+ <description>Use EMS for Local Testing</description>
17
+ <type>Boolean</type>
18
+ <required>false</required>
19
+ <model_dependent>false</model_dependent>
20
+ <default_value>true</default_value>
21
+ <choices>
22
+ <choice>
23
+ <value>true</value>
24
+ <display_name>true</display_name>
25
+ </choice>
26
+ <choice>
27
+ <value>false</value>
28
+ <display_name>false</display_name>
29
+ </choice>
30
+ </choices>
31
+ </argument>
32
+ </arguments>
33
+ <outputs/>
34
+ <provenances/>
35
+ <tags>
36
+ <tag>HVAC.Whole System</tag>
37
+ </tags>
38
+ <attributes>
39
+ <attribute>
40
+ <name>Measure Type</name>
41
+ <value>ModelMeasure</value>
42
+ <datatype>string</datatype>
43
+ </attribute>
44
+ <attribute>
45
+ <name>Intended Software Tool</name>
46
+ <value>Apply Measure Now</value>
47
+ <datatype>string</datatype>
48
+ </attribute>
49
+ <attribute>
50
+ <name>Intended Software Tool</name>
51
+ <value>OpenStudio Application</value>
52
+ <datatype>string</datatype>
53
+ </attribute>
54
+ <attribute>
55
+ <name>Intended Software Tool</name>
56
+ <value>Parametric Analysis Tool</value>
57
+ <datatype>string</datatype>
58
+ </attribute>
59
+ <attribute>
60
+ <name>Intended Use Case</name>
61
+ <value>Model Articulation</value>
62
+ <datatype>string</datatype>
63
+ </attribute>
64
+ <attribute>
65
+ <name>Intended Use Case</name>
66
+ <value>New Construction EE</value>
67
+ <datatype>string</datatype>
68
+ </attribute>
69
+ </attributes>
70
+ <files>
71
+ <file>
72
+ <version>
73
+ <software_program>OpenStudio</software_program>
74
+ <identifier>1.12.2</identifier>
75
+ <min_compatible>1.12.2</min_compatible>
76
+ </version>
77
+ <filename>measure.rb</filename>
78
+ <filetype>rb</filetype>
79
+ <usage_type>script</usage_type>
80
+ <checksum>5D641FEE</checksum>
81
+ </file>
82
+ </files>
83
+ </measure>