Skip to content

Instantly share code, notes, and snippets.

@johnculviner
Created July 20, 2017 15:10
Show Gist options
  • Save johnculviner/518f27063f1ebf5e3b31209500fa44c0 to your computer and use it in GitHub Desktop.
Save johnculviner/518f27063f1ebf5e3b31209500fa44c0 to your computer and use it in GitHub Desktop.
/**
* Whole House Fan II
*
* Copyright 2017 John Culviner
*
* MIT LICENSE
*/
definition(
name: "Whole House Fan II",
namespace: "culviner",
author: "John Culviner",
description: "Makes recommendations to open windows and turn on whole house fan based on indoor/outdoor conditions. Takes actions once you open/close window",
category: "Green Living",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Developers/whole-house-fan.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Developers/whole-house-fan%402x.png"
)
preferences {
section("Outdoor") {
input "outTemp", "capability.temperatureMeasurement", title: "Outdoor Temperature", required: true
input "outHumidity", "capability.relativeHumidityMeasurement", title: "Outdoor Humidity", required: true
}
section("Indoor") {
input "inTemp", "capability.temperatureMeasurement", title: "Indoor Temperature", required: true
input "inHumidity", "capability.relativeHumidityMeasurement", title: "Indoor Humidity", required: true
input "minInTemp", "number", title: "Minimum Indoor Temperature"
input "maxInHumidity", "number", title: "Maximum Indoor Humidity"
input "fan", "capability.switch", title: "Fan Outlet", required: true
}
section("Thermostat") {
input "thermostat", "capability.thermostat", title: "Thermostat"
}
section("Windows/Doors") {
input "contacts", "capability.contactSensor", title: "Fan Window", required: true, multiple: true
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
state.fanRunning = false
subscribe(outTemp, "temperature", "checkThings")
subscribe(inTemp, "temperature", "checkThings")
subscribe(inHumiditiy, "humidity", "checkThings")
subscribe(outHumidity, "humidity", "checkThings")
subscribe(thermostat, "thermostat", "checkThings")
subscribe(contacts, "contact", "checkThings")
}
def checkThings(evt) {
def indoorHumidity = settings.inHumidity.humidity
def outsideTemp = heatIndexCalc(settings.outTemp.currentTemperature, settings.outHumidity.humidity)
def insideTemp = heatIndexCalc(settings.inTemp.currentTemperature, indoorHumidity)
def thermostatMode = settings.thermostat.currentThermostatMode
def windowsOpen = settings.contacts?.find { it.currentContact == 'open' }
log.debug "Inside: $insideTemp, Outside: $outsideTemp, Thermostat: $thermostatMode, Something Open: $windowsOpen"
def reason = ""
def shouldRun = true
if (insideTemp < outsideTemp) {
reason = "insideTemp < outdoorTemp"
shouldRun = false
if (state.fanRunning) {
sendPush("I'm turning off the fan. I recommend you close your windows because ${reason}")
}
}
if (insideTemp < settings.minInTemp) {
reason = "insideTemp < minInTemp"
shouldRun = false
if (state.fanRunning) {
sendPush("I'm turning off the fan because ${reason}")
}
}
if (indoorHumidity > settings.maxInHumidity) {
reason = "Not running due to insideTemp < minInTemp"
shouldRun = false
if (state.fanRunning) {
sendPush("I'm turning off the fan because ${reason}")
}
}
if (shouldRun && !windowsOpen) {
reason = "Please open your window so I can turn on the fan!"
sendPush(reason)
shouldRun = false
}
log.debug(reason)
if (shouldRun && !state.fanRunning) {
fan.on()
state.fanRunning = true
} else if (!shouldRun && state.fanRunning) {
fan.off()
state.fanRunning = false
}
}
def heatIndexCalc(def F, def rh) {
def Hindex
Hindex = -42.379 + 2.04901523 * F + 10.14333127 * rh
Hindex = Hindex - 0.22475541 * F * rh - 6.83783 * Math.pow(10, -3) * F * F
Hindex = Hindex - 5.481717 * Math.pow(10, -2) * rh * rh
Hindex = Hindex + 1.22874 * Math.pow(10, -3) * F * F * rh
Hindex = Hindex + 8.5282 * Math.pow(10, -4) * F * rh * rh
Hindex = Hindex - 1.99 * Math.pow(10, -6) * F * F * rh * rh
DecimalFormat df = new DecimalFormat(RESULT_FORMAT)
df.setRoundingMode(RoundingMode.HALF_UP)
return Double.parseDouble(df.format(Hindex))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment