ZWN-SC7 Enerwave 7 Button Scene Controller

Hello, sorry to message you in this thread, but can’t figure out how to contact you in the ZRC-90 thread. Several of us have had that controller quick working in the last week or so. Your device handler seems to be working fine, but the enhanced button controller does not work. Did you write that? Any suggestions for us? Thanks for all your great work!
Brent

I did not write that app. Smart Lighting is what I would usually use with button devices.

1 Like

Thanks for the reply. Looks like smart Lighting provides on/off, but doesn’t provide light level control. I was using it to be able to set a lamp to variable brightnesses.

I had device handler and button controler loaded for several years working fine, then upgraded to new app a few months ago, then just had a hub update and now the controller is dead.

Cleared it from new ST app, factory reset cont ZWN-SC7 (hold big button till flashing, then top right, middle right, then bottom right, then big button, it flashes and should be reset).

Pick the + button from the new app to add, then scan nearby option (cause it don’t show up as a recognized device), then put device into inclusion mode (big button till flashing, then top left, middle left, then bottom left, all show flashing slow), app says scanning, but controler won’t connect?

Lastest drivers:

ZWN-SC7 Enerwave 7 Button Scene Controller
Date Created: 2014-12-18
Last Updated: 2017-05-10 update DT to support pushed as @ady624

Button Controller App for ZWN-SC7
Date Created: 2014-12-18
Last Updated: 2015-11-14

After clearing smart app and device handler and all copies of the device from the new app, factory reseting the app, powering it’s circuit breaker off for 30 secs, then loading the base device handler and smart app from the mfg, it did recognize good, but it only assignes button 1, all other buttons will not program.

No other smart app or device handler would recognize, heres the ones that worked for button 1 only:

sent email to company for support…

Is there any multiple switch on the market like this that works with ST?

I’m in the same quandary. I keep thinking about the Brilliant device as a replacement, but the cost is a bit salty…

Well, looks like you did write the enhanced button controller…but you’ve written so many you forgot!

Button Controller - Enhanced Lighting
*

@BrentB LOL, yeah I did create that. I thought you were talking about ABC (Advanced Button Controller) for some reason. I haven’t used Button Controller - Enhanced Lighting for years as I have been using the SmartThings provided “Smart Lighting”.

Re: # Enerwave ZWN-SC7 Z-Wave Scene Controller 7-Button Switch

So, I’ve got five of these installed and been working for years @ approx $25 each I’d like to know if smartthings has just made them obsolete with the new fantastic app?

I’ve spent a ton of money and years of time in three houses with smartthings are now all a complete joke. Trying to get things barely working is now a full time job.

Thanks Smartthings, not sure how your programming team sleeps at night knowing how much of a disaster this “upgraded” app is compared to the classic app. +1 for bug fixing job security. All you new users will never know how great it was and will just think THIS is as good as smarthomes get. With New smartthings, Answer is yes until the next time the rug is pulled under our feet.

So sad.

If anyone has a solution to get my 7 button scene controllers back online I’ll happily send you a Starbucks GC

Similar frustration with the ZRC-90, fortunately I only have one of these, now half working thanks to the forum members and many hours trying to get this and my Hue remotes working again.

What is the issue with Samsung and these buttons, I noticed only 2 officially supported devices, Samsungs own button and Aurora AU-A1ZBRC

Yep, last app and Hub update killed mine. As I mentioned above, I got only button 1 to work with the default handler and smart app provided in the mfg’s doc. All the new and updated handlers never allow any buttons to be assigned.

So for now, it’s a single button switch.

Actually, was playing around in the IDE and not sure if when I reselected custom device handler, but all is working again, resent the button programing and back to normal with the factory driver and app. Not sure if ST fixed anything in background, but all good.

When bad, only button 1 worked, all other buttons just flashed fast, now all flash once and work, except for big button just works, no blink on led.

I’ve got eight ZWN-SC7 controllers that stopped working after the new ST “upgrade”.
After removing and adding, the device registers button presses in the RECENTLY section of the app but does not switch on lights as programmed in the ZWN-SC7 Button Controller SmartApp.
I’d be happy to pay $50 to anyone with a solution.

I’m trying to install a ZWN-SC7 into my SmartThings setup. I followed the instructions above (though I created the SmartApp before connecting to the device.) It showed up in the SmartThings iPhone app when I scanned for devices and automatically added (I’ve tried deleting and repairing and the process is sporadic - sometimes the device is added without any notification.) I found no way to “Configure” the device. And when I click on its button in the SmartThings app, it says it can’t connect to the device.

The live logging doesn’t seem to indicate a button press and every button but the top left one makes every LED flash on and off several times. Pressing the top left button causes its LED to flash several times, then stay lit. Pressing it again does the same, always stay lit until I press another button, then all the LEDs flash several times and then all stay solidly lit.

Logging for the top left button press indicates “Parsing 'zw device: 15, command: 2B01, payload: 01 FF '” sometimes.

Logging for the other buttons sporadically gives differing messages/error messages.

Lastly, I noticed that in the ‘Devices’ list in the SmartThings web portal, this device is connected to the hub through another SmartThings device (an outlet.) All the other devices are connected directly to the hub.

@EHarch and @Jack_Cohen

This is a longshot but I tried to update this handler. I don’t have the device and have no way to verify it this update works or not. I’ve updated a lot of other button devices for the new app successfully, but this one is unique and uses older zwave command classes so I’m not sure if it will work.

Try and use it with the original smartapp, and if that doesn’t work, give it a try with the smartlighting app or webcore.

1 Like

I know this is an old post, but if you’re still looking, you can try the code below to see if it works for you. You should monitor the Live Logging in IDE and see if you get any debug info telling you which button you pressed. (then, if you want, you can compare this code with the original mattjfrank one and see where it differs)

The smartapp that goes with the DTH is not (yet) working in the new app… I’ll be trying to debug it soon, hopefully.

/**
 *  ZWN-SC7 Enerwave 7 Button Scene Controller
 *
 *  Author: Matt Frank based on VRCS Button Controller by Brian Dahlem, based on SmartThings Button Controller
 *  Date Created: 2014-12-18
 *  Last Updated: 2017-05-10 update DT to support pushed as @ady624 
 *
 *  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.
 *
 *  2016-09-30 Modified to allow for correct event value "pushed" and added numberOfButtons as per ST documentation
 *
 */

 metadata {
  // Automatically generated. Make future change here.
  definition (name: "LivingWise 7 Button Scene Controller", namespace: "mattjfrank", author: "Matt Frank") {
        capability "Actuator"
        capability "Button"
        capability "Configuration"
        capability "Indicator"
        capability "Sensor"

        attribute "currentButton", "STRING"
        attribute "numButtons", "STRING"
        attribute "numberOfButtons", "NUMBER"

        fingerprint profileId: "0104",
                deviceId: "000C",
                inClusters: "0000, 0005",
                outClusters: "0000, 0005, 0017",
                manufacturer: "欧瑞博",
                model: "75d430d66c164c26ac8601c05932dc94",
                deviceJoinName: "LivingWise 7 Button Scene Controller"
  }

  simulator {
    status "button 1 pushed":  "command: 2B01, payload: 01 FF"
    status "button 2 pushed":  "command: 2B01, payload: 02 FF"
    status "button 3 pushed":  "command: 2B01, payload: 03 FF"
    status "button 4 pushed":  "command: 2B01, payload: 04 FF"
    status "button 5 pushed":  "command: 2B01, payload: 05 FF"
    status "button 6 pushed":  "command: 2B01, payload: 06 FF"
    status "button 7 pushed":  "command: 2B01, payload: 07 FF"
    status "button released":  "command: 2C02, payload: 00"
  }

  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.Weather.weather14", 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"
      state "button 5", label: "5", icon: "st.Weather.weather14", backgroundColor: "#79b821"
      state "button 6", label: "6", icon: "st.Weather.weather14", backgroundColor: "#79b821"
      state "button 7", label: "7", 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"])
  }
}

// parse events into attributes
def parse(String description) {
  // for button2 pressed
  // description: catchall: 0104 0017 01 0A 0100 00 C123 01 00 0000 08 01 020000
  log.debug "Parsing '${description}'"
  def result = zigbee.parse(description)
  // result: SmartShield(text: null, manufacturerId: 0x0000, direction: 0x01, data: [0x02, 0x00, 0x00], number: null, isManufacturerSpecific: false, messageType: 0x00, senderShortId: 0xc123, isClusterSpecific: true, sourceEndpoint: 0x01, profileId: 0x0104, command: 0x08, clusterId: 0x0017, destinationEndpoint: 0x0a, options: 0x0100)
  
  def resultData = result.data
  def buttonId = resultData[0]

  log.debug "Pressed button ${buttonId}"

  buttonEvent(buttonId)
}

// Handle a button being pressed
def buttonEvent(button) {
  button = button as Integer
  def result = []


    updateState("currentButton", "$button")

    if (button > 0) {
        // update the device state, recording the button press
        result << createEvent(name: "button", value: "button $button", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)

        // turn off the button LED
        result << response(zwave.sceneActuatorConfV1.sceneActuatorConfReport(dimmingDuration: 255, level: 255, sceneId: 0))
  }
    else {
        // update the device state, recording the button press
        result << createEvent(name: "button", value: "default", descriptionText: "$device.displayName button was released", isStateChange: true)

        result << response(zwave.sceneActuatorConfV1.sceneActuatorConfReport(dimmingDuration: 255, level: 255, sceneId: 0))
    }

	// result example: [[name:button, value:button 4, data:[buttonNumber:4], descriptionText:Living Scene Controller button 4 was pushed, isStateChange:true, linkText:Living Scene Controller, displayed:true], 2C0300FFFF]
    result
}

// A zwave command for a button press was received
def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {

  // The controller likes to repeat the command... ignore repeats
  if (state.lastScene == cmd.sceneId && (state.repeatCount < 4) && (now() - state.repeatStart < 2000)) {
      log.debug "Button ${cmd.sceneId} repeat ${state.repeatCount}x ${now()}"
        state.repeatCount = state.repeatCount + 1
        createEvent([:])
    }
    else {
      // If the button was really pressed, store the new scene and handle the button press
        state.lastScene = cmd.sceneId
        state.lastLevel = 0
        state.repeatCount = 0
        state.repeatStart = now()

        buttonEvent(cmd.sceneId)
    }
}

// A scene command was received -- it's probably scene 0, so treat it like a button release
def zwaveEvent(physicalgraph.zwave.commands.sceneactuatorconfv1.SceneActuatorConfGet cmd) {

  buttonEvent(cmd.sceneId)

}

// The controller sent a scene activation report.  Log it, but it really shouldn't happen.
def zwaveEvent(physicalgraph.zwave.commands.sceneactuatorconfv1.SceneActuatorConfReport cmd) {
    log.debug "Scene activation report"
  log.debug "Scene ${cmd.sceneId} set to ${cmd.level}"

    createEvent([:])
}


// Configuration Reports are replys to configuration value requests... If we knew what configuration parameters
// to request this could be very helpful.
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
  createEvent([:])
}

// The VRC supports hail commands, but I haven't seen them.
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
    createEvent([name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false])
}

// Update manufacturer information when it is reported
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
  if (state.manufacturer != cmd.manufacturerName) {
    updateDataValue("manufacturer", cmd.manufacturerName)
  }

    createEvent([:])
}

// Association Groupings Reports tell us how many groupings the device supports.  This equates to the number of
// buttons/scenes in the VRCS
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationGroupingsReport cmd) {
  def response = []

    log.debug "${getDataByName("numButtons")} buttons stored"
  if ((getDataByName("numButtons") != "$cmd.supportedGroupings") || (getDataByName("numberOfButtons") != (int) cmd.supportedGroupings)) {
        updateState("numButtons", "$cmd.supportedGroupings")
        updateState("numberOfButtons", (int) cmd.supportedGroupings)
        log.debug "${cmd.supportedGroupings} groups available"
        response << createEvent(name: "numButtons", value: cmd.supportedGroupings, displayed: false)
        response << createEvent(name: "numberOfButtons", value: cmd.supportedGroupings, displayed: false)

        response << associateHub()
  }
    else {
      response << createEvent(name: "numButtons", value: cmd.supportedGroupings, displayed: false)
      response << createEvent(name: "numberOfButtons", value: cmd.supportedGroupings, displayed: false)
    }
    return response
}


// Handles all Z-Wave commands we don't know we are interested in
def zwaveEvent(physicalgraph.zwave.Command cmd) {
    createEvent([:])
}

// handle commands

// Create a list of the configuration commands to send to the device
def configurationCmds() {
  // Always check the manufacturer and the number of groupings allowed
  def commands = [
    zwave.manufacturerSpecificV1.manufacturerSpecificGet().format(),
    zwave.associationV1.associationGroupingsGet().format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:1, sceneId:1).format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:2, sceneId:2).format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:3, sceneId:3).format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:4, sceneId:4).format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:5, sceneId:5).format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:6, sceneId:6).format(),
    zwave.sceneControllerConfV1.sceneControllerConfSet(groupId:7, sceneId:7).format()

    ]

    commands << associateHub()

    delayBetween(commands)
}

// Configure the device
def configure() {
  def cmd=configurationCmds()
    log.debug("Sending configuration: ${cmd}")
    return cmd
}


//
// Associate the hub with the buttons on the device, so we will get status updates
def associateHub() {
    def commands = []

    // Loop through all the buttons on the controller
    for (def buttonNum = 1; buttonNum <= integer(getDataByName("numButtons")); buttonNum++) {

          // Associate the hub with the button so we will get status updates
          commands << zwave.associationV1.associationSet(groupingIdentifier: buttonNum, nodeId: zwaveHubNodeId).format()

  }

    return commands
}

// Update State
// Store mode and settings
def updateState(String name, String value) {
  state[name] = value
  device.updateDataValue(name, value)
}

// Get Data By Name
// Given the name of a setting/attribute, lookup the setting's value
def getDataByName(String name) {
  state[name] ?: device.getDataValue(name)
}

//Stupid conversions

// convert a double to an integer
def integer(double v) {
  return v.toInteger()
}

// convert a hex string to integer
def integerhex(String v) {
  if (v == null) {
      return 0
    }

  return Integer.parseInt(v, 16)
}

// convert a hex string to integer
def integer(String v) {
  if (v == null) {
      return 0
    }

  return Integer.parseInt(v)
}

So, I was able to get everything to work again! I use the “LivingWise Zigbee 7-button scene controller LVS-ZB-SC7” This is one of the most indispensable devices… I love the ability to control multiple devices/scenes with so many buttons/options.

I think the ZWN-SC7 by Enerwave is a Z-Wave scene controller, not Zigbee… so the DTH I posted earlier won’t work with it. However, once you use the proper DTH for your device (the one I posted for Zigbee, or the original one for Z-Wave), the SmartApp I’ll be posting below should work.

/**
 *  Button Controller App for ZWN-SC7
 *
 *  Author: Matt Frank based on VRCS Button Controller by Brian Dahlem, based on SmartThings Button Controller
 *  Date Created: 2014-12-18
 *      Last Updated: 2015-11-14
 *      Modified by Scott Barton to add Dimmer Level, Light Color, FanSpeed, DimmerUp, DimmerDown, and Shade control 2016-10-11
 *      SB Mods based on Button Controller+ and Garden Hue code  
 *
 *  Contributions from erocm1231 @ SmartThings Community
 *
 *  Source: https://community.smartthings.com/t/zwn-sc7-enerwave-7-button-scene-controller/2969/708?u=borice
 *
 */
definition(
    name: "ZWN-SC7   Button Controller",
    namespace: "mattjfrank",
    author: "Matt Frank, using code from Brian Dahlem",
    description: "ZWN-SC7    7-Button    Scene   Controller Button Assignment App",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/MyApps/Cat-MyApps.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/MyApps/Cat-MyApps@2x.png"
)

preferences {
  page(name: "selectButton")
  page(name: "configureButton1")
  page(name: "configureButton2")
  page(name: "configureButton3")
  page(name: "configureButton4")
  page(name: "configureButton5")
  page(name: "configureButton6")
  page(name: "configureButton7")
}

def selectButton() {
  dynamicPage(name: "selectButton", title: "First, select which ZWN-SC7", nextPage: "configureButton1", uninstall: configured()) {
    section {
      input "buttonDevice", "capability.button", title: "Controller", multiple: false, required: true
    }
    section(title: "Advanced", hideable: true, hidden: true) {
      input "debounce", "number", title: "Debounce time in milliseconds", required: true, value: 3000
    }


  }
}

def configureButton1() {
  dynamicPage(name: "configureButton1", title: "1st button, what do you want it to do?",
    nextPage: "configureButton2", uninstall: configured(), getButtonSections(1))

}

def configureButton2() {
  dynamicPage(name: "configureButton2", title: "2nd button, what do you want it to do?",
    nextPage: "configureButton3", uninstall: configured(), getButtonSections(2))
}

def configureButton3() {
  dynamicPage(name: "configureButton3", title: "3rd button, what do you want it to do?",
    nextPage: "configureButton4", uninstall: configured(), getButtonSections(3))
}
def configureButton4() {
  dynamicPage(name: "configureButton4", title: "4th button, what do you want it to do?",
    nextPage: "configureButton5", uninstall: configured(), getButtonSections(4))
}
def configureButton5() {
  dynamicPage(name: "configureButton5", title: "5th button, what do you want it to do?",
    nextPage: "configureButton6", uninstall: configured(), getButtonSections(5))
}
def configureButton6() {
  dynamicPage(name: "configureButton6", title: "6th button, what do you want it to do?",
    nextPage: "configureButton7", uninstall: configured(), getButtonSections(6))
}
def configureButton7() {
  dynamicPage(name: "configureButton7", title: "7th  button, what do you want it to do?",
    install: true, uninstall: true, getButtonSections(7))
}

def getButtonSections(buttonNumber) {
  return {
    section(title: "Toggle these...", hidden: hideSection(buttonNumber, "toggle"), hideable: true) {
      input "lights_${buttonNumber}_toggle", "capability.switch", title: "Switches:", multiple: true, required: false
      input "locks_${buttonNumber}_toggle", "capability.lock", title: "Locks:", multiple: true, required: false
      input "sonos_${buttonNumber}_toggle", "capability.musicPlayer", title: "Music Players:", multiple: true, required: false
    }
    section(title: "Turn on these...", hidden: hideSection(buttonNumber, "on"), hideable: true) {
      input "lights_${buttonNumber}_on", "capability.switch", title: "Switches:", multiple: true, required: false
      input "sonos_${buttonNumber}_on", "capability.musicPlayer", title: "Music Players:", multiple: true, required: false
    }
    section(title: "Turn off these...", hidden: hideSection(buttonNumber, "off"), hideable: true) {
      input "lights_${buttonNumber}_off", "capability.switch", title: "Switches:", multiple: true, required: false
      input "sonos_${buttonNumber}_off", "capability.musicPlayer", title: "Music Players:", multiple: true, required: false
    }
    
    //SB
    //section("Toggle Lights to Level", hidden: hideSection(buttonNumber, "setLevel"), hideable: true) {
    section("Turn on Lights to Level", hidden: hideSection(buttonNumber, "setLevel"), hideable: true) {
            input "dimmers_${buttonNumber}_setLevel", "capability.switchLevel", title: "Lights", multiple: true, required: false
            input "dimmerLevel_${buttonNumber}_level", "number", title: "Dim Level", required: false, description: "0 to 99"
    }
    section("Set Light to Color", hidden: hideSection(buttonNumber, "setColor"), hideable: true) {
            input "lights_${buttonNumber}_setColor", "capability.colorControl", title: "Lights", multiple: true, required: false
            input "lightColor_${buttonNumber}_color", "enum", title: "Color" , options: ["Warm White","Soft White","Daylight","White","Red","Orange","Amber","Yellow","Green","Turquoise","Aqua","Navy Blue","Blue","Indigo","Purple","Pink"], required: false
            input "lightLevel_${buttonNumber}_level", "number", title: "Level", required: false, description: "0 to 99"
    }
    section(title: "Adjust Fan Speed - Low, Medium, High, Off", hidden: hideSection(buttonNumber, "fanSpeed"), hideable: true) {
      input "fans_${buttonNumber}_fanSpeed", "capability.switchLevel", title: "Fans:", multiple: true, required: false
    }
    section(title: "Adjust Dimmer Up 10%", hidden: hideSection(buttonNumber, "dimmerUp"), hideable: true) {
      input "dimmers_${buttonNumber}_dimmerUp", "capability.switchLevel", title: "Dimmers:", multiple: true, required: false
    }
    section(title: "Adjust Dimmer Down 10%", hidden: hideSection(buttonNumber, "dimmerDown"), hideable: true) {
      input "dimmers_${buttonNumber}_dimmerDown", "capability.switchLevel", title: "Dimmers:", multiple: true, required: false
    }
   section("Adjust Shade - Up, Down, or Stop", hidden: hideSection(buttonNumber, "adjustShade"), hideable: true) {
       input "shades_${buttonNumber}_adjustShade", "capability.doorControl", title: "Shades:", multiple: false, required: false
   }
   //END SB
   
    section(title: "Locks:", hidden: hideLocksSection(buttonNumber), hideable: true) {
      input "locks_${buttonNumber}_unlock", "capability.lock", title: "Unlock these locks:", multiple: true, required: false
      input "locks_${buttonNumber}_lock", "capability.lock", title: "Lock these locks:", multiple: true, required: false
    }
    section("Modes") {
      input "mode_${buttonNumber}_on", "mode", title: "Activate these modes:", required: false
    }
    def phrases = location.helloHome?.getPhrases()*.label
    if (phrases) {
      section("Hello Home Actions") {
        log.trace phrases
        input "phrase_${buttonNumber}_on", "enum", title: "Activate these phrases:", required: false, options: phrases
      }
    }
  }
}

def installed() {
  initialize()
}

def updated() {
  unsubscribe()
  initialize()
}

def initialize() {

  subscribe(buttonDevice, "button", buttonEvent)

    if (relayDevice) {
        log.debug "Associating ${relayDevice.deviceNetworkId}"
        if (relayAssociate == true) {
            buttonDevice.associateLoad(relayDevice.deviceNetworkId)
        }
        else {
            buttonDevice.associateLoad(0)
        }
    }
}

def configured() {
  return  buttonDevice || buttonConfigured(1) || buttonConfigured(2) || buttonConfigured(3) || buttonConfigured(4) || buttonConfigured(5) || buttonConfigured(6) || buttonConfigured(7)
}

def buttonConfigured(idx) {
  return settings["lights_$idx_toggle"] ||
    settings["locks_$idx_toggle"] ||
    settings["sonos_$idx_toggle"] ||
    settings["mode_$idx_on"] ||
    settings["lights_$idx_on"] ||
    settings["locks_$idx_on"] ||
    settings["sonos_$idx_on"] ||
    settings["lights_$idx_off"] ||
    //SB
    settings["dimmers_$idx_setLevel"] ||
    settings["dimmerLevel_$idx_level"] ||
    settings["lights_$idx_setColor"] ||
    settings["lightColor_$idx_color"] ||
    settings["lightLevel_$idx_level"] ||
    settings["fans_$idx_fanSpeed"] ||
    settings["dimmers_$idx_dimmerUp"] ||
    settings["dimmers_$idx_dimmerDown"] ||
    settings["shades_$idx_adjustShade"] ||
    //END SB
    settings["locks_$idx_off"] ||
    settings["sonos_$idx_off"]
}

def buttonEvent(evt){
  log.debug "buttonEvent"
  if(allOk) {
      def buttonNumber = evt.jsonData.buttonNumber
      def firstEventId = 0
      def value = evt.value
      //log.debug "buttonEvent: $evt.name = $evt.value ($evt.data)"
      log.debug "button: $buttonNumber, value: $value"
      def recentEvents = buttonDevice.eventsSince(new Date(now() - debounce)).findAll{it.value == evt.value && it.data == evt.data}
      log.debug "Found ${recentEvents.size()?:0} events in past ${debounce/1000} seconds"
      if (recentEvents.size() != 0){
          log.debug "First Event ID: ${recentEvents[0].id}"
          firstEventId = recentEvents[0].id
      }
      else {
          firstEventId = evt.id
      }
        
      log.debug "This Event ID: ${evt.id}"

      if(firstEventId == evt.id){
      switch(buttonNumber) {
        case ~/.*1.*/:
          executeHandlers(1)
          break
        case ~/.*2.*/:
          executeHandlers(2)
          break
        case ~/.*3.*/:
          executeHandlers(3)
          break
        case ~/.*4.*/:
          executeHandlers(4)
          break
        case ~/.*5.*/:
          executeHandlers(5)
          break
        case ~/.*6.*/:
          executeHandlers(6)
          break
        case ~/.*7.*/:
          executeHandlers(7)
          break
      }
    } else if (firstEventId == 0) {
      log.debug "No events found. Possible SmartThings latency"
    } else {
      log.debug "Duplicate button press found. Not executing handlers"
    }
    
  }
    else {
      log.debug "NotOK"
    }
}

def executeHandlers(buttonNumber) {
  log.debug "Executing handler for button ${buttonNumber}"

  def lights = find('lights', buttonNumber, "toggle")
  if (lights != null) toggle(lights)

  def locks = find('locks', buttonNumber, "toggle")
  if (locks != null) toggle(locks)

  def sonos = find('sonos', buttonNumber, "toggle")
  if (sonos != null) toggle(sonos)

  lights = find('lights', buttonNumber, "on")
  if (lights != null) flip(lights, "on")

  locks = find('locks', buttonNumber, "unlock")
  if (locks != null) flip(locks, "unlock")

  sonos = find('sonos', buttonNumber, "on")
  if (sonos != null) flip(sonos, "on")

  lights = find('lights', buttonNumber, "off")
  if (lights != null) flip(lights, "off")
  
//SB
  def level = find('dimmerLevel', buttonNumber, "level")
  if (level == null) level = 99
  def dimmers = find('dimmers', buttonNumber, "setLevel")
  if (dimmers != null) setLightLevel(dimmers, level)
  
  def color = find('lightColor', buttonNumber, "color")
  if (color == null) color = "White"
  level = find('lightLevel', buttonNumber, "level")
  if (level == null) level = 99
  lights = find('lights', buttonNumber, "setColor")
  if (lights != null) setMyColor(lights, color, level)
  
  def fans = find('fans', buttonNumber, "fanSpeed")
  if (fans != null) adjustFan(fans)

  dimmers = find('dimmers', buttonNumber, "dimmerUp")
  if (dimmers != null) dimmerUp(dimmers)

  dimmers = find('dimmers', buttonNumber, "dimmerDown")
  if (dimmers != null) dimmerDown(dimmers)

  def shades = find('shades', buttonNumber, "adjustShade")
  if (shades) adjustShade(shades)
//END SB

  locks = find('locks', buttonNumber, "lock")
  if (locks != null) flip(locks, "lock")

  sonos = find('sonos', buttonNumber, "off")
  if (sonos != null) flip(sonos, "off")

  def mode = find('mode', buttonNumber, "on")
  if (mode != null) changeMode(mode)

  def phrase = find('phrase', buttonNumber, "on")
  if (phrase != null) location.helloHome.execute(phrase)
}

def find(type, buttonNumber, value) {
  def preferenceName = type + "_" + buttonNumber + "_" + value
  def pref = settings[preferenceName]
  if(pref != null) {
    log.debug "Found: $pref for $preferenceName"
  }

  return pref
}

def flip(devices, newState) {
  log.debug "flip: $devices = ${devices*.currentValue('switch')}"


  if (newState == "off") {
    devices.off()
  }
  else if (newState == "on") {
    devices.on()
  }
  else if (newState == "unlock") {
    devices.unlock()
  }
  else if (newState == "lock") {
    devices.lock()
  }
}

def toggle(devices) {
  log.debug "toggle: $devices = ${devices*.currentValue('switch')}"

  if (devices*.currentValue('switch').contains('on')) {
    devices.off()
  }
  else if (devices*.currentValue('switch').contains('off')) {
    devices.on()
  }
  else if (devices*.currentValue('lock').contains('locked')) {
    devices.unlock()
  }
  else if (devices*.currentValue('lock').contains('unlocked')) {
    devices.lock()
  }
  else {
    devices.on()
  }
}

//SB
def setLightLevel(devices, level) {
  log.debug "setLevel: $devices = ${devices*.currentSwitch}"
  if (level < 1) level = 1
  if (level > 99) level = 99
  //if (devices*.currentValue('switch').contains('on')) {
  //  devices.off()
  //}
  //else if (devices*.currentValue('switch').contains('off')) {
  //  devices.setLevel(level)
  //}
  //else {
  //  devices.on()
  //}
  
  devices.setLevel(level)
}


def setMyColor(devices, color, level) {
  log.debug "setLevel: $devices = ${devices*.currentSwitch}"
  if (devices*.currentValue('switch').contains('on')) {
    devices.off()
  }
  else if (devices*.currentValue('switch').contains('off')) {
    setLightColor(devices, color, level)
  }
  else {
    devices.on()
  }
}

def setLightColor(devices, color, brightnessLevel)
{
 log.debug "setColor: $devices = ${devices*.currentValue('switch')}"
    //Initialize the hue and saturation
    def hueColor = 0
    def saturation = 100

    //Use the user specified brightness level. If they exceeded the min or max values, overwrite the brightness with the actual min/max
    if (brightnessLevel<1) {
        brightnessLevel=1
    }
    else if (brightnessLevel>100) {
        brightnessLevel=100
    }
    //Set the hue and saturation for the specified color.
    switch(color) {
        case "White":
            hueColor = 0
            saturation = 0
            break;
        case "Daylight":
            hueColor = 53
            saturation = 91
            break;
        case "Soft White":
            hueColor = 23
            saturation = 56
            break;
        case "Warm White":
            hueColor = 20
            saturation = 80 
            break;
        case "Navy Blue":
            hueColor = 61
            break;
        case "Blue":
            hueColor = 65
            break;
        case "Green":
            hueColor = 33
            break;
        case "Turquoise":
            hueColor = 47
            break;
        case "Aqua":
            hueColor = 50
            break;
        case "Amber":
            hueColor = 13
            break;
        case "Yellow":
            //hueColor = 25
            hueColor = 17
            break; 
        case "Safety Orange":
            hueColor = 7
            break;
        case "Orange":
            hueColor = 10
            break;
        case "Indigo":
            hueColor = 73
            break;
        case "Purple":
            hueColor = 82
            saturation = 100
            break;
        case "Pink":
            hueColor = 90.78
            saturation = 67.84
            break;
        case "Rasberry":
            hueColor = 94
            break;
        case "Red":
            hueColor = 0
            break;
         case "Brick Red":
            hueColor = 4
            break;
         default:
           hueColor = 0
           saturation = 0
           break;
    }

    //Change the color of the light
    def newValue = [hue: hueColor, saturation: saturation, level: brightnessLevel]  
    devices.setColor(newValue)
    state.currentColor = color
    //mysend("$app.label: Setting Color = $color")
    log.debug "$app.label: Setting Color = $color"
}

def adjustFan(devices) {
    log.debug "adjustFan: $devices = ${devices*.currentLevel}"
    
    def levelsList = devices*.currentLevel
    levelsList.sort()
    levelsList = levelsList.reverse() 
    def currentLevel = levelsList[0]
    log.debug "currentLevel =$currentLevel"

    if (!devices*.currentValue('switch').contains('on')) devices.setLevel(20)
    else if (currentLevel < 34) devices.setLevel(50)
    else if (currentLevel < 67) devices.setLevel(99)
    else devices.off()
}

def dimmerUp(devices) {
    //Must take your time (~5s) between button presses or it may get messed up. 
    log.debug "dimmerUp: $devices = ${devices*.currentLevel}"
    
    def levelsList = devices*.currentLevel
    levelsList.sort()
    levelsList = levelsList.reverse()
    def currentLevel = levelsList[0]
    log.debug "currentLevel =$currentLevel"


    if (!devices*.currentValue('switch').contains('on')) devices.setLevel(10)
    else if (currentLevel < 20) devices.setLevel(20)
    else if (currentLevel < 30) devices.setLevel(30)
    else if (currentLevel < 40) devices.setLevel(40)
    else if (currentLevel < 50) devices.setLevel(50)
    else if (currentLevel < 60) devices.setLevel(60)
    else if (currentLevel < 70) devices.setLevel(70)
    else if (currentLevel < 80) devices.setLevel(80)
    else if (currentLevel < 90) devices.setLevel(90)
    else if (currentLevel < 99) devices.setLevel(99)
    else devices.on()
}

def dimmerDown(devices) {
    //Must take your time (~5s) between button presses or it may get messed up. 
    log.debug "dimmerDown: $devices = ${devices*.currentLevel}"
   
    def levelsList = devices*.currentLevel
    log.debug "listSize= $levelsList.size"
    levelsList.sort()
    log.debug "levelsListSorted= $levelsList"
    //levelsList = levelsList.reverse()
    //log.debug "levelsListSortedDesc= $levelsList"

    log.debug "1st Item = ${levelsList[0]}"
    def currentLevel = levelsList[0]
    log.debug "currentLevel =$currentLevel"

    if (devices*.currentValue('switch').contains('off')) devices.off()
    else if (currentLevel > 90) devices.setLevel(90)
    else if (currentLevel > 80) devices.setLevel(80)
    else if (currentLevel > 70) devices.setLevel(70)
    else if (currentLevel > 60) devices.setLevel(60)
    else if (currentLevel > 50) devices.setLevel(50)
    else if (currentLevel > 40) devices.setLevel(40)
    else if (currentLevel > 30) devices.setLevel(30)
    else if (currentLevel > 20) devices.setLevel(20)
    else if (currentLevel > 10) devices.setLevel(10)
    else devices.off()
}

def adjustShade(device) {
    log.debug "adjustShade: $device = ${device.currentMotor} state.lastUP = $state.lastshadesUp"

    if(device.currentMotor in ["up","down"]) {
        state.lastshadesUp = device.currentMotor == "up"
        device.stop()
    } else {
        state.lastshadesUp ? device.down() : device.up()
//      if(state.lastshadesUp) device.down()
//        else device.up()
        state.lastshadesUp = !state.lastshadesUp
    }
}
//END SB

def changeMode(mode) {
  log.debug "changeMode: $mode, location.mode = $location.mode, location.modes = $location.modes"

  if (location.mode != mode && location.modes?.find { it.name == mode }) {
    setLocationMode(mode)
  }
}

// execution filter methods
private getAllOk() {
  modeOk && daysOk && timeOk
}

private getModeOk() {
  def result = !modes || modes.contains(location.mode)
  log.trace "modeOk = $result"
  result
}

private getDaysOk() {
  def result = true
  if (days) {
    def df = new java.text.SimpleDateFormat("EEEE")
    if (location.timeZone) {
      df.setTimeZone(location.timeZone)
    }
    else {
      df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
    }
    def day = df.format(new Date())
    result = days.contains(day)
  }
  log.trace "daysOk = $result"
  result
}

private getTimeOk() {
  def result = true
  if (starting && ending) {
    def currTime = now()
    def start = timeToday(starting).time
    def stop = timeToday(ending).time
    result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
  }
  log.trace "timeOk = $result"
  result
}

private hhmm(time, fmt = "h:mm a")
{
  def t = timeToday(time, location.timeZone)
  def f = new java.text.SimpleDateFormat(fmt)
  f.setTimeZone(location.timeZone ?: timeZone(time))
  f.format(t)
}

private hideOptionsSection() {
  (starting || ending || days || modes) ? false : true
}

private hideSection(buttonNumber, action) {
  (find("lights", buttonNumber, action) || find("locks", buttonNumber, action) || find("sonos", buttonNumber, action)) ? false : true
}

private hideLocksSection(buttonNumber) {
  (find("lights", buttonNumber, "lock") || find("locks", buttonNumber, "unlock")) ? false : true
}

private timeIntervalLabel() {
  (starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
}

private integer(String s) {
  return Integer.parseInt(s)
}

I actually found one of these in the garage I bought a million years ago and forgot about, so I took a shot. It ALMOST worked. Only 1 of the buttons registers anything in Live Logging.

Anything you’d suggest to try to troubleshoot? I don’t mind diving deeper into it, since I know at least I can get 1 button to work