Brightswitch new product like an "open" Wink Relay

I have 2 of these installed, no problem connecting them to smartthings, the user who couldn’t get there’s connected should contact support @brightswitch, but yes they install as on/off plug when first setup.

The fix for dimming is to login to the graph.api.smatthings.com and change the device handle to generic zwave dimmer. Then dim control is available.

I’ve talked with brightswitch support and a new device handler is being created for an upcoming software version. Currently the Brights I have installed are running 1.34, a beta version (current stable version is 1.31) that gives access to the other sensors over wifi. I’m working on a device handler to incorporate them into smartthings as well, but they might come out with one before I finish.

1 Like

Very cool. Thoughts on this vs. the not yet shipping Brilliant https://www.brilliant.tech/?

1 Like

The Brilliant looks cooler, however it is not a real device yet… so it really could be another wink relay (garbage IMO) device. I guess we will see.

side note… I am not smart enough to make a device handler for this… I feel like I have been beating my head against a wall.

1 Like

I have been using this customized DH from smartThings generic Z-wave for my Brights. I added the fingerprint from the Brightswitches to identify the Brights when they are added to smartthings and it also has my own custom code for a 10% dim up and down button on the main on/off tile. If you want just the normal generic dim you can take the fingerprint line and add it to the Smartthings’ generic z-wave dim, or just change the device type from whatever is installed to generic zwave dimmer switch.

/**
 *Modified by spinn360 to add control buttons on manin tile to adjust dim.
 * and to add fingerprint for Brightswitches when they connect to SmartThings
 *Originally authored by SmartThings
 *
 *  Copyright 2015 SmartThings
 *
 *  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: "Z-Wave Dimmer Switch Generic2", namespace: "spinn360", author: "spinn360", ocfDeviceType: "oic.d.light", minHubCoreVersion: '000.019.00012', executeCommandsLocally: true) {
		capability "Switch Level"
		capability "Actuator"
		capability "Health Check"
		capability "Switch"
		capability "Polling"
		capability "Refresh"
		capability "Sensor"
		capability "Light"

        command "levelUp"
        command "levelDown"
        command "randomizeLevel"

		fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer"
		fingerprint mfr:"001D", prod:"1902", deviceJoinName: "Z-Wave Dimmer"
		fingerprint mfr:"001D", prod:"1B03", model:"0334", deviceJoinName: "Leviton Universal Dimmer"
		fingerprint mfr:"011A", prod:"0102", model:"0201", deviceJoinName: "Enerwave In-Wall Dimmer"
		fingerprint mfr:"001D", prod:"1001", model:"0334", deviceJoinName: "Leviton 3-Speed Fan Controller"
		fingerprint mfr:"001D", prod:"0602", model:"0334", deviceJoinName: "Leviton Magnetic Low Voltage Dimmer"
		fingerprint mfr:"001D", prod:"0401", model:"0334", deviceJoinName: "Leviton 600W Incandescent Dimmer"
		fingerprint mfr:"0111", prod:"8200", model:"0200", deviceJoinName: "Remotec Technology Plug-In Dimmer"
		fingerprint mfr:"1104", prod:"001D", model:"0501", deviceJoinName: "Leviton 1000W Incandescant Dimmer"
		fingerprint mfr:"0039", prod:"5044", model:"3033", deviceJoinName: "Honeywell Z-Wave Plug-in Dimmer (Dual Outlet)"
		fingerprint mfr:"0039", prod:"5044", model:"3038", deviceJoinName: "Honeywell Z-Wave Plug-in Dimmer"
		fingerprint mfr:"0039", prod:"4944", model:"3038", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Dimmer"
		fingerprint mfr:"0039", prod:"4944", model:"3130", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Toggle Dimmer"
		fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control"
		fingerprint mfr:"0063", prod:"4944", model:"3131", deviceJoinName: "GE In-Wall Smart Fan Control"
		fingerprint mfr:"0039", prod:"4944", model:"3131", deviceJoinName: "Honeywell Z-Wave Plus In-Wall Fan Speed Control"
                fingerprint mfr:"0196", prod:"00B7", model:"0097", deviceJoinName: "Brightswitch"
	}

	simulator {
		status "on":  "command: 2003, payload: FF"
		status "off": "command: 2003, payload: 00"
		status "09%": "command: 2003, payload: 09"
		status "10%": "command: 2003, payload: 0A"
		status "33%": "command: 2003, payload: 21"
		status "66%": "command: 2003, payload: 42"
		status "99%": "command: 2003, payload: 63"

		// reply messages
		reply "2001FF,delay 5000,2602": "command: 2603, payload: FF"
		reply "200100,delay 5000,2602": "command: 2603, payload: 00"
		reply "200119,delay 5000,2602": "command: 2603, payload: 19"
		reply "200132,delay 5000,2602": "command: 2603, payload: 32"
		reply "20014B,delay 5000,2602": "command: 2603, payload: 4B"
		reply "200163,delay 5000,2602": "command: 2603, payload: 63"
	}

	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:"#00a0dc", 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:"#00a0dc", nextState:"turningOff"
				attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
			}
             tileAttribute("device.level", key: "VALUE_CONTROL") {
				attributeState "VALUE_UP", action: "levelUp"
				attributeState "VALUE_DOWN", action: "levelDown"
              /** attributeState "level", label:'${currentValue}', defaultState: true, backgroundColors:[
				*	[value: 0, color: "#ff0000"],
				*	[value: 20, color: "#ffff00"],
				*	[value: 40, color: "#00ff00"],
				*	[value: 60, color: "#00ffff"],
				*	[value: 80, color: "#0000ff"],
				*	[value: 100, color: "#ff00ff"]
				*]
                */
			}


			tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}
//        controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 2) {
//    	state "level", action:"switch level.setLevel", label:'${currentValue} %', unit:"%", backgroundColor:"#ffffff"
//		}

		standardTile("refresh", "device.switch", width: 6, height: 2, inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}
   //     controlTile("levelSliderControl", "device.level", "slider",
   //         height: 1, width: 2) {
   // state "level", action:"switch level.setLevel"
//}

		main(["switch"])
		details(["switch", "sliderTile", "refresh"])

	}
}

def installed(){
// Device-Watch simply pings if no device events received for 32min(checkInterval)
	sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
	response(refresh())
}

def updated(){
// Device-Watch simply pings if no device events received for 32min(checkInterval)
	sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
}

def getCommandClassVersions() {
	[
		0x20: 1,  // Basic
		0x26: 1,  // SwitchMultilevel
		0x56: 1,  // Crc16Encap
		0x70: 1,  // Configuration
	]
}

def parse(String description) {
	def result = null
	if (description != "updated") {
		log.debug "parse() >> zwave.parse($description)"
		def cmd = zwave.parse(description, commandClassVersions)
		if (cmd) {
			result = zwaveEvent(cmd)
		}
	}
	if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) {
		result = [result, response(zwave.basicV1.basicGet())]
		log.debug "Was hailed: requesting state update"
	} else {
		log.debug "Parse returned ${result?.descriptionText}"
	}
	return result
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
	dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
	dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
	dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd) {
	dimmerEvents(cmd)
}

private dimmerEvents(physicalgraph.zwave.Command cmd) {
	def value = (cmd.value ? "on" : "off")
	def result = [createEvent(name: "switch", value: value)]
	if (cmd.value && cmd.value <= 100) {
		result << createEvent(name: "level", value: cmd.value, unit: "%")
	}
	return result
}


def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	log.debug "ConfigurationReport $cmd"
	def value = "when off"
	if (cmd.configurationValue[0] == 1) {value = "when on"}
	if (cmd.configurationValue[0] == 2) {value = "never"}
	createEvent([name: "indicatorStatus", value: value])
}

def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
	createEvent([name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false])
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
	log.debug "manufacturerId:   ${cmd.manufacturerId}"
	log.debug "manufacturerName: ${cmd.manufacturerName}"
	log.debug "productId:        ${cmd.productId}"
	log.debug "productTypeId:    ${cmd.productTypeId}"
	def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
	updateDataValue("MSR", msr)
	updateDataValue("manufacturer", cmd.manufacturerName)
	createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd) {
	[createEvent(name:"switch", value:"on"), response(zwave.switchMultilevelV1.switchMultilevelGet().format())]
}

def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
	def versions = commandClassVersions
	def version = versions[cmd.commandClass as Integer]
	def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
	def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
	if (encapsulatedCommand) {
		zwaveEvent(encapsulatedCommand)
	}
}

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

def on() {
	delayBetween([
			zwave.basicV1.basicSet(value: 0xFF).format(),
			zwave.switchMultilevelV1.switchMultilevelGet().format()
	],5000)
}

def off() {
	delayBetween([
			zwave.basicV1.basicSet(value: 0x00).format(),
			zwave.switchMultilevelV1.switchMultilevelGet().format()
	],5000)
}

def setLevel(value) {
	log.debug "setLevel >> value: $value"
	def valueaux = value as Integer
	def level = Math.max(Math.min(valueaux, 99), 0)
	if (level > 0) {
		sendEvent(name: "switch", value: "on")
	} else {
		sendEvent(name: "switch", value: "off")
	}
	sendEvent(name: "level", value: level, unit: "%")
	delayBetween ([zwave.basicV1.basicSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value, duration) {
	log.debug "setLevel >> value: $value, duration: $duration"
	def valueaux = value as Integer
	def level = Math.max(Math.min(valueaux, 99), 0)
	def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
	def getStatusDelay = duration < 128 ? (duration*1000)+2000 : (Math.round(duration / 60)*60*1000)+2000
	delayBetween ([zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format(),
				   zwave.switchMultilevelV1.switchMultilevelGet().format()], getStatusDelay)
}

def poll() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

/**
 * PING is used by Device-Watch in attempt to reach the Device
 * */
def ping() {
	refresh()
}

def refresh() {
	log.debug "refresh() is called"
	def commands = []
	commands << zwave.switchMultilevelV1.switchMultilevelGet().format()
	if (getDataValue("MSR") == null) {
		commands << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
	}
	delayBetween(commands,100)
}

def invertSwitch(invert=true) {
	if (invert) {
		zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
	}
	else {
		zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 4, size: 1).format()
	}
}
def levelUp() {
	def level = device.latestValue("level") as Integer ?: 0
	if (level < 101) {
		level = level + 10
	}
	setLevel(level)
}

def levelDown() {
	def level = device.latestValue("level") as Integer ?: 0
	if (level > 0) {
		level = level - 10
	}
	setLevel(level)
}

Talked with the Brightswitch team they have the motion sensor DH and Service manager built to add Brightswtich motion detection on SmartThings… I don’t have the code though. I know I couldn’t figure out smartthings lan device types with smartmanager after reading documentation and re-reading documentation, over and over and over again, so I am glad they were able to figure it out. I swear SmartThings is documented to prevent adding new devices… IMO.

Anyways hope this helps anyone with their Brightswitch.

1 Like

I have both the Brilliant switch and the Bright Switch. Ultimately I’m pretty disappointed in both. The Brilliant looks amazing and feels like it is way better built. The smaller screen size and the multi-gang options look way better than the Bright (in my opinion).

The Bright has been fairly buggy for me. It is Android with a custom app running on top of it. The app sometimes crashes. It only has 1GB of storage I believe. After installing one or two apps the storage is full. Trying to chromecast from it crashes (I tried Google Play Music). It can be extremely slow because of CPU and memory constraints. I’ve had it for a couple months and haven’t gotten any firmware updates.

Brilliant is a much more polished product but my main complaint with it is that it doesn’t integrate into anything really. To clarify, it can control other systems (ring, sonos, etc.) but nothing can control them. For example, I can have the Brilliant switch turn on another SmartThings switch, but SmartThings cannot turn on/off the Brilliant switch. Tough pill to swallow as I’m changing out my fully SmartThings controllable light switches.

I wrote their support asking if they were going to allow this integration and their response wasn’t very promising.

1 Like

Can Brilliant control SmartThings?

After all, this is clearly indicated in very large print on their website. And if it is not available, it takes perhaps 30 minutes for them to update their website to remove the SmartThings logo…

https://www.brilliant.tech/pages/how-it-works


How seamless are its other integrations and features… Alexa, Nest, etc … intercom, Sonos control, …?

Yeah, it can control SmartThings devices. Lights and Locks right now. For some reason only a small number of lights show up to choose from though. Not sure what that is about.

Does the Brilliant work with virtual switches? I’m just trying to find a way for someone to disarm the system. ie: my sister got to my house to pick something up while I was out. system was armed as I was away, she opened the door and set off the alarm, so she called me to have me turn it off and I had no wifi signal where I was at. I just want an easy way for an informed person to hit “I’m Back”. I tried the Aeotec minimote and it would’nt hold a charge. I would prefer something hardwired.

which of the two would you recommend based on my requirements?

1 Like

Tack up a “old” Android phone (perhaps one of those pre-paid ones from Walgreens?) next to an outlet and run ActionTiles. Easy-peasy and a lot cheaper.

ActionTiles can easily be configured with a single huge button to run an “I’m Back” routine; with PIN protection on that button entirely optional.


However, one other thing I would do if I had regular “guests” who need to disarm the home is make sure there is a backup method of turning off any sirens, etc… It’s just not worth the insanity that a SmartThings or internet outage might cause. If I used a Siren, I would either try to figure out if a locally executing Smart Lighting (or ?) can shut it off (not sure that’s possible), or ensure it has a physical override like the ability to unplug it or remove batteries. That’s just me … a siren would drive me crazy. False alarms are inevitable though.

Hi Eric,

How’s the integration with ST working out ? Any other issues ?

Thanks