Wireless Wall Switch (ZME_WALLC-S) to control Smartthings devices and routines

In my experience with scene controllers, this bit of configuration code does the trick with getting the various buttons to provide actionable information to SmartThings (replace 7 with number of buttons)

Then you start to encounter the joy of debouncing button presses. =)

That said, I haven’t taken a full look at the data sheet.

  def configure() {
    def commands = [ ]
	
    for (def i = 1; i <= 7; i++) {
        commands << zwave.associationV1.associationSet(groupingIdentifier: i, nodeId: zwaveHubNodeId).format()
    	commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
	}
	
    log.debug("Sending configuration: ${commands}")
	
    delayBetween(commands, 1250)
}

Thank you @codytruscott - I’ve put in the code but it hasn’t made a difference because I think there are some basics that I have to get right first.

However I have made some big progress which I think proves that this can be done because I am now catching information on the button presses. Please let me know what you think of this:

In the Device Type code there is this piece of code:

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 ]
	}
	log.debug("Parsed '$description' to $results")
	return results
}

I am getting logs for each button press - and there is a pattern to them:

when button 1 is pushed:

Parsed 'zw device: 06, command: 9881, payload: 00 5B 03 B7 00 01 ' to [[descriptionText:Lounge Wall Switch: SecurityMessageEncapsulation(commandByte: [183, 0, 1], commandClassIdentifier: 91, commandIdentifier: 3, reserved13: 0, secondFrame: false, sequenceCounter: 0, sequenced: false), linkText:Lounge Wall Switch, displayed:false]]

when button 1 is held:

Parsed 'zw device: 06, command: 98C1, payload: 00 5B 03 B9 02 01 ' to [descriptionText:null, displayed:false]
Exception 'java.lang.IndexOutOfBoundsException: toIndex = 8' encountered parsing 'cmd: 98C1, payload: 00 5B 03 B9 02 01'

when button 2 is pushed:

Parsed 'zw device: 06, command: 9881, payload: 00 5B 03 CC 00 02 ' to [[descriptionText:Lounge Wall Switch: SecurityMessageEncapsulation(commandByte: [204, 0, 2], commandClassIdentifier: 91, commandIdentifier: 3, reserved13: 0, secondFrame: false, sequenceCounter: 0, sequenced: false), linkText:Lounge Wall Switch, displayed:false]]

when button 2 is held:

Parsed 'zw device: 06, command: 98C1, payload: 00 5B 03 CE 02 02 ' to [descriptionText:null, displayed:false]
Exception 'java.lang.IndexOutOfBoundsException: toIndex = 8' encountered parsing 'cmd: 98C1, payload: 00 5B 03 CE 02 02'

when button 3 is pushed:

Parsed 'zw device: 06, command: 9881, payload: 00 5B 03 DA 00 05 ' to [[descriptionText:Lounge Wall Switch: SecurityMessageEncapsulation(commandByte: [218, 0, 5], commandClassIdentifier: 91, commandIdentifier: 3, reserved13: 0, secondFrame: false, sequenceCounter: 0, sequenced: false), linkText:Lounge Wall Switch, displayed:false]]

when button 2 is held:

Parsed 'zw device: 06, command: 98C1, payload: 00 5B 03 DC 02 05 ' to [descriptionText:null, displayed:false]
Exception 'java.lang.IndexOutOfBoundsException: toIndex = 8' encountered parsing 'cmd: 98C1, payload: 00 5B 03 DC 02 05'

when button 4 is pushed:

Parsed 'zw device: 06, command: 9881, payload: 00 5B 03 EA 00 06 ' to [[descriptionText:Lounge Wall Switch: SecurityMessageEncapsulation(commandByte: [234, 0, 6], commandClassIdentifier: 91, commandIdentifier: 3, reserved13: 0, secondFrame: false, sequenceCounter: 0, sequenced: false), linkText:Lounge Wall Switch, displayed:false]]

when button 4 is held:

Parsed 'zw device: 06, command: 98C1, payload: 00 5B 03 EC 02 06 ' to [descriptionText:null, displayed:false]   
Exception 'java.lang.IndexOutOfBoundsException: toIndex = 8' encountered parsing 'cmd: 98C1, payload: 00 5B 03 EC 02 06'

There is one more thing to the pattern above that complicates things a little - in the payloads the 4th number/letter combo is always different - but seems to increment in a pattern of it’s own. For e.g. the button 1 pressed payload increments like this: 00 5B 03 F7 00 01, 00 5B 03 F8 00 01, 00 5B 03 F9 00 01, 00 5B 03 FA 00 01.

Thoughts anyone? I’m getting events for button presses so we must be on the right path!

Right - after a lot of messing around I now have this wireless switch working with some caveats, below:

  1. This will accurately determine which button is pressed and register as a button press to Smartthings
  2. This will accurately determine which button is held and register as a button hold to Smartthings
  3. If you hold a button down - it does something to the state of the switch and then all subsequent presses/holds do not register correctly (so you have to reset the switch (take batt out and in )
  4. I have not got wake up notifications or battery information working (it produces an error in the log)

I am not a developer - I only have very limited coding experience (and certainly not in groovy). As such use this at your own risk. Things that I know to be wrong with the code:

  1. It is very very messy and I will probably not get around to cleaning it up ever
  2. I have not parsed the z wave command in the usual and recommended manner - as this was too difficult / would have taken me far to long to learn. Instead I have Identified a pattern in the in commands sent from the device, converted the patterns into the button clicks/holds, and then created an event in the smartthings hub that registers the button press.

If anyone out there with real coding ability fancies doing this the proper way - please feel free. However for now, its seems that if you want a reasonably priced wall switch that can use standard wall switch frames and rockers such as Busch-Jaeger (DURO 2000, Reflex SI), Kopp (HK05, HK07, Paris), REV (Everlux, Arcada). Then this is the only way I have found to get this to work:

/**
 *  Copyright 2015 AdamV
 *
 *  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.
 *
 */
metadata {
	definition (name: "ZWaveMeWallc-S", namespace: "smartthings", author: "AdamV") {
		capability "Actuator"
		capability "Button"
        capability "Battery"
//		capability "Configuration"
//		capability "Sensor"

//    	attribute "currentButton", "STRING"
//    	attribute "numButtons", "STRING"
        
		fingerprint deviceId: "0x1801", inClusters: "0x5E, 0x8F, 0x73, 0x98, 0x86, 0x72, 0x70, 0x85, 0x2D, 0x8E, 0x80, 0x84, 0x5A, 0x59, 0x5B, 0xEF, 0x20, 0x5B, 0x26, 0x27, 0x2B, 0x60"
    }

	simulator {
		status "button 1 pushed":  "command: 9881, payload: 00 5B 03 DE 00 01"
		status "button 1 held":  "command: 98C1, payload: 00 5B 03 E4 02 01"
		status "button 2 pushed":  "command: 9881, payload: 00 5B 03 E0 00 02"
		status "button 2 held":  "command: 98C1, payload: 00 5B 03 E6 02 01"
		status "button 3 pushed":  "command: 9881, 00 5B 03 E1 00 05"
		status "button 3 held":  "command: 98C1, payload: 00 5B 03 E8 02 01"
		status "button 4 pushed":  "command: 9881, payload: 00 5B 03 E2 00 06"
		status "button 4 held":  "command: 98C1, payload: 00 5B 03 EA 02 01"
		status "wakeup":  "command: 8003, payload: FF"
	}
	tiles {
		standardTile("button", "device.button", width: 2, height: 2) {
			state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
        	state "button 1", label: "1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
      		state "button 2", label: "2", icon: "st.Weather.weather14", backgroundColor: "#79b821"
      		state "button 3", label: "3", icon: "st.Weather.weather14", backgroundColor: "#79b821"
      		state "button 4", label: "4", icon: "st.Weather.weather14", backgroundColor: "#79b821"
        }
            // Configure button.  Syncronize the device capabilities that the UI provides
    standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
      state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
    }
		main "button"
		details(["button", "configure"])
	}
     valueTile("battery", "device.battery", inactiveLabel: false,
                          decoration: "flat") {
                        state "battery", label:'${currentValue}% battery', unit:""
                }
    
}


def parse(String description) {
	def results = []

	if (description.startsWith("Err")) {
		log.debug("An error has occurred")
//	    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 ]
	}

//    log.debug("Parsed '$description' to $results")
//    log.debug("results: $results")
    log.debug("Description from device: $description")
   
	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)
// Just makes it easier to compare later on.
	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 buttonEvent(button, held) {
// Determine command type
//	if ( commandID == "9881" ) {
//    createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
//    log.debug(createEvent)
    // Tap...
//  	log.debug( 'tap' )
//		}
//	else if ( commandID == "98C1" ) {
//    createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true)
//    log.debug(createEvent)    	
        // Hold...
//	log.debug( 'held' )
//		}
//	else {
//   	 log.debug( "Unrecognised command: $commandID" )
//		}
        
//    return results
//}


def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
	def results = [createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)]

    results += configurationCmds().collect{ response(it) }
    result << zwave.batteryV1.batteryGet().format()
    result << "delay 1200"
	results << response(zwave.wakeUpV1.wakeUpNoMoreInformation().format())

	return results
    log.debug("wakeupnote:", results)
}

// def buttonEvent(button, held) {
//	button = button as Integer
//	if (held) {
//		createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true)
//	} else {
//		createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pressed", isStateChange: true)
//    }


//def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
//	Integer button = ((cmd.sceneId + 1) / 2) as Integer
//	Boolean held = !(cmd.sceneId % 2)
//	buttonEvent(button, held)
//}

//def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
//	Integer button = (cmd.value / 40 + 1) as Integer
//	Boolean held = (button * 40 - cmd.value) <= 20
//	buttonEvent(button, held)
//}

// def zwaveEvent(physicalgraph.zwave.Command cmd) {
//	[ descriptionText: "$device.displayName: $cmd", linkText:device.displayName, displayed: false ]
//}

def configurationCmds() {
	def cmds = []
	def hubId = zwaveHubNodeId
	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: 240+button, scaledConfigurationValue: 1).format()
	}
	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40, configurationValue: [hubId, (button-1)*40 + 1, 0, 0]).format()
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40 + 20, configurationValue: [hubId, (button-1)*40 + 21, 0, 0]).format()
	}
	cmds
}

  def configure() {
    def commands = [ ]
	
    for (def i = 1; i <= 4; i++) {
        commands << zwave.associationV1.associationSet(groupingIdentifier: i, nodeId: zwaveHubNodeId).format()
    	commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
	}
	
    log.debug("Sending configuration: ${commands}")
	
    delayBetween(commands, 1250)
}

// old code
//def configure() {
//	def cmds = configurationCmds()
//	log.debug("Sending configuration: $cmds")
//	return cmds
//}
1 Like

@mattjfrank

@tgauchat

If you have any time, could you take a look at this? This is one of the few multibutton wall devices available in Europe that might work with SmartThings. So it would be nice if it would work at least as well as the Enerwave SC7.

It appears this whole thing is a lot more addictive than I thought - I just could bare to leave it only half working! I’ve now gone through the Smartthings docs and written this device handler correctly:

Working:

  • Button presses handled correctly
  • Wakeup notification handled correctly
  • Battery reporting handled correctly

Not Working:

  • Button holds (mini work around - see below)

It appears that there is a problem with the Smartthings zwave parser @duncan, you should take a look at this. Basically, every time that I do a button hold the parser throws this exception (payload can vary):

Exception 'java.lang.IndexOutOfBoundsException: toIndex = 8' encountered parsing 'cmd: 98C1, payload: 00 5B 03 02 01 06' 

However, because of the pattern identified earlier, I know that cmd 98C1 is a button hold - so I’ve left in the hack-y comparison method to work out button presses / holds.

When the Z Wave parser is fixed I’ll update this to handle holds correctly and hopefully be able to have the hodl duration as a factor.

Here is the device handler:

/**
 *  Copyright 2015 AdamV
 *
 *  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.
 *
 */
metadata {
	definition (name: "Secure Wall Controller", namespace: "Z-Wave.me", author: "AdamV") {
		capability "Actuator"
		capability "Button"
        capability "Battery"
        
		fingerprint deviceId: "0x1801", inClusters: "0x5E, 0x8F, 0x73, 0x98, 0x86, 0x72, 0x70, 0x85, 0x2D, 0x8E, 0x80, 0x84, 0x5A, 0x59, 0x5B, 0xEF, 0x20, 0x5B, 0x26, 0x27, 0x2B, 0x60"
    }

	simulator {
		status "button 1 pushed":  "command: 9881, payload: 00 5B 03 DE 00 01"
		status "button 1 held":  "command: 98C1, payload: 00 5B 03 E4 02 01"
		status "button 2 pushed":  "command: 9881, payload: 00 5B 03 E0 00 02"
		status "button 2 held":  "command: 98C1, payload: 00 5B 03 E6 02 01"
		status "button 3 pushed":  "command: 9881, 00 5B 03 E1 00 05"
		status "button 3 held":  "command: 98C1, payload: 00 5B 03 E8 02 01"
		status "button 4 pushed":  "command: 9881, payload: 00 5B 03 E2 00 06"
		status "button 4 held":  "command: 98C1, payload: 00 5B 03 EA 02 01"
		status "wakeup":  "command: 8003, payload: FF"
	}
	tiles {
		standardTile("button", "device.button", width: 2, height: 2) {
			state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
        }
    	 valueTile("battery", "device.battery", inactiveLabel: false,
                          decoration: "flat") {
                        state "battery", label:'${currentValue}% battery', unit:""
         }
        main "button"
		details(["button", "battery"])
	}
    
}

def parse(String description) {
	def results = []

	if (description.startsWith("Err")) {
		log.debug("An error has occurred")
		} 
    else {
        def cmd = zwave.parse(description, [0x98: 1, 0x20: 1, 0x84: 1, 0x80: 1, 0x60: 3, 0x2B: 1])
        if (cmd) {
       	results = zwaveEvent(cmd)
       	//	log.debug(cmd)
		}
//		if(cmd) results += zwaveEvent(cmd)
//		if(!results) results = [ descriptionText: cmd, displayed: false ]

    }
    log.debug("Description from device: $description")
   
	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.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 configurationCmds() {
	def cmds = []
	def hubId = zwaveHubNodeId
	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: 240+button, scaledConfigurationValue: 1).format()
	}
	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40, configurationValue: [hubId, (button-1)*40 + 1, 0, 0]).format()
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40 + 20, configurationValue: [hubId, (button-1)*40 + 21, 0, 0]).format()
	}
	cmds
}

  def configure() {
    def commands = [ ]
	
    for (def i = 1; i <= 4; i++) {
        commands << zwave.associationV1.associationSet(groupingIdentifier: i, nodeId: zwaveHubNodeId).format()
    	commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
	}
	
    log.debug("Sending configuration: ${commands}")
	
    delayBetween(commands, 1250)
}
3 Likes

Thanks for the responses! :stuck_out_tongue_winking_eye:

Can someone from Smarttthings please look in to the exception? Or at least log it in your bug backlog? There is clearly an error in the z wave parser for this type of command and payload, I’d appreciate it if this was fixed so that I can add all the abilities of this device

@duncan @slagle @smartthing - can this please be acknowledged / logged eta’d to fix?

I’d like to use this device with all of it’s properties and at the moment a bug in smartthings is the only thing in my way.

Many thanks,

Adam

Did you put in a ticket at support@smartthings.com ? That’s what get the official process started to review errors, even for the platform itself.

I found the problem. It doesn’t seem to have anything to do with CentralScene – that “98C1” command is a variant of SecurityMessageEncapsulation that we apparently aren’t handling correctly.

It will be an easy fix but I don’t know how long it will take to get it into production. If you want to continue until then you should be able to do zwave.parse(description.replace("98C1", "9881"), [0x98: 1... to work around it.

2 Likes

So I have done this - and no longer get the error… However although I can capture that it is a button hold rather than a press - the switch goes into a strange mode during this process and I am unable to capture how long the holds are.

I get the feeling that the switch is expecting some sort of response from the hub - maybe some kind of polling, after which it will respond when the switch is let go and this way the duration of the dimming/hold can be captured.

Does anyone have any experience with something like this and could set me in the correct direction?

I added this device type to this wall controller and change the device type. Now what? I tried to use existing 4 button app in the ST app and set it up. But nothing is happening. Can some one help?

  1. Make sure that you are using the same device (zwave.me z wave plus secure wireless wall controller)
  2. set device to inclusion mode (on the instructions that come with the device)
  3. Smartthings should recognise this as a z wave device - add what it finds
  4. go to smartthings IDE and change device type to this one
  5. should now work with button controller smartapp

If the above steps dont work - go to live logging and let me know what you see when you press buttons

the latest version of the code is here:

/**
 *  Copyright 2015 AdamV
 *
 *  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.
 *
 */
metadata {
	definition (name: "Secure Wall Controller", namespace: "Z-Wave.me", author: "AdamV") {
		capability "Actuator"
		capability "Button"
        capability "Battery"
        
		fingerprint deviceId: "0x1801", inClusters: "0x5E, 0x8F, 0x73, 0x98, 0x86, 0x72, 0x70, 0x85, 0x2D, 0x8E, 0x80, 0x84, 0x5A, 0x59, 0x5B, 0xEF, 0x20, 0x5B, 0x26, 0x27, 0x2B, 0x60"
    }

	simulator {
		status "button 1 pushed":  "command: 9881, payload: 00 5B 03 DE 00 01"
		status "button 1 held":  "command: 98C1, payload: 00 5B 03 E4 02 01"
		status "button 2 pushed":  "command: 9881, payload: 00 5B 03 E0 00 02"
		status "button 2 held":  "command: 98C1, payload: 00 5B 03 E6 02 01"
		status "button 3 pushed":  "command: 9881, 00 5B 03 E1 00 05"
		status "button 3 held":  "command: 98C1, payload: 00 5B 03 E8 02 01"
		status "button 4 pushed":  "command: 9881, payload: 00 5B 03 E2 00 06"
		status "button 4 held":  "command: 98C1, payload: 00 5B 03 EA 02 01"
		status "wakeup":  "command: 8003, payload: FF"
	}
	tiles {
		standardTile("button", "device.button", width: 2, height: 2) {
			state "default", label: "", icon: "st.Home.home30", backgroundColor: "#ffffff"
        }
    	 valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
         	tileAttribute ("device.battery", key: "PRIMARY_CONTROL"){
                        state "battery", label:'${currentValue}% battery', unit:""
        }
        }
        main "button"
		details(["button", "battery"])
	}
    
}

def parse(String description) {
	def results = []

	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])
        if (cmd) {
       	results = zwaveEvent(cmd)
       	//	log.debug(cmd)
		}
//		if(cmd) results += zwaveEvent(cmd)
//		if(!results) results = [ descriptionText: cmd, displayed: false ]

    }
    log.debug("Description from device: $description")
   
	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.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 configurationCmds() {
	def cmds = []
	def hubId = zwaveHubNodeId
	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: 240+button, scaledConfigurationValue: 1).format()
	}
	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40, configurationValue: [hubId, (button-1)*40 + 1, 0, 0]).format()
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40 + 20, configurationValue: [hubId, (button-1)*40 + 21, 0, 0]).format()
	}
	cmds
}

  def configure() {
    def commands = [ ]
	
    for (def i = 1; i <= 4; i++) {
        commands << zwave.associationV1.associationSet(groupingIdentifier: i, nodeId: zwaveHubNodeId).format()
    	commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
	}
	
    log.debug("Sending configuration: ${commands}")
	
    delayBetween(commands, 1250)
}
1 Like

Ok - I need some help again! So I decided to go back to this device handler to finally get the last bits working perfectly.

I finally have it reporting absolutely everything correctly:

All button pushes - handled
All button long holds - registers the start and end
Battery
Wake up notifications
configuration

Now that I do - I wanted to see if anyone has a smartapp - or knows how I can modify the button controller smart app so that when the button hold starts, it triggers lights to start dimming up or down and a variable rate (decided in the code) and when the button is released it stops the process?

Anyone done anything like this?

Thank you!

For anyone who wants the code for their own use (I haven’t seen any other wall controllers on smartthings community that can be made to 1. Look so nice (loads of faceplate and rocker switches compatible) and 2. actually handle the hold state correctly (FINALLY!) - see below:

/**
 *  Copyright 2015 AdamV
 *
 *  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.
 *
 */
metadata {
	definition (name: "Secure Wall Controller", namespace: "Z-Wave.me", author: "AdamV") {
		capability "Actuator"
		capability "Button"
capability "Contact Sensor"
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"
		status "button 1 held":  "command: 98C1, payload: 00 5B 03 E4 02 01"
		status "button 2 pushed":  "command: 9881, payload: 00 5B 03 E0 00 02"
		status "button 2 held":  "command: 98C1, payload: 00 5B 03 E6 02 01"
		status "button 3 pushed":  "command: 9881, 00 5B 03 E1 00 05"
		status "button 3 held":  "command: 98C1, payload: 00 5B 03 E8 02 01"
		status "button 4 pushed":  "command: 9881, payload: 00 5B 03 E2 00 06"
		status "button 4 held":  "command: 98C1, payload: 00 5B 03 EA 02 01"
		status "wakeup":  "command: 8003, payload: FF"
	}
	tiles {
		standardTile("button", "device.button", width: 2, height: 2) {
			state "default", label: "", icon: "st.Home.home30", backgroundColor: "#ffffff"
}
 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: 2, height: 2) {
			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)

		}
//		if(cmd) results += zwaveEvent(cmd)
//		if(!results) results = [ descriptionText: cmd, displayed: false ]

}

/*   
	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 == 13 ) {
Integer button = 1
sendEvent(name: “button”, value: “hold start”, data: [buttonNumber: button], descriptionText: “Button $button is closed”)
log.debug( “Button $button Hold start” )
}
else if ( cmd.sceneId == 15 ) {
Integer button = 1
sendEvent(name: “button”, value: “hold stop”, data: [buttonNumber: button], descriptionText: “Button $button is open”)
log.debug( “Button $button 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 == 23 ) {
Integer button = 2
sendEvent(name: “button”, value: “hold start”, data: [buttonNumber: button], descriptionText: “Button $button is closed”)
log.debug( “Button $button Hold start” )
}
else if ( cmd.sceneId == 25 ) {
Integer button = 2
sendEvent(name: “button”, value: “hold stop”, data: [buttonNumber: button], descriptionText: “Button $button is open”)
log.debug( “Button $button Hold stop” )
}
else if ( cmd.sceneId == 12 ) {
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 == 14 ) {
Integer button = 3
sendEvent(name: “button”, value: “hold start”, data: [buttonNumber: button], descriptionText: “Button $button is closed”)
log.debug( “Button $button Hold start” )
}
else if ( cmd.sceneId == 16 ) {
Integer button = 3
sendEvent(name: “button”, value: “hold stop”, data: [buttonNumber: button], descriptionText: “Button $button is open”)
log.debug( “Button $button Hold stop” )
}
else if ( cmd.sceneId == 22 ) {
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 == 24 ) {
Integer button = 4
sendEvent(name: “button”, value: “hold start”, data: [buttonNumber: button], descriptionText: “Button $button is closed”)
log.debug( “Button $button Hold start” )
}
else if ( cmd.sceneId == 26 ) {
Integer button = 4
sendEvent(name: “button”, value: “hold stop”, data: [buttonNumber: button], descriptionText: “Button $button is open”)
log.debug( “Button $button 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 cmds = configurationCmds()
	log.debug("Sending configuration: $cmds")
	return cmds
}
def configurationCmds() {
	//zwave.configurationV1.configurationReport().format()

//zwave.associationGrpInfoV1.associationGroupCommandListGet().format()
//zwave.associationCommandConfigurationV1.commandConfigurationGet().format()

	//zwave.configurationV1.configurationSet(parameterNumber:11, size:14, scaledConfigurationValue:8).format()
	def cmds = []
	def hubId = zwaveHubNodeId
	(11..14).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: button, scaledConfigurationValue: 4).format()
	}
/*	(1..4).each { button ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40, configurationValue: [hubId, (button-1)*40 + 1, 0, 0]).format()
		cmds << zwave.configurationV1.configurationSet(parameterNumber: (button-1)*40 + 20, configurationValue: [hubId, (button-1)*40 + 21, 0, 0]).format()
	}*/

/*
cmds

}
*/

  def configure() {

def commands = [ ]

   //     for (def i = 1; i <= 2; i++) {

// commands << zwave.associationV1.associationSet(groupingIdentifier: i, nodeId: zwaveHubNodeId).format()
// commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
// commands << zwave.configurationV1.configurationSet(parameterNumber:i, size:1, scaledConfigurationValue:2).format()
//}

for (def i = 11; i <= 12; 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:4).format()
}
for (def i = 13; i <= 14; i++) {
commands << zwave.associationV1.associationSet(groupingIdentifier: 3, nodeId: zwaveHubNodeId).format()
// commands << zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:i, sceneId:i).format()
commands << zwave.configurationV1.configurationSet(parameterNumber:i, size:1, scaledConfigurationValue:4).format()
}

log.debug(“Sending configuration: ${commands}”)

delayBetween(commands, 1250)
}

Nice!

Are you going to put a release topic in the device type section? That way more people will find it. :sunglasses: Or do you want to wait for more feedback?

https://community.smartthings.com/c/projects-stories/community-created-device-types

I didn’t know about that thread - good idea!

I think there are a few things I need to do before I release:

  • Clean up code (loads of redundant stuff in there now)
  • Create (or find) an accompanying smartapp (without this its not as useful as it could be)
  • I’ll have to write up the configuration process (it’s not intuitive)
  • Probably take some pics of the completed switches with cover plates and rockers so people know what this looks like

@tgauchat & @codytruscott If you know of any smartapps that facilitate dimming up or down based on the duration that a button is held (starts dimming up or down on trigger and stops dimming up or down on different trigger) - please let me know

Also - anyone know if its possible to update the firmware of a z-wave plus device through smartthings? I ask this because some of the wall controllers that arrive are using a firmware 1.0 and others 1.3. the ones on 1.3 are noticeably quicker at communicating with the hub.

Many thanks

Tagging @duncan on firmware updates for Zwave plus devices

We’re planning to add Z-Wave OTA firmware updates but it hasn’t been put on a timeline yet – it’s likely still a ways out.

2 Likes

Moving to this thread (all code updated here):

1 Like

Hi @AdamV

if you have time could you help out with the wall switch.

duwi z-wave.me 05443, if I include it into the network it is detected as aeon key fob and looking at the log nothing is received when I press the a button. so I have changed the device over to your device type " Secure Wall Controller" and then press configure. in the log I see ‎21‎:‎49‎:‎51: debug Sending configuration, I try waking the switch up. but still nothing in the log.

I have found some information bellow about the switch. it used to work with vera ok.

http://www.vrdigitalworld.com/smarthome/test-des-interrupteurs-muraux-duwi-z-wave-me-05443-et-05460?lang=en

Thanks

Paul

Hi Paul,

Firstly, this is a different switch, so I wouldn’t expect it to work out the box with this device type.

Also, just because nothing shows in the logs, doesn’t mean that it’s not registering your button presses.

So I would try the following to ascertain if it is working / not working and how to sort it:

  1. Make sure that you do a full factory reset on the device and then include to smartthings

  2. reassign the original aeon keyfob device type. Then go to the button controller smartapp (from marketplace) and assign all four button presses to lights or sometihing in your house that you would notice (I realise that this device only has two buttons - but in the event that the aeon device type does work then we wont know which number of button it shows up as). Then test the switch and see if there is a result.

  3. If no. 1 does not work / yield any results, then reassign my device type and make an edit to line 71 (currently nothing there) and put: log.debug (“Parsed command: $cmd”)

  4. Then go to live logging and press the buttons. For each button press you should get a RAW command entry and a Parsed command entry. Then put these results here and we’ll take a look and see what we can do. If you do not get results for RAW and Parsed then it means that either the device is not compatible with Smartthings at all or is not configured correctly. If the issue is configuration then we’ll have to find the original manual and do some fiddling - and it wont be easy… but it may be fixable.

1 Like

Hi @AdamV

I have tried they above and nothing was reported at all in the log files. I am wondering if the switch needs a parameter changing to work. I have given up on them and purchased one of the Popp 009303 Z-Wave Plus Battery Wall Controller and got that to work with your code in 10 min. if you fancy a challenge I would gladly loan you one of the switched to play with if you like. (I would cover postage both ways)

Thanks for your support and code.

Paul