Update lighting-director.groovy
[smartapps.git] / official / auto-humidity-vent.groovy
1 /**
2  *  Auto Humidity Vent
3  *
4  *  Copyright 2014 Jonathan Andersson
5  *
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:
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
14  *
15  */
16  
17  
18 definition (
19
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"
27
28 )
29
30
31 preferences {
32
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
36         }
37
38         section("Choose a humidity sensor...") {
39                 input "humidity_sensor", "capability.relativeHumidityMeasurement", title: "Humidity Sensor", required: true
40         }
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
43         }
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
46         }
47
48         section("Select the vent fans to control...") {
49                 input "fans", "capability.switch", title: "Vent Fans", multiple: true, required: true
50         }
51
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
55         }
56
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
60     }
61
62 }
63
64
65 def installed() {
66
67         log.debug "${app.label} installed with settings: ${settings}"
68
69         state.app_enabled = false
70         state.fan_control_enabled = false
71
72         state.fansOn = false
73         state.fansOnTime = now()
74         state.fansLastRunTime = 0
75
76         initialize()
77
78 }
79
80
81 def uninstalled()
82 {
83
84         send("${app.label} uninstalled.")
85     
86         state.app_enabled = false
87
88         set_fans(false)
89
90         state.fan_control_enabled = false
91
92 }
93
94
95 def updated() {
96
97         log.debug "${app.label} updated with settings: ${settings}"
98
99         unsubscribe()
100
101         initialize()
102
103 }
104
105
106 def initialize() {
107
108         if (settings.fan_control_enabled) {
109                 if(state.fan_control_enabled == false) {
110                         send("Vent Fan Control Enabled.")
111         } else {
112                 log.debug "Vent Fan Control Enabled."
113         }
114
115                 state.fan_control_enabled = true
116         } else {
117                 if(state.fan_control_enabled == true) {
118                         send("Vent Fan Control Disabled.")
119         } else {
120                 log.debug "Vent Fan Control Disabled."
121         }
122
123                 state.fan_control_enabled = false
124         }
125
126         if (settings.app_enabled) {
127                 if(state.app_enabled == false) {
128                         send("${app.label} Enabled.")
129         } else {
130                 log.debug "${app.label} Enabled."
131         }
132
133                 subscribe(humidity_sensor, "humidity", "handleThings")
134
135                 state.app_enabled = true
136         } else {
137                 if(state.app_enabled == true) {
138                         send("${app.label} Disabled.")
139         } else {
140                 log.debug "${app.label} Disabled."
141         }
142
143                 state.app_enabled = false
144     }
145
146     handleThings()
147
148 }
149
150
151 def handleThings(evt) {
152
153
154         log.debug "handleThings()"
155
156         if(evt) {
157                 log.debug "$evt.descriptionText"
158     }
159         
160         def h = 0.0 as BigDecimal
161         if (settings.app_enabled) {
162             h = settings.humidity_sensor.currentValue('humidity')
163 /*
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()
168         } else {
169                 h = 20
170         }        
171 */
172         }
173
174         log.debug "Humidity: $h%, Activate: $humidity_a%, Deactivate: $humidity_d%"
175
176     def activateFans = false
177     def deactivateFans = false
178     
179         if (settings.app_enabled) {
180         
181                 if (state.fansOn) {
182             if (h > humidity_d) {
183                 log.debug "Humidity not sufficient to deactivate vent fans: $h > $humidity_d"
184             } else {
185                 log.debug "Humidity sufficient to deactivate vent fans: $h <= $humidity_d"
186                 deactivateFans = true
187             }
188         } else {
189             if (h < humidity_a) {
190                 log.debug "Humidity not sufficient to activate vent fans: $h < $humidity_a"
191             } else {
192                 log.debug "Humidity sufficient to activate vent fans: $h >= $humidity_a"
193                 activateFans = true
194             }
195         }
196         }
197
198         if(activateFans) {
199                 set_fans(true)
200     }
201         if(deactivateFans) {
202                 set_fans(false)
203     }
204
205 }
206
207
208 def set_fans(fan_state) {
209
210         if (fan_state) {
211         if (state.fansOn == false) {
212             send("${app.label} fans On.")
213             state.fansOnTime = now()
214             if (settings.fan_control_enabled) {
215                 if (emeters) {
216                     emeters.reset()
217                 }
218                 fans.on()
219             } else {
220                 send("${app.label} fan control is disabled.")
221             }
222             state.fansOn = true
223                 } else {
224             log.debug "${app.label} fans already On."
225                 }        
226     } else {
227         if (state.fansOn == true) {
228                 send("${app.label} fans Off.")
229                 //state.fansLastRunTime = (now() - state.fansOnTime)
230
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))
236
237                 //      def sb = String.format("${app.label} cycle: %d:%02d:%02d:%02d", days, hours, minutes, seconds)
238                         
239                 //    send(sb)
240
241         if (settings.fan_control_enabled) {
242                 fans.off()
243                 if (emeters) {
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.fansLastRunEnergy = emeters.currentValue('energy')
250                     state.fansLastRunCost = ((state.fansLastRunEnergy * price_kwh) / 100.0) 
251                     send("${app.label} cycle: ${state.fansLastRunEnergy}kWh @ \$${state.fansLastRunCost}")
252                 }
253                 } else {
254                 send("${app.label} fan control is disabled.")
255             }
256                 state.fansOn = false
257             state.fansHoldoff = now()
258         } else {
259             log.debug "${app.label} fans already Off."
260         }
261     }
262
263 }
264
265
266 private send(msg) {
267
268         if (sendPushMessage) {
269         sendPush(msg)
270     }
271
272     if (phone) {
273         sendSms(phone, msg)
274     }
275
276     log.debug(msg)
277 }
278