Directly Controlling the Ecobee Fan

I am trying to directly control the Ecobee3 fan via OpenHAB (currently still on 3.4.5) so that I can keep the house comfortable without running the air conditioning when electricity rates are high. I have successfully done this by adjust FanMinOnTime based on the current house temperature.. Unfortunately, the demand response program that I signed up for adjusts the A/C setpoint but also disables the FanMinOnTime. Fortunately, I can still control the fan setting between Auto and On via the thermostat.

I found Ecobee - controlling fan "On or Auto" setting - #17 by watou that seemed similar to my requirements. I created an “FanHold” DSL script that I assume accepts a dictionary with the key “desiredFan” and a value that is stored in “receivedCommand” (I modified line 3 to match).

rule FanHold
when
  Item desiredFan receivedCommand
then
  logInfo("FanHold", "Setting fan hold to " + receivedCommand.toString)
  val params = newLinkedHashMap(
    'isTemperatureAbsolute'-> false,
    'isTemperatureRelative' -> false,
    'isCoolOff' -> true,
    'isHeatOff' -> true,
    'coolHoldTemp' -> 90,
    'heatHoldTemp' -> 50,
    'fan' -> receivedCommand.toString)
  ecobeeSetHold("411931361863", params, null, null, null, null)
end

I tried to invoke the FanHold function from Blockly via its Unique ID:

When I ran the Blockly script, the log showed:

026-07-03 19:39:25.232 [INFO ] [org.openhab.rule.6a9fb579ce] - Test Ecobee Fan Controls
  ecobeeSetHold("<thermostat ID>", params, null, null, null, null)
   6. The method ecobeeSetHold(String, LinkedHashMap<String, Comparable<?> & Constable & Serializable>, Object, Object, Object, Object) is undefined; line 14, column 380, length 13

which suggests FanHold was invoked but could not find the ecobeeSetHold() function. I am not sure why the logInfo function in FanHold did not post anything to the log.

I freely admit that I have zero knowledge of DSL rules. So far, Blockly has worked for all my OpenHAB rules and I would rather invest my time upgrading to OpenHAB 5. Any suggestions would be greatly appreciated.

Hey there, the Thing/channel rewrite of my original Ecobee binding implemented the actions differently (by necessity), so it’s not ecobeeSetHold now, it’s setHold. See this link for more. Your DSL rule logInfo line probably didn’t run because the block of code was itself not valid with the unknown function name contained therein. Best of success getting this to work, and kudos to whoever rewrote my original binding with all the detail that involved.

Hi John, thanks for the quick response. I am also getting a bunch of DSL rules errors. I will read up on DSL rules once I get my head above water.

Hi John, I am making some progress. I figured out that the DSL rule “when” clause mapped to the “When” trigger in the UI, and I had to remove the “then” statement from the rule definition, otherwise OpenHAB threw errors that were not particularly useful.

I created a global switch that I could toggle on or off via the GUI during testing. It successfully triggered my DSL rule, which was able to reference the state of the switch in “newstate”. I initially tried to follow the example in Ecobee Binding · openhab/openhab1-addons Wiki · GitHub (now gone), which resulted in “SetHold … is undefined”.

Based on Ecobee - Bindings | openHAB, I should be doing something like:

val ecobeeActions = getActions("ecobee","ecobee:thermostat:account:<thermostat UID>")
ecobeeActions.setHold(UserCool.state as QuantityType, UserHeat.state as QuantityType)

I can create the ecobeeActions variable but I am now stuck. Fan control is not listed in the examples. It is also not clear if the proxy items are defined in the DSL rule when using the rule UI, and what proxy items are required to control the fan. In my case, I only want to change the fan setting to On or Auto without making any adjustments to temperature settings.

I admit that I never could figure out text based definitions in OpenHAB 2. I only made progress when OpenHAB 3 allowed me to write rules using Blockly.

When I checked the Ecobee Thinkg Channels for “Fan”, I found nothing that would let me change the fan mode. Only today did I notice a Hold Action channel. I updated my Blockly rule to

When I run the rule, I see:

your code goes here2026-07-10 15:58:16.120 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Ecobee_Thermostat_Main_Floor_Hold_Action' received command "Fan" : "On"
2026-07-10 15:58:16.121 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'Ecobee_Thermostat_Main_Floor_Hold_Action' predicted to become "Fan" : "On"
2026-07-10 15:58:16.125 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Ecobee_Thermostat_Main_Floor_Hold_Action' changed from askMe to "Fan" : "On"
2026-07-10 15:59:51.585 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 
2026-07-10 15:59:51.600 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Ecobee_Thermostat_Main_Floor_Hold_Action' changed from "Fan" : "On" to askMe

The fan mode via the Ecobee thermostat is still showing Auto:at least 10 min/hr but at least I am not getting errors. I may need to create a JSON object for the parameters. I will try out Json Tools in the Markplace after the Spain/Belgium game finishes.

I have installed and tried the Json tools “stringify” function which appears to pass {“Fan”:“On”} to the Hold Action item. It is accepted but Hold Action reverts to askMe. Maybe I need to pass additional parameters but could use some guidance.

My goal is to continue to control the furnace fan during demand response events which cripple the minimum fan runtime function. In the process, I need to avoid making changes to the temperature setpoint which would cause me to exit from the demand response. I can deal with the higher A/C setpoint during the event so long as I can keep air flow in the house.