/** * * 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. * * Inverse Link Two Switches * * Author: kahn@lgk.com * * Date: 2015-11-08 */ /** * Inverse Link Two Switches Parent * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * Change History: * * ORIGINAL SOURCE * 2015 kahn@lgk.com no version * * Date Source Version What URL * ---- ------ ------- ---- --- * 2023-10-08 jshimota 0.1.0.1 My 'fork' of this driver taken from the above original source * 2023-10-08 jshimota 0.1.0.2 Initial edits to create reversal * 2023-10-08 jshimota 0.1.0.3 Updates to create HPM usability * 2023-10-08 jshimota 0.1.0.4 Split to a Parent / child app. * 2023-10-08 bturcott 0.1.0.5 Used Brians code to create basic Parent/child app as model * */ def setVersion(){ state.name = "Inverse Link Two Switches" state.version = "0.1.0.5" } import groovy.json.* import hubitat.helper.RMUtils import java.util.TimeZone import groovy.transform.Field import groovy.time.TimeCategory import java.text.SimpleDateFormat def checkHubVersion() { hubVersion = getHubVersion() hubFirmware = location.hub.firmwareVersionString if(txtEnabled) log.info "In checkHubVersion - Info: ${hubVersion} - ${hubFirware}" } def parentCheck(){ state.appInstalled = app.getInstallationState() if(state.appInstalled != 'COMPLETE'){ parentChild = true } else { parentChild = false } } def appControlSection() { input "pauseApp", "bool", title: "Pause App", defaultValue:false, submitOnChange:true if(pauseApp) { if(app.label) { if(!app.label.contains("(Paused)")) { app.updateLabel(app.label + " (Paused)") } } } else { if(app.label) { if(app.label.contains("(Paused)")) { app.updateLabel(app.label - " (Paused)") } } } if(pauseApp) { paragraph app.label } else { label title: "Enter a name for this automation", required:true, submitOnChange:true } } def uninstalled() { sendLocationEvent(name: "updateVersionInfo", value: "${app.id}:remove") removeChildDevices(getChildDevices()) } private removeChildDevices(delete) { delete.each {deleteChildDevice(it.deviceNetworkId)} } // ********** Normal Stuff ********** def logsOff() { if(txtEnabled) log.info "${app.label} - Debug logging auto disabled" app.updateSetting("txtEnabled",[value:"false",type:"bool"]) } def checkEnableHandler() { setVersion() state.eSwitch = false if(disableSwitch) { if(dbgEnabled) log.debug "In checkEnableHandler - disableSwitch: ${disableSwitch}" disableSwitch.each { it -> theStatus = it.currentValue("switch") if(theStatus == "on") { state.eSwitch = true } } if(dbgEnabled) log.debug "In checkEnableHandler - eSwitch: ${state.eSwitch}" } } def getImage(type) { // Modified from @Stephack Code def loc = "" if(type == "checkMarkGreen") return "${loc}checkMarkGreen2.png height=30 width=30>" if(type == "optionsGreen") return "${loc}options-green.png height=30 width=30>" if(type == "optionsRed") return "${loc}options-red.png height=30 width=30>" if(type == "instructions") return "${loc}instructions.png height=30 width=30>" if(type == "logo") return "${loc}logo.png height=40>" } def getFormat(type, myText=null, page=null) { // Modified code from @Stephack if(type == "header-green") return "
${myText}
" if(type == "line") return "
" if(type == "title") return "

${myText}

" if(type == "button-blue") return "${myText}" } def display(data) { if(data == null) data = "" if(app.label) { if(app.label.contains("(Paused)")) { theName = app.label - " (Paused)" } else { theName = app.label } } if(theName == null || theName == "") theName = "New Child App" if(!state.name) { state.name = "" } if(state.name == theName) { headerName = state.name } else { if(state.name == null || state.name == "") { headerName = "${theName}" } else { headerName = "${state.name} - ${theName}" } } } definition( name: "Inverse Link Two Switches", namespace: "jshimota", author: "James Shimota", description: "Based on the Link Two Switches by Larry Kahn, if one switch goes on, the other goes off and vice versa ", category: "Convenience", iconUrl: "", iconX2Url: "", iconX3Url: "", importUrl: "https://raw.githubusercontent.com/jshimota01/hubitat/main/Apps/inverse_link/inverse_link.groovy", ) preferences { page name: "mainPage", title: "", install: true, uninstall: true } def installed() { if(dbgEnabled) log.debug "Installed with settings: ${settings}" initialize() } def updated() { if(txtEnabled) log.info "Updated with settings: ${settings}" unsubscribe() initialize() } def initialize() { if(txtEnabled) log.info "There are ${childApps.size()} child apps" childApps.each {child -> if(txtEnabled) log.info "Child app: ${child.label}" } } def mainPage() { dynamicPage(name: "mainPage") { installCheck() if(state.appInstalled == 'COMPLETE'){ section("Instructions:", hideable: true, hidden: true) { paragraph "Information" paragraph "Connect two switches (real or virtual) that will always be opposite." } section(getFormat("header-green", "${getImage("Blank")}"+" Child Apps")) { app(name: "anyOpenApp", appName: "Inverse Link Two Switches Child", namespace: "jshimota", title: "Add a new 'Inverse Link Two Switches' child", multiple: true) } section(getFormat("header-green", "${getImage("Blank")}"+" General")) { label title: "Enter a name for parent app (optional)", required: false } section(getFormat("header-green", "${getImage("Blank")}"+" Logging")) { input "txtEnabled", "bool", title: "Enable Text Logging Option", description: "Debug Log Options", defaultValue:true, submitOnChange:true input "dbgEnabled", "bool", title: "Enable Debug Options", description: "Debug Log Options", defaultValue:false, submitOnChange:true if(dbgEnabled) { input "logOffTime", "enum", title: "Logs Off Time", required:false, multiple:false, options: ["1 Hour", "2 Hours", "3 Hours", "4 Hours", "5 Hours", "Keep On"] } paragraph "This app can be enabled/disabled by using a switch. The switch can also be used to enable/disable several apps at the same time." input "disableSwitch", "capability.switch", title: "Switch Device(s) to Enable / Disable this app (When selected switch is ON, app is disabled.)", submitOnChange:true, required:false, multiple:true } } } } def installCheck(){ display() state.appInstalled = app.getInstallationState() if(state.appInstalled != 'COMPLETE'){ section{paragraph "Please hit 'Done' to install '${app.label}' parent app "} } else{ if(dbgEnabled) log.debug "Parent Installed OK" } }