Drying mode actions bypass Global Cooldown (GCD) entirely
Summary
All four drying handlers in DryingActions.py (ElClassico, 5DayDry, DewBased, OwnDry) emit device actions directly via event_manager.emit(...), completely bypassing OGBActionManager's cooldown filter and OGBgcdManager. This means a user-configured Global Cooldown (GCD) — e.g. a 30-minute cooldown on the humidifier capability — has no effect at all while tentMode == "Drying", regardless of which drying sub-mode is active.
Reproduction / observed behavior
- Tent Mode:
Drying, Drying Mode: ElClassico
- Humidifier GCD configured: 30 minutes
- Actual device log from a live drying cycle, ~8 minutes apart:
19:35:13 ElClassico HUM HIGH - 65.4% > 62.0% → Dehumidify ON
executing: ['Increase Dehumidifier', 'Reduce Humidifier', 'Increase Exhaust', 'Increase Ventilation']
19:37:23 ElClassico HUM LOW - 59.0% < 62.0% → Humidify ON
executing: ['Increase Humidifier', 'Reduce Dehumidifier', 'Reduce Exhaust', 'Increase Ventilation']
The humidifier and dehumidifier flip against each other roughly every 1-2 minutes as the reading oscillates around the ±2% tolerance band, with no cooldown throttling the switching — despite a 30-minute GCD being configured for that capability.
Root cause
-
Every drying handler builds a finalActionMap and emits it directly:
handle_ElClassico → DryingActions.py:225-226
handle_5DayDry → DryingActions.py:359-360
handle_DewBased → DryingActions.py:486-487
handle_OwnDry → DryingActions.py:575-576
for action_name in finalActionMap:
await self.event_manager.emit(action_name, None)
This goes straight to each device class's listener (e.g. Humidifier.py's increaseAction/reduceAction, registered via event_manager.on("Increase Humidifier", ...) in __init__). The docstring on every one of these handlers states this explicitly: "Direct event emission - no cooldowns or VPD logic interference."
-
The only place GCD/cooldown enforcement exists is OGBActionManager._process_actions_with_cooldown_filter() (OGBActionManager.py:158-194), which delegates to OGBgcdManager.is_allowed(). That filter is only invoked from the VPD/action-map pipeline (OGBActionManager.py around lines 1153-1156 and 1239-1242), used by VPD Perfection, VPD Target, Closed Environment, and the Premium PID/MPC/AI modes.
-
DryingActions never calls into OGBActionManager, so drying-mode actions never pass through that filter. Device classes themselves (checked Humidifier.py and the base Device.py) have no cooldown check either — the only per-device gate is an unrelated "Smart Deadband" check in reduceAction.
Suggested fix
Route the finalActionMap built in each DryingActions handler through the same cooldown mechanism used by the VPD pipeline (e.g. action_manager.cooldown_manager.is_allowed() / .register()) before emitting, so a configured GCD is respected consistently regardless of tentMode. Given GCD is presented as a global, per-capability safety feature, having it silently no-op for an entire mode is surprising and can cause rapid actuator cycling (as shown above) during an otherwise sensitive process like drying.
Environment
- OGB installed via HACS on Home Assistant
- Drying Mode: ElClassico
- Humidifier GCD: 30 minutes
Drying mode actions bypass Global Cooldown (GCD) entirely
Summary
All four drying handlers in
DryingActions.py(ElClassico,5DayDry,DewBased,OwnDry) emit device actions directly viaevent_manager.emit(...), completely bypassingOGBActionManager's cooldown filter andOGBgcdManager. This means a user-configured Global Cooldown (GCD) — e.g. a 30-minute cooldown on the humidifier capability — has no effect at all whiletentMode == "Drying", regardless of which drying sub-mode is active.Reproduction / observed behavior
Drying, Drying Mode:ElClassicoThe humidifier and dehumidifier flip against each other roughly every 1-2 minutes as the reading oscillates around the ±2% tolerance band, with no cooldown throttling the switching — despite a 30-minute GCD being configured for that capability.
Root cause
Every drying handler builds a
finalActionMapand emits it directly:handle_ElClassico→DryingActions.py:225-226handle_5DayDry→DryingActions.py:359-360handle_DewBased→DryingActions.py:486-487handle_OwnDry→DryingActions.py:575-576This goes straight to each device class's listener (e.g.
Humidifier.py'sincreaseAction/reduceAction, registered viaevent_manager.on("Increase Humidifier", ...)in__init__). The docstring on every one of these handlers states this explicitly: "Direct event emission - no cooldowns or VPD logic interference."The only place GCD/cooldown enforcement exists is
OGBActionManager._process_actions_with_cooldown_filter()(OGBActionManager.py:158-194), which delegates toOGBgcdManager.is_allowed(). That filter is only invoked from the VPD/action-map pipeline (OGBActionManager.pyaround lines 1153-1156 and 1239-1242), used by VPD Perfection, VPD Target, Closed Environment, and the Premium PID/MPC/AI modes.DryingActionsnever calls intoOGBActionManager, so drying-mode actions never pass through that filter. Device classes themselves (checkedHumidifier.pyand the baseDevice.py) have no cooldown check either — the only per-device gate is an unrelated "Smart Deadband" check inreduceAction.Suggested fix
Route the
finalActionMapbuilt in eachDryingActionshandler through the same cooldown mechanism used by the VPD pipeline (e.g.action_manager.cooldown_manager.is_allowed()/.register()) before emitting, so a configured GCD is respected consistently regardless oftentMode. Given GCD is presented as a global, per-capability safety feature, having it silently no-op for an entire mode is surprising and can cause rapid actuator cycling (as shown above) during an otherwise sensitive process like drying.Environment