The wallmote quad says it supports slide actions - is there any way to get that enabled in hubitat? I found a smartthings driver, but cant get it to load. I was able to get push and hold to work with the built in driver, but there is no slide option.
I experimented with the release function, but it conflicts with the hold.. for example, in my rule touch button 1 turns the light on. hold it and it turns off, but since the hold also has a release to it, whatever you set the release command to is the one that sticks - so if you wanted release to dim it to 50% and hold to turn it off and you set both, it would never turn off and will always go to 50% since the release comes after the hold - hence why slide is important.
Ditto the request for slide actions. It would be cool if it could be configured as a dimmer. I bought one for bedside to trigger "good night" routine so I don't have to sleep with Alexa!
and modified a few items such as physcialgraph to hubitat and a few others. Then I found info about changing def configuration = parseXml(configuration_model) to def configuration = new XmlSlurper().parseText(configuration_model) I did that and then the driver would save and load !! But.. then I went to set the preferences and I get this in the logs - ` error groovy.lang.MissingMethodException: No signature of method: user_driver_erocm123_Aeon_WallMote_Quad___User_762.parseXml() is applicable for argument types: (java.lang.String) values: [
Which model of WallMote is this?
Enable/disable the touch sound.
Default: Enable
Enable/disable the touch vibration.
Default: Enable
Enable/disable the function of button slide.
Default: Enable
To configure which color will be displayed when the button is pressed.
Default: Blue
Multiple "held" events on botton hold? With this option, the controller will send a "held" event about every second while holding down a button. If set to No it will send a "held" event a single time when the button is released.
Default: No
]
Possible solutions: parse(java.lang.String) on line 327 (updated)`
.. so nothing happens.. however the logs are full in info when you touch the wallmote or even slide it..
last but not least - here is the modified code: is doesnt like line 327.. def configuration = new XmlSlurper().parseText(configuration_model) eventhough thats the code it liked before.
/**
* Copyright 2016 Eric Maycock
*
* 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.
*
* Aeon WallMote Dual/Quad
*
* Author: Eric Maycock (erocm123)
* Date: 2017-06-19
*
* 2017-06-19: Added check to only send color change config for three wakeups. Editing preferences
* and hitting "done" will reset the counter. This is an attempt to prevent freezing
* caused by updating preferences.
*/
metadata {
definition (name: "Aeon WallMote Quad - User", namespace: "erocm123", author: "Eric Maycock", vid:"generic-button") {
capability "Actuator"
capability "PushableButton"
capability "HoldableButton"
capability "Configuration"
capability "Sensor"
capability "Battery"
capability "Health Check"
attribute "sequenceNumber", "number"
attribute "numberOfButtons", "number"
attribute "needUpdate", "string"
fingerprint mfr: "0086", prod: "0102", model: "0082", deviceJoinName: "Aeon WallMote"
fingerprint deviceId: "0x1801", inClusters: "0x5E,0x73,0x98,0x86,0x85,0x59,0x8E,0x60,0x72,0x5A,0x84,0x5B,0x71,0x70,0x80,0x7A", outClusters: "0x25,0x26" // secure inclusion
fingerprint deviceId: "0x1801", inClusters: "0x5E,0x85,0x59,0x8E,0x60,0x86,0x70,0x72,0x5A,0x73,0x84,0x80,0x5B,0x71,0x7A", outClusters: "0x25,0x26"
}
preferences {
input description: "Once you change values on this page, the corner of the \"configuration\" icon will change orange until all configuration parameters are updated.", title: "Settings", displayDuringSetup: false, type: "paragraph", element: "paragraph"
generate_preferences(configuration_model())
}
simulator {
}
tiles (scale: 2) {
multiAttributeTile(name:"button", type:"generic", width:6, height:4) {
tileAttribute("device.button", key: "PRIMARY_CONTROL"){
attributeState "default", label:'', backgroundColor:"#ffffff", icon: "st.unknown.zwave.remote-controller"
}
tileAttribute ("device.battery", key: "SECONDARY_CONTROL") {
attributeState "battery", label:'${currentValue} % battery'
}
}
valueTile(
"battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}%', unit:""
}
valueTile(
"sequenceNumber", "device.sequenceNumber", decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}', unit:""
}
standardTile("configure", "device.needUpdate", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "NO" , label:'', action:"configuration.configure", icon:"st.secondary.configure"
state "YES", label:'', action:"configuration.configure", icon:"https://github.com/erocm123/SmartThingsPublic/raw/master/devicetypes/erocm123/qubino-flush-1d-relay.src/configure@2x.png"
}
main "button"
details(["button", "battery", "sequenceNumber", "configure"])
}
}
def parse(String description) {
def results = []
if (description.startsWith("Err")) {
results = createEvent(descriptionText:description, displayed:true)
} else {
def cmd = zwave.parse(description, [0x2B: 1, 0x80: 1, 0x84: 1])
if(cmd) results += zwaveEvent(cmd)
if(!results) results = [ descriptionText: cmd, displayed: false ]
}
return results
}
def zwaveEvent(hubitat.zwave.commands.switchmultilevelv3.SwitchMultilevelStartLevelChange cmd) {
logging("upDown: $cmd.upDown")
switch (cmd.upDown) {
case 0: // Up
buttonEvent(device.currentValue("numberOfButtons"), "pushed")
break
case 1: // Down
buttonEvent(device.currentValue("numberOfButtons"), "held")
break
default:
logging("Unhandled SwitchMultilevelStartLevelChange: ${cmd}")
break
}
}
def zwaveEvent(hubitat.zwave.commands.centralscenev1.CentralSceneNotification cmd) {
logging("keyAttributes: $cmd.keyAttributes")
logging("sceneNumber: $cmd.sceneNumber")
logging("sequenceNumber: $cmd.sequenceNumber")
sendEvent(name: "sequenceNumber", value: cmd.sequenceNumber, displayed:false)
switch (cmd.keyAttributes) {
case 0:
buttonEvent(cmd.sceneNumber, "pushed")
break
case 1: // released
if (!settings.holdMode || settings.holdMode == "2") buttonEvent(cmd.sceneNumber, "held")
break
case 2: // held
if (settings.holdMode == "1") buttonEvent(cmd.sceneNumber, "held")
break
default:
logging("Unhandled CentralSceneNotification: ${cmd}")
break
}
}
def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x5B: 1, 0x20: 1, 0x31: 5, 0x30: 2, 0x84: 1, 0x70: 1])
state.sec = 1
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpIntervalReport cmd)
{
logging("WakeUpIntervalReport ${cmd.toString()}")
state.wakeInterval = cmd.seconds
}
def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
logging("Device ${device.displayName} woke up")
def request = update_needed_settings()
request << zwave.versionV1.versionGet()
if (!state.lastBatteryReport || (now() - state.lastBatteryReport) / 60000 >= 60 * 24)
{
logging("Over 24hr since last battery report. Requesting report")
request << zwave.batteryV1.batteryGet()
}
state.wakeCount? (state.wakeCount = state.wakeCount + 1) : (state.wakeCount = 2)
if(request != []){
response(commands(request) + ["delay 5000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()])
} else {
logging("No commands to send")
response([zwave.wakeUpV1.wakeUpNoMoreInformation().format()])
}
}
def buttonEvent(button, value) {
createEvent(name: "button", value: value, data: [buttonNumber: button], descriptionText: "$device.displayName button $button was $value", isStateChange: true)
}
def zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) {
logging("Battery Report: $cmd")
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastBatteryReport = now()
createEvent(map)
}
def zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd) {
logging("AssociationReport $cmd")
state."association${cmd.groupingIdentifier}" = cmd.nodeId[0]
}
def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd) {
update_current_properties(cmd)
logging("${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd2Integer(cmd.configurationValue)}'")
}
def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
update_current_properties(cmd)
logging("${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd2Integer(cmd.configurationValue)}'")
}
def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) {
def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}"
updateDataValue("fw", fw)
if (state.MSR == "003B-6341-5044") {
updateDataValue("ver", "${cmd.applicationVersion >> 4}.${cmd.applicationVersion & 0xF}")
}
def text = "$device.displayName: firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}"
createEvent(descriptionText: text, isStateChange: false)
}
def zwaveEvent(hubitat.zwave.Command cmd) {
logging("Unhandled zwaveEvent: ${cmd}")
}
def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)
}
def installed() {
logging("installed()")
configure()
}
/**
* Triggered when Done button is pushed on Preference Pane
*/
def updated()
{
logging("updated() is being called")
state.wakeCount = 1
def cmds = update_needed_settings()
sendEvent(name: "checkInterval", value: 2 * 60 * 12 * 60 + 5 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
sendEvent(name: "numberOfButtons", value: settings.buttons ? (settings."3" == "1" ? settings.buttons.toInteger() + 1 : settings.buttons) : (settings."3" ? 4 + 1 : 4), displayed: true)
sendEvent(name:"needUpdate", value: device.currentValue("needUpdate"), displayed:false, isStateChange: true)
if (cmds != []) response(commands(cmds))
}
def configure() {
state.enableDebugging = settings.enableDebugging
logging("Configuring Device For SmartThings Use")
def cmds = []
cmds = update_needed_settings()
sendEvent(name: "numberOfButtons", value: settings.buttons ? (settings."3" == "1" ? settings.buttons.toInteger() + 1 : settings.buttons) : (settings."3" ? 4 + 1 : 4), displayed: true)
if (cmds != []) commands(cmds)
}
def ping() {
logging("ping()")
logging("Battery Device - Not sending ping commands")
}
def generate_preferences(configuration_model)
{
def configuration = new XmlSlurper().parseText(configuration_model)
configuration.Value.each
{
switch(it.@type)
{
case ["byte","short","four"]:
input "${it.@index}", "number",
title:"${it.@label}\n" + "${it.Help}",
range: "${it.@min}..${it.@max}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}"
break
case "list":
def items = []
it.Item.each { items << ["${it.@value}":"${it.@label}"] }
input "${it.@index}", "enum",
title:"${it.@label}\n" + "${it.Help}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}",
options: items
break
case "decimal":
input "${it.@index}", "decimal",
title:"${it.@label}\n" + "${it.Help}",
range: "${it.@min}..${it.@max}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}"
break
case "boolean":
input "${it.@index}", "boolean",
title: it.@label != "" ? "${it.@label}\n" + "${it.Help}" : "" + "${it.Help}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}"
break
}
}
}
def update_current_properties(cmd)
{
def currentProperties = state.currentProperties ?: [:]
currentProperties."${cmd.parameterNumber}" = cmd.configurationValue
if (settings."${cmd.parameterNumber}" != null)
{
if (convertParam(cmd.parameterNumber, settings."${cmd.parameterNumber}") == cmd2Integer(cmd.configurationValue))
{
sendEvent(name:"needUpdate", value:"NO", displayed:false, isStateChange: true)
}
else
{
sendEvent(name:"needUpdate", value:"YES", displayed:false, isStateChange: true)
}
}
state.currentProperties = currentProperties
}
def update_needed_settings()
{
def cmds = []
def currentProperties = state.currentProperties ?: [:]
def configuration = new XmlSlurper().parseText(configuration_model)
def isUpdateNeeded = "NO"
if(state.wakeInterval == null || state.wakeInterval != 86400){
logging("Setting Wake Interval to 86400")
cmds << zwave.wakeUpV1.wakeUpIntervalSet(seconds: 86400, nodeid:zwaveHubNodeId)
cmds << zwave.wakeUpV1.wakeUpIntervalGet()
}
if(settings."3" == "1"){
if(!state.association3 || state.association3 == "" || state.association3 == "1"){
logging("Setting association group 3")
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:zwaveHubNodeId)
cmds << zwave.associationV2.associationGet(groupingIdentifier:3)
}
if(!state.association5 || state.association5 == "" || state.association5 == "1"){
logging("Setting association group 5")
cmds << zwave.associationV2.associationSet(groupingIdentifier:5, nodeId:zwaveHubNodeId)
cmds << zwave.associationV2.associationGet(groupingIdentifier:5)
}
if(!state.association7 || state.association7 == "" || state.association7 == "1"){
logging("Setting association group 7")
cmds << zwave.associationV2.associationSet(groupingIdentifier:7, nodeId:zwaveHubNodeId)
cmds << zwave.associationV2.associationGet(groupingIdentifier:7)
}
if(!state.association9 || state.association9 == "" || state.association9 == "1"){
logging("Setting association group 9")
cmds << zwave.associationV2.associationSet(groupingIdentifier:9, nodeId:zwaveHubNodeId)
cmds << zwave.associationV2.associationGet(groupingIdentifier:9)
}
}
if(state.MSR == null){
logging("Getting Manufacturer Specific Info")
cmds << zwave.manufacturerSpecificV2.manufacturerSpecificGet()
}
configuration.Value.each
{
if ("${it.@setting_type}" == "zwave"){
if (currentProperties."${it.@index}" == null)
{
if (it.@setonly == "true"){
if (it.@index == 5) {
if (state.wakeCount <= 3) {
logging("Parameter ${it.@index} will be updated to " + convertParam(it.@index.toInteger(), settings."${it.@index}"? settings."${it.@index}" : "${it.@value}"))
def convertedConfigurationValue = convertParam(it.@index.toInteger(), settings."${it.@index}"? settings."${it.@index}" : "${it.@value}")
cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertedConfigurationValue, it.@byteSize.toInteger()), parameterNumber: it.@index.toInteger(), size: it.@byteSize.toInteger())
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
} else {
logging ("Parameter has already sent. Will not send again until updated() gets called")
}
} else {
logging("Parameter ${it.@index} will be updated to " + convertParam(it.@index.toInteger(), settings."${it.@index}"? settings."${it.@index}" : "${it.@value}"))
def convertedConfigurationValue = convertParam(it.@index.toInteger(), settings."${it.@index}"? settings."${it.@index}" : "${it.@value}")
cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertedConfigurationValue, it.@byteSize.toInteger()), parameterNumber: it.@index.toInteger(), size: it.@byteSize.toInteger())
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
}
} else {
isUpdateNeeded = "YES"
logging("Current value of parameter ${it.@index} is unknown")
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
}
}
else if (settings."${it.@index}" != null && cmd2Integer(currentProperties."${it.@index}") != convertParam(it.@index.toInteger(), settings."${it.@index}"))
{
isUpdateNeeded = "YES"
if (it.@index == 5) {
if (state.wakeCount <= 3) {
logging("Parameter ${it.@index} will be updated to " + convertParam(it.@index.toInteger(), settings."${it.@index}"))
def convertedConfigurationValue = convertParam(it.@index.toInteger(), settings."${it.@index}")
cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertedConfigurationValue, it.@byteSize.toInteger()), parameterNumber: it.@index.toInteger(), size: it.@byteSize.toInteger())
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
} else {
logging ("Parameter has already sent. Will not send again until updated() gets called")
}
} else {
logging("Parameter ${it.@index} will be updated to " + convertParam(it.@index.toInteger(), settings."${it.@index}"))
def convertedConfigurationValue = convertParam(it.@index.toInteger(), settings."${it.@index}")
cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertedConfigurationValue, it.@byteSize.toInteger()), parameterNumber: it.@index.toInteger(), size: it.@byteSize.toInteger())
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
}
}
}
}
sendEvent(name:"needUpdate", value: isUpdateNeeded, displayed:false, isStateChange: true)
return cmds
}
def convertParam(number, value) {
long parValue
switch (number){
case 5:
switch (value) {
case "1":
parValue = 4278190080
break
case "2":
parValue = 16711680
break
case "3":
parValue = 65280
break
default:
parValue = value
break
}
break
default:
parValue = value.toLong()
break
}
return parValue
}
private def logging(message) {
if (state.enableDebugging == null || state.enableDebugging == "true") log.debug "$message"
}
/**
* Convert 1 and 2 bytes values to integer
*/
def cmd2Integer(array) {
long value
if (array != [255, 0, 0, 0]){
switch(array.size()) {
case 1:
value = array[0]
break
case 2:
value = ((array[0] & 0xFF) << 8) | (array[1] & 0xFF)
break
case 3:
value = ((array[0] & 0xFF) << 16) | ((array[1] & 0xFF) << 8) | (array[2] & 0xFF)
break
case 4:
value = ((array[0] & 0xFF) << 24) | ((array[1] & 0xFF) << 16) | ((array[2] & 0xFF) << 8) | (array[3] & 0xFF)
break
}
} else {
value = 4278190080
}
return value
}
def integer2Cmd(value, size) {
switch(size) {
case 1:
[value.toInteger()]
break
case 2:
def short value1 = value & 0xFF
def short value2 = (value >> 8) & 0xFF
[value2.toInteger(), value1.toInteger()]
break
case 3:
def short value1 = value & 0xFF
def short value2 = (value >> 8) & 0xFF
def short value3 = (value >> 16) & 0xFF
[value3.toInteger(), value2.toInteger(), value1.toInteger()]
break
case 4:
def short value1 = value & 0xFF
def short value2 = (value >> 8) & 0xFF
def short value3 = (value >> 16) & 0xFF
def short value4 = (value >> 24) & 0xFF
[value4.toInteger(), value3.toInteger(), value2.toInteger(), value1.toInteger()]
break
}
}
private command(hubitat.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=1000) {
delayBetween(commands.collect{ command(it) }, delay)
}
def configuration_model()
{
'''
<configuration>
<Value type="list" byteSize="1" index="buttons" label="WallMote Model" min="2" max="4" value="" setting_type="preference" fw="" displayDuringSetup="true">
<Help>
Which model of WallMote is this?
</Help>
<Item label="Dual" value="2" />
<Item label="Quad" value="4" />
</Value>
<Value type="list" byteSize="1" index="1" label="Touch Sound" min="0" max="1" value="1" setting_type="zwave" fw="">
<Help>
Enable/disable the touch sound.
Default: Enable
</Help>
<Item label="Disable" value="0" />
<Item label="Enable" value="1" />
</Value>
<Value type="list" byteSize="1" index="2" label="Touch Vibration" min="0" max="1" value="1" setting_type="zwave" fw="">
<Help>
Enable/disable the touch vibration.
Default: Enable
</Help>
<Item label="Disable" value="0" />
<Item label="Enable" value="1" />
</Value>
<Value type="list" byteSize="1" index="3" label="Button Slide" min="0" max="1" value="1" setting_type="zwave" fw="">
<Help>
Enable/disable the function of button slide.
Default: Enable
</Help>
<Item label="Disable" value="0" />
<Item label="Enable" value="1" />
</Value>
<Value type="list" byteSize="4" index="5" label="Color" min="1" max="3" value="3" setting_type="zwave" fw="" setonly="true">
<Help>
To configure which color will be displayed when the button is pressed.
Default: Blue
</Help>
<Item label="Red" value="1" />
<Item label="Green" value="2" />
<Item label="Blue" value="3" />
</Value>
<Value type="list" byteSize="4" index="holdMode" label="Hold Mode" min="1" max="2" value="2" setting_type="preference" fw="">
<Help>
Multiple "held" events on botton hold? With this option, the controller will send a "held" event about every second while holding down a button. If set to No it will send a "held" event a single time when the button is released.
Default: No
</Help>
<Item label="No" value="2" />
<Item label="Yes" value="1" />
</Value>
<Value type="boolean" index="enableDebugging" label="Enable Debug Logging?" value="true" setting_type="preference" fw="">
<Help>
</Help>
</Value>
</configuration>
'''
}
Also curious myself, as they are on sale and look enticing. Though without the sliding function, I might as well keep my two-position switches instead.
I just tried this out and when I went to hit 'configure' I received an error about line 327 and it did not seem to work. So I reverted to the the backup I created immediately before my test. No harm no foul. Would also be interested to know if @darby427 or anyone else was able to get this working? Thanks
Sorry guys.. no luck here.. I try a few more things but could never get it to work so I just gave up and I use it as basically an 8 button device. Someone I think @codahq - said they were working on something in one of the YouTube live broadcasts but I don't know that anything's come of it..
Yes, it's on my todo list. Unfortunately, it's pretty far down the list of priorities. I'm pretty sure the SmartThings device handler already supports the swiping actions as button presses. There's a good chance somebody can take that, capture the responses from swiping in Hubitat and turn them into button events. I'll get to it eventually.