buildingsync 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/continuous_integration.yml +146 -0
- data/.gitignore +33 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +50 -0
- data/Gemfile +31 -0
- data/Jenkinsfile +10 -0
- data/LICENSE.md +29 -0
- data/README.md +105 -0
- data/Rakefile +77 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/buildingsync.gemspec +37 -0
- data/config.rb.in +26 -0
- data/doc_templates/LICENSE.md +29 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +38 -0
- data/doc_templates/copyright_js.txt +5 -0
- data/doc_templates/copyright_ruby.txt +36 -0
- data/lib/buildingsync.rb +43 -0
- data/lib/buildingsync/all_resource_total.rb +54 -0
- data/lib/buildingsync/audit_date.rb +54 -0
- data/lib/buildingsync/constants.rb +49 -0
- data/lib/buildingsync/contact.rb +54 -0
- data/lib/buildingsync/extension.rb +57 -0
- data/lib/buildingsync/generator.rb +584 -0
- data/lib/buildingsync/get_bcl_weather_file.rb +326 -0
- data/lib/buildingsync/helpers/Model.hvac.rb +216 -0
- data/lib/buildingsync/helpers/helper.rb +494 -0
- data/lib/buildingsync/helpers/xml_get_set.rb +215 -0
- data/lib/buildingsync/makers/phase_zero_base.osw +178 -0
- data/lib/buildingsync/makers/workflow_maker.json +811 -0
- data/lib/buildingsync/makers/workflow_maker.rb +581 -0
- data/lib/buildingsync/makers/workflow_maker_base.rb +167 -0
- data/lib/buildingsync/model_articulation/building.rb +1119 -0
- data/lib/buildingsync/model_articulation/building_and_system_types.json +121 -0
- data/lib/buildingsync/model_articulation/building_section.rb +190 -0
- data/lib/buildingsync/model_articulation/building_system.rb +49 -0
- data/lib/buildingsync/model_articulation/envelope_system.rb +102 -0
- data/lib/buildingsync/model_articulation/exterior_floor_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/facility.rb +439 -0
- data/lib/buildingsync/model_articulation/foundation_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/hvac_system.rb +395 -0
- data/lib/buildingsync/model_articulation/lighting_system.rb +102 -0
- data/lib/buildingsync/model_articulation/loads_system.rb +287 -0
- data/lib/buildingsync/model_articulation/location_element.rb +129 -0
- data/lib/buildingsync/model_articulation/measure.rb +57 -0
- data/lib/buildingsync/model_articulation/roof_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/service_hot_water_system.rb +87 -0
- data/lib/buildingsync/model_articulation/site.rb +242 -0
- data/lib/buildingsync/model_articulation/spatial_element.rb +343 -0
- data/lib/buildingsync/model_articulation/wall_system_type.rb +64 -0
- data/lib/buildingsync/report.rb +217 -0
- data/lib/buildingsync/resource_use.rb +55 -0
- data/lib/buildingsync/scenario.rb +622 -0
- data/lib/buildingsync/selection_tool.rb +98 -0
- data/lib/buildingsync/time_series.rb +85 -0
- data/lib/buildingsync/translator.rb +167 -0
- data/lib/buildingsync/utility.rb +67 -0
- data/lib/buildingsync/version.rb +45 -0
- metadata +223 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
|
40
|
+
module BuildingSync
|
41
|
+
# Contact class
|
42
|
+
class Contact
|
43
|
+
include BuildingSync::Helper
|
44
|
+
include BuildingSync::XmlGetSet
|
45
|
+
# @param base_xml [REXML::Element]
|
46
|
+
# @param ns [String]
|
47
|
+
def initialize(base_xml, ns)
|
48
|
+
@base_xml = base_xml
|
49
|
+
@ns = ns
|
50
|
+
|
51
|
+
help_element_class_type_check(base_xml, 'Contact')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
|
40
|
+
require 'openstudio/model_articulation/version'
|
41
|
+
require 'openstudio/extension'
|
42
|
+
|
43
|
+
module BuildingSync
|
44
|
+
# Extension class
|
45
|
+
class Extension < OpenStudio::Extension::Extension
|
46
|
+
# Override the base class
|
47
|
+
# The Extension class contains both the instance of the BuildingSync file (in XML) and the
|
48
|
+
# helper methods from the OpenStudio::Extension gem to support managing measures that are related
|
49
|
+
# to BuildingSync.
|
50
|
+
def initialize
|
51
|
+
# Initialize the root directory for use in the extension class. This must be done, otherwise the
|
52
|
+
# root_dir will be the root_dir in the OpenStudio Extension Gem.
|
53
|
+
super
|
54
|
+
@root_dir = File.absolute_path(File.join(File.dirname(__FILE__), '..', '..'))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,584 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
require 'builder/xmlmarkup'
|
40
|
+
require 'rexml/document'
|
41
|
+
|
42
|
+
require 'buildingsync/helpers/helper'
|
43
|
+
|
44
|
+
module BuildingSync
|
45
|
+
# Generator class that generates basic data that is used mostly for testing
|
46
|
+
class Generator
|
47
|
+
include BuildingSync::Helper
|
48
|
+
# @param version [String] version of BuildingSync
|
49
|
+
def initialize(ns = 'auc', version = '2.2.0')
|
50
|
+
supported_versions = ['2.0', '2.2.0']
|
51
|
+
if !supported_versions.include? version
|
52
|
+
@version = nil
|
53
|
+
OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Generator.initialize', "The version: #{version} is not one of the supported versions: #{supported_versions}")
|
54
|
+
else
|
55
|
+
@version = version
|
56
|
+
end
|
57
|
+
@ns = ns
|
58
|
+
end
|
59
|
+
|
60
|
+
# Starts from scratch and creates all necessary elements up to and including an
|
61
|
+
# - Sites/Site/Buildings/Building/Sections/Section
|
62
|
+
# - Reports/Report/Scenarios/Scenario
|
63
|
+
# @return [String] string formatted XML document
|
64
|
+
def create_bsync_root_to_building
|
65
|
+
xml = Builder::XmlMarkup.new(indent: 2)
|
66
|
+
auc_ns = 'http://buildingsync.net/schemas/bedes-auc/2019'
|
67
|
+
location = "https://raw.githubusercontent.com/BuildingSync/schema/v#{@version}/BuildingSync.xsd"
|
68
|
+
xml.instruct! :xml
|
69
|
+
xml.tag!("#{@ns}:BuildingSync",
|
70
|
+
:"xmlns:#{@ns}" => auc_ns,
|
71
|
+
:"xsi:schemaLocation" => "#{auc_ns} #{location}",
|
72
|
+
:"xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
|
73
|
+
:version => @version.to_s) do |buildsync|
|
74
|
+
|
75
|
+
buildsync.tag!("#{@ns}:Facilities") do |faclts|
|
76
|
+
faclts.tag!("#{@ns}:Facility", ID: 'Facility1') do |faclt|
|
77
|
+
faclt.tag!("#{@ns}:Sites") do |sites|
|
78
|
+
sites.tag!("#{@ns}:Site", ID: 'Site1') do |site|
|
79
|
+
site.tag!("#{@ns}:Buildings") do |builds|
|
80
|
+
builds.tag!("#{@ns}:Building", ID: 'Building1') do |build|
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_or_create_linked_premises(element_xml)
|
91
|
+
linked_premises_xml = help_get_or_create(element_xml, "#{@ns}:LinkedPremises")
|
92
|
+
return linked_premises_xml
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_linked_premise_of_type(premise_type_xml, premise_type, id)
|
96
|
+
linked_xml = REXML::Element.new("#{@ns}:Linked#{premise_type}ID", premise_type_xml)
|
97
|
+
linked_xml.add_attribute('IDref', id)
|
98
|
+
return linked_xml
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_or_create_premise_of_type(premise_xml, premise_type)
|
102
|
+
premise_type_xml = help_get_or_create(premise_xml, "#{@ns}:#{premise_type}")
|
103
|
+
return premise_type_xml
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_linked_premise(base_xml, id, premise_type)
|
107
|
+
linked_premises_xml = get_or_create_linked_premises(base_xml)
|
108
|
+
premise_type_xml = get_or_create_premise_of_type(linked_premises_xml, premise_type)
|
109
|
+
add_linked_premise_of_type(premise_type_xml, premise_type, id)
|
110
|
+
return linked_premises_xml
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_linked_building(base_xml, id)
|
114
|
+
add_linked_premise(base_xml, id, 'Building')
|
115
|
+
end
|
116
|
+
|
117
|
+
def add_linked_section(base_xml, id)
|
118
|
+
add_linked_premise(base_xml, id, 'Section')
|
119
|
+
end
|
120
|
+
|
121
|
+
# @see add_hvac_system_to_facility
|
122
|
+
def add_hvac_system_to_first_facility(doc, id = 'HVACSystem-1', principal_hvac_system_type = nil)
|
123
|
+
facility_xml = get_first_facility_element(doc)
|
124
|
+
return add_hvac_system_to_facility(facility_xml, id, principal_hvac_system_type)
|
125
|
+
end
|
126
|
+
|
127
|
+
# @see add_lighting_system_to_facility
|
128
|
+
def add_lighting_system_to_first_facility(doc, id = 'LightingSystem-1')
|
129
|
+
facility_xml = get_first_facility_element(doc)
|
130
|
+
return add_lighting_system_to_facility(facility_xml, id)
|
131
|
+
end
|
132
|
+
|
133
|
+
# @see add_plug_load_to_facility
|
134
|
+
def add_plug_load_to_first_facility(doc, id = 'PlugLoad-1')
|
135
|
+
facility_xml = get_first_facility_element(doc)
|
136
|
+
return add_plug_load_to_facility(facility_xml, id)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Adds hvac system with id. also adds principal hvac element if specified
|
140
|
+
# @see get_or_create_system_of_type
|
141
|
+
# @param facility_xml [REXML::Element]
|
142
|
+
# @param id [String]
|
143
|
+
def add_hvac_system_to_facility(facility_xml, id = 'HVACSystem-1', principal_hvac_system_type = nil)
|
144
|
+
systems_xml = get_or_create_systems(facility_xml)
|
145
|
+
hvac_system_xml = get_or_create_system_of_type(systems_xml, 'HVACSystem')
|
146
|
+
|
147
|
+
hvac_system_xml.add_attribute('ID', id)
|
148
|
+
if !principal_hvac_system_type.nil?
|
149
|
+
principal_xml = REXML::Element.new("#{@ns}:PrincipalHVACSystemType", hvac_system_xml)
|
150
|
+
principal_xml.text = principal_hvac_system_type
|
151
|
+
end
|
152
|
+
return hvac_system_xml
|
153
|
+
end
|
154
|
+
|
155
|
+
# Adds lighting system with id. wrapper around:
|
156
|
+
# @see get_or_create_system_of_type
|
157
|
+
# @param facility_xml [REXML::Element]
|
158
|
+
# @param id [String]
|
159
|
+
def add_lighting_system_to_facility(facility_xml, id = 'LightingSystem-1')
|
160
|
+
systems_xml = get_or_create_systems(facility_xml)
|
161
|
+
lighting_system_xml = get_or_create_system_of_type(systems_xml, 'LightingSystem')
|
162
|
+
lighting_system_xml.add_attribute('ID', id)
|
163
|
+
return lighting_system_xml
|
164
|
+
end
|
165
|
+
|
166
|
+
# Adds plug load with id. wrapper around:
|
167
|
+
# @see get_or_create_system_of_type
|
168
|
+
# @param facility_xml [REXML::Element]
|
169
|
+
# @param id [String]
|
170
|
+
def add_plug_load_to_facility(facility_xml, id = 'PlugLoad-1')
|
171
|
+
systems_xml = get_or_create_systems(facility_xml)
|
172
|
+
new_system_xml = get_or_create_system_of_type(systems_xml, 'PlugLoad')
|
173
|
+
new_system_xml.add_attribute('ID', id)
|
174
|
+
return new_system_xml
|
175
|
+
end
|
176
|
+
|
177
|
+
# Create new system without id. Will check for pluralized version and create if not there,
|
178
|
+
# else gets existing pluralized version and adds new singular as child.
|
179
|
+
# @example:
|
180
|
+
# systems_xml = <auc:Systems/>
|
181
|
+
# system_type = HVACSystem
|
182
|
+
# returns <auc:Systems><auc:HVACSystems><auc:HVACSystem/></..></..>
|
183
|
+
# @example:
|
184
|
+
# systems_xml = <auc:Systems><auc:HVACSystems/></..>
|
185
|
+
# system_type = HVACSystem
|
186
|
+
# returns <auc:System><auc:HVACSystems><auc:HVACSystem/></..></..>
|
187
|
+
# @param systems_xml [REXML::Element] pass the auc:Systems element
|
188
|
+
# @param system_type [String] a valid BSync system type: HVACSystem, LightingSystem, etc.
|
189
|
+
def get_or_create_system_of_type(systems_xml, system_type)
|
190
|
+
new_systems_xml = help_get_or_create(systems_xml, "#{@ns}:#{system_type}s")
|
191
|
+
new_system_xml = REXML::Element.new("#{@ns}:#{system_type}", new_systems_xml)
|
192
|
+
return new_system_xml
|
193
|
+
end
|
194
|
+
|
195
|
+
# Get or create <auc:Systems/> from <auc:Facility>...</..>
|
196
|
+
def get_or_create_systems(facility_xml)
|
197
|
+
return help_get_or_create(facility_xml, "#{@ns}:Systems")
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_section_to_first_building(doc, id = 'Section-1')
|
201
|
+
building_xml = get_first_building_element(doc)
|
202
|
+
sections_xml = help_get_or_create(building_xml, "#{@ns}:Sections")
|
203
|
+
section = REXML::Element.new("#{@ns}:Section", sections_xml)
|
204
|
+
section.add_attribute('ID', id)
|
205
|
+
return section
|
206
|
+
end
|
207
|
+
|
208
|
+
def add_energy_resource_use_to_scenario(scenario_xml, energy_resource_type = 'Electricity', end_use = 'All end uses', id = 'ResourceUse-1', native_units = nil)
|
209
|
+
resource_uses = help_get_or_create(scenario_xml, "#{@ns}:ResourceUses")
|
210
|
+
|
211
|
+
# Define ResourceUse and add ID
|
212
|
+
resource_use = REXML::Element.new("#{@ns}:ResourceUse", resource_uses)
|
213
|
+
resource_use.add_attribute('ID', id)
|
214
|
+
|
215
|
+
# Add ResourceUnits
|
216
|
+
if !native_units.nil?
|
217
|
+
nu = REXML::Element.new("#{@ns}:ResourceUnits", resource_use)
|
218
|
+
nu.text = native_units
|
219
|
+
end
|
220
|
+
|
221
|
+
# Add EnergyResource
|
222
|
+
energy_resource = REXML::Element.new("#{@ns}:EnergyResource", resource_use)
|
223
|
+
energy_resource.text = energy_resource_type
|
224
|
+
|
225
|
+
# Add EndUse
|
226
|
+
eu = REXML::Element.new("#{@ns}:EndUse", resource_use)
|
227
|
+
eu.text = end_use
|
228
|
+
return resource_use
|
229
|
+
end
|
230
|
+
|
231
|
+
def add_all_resource_total_to_scenario(scenario_xml, end_use = 'All end uses', id = 'AllResourceTotal-1')
|
232
|
+
all_resource_totals = help_get_or_create(scenario_xml, "#{@ns}:AllResourceTotals")
|
233
|
+
|
234
|
+
all_resource_total = REXML::Element.new("#{@ns}:AllResourceTotal", all_resource_totals)
|
235
|
+
all_resource_total.add_attribute('ID', id)
|
236
|
+
eu = REXML::Element.new("#{@ns}:EndUse", all_resource_total)
|
237
|
+
eu.text = end_use
|
238
|
+
|
239
|
+
return all_resource_total
|
240
|
+
end
|
241
|
+
|
242
|
+
def add_time_series_to_scenario(scenario_xml, id = 'TimeSeries-1')
|
243
|
+
time_series_data = help_get_or_create(scenario_xml, "#{@ns}:TimeSeriesData")
|
244
|
+
time_series = REXML::Element.new("#{@ns}:TimeSeries", time_series_data)
|
245
|
+
time_series.add_attribute('ID', id)
|
246
|
+
return time_series
|
247
|
+
end
|
248
|
+
|
249
|
+
# @param doc [REXML::Document]
|
250
|
+
# @param scenario_type [String] see add_scenario_type_to_scenario
|
251
|
+
# @param id [String] id for the new scenario
|
252
|
+
# @return [REXML::Element] newly added scenario
|
253
|
+
def add_scenario_to_first_report(doc, scenario_type = nil, id = 'Scenario-1')
|
254
|
+
report = doc.get_elements(".//#{@ns}:Reports/#{@ns}:Report").first
|
255
|
+
return add_scenario_to_report(report, scenario_type, id)
|
256
|
+
end
|
257
|
+
|
258
|
+
# Add a Scenario element to the Report XML element provided.
|
259
|
+
# If auc:Scenarios does not exist, this is added as well
|
260
|
+
# @param report_xml [REXML::Element] an XML element of auc:Report
|
261
|
+
# @param scenario_type [String] see add_scenario_type_to_scenario
|
262
|
+
# @param id [String] id of the Scenario element to add
|
263
|
+
# @return [REXML::Element] the newly created Scenario element
|
264
|
+
def add_scenario_to_report(report_xml, scenario_type = nil, id = 'Scenario-1')
|
265
|
+
scenarios = report_xml.get_elements("./#{@ns}:Scenarios").first
|
266
|
+
if scenarios.nil?
|
267
|
+
scenarios = REXML::Element.new("#{@ns}:Scenarios", report_xml)
|
268
|
+
end
|
269
|
+
scenario = REXML::Element.new("#{@ns}:Scenario", scenarios)
|
270
|
+
scenario.add_attribute('ID', id)
|
271
|
+
return add_scenario_type_to_scenario(scenario, scenario_type)
|
272
|
+
end
|
273
|
+
|
274
|
+
# Add a Report element to the first Facility in the doc.
|
275
|
+
# If auc:Reports does not exist, this is added as well
|
276
|
+
# @param doc [REXML::Document] a buildingsync document with atleast an auc:Facility
|
277
|
+
# @param id [String] id of the Report element to add
|
278
|
+
# @return [REXML::Element] the newly created Report element
|
279
|
+
def add_report_to_first_facility(doc, id = 'Report-1')
|
280
|
+
facility_xml = doc.get_elements(".//#{@ns}:Facilities/#{@ns}:Facility").first
|
281
|
+
reports = help_get_or_create(facility_xml, "#{@ns}:Reports")
|
282
|
+
report = REXML::Element.new("#{@ns}:Report", reports)
|
283
|
+
report.add_attribute('ID', id)
|
284
|
+
return report
|
285
|
+
end
|
286
|
+
|
287
|
+
# Add a specific scenario type to the provided scenario element
|
288
|
+
# @param scenario_element [REXML::Element]
|
289
|
+
# @param scenario_type [String] one of: ['CBMeasured', 'CBModeled', 'POM', 'Benchmark', 'Target']
|
290
|
+
# @return [REXML::Element] Scenario element
|
291
|
+
def add_scenario_type_to_scenario(scenario_element, scenario_type)
|
292
|
+
scenario_type_element = REXML::Element.new("#{@ns}:ScenarioType", scenario_element)
|
293
|
+
if scenario_type.nil?
|
294
|
+
return scenario_element
|
295
|
+
elsif scenario_type == 'CBMeasured'
|
296
|
+
cb_element = REXML::Element.new("#{@ns}:CurrentBuilding", scenario_type_element)
|
297
|
+
cm_element = REXML::Element.new("#{@ns}:CalculationMethod", cb_element)
|
298
|
+
measured = REXML::Element.new("#{@ns}:Measured", cm_element)
|
299
|
+
elsif scenario_type == 'CBModeled'
|
300
|
+
cb_element = REXML::Element.new("#{@ns}:CurrentBuilding", scenario_type_element)
|
301
|
+
cm_element = REXML::Element.new("#{@ns}:CalculationMethod", cb_element)
|
302
|
+
modeled = REXML::Element.new("#{@ns}:Modeled", cm_element)
|
303
|
+
elsif scenario_type == 'POM'
|
304
|
+
pom = REXML::Element.new("#{@ns}:PackageOfMeasures", scenario_type_element)
|
305
|
+
elsif scenario_type == 'Benchmark'
|
306
|
+
benchmark = REXML::Element.new("#{@ns}:Benchmark", scenario_type_element)
|
307
|
+
elsif scenario_type == 'Target'
|
308
|
+
target = REXML::Element.new("#{@ns}:Target", scenario_type_element)
|
309
|
+
end
|
310
|
+
return scenario_element
|
311
|
+
end
|
312
|
+
|
313
|
+
# creates a minimum building sync snippet
|
314
|
+
# @param occupancy_classification [String]
|
315
|
+
# @param year_of_const [Integer]
|
316
|
+
# @param floor_area_type [String]
|
317
|
+
# @param floor_area_value [Float]
|
318
|
+
# @param ns [String]
|
319
|
+
# @return REXML::Document
|
320
|
+
def create_minimum_snippet(occupancy_classification, year_of_const = 2000, floor_area_type = 'Gross', floor_area_value = 1000, floors_above_grade = 1)
|
321
|
+
doc_string = create_bsync_root_to_building
|
322
|
+
doc = REXML::Document.new(doc_string)
|
323
|
+
|
324
|
+
facility_element = doc.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility"]
|
325
|
+
site_element = facility_element.elements["#{@ns}:Sites/#{@ns}:Site"]
|
326
|
+
building_element = site_element.elements["#{@ns}:Buildings/#{@ns}:Building"]
|
327
|
+
|
328
|
+
# Add Facility info
|
329
|
+
report_element = add_report_to_first_facility(doc)
|
330
|
+
junk = add_scenario_to_report(report_element, 'CBModeled')
|
331
|
+
|
332
|
+
# Add Site info
|
333
|
+
occupancy_classification_element = REXML::Element.new("#{@ns}:OccupancyClassification", site_element)
|
334
|
+
occupancy_classification_element.text = occupancy_classification
|
335
|
+
|
336
|
+
# Add Building info
|
337
|
+
year_of_construction_element = REXML::Element.new("#{@ns}:YearOfConstruction", building_element)
|
338
|
+
year_of_construction_element.text = year_of_const
|
339
|
+
floor_areas_element = REXML::Element.new("#{@ns}:FloorAreas", building_element)
|
340
|
+
floor_area_element = REXML::Element.new("#{@ns}:FloorArea", floor_areas_element)
|
341
|
+
floor_area_type_element = REXML::Element.new("#{@ns}:FloorAreaType", floor_area_element)
|
342
|
+
floor_area_type_element.text = floor_area_type
|
343
|
+
floor_area_value_element = REXML::Element.new("#{@ns}:FloorAreaValue", floor_area_element)
|
344
|
+
floor_area_value_element.text = floor_area_value
|
345
|
+
floors_above_grade_element = REXML::Element.new("#{@ns}:FloorsAboveGrade", building_element)
|
346
|
+
floors_above_grade_element.text = floors_above_grade
|
347
|
+
occupancy_classification_element = REXML::Element.new("#{@ns}:OccupancyClassification", building_element)
|
348
|
+
occupancy_classification_element.text = occupancy_classification
|
349
|
+
|
350
|
+
return doc
|
351
|
+
end
|
352
|
+
|
353
|
+
# creates a minimum facility
|
354
|
+
# @param occupancy_classification [String]
|
355
|
+
# @param year_of_const [Integer]
|
356
|
+
# @param floor_area_type [String]
|
357
|
+
# @param floor_area_value [Float]
|
358
|
+
# @return BuildingSync::Facility
|
359
|
+
def create_minimum_facility(occupancy_classification, year_of_const, floor_area_type, floor_area_value, floors_above_grade = 1)
|
360
|
+
xml_snippet = create_minimum_snippet(occupancy_classification, year_of_const, floor_area_type, floor_area_value, floors_above_grade)
|
361
|
+
facility_element = xml_snippet.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility"]
|
362
|
+
if !facility_element.nil?
|
363
|
+
return BuildingSync::Facility.new(facility_element, @ns)
|
364
|
+
else
|
365
|
+
expect(facility_element.nil?).to be false
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# create minimum site
|
370
|
+
# @param occupancy_classification [String]
|
371
|
+
# @param year_of_const [Integer]
|
372
|
+
# @param floor_area_type [String]
|
373
|
+
# @param floor_area_value [Float]
|
374
|
+
# @return [BuildingSync::Site]
|
375
|
+
def create_minimum_site(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
|
376
|
+
xml_snippet = create_minimum_snippet(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
|
377
|
+
site_element = xml_snippet.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site"]
|
378
|
+
if !site_element.nil?
|
379
|
+
return BuildingSync::Site.new(site_element, @ns)
|
380
|
+
else
|
381
|
+
expect(site_element.nil?).to be false
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def create_minimum_building(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
|
386
|
+
xml_snippet = create_minimum_snippet(occupancy_classification, year_of_const, floor_area_type, floor_area_value)
|
387
|
+
|
388
|
+
building_element = xml_snippet.elements["/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site/#{@ns}:Buildings/#{@ns}:Building"]
|
389
|
+
if !building_element.nil?
|
390
|
+
return BuildingSync::Building.new(building_element, '', '', @ns)
|
391
|
+
else
|
392
|
+
expect(building_element.nil?).to be false
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
def create_minimum_section_xml(typical_usage_hours = 40)
|
397
|
+
section = REXML::Element.new("#{@ns}:Section")
|
398
|
+
# adding the XML elements for the typical hourly usage per week
|
399
|
+
typical_usages = REXML::Element.new("#{@ns}:TypicalOccupantUsages")
|
400
|
+
section.add_element(typical_usages)
|
401
|
+
typical_usage = REXML::Element.new("#{@ns}:TypicalOccupantUsage")
|
402
|
+
typical_usages.add_element(typical_usage)
|
403
|
+
typical_usage_unit = REXML::Element.new("#{@ns}:TypicalOccupantUsageUnits")
|
404
|
+
typical_usage_unit.text = 'Hours per week'
|
405
|
+
typical_usage.add_element(typical_usage_unit)
|
406
|
+
typical_usage_value = REXML::Element.new("#{@ns}:TypicalOccupantUsageValue")
|
407
|
+
typical_usage_value.text = typical_usage_hours
|
408
|
+
typical_usage.add_element(typical_usage_value)
|
409
|
+
return section
|
410
|
+
end
|
411
|
+
|
412
|
+
# -- Generate Baseline functions
|
413
|
+
def generate_baseline_facilities(xml_path)
|
414
|
+
facilities = []
|
415
|
+
doc = help_load_doc(xml_path)
|
416
|
+
|
417
|
+
doc.elements.each("#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility") do |facility_element|
|
418
|
+
facilities.push(BuildingSync::Facility.new(facility_element, @ns))
|
419
|
+
end
|
420
|
+
return facilities
|
421
|
+
end
|
422
|
+
|
423
|
+
def generate_baseline_sites(xml_path)
|
424
|
+
sites = []
|
425
|
+
doc = help_load_doc(xml_path)
|
426
|
+
facility_xml = get_first_facility_element(doc)
|
427
|
+
|
428
|
+
facility_xml.elements.each("#{@ns}:Sites/#{@ns}:Site") do |site_element|
|
429
|
+
sites.push(BuildingSync::Site.new(site_element, @ns))
|
430
|
+
end
|
431
|
+
return sites
|
432
|
+
end
|
433
|
+
|
434
|
+
def generate_baseline_buildings(xml_path, occupancy_classification, total_floor_area)
|
435
|
+
buildings = []
|
436
|
+
|
437
|
+
doc = help_load_doc(xml_path)
|
438
|
+
site_xml = get_first_site_element(doc)
|
439
|
+
|
440
|
+
site_xml.elements.each("#{@ns}:Buildings/#{@ns}:Building") do |building_element|
|
441
|
+
buildings.push(BuildingSync::Building.new(building_element, occupancy_classification, total_floor_area, @ns))
|
442
|
+
end
|
443
|
+
return buildings
|
444
|
+
end
|
445
|
+
|
446
|
+
def generate_baseline_building_sections(xml_path, occupancy_classification, total_floor_area)
|
447
|
+
building_sections = []
|
448
|
+
|
449
|
+
doc = help_load_doc(xml_path)
|
450
|
+
building_xml = get_first_building_element(doc)
|
451
|
+
|
452
|
+
building_xml.elements.each("#{@ns}:Sections/#{@ns}:Section") do |building_element|
|
453
|
+
building_sections.push(BuildingSync::BuildingSection.new(building_element, occupancy_classification, total_floor_area, 1, @ns))
|
454
|
+
end
|
455
|
+
return building_sections
|
456
|
+
end
|
457
|
+
|
458
|
+
def get_first_facility_element(doc)
|
459
|
+
facility = doc.get_elements("#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility").first
|
460
|
+
return facility
|
461
|
+
end
|
462
|
+
|
463
|
+
def get_first_site_element(doc)
|
464
|
+
site = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site").first
|
465
|
+
return site
|
466
|
+
end
|
467
|
+
|
468
|
+
def get_first_building_element(doc)
|
469
|
+
building = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site/#{@ns}:Buildings/#{@ns}:Building").first
|
470
|
+
return building
|
471
|
+
end
|
472
|
+
|
473
|
+
def get_first_building_section_element(doc)
|
474
|
+
section = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Sites/#{@ns}:Site/#{@ns}:Buildings/#{@ns}:Building/#{@ns}:Sections/#{@ns}:Section").first
|
475
|
+
return section
|
476
|
+
end
|
477
|
+
|
478
|
+
def get_first_report_element(doc)
|
479
|
+
report = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Reports/#{@ns}:Report").first
|
480
|
+
return report
|
481
|
+
end
|
482
|
+
|
483
|
+
def get_first_scenario_element(doc)
|
484
|
+
scenario = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Reports/#{@ns}:Report/#{@ns}:Scenarios/#{@ns}:Scenario").first
|
485
|
+
return scenario
|
486
|
+
end
|
487
|
+
|
488
|
+
def get_first_utility_element(doc)
|
489
|
+
scenario = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Reports/#{@ns}:Report/#{@ns}:Utilities/#{@ns}:Utility").first
|
490
|
+
return scenario
|
491
|
+
end
|
492
|
+
|
493
|
+
def get_first_hvac_system_element(doc)
|
494
|
+
scenario = doc.get_elements("/#{@ns}:BuildingSync/#{@ns}:Facilities/#{@ns}:Facility/#{@ns}:Systems/#{@ns}:HVACSystems/#{@ns}:HVACSystem").first
|
495
|
+
return scenario
|
496
|
+
end
|
497
|
+
|
498
|
+
def get_utility_from_file(xml_file_path)
|
499
|
+
doc = nil
|
500
|
+
File.open(xml_file_path, 'r') do |file|
|
501
|
+
doc = REXML::Document.new(file)
|
502
|
+
end
|
503
|
+
report = get_first_utility_element(doc)
|
504
|
+
return BuildingSync::Utility.new(report, @ns)
|
505
|
+
end
|
506
|
+
|
507
|
+
def get_report_from_file(xml_file_path)
|
508
|
+
doc = nil
|
509
|
+
File.open(xml_file_path, 'r') do |file|
|
510
|
+
doc = REXML::Document.new(file)
|
511
|
+
end
|
512
|
+
report = get_first_report_element(doc)
|
513
|
+
return BuildingSync::Report.new(report, @ns)
|
514
|
+
end
|
515
|
+
|
516
|
+
def get_facility_from_file(xml_file_path)
|
517
|
+
doc = nil
|
518
|
+
File.open(xml_file_path, 'r') do |file|
|
519
|
+
doc = REXML::Document.new(file)
|
520
|
+
end
|
521
|
+
facility = get_first_facility_element(doc)
|
522
|
+
return BuildingSync::Facility.new(facility, @ns)
|
523
|
+
end
|
524
|
+
|
525
|
+
def get_building_from_file(xml_file_path)
|
526
|
+
doc = nil
|
527
|
+
File.open(xml_file_path, 'r') do |file|
|
528
|
+
doc = REXML::Document.new(file)
|
529
|
+
end
|
530
|
+
building = get_first_building_element(doc)
|
531
|
+
return BuildingSync::Building.new(building, 'Office', '20000', @ns)
|
532
|
+
end
|
533
|
+
|
534
|
+
def get_building_section_from_file(xml_file_path)
|
535
|
+
doc = nil
|
536
|
+
File.open(xml_file_path, 'r') do |file|
|
537
|
+
doc = REXML::Document.new(file)
|
538
|
+
end
|
539
|
+
section = get_first_building_section_element(doc)
|
540
|
+
return BuildingSync::BuildingSection.new(section, 'Office', '20000', 1, @ns)
|
541
|
+
end
|
542
|
+
|
543
|
+
# get hvac system from xml file
|
544
|
+
# @param xml_file_name [String]
|
545
|
+
# @param standard_to_be_used [String]
|
546
|
+
# @return [BuildingSync::HVACSystem]
|
547
|
+
def get_hvac_system_from_file(xml_file_path)
|
548
|
+
doc = nil
|
549
|
+
File.open(xml_file_path, 'r') do |file|
|
550
|
+
doc = REXML::Document.new(file)
|
551
|
+
end
|
552
|
+
hvac_system = get_first_hvac_system_element(doc)
|
553
|
+
return BuildingSync::HVACSystem.new(hvac_system, @ns)
|
554
|
+
end
|
555
|
+
|
556
|
+
# create and return the set of elements:
|
557
|
+
# auc:CalculationMethod/auc:Modeled/
|
558
|
+
# auc:SoftwareProgramUsed = OpenStudio
|
559
|
+
# auc:SoftwareProgramVersion = ...
|
560
|
+
# auc:WeatherDataType = TMY
|
561
|
+
# auc:SimulationCompletionStatus = Success or Failed, depending on result[:completion_status]
|
562
|
+
# @param result [hash] must have key: result[:completed_status]
|
563
|
+
# @return [REXML::Element]
|
564
|
+
def create_calculation_method_element(result)
|
565
|
+
calc_method = REXML::Element.new("#{@ns}:CalculationMethod")
|
566
|
+
modeled = REXML::Element.new("#{@ns}:Modeled", calc_method)
|
567
|
+
software_program_used = REXML::Element.new("#{@ns}:SoftwareProgramUsed", modeled)
|
568
|
+
software_program_used.text = 'OpenStudio'
|
569
|
+
|
570
|
+
software_program_version = REXML::Element.new("#{@ns}:SoftwareProgramVersion", modeled)
|
571
|
+
software_program_version.text = OpenStudio.openStudioLongVersion.to_s
|
572
|
+
|
573
|
+
weather_data_type = REXML::Element.new("#{@ns}:WeatherDataType", modeled)
|
574
|
+
weather_data_type.text = 'TMY3'
|
575
|
+
|
576
|
+
sim_completion_status = REXML::Element.new("#{@ns}:SimulationCompletionStatus", modeled)
|
577
|
+
sim_completion_status.text = result[:completed_status] == 'Success' ? 'Finished' : 'Failed'
|
578
|
+
|
579
|
+
return calc_method
|
580
|
+
end
|
581
|
+
|
582
|
+
attr_reader :version
|
583
|
+
end
|
584
|
+
end
|