buildingsync 0.2.0
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.
- 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
|