You probably want to look in the "resources" directory at the OSLib_HVAC.rb file. This contains common methods used by a lot of the AEDG HVAC measures.
For example there is a method to make the primary air loop
def OsLib_HVAC.createPrimaryZoneEquipment(model, runner, options)
"model" is passed in because we need access to the model to get and add things to it. "runner" gives us the ability to add log messages from the helper. "options" is a hash containing many objects. If you search for "options" in the method above you will for example see an if statement with many elsif options for options["ZoneHVAC"] that has values such as ASHP, Baseboard, Radiant or DualDuct. You could extend this to have more methods, or add another key to the options hash to store additional inputs such as motor efficiency values, which or currently hard coded. Below is one of the "elsif" options for this ZoneHVAC.
elsif options["zoneHVAC"] == "Baseboard"
# create baseboard heater add add to thermal zone and hot water loop
baseboard_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
baseboard_heater = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule(), baseboard_coil)
baseboard_heater.addToThermalZone(zone)
options["hot_water_plant"].addDemandBranchForComponent(baseboard_coil)
elsif options["zoneHVAC"] == "Radiant"
#. . .
Back to your original question there is a hash value for options["PrimaryHVAC']. But instead of just returning a string, as you have found it returns its own hash. Really, we could have just made the main hash a lot bigger, but in this case when we ask about it in the measure check for the value two hashes deep. Below is an example of that in the method to make the primary air loop. Note that we are not currently setup to handle electric heat on the primary air loop, we didn't need it, but if you did, you could just extent the statement with an "elsif" option before the final "else".
if options["primaryHVAC"]["heat"] == "Water"
# water coil
heating_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule())
air_loop_comps << heating_coil
else
# gas coil
heating_coil = OpenStudio::Model::CoilHeatingGas.new(model, model.alwaysOnDiscreteSchedule())
air_loop_comps << heating_coil
end
One last thing to think about. You will notice for the AEDG''s we didn't just make one measure for all of HVAC Types with a choice list to choose the one you want. We felt they were different enough that the user can choose form a collection of measures each which is focused on one type of HVAC system. There is no right or wrong answer for weather they should all be one measure or many. It depends on the needs of your use-case and how complex you want them. Our AEDG HVACmeasures also have code to address removal of existing systems, and handling plenums. If you know you will be working from clean models then you can simplify a lot of the code. You could also hand stub in air loops in your model vs. allowing OpenStudio to determine which zones go on which loop. In this case all of the objects on the ... (more)