Skip to content

Fix #8904: OA node wetbulb actuator silently fails via Python plugin API#11540

Open
brianlball wants to merge 2 commits intodevelopfrom
fix/issue-8904-oa-node-wetbulb-actuator
Open

Fix #8904: OA node wetbulb actuator silently fails via Python plugin API#11540
brianlball wants to merge 2 commits intodevelopfrom
fix/issue-8904-oa-node-wetbulb-actuator

Conversation

@brianlball
Copy link
Copy Markdown
Contributor

Summary

Fixes #8904 — EMS "Outdoor Air System Node" / "Wetbulb Temperature" actuator has no effect when set via the Python plugin API (getActuatorHandle). Drybulb works; wetbulb is silently discarded.

Scope: Python plugin API path only. Traditional EMS wetbulb overrides work correctly (fixed in PR #6841, which sets IsLocalNode=true during SetupNodeSetPointsAsActuators at EMSManager.cc:1427). The issue's follow-up EMS example appears broken due to a typo (SET cond_dbt = 23.9 should be SET cond_wbt = 23.9) — Node 1's reported Twb=19.41 confirms the traditional path works.

Root cause

SetOANodeValues (OutAirNodeManager.cc:595) gates the PsyWFnTdbTwbPb HumRat recalculation behind if (Node.IsLocalNode). Traditional EMS sets IsLocalNode = true during setup via SetupNodeSetPointsAsActuators (EMSManager.cc:1427), but getActuatorHandle() (datatransfer.cc:457) never does — by the time a Python plugin requests the handle, setup has already run and found no match.

Fix

Two complementary changes:

File Change
OutAirNodeManager.cc:595 Widen gate: IsLocalNode || EMSOverrideOutAirDryBulb || EMSOverrideOutAirWetBulb — EMS override bools are ground truth set by both traditional and plugin paths
datatransfer.cc:461-468 Set IsLocalNode = true in getActuatorHandle when type is "OUTDOOR AIR SYSTEM NODE", mirroring EMSManager.cc:1427 — covers AirflowNetwork and any other IsLocalNode consumer
OutAirNodeManager.unit.cc New test

Flow tree

Pre-fix (Python plugin wetbulb override):
├─ Plugin calls getActuatorHandle("Outdoor Air System Node", "Wetbulb Temperature", node)
│  └─ datatransfer.cc:457 — returns handle, but IsLocalNode stays false
├─ Plugin sets actuator value → EMSOverrideOutAirWetBulb = true
└─ SetOANodeValues (OutAirNodeManager.cc:595)
   └─ if (Node.IsLocalNode) → FALSE → skip HumRat recalc → override discarded

Post-fix:
├─ getActuatorHandle — sets IsLocalNode = true (datatransfer.cc:464)
└─ SetOANodeValues (OutAirNodeManager.cc:595)
   └─ if (IsLocalNode || EMSOverrideOutAirDryBulb || EMSOverrideOutAirWetBulb) → TRUE
      └─ PsyWFnTdbTwbPb recalculates HumRat from overridden Twb ✓

Test added

OutAirNodeManager_EMSWetbulbOverride_NoIsLocalNode — two OA nodes with IsLocalNode=false and EMS wetbulb overrides active. Verifies HumRat is recalculated from overridden temps, not left at environment value.

Test plan

  • New unit test passes
  • Full test suite: 3014/3014 passed
  • pre-commit clean
  • gcc warning check clean
  • CI green

SetOANodeValues gates HumRat recalculation on IsLocalNode, which
is not set for Python plugin actuators. Widen gate to also check
EMSOverrideOutAirDryBulb/WetBulb so the psychrometric recalc runs
whenever an override is actually active, regardless of IsLocalNode.

Add unit test reproducing the bug with IsLocalNode=false.
Python plugin path (getActuatorHandle) never set IsLocalNode=true,
unlike traditional EMS path in EMSManager::SetupNodeSetPointsAsActuators.
This also fixes AirflowNetwork propagation for plugin OA overrides.
@brianlball brianlball added the Defect Includes code to repair a defect in EnergyPlus label Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Defect Includes code to repair a defect in EnergyPlus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EMS/Python Outdoor Air System Node Wetbulb Temperature Actuator Not Working

2 participants