diff --git a/Apps/BathroomHumidityFan/BathroomHumidityParent.src b/Apps/BathroomHumidityFan/BathroomHumidityParent.src
index 5bf225a..b0730f0 100644
--- a/Apps/BathroomHumidityFan/BathroomHumidityParent.src
+++ b/Apps/BathroomHumidityFan/BathroomHumidityParent.src
@@ -1,1170 +1,94 @@
-/**
-* Bathroom Humidity Fan
-*
-* Turns on a fan when you start taking a shower... turns it back off when you are done.
-* -Uses humidity change rate for rapid response
-* -Timeout option when manaully controled (for stench mitigation)
-* -Child/Parent with pause/resume (Thanks to Lewis.Heidrick!)
-*
-* Copyright 2018 Craig Romei
-* GNU General Public License v2 (https://www.gnu.org/licenses/gpl-2.0.txt)
-*
-*/
-import groovy.transform.Field
-import hubitat.helper.RMUtils
+/*
+ * Bathroom Humidity Fan (Parent)
+ *
+ * I just wanted a parent/child version.
+ *
+ *
+ */
-def setVersion() {
- state.version = "1.1.40" // Version number of this app
- state.InternalName = "BathroomHumidityFan" // this is the name used in the JSON file for this app
+def setVersion(){
+ state.version = "1.1.40" // Version number of this app
+ state.InternalName = "BathroomHumidityFan" // this is the name used in the JSON file for this app
}
definition(
- name: "Bathroom Humidity Fan Child",
+ name: "Bathroom Humidity Fan",
namespace: "Craig.Romei",
+ singleInstance: true,
author: "Craig Romei",
- description: "Control a fan (switch) based on relative humidity.",
+ description: "Control a fan (switch) based on relative humidity. - Parent",
category: "Convenience",
- parent: "Craig.Romei:Bathroom Humidity Fan",
iconUrl: "",
iconX2Url: "",
iconX3Url: "",
- importUrl: "https://raw.githubusercontent.com/napalmcsr/Hubitat_Napalmcsr/master/Apps/BathroomHumidityFan/BathroomHumidityChild.src")
+ importUrl: "https://raw.githubusercontent.com/napalmcsr/Hubitat_Napalmcsr/master/Apps/BathroomHumidityFan/BathroomHumidity.src")
preferences {
- page(name: "mainPage")
- page(name: "timeIntervalInput", title: "Only during a certain time") {
- section {
- input "starting", "time", title: "Starting", required: false
- input "ending", "time", title: "Ending", required: false
- }
- }
+ page(name: "mainPage")
}
-def mainPage() {
- dynamicPage(name: "", title: "", install: true, uninstall: true, refreshInterval:0) {
- ifTrace("mainPage")
- turnOffLoggingTogglesIn30()
- setPauseButtonName()
- setCreateSmartSwitchButtonName()
-
- section("") {
- input name: "Pause", type: "button", title: state.pauseButtonName, submitOnChange:true
- input name: "detailedInstructions", type: "bool", title: "Enable detailed instructions", defaultValue: false, submitOnChange: true
- input name: "On", type: "button", title: "On", submitOnChange:true
- input name: "Off", type: "button", title: "Off", submitOnChange:true
- }
- section("") {
- if ((state.thisName == null) || (state.thisName == "null ")) {state.thisName = "Enter a name for this app."}
- input name: "thisName", type: "text", title: "", required:true, submitOnChange:true, defaultValue: "Enter a name for this app."
- state.thisName = thisName
- updateLabel()
- }
- section("") {
- input "refresh", "bool", title: "Click here to refresh the device status", submitOnChange:true
- if (detailedInstructions == true) {paragraph "This is the device that is triggered when conditions are met."}
- input "fanSwitch", "capability.switch", title: "${state.fanSwitchStatus}", required: true, submitOnChange:true
- if (detailedInstructions == true) {paragraph "This humidity sensor is used to trigger any of the response methods."}
- input "humiditySensor", "capability.relativeHumidityMeasurement", title: "${state.humiditySensorStatus} ${state.humiditySensorBatteryStatus}", required: true, submitOnChange:true
- paragraph "NOTE: The humidity sensor you select will need to report about 5 min or less."
- if (detailedInstructions == true) {paragraph "Rate of change: Triggers when the humidity sensors humidity value increases by more than the humidity increase rate."}
- if (detailedInstructions == true) {paragraph "Humidity over fixed threshold: Triggers when the humidity sensors humidity value goes over the humidity threshold."}
- if (detailedInstructions == true) {paragraph "Rate of change and humidity over comparison sensor: Triggers when the humidity is greater than the comparison humidity sensor + comparison offset trigger and the rate of change is greater than the humidity increase rate."}
- if (detailedInstructions == true) {paragraph "Humidity over comparison senor: Triggers when the humidity sensors humidity value is greater than the comparison sensors humidity value + comparison offset trigger."}
- input "humidityResponseMethod", "enum", title: "Humidity Response Method", options: humidityResponseMethodOptions, defaultValue: 1, required: true, multiple: true, submitOnChange:true
- app.updateSetting("refresh",[value:"false",type:"bool"])
- }
- if (settings.humidityResponseMethod?.contains("3") || settings.humidityResponseMethod?.contains("4")) {
- section("") {
- if (detailedInstructions == true) {paragraph "Comparison sensor is used as a dynamic method of setting a humidity threshold. Combining multiple humidity sensors is a good way of providing a stable baseline humidity value that will adjust over the seasons. Take the comparison sensors humidity plus comparison offset trigger to get your target humidity that you want the fan to come on."}
- input "compareHumiditySensor", "capability.relativeHumidityMeasurement", title: "${state.compareHumiditySensorStatus} ${state.compareHumiditySensorBatteryStatus}", required: true, submitOnChange:true
- if (compareHumiditySensor) {compareHumiditySensor = (compareHumiditySensor.currentValue("humidity"))}
- if (detailedInstructions == true) {paragraph "Comparison offset trigger is used to increase the comparison humidity by a fixed value. This is added to the comparison sensors humidity value to provide a threshold value to trigger the fan. How much deviation from the comparison sensor do you want to trigger the fan? This will set the comparison sensor to be the threshold plus this offset."}
- input "compareHumiditySensorOffset", "decimal", title: "Comparison Offset Trigger, Range: 0-100, Default Value:10", required: true, submitOnChange:true, defaultValue: 10
+def mainPage() {
+ return dynamicPage(name: "mainPage", title: "", install: true, uninstall: true) {
+ if(!state.ShfInstalled) {
+ section("Hit Done to install Bathroom Humidity Fan App") {
+ }
}
+ else {
+ section("Create a new Bathroom Humidity Fan Instance.") {
+ app(name: "childApps", appName: "Bathroom Humidity Fan Child", namespace: "Craig.Romei", title: "New Bathroom Humidity Fan Instance", multiple: true)
+ }
+ section("Create a combined humidity sensor.") {
+ input "humidSensors", "capability.relativeHumidityMeasurement", title: "Select Humidity Sensors", submitOnChange: true, required: false, multiple: true
+ input name: "Create", type: "button", title: state.createCombinedSensorButtonName, submitOnChange:true, width: 5
+ if(humidSensors) paragraph "Current average is ${averageHumid()}%"
+ }
+ }
}
- section("Fan Activation"){
- if (detailedInstructions == true) {paragraph "Humidity increase rate: This checks the change between humidity samplings. The sampling rate is device dependent, room size also plays a large part in how fast the humidity will increase. Typical values are around 3 to 6."}
- if (settings.humidityResponseMethod?.contains("1") || settings.humidityResponseMethod?.contains("3")) {input "humidityIncreaseRate", "decimal", title: "Humidity Increase Rate, Range: 1-20, Default value: 3", required: true, defaultValue: 3}
- if (detailedInstructions == true) {paragraph "Humidity threshold: This is the trigger point when humidity goes above or below this value."}
- if (settings.humidityResponseMethod?.contains("2")) {input "humidityThreshold", "decimal", title: "Humidity Threshold (%), Range 1-100, Default Value: 65", required: false, defaultValue: 65}
- if (detailedInstructions == true) {paragraph "Fan on delay: When a trigger tries to turn on the fan, it will wait for this delay before kicking on."}
- input "fanOnDelay", "number", title: "Delay turning fan on (Minutes), Default Value: 0", required: false, defaultValue: 0
- }
- section("Fan Deactivation") {
- input "humidityDropTimeout", "number", title: "How long after the humidity returns to normal should the fan turn off (minutes)? Default Value: 10", required: true, defaultValue: 10
- if (humidityDropTimeout > 0) {input "humidityDropLimit", "decimal", title: "What percentage above the starting humidity before triggering the turn off delay? Default Value: 25", required: true, defaultValue: 25} else {humidityDropLimit = 0}
- input "maxRunTime", "number", title: "Maximum time (minutes) for Fan to run when automatically turned on. Default Value: 120", required: false, defaultValue: 120
- }
- section("Manual Activation") {
- input "manualControlMode", "enum", title: "When should the fan turn off when turned on manually?", submitOnChange:true, required: true, options: manualControlModeOptions, defaultValue: 2
- if (detailedInstructions == true) { paragraph "When the fan is manually turned on, wait this delay before turning off."}
- if (settings.manualControlMode?.contains("2")) {input "manualOffMinutes", "number", title: "How many minutes until the fan is auto-turned-off? Default Value: 20", submitOnChange:true, required: true, defaultValue: 20}
- }
- section(title: "Additional Features:", hideable: true, hidden: hideAdditionalFeaturesSection()) {
- input "deviceActivation", "capability.switch", title: "Switches to turn on and off the fan immediately.", submitOnChange:true, required:false, multiple:true
- paragraph ""
- input name: "CreateSmartSwitch", type: "button", title: state.createSmartSwitchButtonName, submitOnChange:true, width: 5
- paragraph "Create a virtual switch to keep lights on while the fan is running to use in other apps or rules."
- paragraph "Note: You can use an existing switch. The app will turn on and off this switch in sync with the fan."
- input "smartSwitch", "capability.switch", title: "${state.smartSwitchStatus}", required: false, submitOnChange:true
- }
- section(title: "Only Run When:", hideable: true, hidden: hideOptionsSection()) {
- def timeLabel = timeIntervalLabel()
- href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : null
- input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false, options: daysOptions
- input "modes", "mode", title: "Only when mode is", multiple: true, required: false
- input "disabledSwitch", "capability.switch", title: "Switch to Enable and Disable this app", submitOnChange:true, required:false, multiple:true
- }
- section(title: "Logging Options:", hideable: true, hidden: hideLoggingSection()) {
- if (detailedInstructions == true) {paragraph "Enable Info logging for 30 minutes will enable info logs to show up in the Hubitat logs for 30 minutes after which it will turn them off. Useful for checking if the app is performing actions as expected."}
- input "isInfo", "bool", title: "Enable Info logging for 30 minutes", submitOnChange: false, required:false, defaultValue: false
- if (detailedInstructions == true) {paragraph "Enable Debug logging for 30 minutes will enable debug logs to show up in the Hubitat logs for 30 minutes after which it will turn them off. Useful for troubleshooting problems."}
- input "isDebug", "bool", title: "Enable debug logging for 30 minutes", submitOnChange: false, required:false, defaultValue: false
- if (detailedInstructions == true) {paragraph "Enable Trace logging for 30 minutes will enable trace logs to show up in the Hubitat logs for 30 minutes after which it will turn them off. Useful for following the logic inside the application but usually not neccesary."}
- input "isTrace", "bool", title: "Enable Trace logging for 30 minutes", submitOnChange: false, required:false, defaultValue: false
- if (detailedInstructions == true) {paragraph "Logging level is used to permanantly set your logging level for the application. This is useful if you prefer you logging set to a low level and then can use the logging toggles for specific use cases so you dont have to remember to go back in and change them later. It's also useful if you are experiencing issues and need higher logging enabled for longer than 30 minutes."}
- input "ifLevel","enum", title: "Logging level", required: false, multiple: true, submitOnChange: false, options: logLevelOptions
- paragraph "NOTE: Logging level overrides the temporary logging selections."
- }
- }
}
-// Application settings and startup
-@Field static List