Compare commits

...

17 Commits

Author SHA1 Message Date
Vinay Rao
728b169a08 Merge pull request #2143 from SmartThingsCommunity/staging
Rolling up staging to production
2017-07-05 14:16:16 -07:00
Vinay Rao
d2f981fd34 Merge pull request #2142 from SmartThingsCommunity/production
Rolling down production to staging
2017-07-05 14:13:37 -07:00
Vinay Rao
a58dd2094d Merge pull request #2137 from twack/update-gopher-water-valve-initail-state
(ICP-1050) Added check gopher valve initial state in installed()
2017-07-05 13:57:44 -07:00
twack
c549a5bed0 Added check valve initial state in installed() 2017-07-04 08:10:09 -07:00
Vinay Rao
ef5fffc4bc Merge pull request #2133 from jackchi/health-dhf-16
[DHF-16] ZigBee Button Device Health Update
2017-06-30 11:17:31 -07:00
jackchi
c370e88a6b [DHF-16] ZigBee Button Device Health Update 2017-06-30 10:44:20 -07:00
Vinay Rao
ce8c50c630 Merge pull request #2128 from marstorp/icp1148EcobeeHotfix
ICP-1148 Support Thermostat Dynamic data
2017-06-27 16:29:03 -07:00
marstorp
b069669c11 ICP-1148 Support Thermostat Dynamic data
Adding default "off" thermostat mode as it is not provided by the thermostat.
2017-06-27 16:19:49 -07:00
Vinay Rao
4d61d28b42 Merge pull request #2127 from SmartThingsCommunity/master
Rolling up master to staging
2017-06-27 16:05:32 -07:00
Vinay Rao
4547d0543b Merge pull request #2126 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-27 16:03:00 -07:00
Vinay Rao
6b1e41198c Merge pull request #2125 from SmartThingsCommunity/staging
Rolling up staging to production
2017-06-27 15:07:38 -07:00
Vinay Rao
5aee3a1861 Merge pull request #2114 from marstorp/icp1148dynamicModeSupport
ICP-1148 Support Thermostat Dynamic data
2017-06-23 14:15:56 -07:00
marstorp
17ae692aa0 ICP-1148 Support Thermostat Dynamic data
Adding support for dynamic thermostat and fan modes to ecobee
2017-06-23 13:24:03 -07:00
Vinay Rao
f02428b99f Merge pull request #2113 from larsfinander/DVCSMP-2702_smartpower-outlet_remove_light_staging
DVCSMP-2702 smartpower-outlet DTH incorrectly has capability.light
2017-06-22 12:25:26 -07:00
Lars Finander
34174b730c DVCSMP-2702 smartpower-outlet DTH incorrectly has capability.light 2017-06-22 13:13:08 -06:00
Vinay Rao
12f874408a Merge pull request #2110 from SmartThingsCommunity/master
Rolling up master to staging
2017-06-20 11:46:47 -07:00
Vinay Rao
f752a01906 Merge pull request #2108 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2017-06-20 11:29:13 -07:00
5 changed files with 45 additions and 57 deletions

View File

@@ -70,7 +70,7 @@ metadata {
state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat" state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat"
state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool" state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool"
state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto" state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto"
state "emergency heat", action:"switchMode", icon: "st.thermostat.emergency-heat" // emergency heat = auxHeatOnly state "auxheatonly", action:"switchMode", icon: "st.thermostat.emergency-heat"
state "updating", label:"Working", icon: "st.secondary.secondary" state "updating", label:"Working", icon: "st.secondary.secondary"
} }
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") { standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
@@ -156,47 +156,49 @@ void poll() {
def generateEvent(Map results) { def generateEvent(Map results) {
log.debug "parsing data $results" log.debug "parsing data $results"
if(results) { if(results) {
results.each { name, value ->
def linkText = getLinkText(device) def linkText = getLinkText(device)
def isChange = false def supportedThermostatModes = ["off"]
def isDisplayed = true def thermostatMode = null
results.each { name, value ->
def event = [name: name, linkText: linkText, descriptionText: getThermostatDescriptionText(name, value, linkText), def event = [name: name, linkText: linkText, descriptionText: getThermostatDescriptionText(name, value, linkText),
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 = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
isChange = isTemperatureStateChange(device, name, value.toString()) event << [value: sendValue, unit: temperatureScale]
isDisplayed = isChange
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 = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
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()) if (value == true) {
event << [value: value.toString(), isStateChange: isChange, displayed: false] supportedThermostatModes << ((name == "auxHeatMode") ? "auxheatonly" : name - "Mode")
}
return // as we don't want to send this event here, proceed to next name/value pair
} else if (name=="thermostatFanMode"){ } else if (name=="thermostatFanMode"){
isChange = isStateChange(device, name, value.toString()) sendEvent(name: "supportedThermostatFanModes", value: fanModes(), displayed: false)
event << [value: value.toString(), isStateChange: isChange, displayed: false] event << [value: value.toString(), data:[supportedThermostatFanModes: fanModes()]]
} else if (name=="humidity") { } else if (name=="humidity") {
isChange = isStateChange(device, name, value.toString()) event << [value: value.toString(), displayed: false, unit: "%"]
event << [value: value.toString(), isStateChange: isChange, displayed: false, unit: "%"]
} else if (name == "deviceAlive") { } else if (name == "deviceAlive") {
isChange = isStateChange(device, name, value.toString())
event['isStateChange'] = isChange
event['displayed'] = false event['displayed'] = false
} else if (name == "thermostatMode") { } else if (name == "thermostatMode") {
def mode = value.toString() thermostatMode = value.toLowerCase()
mode = (mode == "auxHeatOnly") ? "emergency heat" : mode return // as we don't want to send this event here, proceed to next name/value pair
isChange = isStateChange(device, name, mode)
event << [value: mode, isStateChange: isChange, displayed: isDisplayed]
} else { } else {
isChange = isStateChange(device, name, value.toString()) event << [value: value.toString()]
isDisplayed = isChange
event << [value: value.toString(), isStateChange: isChange, displayed: isDisplayed]
} }
sendEvent(event) sendEvent(event)
} }
if (state.supportedThermostatModes != supportedThermostatModes) {
state.supportedThermostatModes = supportedThermostatModes
sendEvent(name: "supportedThermostatModes", value: supportedThermostatModes, displayed: false)
}
if (thermostatMode) {
sendEvent(name: "thermostatMode", value: thermostatMode, data:[supportedThermostatModes:state.supportedThermostatModes], linkText: linkText,
descriptionText: getThermostatDescriptionText("thermostatMode", thermostatMode, linkText), handlerName: "thermostatMode")
}
generateSetpointEvent () generateSetpointEvent ()
generateStatusEvent () generateStatusEvent ()
} }
@@ -322,15 +324,7 @@ void resumeProgram() {
} }
def modes() { def modes() {
if (state.modes) { return state.supportedThermostatModes
log.debug "Modes = ${state.modes}"
return state.modes
}
else {
state.modes = parent.availableModes(this)
log.debug "Modes = ${state.modes}"
return state.modes
}
} }
def fanModes() { def fanModes() {
@@ -413,11 +407,13 @@ def setThermostatFanMode(String mode) {
} }
def generateModeEvent(mode) { def generateModeEvent(mode) {
sendEvent(name: "thermostatMode", value: mode, descriptionText: "$device.displayName is in ${mode} mode", displayed: true) sendEvent(name: "thermostatMode", value: mode, data:[supportedThermostatModes: state.supportedThermostatModes],
descriptionText: "$device.displayName is in ${mode} mode")
} }
def generateFanModeEvent(fanMode) { def generateFanModeEvent(fanMode) {
sendEvent(name: "thermostatFanMode", value: fanMode, descriptionText: "$device.displayName fan is in ${fanMode} mode", displayed: true) sendEvent(name: "thermostatFanMode", value: fanMode, data:[supportedThermostatFanModes: fanModes()],
descriptionText: "$device.displayName fan is in ${fanMode} mode")
} }
def generateOperatingStateEvent(operatingState) { def generateOperatingStateEvent(operatingState) {
@@ -453,14 +449,14 @@ def heat() {
} }
def emergencyHeat() { def emergencyHeat() {
auxHeatOnly() auxheatonly()
} }
def auxHeatOnly() { def auxheatonly() {
log.debug "auxHeatOnly = emergency heat" log.debug "auxheatonly()"
def deviceId = device.deviceNetworkId.split(/\./).last() def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode ("auxHeatOnly", deviceId)) if (parent.setMode ("auxHeatOnly", deviceId))
generateModeEvent("emergency heat") // emergency heat = auxHeatOnly generateModeEvent("auxheatonly")
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
@@ -593,7 +589,7 @@ def generateSetpointEvent() {
} else if (mode == "off") { } else if (mode == "off") {
sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale) sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale)
sendEvent("name":"displayThermostatSetpoint", "value":"Off", displayed: false) sendEvent("name":"displayThermostatSetpoint", "value":"Off", displayed: false)
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly } else if (mode == "auxheatonly") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale) sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false) sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false)
} }
@@ -632,7 +628,7 @@ void raiseSetpoint() {
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0 targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5 targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5
if ((mode == "heat" || mode == "emergency heat") && targetvalue > maxHeatingSetpoint) { // emergency heat = auxHeatOnly if ((mode == "heat" || mode == "auxheatonly") && targetvalue > maxHeatingSetpoint) {
targetvalue = maxHeatingSetpoint targetvalue = maxHeatingSetpoint
} else if (mode == "cool" && targetvalue > maxCoolingSetpoint) { } else if (mode == "cool" && targetvalue > maxCoolingSetpoint) {
targetvalue = maxCoolingSetpoint targetvalue = maxCoolingSetpoint
@@ -678,7 +674,7 @@ void lowerSetpoint() {
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0 targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5 targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5
if ((mode == "heat" || mode == "emergency heat") && targetvalue < minHeatingSetpoint) { // emergency heat = auxHeatOnly if ((mode == "heat" || mode == "auxheatonly") && targetvalue < minHeatingSetpoint) {
targetvalue = minHeatingSetpoint targetvalue = minHeatingSetpoint
} else if (mode == "cool" && targetvalue < minCoolingSetpoint) { } else if (mode == "cool" && targetvalue < minCoolingSetpoint) {
targetvalue = minCoolingSetpoint targetvalue = minCoolingSetpoint
@@ -719,7 +715,7 @@ void alterSetpoint(temp) {
} }
//step1: check thermostatMode, enforce limits before sending request to cloud //step1: check thermostatMode, enforce limits before sending request to cloud
if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly if (mode == "heat" || mode == "auxheatonly"){
if (temp.value > coolingSetpoint){ if (temp.value > coolingSetpoint){
targetHeatingSetpoint = temp.value targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value targetCoolingSetpoint = temp.value
@@ -754,7 +750,7 @@ void alterSetpoint(temp) {
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}" log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
} else { } else {
log.error "Error alterSetpoint()" log.error "Error alterSetpoint()"
if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly if (mode == "heat" || mode == "auxheatonly"){
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false) sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false) sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
} else if (mode == "cool") { } else if (mode == "cool") {
@@ -783,7 +779,7 @@ def generateStatusEvent() {
log.debug "Cooling set point = ${coolingSetpoint}" log.debug "Cooling set point = ${coolingSetpoint}"
log.debug "HVAC Mode = ${mode}" log.debug "HVAC Mode = ${mode}"
if (mode == "heat") { if (mode == "heat" || mode == "auxheatonly") {
if (temperature >= heatingSetpoint) { if (temperature >= heatingSetpoint) {
statusText = "Right Now: Idle" statusText = "Right Now: Idle"
} else { } else {
@@ -806,8 +802,6 @@ def generateStatusEvent() {
} }
} else if (mode == "off") { } else if (mode == "off") {
statusText = "Right Now: Off" statusText = "Right Now: Off"
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
statusText = "Emergency Heat"
} else { } else {
statusText = "?" statusText = "?"
} }

View File

@@ -23,7 +23,6 @@ metadata {
capability "Refresh" capability "Refresh"
capability "Sensor" capability "Sensor"
capability "Health Check" capability "Health Check"
capability "Light"
capability "Outlet" capability "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet"

View File

@@ -28,9 +28,8 @@ Works with:
## Device Health ## Device Health
SmartThings platform will ping the device after `checkInterval` seconds of inactivity in last attempt to reach the device before marking it `OFFLINE` ZigBee Button is marked offline only in the case when Hub is offline.
* __722min__ checkInterval
## Troubleshooting ## Troubleshooting

View File

@@ -13,6 +13,8 @@
* for the specific language governing permissions and limitations under the License. * for the specific language governing permissions and limitations under the License.
* *
*/ */
import groovy.json.JsonOutput
import physicalgraph.zigbee.zcl.DataType import physicalgraph.zigbee.zcl.DataType
metadata { metadata {
@@ -183,13 +185,6 @@ private Map parseNonIasButtonMessage(Map descMap){
} }
} }
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
refresh()
}
def refresh() { def refresh() {
log.debug "Refreshing Battery" log.debug "Refreshing Battery"
@@ -198,8 +193,6 @@ def refresh() {
} }
def configure() { def configure() {
// Device-Watch allows 2 check-in misses from device (plus 2 mins lag time)
sendEvent(name: "checkInterval", value: 2 * 6 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting, IAS CIE, and Bindings." log.debug "Configuring Reporting, IAS CIE, and Bindings."
def cmds = [] def cmds = []
if (device.getDataValue("model") == "3450-L") { if (device.getDataValue("model") == "3450-L") {
@@ -259,6 +252,8 @@ def updated() {
} }
def initialize() { def initialize() {
// Arrival sensors only goes OFFLINE when Hub is off
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false)
if ((device.getDataValue("manufacturer") == "OSRAM") && (device.getDataValue("model") == "LIGHTIFY Dimming Switch")) { if ((device.getDataValue("manufacturer") == "OSRAM") && (device.getDataValue("model") == "LIGHTIFY Dimming Switch")) {
sendEvent(name: "numberOfButtons", value: 2) sendEvent(name: "numberOfButtons", value: 2)
} }

View File

@@ -58,6 +58,7 @@ metadata {
def installed() { def installed() {
// Device-Watch simply pings if no device events received for 32min(checkInterval) // 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]) sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
response(refresh())
} }
def updated() { def updated() {