4 * Copyright 2014 Jonathan Andersson
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 * in compliance with the License. You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
12 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
13 * for the specific language governing permissions and limitations under the License.
20 name: "Auto Humidity Vent",
21 namespace: "jonathan-a",
22 author: "Jonathan Andersson",
23 description: "When the humidity reaches a specified level, activate one or more vent fans until the humidity is reduced to a specified level.",
24 category: "Convenience",
25 iconUrl: "https://s3.amazonaws.com/smartthings-device-icons/Appliances/appliances11-icn.png",
26 iconX2Url: "https://s3.amazonaws.com/smartthings-device-icons/Appliances/appliances11-icn@2x.png"
33 section("Enable / Disable the following functionality:") {
34 input "app_enabled", "bool", title: "Auto Humidity Vent", required:true, defaultValue:true
35 input "fan_control_enabled", "bool", title: "Vent Fan Control", required:true, defaultValue:true
38 section("Choose a humidity sensor...") {
39 input "humidity_sensor", "capability.relativeHumidityMeasurement", title: "Humidity Sensor", required: true
41 section("Enter the relative humudity level (%) above which the vent fans will activate:") {
42 input "humidity_a", "number", title: "Humidity Activation Level", required: true, defaultValue:70
44 section("Enter the relative humudity level (%) below which the vent fans will deactivate:") {
45 input "humidity_d", "number", title: "Humidity Deactivation Level", required: true, defaultValue:65
48 section("Select the vent fans to control...") {
49 input "fans", "capability.switch", title: "Vent Fans", multiple: true, required: true
52 section("Select the vent fan energy meters to monitor...") {
53 input "emeters", "capability.energyMeter", title: "Energy Meters", multiple: true, required: false
54 input "price_kwh", "decimal", title: "Cost in cents per kWh (12 is US avg)", required: true, defaultValue:12
57 section("Set notification options:") {
58 input "sendPushMessage", "bool", title: "Push notifications", required:true, defaultValue:false
59 input "phone", "phone", title: "Send text messages to", required: false
67 log.debug "${app.label} installed with settings: ${settings}"
69 state.app_enabled = false
70 state.fan_control_enabled = false
73 state.fansOnTime = now()
74 state.fansLastRunTime = 0
84 send("${app.label} uninstalled.")
86 state.app_enabled = false
90 state.fan_control_enabled = false
97 log.debug "${app.label} updated with settings: ${settings}"
108 if (settings.fan_control_enabled) {
109 if(state.fan_control_enabled == false) {
110 send("Vent Fan Control Enabled.")
112 log.debug "Vent Fan Control Enabled."
115 state.fan_control_enabled = true
117 if(state.fan_control_enabled == true) {
118 send("Vent Fan Control Disabled.")
120 log.debug "Vent Fan Control Disabled."
123 state.fan_control_enabled = false
126 if (settings.app_enabled) {
127 if(state.app_enabled == false) {
128 send("${app.label} Enabled.")
130 log.debug "${app.label} Enabled."
133 subscribe(humidity_sensor, "humidity", "handleThings")
135 state.app_enabled = true
137 if(state.app_enabled == true) {
138 send("${app.label} Disabled.")
140 log.debug "${app.label} Disabled."
143 state.app_enabled = false
151 def handleThings(evt) {
154 log.debug "handleThings()"
157 log.debug "$evt.descriptionText"
160 def h = 0.0 as BigDecimal
161 if (settings.app_enabled) {
162 h = settings.humidity_sensor.currentValue('humidity')
164 //Simulator is broken and requires this work around for testing.
165 if (settings.humidity_sensor.latestState('humidity')) {
166 log.debug settings.humidity_sensor.latestState('humidity').stringValue[0..-2]
167 h = settings.humidity_sensor.latestState('humidity').stringValue[0..-2].toBigDecimal()
174 log.debug "Humidity: $h%, Activate: $humidity_a%, Deactivate: $humidity_d%"
176 def activateFans = false
177 def deactivateFans = false
179 if (settings.app_enabled) {
182 if (h > humidity_d) {
183 log.debug "Humidity not sufficient to deactivate vent fans: $h > $humidity_d"
185 log.debug "Humidity sufficient to deactivate vent fans: $h <= $humidity_d"
186 deactivateFans = true
189 if (h < humidity_a) {
190 log.debug "Humidity not sufficient to activate vent fans: $h < $humidity_a"
192 log.debug "Humidity sufficient to activate vent fans: $h >= $humidity_a"
208 def set_fans(fan_state) {
211 if (state.fansOn == false) {
212 send("${app.label} fans On.")
213 state.fansOnTime = now()
214 if (settings.fan_control_enabled) {
220 send("${app.label} fan control is disabled.")
224 log.debug "${app.label} fans already On."
227 if (state.fansOn == true) {
228 send("${app.label} fans Off.")
229 state.fansLastRunTime = (now() - state.fansOnTime)
231 BigInteger ms = new java.math.BigInteger(state.fansLastRunTime)
232 int seconds = (BigInteger) (((BigInteger) ms / (1000I)) % 60I)
233 int minutes = (BigInteger) (((BigInteger) ms / (1000I * 60I)) % 60I)
234 int hours = (BigInteger) (((BigInteger) ms / (1000I * 60I * 60I)) % 24I)
235 int days = (BigInteger) ((BigInteger) ms / (1000I * 60I * 60I * 24I))
237 def sb = String.format("${app.label} cycle: %d:%02d:%02d:%02d", days, hours, minutes, seconds)
241 if (settings.fan_control_enabled) {
244 log.debug emeters.currentValue('energy')
245 //TODO: How to ensure latest (most accurate) energy reading?
246 //emeters.poll() //[configure, refresh, on, off, poll, reset]
247 // emeters.refresh() //[configure, refresh, on, off, poll, reset]
248 state.fansLastRunEnergy = emeters.currentValue('energy').sum()
249 state.fansLastRunCost = ((state.fansLastRunEnergy * price_kwh) / 100.0)
250 send("${app.label} cycle: ${state.fansLastRunEnergy}kWh @ \$${state.fansLastRunCost}")
253 send("${app.label} fan control is disabled.")
256 state.fansHoldoff = now()
258 log.debug "${app.label} fans already Off."
267 if (sendPushMessage) {