Notify me when it is warmer outside than inside?

Hey folks!

I am simply trying to get a (push or text) notification when it is warmer outside than inside, according to my own sensors.

I thought that this would be really easy to implement in SmartThings, but so far I have been unable to figure it out…maybe someone has already filled this niche.

I have a shaded temperature/motion sensor on my front porch that gives a very good outside temperature reading, and I have several interior temperature sensors to choose from. I am in Colorado, so it is cool and dry at night in the summer, and we frequently leave the house open in the morning to cool off.

But it does warm up during the day, so I would like to be notified when the outside temperature crosses the inside temperature so that I can close up. I frequently get absorbed in my work in the home office, and when I look up it’s 80 degrees outside and I have sacrificed a bunch of my cool air for the day.

I have considered a couple of approaches:

  • Notify me When: This will give me a notification when a sensor crosses a set point. That’s not bad, but what I really want to know is that it’s now 67 outside and 66 inside. That’s when I would close the windows. If I pick a set point like 72 degrees, the outside air will be warming my house until 72 hits.
  • Whole House Fan: There is an app to trigger a fan/switch when it is cooler outside than in. Of course, I don’t want to trigger anything, but it occurred to me that I could create a virtual switch that this app could move, and then elsewhere I could send a notification when this switch went from off to on, or something. But alas, I can’t figure out how to do that second part…Notify me When won’t monitor switches, it seems.

But really it shouldn’t be this hard. I have searched around but things often slip through the net…can anyone point me to a simple temperature comparison/notification app?

(Additional nice-to-haves: mode selector, so I’m not getting notifications when I’m Away, etc; bias field so that I can calibrate the comparison)

Thanks,
Drew

I remember writing something like this to remind me to close/open the windows. Let me see if I can find it when I get home.

1 Like

Here you go…

/**
 *  Close/Open the Windows
 *
 *  Copyright 2014 Scottin Pollock
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */
definition(
    name: "Summer Windows",
    namespace: "soletc.com",
    author: "Scottin Pollock",
    description: "Sends a notification to open/close windows when the outside temperature is lower/higher than the inside temperature.",
    category: "My Apps",
    iconUrl: "http://solutionsetcetera.com/stuff/STIcons/SiP.png",
    iconX2Url: "http://solutionsetcetera.com/stuff/STIcons/SiP@2x.png")


preferences {
	section("Outdoor sensor...") {
		input "temperatureSensorOut", "capability.temperatureMeasurement"
	}
    section("Indoor sensor...") {
		input "temperatureSensorIn", "capability.temperatureMeasurement"
	}
    section("How much cooler or warmer...") {
		input "offset", "number", title: "how many degrees.", required: true
	}
    section("Open/Close what?") {
		input "noteSuffix", "text", title: "Room and Door/Windows", required: true
	}
}

def installed() {
	log.debug "Installed with settings: ${settings}"
	initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"
	unsubscribe()
	initialize()
}

def initialize() {
	subscribe(temperatureSensorIn, "temperature", temperatureHandler)
}

// TODO: implement event handlers

def temperatureHandler(evt) {
	def inIS = evt.doubleValue
    def lastOut = temperatureSensorOut.currentTemperature - offset
    log.debug "in is $inIS and out is $lastOut"
    if (inIS > lastOut) {
        if (state.windows != "open") {
        	send("It's cooling off outside, open the ${settings.noteSuffix}!")
        	state.windows ="open"
            log.debug "open"
        }
    } else if (inIS < lastOut) {
    	if (state.windows != "closed") {
        	send("It's warming up outside, close the ${settings.noteSuffix}!")
        	state.windows ="closed"
            log.debug "closed"
    	}
  	}
}

private send(msg) {
	log.debug msg
	sendPush( msg )
}
2 Likes

Wow, this looks great, thanks! I’ll plug it in and see how it works for me. From the code, it appears to take an open/close sensor as well, but that works…I do actually have an open/close sensor on a relevant window.

Am I right to interpret that it runs the comparison when either of the sensor values change?

No. Since the only space I care about is the indoor one, that is the only sensor we get events from. You could subscribe to both sensors and create another similar event handler.

BTW, this does not monitor any open/close sensors; I am simply setting a state variable that assumes I have open/closed the windows after getting the notification. You could certainly replace the state variables with actual sensor states if you have them.

Ok, I think I will probably take your suggestion and subscribe to the outside sensor as well. In the moment of truth, I would expect the indoor temperature to remain fairly constant, while the outdoor temp climbs up past it…

Just to follow up, I did clone the handler so that it triggered on both temperature sensors, and so far it’s working well. Thanks again! I’m not sure the messages make complete sense now that it could be either the house warming up or the outside cooling off (or vice versa), but it gets the point across. I may yet customize the notification.

Hi. I’m just getting into editing code and am not 100% sure I know what I’m doing. Can you send me the code you are using that triggers on both temperature sensors? Seems like that is a more robust solution. Thanks!

Oh, I’m really just a hack…I know enough to get myself into trouble. That’s why I asked the community for help instead of just writing it myself from a template. :slight_smile:

Here’s my version of Scott’s code. The changes are minor, really. I’ve added the other sensor to the initialize method, and then cloned the handler (and made one “In” and the other “Out”). As I mentioned above, it probably makes sense to update the messages…right now they all say “outside”. Exercise for the reader. :wink:

/**
 *  Close/Open the Windows
 *
 *  Copyright 2014 Scottin Pollock
 *    Modified 6/2016 ATV
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */
definition(
    name: "Summer Windows",
    namespace: "soletc.com",
    author: "Scottin Pollock",
    description: "Sends a notification to open/close windows when the outside temperature is lower/higher than the inside temperature.",
    category: "My Apps",
    iconUrl: "http://solutionsetcetera.com/stuff/STIcons/SiP.png",
    iconX2Url: "http://solutionsetcetera.com/stuff/STIcons/SiP@2x.png")


preferences {
	section("Outdoor sensor...") {
		input "temperatureSensorOut", "capability.temperatureMeasurement"
	}
    section("Indoor sensor...") {
		input "temperatureSensorIn", "capability.temperatureMeasurement"
	}
    section("Reduce outdoor sensor by...") {
		input "offset", "number", title: "Degrees", required: true
	}
    section("Open/Close what?") {
		input "noteSuffix", "text", title: "Room and Door/Windows", required: true
	}
}

def installed() {
	log.debug "Installed with settings: ${settings}"
	initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"
	unsubscribe()
	initialize()
}

def initialize() {
	subscribe(temperatureSensorIn, "temperature", temperatureInHandler)
	subscribe(temperatureSensorOut, "temperature", temperatureOutHandler)
}

// TODO: implement event handlers

def temperatureInHandler(evt) {
	def inIS = evt.doubleValue
    def lastOut = temperatureSensorOut.currentTemperature - offset
    log.debug "in is $inIS and out is $lastOut"
    if (inIS > lastOut) {
        if (state.windows != "open") {
        	send("It's cooling off outside, open the ${settings.noteSuffix}!")
        	state.windows ="open"
            log.debug "open"
        }
    } else if (inIS < lastOut) {
    	if (state.windows != "closed") {
        	send("It's warming up outside, close the ${settings.noteSuffix}!")
        	state.windows ="closed"
            log.debug "closed"
    	}
  	}
}

def temperatureOutHandler(evt) {
	def inIS = temperatureSensorIn.currentTemperature
    def lastOut = evt.doubleValue - offset
    log.debug "in is $inIS and out is $lastOut"
    if (inIS > lastOut) {
        if (state.windows != "open") {
        	send("It's cooling off outside, open the ${settings.noteSuffix}!")
        	state.windows ="open"
            log.debug "open"
        }
    } else if (inIS < lastOut) {
    	if (state.windows != "closed") {
        	send("It's warming up outside, close the ${settings.noteSuffix}!")
        	state.windows ="closed"
            log.debug "closed"
    	}
  	}
}

private send(msg) {
	log.debug msg
	sendPush( msg )
}

Having the need to reinstall this app the other day (Summer is now here), I added events for both sensors.

/**
 *  Summer Windows
 *
 *  Copyright 2016 Scottin Pollock
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */
definition(
	name: "Summer Windows",
	namespace: "soletc.com",
	author: "Scottin Pollock",
	description: "Sends a notification to open/close windows when the outside temperature is lower/higher than the inside temperature.",
	category: "My Apps",
	iconUrl: "http://solutionsetcetera.com/stuff/STIcons/SiP.png",
	iconX2Url: "http://solutionsetcetera.com/stuff/STIcons/SiP@2x.png")


preferences {
	section("Outdoor sensor...") {
		input "temperatureSensorOut", "capability.temperatureMeasurement"
	}
	section("Indoor sensor...") {
		input "temperatureSensorIn", "capability.temperatureMeasurement"
	}
	section("How much cooler or warmer...") {
		input "offset", "number", title: "how many degrees.", required: true
	}
	section("Open/Close what?") {
		input "noteSuffix", "text", title: "Room and Door/Windows", required: true
	}
}

def installed() {
	initialize()
}

def updated() {
	unsubscribe()
	initialize()
}

def initialize() {
	subscribe(temperatureSensorIn, "temperature", temperatureHandler)
	subscribe(temperatureSensorOut, "temperature", temperatureHandler)
}

def temperatureHandler(evt) {
	def inTEMP = temperatureSensorIn.currentTemperature
	def outTEMP = temperatureSensorOut.currentTemperature - offset
	if (inTEMP > outTEMP) {
		if (state.windows != "open") {
			send("It's cooling off outside, open the ${settings.noteSuffix}!")
			state.windows ="open"
		}
	} else if (inTEMP < outTEMP) {
		if (state.windows != "closed") {
			send("It's warming up outside, close the ${settings.noteSuffix}!")
			state.windows ="closed"
		}
	}
}

private send(msg) {
	sendPush( msg )
}
1 Like

Man…when I tried to subscribe both sensors to the same handler, it straight didn’t work. Not in the simulator or a real test. This is a lot more elegant than what I posted above, but I can’t see how it’s different from what I tried a few weeks ago.

The original handler returned data for the event. The new handler ignores that and simply gets the current value of each sensor.

Now how did you know that? Experience? Docs? I rooted through the docs to see if there was some kind of limitation, and I couldn’t find it. I was trying to use various attributes of the evt (I forget what…maybe “.device”?) to determine which device triggered the handler, so that I could act accordingly. But eventually when it didn’t work I abandoned that logic and was just trying to get the handler to print a debug when the temp changed, and I couldn’t even get that to work.

I guessed. (c;

This is awesome!! Thanks for the help guys!

This works great. Thanks!
I don’t have an outdoor temperature sensor so I used a virtual weather DTH

Please note: Groovy is part of the old legacy architecture and when ST completes the migration to Edge and LUA then the old legacy architecture will end. Any use of the items above will be very short term at this point. You may want to look at Edge replacements and a combination of Routines. :slight_smile:

2 Likes