Thank you @Fuzzyligic!! it works!
Release: V1.4 See all details on first post
both Device Handler & Smartapp need to be updated for new features
Thank you @Fuzzyligic!! it works!
both Device Handler & Smartapp need to be updated for new features
cool glad it works. Just noticed you credited me in first post cheers
no worries - Iāve just credited you now in the Device Handler as well
Hi,
I suppose the device handler I have cobbled together might go better on here.
I have a Z-Wave.Me secure keyfob Pert Number: ZME-KFOB-S
I have almost just done what you have just done with the help of @Fuzzyligic.
I used the config from his device handler as yours was knocking off the 4th button on my keyfob for some reason.
I then used the body from your device handler, modified the scene numbers, added some more scenes (Click then hold).
The click and hold function wont work until a smartapp will recognise it though.
This all seems to work.
Anyway here is the code, you may be able to add it to yours, or if not add it as an extra.
`
/**
* Copyright 2016 milesfrankland
* Originals from AdamV and Fuzzyligic
*
* 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.
*
* TODO:
* Get Double Click working
* Create Smartapp to handle dim events
*
*/
metadata {
definition (name: "Secure Z-Wave.me Keyfob ZME-KFOB-S", author: "milesfrankland") {
capability "Actuator"
capability "Button"
capability "Battery"
capability "Configuration"
capability "Refresh"
fingerprint deviceId: "0x1801", inClusters: "0x5E, 0x70, 0x85, 0x2D, 0x8E, 0x80, 0x84, 0x8F, 0x5A, 0x59, 0x5B, 0x73, 0x86, 0x72, 0xEF, 0x20, 0x5B, 0x26, 0x27, 0x2B, 0x60"
}
simulator {
status "button 1 pushed": "command: 9881, payload: 00 5B 03 DE 00 01"
// need to redo simulator commands
}
tiles {
standardTile("button", "device.button", width: 2, height: 2) {
state "default", label: "", icon: "st.Home.home30", backgroundColor: "#ffffff"
state "held", label: "holding", icon: "st.Home.home30", backgroundColor: "#C390D4"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
tileAttribute ("device.battery", key: "PRIMARY_CONTROL"){
state "battery", label:'${currentValue}% battery', unit:""
}
}
standardTile("configure", "device.button", width: 1, height: 1, decoration: "flat") {
state "default", label: "configure", backgroundColor: "#ffffff", action: "configure"
}
main "button"
details(["button", "battery", "configure"])
}
}
def parse(String description) {
def results = []
log.debug("RAW command: $description")
if (description.startsWith("Err")) {
log.debug("An error has occurred")
}
else {
def cmd = zwave.parse(description.replace("98C1", "9881"), [0x98: 1, 0x20: 1, 0x84: 1, 0x80: 1, 0x60: 3, 0x2B: 1, 0x26: 1])
// log.debug "Parsed Command: $cmd"
if (cmd) {
results = zwaveEvent(cmd)
}
}
/*
// OLD logic for default configuration:
def BUTTON_IDs = [ 1, 2, 5, 6 ]
// Split string by comma xter, will return an array.
String [] sections = description.split( "," )
// log.debug("sections: $sections")
// Remove all whitespace from beginning and end of each section string.
for (def i = 0; i < sections.length; i++) {
sections[ i ] = sections[ i ].trim()
}
// log.debug("Trimmed sections: $sections")
// Fetch the command and payload strings from the sections array.
String command = sections[ 1 ]
String payload = sections[ 2 ]
// log.debug( "Command: $command" )
// log.debug( "Payload: $payload" )
// Get the command ID and payload ID from these strings.
String commandID = command[-4..-1]
String payloadID = payload[-2..-1]
// log.debug( "CommandID: $commandID" )
// log.debug( "PayloadID: $payloadID" )
// Coerce the payloadID to a Number from a string (using base 10 as radix)
Integer payloadIDint = payloadID.toInteger()
// log.debug(payloadIDint)
*/
/*
// Determine which button was pressed.
if ( commandID == "9881" && payloadIDint == BUTTON_IDs[ 0 ]) {
Integer button = 1
results = createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( commandID == "9881" && payloadIDint == BUTTON_IDs[ 1 ]) {
Integer button = 2
results = createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( commandID == "9881" && payloadIDint == BUTTON_IDs[ 2 ]) {
Integer button = 3
results = createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( commandID == "9881" && payloadIDint == BUTTON_IDs[ 3 ]) {
Integer button = 4
results = createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( commandID == "98C1" && payloadIDint == BUTTON_IDs[ 0 ]) {
Integer button = 1
results = createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true)
log.debug( "Button $button was held" )
}
else if ( commandID == "98C1" && payloadIDint == BUTTON_IDs[ 1 ]) {
Integer button = 2
results = createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was held" )
}
else if ( commandID == "98C1" && payloadIDint == BUTTON_IDs[ 2 ]) {
Integer button = 4
results = createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was held" )
}
else if ( commandID == "98C1" && payloadIDint == BUTTON_IDs[ 3 ]) {
Integer button = 4
results = createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was held" )
}
else {
log.debug( "Commands and Button ID combinations unaccounted for happened" )
}
return results
// return commandID
*/
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x98: 1, 0x20: 1])
// can specify command class versions here like in zwave.parse
if (encapsulatedCommand) {
log.debug(encapsulatedCommand)
return zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.commands.centralscenev1.CentralSceneNotification cmd) {
log.debug( "keyAttributes: $cmd.keyAttributes")
log.debug( "sceneNumber: $cmd.sceneNumber")
log.debug( "sequenceNumber: $cmd.sequenceNumber")
// log.debug( "payload: $cmd.payload")
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
[ createEvent(descriptionText: "${device.displayName} woke up"),
response(zwave.wakeUpV1.wakeUpNoMoreInformation()) ]
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelGet cmd) {
log.debug "Multilevel get: $cmd"
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
log.debug "Multilevel report: $cmd"
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) { // Special value for low battery alert
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
log.debug ("Battery: $cmd.batteryLevel")
}
// Store time of last battery update so we don't ask every wakeup, see WakeUpNotification handler
state.lastbatt = new Date().time
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd){
log.debug "basic event: $cmd.value"
}
def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
//log.debug( "Dimming Duration: $cmd.dimmingDuration")
//log.debug( "Button code: $cmd.sceneId")
if ( cmd.sceneId == 11 ) {
Integer button = 1
sendEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( cmd.sceneId == 12 ) {
Integer button = 1
sendEvent(name: "button", value: "doubleclick", data: [buttonNumber: button], descriptionText: "$device.displayName Button $button was Double Clicked", isStateChange: true)
log.debug( "Button $button was Double Clicked" )
}
else if ( cmd.sceneId == 13 ) {
Integer button = 1
sendEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "Button $button is closed", isStateChange: true)
log.debug( "Button $button Hold start - held" )
}
else if ( cmd.sceneId == 15 ) {
Integer button = 1
sendEvent(name: "button", value: "holdRelease", data: [buttonNumber: button], descriptionText: "Button $button is open")
log.debug( "Button $button Hold stop" )
}
else if ( cmd.sceneId == 14 ) {
Integer button = 1
sendEvent(name: "button", value: "clickheld", data: [buttonNumber: button], descriptionText: "Button $button is click-closed")
log.debug( "Button $button Click-Hold start - held" )
}
else if ( cmd.sceneId == 16 ) {
Integer button = 1
sendEvent(name: "button", value: "clickholdRelease", data: [buttonNumber: button], descriptionText: "Button $button is click-open")
log.debug( "Button $button Click-Hold stop" )
}
else if ( cmd.sceneId == 21 ) {
Integer button = 2
sendEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( cmd.sceneId == 22 ) {
Integer button = 2
sendEvent(name: "button", value: "doubleclick", data: [buttonNumber: button], descriptionText: "$device.displayName Button $button was Double Clicked", isStateChange: true)
log.debug( "Button $button was Double Clicked" )
}
else if ( cmd.sceneId == 23 ) {
Integer button = 2
sendEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "Button $button is closed")
log.debug( "Button $button Hold start - held" )
}
else if ( cmd.sceneId == 25 ) {
Integer button = 2
sendEvent(name: "button", value: "holdRelease", data: [buttonNumber: button], descriptionText: "Button $button is open")
log.debug( "Button $button Hold stop" )
}
else if ( cmd.sceneId == 24 ) {
Integer button = 2
sendEvent(name: "button", value: "clickheld", data: [buttonNumber: button], descriptionText: "Button $button is click-closed")
log.debug( "Button $button Click-Hold start - held" )
}
else if ( cmd.sceneId == 26 ) {
Integer button = 2
sendEvent(name: "button", value: "clickholdRelease", data: [buttonNumber: button], descriptionText: "Button $button is click-open")
log.debug( "Button $button Click-Hold stop" )
}
else if ( cmd.sceneId == 31 ) {
Integer button = 3
sendEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( cmd.sceneId == 32 ) {
Integer button = 3
sendEvent(name: "button", value: "doubleclick", data: [buttonNumber: button], descriptionText: "$device.displayName Button $button was Double Clicked", isStateChange: true)
log.debug( "Button $button was Double Clicked" )
}
else if ( cmd.sceneId == 33 ) {
Integer button = 3
sendEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "Button $button is closed")
log.debug( "Button $button Hold start - held" )
}
else if ( cmd.sceneId == 35 ) {
Integer button = 3
sendEvent(name: "button", value: "holdRelease", data: [buttonNumber: button], descriptionText: "Button $button is open")
log.debug( "Button $button Hold stop" )
}
else if ( cmd.sceneId == 34 ) {
Integer button = 3
sendEvent(name: "button", value: "clickheld", data: [buttonNumber: button], descriptionText: "Button $button is click-closed")
log.debug( "Button $button Click-Hold start - held" )
}
else if ( cmd.sceneId == 36 ) {
Integer button = 3
sendEvent(name: "button", value: "clickholdRelease", data: [buttonNumber: button], descriptionText: "Button $button is click-open")
log.debug( "Button $button Click-Hold stop" )
}
else if ( cmd.sceneId == 41 ) {
Integer button = 4
sendEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
log.debug( "Button $button was pushed" )
}
else if ( cmd.sceneId == 42 ) {
Integer button = 4
sendEvent(name: "button", value: "doubleclick", data: [buttonNumber: button], descriptionText: "$device.displayName Button $button was Double Clicked", isStateChange: true)
log.debug( "Button $button was Double Clicked" )
}
else if ( cmd.sceneId == 43 ) {
Integer button = 4
sendEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "Button $button is closed")
log.debug( "Button $button Hold start - held" )
}
else if ( cmd.sceneId == 45 ) {
Integer button = 4
sendEvent(name: "button", value: "holdRelease", data: [buttonNumber: button], descriptionText: "Button $button is open")
log.debug( "Button $button Hold stop" )
}
else if ( cmd.sceneId == 44 ) {
Integer button = 4
sendEvent(name: "button", value: "clickheld", data: [buttonNumber: button], descriptionText: "Button $button is click-closed")
log.debug( "Button $button Click-Hold start - held" )
}
else if ( cmd.sceneId == 46 ) {
Integer button = 4
sendEvent(name: "button", value: "clickholdRelease", data: [buttonNumber: button], descriptionText: "Button $button is click-open")
log.debug( "Button $button Click-Hold stop" )
}
else {
log.debug( "Commands and Button ID combinations unaccounted for happened" )
}
}
/*
def zwaveEvent(physicalgraph.zwave.Command cmd) {
[ descriptionText: "$device.displayName: $cmd", linkText:device.displayName, displayed: false ]
log.debug "command event: $cmd"
}
*/
def configure() {
def commands = [ ]
// Correct configure for dim events:
for (def i = 11; i <= 12; i++) {
commands << zwave.associationV1.associationSet(groupingIdentifier: 2, nodeId: zwaveHubNodeId).format()
// commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId: 4, sceneId:i).format()
commands << zwave.configurationV1.configurationSet(parameterNumber:i, size: 1, scaledConfigurationValue:4).format()
}
for (def i = 13; i <= 14; i++) {
commands << zwave.associationV1.associationSet(groupingIdentifier: 3, nodeId: zwaveHubNodeId).format()
// commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId: 5, sceneId:i).format()
commands << zwave.configurationV1.configurationSet(parameterNumber:i, size: 1, scaledConfigurationValue:4).format()
}
/*
// Correct configure for default hold trigger:
for (def i = 11; i <= 14; i++) {
// commands << zwave.associationV1.associationSet(groupingIdentifier: 2, nodeId: zwaveHubNodeId).format()
// commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
commands << zwave.configurationV1.configurationSet(parameterNumber:i, size:1, scaledConfigurationValue:8).format()
}
*/
log.debug("Sending configuration")
delayBetween(commands, 1250)
}
`
@milesfrankland Thanks for this - Iāll check it out tonight.
TBH I have the same Key fob as you - and didnāt have any issues with the last two buttons - Iām definitely interested in this click hold business thoughā¦ I donāt even know the controllers had another input method. Could you please explain the exact interaction here?
Hi,
What do you mean by the exact interaction?
On my keyfob it comes up with a different sceneID for all these click modes:
Single
Double
Hold
Click Hold
Iāve ever come across click holdā¦ what is it? as in you click, release and the click hold again for longer and its treated differently?
Yes exactly. Click once then click again and hold in quick succession. the remote recognises this as a different action.
Thanks @milesfrankland - I checked out the action and it works! - Iāve updated the device handler code to take account of the extra actions - and updated the smartapp to let you take advantage of them with actions.
I do have one question for you - I tested my device type on the two types of wall controllers and my Key fob and all actions worked - but I can see from you and Stuartās conversation that there is some other kind of Key fob that I clearly donāt have that seems to have an issue with some of the configuration - do you know what the difference is?
**
**
both Device Handler & Smartapp need to be updated for new features
AdamV, the only difference between them i believe is that the first once i had buttons 1 - 4 were assigned to Association Group 2 - 5 respectively, and association group 1 was only for messages such as the Battery report etcā¦ which i didnt realise in the original device type i made. however on the newer fob i have button 1 - 4 are assigned to association group 1 - 4 respectively and Association group 5 is not used.
My newer device type just attempts to associate with groups 1 - 5 which works with both fobs. obvoiusly i wasnt aware of the click hold functionality which @milesfrankland discovered, but its pretty awesome that you can potentially have 16 actions assigned to a single switch. now only if i could think of 16 actions most of my stuff is automated anyway so you donāt need to press buttons and switches, the only exception was the 3 locks i have, but thats only 3 actions out of 16
I have to agree - 16 actions per controller is pretty awesome!
Now if only someone could find a good workaround for this 1s action firing whilst held (with no race conditions!) issue and these controllers are perfect
More than likely just me being stupid but im really struggling to get this to wor with a Zwave me wallc-s controller.
Ive tried to connect it by pressing down the 4 buttons then pushing one to enter inclusion mode. Smartthings then connects and adds it, i then change the device type to the custom one which seems to change ok.
I then cant get the āconfigure buttonā to work. Im assuming this is the configure button in the device bit of the smartthings app? When i push it nothing happens at all. Ive tried going back into inclusion mode again by pushing the 4 buttons together and pressing 1 but it still doesnt do anything?
Any help much appreciated
@Andygosport Ye this bit is a bit fiddley - not much I can do because the device is a bit rubbish in this respect. Here is what you need to know:
I use quite a few routines but only having the option to assign a routine to the click function Iāve quickly used all my routine slots.
Might be a good option to have routines be able to be fired when double clicked too.
Thanks
Ok - good feature request - Iāll add this tonight
Cool - thatās all taken care of
Wow, quick work! Will test this out soon. Thanks!
##Device Handler Release 1.6 - details:
Mappings for other SmartApps work like this:
button pushed = button number pushed
button held = button number held
button double clicked = (real button number + 4) pushed
button hold stopped = (real button number + 8) pushed
button click-held start = (real button number + 4) held
button click-held stopped = (real button number + 8) held
This allows you to use this with Rule Machine properly (especially as Bruce just updated it to work with up to 20 buttons per device).
This is great because the only real advantage my Smartapp has is that it can do dimming and is neat for containing all the actions for a controller. However, itās drawback is that it has no where near as many possible actions as rule machine has, or the versatility. With this new release you can use any type of action with any button of a controller using the mapping above.
As an example for button 1 from a controller, used in a different SmartApp e.g. Rule Machine:
button 1 pushed = button 1 pushed
button 1 held = button 1 held
button 1 double clicked = button 5 pushed
button 1 hold stopped = button 9 pushed
button 1 click-held start = button 5 held
button 1 click-held stopped = button 9 held
etc etc
Hey!
I still have a problem with my wall controller
When I use your new code, and āconfigureā the device using the app, my buttons 3 and 4 stop working.
Here is the device I have:
When I click button 3 I get button 1 double click in the logs.
When I click button 4 I get button 2 double click in the logs.
What do you think?..