openstudio-metadata 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.
@@ -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>