[RELEASE] OSRAM Lightify Dimmer Switch Device Type - use as Switch, not buttons

This device type is a lot of cut and paste work, so forgive me if it’s a hack job.
The entire parsing section is taken from @Motley’s Device Type. (Many thanks to @Motley for all the work in figuring out how to parse the info!!! See RELEASE: OSRAM Lightify Smart Dimmer Switch (button controller device handler and smart app))
I was looking to use the switch with switch and switch level capabilities, so I basically merged with the Virtual Dimmer Device Type. Using this device type, you can use apps such as Dim with Me or Smart Lighting to pair with light(s) and the device is a functional switch in the SmartThings App.
The top button turns the device on, the bottom turns it off. A press and hold of the top button will raise the level by 20, the bottom will lower by 20. (I have been trying to figure out how to have the hold continue to raise or lower the level, but have been unsuccessful).
Additionally, the battery indicator isn’t working. I don’t think it was working for my on the original device type, but I may have screwed something up. If anyone has any suggestions to fix the battery indicator, it would be greatly appreciated. It’s calculating the level correctly, just not updating the tile.

The device type is in GitHub:

/**
*  OSRAM Lightify Dimming Switch
*
*  Copyright 2016 Smartthings Comminuty
*
*  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.
*
*  Thanks to Michael Hudson for OSRAM Lightify Dimming Switch device.
*  Also borrowed pieces from Virtual Dimmer and GE/Jasco Dimmer
*/

metadata {
	definition (name: "OSRAM Dimmer", namespace: "nsweet68", author: "nick@sweet-stuff.cc") {
		capability "Switch"
		capability "Switch Level"
		capability "Configuration"
		capability "Refresh"
		capability "Battery"

	}

	// simulator metadata
	simulator {
		// status messages
		status "on": "on/off: 1"
		status "off": "on/off: 0"

		// reply messages
		reply "zcl on-off on": "on/off: 1"
		reply "zcl on-off off": "on/off: 0"
	}

	tiles(scale: 2) {
		multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
			tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
				attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
				attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
				attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
				attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
			}
			tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}
		valueTile("level", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "level", label: 'Level ${currentValue}%'
		}
        valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
            state "battery", label:'${currentValue}% battery'
        }
		standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}
		main "switch"
		details(["switch", "level", "battery","levelSliderControl","refresh"])
	}
}

// Parse incoming device messages to generate events
def parse(String description) {

  Map map = [:]
  log.debug "parse description: $description"
  if (description?.startsWith('catchall:')) {
    // call parseCatchAllMessage to parse the catchall message received
    map = parseCatchAllMessage(description)
  } else if (description?.startsWith('read')) {
    // call parseReadMessage to parse the read message received
    map = parseReadMessage(description)
  } else {
    log.debug "Unknown message received: $description"
  }
  //return event unless map is not set
  return map 
}

def configure() {
  log.debug "Confuguring Reporting and Bindings."
  def configCmds = [
    // Bind the outgoing on/off cluster from remote to hub, so the hub receives messages when On/Off buttons pushed
    "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0006 {${device.zigbeeId}} {}",

    // Bind the outgoing level cluster from remote to hub, so the hub receives messages when Dim Up/Down buttons pushed
    "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0008 {${device.zigbeeId}} {}",
    
    // Bind the incoming battery info cluster from remote to hub, so the hub receives battery updates
    "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0001 {${device.zigbeeId}} {}",
  ]
  return configCmds 
}

def refresh() {
  sendEvent(name: 'battery', value: state.battery)
  def refreshCmds = [
    zigbee.readAttribute(0x0001, 0x0020)
  ]
  //when refresh button is pushed, read updated status
  return refreshCmds
}

private Map parseReadMessage(String description) {
  // Create a map from the message description to make parsing more intuitive
  def msg = zigbee.parseDescriptionAsMap(description)
  //def msg = zigbee.parse(description)
  if (msg.clusterInt==1 && msg.attrInt==32) {
    // call getBatteryResult method to parse battery message into event map
    
    def result = getBatteryResult(Integer.parseInt(msg.value, 16))
  } else {
    log.debug "Unknown read message received, parsed message: $msg"
  }
  // return map used to create event
  return result
}

private Map parseCatchAllMessage(String description) {
  // Create a map from the raw zigbee message to make parsing more intuitive
  def msg = zigbee.parse(description)
  log.debug "Parse CatchAll $msg"
  switch(msg.clusterId) {
    case 1:
      // call getBatteryResult method to parse battery message into event map
      log.info 'BATTERY MESSAGE'
      def result = getBatteryResult(Integer.parseInt(msg.value, 16))
      break
    case 6:
      def button = (msg.command == 1 ? 1 : 2)
      if (button == 1) {
      on()
      } 
      else 
      {
      off()
      }
      break

    case 8:
      switch(msg.command) {
        case 1: // brightness decrease command
          state.pressed = 1   
          adjDimmer(-20)
          break
        case 3: 
           state.pressed = 0
           log.info "Received stop command"
        break
        case 5: // brightness increase command
          state.pressed = 1
		  adjDimmer(20)
          break
        }
  }
}

//obtained from other examples, converts battery message into event map
private Map getBatteryResult(rawValue) {
  def linkText = getLinkText(device)
  def result = [
    name: 'battery',
    value: state.battery
  ]
  def volts = rawValue / 10
  def descriptionText
  if (rawValue == 0) {
     state.battery="unknown"
  } else {
    if (volts > 3.5) {
      result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
      state.battery="overvoltage"
    } else if (volts > 0){
      def minVolts = 2.1
      def maxVolts = 3.0
      def pct = (volts - minVolts) / (maxVolts - minVolts)
      result.value = Math.min(100, (int) pct * 100)
      state.battery="${result.value}"
      result.descriptionText = "${linkText} battery was ${result.value}%"
    }
  }
  log.debug "Parse returned ${result?.descriptionText}"
  return result
}

def on() {
	sendEvent(name: "switch", value: "on")
    if (state.dimmer < 1) {
    setLevel(10)
    }
    log.info "Dimmer On"
}

def off() {
	sendEvent(name: "switch", value: "off")
    log.info "Dimmer Off"
}

def setLevel(val){
    log.info "setLevel $val"
    
    // make sure we don't drive switches past allowed values (command will hang device waiting for it to
    // execute. Never commes back)
    
        
    if (val < 0){
    	val = 0
    }
    
    if( val > 100){
    	val = 100
    }
    state.dimmer = val
    
    if (val == 0){ // I liked that 0 = off
    	sendEvent(name:"level",value:val)
    	off()
    }
    else
    {
    	on()
    	sendEvent(name:"level",value:val)
    	sendEvent(name:"switch.setLevel",value:val) // had to add this to work if apps subscribed to
                                                    // setLevel event. "Dim With Me" was one.
    }
}
def adjDimmer(adj){
    def dimVal = state.dimmer + adj
    setLevel(dimVal)

  
}

Hope this is useful!

Fixed battery status from @adamoutler code posted here: RELEASE: OSRAM Lightify Smart Dimmer Switch (button controller device handler and smart app)
You need to refresh to get current battery status.

Thanks!!!

1 Like

Thank you for this device driver. Using this Dimming Switch as a button seems like a waste. I installed your device handler via GitHub and set it up like a dimming switch with my lightify spot lights. The on/off works fine but the long hold for dimming isn’t doing anything. Do you have any suggestions?

Mike

Is the dimmer level displayed in the SmartThings app changing when you press and hold the OSRAM swtich?

This device type is basically a using the OSRAM dimmer switch to control a virtual dimmer, so it’s the SmartApp that you use that is really doing the work.

I’ve been using the Dim With Me SmartApp to control Cree and LG bulbs without any issues. If you are using Dim With Me, make sure you select your bulbs in the “And these will follow with dimming level…” section for the dimming to work.

I’m using trendsetter to synchronize six lights into one device. The Osram Dimmer app turns the lights on or off but they don’t dim from the app or the physical switch. From the trendsetter device I have full control of the lights. If I assign the Osram Dimmer app to an individual light I get the same result, on and off but no dimming. Any advice is welcome.

I haven’t used trendsetter (basically I’m too lazy, when the instructions include multiple device types and apps, my eyes glaze over and I move on) but in theory it should work.
There is a lot going on there, which is why I use Dim With Me.
I guess the simplest way to see if I’ve missed something that trendsetter doesn’t like is to remove the OSRAM switch from any smartapps. Then push the button on the osram switch and see if the level increases in the SmartApp. If this works when it is not on trendsetter, but fails when it is on trendsetter, then I guess I’m going to have to install trendsetter and see what is going on. :disappointed_relieved::

If it doesn’t work when isolated. then I’m not sure what is going on. We’ll need to check the logs or try one of the other device types out there and see if they work and it’s just mine that sucks.

Just to clarify, when you “press and hold”, this device type will only adjust the brightness by 20. Then you need to release and press and hold again.

I did like you said and uninstalled the smart lights app from the dimmer. The button worked after that in your app. When I reinstalled the smart lights app along with a single light or all of them with trendsetter, your app still responds to the button but the lights are unaffected.

Are you using the smart lights app or something like CoRE?

I’m using an app called “Dim with Me”. Below is the post with the app.

I tested with Smart Lights and things worked for me, however, Smart Lights only controls on and off, not dimming.

If I get a chance, I’ll load up trend setter and see if I can duplicate your the issues.
I haven’t messed with CoRE. That falls under my category of too much too read and install… (I told ya, i’m lazy)

Hope this helps!

Not sure if you were able to try out 'Dim with Me".
I just started to look at Trend Setter and I thing I see why it’s not going to work with Trend Setter. From the release post [quote=“Kriskit, post:1, topic:31286”]
the master device is not a physical device
[/quote]
So basically the master device is a virtual dimmer. Since it is it’s own device, to make it mirror any other physical device, you would need a smartApp that controls both the on/off and level. So you would still need an app like Dim with Me to control the trend setter virtual dimmer.
Since “Dim with me” already can control a group of light, that seem a bit redundant (unless I’m missing a key feature in Trend Setter).

IF you really want to use Trend Setter and the OSRAM switch, the either merge the OSRAM device type with Trend Setter dimmer, so they are one device or use the Device Type below, which bind directly to devices. You could bind the Trend Setter dimmer to the OSRAM switch.

1 Like

Any possibility to hold the dimmer button and have a continuous dim?

Also is there a way to “program” what the buttons do?

For example, press top button to full brightness rather than previous level, or may be even programming a double press to do something else?

TIA

I had tried doing a continuous dim when I first created this and was not successful. So I stuck with the multi-press dim.
I’m pretty much hacking my way through this code, and currently don’t have time to play with this so I don’t think I’ll be making any changes on this.
Anyone else who want to improve upon this device handle is more than welcome to go for it.

There is another device handler for this that does dim via press and hold, but it treats the device as buttons and you attached the controlled devices (up to 5) in the device handler. It’s a different approach that may or may not work for your application. (i.e. Buttons don’t work with Amazon Alexia) This device type is here:

Not with this device type, as this is designed specifically to be used as a switch.
I haven’t tried it but the aeon labs minimote device handler may allow you to do that.
Also the link I just posted in my last response uses the device as buttons and I think the author was adding customization for double click.