I do use a device handler too… Posting the code for it as well.
/**
-
MIMOlite as a Garage Door Control with Potentiometer Multi Sensor
-
-
Copyright 2016 Simon Capper
-
-
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.
-
-
Inspired by a similar handler written by https://community.smartthings.com/users/johnconstantelo
*/
metadata {
definition (name: “MIMOlite - Garage Door Control”, namespace: “skyjunky”, author: “Simon Capper”) {
capability “Polling”
capability “Refresh”
capability “Momentary”
capability “Configuration”
capability “Switch”
capability “Actuator”
attribute “powerSupply”, “string”
attribute “doorPosition”, “number”
attribute “doorPositionClosed”, “number”
attribute “doorPositionOpen”, “number”
command “setOpenPosition”
command “setClosedPosition”
fingerprint deviceId:“0x1000”, inClusters:“0x72, 0x86, 0x71, 0x30, 0x31, 0x35, 0x70, 0x85, 0x25”
}
// UI tile definitions
tiles(scale:2) {
multiAttributeTile(name:“door”, type: “generic”, width: 6, height: 4){
tileAttribute (“device.door”, key: “PRIMARY_CONTROL”) {
attributeState “open”, label: “Open”, action: “push”, icon: “st.doors.garage.garage-open”, backgroundColor: “#ffa81e”, nextState:“closing”
attributeState “opening”, label: “Opening”, action: “push”, icon: “st.doors.garage.garage-opening”, backgroundColor: “#ffffff”, nextState:“closing”
attributeState “closed”, label: “Closed”, action: “push”, icon: “st.doors.garage.garage-closed”, backgroundColor: “#79b821”, nextState:“opening”
attributeState “closing”, label: “Closing”, action: “push”, icon: “st.doors.garage.garage-closing”, backgroundColor: “#ffffff”, nextState:“opening”
attributeState “unknown”, label: “Power Out”, icon: “st.alarm.alarm.alarm”, backgroundColor: “#bc2323”
}
tileAttribute (“powerSupply”, key: “SECONDARY_CONTROL”) {
attributeState “good”, label: “Power Good”
attributeState “powerOutOpen”, label: “Power Out - Door Open”
attributeState “powerOutClosed”, label: “Power Out - Door Closed”
}
}
valueTile (“doorPositionOpen”, “device.doorPositionOpen”, width: 5, height: 1) {
state “doorPositionOpen”, label: ‘Configured Open Position ${currentValue}’
}
standardTile (“setOpenPos”, “setOpenPos”, decoration: “flat” ) {
state “setOpenPos”, label: ‘’, action: ‘setOpenPosition’, icon: “st.secondary.configure”
}
valueTile (“doorPositionClosed”, “device.doorPositionClosed”, width: 5, height: 1) {
state “doorPositionClosed”, label: ‘Configured Close Position ${currentValue}’
}
standardTile (“setClosedPos”, “setClosedPos”, decoration: “flat”) {
state “setClosedPos”, label: ‘’, action: ‘setClosedPosition’, icon: “st.secondary.configure”
}
valueTile (“doorPosition”, “device.doorPosition”, width: 5, height: 1) {
state “doorPosition”, label: ‘Current Door Position ${currentValue}’
}
main "door"
details(["door", "doorPositionOpen", "setOpenPos",
"doorPositionClosed", "setClosedPos", "doorPosition"])
}
}
def parse(String description) {
def result = null
// supported classes
// 0x20 - BasicSet used to report when the sensor trigger level changes
// 0x25 - switch binary V1
// 0x30 - sensor binary V1
// 0x31 - sensor multilevel V1
// 0x35 - meter pulse (not tested)
// 0x70 - configuration V1
// 0x71 - alarm V1 (for supply voltage monitor, does not seem to respond to AlarmGet)
// 0x72 - manufacturer specific V1
// 0x85 - association V1
// 0x86 - version V1
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x86: 1, 0x30: 1, 0x31: 1, 0x72: 1, 0x71: 1])
if (cmd) {
result = createEvent(zwaveEvent(cmd))
if (result) {
log.debug "Parsed command: ${result?.descriptionText} raw: ${description}"
} else {
log.debug "Unhandled command: ${description}"
}
} else {
log.debug "Unparsed command: ${description}"
}
return result
}
def getSensitivity() {
return 0x1
}
def getPotOpen() {
def rc = device.currentValue(“doorPositionOpen”)
if (rc == null) {
sendEvent(name: “doorPositionOpen”, value: 158)
return 158
}
return rc
}
def getPotClosed() {
def rc = device.currentValue(“doorPositionClosed”)
if (rc == null) {
sendEvent(name: “doorPositionClosed”, value: 0)
return 0
}
return rc
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
// trigger fires, request the door position so we can see what state it is in
poll().collect { sendHubCommand(new physicalgraph.device.HubAction(it)) }
return null
}
def zwaveEvent(physicalgraph.zwave.commands.alarmv1.AlarmReport cmd) {
if (cmd.alarmLevel) {
if (device.currentValue(“door”) == “closed”) {
sendEvent(name: “powerSupply”, value: “powerOutClosed”)
} else {
sendEvent(name: “powerSupply”, value: “powerOutOpen”)
}
return [name: “door”, value: “unknown”]
}
return null
}
def convertSensorValueToDoorState( BigDecimal sensorValue ) {
def upper = (potOpen < potClosed) ? potClosed : potOpen
def lower = (potOpen > potClosed) ? potClosed : potOpen
def upperState = (potOpen > potClosed) ? “open” : “closed”
def lowerState = (potOpen < potClosed) ? “open” : “closed”
if (sensorValue >= (upper - sensitivity)) {
return upperState
} else if (sensorValue <= (lower + sensitivity)) {
return lowerState
} else if (device.currentValue('door') == "open") {
return 'closing'
} else if (device.currentValue('door') == "closed") {
return 'opening'
}
return device.currentValue('door')
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd) {
// if we are in a power fail state this is the first message we’ll get after the power comes back
// so update the powerState
if (device.currentValue(‘powerSupply’) != “good”) {
sendEvent(name: “powerSupply”, value: “good”)
}
def adjustedValue = cmd.scaledSensorValue.intValue() >> 4
if (adjustedValue != device.currentValue('doorPosition')) {
def doorState = convertSensorValueToDoorState( adjustedValue )
sendEvent(name: "doorPosition", value: adjustedValue)
if (device.currentValue('door') != doorState) {
return [name: "door", value: doorState]
}
}
return null
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren’t interested in
return null
}
def setOpenPosition() {
sendEvent(name: “doorPositionOpen”, value: device.currentValue(‘doorPosition’))
setTriggerLevels().collect { sendHubCommand(new physicalgraph.device.HubAction(it)) }
}
def setClosedPosition() {
sendEvent(name: “doorPositionClosed”, value: device.currentValue(‘doorPosition’))
setTriggerLevels().collect { sendHubCommand(new physicalgraph.device.HubAction(it)) }
}
def on() {
open()
}
def off() {
close()
}
def open() {
if (device.currentValue(“door”) == “closed”) {
push()
}
}
def close() {
if (device.currentValue(“door”) == “open”) {
push()
}
}
def push() {
def cmds = delayBetween([
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xff).format(),
],500)
return cmds
}
def poll() {
delayBetween([
zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
],500)
}
def refresh() {
delayBetween([
zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
],500)
}
def updated() {
// called when the device is updated
configure()
}
def installed() {
// called when the device is installed
configure()
}
def setTriggerLevels() {
def openVal = getPotOpen()
def closedVal = getPotClosed()
def slop = getSensitivity()
// if the potentiometer is installed backwards reverse the parameters
if (openVal < closedVal) {
def temp = closedVal
closedVal = openVal
openVal = temp
}
def lowerValHigh = closedVal + (2 * slop)
def lowerValLow = closedVal + slop
def upperValHigh = openVal - slop
def upperValLow = openVal - (2 * slop)
delayBetween([
// Lower Threshold, High (Default=0xBB)
zwave.configurationV1.configurationSet(scaledConfigurationValue: lowerValHigh, parameterNumber: 4, size: 2).format(),
// Lower Threshold, Low (Default=0xAB)
zwave.configurationV1.configurationSet(scaledConfigurationValue: lowerValLow, parameterNumber: 5, size: 2).format(),
// Upper Threshold, High (Default=0xFF)
zwave.configurationV1.configurationSet(scaledConfigurationValue: upperValHigh, parameterNumber: 6, size: 2).format(),
// Upper Threshold, Low (Default = 0xFE)
zwave.configurationV1.configurationSet(scaledConfigurationValue: upperValLow, parameterNumber: 7, size: 2).format(),
],500)
}
def configure() {
log.debug “configure”
def cmds = delayBetween([
// enable analog alert thresholds
zwave.configurationV1.configurationSet(scaledConfigurationValue: 0, parameterNumber: 8, size: 2).format(),
// turn on momentary button press, this presses it for 1 second
zwave.configurationV1.configurationSet(scaledConfigurationValue: 10, parameterNumber: 11, size: 2).format(),
// tell device to send multivalue sensor updates every 10 seconds
zwave.configurationV1.configurationSet(scaledConfigurationValue: 1, parameterNumber: 9, size: 2).format(),
// enable alarms to be sent to smartthings hub
zwave.associationV1.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format(),
// enable multivalue sensor updates to be sent to smartthings hub
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format(),
],500)
cmds += setTriggerLevels()
return cmds
}