2.3.1.139, Button Controllers, WallMote

I had recently updated my button controller from 5.0 to the recent 5.1 release. Everything seemed to work fine, in fact, it seemed to work better than the 5.0. I updated the firmware of the Hub from 138 to 139 and the button controls are terribly slow or non-responsive. I am running a two button Walmote from Aeontec. I am using a custom device Handler driver. However, I did attempt to use the built-in driver with no such luck. All the button options are either slow or will not respond.

image

I ran a z-wave repair on the c-5 where all the rules are running from and where the button is associated with. The lock in this case is on c7, the lock works very other way. I believe is it is something with Button Controller app or software layer.

Can you tell where this slowness is happening? From your logs, the time from the hub receiving the button press in from the device and the dimmer reporting back that it was turned on was under half a second (and the time before it actually turned on was likely a bit less). That seems pretty good to me.

If there is a delay between the "real" button press and the first (bottom-most, in your screenshot) log entry, that to me would suggest a Z-Wave network problem more than an app issue; the hub is just having problems getting the initial button-press/scene report from the device for whatever reason. "Ghost nodes," chatty/spammy devices, or range issues are three possible causes for Z-Wave trouble, but if you haven't already done the firmware update from Settings > Z-Wave Details for your C-7 Z-Wave radio, that would be a good first step (the Firmware Update button, if you see it; if you don't, you're already up-to-date--and note that this is not the "Update" button). While you're there, comb the list for any ghosts--devices without routes listed are good suspects, unless they are battery devices that may have been sleeping the entire time since the last hub reboot, or perhaps a powered device you know if that just hasn't been used, but if you see anything suspicious...

There aren't any ghosts devices on the c7. From the time I press the button to the device responds is what I measuring, if it responds at all. The lock responds every single way from automated actions from the C5 without any issue. Only when using this button it's a problem on the C5. As you can see the hub is recognizing the button push.
Yes, the firmware is updated to on the c7. I'm confident that issue is on the C5 side and not the C7. The C7 and lock have a direct connection and it responds in every way quickly.
As you can see from my rules some the items that I'm automating is virtual devices and non-zwave devices and they have the same issue. Which would also exclude the C7 as well and z-wave network issue. Plus, I have button next to C5. So, I don't think it is a distance issue.

Let me know if that makes sense. Thanks for your help.

So the "real" device is on the C-5? If the automation is on the C-7 (and the device/events are coming over via Hub Mesh), then I suppose another thing would be to check the timing on the C-5, leaving the meshed hub out of the picture, to make sure that's not where the delay is. It should be pretty fast, and it looks like your first post says they're both on the C-5, but just in case... :man_shrugging:

Yes so the button, automation, virtual and ip devices are on the C5 and the lock is on c7. All actions with buttons either fail or are extremely slow.

If I attempt button push from device manager no response.

Do you mean the device page, i.e., via the commands/buttons like "Push" at the top? If so:

  1. make sure you provide the appropriate button number (type "1", no quotes, or whatever number into the text box; this should correspond to the event and button number you'd get from a real push); and
  2. particularly if this is a community driver, it may not implement the push() command at all (it's a relatively recent addition, though it's been convention since more or less the beginning)--you'd likely see an error in logs, but you could also inspect the driver code to see what it does; and
  3. I assume you already know this, but keep in mind that this just generates a sort of "virtual" or simulated event and does not affect the actual device itself (nor would it troubleshoot problems with the actual device, but it can be useful for testing automations that should get "triggered" by the same event)

Virtual device could be Hsm. Which I am automating as per my screenshot above.
I tried the built-in driver either same results for the push button.
According to the logs I do have a push when I enter it in. I am using the correct number and type of push.
If I execute the action from the button controll app. It works. Not from device driver or from the physical device.

I am not talking about virtual devices or devices that you're controlling via the automation, just virtual/digital events (button events here, simulating "real" ones from the device) and events that would trigger the automation.

If you aren't getting a button event when you manually run a push(1) command (what you should get if you type 1 into the textbox on the Push button on the device page, then click/tap the button to run the command), then your app will not trigger--same as if it doesn't receive the physical event. This could be a driver issue.

But it sounds like your app does respond to physical events, just slowly -- or really, the app responds quickly, but it just takes a while for the button event to "register" on the hub compared to when you press the button in real life. Again, this strongly suggests some sort of Z-Wave mesh network problem to me. If any of these assumptions are incorrect, please provide clarification, since it will affect the possible source of problems. This is just what I think based on what I understand. :slight_smile:

If this is a Z-Wave problem, consider this tip:

  1. Go to Settings > Shutdown.
  2. Unplug power from the hub for 30 seconds or more (often, it is recommended to unplug from the wall instead of the hub; early C-7 models might have somewhat fragile micro-USB ports, so the less stress teh better)
  3. Re-attach power to reboot the hub, wait a few minutes for it to reboot (and ideally a few more for things to settle down), then try again.

This is the only way to power cycle the Z-Wave radio, which can help if it crashed and wasn't able to recover on its own. Probably not, but worth a try!

This will also reboot the hub, which usually doesn't magically resolve things on its own (unless you have memory or resource problems, which it looks like you don't), but it can't hurt to try once.

If nothing else, you can also rule out database corruption by creating a backup from Settings > Backup and Restore, downloading it to your computer, then doing a soft reset from Settings > Diagnostic Tool (do not reset any of your radios, and make sure this is "soft reset" and not "full reset"), then choosing Restore from backup? at the bottom of the "Getting Started" wizard that will appear after the hub is reset and reboots (choose the file you just downloaded). As long as you don't reset anything else, this process is fairly safe and will ensure your problem isn't database corruption. Again, doesn't seem likely, but it's another thing that can't hurt.

1 Like

This is the first time I have gotten an error. Not I'm seeing the same symptoms with the native drivers too.

I'm going back to 138. I'm backing up my button rules and see what happens.

This is with the native drivers.

Still no response from devices.

I am using the native driver, Only doing 1 action. I'm back 138.. 1 held seem to work every time now, but none of the others work.
If do it from driver log show that it isn't communicating to button app. No logs from there. Something is messed up.

Deleted the button controller completely and re-entered all rule/functions again. Working now. Update 139......

update 139 is still working. Thanks for your help.

I'm still getting this

When I attempt from the driver. Other than that, it is working.

This appears to be a user (3rd party) driver, so the best approach would be to contact the driver author about this error.

1 Like

I don't think the author is supporting the driver anymore. That's the issue. And the native driver does not have the features necessary for what the device is.

Might be a simple fix, do you have a link to the source code?

I have file but the link was taken down by codahq but erocom123 still has his link.

Updated by Ben Rimmasch (codahq) https://raw.githubusercontent.com/codahq/hubitat_codahq/master/devicestypes/aeon-wallmote.groovy

Originally written: Eric Maycock (erocm123) SmartThingsPublic/aeon-wallmote.groovy at master · erocm123/SmartThingsPublic · GitHub

The biggest advantage to this driver is the ability to swipe up or down as a third and fourth button. That's the big advantage to this device both dual and quad. Although, the native driver that's part of hubitat does not have this ability and only functions as a two-button or 4 button (quad) remote.

All the other options I really don't care too much about. But the swiping is the key thing that differentiates this remote from any other remote.

If you’ll post the file you are currently using (inside a summary block please) I’ll take a look at it. (I’d rather do that than re-porting the ST driver from erocm123 to make sure that any enhancements that codahq may have added are retained.)

1 Like

@thebearmay Thank you for looking at this.

/**
 *  Aeon WallMote (with slide functionality)
 *
 *  Copyright 2019 Ben Rimmasch
 *
 *  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 Quad
 *  https://aeotec.freshdesk.com/support/solutions/articles/6000162392-wallmote-quad-user-guide-
 *  https://aeotec.freshdesk.com/support/solutions/articles/6000166184-wallmote-quad-technical-specifications-
 *  https://aeotec.freshdesk.com/support/solutions/articles/6000187144-wallmote-quad-group-association-explanation-for-direct-communication-
 *
 *  Aeon WallMote Dual
 *  https://aeotec.freshdesk.com/support/solutions/articles/6000176572-wallmote-user-guide-
 *  https://aeotec.freshdesk.com/support/solutions/articles/6000176570-wallmote-technical-specification-
 *  No group associations document but the above document for quad is applicable
 *
 *  Author: Ben Rimmasch (codahq)
 *  Original Author: Eric Maycock (erocm123)
 *  Date: 2019-01-23
 *
 *  Change Log:
 *  2020-01-23: Initial
 *  2020-01-26: Fixed logging for those that switch to this driver and have never set a logging level yet
 *              Change to two pushed buttons instead of one button that is pushed and held
 *              Bug fixes for some events
 *              Handled the event sent when a user initiates a connectivity health test from the remote's button
 *              Fixed firmware reporting for current Hubitat command classes
 *
 *
 *  Previous Author's Change Log:
 *  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", namespace: "codahq-hubitat", author: "Ben Rimmasch",
      importUrl: "https://raw.githubusercontent.com/codahq/hubitat_codahq/master/devicestypes/aeon-wallmote.groovy") {
    capability "Actuator"
    capability "PushableButton"
    capability "HoldableButton"
    capability "ReleasableButton"
    capability "Configuration"
    capability "Sensor"
    capability "Battery"
    capability "Health Check"

    attribute "sequenceNumber", "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 attribute value \"needUpdate\" will show \"YES\" until all configuration parameters are updated.", title: "<b>Settings</b>", displayDuringSetup: false, type: "paragraph", element: "paragraph"
    generate_preferences(configuration_model())
  }

}

def parse(String description) {
  logDebug "parse(String description)"
  logTrace "description: $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.switchmultilevelv1.SwitchMultilevelSet cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd)"
  logTrace "cmd: $cmd"
  //not needed. do nothing.
}

def zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd)"
  logTrace "cmd: $cmd"
  //not needed. do nothing.
}

def zwaveEvent(hubitat.zwave.commands.switchmultilevelv3.SwitchMultilevelStartLevelChange cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.switchmultilevelv3.SwitchMultilevelStartLevelChange cmd)"
  logTrace "cmd: $cmd"
 
  def result = []
  
  //if not held buttons and button slide is enabled
  if (!getHeldButtons() && settings."3" == "1") {
    switch (cmd.upDown) {
      case false: // Up
        logTrace "Slide up"
        result << buttonEvent(device.currentValue("numberOfButtons") - 1, "pushed")
        break
      case true: // Down
        logTrace "Slide down"
        result << buttonEvent(device.currentValue("numberOfButtons"), "pushed")
        break
      default:
        logDebug "Unhandled SwitchMultilevelStartLevelChange: ${cmd}"
        break
    }
  }
  result
}

def zwaveEvent(hubitat.zwave.commands.centralscenev1.CentralSceneNotification cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.centralscenev1.CentralSceneNotification cmd)"
  logTrace "cmd: $cmd"

  def result = []
  
  sendEvent(name: "sequenceNumber", value: cmd.sequenceNumber, displayed:false)
  switch (cmd.keyAttributes) {
    case 0:
      result << buttonEvent(cmd.sceneNumber, "pushed")
      break
    case 1: // released
      state."${cmd.sceneNumber}" = cmd.keyAttributes
      if (!settings.holdMode || settings.holdMode == "2") result << buttonEvent(cmd.sceneNumber, "held")
      result << buttonEvent(cmd.sceneNumber, "released")
      break
    case 2: // held
      state."${cmd.sceneNumber}" = cmd.keyAttributes
      if (settings.holdMode == "1") result << buttonEvent(cmd.sceneNumber, "held")
      break
    default:
      logDebug "Unhandled CentralSceneNotification: ${cmd}"
      break
  }
  result
}

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) {
  logDebug "zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpIntervalReport cmd)"
  logTrace "cmd: $cmd"
  
  state.wakeInterval = cmd.seconds
}

def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpNotification cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpNotification cmd)"
  logTrace "cmd: $cmd"
  
  logInfo "Device ${device.displayName} woke up"

  def request = update_needed_settings()

  request << zwave.versionV1.versionGet()

  if (!state.lastBatteryReport || (now() - state.lastBatteryReport) / 60000 >= 60 * 24) {
    logDebug "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 {
    logDebug "No commands to send"
    response([zwave.wakeUpV1.wakeUpNoMoreInformation().format()])
  }
}

def buttonEvent(button, name) {
  def msg = "$device.displayName button $button was $name"
  logInfo msg
  createEvent(name: name, value: button, descriptionText: msg, isStateChange: true)
}

def zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd)"
  logTrace "cmd: $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) {
  logDebug "zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd)"
  logTrace "cmd: $cmd"
  state."association${cmd.groupingIdentifier}" = cmd.nodeId[0]
}

def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd) {
  update_current_properties(cmd)
  logDebug "${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)
  logDebug "${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.firmware0Version}.${cmd.firmware0SubVersion}"
  updateDataValue("fw", fw)
  if (state.MSR == "003B-6341-5044") {
    updateDataValue("ver", "${cmd.firmware0Version >> 4}.${cmd.firmware0SubVersion & 0xF}")
  }
  def text = "$device.displayName: firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}"
  createEvent(descriptionText: text, isStateChange: false)
}

def zwaveEvent(hubitat.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
  logDebug "zwaveEvent(hubitat.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd)"
  logTrace "cmd: $cmd"
  logInfo "Connectivity testing performed by user at remote..."
}

def zwaveEvent(hubitat.zwave.Command cmd) {
  log.warn "Unhandled zwaveEvent: ${cmd}"
}

def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
  def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
  logDebug "msr: $msr"
  updateDataValue("MSR", msr)
}

def installed() {
  log.info "...Aeon WallMote Installed..."
  configure()
}

/**
* Triggered when Done button is pushed on Preference Pane
*/
def updated() {
  logDebug "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: getNumButtons(), displayed: true)
  sendEvent(name:"needUpdate", value: device.currentValue("needUpdate"), displayed:false, isStateChange: true)
  if (cmds != []) response(commands(cmds))
}

def configure() {
  logDebug "Configuring Device For Use"
  def cmds = []
  cmds = update_needed_settings()
  sendEvent(name: "numberOfButtons", value: getNumButtons(), displayed: true)
  if (cmds != []) commands(cmds)
}

private getNumButtons() {
  return settings.buttons ? (settings."3" == "1" ? settings.buttons.toInteger() + 2 : settings.buttons) : (settings."3" ? 4 + 2 : 4)
}

def ping() {
  logDebug "ping()"
  log.warn "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:"<b>${it.@label}</b>", description: "${it.Help}", range: "${it.@min}..${it.@max}", defaultValue: "${it.@value}",
          displayDuringSetup: "${it.@displayDuringSetup}", required: "${it.@required}"
        break
      case "list":
        def items = []
        it.Item.each { items << ["${it.@value}": "${it.@label}"] }
        input "${it.@index}", "enum", title:"<b>${it.@label}</b>", description: "${it.Help}", defaultValue: "${it.@value}", options: items,
          displayDuringSetup: "${it.@displayDuringSetup}", required: "${it.@required}"
        break
      case "decimal":
        input "${it.@index}", "decimal", title:"<b>${it.@label}</b>", description: "${it.Help}", range: "${it.@min}..${it.@max}", defaultValue: "${it.@value}",
          displayDuringSetup: "${it.@displayDuringSetup}", required: "${it.@required}"
        break
      case "boolean":
        input "${it.@index}", "bool", title: "<b>${it.@label}</b>", description: "${it.Help}", defaultValue: "${it.@value}",
          displayDuringSetup: "${it.@displayDuringSetup}", required: "${it.@required}"
        break
      case "string":
        input "${it.@index}", "text", title: "<b>${it.@label}</b>", description: "${it.Help}", defaultValue: "${it.@value}",
          displayDuringSetup: "${it.@displayDuringSetup}", required: "${it.@required}"
        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) {
    logDebug "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") {
      logDebug "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") {
      logDebug "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") {
      logDebug "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") {
      logDebug "Setting association group 9"
      cmds << zwave.associationV2.associationSet(groupingIdentifier:9, nodeId:zwaveHubNodeId)
      cmds << zwave.associationV2.associationGet(groupingIdentifier:9)
    }
  }

  if (state.MSR == null){
    logDebug "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) {
              logDebug "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 {
              logDebug "Parameter has already sent. Will not send again until updated() gets called"
            }
          }
          else {
            logDebug "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"
          logDebug "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) {
            logDebug "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 {
            logDebug "Parameter has already sent. Will not send again until updated() gets called"
          }
        }
        else {
          logDebug "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 getHeldButtons() {
  def heldButtons = (1..device.currentValue("numberOfButtons"))
  heldButtons = heldButtons.find { button ->
    state."${button}" == 2
  }
  logTrace "heldButtons $heldButtons"
  return heldButtons
}

private logInfo(msg) {
  if (settings.loggingLevel?.toInteger() >= 1) log.info msg
}

def logDebug(msg) {
  if (settings.loggingLevel?.toInteger() >= 2) log.debug msg
}

def logTrace(msg) {
  if (settings.loggingLevel?.toInteger() >= 3) log.trace msg
}

/**
* 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" deviceId="" 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" deviceId="">
    <Help>
Enable/disable the touch sound.<br/>
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" deviceId="">
    <Help>
Enable/disable the touch vibration.<br/>
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" deviceId="">
    <Help>
Enable/disable the function of button slide.<br/>
Default: Enable
    </Help>
    <Item label="Disable" value="0" />
    <Item label="Enable" value="1" />
  </Value>
  <Value type="list" byteSize="4" index="5" label="LED Color" min="1" max="3" value="3" setting_type="zwave" deviceId="" setonly="true">
    <Help>
To configure which color will be displayed when the button is pressed.<br/>
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" deviceId=""> 
    <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.<br/>
Default: No
    </Help>
    <Item label="No" value="2" />
    <Item label="Yes" value="1" />
  </Value>
  <Value type="list" byteSize="1" index="loggingLevel" label="Logging Level?" min="0" max="3" value="0" setting_type="preference" deviceId="" required="true">
    <Help>
Set the verbosity of the logs.
    </Help>
    <Item label="No Logging" value="0" />
    <Item label="Descriptive Text" value="1" />
    <Item label="Debug" value="2" />
    <Item label="Trace" value="3" />
  </Value>
</configuration>
'''
}


Thank you so much for looking at this please, don't go crazy.[quote="thebearmay, post:19, topic:92414, full:true"]
If you’ll post the file you are currently using (inside a summary block please) I’ll take a look at it. (I’d rather do that than re-porting the ST driver from erocm123 to make sure that any enhancements that codahq may have added are retained.)