Revision history [back]
Credits go to macumber and David. Solution was in using the .toIdfFile and adding all objects simulataneously using the .addObjects.
I created an importer for a YAML-file, which holds data for fixing the remaining missing references. This way the connection between the original .osm-file and imported .idf-file can be fixed.
I don't belong to any group in the BCL-library, so for ppl looking for a way to import an .idf file and fixing remaining links, below the full code, including example .yml file.
# YAML style file containing params to be adjusted
---
- class: BuildingSurface:Detailed
name: Surface Name
field: 4
value: OtherSideConditionsModel
- class: BuildingSurface:Detailed
name: Surface Name
field: 5
value: ICS Collector 1 OSCM
- class: SurfaceProperty:ExteriorNaturalVentedCavity
name: ICSRoofPaverExtVentCav1
field: 11
value: Zolder voor
- class: SolarCollector:IntegralCollectorStorage
name: Collector 1
field: 2
value: Surface Name
.
class ImportIDFFile < OpenStudio::Ruleset::WorkspaceUserScript
# human readable name
def name
return " Import IDF-file"
end
# human readable description
def description
return "This measure can be used to import functionality from EnergyPlus, which is not exposed (yet) to OpenStudio. E.g. HVAC-components can be imported."
end
# human readable description of modeling approach
def modeler_description
return "Imports an .idf-file from the /resources folder. Connections from .idf-file which are not satisfied internally (e.g. references to objects in the .osm-file) will be broken. Use the .yml-file to restore these references, example file provided.
Note that this measure is run after the preprocessor. This means you cannot use HVACTemplate objects, instead expand these first and copy from the .expidf-file.
"
end
# define the arguments that the user will input
def arguments(workspace)
args = OpenStudio::Ruleset::OSArgumentVector.new
idf_file = OpenStudio::Ruleset::OSArgument::makeStringArgument('idf_file', false)
idf_file.setDisplayName("IDF-file")
idf_file.setDescription("The name of the IDF-file residing in the resources directory of this measure")
idf_file.setDefaultValue('import.idf')
args << idf_file
yml_file = OpenStudio::Ruleset::OSArgument::makeStringArgument('yml_file', false)
yml_file.setDisplayName("YML-file")
yml_file.setDescription("The name of the YML-file residing in the resources directory of this measure")
yml_file.setDefaultValue('import.yml')
args << yml_file
return args
end
# define what happens when the measure is run
def run(workspace, runner, user_arguments)
super(workspace, runner, user_arguments)
# Use the built-in error checking
if !runner.validateUserArguments(arguments(workspace), user_arguments)
return false
end
# Assign the user inputs to variables
idf_file = runner.getStringArgumentValue("idf_file", user_arguments)
yml_file = runner.getStringArgumentValue("yml_file", user_arguments)
# Parameters
idf_file = "#{File.dirname(__FILE__)}/resources/#{idf_file}"
yml_file = "#{File.dirname(__FILE__)}/resources/#{yml_file}"
# Process .idf file
if !idf_file.empty?
# Load workspace to be imported
idf = OpenStudio::Workspace::load(idf_file)
if idf.empty?
runner.registerError("Cannot load #{idf_file}")
return false
end
idf = idf.get.toIdfFile()
workspace.addObjects(idf.objects)
end
# Process .yml file
if !yml_file.empty?
require 'yaml'
fixfields = YAML::load_file(yml_file)
fixfields.each do |f|
o = workspace.getObjectByTypeAndName(f['class'].to_IddObjectType,f['name'])
if o.empty?
runner.registerError("No #{f['class']} found with name #{f['name']}")
return false
end
o = o.get
if !o.setString(f['field'],f['value'])
runner.registerError("Unable to set #{f['value']} to field #{f['field']} in #{f['name']}")
return false
end
end
end
return true
end
end
# register the measure to be used by the application
ImportIDFFile.new.registerWithApplication
Credits go I've tried a million different ways of getting this to macumber work, unfortunately the inner working of the Workspace / OptionalWorkspace (undocumented?) / IdfObject remain unclear to me.
For reference: some documentation is available here: https://s3.amazonaws.com/openstudio-sdk-documentation/index.html under utilities and David. Solution was in using the .toIdfFile and adding all objects simulataneously using the .addObjects.model.
For now I've written a work-around in which I created an importer for write the current workspace to a YAML-file, which holds data for fixing temporary file, append the remaining missing references. This way .idf file file I want to load, and then reload the connection between the original .osm-file and imported .idf-file can be fixed.workspace:
I don't belong to any group in the BCL-library, so for ppl looking for a way to import an .idf file and fixing remaining links, below the full code, including example .yml file.
# YAML style file containing params to be adjusted
---
- class: BuildingSurface:Detailed
name: Surface Name
field: 4
value: OtherSideConditionsModel
- class: BuildingSurface:Detailed
name: Surface Name
field: 5
value: ICS Collector 1 OSCM
- class: SurfaceProperty:ExteriorNaturalVentedCavity
name: ICSRoofPaverExtVentCav1
field: 11
value: Zolder voor
- class: SolarCollector:IntegralCollectorStorage
name: Collector 1
field: 2
value: Surface Name
Save the model
f = "#{File.dirname(__FILE__)}/resources/tmp.idf"
workspace.save(OpenStudio::Path.new(f),true)
# Append .idf
fo = File.open(f,'a')
fo.print(File.read("#{File.dirname(__FILE__)}/resources/import.idf"))
# Reload workspace
workspace = OpenStudio::Workspace::load("#{File.dirname(__FILE__)}/resources/tmp.idf").get
.
class ImportIDFFile < OpenStudio::Ruleset::WorkspaceUserScript
# human readable name
def name
return " Import IDF-file"
end
# human readable description
def description
return "This measure can be used to import functionality from EnergyPlus, which is not exposed (yet) to OpenStudio. E.g. HVAC-components can be imported."
end
# human readable description of modeling approach
def modeler_description
return "Imports an .idf-file from the /resources folder. Connections from .idf-file which are not satisfied internally (e.g. references to objects in the .osm-file) will be broken. Use the .yml-file to restore these references, example file provided.
Note that this measure is run after the preprocessor. This means you cannot use HVACTemplate objects, instead expand these first and copy from the .expidf-file.
"
end
# define the arguments that the user will input
def arguments(workspace)
args = OpenStudio::Ruleset::OSArgumentVector.new
idf_file = OpenStudio::Ruleset::OSArgument::makeStringArgument('idf_file', false)
idf_file.setDisplayName("IDF-file")
idf_file.setDescription("The name of the IDF-file residing in the resources directory of this measure")
idf_file.setDefaultValue('import.idf')
args << idf_file
yml_file = OpenStudio::Ruleset::OSArgument::makeStringArgument('yml_file', false)
yml_file.setDisplayName("YML-file")
yml_file.setDescription("The name of the YML-file residing in the resources directory of this measure")
yml_file.setDefaultValue('import.yml')
args << yml_file
return args
end
# define what happens when the measure is run
def run(workspace, runner, user_arguments)
super(workspace, runner, user_arguments)
# Use the built-in error checking
if !runner.validateUserArguments(arguments(workspace), user_arguments)
return false
end
# Assign the user inputs to variables
idf_file = runner.getStringArgumentValue("idf_file", user_arguments)
yml_file = runner.getStringArgumentValue("yml_file", user_arguments)
# Parameters
idf_file = "#{File.dirname(__FILE__)}/resources/#{idf_file}"
yml_file = "#{File.dirname(__FILE__)}/resources/#{yml_file}"
# Process .idf file
if !idf_file.empty?
# Load workspace to be imported
idf = OpenStudio::Workspace::load(idf_file)
if idf.empty?
runner.registerError("Cannot load #{idf_file}")
return false
end
idf = idf.get.toIdfFile()
workspace.addObjects(idf.objects)
end
# Process .yml file
if !yml_file.empty?
require 'yaml'
fixfields = YAML::load_file(yml_file)
fixfields.each do |f|
o = workspace.getObjectByTypeAndName(f['class'].to_IddObjectType,f['name'])
if o.empty?
runner.registerError("No #{f['class']} found with name #{f['name']}")
return false
end
o = o.get
if !o.setString(f['field'],f['value'])
runner.registerError("Unable to set #{f['value']} to field #{f['field']} in #{f['name']}")
return false
end
end
end
return true
end
end
# register the measure to be used by the application
ImportIDFFile.new.registerWithApplication