Thermostat Mode Change based on Outdoor Temp with Window Sensors


I’m new to webCoRE and this is my first post, i have webCoRE installed and working in SmartThings.

I’m looking or may have to write a piston(s) to control my thermostat (i have three) modes (heating, off, cooling) based on outside temperature (if below 55 turn on heat, if between 60 and 70 turn off, if above 80 turn on cool) and then turn off thermostat if a window is open and on cool. This is not to change the heating or cooling set points, which is controlled by SmartThings (mode and presence sensors).
I would like this to be how i would manually control a thermostat my self, if really cold outside then finally turn on heat, if really hot turn on the A/C, if mild out set off; but i don’t want it to be “hunting”. So I think the most efficient way would be to start making this mode based; heat, off, cool and perhaps auto (which i never use but if it was on auto stay on auto and turn off thermostat when windows are open and above a certain temp, perhaps 40 degrees) as the first logical checks. I would want the heat to stay on, perhaps get a notification, if window(s) are open as i don’t want the pipes to freeze!

I have window contact sensors on my honeywell vista-128 alarm panel integrated with SmartThings thru envisalink 4 panel emulator device, and I also have the outdoor temperature from my davis vantage pro2 weather station integrated with SmartThings thru an Ambient Weather App.

I saw this post Created a Piston to turn off thermostat when door is open on how to capture the state of something. i do think i would want to create variables for temperature points.

I think i need would need to create a variable, say “target state” and initialize it to current TS state at piston start up, and then use that as my logical test.

rough draft:
capture thermostats state
if target state is heat do
notify if window is open
if outdoor temp is above 60 turn off TS and change target state to off
end if
if target state is off do
if outdoor temp below 55 turn on heat and change target state to heat
if outdoor temp above 80 turn on cool and change target state to cool
end if
if target state is cool do
if window open, capture TS state and then turn off TS and return to cool when window(s) close
if outdoor temp below 70 turn off and change target state to off
end if
if target state auto do
if window open, capture TS state and then turn off TS and return to cool when window(s) close
end if
loop back to after capture TS state

thought please and all help is welcome:D


for some reason i can’t do preformed text so indentations are lost one above draft, sorry.

what causes pistons to continually run? can i loop them myself? i don’t think above draft works unless i can control the loop without rerunning everything.

i could do two pistons, one for setting mode and the other turning off TS when window is open and above 50 degrees (don’t want pipes freezing if window was opened. But i would think the two would fight each other for control of TS mode.


guess i could loop the main body with a //todo: openwindow for the open window check, which i would think would mean two pistons. sound reasonable?


This is what I came up with in my head, not tested at all. The outsideSensor temp changes would be the trigger and also the opening of the windows. You may notice that there is no resumption of cooling in this example… that can be added later if this works. What I would do to mock this is to use Push Notification for now instead of the actual turn on/off of the thermostat to see if it will work like you expected.

device windows = window1, window2
string tsState =;


If outsideSensor temperature stays in the range of 60-70 for X minutes
  with Thermostat
    turn off
    set tsState = off
  end with;
end if;

If outsideSensor temperature stays above 80 for X minutes
  with Thermostat
    set operatingMode to cool
    set tsState =  cooling
  end with;
end if;

If outsideSensor temperature stays below 55 for X minutes
  with Thermostat
    set operatingMode to heat
    set tsState =  heating
  end with;
end if;

If any of windows is open
  If tsState == cooling
    with Thermostat
      turn off
      send notification {$currentEventDevice} is open, turning off...
    end with;
  end if;
  If tsState == heating
    with Location
      send notification {$currentEventDevice} is open and thermostat is in {tsState} mode
    end with;
  end if;
end if;


My thermostat piston does other things but the triggers would be the same. I put three triggers in the piston since the AC/heat may not be on when the windows is open. With these three triggers, it will trigger if the AC/Heat starts when a windows is already open as well as if a window is open when the AC/heat is currently on.

If you want to do separate things when the system is cooling vs. heating
If [thermostat]'s thermostatOperatingState is cooling
If [thermostat]'s thermostatOperatingState is heating
If [windows]'s contact is open

If the cooling/heating state doesn’t matter
If [thermostat]'s thermostatOperatingState is any of cooling or heating
If [windows]'s contact is open


Thanks guys. I saw a “pro tip” that basically says a string of if”s will always be evaluated and each “if” will not run if state is same as the result of the if. Just like you guys are stating.

What is the difference in a logical statement between “is” open and “changes” to open?

To me “changes” will only be evaluated as true when the window opens and will always be false there after. Such that when a window is opened and then I manually restore the thermostat to on that it will stay on until the next window is opened and with “is” then thermostat will shut off again. Is that correct? I think I like “changes” best if this senecio is correct.

The only thing I think I need to add to the above suggestion is add “and if tsState not equal to cooling” to the outside cooling check, or I think it will fight with the window check when a window is open…
I also think I will shut off the heat unless it is freezing out.


In the absence of a trigger (changes to open), is open will function as a trigger.


TY. But in my senerio with “changes to” open I could enable TS manually and it will not be turned off again until next window is opened.

“Such that when a window is opened and then I manually restore the thermostat to on that it will stay on until the next window is opened and with “is” then thermostat will shut off again.”


You are correct.

  • IS open” is a vague condition that can be true for a while
  • CHANGES TO open” is a precise trigger, that is only true for a moment.

…but @eibyer is also correct. If there are no triggers in the piston anywhere, then all conditions become triggers.

Generally speaking, I prefer using Triggers to execute a piston, and using Conditions to decide which blocks to run/ignore afterwards.

To resolve this, I use a second piston that has a trigger:

IF AC changes to on        <-- Trigger
    IF any Window is open  <-- Condition
        Send Alert Notification or verbal alert
        Flash Red light (for visual notification)
    END IF


this is what i got so far. the only problem i have is when i start it the AC Mode Management will not fire until the outside temperature crosses the set points, so i have to set the mode manually the first time.


This is normal, and happens with a lot of advanced pistons. Be thankful you aren’t working on one based on dayOfYear… where it takes 365 days just to see a single cycle. (and most of the testing is done using simulated data)

It suddenly doesn’t seem so bad waiting a few hours while yours automatically calibrates itself… :sunglasses:

Personally, I think that faking or forcing a starting variable is better than creating code that will only run once.

Another alternative is to edit the piston as the temp is moving towards a trigger, or change the trigger to a closer number temporarily. There will still be a small wait after you save, but it’ll trigger much sooner


I added all of my contact sensors, i had to go and cycle all my windows open/close so they would register as windows are closed. pain in the butt. When i closed the windows this morning it didn’t return the system to closed window state.
So i broke out window state into a separate piston and gave each window sensor its own variable and a global variable for window state. that way i could initialize as closed and then let the system flip them to open when the window opens. a window that hasn’t been opened in a while would cause the system to hang in the window open because it hadn’t had state change in a while. I ran into this after add all my window, perhaps I just needed to cycle all the window open close and it would be ok, but I didn’t try that, this way is more robust.


HVAC Mode control:

On HVAC Mode Control i don’t need the “CurrentMode…” variables or the restore state portion (disabled) at the bottom. I ended up putting a windows closed check into the conditional with outside temperature. i was afraid the piston temperature check would fire with the windows open and turn the system back on.

Thermostat off When Window is Open. Restore thermostat mode when closed

You probably already realize this, but to add a bit to our other conversation, if you press TEST on piston “au60” then all the variables would be automatically set.


I did hit test and they didn’t set… I had to edit them or cycle the sensors.

So far it is working well, came home from work and opened the windows and I got the notification the “hvac was turned off because window(s) were opened”.


latest code… for hvac control, window sensor piston remains unchanged.