diff --git a/smartapps/bangali/rooms-child-app.src/rooms-child-app.groovy b/smartapps/bangali/rooms-child-app.src/rooms-child-app.groovy index aaec33e..ad2ce72 100644 --- a/smartapps/bangali/rooms-child-app.src/rooms-child-app.groovy +++ b/smartapps/bangali/rooms-child-app.src/rooms-child-app.groovy @@ -1508,7 +1508,14 @@ private pageAsleepSettings() { private pageLockedSettings() { dynamicPage(name: "pageLockedSettings", title: "", install: false, uninstall: false) { section("Switch configuration for LOCKED state:", hideable:false) { - input "lockedSwitch", "capability.switch", title: "Which switch turns ON?", required:false, multiple: false + input "lockedSwitch", "capability.switch", title: "This switch will Lock this room?", required:false, multiple: false, submitOnChange: true + if (lockedSwitch) { + input "lockedSwitchCmd", "enum", title: "...when it is turned...", options: [[on:"On"],[off:"Off"]], submitOnChange: true, required:false + } + input "lockedContact", "capability.contactSensor", title: "This contact will Lock this room?", required:false, multiple: false, submitOnChange: true + if (lockedContact) { + input "lockedContactCmd", "enum", title: "...when it is...", options: [[open:"Open"],[closed:"Closed"]], submitOnChange: true, required:false + } input "lockedTurnOff", "bool", title: "Turn off switches when room changes to LOCKED?", required: false, multiple: false, defaultValue: false input "unLocked", "number", title: "Timeout LOCKED state after how many hours?", required: false, multiple: false, defaultValue: null, range: "1..99" } @@ -1829,10 +1836,32 @@ def updateRoom(adjMotionSensors) { state.nightSetCT = (nightSetCT ? nightSetCT as Integer : null) state.noAsleep = ((noAsleep && noAsleep >= 1) ? (noAsleep * 60 * 60) : null) ifDebug("updateRoom 4") - if (lockedSwitch) { + +if (lockedContact) { + if (lockedContactCmd == "open") { + subscribe(lockedContact, "contact.open", lockedContactOpenEventHandler) + log.info "locked contact has opened with the command Open" + subscribe(lockedContact, "contact.closed", lockedContactClosedEventHandler) + log.info "locked contact has closed with the command Open" + } + if (lockedContactCmd == "closed") { + subscribe(lockedContact, "contact.open", lockedContactClosedEventHandler) + log.info "locked contact has opened with the command Closed" + subscribe(lockedContact, "contact.closed", lockedContactOpenEventHandler) + log.info "locked contact has closed with the command Closed" + } + } + +if (lockedSwitch) { + if (lockedSwitchCmd == "on") { subscribe(lockedSwitch, "switch.on", lockedSwitchOnEventHandler) - subscribe(lockedSwitch, "switch.off", lockedSwitchOffEventHandler) - } + subscribe(lockedSwitch, "switch.off", lockedSwitchOffEventHandler) + } + if (lockedSwitchCmd == "off") { + subscribe(lockedSwitch, "switch.off", lockedSwitchOnEventHandler) + subscribe(lockedSwitch, "switch.on", lockedSwitchOffEventHandler) + } + } if (windowShades) subscribe(windowShades, "windowShade", windowShadeEventHandler); if (roomFanSwitch) { subscribe(roomFanSwitch, "switch", updateFanIndP) @@ -1988,6 +2017,21 @@ private isAnyLSwitchOn() { return (lockedSwitch ? (lockedSwitch.currentSwitch.contains('on') ? 1 : 0) : -1) } +private isAnyLSwitchOff() { + ifDebug("isAnyLSwitchOff") + return (lockedSwitch ? (lockedSwitch.currentSwitch.contains('off') ? 1 : 0) : -1) +} + +private isAnyLContactOpen() { + ifDebug("isAnyLContactOpen") + return (lockedSwitch ? (lockedSwitch.currentSwitch.contains('on') ? 1 : 0) : -1) +} + +private isAnyLContactClosed() { + ifDebug("isAnyLContactClosed") + return (lockedSwitch ? (lockedSwitch.currentSwitch.contains('off') ? 1 : 0) : -1) +} + def updateRulesToState() { ifDebug("updateRulesToState") state.timeCheck = false @@ -2670,21 +2714,60 @@ def asleepSwitchOffEventHandler(evt) { } def lockedSwitchOnEventHandler(evt) { +log.info "lockedSwitchOnEventHandler has been called = On" ifDebug("lockedSwitchOnEventHandler") def child = getChildDevice(getRoom()) + if (lockedSwitchCmd == "on") { child.updateLSwitchInd(isAnyLSwitchOn()) + } + if (lockedSwitchCmd == "off") { + child.updateLSwitchInd(isAnyLSwitchOff()) + } if (!checkPauseModesAndDoW()) return; child.generateEvent(locked) } def lockedSwitchOffEventHandler(evt) { +log.info "lockedSwtichOffEventHandler has been called = Off" ifDebug("lockedSwitchOffEventHandler") def child = getChildDevice(getRoom()) + if (lockedSwitchCmd == "on") { child.updateLSwitchInd(isAnyLSwitchOn()) + } + if (lockedSwitchCmd == "off") { + child.updateLSwitchInd(isAnyLSwitchOff()) + } if (!checkPauseModesAndDoW()) return; if (child?.currentValue(occupancy) == locked) child.generateEvent(checking); } +def lockedContactOpenEventHandler(evt) { +log.info "lockedContactOpenEventHandler has been called = Open" + ifDebug("lockedContactOpenEventHandler") + def child = getChildDevice(getRoom()) + if (lockedContactCmd == "open") { + child.updateLContactInd(isAnyLContactOpen()) + } + if (lockedContactCmd == "closed") { + child.updateLContactInd(isAnyLContactClosed()) + } + if (!checkPauseModesAndDoW()) return; + child.generateEvent(locked) +} + +def lockedContactClosedEventHandler(evt) { +log.info "lockedContactClosedEventHandler has been called = Closed" + ifDebug("lockedContactClosedEventHandler") + def child = getChildDevice(getRoom()) + if (lockedContactCmd == "open") { + child.updateLContactInd(isAnyLContactOpen()) + } + if (lockedContactCmd == "closed") { + child.updateLContactInd(isAnyLContactClosed()) + } + if (!checkPauseModesAndDoW()) return; + if (child?.currentValue(occupancy) == locked) child.generateEvent(checking); +} /* def processCoolHeat() { diff --git a/smartapps/bangali/rooms-manager.src/rooms-manager.groovy b/smartapps/bangali/rooms-manager.src/rooms-manager.groovy index f63dbcd..29d8106 100644 --- a/smartapps/bangali/rooms-manager.src/rooms-manager.groovy +++ b/smartapps/bangali/rooms-manager.src/rooms-manager.groovy @@ -466,36 +466,40 @@ def pageSpeakerSettings() { if (i != j) sendNotification("Count of presense sensors and names do not match!", [method: "push"]); dynamicPage(name: "pageSpeakerSettings", title: "Speaker Settings", install: true, uninstall: true) { section("Speaker selection:") { + input "musicPlayers", "capability.musicPlayer", title: "Which Media Players?", required: false, multiple: true, submitOnChange: true + if (musicPlayers) { + input "volume", "number", title: "Temporarily change volume", description: "0-100% (default value = 30%)", required: false + } input "speakerDevices", "capability.audioNotification", title: "Which speakers?", required: false, multiple: true, submitOnChange: true input "speechDevices", "capability.speechSynthesis", title: "Which speech devices?\nlike lannounceer.", required: false, multiple: true, submitOnChange: true - if (speakerDevices || speechDevices) + if (speakerDevices || speechDevices || musicPlayers) input "speakerVolume", "number", title: "Speaker volume?", required: false, multiple: false, defaultValue: 33, range: "1..100" else paragraph "Speaker volume?\nselect speaker(s) to set." } - section("Annouce only between hours:") { - if ((speakerDevices || speechDevices)) { - input "startHH", "number", title: "Annouce from hour?", required: true, multiple: false, defaultValue: 7, range: "1..${endHH ? endHH : 23}", submitOnChange: true + section("Announce only between hours:") { + if ((speakerDevices || speechDevices || musicPlayers)) { + input "startHH", "number", title: "Announce from hour?", required: true, multiple: false, defaultValue: 7, range: "1..${endHH ? endHH : 23}", submitOnChange: true input "endHH", "number", title: "Announce to hour?", required: true, multiple: false, defaultValue: 7, range: "${startHH ? startHH : 23}..23", submitOnChange: true } else { - paragraph "Announce from hour?\nselect either presence or time annoucement to set" - paragraph "Announce to hour?\nselect either presence or time annoucement to set" + paragraph "Announce from hour?\nselect either presence or time announcement to set" + paragraph "Announce to hour?\nselect either presence or time announcement to set" } } section("Time announcement:") { - if (speakerDevices || speechDevices) + if (speakerDevices || speechDevices || musicPlayers) input "timeAnnounce", "enum", title: "Announce time?", required: false, multiple: false, defaultValue: 4, options: [[1:"Every 15 minutes"], [2:"Every 30 minutes"], [3:"Every hour"], [4:"No"]], submitOnChange: true else paragraph "Announce time?\nselect speaker devices to set." } - section("Arrival and departure annoucement:") { - if (speakerDevices || speechDevices) + section("Arrival and departure announcement:") { + if (speakerDevices || speechDevices || musicPlayers) input "speakerAnnounce", "bool", title: "Announce when presence sensors arrive or depart?", required: false, multiple: false, defaultValue: false, submitOnChange: true else paragraph "Announce when presence sensors arrive or depart?\nselect speaker(s) to set." - if ((speakerDevices || speechDevices) && speakerAnnounce) { + if ((speakerDevices || speechDevices || musicPlayers) && speakerAnnounce) { input "presenceSensors", "capability.presenceSensor", title: "Which presence snesors?", required: true, multiple: true input "presenceNames", "text", title: "Comma delmited names? (in sequence of presence sensors)", required: true, multiple: false, submitOnChange: true input "contactSensors", "capability.contactSensor", title: "Which contact sensors? (welcome home greeting is played after this contact sensor closes.)", @@ -522,7 +526,7 @@ def pageSpeakerSettings() { } } section("Battery status:") { - if (speakerDevices || speechDevices) + if (speakerDevices || speechDevices || musicPlayers) input "batteryTime", "time", title: "Annouce battery status when?", required: false, multiple: false, submitOnChange: true else paragraph "Annouce battery status when?\nselect either speakers or speech device to set" @@ -589,7 +593,7 @@ private announceSetup() { state.welcomeHome1 = [:] state.welcomeHome2 = [:] state.welcomeHomeCloser = [:] - str = welcomeHome.split(',') + str = welcomeHome.split('/') i = 0 str.each { def str2 = it.split('&') @@ -598,7 +602,7 @@ private announceSetup() { i = i + 1 } if (welcomeHomeCloser) { - str = welcomeHomeCloser.split(',') + str = welcomeHomeCloser.split('/') i = 0 str.each { state.welcomeHomeCloser[i] = it @@ -608,7 +612,7 @@ private announceSetup() { state.leftHome1 = [:] state.leftHome2 = [:] state.leftHomeCloser = [:] - str = leftHome.split(',') + str = leftHome.split('/') i = 0 str.each { def str2 = it.split('&') @@ -617,7 +621,7 @@ private announceSetup() { i = i + 1 } if (leftHomeCloser) { - str = leftHomeCloser.split(',') + str = leftHomeCloser.split('/') i = 0 str.each { state.leftHomeCloser[i] = it @@ -672,7 +676,7 @@ def contactClosedEventHandler(evt = null) { // ifDebug("k: $k ${state.welcomeHome1[(k)]} | l: $l ${state.leftHome1[(l)]}") def persons = (evt ? state.welcomeHome1[(k)] : state.leftHome1[(l)]) + ' ' str.each { - persons = persons + (j != 1 ? (j == i ? ' and ' : ', ') : '') + it + persons = persons + (j != 1 ? (j == i ? ' and ' : '/ ') : '') + it j = j + 1 } persons = persons + ' ' + (evt ? state.welcomeHome2[(k)] : state.leftHome2[(l)]) + @@ -680,18 +684,39 @@ def contactClosedEventHandler(evt = null) { (leftHomeCloser ? state.leftHomeCloser[(l2)] : '')) + '.' // ifDebug("k: $k ${state.welcomeHome2[(k)]} | l: $l ${state.leftHome2[(l)]}") ifDebug("message: $persons") - speakIt(persons) + speakIt(str, persons) if (evt) state.whoCameHome.personsIn = []; else state.whoCameHome.personsOut = []; } -private speakIt(string) { +private speakIt(str, persons) { def nowDate = new Date(now()) def intCurrentHH = nowDate.format("HH", location.timeZone) as Integer def intCurrentMM = nowDate.format("mm", location.timeZone) as Integer if (intCurrentHH >= startHH && (intCurrentHH < endHH || (intCurrentHH == endHH && intCurrentMM == 0))) { - if (speakerDevices) speakerDevices.playTextAndResume(persons, speakerVolume); - if (speechDevices) speechDevices.speak(persons); + if (speakerDevices) speakerDevices.playTextAndResume(str, speakerVolume); + if (speechDevices) speechDevices.speak(str); +// if (musicPlayers) musicPlayers.speak(persons); + if (persons) { + state.sound = textToSpeech(persons instanceof List ? persons[9] : persons) + } + else { + state.sound = textToSpeech("You selected the custom message option but did not enter a message in the $app.label Smart App") + log.debug "You selected the custom message option but did not enter a message" + } + if (musicPlayers) { + def currVolLevel = musicPlayers.latestValue("level") + def currMuteOn = musicPlayers.latestValue("mute").contains("muted") + log.debug "currVolSwitchOff = ${currVolSwitchOff}, vol level = ${currVolLevel}, currMuteOn = ${currMuteOn} " + if (currMuteOn) { + log.warn "speaker is on mute, sending unmute command" + musicPlayers.unmute() + } + def sVolume = settings.volume ?: 30 + musicPlayers?.playTrackAndResume(state.sound.uri, state.sound.duration, sVolume) + log.info "Playing message on the music player '${musicPlayers}' at volume '${volume}'" + }; + } }