Registering a new SDK object in the OSApp - openstudiocoalition/OpenStudioApplication GitHub Wiki
Registering an object is extremely simple, but it takes a little bit of same as you need an icon.
Usually I take one that exists for another coil and add something unique to it, so that when viewed on a loop topology you don't have to guess whether it's a coil DX SingleSpeed, MultipleSpeed, VariableSpeed).
You save two versions of the icon as PNG:
- A 100px * 100px version in
src/openstudio_lib/images/
- A 24px * 24px version in
src/openstudio_lib/images/mini_icons/
To register the icon files themselves (to embed them really), edit src/openstudio_lib/openstudio.qrc
<file>images/objectname.png</file>
[...]
<file>images/mini_icons/objectname.png</file>
Then, associate the IddObjectType
with the icon by adding two lines in src/openstudio_lib/IconLibrary.cpp
m_icons[openstudio::IddObjectType(openstudio::IddObjectType::OS_ObjectName).value()] = new QPixmap(":images/objectname.png");
[...]
m_miniIcons[openstudio::IddObjectType(openstudio::IddObjectType::OS_ObjectName).value()] = new QPixmap(":images/mini_icons/objectname.png");
A example of such a commit is here: CoilHeatingDesuperHeater exmaple.
The MainRightColumnController
is responsible to say on which tab you want to display the IddObjectType
, on either/or "My Model" or "Library" subtabs.
You do this by editing src/openstudio_lib/MainRightColumnController.cpp. For example, to show an object on the "HVAC Systems" tab, edit MainRightColumnController::configureForHVACSystemsSubTab
// Show under 'My Model'
myModelList->addModelObjectType(IddObjectType::OS_WaterUse_Equipment, "Water Use Equipment"); // second param is the display name
// Show under `Library`
libraryWidget->addModelObjectType(IddObjectType::OS_WaterUse_Equipment, "Water Use Equipment");
Note that things are displayed in reverse order as they are defined.
You can hide, or lock any fields on the object by editing src/openstudio_lib/library/OpenStudioPolicy.xml
To have objects be listed on Thermal Zones and HVAC Systems tabs under Library
, they have to be added to the src/openstudio_app/Resources/default/hvac_library.osm.
You should use the ruby bindings to add your object to the library. This is is typically a bit more involved if you are doing this with a custom build of OpenStudio SDK (while actively adding the object to the SDK) as doing so will translate the hvac_library.osm while future PRs to the SDK before the actual official release might need translation as well (which won't happen), so reach out for help if need be. We recommend creating a ruby script to add objects to the library, so that it can be run later when the official SDK containing the new object is out. For an exemple, see PR#72
Note: when dragging an object from "Library" to your model, the clone
method is called, so it will pull resources objects such as curves and schedules with it (along with any custom logic implemented in the clone
method for that class)
A special case are the alwaysOnDiscreteSchedule
(and related alwaysOff / Continuous ones). To avoid ending up with a ton of different versions in your model when dragging multiple library objects, please after adding your ModelObject to the hvac_library, delete these objects and replace them with the special ones we defined atop the hvac_library file such as Always On Discrete hvac_library
.
Here's an example of creating an object, and cleaning up the always on discrete schedule it'll create in its constructor to replace it with the hvac_library.osm
one
require 'openstudio'
include OpenStudio::Model
# Helper to load a model in one line
# It will raise if the path (or the model) isn't valid
#
# @param path [String] The path to the osm
# @return [OpenStudio::Model::Model] the resulting model.
def osload(path)
translator = OpenStudio::OSVersion::VersionTranslator.new
ospath = OpenStudio::Path.new(path)
model = translator.loadModel(ospath)
if model.empty?
raise "Path '#{path}' is not a valid path to an OpenStudio Model"
else
model = model.get
end
return model
end
m = osload('hvac_library.osm')
alwaysOn = m.getScheduleConstantByName("Always On Discrete hvac_library").get
fan = FanComponentModel.new(m)
fan.setName('FanComponentModel')
# Availability Schedule Name: Required Object
fan.setAvailabilitySchedule(alwaysOn)
# Do more stuff....
# Remove the alwaysOn it created by default, and the schedule type lim
sch = m.getScheduleConstantByName("Always On Discrete").get
sch_lim = sch.scheduleTypeLimits.get
sch_lim.remove()
sch.remove()
m.save('hvac_library.osm', true)