mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-13 05:11:51 +00:00
Compare commits
9 Commits
MSA-2099-1
...
MSA-2118-8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ca07ce9db | ||
|
|
de5f0683d3 | ||
|
|
36e63133fc | ||
|
|
838c466312 | ||
|
|
97bfe61baa | ||
|
|
34df40d5b4 | ||
|
|
545be046f0 | ||
|
|
a5041e0fcb | ||
|
|
771926c337 |
@@ -27,13 +27,9 @@ Works with:
|
||||
## Device Health
|
||||
|
||||
Aeon Labs MultiSensor 6 is polled by the hub.
|
||||
As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed.
|
||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
|
||||
Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for
|
||||
the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row,
|
||||
it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time.
|
||||
Aeon MultiSensor reports in once every hour.
|
||||
|
||||
* __32min__ checkInterval
|
||||
* __122min__ checkInterval
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -130,13 +130,13 @@ metadata {
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
// Device-Watch simply pings if no device events received for 122min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
// Device-Watch simply pings if no device events received for 122min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
log.debug "${device.displayName} is now ${device.latestValue("powerSupply")}"
|
||||
|
||||
|
||||
@@ -171,8 +171,8 @@ private Map getBatteryResult(rawValue) {
|
||||
def pct = batteryMap[volts]
|
||||
result.value = pct
|
||||
} else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def minVolts = 2.4
|
||||
def maxVolts = 2.7
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
|
||||
@@ -274,7 +274,7 @@ private Map getBatteryResult(rawValue) {
|
||||
result.value = pct
|
||||
} else {
|
||||
def minVolts = 2.1
|
||||
def maxVolts = 3.0
|
||||
def maxVolts = 2.7
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
|
||||
@@ -15,10 +15,9 @@ metadata {
|
||||
definition (name: "Z-Wave Thermostat", namespace: "smartthings", author: "SmartThings") {
|
||||
capability "Actuator"
|
||||
capability "Temperature Measurement"
|
||||
capability "Relative Humidity Measurement"
|
||||
capability "Thermostat"
|
||||
capability "Configuration"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
capability "Health Check"
|
||||
|
||||
@@ -117,7 +116,7 @@ metadata {
|
||||
state "cool", label:'${currentValue}° cool', backgroundColor:"#ffffff"
|
||||
}
|
||||
standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
|
||||
state "default", action:"polling.poll", icon:"st.secondary.refresh"
|
||||
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||
}
|
||||
main "temperature"
|
||||
details(["temperature", "mode", "fanMode", "heatSliderControl", "heatingSetpoint", "coolSliderControl", "coolingSetpoint", "refresh"])
|
||||
@@ -125,13 +124,20 @@ metadata {
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
sendHubCommand(new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSupportedGet().format()))
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated(){
|
||||
initialize()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
unschedule()
|
||||
runEvery5Minutes("refresh")
|
||||
refresh()
|
||||
}
|
||||
|
||||
def parse(String description)
|
||||
@@ -149,6 +155,7 @@ def parse(String description)
|
||||
]
|
||||
if (map.name == "thermostatMode") {
|
||||
state.lastTriedMode = map.value
|
||||
map.data = [supportedThermostatModes:state.supportedThermostatModes]
|
||||
if (map.value == "cool") {
|
||||
map2.value = device.latestValue("coolingSetpoint")
|
||||
log.info "THERMOSTAT, latest cooling setpoint = ${map2.value}"
|
||||
@@ -172,6 +179,7 @@ def parse(String description)
|
||||
}
|
||||
} else if (map.name == "thermostatFanMode" && map.isStateChange) {
|
||||
state.lastTriedFanMode = map.value
|
||||
map.data = [supportedThermostatFanModes: state.supportedThermostatFanModes]
|
||||
}
|
||||
log.debug "Parse returned $result"
|
||||
result
|
||||
@@ -305,26 +313,26 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanMod
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) {
|
||||
def supportedModes = ""
|
||||
if(cmd.off) { supportedModes += "off " }
|
||||
if(cmd.heat) { supportedModes += "heat " }
|
||||
if(cmd.auxiliaryemergencyHeat) { supportedModes += "emergency heat " }
|
||||
if(cmd.cool) { supportedModes += "cool " }
|
||||
if(cmd.auto) { supportedModes += "auto " }
|
||||
def supportedModes = []
|
||||
if(cmd.off) { supportedModes << "off" }
|
||||
if(cmd.heat) { supportedModes << "heat" }
|
||||
if(cmd.cool) { supportedModes << "cool" }
|
||||
if(cmd.auto) { supportedModes << "auto" }
|
||||
if(cmd.auxiliaryemergencyHeat) { supportedModes << "emergency heat" }
|
||||
|
||||
state.supportedModes = supportedModes
|
||||
// No events to be generated, return empty map
|
||||
state.supportedThermostatModes = supportedModes
|
||||
sendEvent(name: "supportedThermostatModes", value: supportedModes, displayed: false)
|
||||
return [:]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
|
||||
def supportedFanModes = ""
|
||||
if(cmd.auto) { supportedFanModes += "auto " } // "fanAuto "
|
||||
if(cmd.low) { supportedFanModes += "on " } // "fanOn"
|
||||
if(cmd.circulation) { supportedFanModes += "circulate " } // "fanCirculate"
|
||||
def supportedFanModes = []
|
||||
if(cmd.auto) { supportedFanModes << "auto" } // "fanAuto "
|
||||
if(cmd.circulation) { supportedFanModes << "circulate" } // "fanCirculate"
|
||||
if(cmd.low) { supportedFanModes << "on" } // "fanOn"
|
||||
|
||||
state.supportedFanModes = supportedFanModes
|
||||
// No events to be generated, return empty map
|
||||
state.supportedThermostatFanModes = supportedFanModes
|
||||
sendEvent(name: "supportedThermostatFanModes", value: supportedFanModes, displayed: false)
|
||||
return [:]
|
||||
}
|
||||
|
||||
@@ -337,15 +345,17 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
}
|
||||
|
||||
// Command Implementations
|
||||
def poll() {
|
||||
delayBetween([
|
||||
zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature
|
||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
|
||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format(),
|
||||
zwave.thermostatModeV2.thermostatModeGet().format(),
|
||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format(),
|
||||
zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
|
||||
], 2300)
|
||||
def refresh() {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSupportedGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.sensorMultilevelV2.sensorMultilevelGet().format()) // current temperature
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
def quickSetHeat(degrees) {
|
||||
@@ -416,28 +426,14 @@ def ping() {
|
||||
poll()
|
||||
}
|
||||
|
||||
def configure() {
|
||||
delayBetween([
|
||||
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
|
||||
zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format(),
|
||||
zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format(),
|
||||
zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature
|
||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
|
||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format(),
|
||||
zwave.thermostatModeV2.thermostatModeGet().format(),
|
||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format(),
|
||||
zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
|
||||
], 2300)
|
||||
}
|
||||
|
||||
def modes() {
|
||||
["off", "heat", "cool", "auto", "emergency heat"]
|
||||
return state.supportedThermostatModes
|
||||
}
|
||||
|
||||
def switchMode() {
|
||||
def currentMode = device.currentState("thermostatMode")?.value
|
||||
def lastTriedMode = state.lastTriedMode ?: currentMode ?: "off"
|
||||
def supportedModes = getDataByName("supportedModes")
|
||||
def lastTriedMode = state.lastTriedMode ?: currentMode ?: ["off"]
|
||||
def supportedModes = getDataByName("supportedThermostatModes")
|
||||
def modeOrder = modes()
|
||||
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
|
||||
def nextMode = next(lastTriedMode)
|
||||
@@ -454,7 +450,7 @@ def switchMode() {
|
||||
}
|
||||
|
||||
def switchToMode(nextMode) {
|
||||
def supportedModes = getDataByName("supportedModes")
|
||||
def supportedModes = getDataByName("supportedThermostatModes")
|
||||
if(supportedModes && !supportedModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
|
||||
if (nextMode in modes()) {
|
||||
state.lastTriedMode = nextMode
|
||||
@@ -466,9 +462,9 @@ def switchToMode(nextMode) {
|
||||
|
||||
def switchFanMode() {
|
||||
def currentMode = device.currentState("thermostatFanMode")?.value
|
||||
def lastTriedMode = state.lastTriedFanMode ?: currentMode ?: "off"
|
||||
def supportedModes = getDataByName("supportedFanModes") ?: "auto on" // "fanAuto fanOn"
|
||||
def modeOrder = ["auto", "circulate", "on"] // "fanAuto", "fanCirculate", "fanOn"
|
||||
def lastTriedMode = state.lastTriedFanMode ?: currentMode ?: ["off"]
|
||||
def supportedModes = getDataByName("supportedThermostatFanModes") ?: ["auto", "on"]
|
||||
def modeOrder = state.supportedThermostatFanModes
|
||||
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
|
||||
def nextMode = next(lastTriedMode)
|
||||
while (!supportedModes?.contains(nextMode) && nextMode != "auto") { // "fanAuto"
|
||||
@@ -478,7 +474,7 @@ def switchFanMode() {
|
||||
}
|
||||
|
||||
def switchToFanMode(nextMode) {
|
||||
def supportedFanModes = getDataByName("supportedFanModes")
|
||||
def supportedFanModes = getDataByName("supportedThermostatFanModes")
|
||||
if(supportedFanModes && !supportedFanModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
|
||||
|
||||
def returnCommand
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
* Leak Detector for FortrezZ Water Meter
|
||||
*
|
||||
* Copyright 2016 Daniel Kurin
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "FortrezZ Leak Detector",
|
||||
namespace: "fortrezz",
|
||||
author: "FortrezZ, LLC",
|
||||
description: "Use the FortrezZ Water Meter to identify leaks in your home's water system.",
|
||||
category: "Green Living",
|
||||
iconUrl: "http://swiftlet.technology/wp-content/uploads/2016/05/logo-square-200-1.png",
|
||||
iconX2Url: "http://swiftlet.technology/wp-content/uploads/2016/05/logo-square-500.png",
|
||||
iconX3Url: "http://swiftlet.technology/wp-content/uploads/2016/05/logo-square.png")
|
||||
|
||||
|
||||
preferences {
|
||||
page(name: "page2", title: "Select device and actions", install: true, uninstall: true)
|
||||
}
|
||||
|
||||
def page2() {
|
||||
dynamicPage(name: "page2") {
|
||||
section("Choose a water meter to monitor:") {
|
||||
input(name: "meter", type: "capability.energyMeter", title: "Water Meter", description: null, required: true, submitOnChange: true)
|
||||
}
|
||||
|
||||
if (meter) {
|
||||
section {
|
||||
app(name: "childRules", appName: "Leak Detector", namespace: "fortrezz", title: "Create New Leak Detector...", multiple: true)
|
||||
}
|
||||
}
|
||||
|
||||
section("Send notifications through...") {
|
||||
input(name: "pushNotification", type: "bool", title: "SmartThings App", required: false)
|
||||
input(name: "smsNotification", type: "bool", title: "Text Message (SMS)", submitOnChange: true, required: false)
|
||||
if (smsNotification)
|
||||
{
|
||||
input(name: "phone", type: "phone", title: "Phone number?", required: true)
|
||||
}
|
||||
input(name: "minutesBetweenNotifications", type: "number", title: "Minutes between notifications", required: true, defaultValue: 60)
|
||||
}
|
||||
|
||||
log.debug "there are ${childApps.size()} child smartapps"
|
||||
def childRules = []
|
||||
childApps.each {child ->
|
||||
//log.debug "child ${child.id}: ${child.settings()}"
|
||||
childRules << [id: child.id, rules: child.settings()]
|
||||
}
|
||||
state.rules = childRules
|
||||
//log.debug("Child Rules: ${state.rules} w/ length ${state.rules.toString().length()}")
|
||||
log.debug "Parent Settings: ${settings}"
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
|
||||
unsubscribe()
|
||||
initialize()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
subscribe(meter, "cumulative", cumulativeHandler)
|
||||
subscribe(meter, "gpm", gpmHandler)
|
||||
log.debug("Subscribing to events")
|
||||
}
|
||||
|
||||
def cumulativeHandler(evt) {
|
||||
//Date Stuff
|
||||
def daysOfTheWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
||||
def today = new Date()
|
||||
today.clearTime()
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(today);
|
||||
int dow = c.get(Calendar.DAY_OF_WEEK);
|
||||
def dowName = daysOfTheWeek[dow-1]
|
||||
|
||||
def gpm = meter.latestValue("gpm")
|
||||
def cumulative = new BigDecimal(evt.value)
|
||||
log.debug "Cumulative Handler: [gpm: ${gpm}, cumulative: ${cumulative}]"
|
||||
def rules = state.rules
|
||||
rules.each { it ->
|
||||
def r = it.rules
|
||||
def childAppID = it.id
|
||||
//log.debug("Rule: ${r}")
|
||||
switch (r.type) {
|
||||
case "Mode":
|
||||
log.debug("Mode Test: ${location.currentMode} in ${r.modes}... ${findIn(r.modes, location.currentMode)}")
|
||||
if (findIn(r.modes, location.currentMode))
|
||||
{
|
||||
log.debug("Threshold:${r.gpm}, Value:${gpm}")
|
||||
if(gpm > r.gpm)
|
||||
{
|
||||
sendNotification(childAppID, gpm)
|
||||
if(r.dev)
|
||||
{
|
||||
//log.debug("Child App: ${childAppID}")
|
||||
def activityApp = getChildById(childAppID)
|
||||
activityApp.devAction(r.command)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Time Period":
|
||||
log.debug("Time Period Test: ${r}")
|
||||
def boolTime = timeOfDayIsBetween(r.startTime, r.endTime, new Date(), location.timeZone)
|
||||
def boolDay = !r.days || findIn(r.days, dowName) // Truth Table of this mess: http://swiftlet.technology/wp-content/uploads/2016/05/IMG_20160523_150600.jpg
|
||||
def boolMode = !r.modes || findIn(r.modes, location.currentMode)
|
||||
|
||||
if(boolTime && boolDay && boolMode)
|
||||
{
|
||||
if(gpm > r.gpm)
|
||||
{
|
||||
sendNotification(childAppID, gpm)
|
||||
if(r.dev)
|
||||
{
|
||||
def activityApp = getChildById(childAppID)
|
||||
activityApp.devAction(r.command)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Accumulated Flow":
|
||||
log.debug("Accumulated Flow Test: ${r}")
|
||||
def boolTime = timeOfDayIsBetween(r.startTime, r.endTime, new Date(), location.timeZone)
|
||||
def boolDay = !r.days || findIn(r.days, dowName) // Truth Table of this mess: http://swiftlet.technology/wp-content/uploads/2016/05/IMG_20160523_150600.jpg
|
||||
def boolMode = !r.modes || findIn(r.modes, location.currentMode)
|
||||
|
||||
if(boolTime && boolDay && boolMode)
|
||||
{
|
||||
def delta = 0
|
||||
if(state["accHistory${childAppID}"] != null)
|
||||
{
|
||||
delta = cumulative - state["accHistory${childAppID}"]
|
||||
}
|
||||
else
|
||||
{
|
||||
state["accHistory${childAppID}"] = cumulative
|
||||
}
|
||||
log.debug("Currently in specified time, delta from beginning of time period: ${delta}")
|
||||
|
||||
if(delta > r.gallons)
|
||||
{
|
||||
sendNotification(childAppID, delta)
|
||||
if(r.dev)
|
||||
{
|
||||
def activityApp = getChildById(childAppID)
|
||||
activityApp.devAction(r.command)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("Outside specified time, saving value")
|
||||
state["accHistory${childAppID}"] = cumulative
|
||||
}
|
||||
break
|
||||
|
||||
case "Continuous Flow":
|
||||
log.debug("Continuous Flow Test: ${r}")
|
||||
def contMinutes = 0
|
||||
def boolMode = !r.modes || findIn(r.modes, location.currentMode)
|
||||
|
||||
if(gpm != 0)
|
||||
{
|
||||
if(state["contHistory${childAppID}"] == [])
|
||||
{
|
||||
state["contHistory${childAppID}"] = new Date()
|
||||
}
|
||||
else
|
||||
{
|
||||
//def td = now() - Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", state["contHistory${childAppID}"]).getTime()
|
||||
//log.debug(state["contHistory${childAppID}"])
|
||||
//def historyDate = new Date(state["contHistory${childAppID}"])
|
||||
def historyDate = new Date().parse("yyyy-MM-dd'T'HH:mm:ssZ", state["contHistory${childAppID}"])
|
||||
def td = now() - historyDate.getTime()
|
||||
//log.debug("Now minus then: ${td}")
|
||||
contMinutes = td/60000
|
||||
log.debug("Minutes of constant flow: ${contMinutes}, since ${state["contHistory${childAppID}"]}")
|
||||
}
|
||||
}
|
||||
|
||||
if(contMinutes > r.flowMinutes && boolMode)
|
||||
{
|
||||
sendNotification(childAppID, Math.round(contMinutes))
|
||||
if(r.dev)
|
||||
{
|
||||
def activityApp = getChildById(childAppID)
|
||||
activityApp.devAction(r.command)
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Water Valve Status":
|
||||
log.debug("Water Valve Test: ${r}")
|
||||
def child = getChildById(childAppID)
|
||||
//log.debug("Water Valve Child App: ${child.id}")
|
||||
if(child.isValveStatus(r.valveStatus))
|
||||
{
|
||||
if(gpm > r.gpm)
|
||||
{
|
||||
sendNotification(childAppID, gpm)
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Switch Status":
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def gpmHandler(evt) {
|
||||
//Date Stuff
|
||||
def daysOfTheWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
||||
def today = new Date()
|
||||
today.clearTime()
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(today);
|
||||
int dow = c.get(Calendar.DAY_OF_WEEK);
|
||||
def dowName = daysOfTheWeek[dow-1]
|
||||
|
||||
def gpm = evt.value
|
||||
def cumulative = meter.latestValue("cumulative")
|
||||
log.debug "GPM Handler: [gpm: ${gpm}, cumulative: ${cumulative}]"
|
||||
def rules = state.rules
|
||||
rules.each { it ->
|
||||
def r = it.rules
|
||||
def childAppID = it.id
|
||||
switch (r.type) {
|
||||
|
||||
// This is down here because "cumulative" never gets sent in the case of 0 change between messages
|
||||
case "Continuous Flow":
|
||||
log.debug("Continuous Flow Test (GPM): ${r}")
|
||||
def contMinutes = 0
|
||||
|
||||
if(gpm == "0.0")
|
||||
{
|
||||
state["contHistory${childAppID}"] = []
|
||||
}
|
||||
//log.debug("contHistory${childAppID} is ${state["contHistory${childAppID}"]}")
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
def sendNotification(device, gpm)
|
||||
{
|
||||
def set = getChildById(device).settings()
|
||||
def msg = ""
|
||||
if(set.type == "Accumulated Flow")
|
||||
{
|
||||
msg = "Water Flow Warning: \"${set.ruleName}\" is over threshold at ${gpm} gallons"
|
||||
}
|
||||
else if(set.type == "Continuous Flow")
|
||||
{
|
||||
msg = "Water Flow Warning: \"${set.ruleName}\" is over threshold at ${gpm} minutes"
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Water Flow Warning: \"${set.ruleName}\" is over threshold at ${gpm}gpm"
|
||||
}
|
||||
log.debug(msg)
|
||||
|
||||
// Only send notifications as often as the user specifies
|
||||
def lastNotification = 0
|
||||
if(state["notificationHistory${device}"])
|
||||
{
|
||||
lastNotification = Date.parse("yyyy-MM-dd'T'HH:mm:ssZ", state["notificationHistory${device}"]).getTime()
|
||||
}
|
||||
def td = now() - lastNotification
|
||||
log.debug("Last Notification at ${state["notificationHistory${device}"]}... ${td/(60*1000)} minutes")
|
||||
if(td/(60*1000) > minutesBetweenNotifications.value)
|
||||
{
|
||||
log.debug("Sending Notification")
|
||||
if (pushNotification)
|
||||
{
|
||||
sendPush(msg)
|
||||
state["notificationHistory${device}"] = new Date()
|
||||
}
|
||||
if (smsNotification)
|
||||
{
|
||||
sendSms(phone, msg)
|
||||
state["notificationHistory${device}"] = new Date()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getChildById(app)
|
||||
{
|
||||
return childApps.find{ it.id == app }
|
||||
}
|
||||
|
||||
def findIn(haystack, needle)
|
||||
{
|
||||
def result = false
|
||||
haystack.each { it ->
|
||||
//log.debug("findIn: ${it} <- ${needle}")
|
||||
if (needle == it)
|
||||
{
|
||||
//log.debug("Found needle in haystack")
|
||||
result = true
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
243
smartapps/fortrezz/leak-detector.src/leak-detector.groovy
Normal file
243
smartapps/fortrezz/leak-detector.src/leak-detector.groovy
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Leak Detector
|
||||
*
|
||||
* Copyright 2016 Daniel Kurin
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "Leak Detector",
|
||||
namespace: "fortrezz",
|
||||
author: "FortrezZ, LLC",
|
||||
description: "Child SmartApp for leak detector rules",
|
||||
category: "Green Living",
|
||||
parent: "fortrezz:FortrezZ Leak Detector",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
|
||||
|
||||
|
||||
preferences {
|
||||
page(name: "prefsPage", title: "Choose the detector behavior", install: true, uninstall: true)
|
||||
|
||||
// Do something here like update a message on the screen,
|
||||
// or introduce more inputs. submitOnChange will refresh
|
||||
// the page and allow the user to see the changes immediately.
|
||||
// For example, you could prompt for the level of the dimmers
|
||||
// if dimmers have been selected:
|
||||
//log.debug "Child Settings: ${settings}"
|
||||
}
|
||||
|
||||
def prefsPage() {
|
||||
def daysOfTheWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
||||
dynamicPage(name: "prefsPage") {
|
||||
section("Set Leak Threshold by...") {
|
||||
input(name: "type", type: "enum", title: "Type...", submitOnChange: true, options: ruleTypes())
|
||||
}
|
||||
|
||||
if(type)
|
||||
{
|
||||
switch (type) {
|
||||
case "Mode":
|
||||
section("Threshold settings") {
|
||||
input(name: "ruleName", type: "text", title: "Rule Name", required: true)
|
||||
input(name: "gpm", type: "decimal", title: "GPM exceeds", required: true, defaultValue: 0.1)
|
||||
}
|
||||
section("Only in these modes") {
|
||||
input(name: "modes", type: "mode", title: "select a mode(s)", multiple: true, required: true)
|
||||
}
|
||||
section ("Action") {
|
||||
input(name: "dev", type: "capability.actuator", title: "Choose a device to perform the action", required: false, submitOnChange: true)
|
||||
if (dev) {
|
||||
input(name: "command", type: "enum", title: "Command...", submitOnChange: true, options: deviceCommands(dev))
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Time Period":
|
||||
section("Threshold settings") {
|
||||
input(name: "ruleName", type: "text", title: "Rule Name", required: true)
|
||||
input(name: "gpm", type: "decimal", title: "GPM exceeds", required: true)
|
||||
}
|
||||
section("Between...") {
|
||||
input(name: "startTime", type: "time", title: "Start Time", required: true)
|
||||
}
|
||||
section("...and...") {
|
||||
input(name: "endTime", type: "time", title: "End Time", required: true)
|
||||
}
|
||||
section("Only on these days") {
|
||||
input(name: "days", type: "enum", title: "Days of the week", required: false, options: daysOfTheWeek, multiple: true)
|
||||
}
|
||||
section("Only in these modes") {
|
||||
input(name: "modes", type: "mode", title: "System Modes", required: false, multiple: true)
|
||||
}
|
||||
section ("Action") {
|
||||
input(name: "dev", type: "capability.actuator", title: "Choose a device to perform the action", required: false, submitOnChange: true)
|
||||
if (dev) {
|
||||
input(name: "command", type: "enum", title: "Command...", submitOnChange: true, options: deviceCommands(dev))
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Accumulated Flow":
|
||||
section("Threshold settings") {
|
||||
input(name: "ruleName", type: "text", title: "Rule Name", required: true)
|
||||
input(name: "gallons", type: "number", title: "Total Gallons exceeds", required: true)
|
||||
}
|
||||
section("Between...") {
|
||||
input(name: "startTime", type: "time", title: "Start Time", required: true)
|
||||
}
|
||||
section("...and...") {
|
||||
input(name: "endTime", type: "time", title: "End Time", required: true)
|
||||
}
|
||||
section("Only on these days") {
|
||||
input(name: "days", type: "enum", title: "Days of the week", required: false, options: daysOfTheWeek, multiple: true)
|
||||
}
|
||||
section("Only in these modes") {
|
||||
input(name: "modes", type: "mode", title: "System Modes", required: false, multiple: true)
|
||||
}
|
||||
section ("Action") {
|
||||
input(name: "dev", type: "capability.actuator", title: "Choose a device to perform the action", required: false, submitOnChange: true)
|
||||
if (dev) {
|
||||
input(name: "command", type: "enum", title: "Command...", submitOnChange: true, options: deviceCommands(dev))
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Continuous Flow":
|
||||
section("Threshold settings") {
|
||||
input(name: "ruleName", type: "text", title: "Rule Name", required: true)
|
||||
input(name: "flowMinutes", type: "number", title: "Minutes of constant flow", required: true, defaultValue: 60)
|
||||
}
|
||||
section("Only in these modes") {
|
||||
input(name: "modes", type: "mode", title: "System Modes", required: false, multiple: true)
|
||||
}
|
||||
section ("Action") {
|
||||
input(name: "dev", type: "capability.actuator", title: "Choose a device to perform the action", required: false, submitOnChange: true)
|
||||
if (dev) {
|
||||
input(name: "command", type: "enum", title: "Command...", submitOnChange: true, options: deviceCommands(dev))
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case "Water Valve Status":
|
||||
section("Threshold settings") {
|
||||
input(name: "ruleName", type: "text", title: "Rule Name", required: true)
|
||||
input(name: "gpm", type: "decimal", title: "GPM exceeds", required: true, defaultValue: 0.1)
|
||||
}
|
||||
section ("While...") {
|
||||
input(name: "valve", type: "capability.valve", title: "Choose a valve", required: true)
|
||||
}
|
||||
section ("...is...") {
|
||||
input(name: "valveStatus", type: "enum", title: "Status", options: ["Open","Closed"], required: true)
|
||||
}
|
||||
break
|
||||
|
||||
case "Switch Status":
|
||||
section("Threshold settings") {
|
||||
input(name: "ruleName", type: "text", title: "Rule Name", required: true)
|
||||
input(name: "gpm", type: "decimal", title: "GPM exceeds", required: true, defaultValue: 0.1)
|
||||
}
|
||||
section ("If...") {
|
||||
input(name: "valve", type: "capability.switch", title: "Choose a switch", required: true)
|
||||
}
|
||||
section ("...is...") {
|
||||
input(name: "switchStatus", type: "enum", title: "Status", options: ["On","Off"], required: true)
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def ruleTypes() {
|
||||
def types = []
|
||||
types << "Mode"
|
||||
types << "Time Period"
|
||||
types << "Accumulated Flow"
|
||||
types << "Continuous Flow"
|
||||
types << "Water Valve Status"
|
||||
//types << "Switch Status"
|
||||
|
||||
return types
|
||||
}
|
||||
|
||||
def actionTypes() {
|
||||
def types = []
|
||||
types << [name: "Switch", capability: "capabilty.switch"]
|
||||
types << [name: "Water Valve", capability: "capability.valve"]
|
||||
|
||||
return types
|
||||
}
|
||||
|
||||
def deviceCommands(dev)
|
||||
{
|
||||
def cmds = []
|
||||
dev.supportedCommands.each { command ->
|
||||
cmds << command.name
|
||||
}
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
app.updateLabel("${ruleName ? ruleName : ""} - ${type}")
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
app.updateLabel("${ruleName ? ruleName : ""} - ${type}")
|
||||
|
||||
unsubscribe()
|
||||
initialize()
|
||||
}
|
||||
|
||||
def settings() {
|
||||
def set = settings
|
||||
if (set["dev"] != null)
|
||||
{
|
||||
log.debug("dev set: ${set.dev}")
|
||||
set.dev = set.dev.id
|
||||
}
|
||||
if (set["valve"] != null)
|
||||
{
|
||||
log.debug("valve set: ${set.valve}")
|
||||
set.valve = set.valve.id
|
||||
}
|
||||
log.debug(set)
|
||||
return set
|
||||
}
|
||||
|
||||
def devAction(action)
|
||||
{
|
||||
if(dev)
|
||||
{
|
||||
log.debug("device: ${dev}, action: ${action}")
|
||||
dev."${action}"()
|
||||
}
|
||||
}
|
||||
|
||||
def isValveStatus(status)
|
||||
{
|
||||
def result = false
|
||||
log.debug("Water Valve ${valve} has status ${valve.currentState("contact").value}, compared to ${status.toLowerCase()}")
|
||||
if(valve)
|
||||
{
|
||||
if(valve.currentState("contact").value == status.toLowerCase())
|
||||
{
|
||||
result = true
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
// TODO: subscribe to attributes, devices, locations, etc.
|
||||
}
|
||||
|
||||
// TODO: implement event handlers
|
||||
@@ -1,470 +0,0 @@
|
||||
/* **DISCLAIMER**
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Without limitation of the foregoing, Contributors/Regents expressly does not warrant that:
|
||||
* 1. the software will meet your requirements or expectations;
|
||||
* 2. the software or the software content will be free of bugs, errors, viruses or other defects;
|
||||
* 3. any results, output, or data provided through or generated by the software will be accurate, up-to-date, complete or reliable;
|
||||
* 4. the software will be compatible with third party software;
|
||||
* 5. any errors in the software will be corrected.
|
||||
* The user assumes all responsibility for selecting the software and for the results obtained from the use of the software. The user shall bear the entire risk as to the quality and the performance of the software.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 5-2 Day Thermostat
|
||||
*
|
||||
* Base code from mwoodengr@hotmail.com, bugfixed and enhanced by RBoy
|
||||
* Changes Copyright RBoy, redistribution of any changes or modified code is not allowed without permission
|
||||
* Version 2.1.0
|
||||
* 2015-10-3 - Fixed an issue with selecting multiple thermostats and for recent platform changes
|
||||
* 2015-5-17 - Added ability to select mutiple thermostats simultaneously
|
||||
* 2015-2-11 - Fixed issue with fan mode
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "5-2 Day Thermostat",
|
||||
namespace: "rboy",
|
||||
author: "RBoy",
|
||||
description: "Weekday and Weekend Thermostat",
|
||||
category: "Green Living",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/GreenLiving/Cat-GreenLiving.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/GreenLiving/Cat-GreenLiving@2x.png",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/GreenLiving/Cat-GreenLiving@3x.png")
|
||||
|
||||
preferences {
|
||||
section("Choose thermostat (s)") {
|
||||
input "thermostats", "capability.thermostat", required: true, multiple:true
|
||||
}
|
||||
|
||||
section("Switch HVAC mode (auto to cool/heat) based on the outside temperature (optional)") {
|
||||
input "temperatureSensor", "capability.temperatureMeasurement", required: false
|
||||
input "temperatureH", "number", title: "Switch to heating temperature", required: false, description: "Temperature below which switch to heat mode"
|
||||
input "temperatureC", "number", title: "Switch to cooling temperature", required: false, description: "Temperature above which switch to cool mode"
|
||||
}
|
||||
|
||||
section("Monday to Friday Schedule") {
|
||||
input "time1", "time", title: "Wake Time", required: true
|
||||
input "tempSetpoint1", "number", title: "Wake Heat Temp", required: true
|
||||
input "tempSetpointA", "number", title: "Wake Cool Temp", required: true
|
||||
input "time2", "time", title: "Leave Time", required: true
|
||||
input "tempSetpoint2", "number", title: "Leave Heat Temp", required: true
|
||||
input "tempSetpointB", "number", title: "Leave Cool Temp", required: true
|
||||
input "time3", "time", title: "Return Time", required: true
|
||||
input "tempSetpoint3", "number", title: "Return Heat Temp", required: true
|
||||
input "tempSetpointC", "number", title: "Return Cool Temp", required: true
|
||||
input "time4", "time", title: "Sleep Time", required: true
|
||||
input "tempSetpoint4", "number", title: "Sleep Heat Temp", required: true
|
||||
input "tempSetpointD", "number", title: "Sleep Cool Temp", required: true
|
||||
}
|
||||
section("Saturday and Sunday Schedule") {
|
||||
input "time11", "time", title: "Wake Time", required: true
|
||||
input "tempSetpoint11", "number", title: "Wake Heat Temp", required: true
|
||||
input "tempSetpointAA", "number", title: "Wake Cool Temp", required: true
|
||||
input "time21", "time", title: "Leave Time", required: true
|
||||
input "tempSetpoint21", "number", title: "Leave Heat Temp", required: true
|
||||
input "tempSetpointBB", "number", title: "Leave Cool Temp", required: true
|
||||
input "time31", "time", title: "Return Time", required: true
|
||||
input "tempSetpoint31", "number", title: "Return Heat Temp", required: true
|
||||
input "tempSetpointCC", "number", title: "Return Cool Temp", required: true
|
||||
input "time41", "time", title: "Sleep Time", required: true
|
||||
input "tempSetpoint41", "number", title: "Sleep Heat Temp", required: true
|
||||
input "tempSetpointDD", "number", title: "Sleep Cool Temp", required: true
|
||||
}
|
||||
}
|
||||
|
||||
def installed()
|
||||
{
|
||||
subscribeToEvents()
|
||||
}
|
||||
|
||||
def updated()
|
||||
{
|
||||
unsubscribe()
|
||||
subscribeToEvents()
|
||||
}
|
||||
|
||||
def subscribeToEvents() {
|
||||
subscribe(temperatureSensor, "temperature", temperatureHandler)
|
||||
subscribe(location, modeChangeHandler)
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
// Handle mode changes, reinitialize the current temperature and timers after a mode change, this is to workaround the issue of the last timer firing while in a non running mode, resume operations when supported modes are set
|
||||
def modeChangeHandler(evt) {
|
||||
log.debug "Reinitializing thermostats on mode change notification, new mode $evt.value"
|
||||
//sendNotificationEvent("$thermostats Reinitializing on mode change notification, new mode $evt.value")
|
||||
initialize()
|
||||
}
|
||||
|
||||
// This section sets the HVAC mode based outside temperature. HVAC fan mode is set to "auto".
|
||||
def temperatureHandler(evt) {
|
||||
log.debug "Heat mode switch temperature $temperatureH, cool mode switch temperature $temperatureC"
|
||||
|
||||
if (temperatureH == null || temperatureC == null) { // We are in Auto mode or user doesn't want us to switch modes
|
||||
return
|
||||
}
|
||||
|
||||
thermostats.each { thermostat ->
|
||||
def extTemp = temperatureSensor.currentTemperature
|
||||
log.debug "External temperature is: $extTemp"
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "HVAC current mode $thermostatState"
|
||||
log.debug "HVAC Fan current mode $thermostatFan"
|
||||
if (extTemp < temperatureH) {
|
||||
if (thermostatState == "cool") {
|
||||
def hvacmode = "heat"
|
||||
thermostat.setThermostatMode(hvacmode)
|
||||
log.debug "HVAC mode set to $hvacmode"
|
||||
}
|
||||
}
|
||||
else if (extTemp > temperatureC) {
|
||||
if (thermostatState == "heat") {
|
||||
def hvacmode = "cool"
|
||||
thermostat.setThermostatMode(hvacmode)
|
||||
log.debug "HVAC mode set to $hvacmode"
|
||||
}
|
||||
}
|
||||
|
||||
if (thermostatFan != "fanAuto") {
|
||||
thermostat.setThermostatFanMode("auto")
|
||||
log.debug "HVAC fan mode set to auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This section determines which day it is.
|
||||
def initialize() {
|
||||
log.trace "Initialized with $settings"
|
||||
|
||||
unschedule()
|
||||
def calendar = Calendar.getInstance()
|
||||
calendar.setTimeZone(location.timeZone)
|
||||
def today = calendar.get(Calendar.DAY_OF_WEEK)
|
||||
def timeNow = now()
|
||||
def midnightToday = timeToday("2000-01-01T23:59:59.999-0000", location.timeZone)
|
||||
log.debug("Current time is ${(new Date(timeNow)).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
log.debug("Midnight today is ${midnightToday.format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekday schedule1 ${timeToday(time1, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekday schedule2 ${timeToday(time2, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekday schedule3 ${timeToday(time3, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekday schedule4 ${timeToday(time4, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekend schedule1 ${timeToday(time11, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekend schedule2 ${timeToday(time21, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekend schedule3 ${timeToday(time31, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
log.trace("Weekend schedule4 ${timeToday(time41, location.timeZone).format("HH:mm z", location.timeZone)}")
|
||||
|
||||
// This section is where the time/temperature schedule is set
|
||||
switch (today) {
|
||||
case Calendar.MONDAY:
|
||||
case Calendar.TUESDAY:
|
||||
case Calendar.WEDNESDAY:
|
||||
case Calendar.THURSDAY:
|
||||
if (timeNow >= timeToday(time1, location.timeZone).time && timeNow < timeToday(time2, location.timeZone).time) { // Are we between 1st time and 2nd time
|
||||
changeTemp1()
|
||||
schedule(timeToday(time2, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time2, location.timeZone).time && timeNow < timeToday(time3, location.timeZone).time) { // Are we between 2nd time and 3rd time
|
||||
changeTemp2()
|
||||
schedule(timeToday(time3, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time3, location.timeZone).time && timeNow < timeToday(time4, location.timeZone).time) { // Are we between 3rd time and 4th time
|
||||
changeTemp3()
|
||||
schedule(timeToday(time4, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time4, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time and midnight, schedule next day
|
||||
changeTemp4()
|
||||
schedule(timeToday(time1, location.timeZone) + 1, initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time1, location.timeZone).time) { // Are we between midnight yesterday and 1st time, schedule today
|
||||
changeTemp4()
|
||||
schedule(timeToday(time1, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
break
|
||||
|
||||
case Calendar.FRIDAY:
|
||||
if (timeNow >= timeToday(time1, location.timeZone).time && timeNow < timeToday(time2, location.timeZone).time) { // Are we between 1st time and 2nd time
|
||||
changeTemp1()
|
||||
schedule(timeToday(time2, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time2, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time2, location.timeZone).time && timeNow < timeToday(time3, location.timeZone).time) { // Are we between 2nd time and 3rd time
|
||||
changeTemp2()
|
||||
schedule(timeToday(time3, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time3, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time3, location.timeZone).time && timeNow < timeToday(time4, location.timeZone).time) { // Are we between 3rd time and 4th time
|
||||
changeTemp3()
|
||||
schedule(timeToday(time4, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time4, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time4, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time Friday and midnight, we schedule Saturday
|
||||
changeTemp4()
|
||||
schedule(timeToday(time11, location.timeZone) + 1, initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time11, location.timeZone).time) { // Are we between midnight Friday and 1st time on Saturday, we schedule Saturday
|
||||
changeTemp4()
|
||||
schedule(timeToday(time11, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
break
|
||||
|
||||
case Calendar.SATURDAY:
|
||||
if (timeNow >= timeToday(time11, location.timeZone).time && timeNow < timeToday(time21, location.timeZone).time) { // Are we between 1st time and 2nd time
|
||||
changeTemp11()
|
||||
schedule(timeToday(time21, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time21, location.timeZone).time && timeNow < timeToday(time31, location.timeZone).time) { // Are we between 2nd time and 3rd time
|
||||
changeTemp21()
|
||||
schedule(timeToday(time31, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time31, location.timeZone).time && timeNow < timeToday(time41, location.timeZone).time) { // Are we between 3rd time and 4th time
|
||||
changeTemp31()
|
||||
schedule(timeToday(time41, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time41, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time and midnight, schedule the next day
|
||||
changeTemp41()
|
||||
schedule(timeToday(time11, location.timeZone) + 1, initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time11, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time11, location.timeZone).time) { // Are we between midnight yesterday and 1st time, schedule today
|
||||
changeTemp41()
|
||||
schedule(timeToday(time11, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time11, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
break
|
||||
|
||||
case Calendar.SUNDAY:
|
||||
if (timeNow >= timeToday(time11, location.timeZone).time && timeNow < timeToday(time21, location.timeZone).time) { // Are we between 1st time and 2nd time
|
||||
changeTemp11()
|
||||
schedule(timeToday(time21, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time21, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time21, location.timeZone).time && timeNow < timeToday(time31, location.timeZone).time) { // Are we between 2nd time and 3rd time
|
||||
changeTemp21()
|
||||
schedule(timeToday(time31, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time31, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time31, location.timeZone).time && timeNow < timeToday(time41, location.timeZone).time) { // Are we between 3rd time and 4th time
|
||||
changeTemp31()
|
||||
schedule(timeToday(time41, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time41, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= timeToday(time41, location.timeZone).time && timeNow < midnightToday.time) { // Are we between 4th time Sunday and midnight, we schedule Monday
|
||||
changeTemp41()
|
||||
schedule(timeToday(time1, location.timeZone) + 1, initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${(timeToday(time1, location.timeZone) + 1).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
else if (timeNow >= (midnightToday - 1).time && timeNow < timeToday(time1, location.timeZone).time) { // Are we between midnight Sunday and 1st time on Monday, we schedule Monday
|
||||
changeTemp41()
|
||||
schedule(timeToday(time1, location.timeZone), initialize)
|
||||
log.info("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
//sendNotificationEvent("$thermostats Scheduled next adjustment for ${timeToday(time1, location.timeZone).format("EEE MMM dd yyyy HH:mm z", location.timeZone)}")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// This section is where the thermostat temperature settings are set.
|
||||
def changeTemp1() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint1)
|
||||
thermostat.setCoolingSetpoint(tempSetpointA)
|
||||
log.info "Set $thermostat Heat $tempSetpoint1°, Cool $tempSetpointA°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint1)
|
||||
log.info "Set $thermostat Heat $tempSetpoint1°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointA)
|
||||
log.info "Set $thermostat Cool $tempSetpointA°"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp2() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint2)
|
||||
thermostat.setCoolingSetpoint(tempSetpointB)
|
||||
log.info "Set $thermostat Heat $tempSetpoint2°, Cool $tempSetpointB°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint2)
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointB)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp3() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint3)
|
||||
thermostat.setCoolingSetpoint(tempSetpointC)
|
||||
log.info "Set $thermostat Heat $tempSetpoint3°, Cool $tempSetpointC°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint3)
|
||||
log.info "Set $thermostat Heat $tempSetpoint3°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointC)
|
||||
log.info "Set $thermostat Cool $tempSetpointC°"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp4() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint4)
|
||||
thermostat.setCoolingSetpoint(tempSetpointD)
|
||||
log.info "Set $thermostat Heat $tempSetpoint4°, Cool $tempSetpointD°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint4)
|
||||
log.info "Set $thermostat Heat $tempSetpoint4°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointD)
|
||||
log.info "Set $thermostat Cool $tempSetpointD°"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp11() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint11)
|
||||
thermostat.setCoolingSetpoint(tempSetpointAA)
|
||||
log.info "Set $thermostat Heat $tempSetpoint11°, Cool $tempSetpointAA°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint11)
|
||||
log.info "Set $thermostat Heat $tempSetpoint11°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointAA)
|
||||
log.info "Set $thermostat Cool $tempSetpointAA°"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp21() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint21)
|
||||
thermostat.setCoolingSetpoint(tempSetpointBB)
|
||||
log.info "Set $thermostat Heat $tempSetpoint21°, Cool $tempSetpointBB°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint21)
|
||||
log.info "Set $thermostat Heat $tempSetpoint21°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointBB)
|
||||
log.info "Set $thermostat Cool $tempSetpointBB°"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp31() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint31)
|
||||
thermostat.setCoolingSetpoint(tempSetpointCC)
|
||||
log.info "Set $thermostat Heat $tempSetpoint31°, Cool $tempSetpointCC°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint31)
|
||||
log.info "Set $thermostat Heat $tempSetpoint31°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointCC)
|
||||
log.info "Set $thermostat Cool $tempSetpointCC°"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def changeTemp41() {
|
||||
thermostats.each { thermostat ->
|
||||
def thermostatState = thermostat.currentThermostatMode
|
||||
log.debug "Thermostat mode = $thermostatState"
|
||||
def thermostatFan = thermostat.currentThermostatFanMode
|
||||
log.debug "Thermostat fan = $thermostatFan"
|
||||
if (thermostatState == "auto") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint41)
|
||||
thermostat.setCoolingSetpoint(tempSetpointDD)
|
||||
log.info "Set $thermostat Heat $tempSetpoint41°, Cool $tempSetpointDD°"
|
||||
}
|
||||
else if (thermostatState == "heat") {
|
||||
thermostat.setHeatingSetpoint(tempSetpoint41)
|
||||
log.info "Set $thermostat Heat $tempSetpoint41°"
|
||||
}
|
||||
else {
|
||||
thermostat.setCoolingSetpoint(tempSetpointDD)
|
||||
log.info "Set $thermostat Cool $tempSetpointDD°"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user