mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-29 14:23:08 +01:00
Compare commits
1 Commits
PROD_2016.
...
MSA-1535-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc2e0db723 |
@@ -148,12 +148,14 @@ def generateEvent(Map results) {
|
|||||||
handlerName: name]
|
handlerName: name]
|
||||||
|
|
||||||
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint" ) {
|
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint" ) {
|
||||||
def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
|
def sendValue = convertTemperatureIfNeeded(value.toDouble(), "F", 1) //API return temperature value in F
|
||||||
|
sendValue = location.temperatureScale == "C"? roundC(sendValue) : sendValue
|
||||||
isChange = isTemperatureStateChange(device, name, value.toString())
|
isChange = isTemperatureStateChange(device, name, value.toString())
|
||||||
isDisplayed = isChange
|
isDisplayed = isChange
|
||||||
event << [value: sendValue, unit: temperatureScale, isStateChange: isChange, displayed: isDisplayed]
|
event << [value: sendValue, unit: temperatureScale, isStateChange: isChange, displayed: isDisplayed]
|
||||||
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
|
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
|
||||||
def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
|
def sendValue = convertTemperatureIfNeeded(value.toDouble(), "F", 1) //API return temperature value in F
|
||||||
|
sendValue = location.temperatureScale == "C"? roundC(sendValue) : sendValue
|
||||||
event << [value: sendValue, unit: temperatureScale, displayed: false]
|
event << [value: sendValue, unit: temperatureScale, displayed: false]
|
||||||
} else if (name=="heatMode" || name=="coolMode" || name=="autoMode" || name=="auxHeatMode"){
|
} else if (name=="heatMode" || name=="coolMode" || name=="autoMode" || name=="auxHeatMode"){
|
||||||
isChange = isStateChange(device, name, value.toString())
|
isChange = isStateChange(device, name, value.toString())
|
||||||
@@ -251,6 +253,7 @@ void setCoolingSetpoint(setpoint) {
|
|||||||
def maxCoolingSetpoint = device.currentValue("maxCoolingSetpoint")
|
def maxCoolingSetpoint = device.currentValue("maxCoolingSetpoint")
|
||||||
def minCoolingSetpoint = device.currentValue("minCoolingSetpoint")
|
def minCoolingSetpoint = device.currentValue("minCoolingSetpoint")
|
||||||
|
|
||||||
|
|
||||||
if (coolingSetpoint > maxCoolingSetpoint) {
|
if (coolingSetpoint > maxCoolingSetpoint) {
|
||||||
coolingSetpoint = maxCoolingSetpoint
|
coolingSetpoint = maxCoolingSetpoint
|
||||||
} else if (coolingSetpoint < minCoolingSetpoint) {
|
} else if (coolingSetpoint < minCoolingSetpoint) {
|
||||||
@@ -280,6 +283,7 @@ void setCoolingSetpoint(setpoint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resumeProgram() {
|
void resumeProgram() {
|
||||||
|
|
||||||
log.debug "resumeProgram() is called"
|
log.debug "resumeProgram() is called"
|
||||||
sendEvent("name":"thermostatStatus", "value":"resuming schedule", "description":statusText, displayed: false)
|
sendEvent("name":"thermostatStatus", "value":"resuming schedule", "description":statusText, displayed: false)
|
||||||
def deviceId = device.deviceNetworkId.split(/\./).last()
|
def deviceId = device.deviceNetworkId.split(/\./).last()
|
||||||
@@ -350,6 +354,7 @@ def switchFanMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def switchToFanMode(nextMode) {
|
def switchToFanMode(nextMode) {
|
||||||
|
|
||||||
log.debug "switching to fan mode: $nextMode"
|
log.debug "switching to fan mode: $nextMode"
|
||||||
def returnCommand
|
def returnCommand
|
||||||
|
|
||||||
@@ -515,56 +520,63 @@ def fanAuto() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def generateSetpointEvent() {
|
def generateSetpointEvent() {
|
||||||
|
|
||||||
log.debug "Generate SetPoint Event"
|
log.debug "Generate SetPoint Event"
|
||||||
|
|
||||||
def mode = device.currentValue("thermostatMode")
|
def mode = device.currentValue("thermostatMode")
|
||||||
|
log.debug "Current Mode = ${mode}"
|
||||||
|
|
||||||
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
||||||
|
log.debug "Heating Setpoint = ${heatingSetpoint}"
|
||||||
|
|
||||||
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
||||||
|
log.debug "Cooling Setpoint = ${coolingSetpoint}"
|
||||||
|
|
||||||
def maxHeatingSetpoint = device.currentValue("maxHeatingSetpoint")
|
def maxHeatingSetpoint = device.currentValue("maxHeatingSetpoint")
|
||||||
def maxCoolingSetpoint = device.currentValue("maxCoolingSetpoint")
|
def maxCoolingSetpoint = device.currentValue("maxCoolingSetpoint")
|
||||||
def minHeatingSetpoint = device.currentValue("minHeatingSetpoint")
|
def minHeatingSetpoint = device.currentValue("minHeatingSetpoint")
|
||||||
def minCoolingSetpoint = device.currentValue("minCoolingSetpoint")
|
def minCoolingSetpoint = device.currentValue("minCoolingSetpoint")
|
||||||
|
|
||||||
if(location.temperatureScale == "C") {
|
if(location.temperatureScale == "C")
|
||||||
maxHeatingSetpoint = maxHeatingSetpoint > 40 ? roundC(convertFtoC(maxHeatingSetpoint)) : roundC(maxHeatingSetpoint)
|
{
|
||||||
maxCoolingSetpoint = maxCoolingSetpoint > 40 ? roundC(convertFtoC(maxCoolingSetpoint)) : roundC(maxCoolingSetpoint)
|
maxHeatingSetpoint = roundC(maxHeatingSetpoint)
|
||||||
minHeatingSetpoint = minHeatingSetpoint > 40 ? roundC(convertFtoC(minHeatingSetpoint)) : roundC(minHeatingSetpoint)
|
maxCoolingSetpoint = roundC(maxCoolingSetpoint)
|
||||||
minCoolingSetpoint = minCoolingSetpoint > 40 ? roundC(convertFtoC(minCoolingSetpoint)) : roundC(minCoolingSetpoint)
|
minHeatingSetpoint = roundC(minHeatingSetpoint)
|
||||||
heatingSetpoint = heatingSetpoint > 40 ? roundC(convertFtoC(heatingSetpoint)) : roundC(heatingSetpoint)
|
minCoolingSetpoint = roundC(minCoolingSetpoint)
|
||||||
coolingSetpoint = coolingSetpoint > 40 ? roundC(convertFtoC(coolingSetpoint)) : roundC(coolingSetpoint)
|
heatingSetpoint = roundC(heatingSetpoint)
|
||||||
} else {
|
coolingSetpoint = roundC(coolingSetpoint)
|
||||||
maxHeatingSetpoint = maxHeatingSetpoint < 40 ? roundC(convertCtoF(maxHeatingSetpoint)) : maxHeatingSetpoint
|
|
||||||
maxCoolingSetpoint = maxCoolingSetpoint < 40 ? roundC(convertCtoF(maxCoolingSetpoint)) : maxCoolingSetpoint
|
|
||||||
minHeatingSetpoint = minHeatingSetpoint < 40 ? roundC(convertCtoF(minHeatingSetpoint)) : minHeatingSetpoint
|
|
||||||
minCoolingSetpoint = minCoolingSetpoint < 40 ? roundC(convertCtoF(minCoolingSetpoint)) : minCoolingSetpoint
|
|
||||||
heatingSetpoint = heatingSetpoint < 40 ? roundC(convertCtoF(heatingSetpoint)) : heatingSetpoint
|
|
||||||
coolingSetpoint = coolingSetpoint < 40 ? roundC(convertCtoF(coolingSetpoint)) : coolingSetpoint
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug "Current Mode = ${mode}"
|
|
||||||
log.debug "Heating Setpoint = ${heatingSetpoint}"
|
|
||||||
log.debug "Cooling Setpoint = ${coolingSetpoint}"
|
|
||||||
|
|
||||||
sendEvent("name":"maxHeatingSetpoint", "value":maxHeatingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"maxHeatingSetpoint", "value":maxHeatingSetpoint, "unit":location.temperatureScale)
|
||||||
sendEvent("name":"maxCoolingSetpoint", "value":maxCoolingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"maxCoolingSetpoint", "value":maxCoolingSetpoint, "unit":location.temperatureScale)
|
||||||
sendEvent("name":"minHeatingSetpoint", "value":minHeatingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"minHeatingSetpoint", "value":minHeatingSetpoint, "unit":location.temperatureScale)
|
||||||
sendEvent("name":"minCoolingSetpoint", "value":minCoolingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"minCoolingSetpoint", "value":minCoolingSetpoint, "unit":location.temperatureScale)
|
||||||
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
|
||||||
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
|
|
||||||
|
|
||||||
if (mode == "heat") {
|
if (mode == "heat") {
|
||||||
|
|
||||||
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (mode == "cool") {
|
else if (mode == "cool") {
|
||||||
|
|
||||||
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
|
||||||
|
|
||||||
} else if (mode == "auto") {
|
} else if (mode == "auto") {
|
||||||
|
|
||||||
sendEvent("name":"thermostatSetpoint", "value":"Auto")
|
sendEvent("name":"thermostatSetpoint", "value":"Auto")
|
||||||
|
|
||||||
} else if (mode == "off") {
|
} else if (mode == "off") {
|
||||||
|
|
||||||
sendEvent("name":"thermostatSetpoint", "value":"Off")
|
sendEvent("name":"thermostatSetpoint", "value":"Off")
|
||||||
|
|
||||||
} else if (mode == "auxHeatOnly") {
|
} else if (mode == "auxHeatOnly") {
|
||||||
|
|
||||||
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void raiseSetpoint() {
|
void raiseSetpoint() {
|
||||||
@@ -573,31 +585,21 @@ void raiseSetpoint() {
|
|||||||
def maxHeatingSetpoint = device.currentValue("maxHeatingSetpoint")
|
def maxHeatingSetpoint = device.currentValue("maxHeatingSetpoint")
|
||||||
def maxCoolingSetpoint = device.currentValue("maxCoolingSetpoint")
|
def maxCoolingSetpoint = device.currentValue("maxCoolingSetpoint")
|
||||||
|
|
||||||
|
|
||||||
if (mode == "off" || mode == "auto") {
|
if (mode == "off" || mode == "auto") {
|
||||||
log.warn "this mode: $mode does not allow raiseSetpoint"
|
log.warn "this mode: $mode does not allow raiseSetpoint"
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
||||||
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
||||||
def thermostatSetpoint = device.currentValue("thermostatSetpoint")
|
def thermostatSetpoint = device.currentValue("thermostatSetpoint")
|
||||||
|
|
||||||
if (location.temperatureScale == "C") {
|
|
||||||
maxHeatingSetpoint = maxHeatingSetpoint > 40 ? convertFtoC(maxHeatingSetpoint) : maxHeatingSetpoint
|
|
||||||
maxCoolingSetpoint = maxCoolingSetpoint > 40 ? convertFtoC(maxCoolingSetpoint) : maxCoolingSetpoint
|
|
||||||
heatingSetpoint = heatingSetpoint > 40 ? convertFtoC(heatingSetpoint) : heatingSetpoint
|
|
||||||
coolingSetpoint = coolingSetpoint > 40 ? convertFtoC(coolingSetpoint) : coolingSetpoint
|
|
||||||
thermostatSetpoint = thermostatSetpoint > 40 ? convertFtoC(thermostatSetpoint) : thermostatSetpoint
|
|
||||||
} else {
|
|
||||||
maxHeatingSetpoint = maxHeatingSetpoint < 40 ? convertCtoF(maxHeatingSetpoint) : maxHeatingSetpoint
|
|
||||||
maxCoolingSetpoint = maxCoolingSetpoint < 40 ? convertCtoF(maxCoolingSetpoint) : maxCoolingSetpoint
|
|
||||||
heatingSetpoint = heatingSetpoint < 40 ? convertCtoF(heatingSetpoint) : heatingSetpoint
|
|
||||||
coolingSetpoint = coolingSetpoint < 40 ? convertCtoF(coolingSetpoint) : coolingSetpoint
|
|
||||||
thermostatSetpoint = thermostatSetpoint < 40 ? convertCtoF(thermostatSetpoint) : thermostatSetpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug "raiseSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
|
log.debug "raiseSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
|
||||||
|
|
||||||
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
|
if (device.latestState('thermostatSetpoint')) {
|
||||||
|
targetvalue = device.latestState('thermostatSetpoint').value
|
||||||
|
targetvalue = location.temperatureScale == "F"? targetvalue.toInteger() : targetvalue.toDouble()
|
||||||
|
} else {
|
||||||
|
targetvalue = 0
|
||||||
|
}
|
||||||
targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5
|
targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5
|
||||||
|
|
||||||
if ((mode == "heat" || mode == "auxHeatOnly") && targetvalue > maxHeatingSetpoint) {
|
if ((mode == "heat" || mode == "auxHeatOnly") && targetvalue > maxHeatingSetpoint) {
|
||||||
@@ -620,29 +622,20 @@ void lowerSetpoint() {
|
|||||||
def minHeatingSetpoint = device.currentValue("minHeatingSetpoint")
|
def minHeatingSetpoint = device.currentValue("minHeatingSetpoint")
|
||||||
def minCoolingSetpoint = device.currentValue("minCoolingSetpoint")
|
def minCoolingSetpoint = device.currentValue("minCoolingSetpoint")
|
||||||
|
|
||||||
|
|
||||||
if (mode == "off" || mode == "auto") {
|
if (mode == "off" || mode == "auto") {
|
||||||
log.warn "this mode: $mode does not allow lowerSetpoint"
|
log.warn "this mode: $mode does not allow lowerSetpoint"
|
||||||
} else {
|
} else {
|
||||||
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
||||||
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
||||||
def thermostatSetpoint = device.currentValue("thermostatSetpoint")
|
def thermostatSetpoint = device.currentValue("thermostatSetpoint")
|
||||||
|
|
||||||
if (location.temperatureScale == "C") {
|
|
||||||
minHeatingSetpoint = minHeatingSetpoint > 40 ? convertFtoC(minHeatingSetpoint) : minHeatingSetpoint
|
|
||||||
minCoolingSetpoint = minCoolingSetpoint > 40 ? convertFtoC(minCoolingSetpoint) : minCoolingSetpoint
|
|
||||||
heatingSetpoint = heatingSetpoint > 40 ? convertFtoC(heatingSetpoint) : heatingSetpoint
|
|
||||||
coolingSetpoint = coolingSetpoint > 40 ? convertFtoC(coolingSetpoint) : coolingSetpoint
|
|
||||||
thermostatSetpoint = thermostatSetpoint > 40 ? convertFtoC(thermostatSetpoint) : thermostatSetpoint
|
|
||||||
} else {
|
|
||||||
minHeatingSetpoint = minHeatingSetpoint < 40 ? convertCtoF(minHeatingSetpoint) : minHeatingSetpoint
|
|
||||||
minCoolingSetpoint = minCoolingSetpoint < 40 ? convertCtoF(minCoolingSetpoint) : minCoolingSetpoint
|
|
||||||
heatingSetpoint = heatingSetpoint < 40 ? convertCtoF(heatingSetpoint) : heatingSetpoint
|
|
||||||
coolingSetpoint = coolingSetpoint < 40 ? convertCtoF(coolingSetpoint) : coolingSetpoint
|
|
||||||
thermostatSetpoint = thermostatSetpoint < 40 ? convertCtoF(thermostatSetpoint) : thermostatSetpoint
|
|
||||||
}
|
|
||||||
log.debug "lowerSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
|
log.debug "lowerSetpoint() mode = ${mode}, heatingSetpoint: ${heatingSetpoint}, coolingSetpoint:${coolingSetpoint}, thermostatSetpoint:${thermostatSetpoint}"
|
||||||
|
if (device.latestState('thermostatSetpoint')) {
|
||||||
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
|
targetvalue = device.latestState('thermostatSetpoint').value
|
||||||
|
targetvalue = location.temperatureScale == "F"? targetvalue.toInteger() : targetvalue.toDouble()
|
||||||
|
} else {
|
||||||
|
targetvalue = 0
|
||||||
|
}
|
||||||
targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5
|
targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5
|
||||||
|
|
||||||
if ((mode == "heat" || mode == "auxHeatOnly") && targetvalue < minHeatingSetpoint) {
|
if ((mode == "heat" || mode == "auxHeatOnly") && targetvalue < minHeatingSetpoint) {
|
||||||
@@ -660,6 +653,7 @@ void lowerSetpoint() {
|
|||||||
|
|
||||||
//called by raiseSetpoint() and lowerSetpoint()
|
//called by raiseSetpoint() and lowerSetpoint()
|
||||||
void alterSetpoint(temp) {
|
void alterSetpoint(temp) {
|
||||||
|
|
||||||
def mode = device.currentValue("thermostatMode")
|
def mode = device.currentValue("thermostatMode")
|
||||||
|
|
||||||
if (mode == "off" || mode == "auto") {
|
if (mode == "off" || mode == "auto") {
|
||||||
@@ -672,18 +666,6 @@ void alterSetpoint(temp) {
|
|||||||
def targetHeatingSetpoint
|
def targetHeatingSetpoint
|
||||||
def targetCoolingSetpoint
|
def targetCoolingSetpoint
|
||||||
|
|
||||||
def temperatureScaleHasChanged = false
|
|
||||||
|
|
||||||
if (location.temperatureScale == "C") {
|
|
||||||
if ( heatingSetpoint > 40.0 || coolingSetpoint > 40.0 ) {
|
|
||||||
temperatureScaleHasChanged = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ( heatingSetpoint < 40.0 || coolingSetpoint < 40.0 ) {
|
|
||||||
temperatureScaleHasChanged = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//step1: check thermostatMode, enforce limits before sending request to cloud
|
//step1: check thermostatMode, enforce limits before sending request to cloud
|
||||||
if (mode == "heat" || mode == "auxHeatOnly"){
|
if (mode == "heat" || mode == "auxHeatOnly"){
|
||||||
if (temp.value > coolingSetpoint){
|
if (temp.value > coolingSetpoint){
|
||||||
@@ -725,18 +707,17 @@ void alterSetpoint(temp) {
|
|||||||
sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
|
sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( temperatureScaleHasChanged )
|
|
||||||
generateSetpointEvent()
|
|
||||||
generateStatusEvent()
|
generateStatusEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateStatusEvent() {
|
def generateStatusEvent() {
|
||||||
|
|
||||||
def mode = device.currentValue("thermostatMode")
|
def mode = device.currentValue("thermostatMode")
|
||||||
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
def heatingSetpoint = device.currentValue("heatingSetpoint")
|
||||||
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
||||||
def temperature = device.currentValue("temperature")
|
def temperature = device.currentValue("temperature")
|
||||||
|
|
||||||
def statusText
|
def statusText
|
||||||
|
|
||||||
log.debug "Generate Status Event for Mode = ${mode}"
|
log.debug "Generate Status Event for Mode = ${mode}"
|
||||||
@@ -746,25 +727,36 @@ def generateStatusEvent() {
|
|||||||
log.debug "HVAC Mode = ${mode}"
|
log.debug "HVAC Mode = ${mode}"
|
||||||
|
|
||||||
if (mode == "heat") {
|
if (mode == "heat") {
|
||||||
|
|
||||||
if (temperature >= heatingSetpoint)
|
if (temperature >= heatingSetpoint)
|
||||||
statusText = "Right Now: Idle"
|
statusText = "Right Now: Idle"
|
||||||
else
|
else
|
||||||
statusText = "Heating to ${heatingSetpoint} ${location.temperatureScale}"
|
statusText = "Heating to ${heatingSetpoint} ${location.temperatureScale}"
|
||||||
|
|
||||||
} else if (mode == "cool") {
|
} else if (mode == "cool") {
|
||||||
|
|
||||||
if (temperature <= coolingSetpoint)
|
if (temperature <= coolingSetpoint)
|
||||||
statusText = "Right Now: Idle"
|
statusText = "Right Now: Idle"
|
||||||
else
|
else
|
||||||
statusText = "Cooling to ${coolingSetpoint} ${location.temperatureScale}"
|
statusText = "Cooling to ${coolingSetpoint} ${location.temperatureScale}"
|
||||||
} else if (mode == "auto") {
|
|
||||||
statusText = "Right Now: Auto"
|
|
||||||
} else if (mode == "off") {
|
|
||||||
statusText = "Right Now: Off"
|
|
||||||
} else if (mode == "auxHeatOnly") {
|
|
||||||
statusText = "Emergency Heat"
|
|
||||||
} else {
|
|
||||||
statusText = "?"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} else if (mode == "auto") {
|
||||||
|
|
||||||
|
statusText = "Right Now: Auto"
|
||||||
|
|
||||||
|
} else if (mode == "off") {
|
||||||
|
|
||||||
|
statusText = "Right Now: Off"
|
||||||
|
|
||||||
|
} else if (mode == "auxHeatOnly") {
|
||||||
|
|
||||||
|
statusText = "Emergency Heat"
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
statusText = "?"
|
||||||
|
|
||||||
|
}
|
||||||
log.debug "Generate Status Event = ${statusText}"
|
log.debug "Generate Status Event = ${statusText}"
|
||||||
sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true)
|
sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true)
|
||||||
}
|
}
|
||||||
@@ -778,7 +770,7 @@ def roundC (tempC) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def convertFtoC (tempF) {
|
def convertFtoC (tempF) {
|
||||||
return ((Math.round(((tempF - 32)*(5/9)) * 2))/2).toDouble()
|
return String.format("%.1f", (Math.round(((tempF - 32)*(5/9)) * 2))/2)
|
||||||
}
|
}
|
||||||
|
|
||||||
def convertCtoF (tempC) {
|
def convertCtoF (tempC) {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void installed() {
|
void installed() {
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
|
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
@@ -172,3 +172,6 @@ def verifyPercent(percent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ping() {
|
||||||
|
log.debug "${parent.ping(this)}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void installed() {
|
void installed() {
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
|
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan"], displayed: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
@@ -87,3 +87,6 @@ def parse(description) {
|
|||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ping() {
|
||||||
|
log.debug "${parent.ping(this)}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void installed() {
|
void installed() {
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
|
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
@@ -188,3 +188,6 @@ def verifyPercent(percent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ping() {
|
||||||
|
log.trace "${parent.ping(this)}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void installed() {
|
void installed() {
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
|
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
@@ -93,3 +93,6 @@ void refresh() {
|
|||||||
parent.manualRefresh()
|
parent.manualRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ping() {
|
||||||
|
log.debug "${parent.ping(this)}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void installed() {
|
void installed() {
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
|
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
@@ -107,3 +107,6 @@ void refresh() {
|
|||||||
parent.manualRefresh()
|
parent.manualRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ping() {
|
||||||
|
log.debug "${parent.ping(this)}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2015 SmartThings
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* LEEDARSON White Color Temperature Bulb
|
||||||
|
*
|
||||||
|
* Author: Yechi
|
||||||
|
* Date: 2015-09-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
metadata {
|
||||||
|
definition (name: "LEEDARSON White Color Temperature Bulb", namespace: "smartthings", author: "Yechi") {
|
||||||
|
|
||||||
|
capability "Actuator"
|
||||||
|
capability "Color Temperature"
|
||||||
|
capability "Configuration"
|
||||||
|
capability "Health Check"
|
||||||
|
capability "Refresh"
|
||||||
|
capability "Switch"
|
||||||
|
capability "Switch Level"
|
||||||
|
|
||||||
|
attribute "colorName", "string"
|
||||||
|
command "setGenericName"
|
||||||
|
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019"
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04", outClusters: "0019"
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY BR Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Flood BR30 Tunable White"
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY RT Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Recessed Kit RT 5/6 Tunable White"
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 TW", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W"
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W"
|
||||||
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic B40 TW - LIGHTIFY", deviceJoinName: "OSRAM LIGHTIFY Classic B40 Tunable White"
|
||||||
|
fingerprint profileId: "0104", deviceId: "0102", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "Eaton", model: "Halo_LT01", deviceJoinName: "LDS Tunable White"
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI tile definitions
|
||||||
|
tiles(scale: 2) {
|
||||||
|
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
||||||
|
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||||
|
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff"
|
||||||
|
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||||
|
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff"
|
||||||
|
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||||
|
}
|
||||||
|
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
|
||||||
|
attributeState "level", action:"switch level.setLevel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
|
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||||
|
}
|
||||||
|
|
||||||
|
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..5000)") {
|
||||||
|
state "colorTemperature", action:"color temperature.setColorTemperature"
|
||||||
|
}
|
||||||
|
valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
|
state "colorName", label: '${currentValue}'
|
||||||
|
}
|
||||||
|
|
||||||
|
main(["switch"])
|
||||||
|
details(["switch", "colorTempSliderControl", "colorName", "refresh"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse incoming device messages to generate events
|
||||||
|
def parse(String description) {
|
||||||
|
log.debug "description is $description"
|
||||||
|
def event = zigbee.getEvent(description)
|
||||||
|
if (event) {
|
||||||
|
if (event.name=="level" && event.value==0) {}
|
||||||
|
else {
|
||||||
|
if (event.name=="colorTemperature") {
|
||||||
|
setGenericName(event.value)
|
||||||
|
}
|
||||||
|
sendEvent(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
def cluster = zigbee.parse(description)
|
||||||
|
|
||||||
|
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
|
||||||
|
if (cluster.data[0] == 0x00) {
|
||||||
|
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
|
||||||
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
log.debug "${cluster}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def off() {
|
||||||
|
zigbee.off()
|
||||||
|
}
|
||||||
|
|
||||||
|
def on() {
|
||||||
|
zigbee.on()
|
||||||
|
}
|
||||||
|
|
||||||
|
def setLevel(value) {
|
||||||
|
zigbee.setLevel(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PING is used by Device-Watch in attempt to reach the Device
|
||||||
|
* */
|
||||||
|
def ping() {
|
||||||
|
return zigbee.onOffRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
def refresh() {
|
||||||
|
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
def configure() {
|
||||||
|
log.debug "Configuring Reporting and Bindings."
|
||||||
|
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
||||||
|
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||||
|
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
def setColorTemperature(value) {
|
||||||
|
setGenericName(value)
|
||||||
|
zigbee.setColorTemperature(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature
|
||||||
|
def setGenericName(value){
|
||||||
|
if (value != null) {
|
||||||
|
def genericName = "White"
|
||||||
|
if (value < 3300) {
|
||||||
|
genericName = "Soft White"
|
||||||
|
} else if (value < 4150) {
|
||||||
|
genericName = "Moonlight"
|
||||||
|
} else if (value <= 5000) {
|
||||||
|
genericName = "Cool White"
|
||||||
|
} else if (value >= 5000) {
|
||||||
|
genericName = "Daylight"
|
||||||
|
}
|
||||||
|
sendEvent(name: "colorName", value: genericName)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -141,6 +141,7 @@ def setLevel(percentage) {
|
|||||||
percentage = 1 // clamp to 1%
|
percentage = 1 // clamp to 1%
|
||||||
}
|
}
|
||||||
if (percentage == 0) {
|
if (percentage == 0) {
|
||||||
|
sendEvent(name: "level", value: 0) // Otherwise the level value tile does not update
|
||||||
return off() // if the brightness is set to 0, just turn it off
|
return off() // if the brightness is set to 0, just turn it off
|
||||||
}
|
}
|
||||||
parent.logErrors(logObject:log) {
|
parent.logErrors(logObject:log) {
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ def setLevel(percentage) {
|
|||||||
percentage = 1 // clamp to 1%
|
percentage = 1 // clamp to 1%
|
||||||
}
|
}
|
||||||
if (percentage == 0) {
|
if (percentage == 0) {
|
||||||
|
sendEvent(name: "level", value: 0) // Otherwise the level value tile does not update
|
||||||
return off() // if the brightness is set to 0, just turn it off
|
return off() // if the brightness is set to 0, just turn it off
|
||||||
}
|
}
|
||||||
parent.logErrors(logObject:log) {
|
parent.logErrors(logObject:log) {
|
||||||
@@ -142,7 +143,7 @@ def poll() {
|
|||||||
sendEvent(name: "model", value: data.product.name)
|
sendEvent(name: "model", value: data.product.name)
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
log.debug "Executing 'refresh'"
|
log.debug "Executing 'refresh'"
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ def refresh() {
|
|||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
refresh() + zigbee.onOffConfig(0, 300) + powerConfig()
|
refresh() + zigbee.onOffConfig(0, 300) + powerConfig()
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ def refresh()
|
|||||||
{
|
{
|
||||||
log.debug "refresh temperature, humidity, and battery"
|
log.debug "refresh temperature, humidity, and battery"
|
||||||
return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware
|
return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware
|
||||||
|
zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0x104E]) + // New firmware
|
||||||
zigbee.readAttribute(0x0402, 0x0000) +
|
zigbee.readAttribute(0x0402, 0x0000) +
|
||||||
zigbee.readAttribute(0x0001, 0x0020)
|
zigbee.readAttribute(0x0001, 0x0020)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ def configure() {
|
|||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
|
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ metadata {
|
|||||||
capability "Switch Level"
|
capability "Switch Level"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Gardenspot RGB", deviceJoinName: "OSRAM LIGHTIFY Gardenspot mini RGB"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Gardenspot RGB"
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Gardenspot RGB", deviceJoinName: "OSRAM LIGHTIFY Gardenspot mini RGB"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Gardenspot RGB"
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI tile definitions
|
// UI tile definitions
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ def configure() {
|
|||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
refresh()
|
refresh()
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ def configure() {
|
|||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
refresh()
|
refresh()
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ preferences {
|
|||||||
|
|
||||||
def mainPage() {
|
def mainPage() {
|
||||||
def bridges = bridgesDiscovered()
|
def bridges = bridgesDiscovered()
|
||||||
|
if (state.username && bridges) {
|
||||||
if (state.refreshUsernameNeeded) {
|
|
||||||
return bridgeLinking()
|
|
||||||
} else if (state.username && bridges) {
|
|
||||||
return bulbDiscovery()
|
return bulbDiscovery()
|
||||||
} else {
|
} else {
|
||||||
return bridgeDiscovery()
|
return bridgeDiscovery()
|
||||||
@@ -107,20 +104,11 @@ def bridgeLinking() {
|
|||||||
def title = "Linking with your Hue"
|
def title = "Linking with your Hue"
|
||||||
def paragraphText
|
def paragraphText
|
||||||
if (selectedHue) {
|
if (selectedHue) {
|
||||||
if (state.refreshUsernameNeeded) {
|
|
||||||
paragraphText = "The current Hue username is invalid.\n\nPlease press the button on your Hue Bridge to re-link. "
|
|
||||||
} else {
|
|
||||||
paragraphText = "Press the button on your Hue Bridge to setup a link. "
|
paragraphText = "Press the button on your Hue Bridge to setup a link. "
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
paragraphText = "You haven't selected a Hue Bridge, please Press \"Done\" and select one before clicking next."
|
paragraphText = "You haven't selected a Hue Bridge, please Press \"Done\" and select one before clicking next."
|
||||||
}
|
}
|
||||||
if (state.username) { //if discovery worked
|
if (state.username) { //if discovery worked
|
||||||
if (state.refreshUsernameNeeded) {
|
|
||||||
state.refreshUsernameNeeded = false
|
|
||||||
// Issue one poll with new username to cancel local polling with old username
|
|
||||||
poll()
|
|
||||||
}
|
|
||||||
nextPage = "bulbDiscovery"
|
nextPage = "bulbDiscovery"
|
||||||
title = "Success!"
|
title = "Success!"
|
||||||
paragraphText = "Linking to your hub was a success! Please click 'Next'!"
|
paragraphText = "Linking to your hub was a success! Please click 'Next'!"
|
||||||
@@ -299,7 +287,6 @@ def initialize() {
|
|||||||
state.bridgeRefreshCount = 0
|
state.bridgeRefreshCount = 0
|
||||||
state.bulbRefreshCount = 0
|
state.bulbRefreshCount = 0
|
||||||
state.updating = false
|
state.updating = false
|
||||||
setupDeviceWatch()
|
|
||||||
if (selectedHue) {
|
if (selectedHue) {
|
||||||
addBridge()
|
addBridge()
|
||||||
addBulbs()
|
addBulbs()
|
||||||
@@ -322,14 +309,6 @@ def uninstalled(){
|
|||||||
state.username = null
|
state.username = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupDeviceWatch() {
|
|
||||||
def hub = location.hubs[0]
|
|
||||||
// Make sure that all child devices are enrolled in device watch
|
|
||||||
getChildDevices().each {
|
|
||||||
it.sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${hub?.hub?.hardwareID}\"}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private upgradeDeviceType(device, newHueType) {
|
private upgradeDeviceType(device, newHueType) {
|
||||||
def deviceType = getDeviceType(newHueType)
|
def deviceType = getDeviceType(newHueType)
|
||||||
|
|
||||||
@@ -378,6 +357,7 @@ def addBulbs() {
|
|||||||
if (d) {
|
if (d) {
|
||||||
log.debug "created ${d.displayName} with id $dni"
|
log.debug "created ${d.displayName} with id $dni"
|
||||||
d.completedSetup = true
|
d.completedSetup = true
|
||||||
|
d.refresh()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
|
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
|
||||||
@@ -434,11 +414,9 @@ def addBridge() {
|
|||||||
d.completedSetup = true
|
d.completedSetup = true
|
||||||
log.debug "created ${d.displayName} with id ${d.deviceNetworkId}"
|
log.debug "created ${d.displayName} with id ${d.deviceNetworkId}"
|
||||||
def childDevice = getChildDevice(d.deviceNetworkId)
|
def childDevice = getChildDevice(d.deviceNetworkId)
|
||||||
childDevice?.sendEvent(name: "status", value: "Online")
|
|
||||||
childDevice?.sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false, isStateChange: true)
|
|
||||||
updateBridgeStatus(childDevice)
|
updateBridgeStatus(childDevice)
|
||||||
|
childDevice.sendEvent(name: "idNumber", value: idNumber)
|
||||||
|
|
||||||
childDevice?.sendEvent(name: "idNumber", value: idNumber)
|
|
||||||
if (vbridge.value.ip && vbridge.value.port) {
|
if (vbridge.value.ip && vbridge.value.port) {
|
||||||
if (vbridge.value.ip.contains(".")) {
|
if (vbridge.value.ip.contains(".")) {
|
||||||
childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port)
|
childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port)
|
||||||
@@ -715,14 +693,10 @@ def doDeviceSync(){
|
|||||||
private void updateBridgeStatus(childDevice) {
|
private void updateBridgeStatus(childDevice) {
|
||||||
// Update activity timestamp if child device is a valid bridge
|
// Update activity timestamp if child device is a valid bridge
|
||||||
def vbridges = getVerifiedHueBridges()
|
def vbridges = getVerifiedHueBridges()
|
||||||
def vbridge = vbridges.find {
|
def vbridge = vbridges.find {"${it.value.mac}".toUpperCase() == childDevice?.device?.deviceNetworkId?.toUpperCase()}
|
||||||
"${it.value.mac}".toUpperCase() == childDevice?.device?.deviceNetworkId?.toUpperCase()
|
|
||||||
}
|
|
||||||
vbridge?.value?.lastActivity = now()
|
vbridge?.value?.lastActivity = now()
|
||||||
if (vbridge && childDevice?.device?.currentValue("status") == "Offline") {
|
if(vbridge) {
|
||||||
log.debug "$childDevice is back Online"
|
|
||||||
childDevice?.sendEvent(name: "status", value: "Online")
|
childDevice?.sendEvent(name: "status", value: "Online")
|
||||||
childDevice?.sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false, isStateChange: true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,7 +710,7 @@ private void checkBridgeStatus() {
|
|||||||
def time = now() - (1000 * 60 * 11)
|
def time = now() - (1000 * 60 * 11)
|
||||||
bridges.each {
|
bridges.each {
|
||||||
def d = getChildDevice(it.value.mac)
|
def d = getChildDevice(it.value.mac)
|
||||||
if (d) {
|
if(d) {
|
||||||
// Set id number on bridge if not done
|
// Set id number on bridge if not done
|
||||||
if (it.value.idNumber == null) {
|
if (it.value.idNumber == null) {
|
||||||
it.value.idNumber = getBridgeIdNumber(it.value.serialNumber)
|
it.value.idNumber = getBridgeIdNumber(it.value.serialNumber)
|
||||||
@@ -744,24 +718,16 @@ private void checkBridgeStatus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (it.value.lastActivity < time) { // it.value.lastActivity != null &&
|
if (it.value.lastActivity < time) { // it.value.lastActivity != null &&
|
||||||
if (d.currentStatus == "Online") {
|
log.warn "Bridge $it.value.idNumber is Offline"
|
||||||
log.warn "$d is Offline"
|
|
||||||
d.sendEvent(name: "status", value: "Offline")
|
d.sendEvent(name: "status", value: "Offline")
|
||||||
d.sendEvent(name: "DeviceWatch-DeviceStatus", value: "offline", displayed: false, isStateChange: true)
|
|
||||||
|
|
||||||
Calendar currentTime = Calendar.getInstance()
|
state.bulbs?.each {
|
||||||
|
it.value.online = false
|
||||||
|
}
|
||||||
getChildDevices().each {
|
getChildDevices().each {
|
||||||
def id = getId(it)
|
it.sendEvent(name: "DeviceWatch-DeviceOffline", value: "offline", isStateChange: true, displayed: false)
|
||||||
if (state.bulbs[id]?.online == true) {
|
|
||||||
state.bulbs[id]?.online = false
|
|
||||||
state.bulbs[id]?.unreachableSince = currentTime.getTimeInMillis()
|
|
||||||
it.sendEvent(name: "DeviceWatch-DeviceStatus", value: "offline", displayed: false, isStateChange: true)
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
} else if (d.currentStatus == "Offline") {
|
|
||||||
log.debug "$d is back Online"
|
|
||||||
d.sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false, isStateChange: true)
|
|
||||||
d.sendEvent(name: "status", value: "Online")//setOnline(false)
|
d.sendEvent(name: "status", value: "Online")//setOnline(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -949,15 +915,8 @@ private handleCommandResponse(body) {
|
|||||||
updates[childDeviceNetworkId]."$eventType" = v
|
updates[childDeviceNetworkId]."$eventType" = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (payload?.error) {
|
} else if (payload.error) {
|
||||||
log.warn "Error returned from Hue bridge, error = ${payload?.error}"
|
log.warn "Error returned from Hue bridge error = ${body?.error}"
|
||||||
// Check for unauthorized user
|
|
||||||
if (payload?.error?.type?.value == 1) {
|
|
||||||
log.error "Hue username is not valid"
|
|
||||||
state.refreshUsernameNeeded = true
|
|
||||||
state.username = null
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,10 +924,13 @@ private handleCommandResponse(body) {
|
|||||||
updates.each { childDeviceNetworkId, params ->
|
updates.each { childDeviceNetworkId, params ->
|
||||||
def device = getChildDevice(childDeviceNetworkId)
|
def device = getChildDevice(childDeviceNetworkId)
|
||||||
def id = getId(device)
|
def id = getId(device)
|
||||||
|
// If device is offline, then don't send events which will update device watch
|
||||||
|
if (isOnline(id)) {
|
||||||
sendBasicEvents(device, "on", params.on)
|
sendBasicEvents(device, "on", params.on)
|
||||||
sendBasicEvents(device, "bri", params.bri)
|
sendBasicEvents(device, "bri", params.bri)
|
||||||
sendColorEvents(device, params.xy, params.hue, params.sat, params.ct)
|
sendColorEvents(device, params.xy, params.hue, params.sat, params.ct)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1000,38 +962,39 @@ private handlePoll(body) {
|
|||||||
|
|
||||||
def bulbs = getChildDevices()
|
def bulbs = getChildDevices()
|
||||||
for (bulb in body) {
|
for (bulb in body) {
|
||||||
def device = bulbs.find { it.deviceNetworkId == "${app.id}/${bulb.key}" }
|
def device = bulbs.find{it.deviceNetworkId == "${app.id}/${bulb.key}"}
|
||||||
if (device) {
|
if (device) {
|
||||||
if (bulb.value.state?.reachable) {
|
if (bulb.value.state?.reachable) {
|
||||||
if (state.bulbs[bulb.key]?.online == false || state.bulbs[bulb.key]?.online == null) {
|
if (state.bulbs[bulb.key]?.online == false) {
|
||||||
// light just came back online, notify device watch
|
// light just came back online, notify device watch
|
||||||
device.sendEvent(name: "DeviceWatch-DeviceStatus", value: "online", displayed: false, isStateChange: true)
|
def lastActivity = now()
|
||||||
|
device.sendEvent(name: "deviceWatch-status", value: "ONLINE", description: "Last Activity is on ${new Date((long) lastActivity)}", displayed: false, isStateChange: true)
|
||||||
log.debug "$device is Online"
|
log.debug "$device is Online"
|
||||||
}
|
}
|
||||||
// Mark light as "online"
|
// Mark light as "online"
|
||||||
state.bulbs[bulb.key]?.unreachableSince = null
|
state.bulbs[bulb.key]?.unreachableSince = null
|
||||||
state.bulbs[bulb.key]?.online = true
|
state.bulbs[bulb.key]?.online = true
|
||||||
} else {
|
|
||||||
if (state.bulbs[bulb.key]?.unreachableSince == null) {
|
|
||||||
// Store the first time where device was reported as "unreachable"
|
|
||||||
state.bulbs[bulb.key]?.unreachableSince = currentTime.getTimeInMillis()
|
|
||||||
}
|
|
||||||
if (state.bulbs[bulb.key]?.online || state.bulbs[bulb.key]?.online == null) {
|
|
||||||
// Check if device was "unreachable" for more than 11 minutes and mark "offline" if necessary
|
|
||||||
if (state.bulbs[bulb.key]?.unreachableSince < time11.getTimeInMillis() || state.bulbs[bulb.key]?.online == null) {
|
|
||||||
log.warn "$device went Offline"
|
|
||||||
state.bulbs[bulb.key]?.online = false
|
|
||||||
device.sendEvent(name: "DeviceWatch-DeviceStatus", value: "offline", displayed: false, isStateChange: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.warn "$device may not reachable by Hue bridge"
|
|
||||||
}
|
|
||||||
// If user just executed commands, then do not send events to avoid confusing the turning on/off state
|
// If user just executed commands, then do not send events to avoid confusing the turning on/off state
|
||||||
if (!state.updating) {
|
if (!state.updating) {
|
||||||
sendBasicEvents(device, "on", bulb.value?.state?.on)
|
sendBasicEvents(device, "on", bulb.value?.state?.on)
|
||||||
sendBasicEvents(device, "bri", bulb.value?.state?.bri)
|
sendBasicEvents(device, "bri", bulb.value?.state?.bri)
|
||||||
sendColorEvents(device, bulb.value?.state?.xy, bulb.value?.state?.hue, bulb.value?.state?.sat, bulb.value?.state?.ct, bulb.value?.state?.colormode)
|
sendColorEvents(device, bulb.value?.state?.xy, bulb.value?.state?.hue, bulb.value?.state?.sat, bulb.value?.state?.ct, bulb.value?.state?.colormode)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (state.bulbs[bulb.key]?.unreachableSince == null) {
|
||||||
|
// Store the first time where device was reported as "unreachable"
|
||||||
|
state.bulbs[bulb.key]?.unreachableSince = currentTime.getTimeInMillis()
|
||||||
|
} else if (state.bulbs[bulb.key]?.online) {
|
||||||
|
// Check if device was "unreachable" for more than 11 minutes and mark "offline" if necessary
|
||||||
|
if (state.bulbs[bulb.key]?.unreachableSince < time11.getTimeInMillis()) {
|
||||||
|
log.warn "$device went Offline"
|
||||||
|
state.bulbs[bulb.key]?.online = false
|
||||||
|
device.sendEvent(name: "DeviceWatch-DeviceOffline", value: "offline", displayed: false, isStateChange: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.warn "$device may not reachable by Hue bridge"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
@@ -1198,6 +1161,22 @@ def setColor(childDevice, huesettings) {
|
|||||||
return "Setting color to $value"
|
return "Setting color to $value"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ping(childDevice) {
|
||||||
|
if (childDevice.device?.deviceNetworkId?.equalsIgnoreCase(selectedHue)) {
|
||||||
|
if (childDevice.device?.currentValue("status")?.equalsIgnoreCase("Online")) {
|
||||||
|
childDevice.sendEvent(name: "deviceWatch-ping", value: "ONLINE", description: "Hue Bridge is reachable", displayed: false, isStateChange: true)
|
||||||
|
return "Bridge is Online"
|
||||||
|
} else {
|
||||||
|
return "Bridge is Offline"
|
||||||
|
}
|
||||||
|
} else if (isOnline(getId(childDevice))) {
|
||||||
|
childDevice.sendEvent(name: "deviceWatch-ping", value: "ONLINE", description: "Hue Light is reachable", displayed: false, isStateChange: true)
|
||||||
|
return "Device is Online"
|
||||||
|
} else {
|
||||||
|
return "Device is Offline"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getId(childDevice) {
|
private getId(childDevice) {
|
||||||
if (childDevice.device?.deviceNetworkId?.startsWith("HUE")) {
|
if (childDevice.device?.deviceNetworkId?.startsWith("HUE")) {
|
||||||
return childDevice.device?.deviceNetworkId[3..-1]
|
return childDevice.device?.deviceNetworkId[3..-1]
|
||||||
@@ -1787,4 +1766,3 @@ def hsvToHex(hue, sat, value = 100){
|
|||||||
|
|
||||||
return "#$r1$g1$b1"
|
return "#$r1$g1$b1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
50
smartapps/smarttings/lds-cct.src/lds-cct.groovy
Normal file
50
smartapps/smarttings/lds-cct.src/lds-cct.groovy
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* LDS_CCT
|
||||||
|
*
|
||||||
|
* Copyright 2016 Jungle
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
definition(
|
||||||
|
name: "LDS_CCT",
|
||||||
|
namespace: "smarttings",
|
||||||
|
author: "Jungle",
|
||||||
|
description: "LDS_CCT",
|
||||||
|
category: "",
|
||||||
|
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 {
|
||||||
|
section("Title") {
|
||||||
|
// TODO: put inputs here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def installed() {
|
||||||
|
log.debug "Installed with settings: ${settings}"
|
||||||
|
|
||||||
|
initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
def updated() {
|
||||||
|
log.debug "Updated with settings: ${settings}"
|
||||||
|
|
||||||
|
unsubscribe()
|
||||||
|
initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
def initialize() {
|
||||||
|
// TODO: subscribe to attributes, devices, locations, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement event handlers
|
||||||
Reference in New Issue
Block a user