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