openstudio-metadata 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +49 -0
- data/.rakeTasks +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +9 -0
- data/.travis.yml +20 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +23 -0
- data/README.md +66 -0
- data/Rakefile +22 -0
- data/doc_templates/LICENSE.md +27 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +36 -0
- data/doc_templates/copyright_js.txt +4 -0
- data/doc_templates/copyright_ruby.txt +34 -0
- data/lib/.DS_Store +0 -0
- data/lib/files/brick/1.1/Brick.ttl +11144 -0
- data/lib/files/haystack/3.9.9/defs.ttl +5205 -0
- data/lib/files/mappings.json +388 -0
- data/lib/files/templates.yaml +361 -0
- data/lib/measures/haystack/measure.rb +574 -0
- data/lib/measures/haystack/measure.xml +83 -0
- data/lib/openstudio/metadata/controls.rb +220 -0
- data/lib/openstudio/metadata/creator.rb +432 -0
- data/lib/openstudio/metadata/helpers.rb +184 -0
- data/lib/openstudio/metadata/serializer.rb +141 -0
- data/lib/openstudio/metadata/version.rb +40 -0
- data/lib/openstudio/metadata/writer.rb +107 -0
- data/lib/openstudio/metadata.rb +55 -0
- data/lib/openstudio-metadata.rb +1 -0
- data/openstudio-metadata.gemspec +32 -0
- data/test.rb +15 -0
- metadata +165 -0
@@ -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>
|