Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
2 contributors

Users who have contributed to this file

@ph4r @Ledridge
1236 lines (1052 sloc) 45.4 KB
/**
* RGBWW LED Controller
*
* Copyright 2017 Ph4r
*
*/
metadata {
definition (name: "WiFi 370 LED Strip Controller", namespace: "ledridge", author: "Ph4r") {
capability "Switch Level"
capability "Actuator"
capability "Color Control"
capability "Switch"
capability "Refresh"
capability "Sensor"
command "setRed"
command "setGreen"
command "setBlue"
command "setAdjustedColor"
command "softwhite"
command "daylight"
command "warmwhite"
command "red"
command "green"
command "blue"
command "cyan"
command "magenta"
command "orange"
command "purple"
command "black"
command "yellow"
command "white"
command "setWhiteLevel"
command "setSpeed"
command "Fade7"
command "Strobe7"
command "Jump7"
command "FadeRed"
command "StrobeRed"
command "FadeGreen"
command "StrobeGreen"
command "FadeBlue"
command "StrobeBlue"
command "setCoolWhite"
command "setWarmWhite"
command "user1"
command "user2"
command "user3"
command "refresh"
}
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.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.color", key: "SECONDARY_CONTROL") {
attributeState "color", label:'Color${currentValue}'
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"setAdjustedColor"
}
}
/*
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 4, inactiveLabel: false, range:"(0..100)") {
state "level", action:"switch level.setLevel"
}
*/
controlTile("rlSliderControl", "device.rl", "slider", height: 1, width: 4, range:"(0..255)", inactiveLabel: false) {
state "rl", label:'Red', action:"setRed"
}
valueTile("rl", "device.rl", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "rl", label: 'RL\n${currentValue}'
}
controlTile("glSliderControl", "device.gl", "slider", height: 1, width: 4, range:"(0..255)", inactiveLabel: false) {
state "gl", action:"setGreen"
}
valueTile("gl", "device.gl", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "gl", label: 'GL\n${currentValue}'
}
controlTile("blSliderControl", "device.bl", "slider", height: 1, width: 4, range:"(0..255)", inactiveLabel: false) {
state "bl", action:"setBlue"
}
valueTile("bl", "device.bl", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "bl", label: 'BL\n${currentValue}'
}
/*
valueTile("level", "device.level", height: 2, width: 3, inactiveLabel: false, decoration: "flat") {
state "level", label: 'Level\n${currentValue}%'
}
controlTile("saturationSliderControl", "device.saturation", "slider", height: 1, width: 4, inactiveLabel: false) {
state "saturation", action:"color control.setSaturation"
}
valueTile("saturation", "device.saturation", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "saturation", label: 'Sat ${currentValue}%'
}
controlTile("hueSliderControl", "device.hue", "slider", height: 1, width: 4, inactiveLabel: false) {
state "hue", action:"color control.setHue"
}
valueTile("hue", "device.hue", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "hue", label: 'Hue ${currentValue}%'
}
*/
controlTile("rgbSelector", "device.color", "color", height: 4, width: 4, inactiveLabel: false) {
state "color", action:"setAdjustedColor"
}
standardTile("white", "device.white", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offwhite", label:"White", action:"white", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onwhite", label:"White", action:"white", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("red", "device.red", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offred", label:"red", action:"red", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onred", label:"red", action:"red", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FF0000"
}
standardTile("softwhite", "device.softwhite", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offsoftwhite", label:"soft white", action:"softwhite", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onsoftwhite", label:"soft white", action:"softwhite", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFF1E0"
}
/*
standardTile("daylight", "device.daylight", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offdaylight", label:"daylight", action:"daylight", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "ondaylight", label:"daylight", action:"daylight", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFB"
}
*/
standardTile("warmwhite", "device.warmwhite", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offwarmwhite", label:"warm white", action:"warmwhite", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onwarmwhite", label:"warm white", action:"warmwhite", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFF4E5"
}
standardTile("black", "device.black", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offblack", label:"black", action:"black", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onblack", label:"black", action:"black", icon:"st.illuminance.illuminance.bright", backgroundColor:"#000000"
}
/*
standardTile("yellow", "device.yellow", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offyellow", label:"yellow", action:"yellow", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onyellow", label:"yellow", action:"yellow", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFF00"
}
*/
standardTile("magenta", "device.magenta", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offmagenta", label:"magenta", action:"magenta", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onmagenta", label:"magenta", action:"magenta", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FF00FF"
}
standardTile("green", "device.green", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offgreen", label:"green", action:"green", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "ongreen", label:"green", action:"green", icon:"st.illuminance.illuminance.bright", backgroundColor:"#00FF00"
}
standardTile("blue", "device.blue", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offblue", label:"blue", action:"blue", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onblue", label:"blue", action:"blue", icon:"st.illuminance.illuminance.bright", backgroundColor:"#0000FF"
}
standardTile("cyan", "device.cyan", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offcyan", label:"cyan", action:"cyan", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "oncyan", label:"cyan", action:"cyan", icon:"st.illuminance.illuminance.bright", backgroundColor:"#00FFFF"
}
standardTile("orange", "device.orange", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offorange", label:"orange", action:"orange", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onorange", label:"orange", action:"orange", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FF6600"
}
standardTile("purple", "device.purple", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offpurple", label:"purple", action:"purple", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onpurple", label:"purple", action:"purple", icon:"st.illuminance.illuminance.bright", backgroundColor:"#BF00FF"
}
controlTile("speedSliderControl", "device.speed", "slider", height: 1, width: 4, range:"(1..100)", inactiveLabel: false) {
state "speed", label:'Speed', action:"setSpeed"
}
valueTile("speed", "device.speed", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "speed", label: 'Speed\n${currentValue}'
}
standardTile("Fade7", "device.Fade7", height: 1, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offFade7", label:"Fade7", action:"Fade7", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onFade7", label:"Fade7", action:"Fade7", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("Strobe7", "device.Strobe7", height: 1, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offStrobe7", label:"Strobe7", action:"Strobe7", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onStrobe7", label:"Strobe7", action:"Strobe7", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("Jump7", "device.Jump7", height: 1, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offJump7", label:"Jump7", action:"Jump7", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onJump7", label:"Jump7", action:"Jump7", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("FadeRed", "device.FadeRed", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
state "offFadeRed", label:"FadeRed", action:"FadeRed", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onFadeRed", label:"FadeRed", action:"FadeRed", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("StrobeRed", "device.StrobeRed", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
state "offStrobeRed", label:"StrobeRed", action:"StrobeRed", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onStrobeRed", label:"StrobeRed", action:"StrobeRed", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("FadeGreen", "device.FadeGreen", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
state "offFadeGreen", label:"FadeGreen", action:"FadeGreen", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onFadeGreen", label:"FadeGreen", action:"FadeGreen", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("StrobeGreen", "device.StrobeGreen", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
state "offStrobeGreen", label:"StrobeGreen", action:"StrobeGreen", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onStrobeGreen", label:"StrobeGreen", action:"StrobeGreen", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("FadeBlue", "device.FadeBlue", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
state "offFadeBlue", label:"FadeBlue", action:"FadeBlue", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onFadeBlue", label:"FadeBlue", action:"FadeBlue", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("StrobeBlue", "device.StrobeBlue", height: 1, width: 1, inactiveLabel: false, canChangeIcon: false) {
state "offStrobeBlue", label:"StrobeBlue", action:"StrobeBlue", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onStrobeBlue", label:"StrobeBlue", action:"StrobeBlue", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
controlTile("warmWhiteSliderControl", "device.warmWhite", "slider", height: 1, width: 4, range:"(0..255)", inactiveLabel: false) {
state "warmWhite", label:'Warm White', action:"setWarmWhite"
}
valueTile("warmWhite", "device.warmWhite", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "warmWhite", label: 'WW\n${currentValue}'
}
controlTile("coolWhiteSliderControl", "device.coolWhite", "slider", height: 1, width: 4, range:"(0..255)", inactiveLabel: false) {
state "coolWhite", label:'Cool White', action:"setCoolWhite"
}
valueTile("coolWhite", "device.coolWhite", height: 1, width: 2, inactiveLabel: false, decoration: "flat") {
state "coolWhite", label: 'CW\n${currentValue}'
}
standardTile("user1", "device.user1", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offuser1", label:"user1", action:"user1", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onuser1", label:"user1", action:"user1", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("user2", "device.user2", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offuser2", label:"user2", action:"user2", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onuser2", label:"user2", action:"user2", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
standardTile("user3", "device.user3", height: 2, width: 2, inactiveLabel: false, canChangeIcon: false) {
state "offuser3", label:"user3", action:"user3", icon:"st.illuminance.illuminance.dark", backgroundColor:"#D8D8D8"
state "onuser3", label:"user3", action:"user3", icon:"st.illuminance.illuminance.bright", backgroundColor:"#FFFFFF"
}
main(["switch"])
//details(["switch", "rgbSelector"])
}
preferences {
input("ip", "string", title:"Controller IP Address", description: "Controller IP Address", defaultValue: "192.168.1.69", required: false, displayDuringSetup: true)
input("port", "string", title:"Controller Port", description: "Controller Port", defaultValue: 5577 , required: false, displayDuringSetup: true)
//input("username", "string", title:"Controller Username", description: "Controller Username", defaultValue: admin, required: false, displayDuringSetup: true)
//input("password", "password", title:"Controller Password", description: "Controller Password", defaultValue: nimda, required: false, displayDuringSetup: true)
input(name:"CStyle", type:"enum", title: "Controller Style", options: ["RGBWW", "RGBW", "RGB+WW", "RGB", "RGB-LW12"], description: "Enter Controller Style", defaultValue: "RGBWW" , required: false, displayDuringSetup: true)
//input("userPref1", "string", title:"User Button 1 Name", description: "User Button 1 Name" , required: false, displayDuringSetup: false)
//input("userPref1C", "string", title:"User Button 1 Color", description: "User Button 1 Color" , required: false, displayDuringSetup: false)
//input("userPref2", "string", title:"User Button 2 Name", description: "User Button 2 Name" , required: false, displayDuringSetup: false)
//input("userPref2C", "string", title:"User Button 2 Color", description: "User Button 2 Color" , required: false, displayDuringSetup: false)
//input("userPref3", "string", title:"User Button 3 Name", description: "User Button 3 Name" , required: false, displayDuringSetup: false)
//input("userPref3C", "string", title:"User Button 3 Color", description: "User Button 3 Color" , required: false, displayDuringSetup: false)
}
}
// parse events into attributes
def parse(description) {
log.debug "parse() - $description"
def results = []
def map = description
if (description instanceof String) {
log.debug "WiFi 370 LED Strip stringToMap - ${map}"
map = stringToMap(description)
}
if (map?.name && map?.value) {
results << createEvent(name: "${map?.name}", value: "${map?.value}")
}
results
}
// handle commands
def getSaturation() {
def valueNow = device.latestValue("saturation")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "saturation", value: valueNow)
}
valueNow
}
def getHue() {
def valueNow = device.latestValue("hue")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "hue", value: valueNow)
}
valueNow
}
def getColor() {
def valueNow = device.latestValue("color")
if (valueNow == null) {
valueNow = "#FFFFFF"
sendEvent(name: "color", value: valueNow)
}
valueNow
}
def getSpeed() {
def valueNow = device.latestValue("speed")
if (valueNow == null) {
valueNow = 80
sendEvent(name: "speed", value: valueNow)
}
valueNow
}
def getLevel() {
def valueNow = device.latestValue("level")
if (valueNow == null) {
valueNow = 100
sendEvent(name: "level", value: valueNow)
}
valueNow
}
def getSwitch() {
def valueNow = device.latestValue("switch")
if (valueNow == null) {
valueNow = "off"
sendEvent(name: "switch", value: valueNow)
}
valueNow
}
def getRL() {
def valueNow = device.latestValue("rl")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "rl", value: valueNow)
}
valueNow
}
def getGL() {
def valueNow = device.latestValue("gl")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "gl", value: valueNow)
}
valueNow
}
def getBL() {
def valueNow = device.latestValue("bl")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "bl", value: valueNow)
}
valueNow
}
def getWarmWhite() {
def valueNow = device.latestValue("warmWhite")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "warmWhite", value: valueNow)
}
valueNow
}
def getCoolWhite() {
def valueNow = device.latestValue("coolWhite")
if (valueNow == null) {
valueNow = 0
sendEvent(name: "coolWhite", value: valueNow)
}
valueNow
}
def on() {
sendEvent(name: "switch", value: "on")
sendPower(true)
}
def off() {
sendEvent(name: "switch", value: "off")
sendPower(false)
}
def sendPower2(state) {
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
//byte[] body = buildTLSClientHello();
byte[] body = [0x71, 0x24, 0x0F, 0xA4]
if (CStyle == "RGB-LW12")
{
body = [0xCC, 0x23, 0x33]
}
log.debug "${body.length} ${bytesToHex(body)}";
String strBody = new String(body, "ISO-8859-1");
sendHubCommand(new physicalgraph.device.HubAction(strBody, physicalgraph.device.Protocol.LAN, getDataValue("mac")));
}
def sendPower(state) {
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
byte[] bytes = [0x71, 0x24, 0x0F, 0xA4]
if (state) { // 71 23 0f a3 on
bytes = [0x71, 0x23, 0x0F, 0xA3]
} else { //71 24 0f a4 off
bytes = [0x71, 0x24, 0x0F, 0xA4]
}
String body = bytes.encodeHex()
byte[] bytesLW12 = [0xCC, 0x24, 0x33]
if (state) { // 71 23 0f a3 on
bytesLW12 = [0xCC, 0x23, 0x33]
} else { //71 24 0f a4 off
bytesLW12 = [0xCC, 0x24, 0x33]
}
if (CStyle == "RGB-LW12")
{
body = bytesLW12.encodeHex()
}
String sData = new String(bytes, "ISO-8859-1");
byte[] bytes2 = [0xA4]
String sData2 = new String(bytes2, "ISO-8859-1");
String pure = "\u7123\u0FA4"
log.debug "${sData}:${sData2}:${pure}:${body}"
//sendHubCommand(new physicalgraph.device.HubAction(sData, physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
//sendHubCommand(new physicalgraph.device.HubAction(sData2, physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
//sendHubCommand(new physicalgraph.device.HubAction(pure, physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
sendHubCommand(new physicalgraph.device.HubAction(body.toString(), physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
}
def sendRGB() {
if (CStyle == "RGB-LW12")
{
sendRGBLW12()
return
}
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
byte[] byteHeader = [0x31]
byte[] byteFooter = [0x0F]
if (CStyle == "RGB")
{
byteFooter = [0x0F]
}
else if (CStyle == "RGB+WW")
{
byteFooter = [0xF0, 0x0F] // First byte is a filter F0 passes RGB, 0F passes WW/CW
sendWhites()
}
else // (CStyle == "RGBWW") || (CStyle == "RGBW")
{
byteFooter = [0x00, 0x0F] // First byte is a filter 00 passes all at once
}
int RL = getRL().toInteger()
int GL = getGL().toInteger()
int BL = getBL().toInteger()
int warmWhite = getWarmWhite().toInteger()
int coolWhite = getCoolWhite().toInteger()
def level = getLevel()
log.debug "${RL}:${GL}:${BL}::${warmWhite}:${coolWhite}@${level}+${CStyle}"
String bodyHeader = byteHeader.encodeHex()
String bodyFooter = byteFooter.encodeHex()
String bodyMain = bodyHeader + hex(RL) + hex(GL) + hex(BL) + hex(warmWhite * level/100) + hex(coolWhite * level/100) + bodyFooter
def byteMain = bodyMain.decodeHex()
def checksum = 0
byteMain.each {
checksum += it;
}
checksum = checksum & 0xFF
String checksumHex = Integer.toHexString(checksum)
//log.debug "${checksum}:${checksumHex}"
String body = bodyMain + checksumHex
sendHubCommand(new physicalgraph.device.HubAction(body.toString(), physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
}
def sendRGBLW12() {
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
byte[] byteHeader = [0x56]
byte[] byteFooter = [0xAA]
int RL = getRL().toInteger()
int GL = getGL().toInteger()
int BL = getBL().toInteger()
def level = getLevel()
log.debug "${RL}:${GL}:${BL}@${level}+${CStyle}"
String bodyHeader = byteHeader.encodeHex()
String bodyFooter = byteFooter.encodeHex()
String bodyMain = bodyHeader + hex(RL) + hex(GL) + hex(BL) + bodyFooter
sendHubCommand(new physicalgraph.device.HubAction(bodyMain.toString(), physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
}
def sendWhites() { // Need to maintain this, so that whites can be changed while an animation is running
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
byte[] byteHeader = [0x31, 0x00, 0x00, 0x00]
byte[] byteFooter = [0x0F, 0x0F]
int warmWhite = getWarmWhite().toInteger()
int coolWhite = getCoolWhite().toInteger()
def level = getLevel()
log.debug "${warmWhite}:${coolWhite}@${level}"
String bodyHeader = byteHeader.encodeHex()
String bodyFooter = byteFooter.encodeHex()
String bodyMain = bodyHeader + hex(warmWhite * level/100) + hex(coolWhite * level/100) + bodyFooter
def byteMain = bodyMain.decodeHex()
def checksum = 0
byteMain.each {
checksum += it;
}
checksum = checksum & 0xFF
String checksumHex = Integer.toHexString(checksum)
//log.debug "${checksum}:${checksumHex}"
String body = bodyMain + checksumHex
sendHubCommand(new physicalgraph.device.HubAction(body.toString(), physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
}
def refresh() {
sendStatus()
}
def parseStatus(physicalgraph.device.HubResponse hubResponse) {
log.debug "Entered parseStatus()..."
def body = hubResponse.body
def desc = hubResponse.description
def xml = hubResponse.xml
def json = hubResponse.json
def data = hubResponse?.data
def headers = hubResponse.headers
def error = hubResponse.error
log.debug "hubResponse:${hubResponse}"
log.debug "body:${body}"
log.debug "desc:${desc}"
log.debug "xml:${xml}"
log.debug "json:${json}"
log.debug "data:${data}"
log.debug "headers:${headers}"
log.debug "error:${error}"
// No entries actually contain the payload that is returned
}
def sendStatus() { // To request Status of current Bulb
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
byte[] byteHeader = [0x81, 0x8A, 0x8B]
String bodyHeader = byteHeader.encodeHex()
String bodyMain = bodyHeader
def byteMain = bodyMain.decodeHex()
def checksum = 0
byteMain.each {
checksum += it;
}
checksum = checksum & 0xFF
String checksumHex = Integer.toHexString(checksum)
log.debug "Sending Status Request"
String body = bodyMain + checksumHex
byte[] bytesLW12 = [0xEF, 0x01, 0x77]
if (CStyle == "RGB-LW12")
{
body = bytesLW12.encodeHex()
}
sendHubCommand(new physicalgraph.device.HubAction(body.toString(), physicalgraph.device.Protocol.LAN, getDataValue("mac"), [callback: parseStatus]));
}
def setLevel(level) {
log.trace "setLevel($level)"
if (level == 0) { off() }
else if (getSwitch() == "off") { on() }
def colorMap = [hex: getColor(), level: level]
setColor(colorMap)
}
def setCoolWhite(level) {
log.trace "setCoolWhite($level)"
sendEvent(name: "coolWhite", value: level)
sendWhites()
}
def setWarmWhite(level) {
log.trace "setWarmWhite($level)"
sendEvent(name: "warmWhite", value: level)
sendWhites()
}
def setRed(level) {
log.trace "setRed($level)"
def changed = hex(level)
def hex = getColor()
def hexColor = hex.take(1) + changed + hex.substring(3)
def colorMap = [hex: hexColor]
setColor(colorMap)
}
def setGreen(level) {
log.trace "setGreen($level)"
def changed = hex(level)
def hex = getColor()
def hexColor = hex.take(3) + changed + hex.substring(5)
def colorMap = [hex: hexColor]
setColor(colorMap)
}
def setBlue(level) {
log.trace "setBlue($level)"
def changed = hex(level)
def hex = getColor()
def hexColor = hex.take(5) + changed
def colorMap = [hex: hexColor]
setColor(colorMap)
}
def setSaturation(percent) {
log.debug "Executing 'setSaturation'"
sendEvent(name: "saturation", value: percent)
def colorMap = [hue: getHue() as Integer, saturation: getSaturation() as Integer]
setColor(colorMap)
}
def setHue(percent) {
log.debug "Executing 'setHue'"
sendEvent(name: "hue", value: percent)
def colorMap = [hue: getHue() as Integer, saturation: getSaturation() as Integer]
setColor(colorMap)
}
def setColor(value) {
log.debug "setColor: ${value}"
if (value.size() < 8)
toggleTiles("off")
if (( value.size() == 2) && (value.hue != null) && (value.saturation != null)) { //assuming we're being called from outside of device (App)
def rgb = hslToRGB(value.hue, value.saturation, 0.5)
def level = getLevel()
value.hex = rgbToHex(rgb)
value.rh = hex(rgb.r * level/100)
value.gh = hex(rgb.g * level/100)
value.bh = hex(rgb.b * level/100)
}
if ((value.size() == 3) && (value.hue != null) && (value.saturation != null) && (value.level)) { //user passed in a level value too from outside (App)
def rgb = hslToRGB(value.hue, value.saturation, value.level)
def level = getLevel()
value.hex = rgbToHex(rgb)
value.rh = hex(rgb.r * level/100)
value.gh = hex(rgb.g * level/100)
value.bh = hex(rgb.b * level/100)
}
if (( value.size() == 3) && (value.hue != null) && (value.saturation != null) && (value.hex != null)) { //assuming we're being called from outside of device (App)
def rgb = hslToRGB(value.hue, value.saturation, 0.5)
def level = getLevel()
value.hex = rgbToHex(rgb)
value.rh = hex(rgb.r * level/100)
value.gh = hex(rgb.g * level/100)
value.bh = hex(rgb.b * level/100)
}
if (( value.size() == 4) && (value.hue != null) && (value.saturation != null) && (value.level) && (value.hex != null)) { //assuming we're being called from outside of device (App AKA-WebCore)
def rgb = hslToRGB(value.hue, value.saturation, value.level)
def level = getLevel()
value.hex = rgbToHex(rgb)
value.rh = hex(rgb.r * level/100)
value.gh = hex(rgb.g * level/100)
value.bh = hex(rgb.b * level/100)
}
if (( value.size() == 1) && (value.hex)) { //being called from outside of device (App) with only hex
def rgbInt = hexToRgb(value.hex)
def level = getLevel()
value.rh = hex(rgbInt.r * level/100)
value.gh = hex(rgbInt.g * level/100)
value.bh = hex(rgbInt.b * level/100)
}
if (( value.size() == 2) && (value.hex) && (value.level)) { //being called from outside of device (App) with only hex and level
def rgbInt = hexToRgb(value.hex)
sendEvent(name: "level", value: value.level)
value.rh = hex(rgbInt.r * value.level/100)
value.gh = hex(rgbInt.g * value.level/100)
value.bh = hex(rgbInt.b * value.level/100)
}
if (( value.size() == 1) && (value.colorName)) { //being called from outside of device (App) with only color name
def colorData = getColorData(value.colorName)
setColor(colorData)
return
}
if (( value.size() == 2) && (value.colorName) && (value.level)) { //being called from outside of device (App) with only color name and level
def colorData = getColorData(value.colorName)
sendEvent(name: "level", value: value.level)
setColor(colorData)
return
}
if (( value.size() == 3) && (value.red != null) && (value.green != null) && (value.blue != null)) { //being called from outside of device (App) with only color values (0-255)
def level = getLevel()
value.rh = hex(value.red * level/100)
value.gh = hex(value.green * level/100)
value.bh = hex(value.blue * level/100)
value.hex = "#${value.rh}${value.gh}${value.bh}"
}
if (( value.size() == 4) && (value.red != null) && (value.green != null) && (value.blue != null) && (value.level)) { //being called from outside of device (App) with only color values (0-255) and level
sendEvent(name: "level", value: value.level)
value.rh = hex(value.red * value.level/100)
value.gh = hex(value.green * value.level/100)
value.bh = hex(value.blue * value.level/100)
value.hex = "#${hex(value.red)}${hex(value.green)}${hex(value.blue)}"
}
if (!value.rh && !value.gh && !value.bh) {
def level = getLevel()
value.rh = hex(value.red * level/100)
value.gh = hex(value.green * level/100)
value.bh = hex(value.blue * level/100)
}
sendEvent(name: "hue", value: value.hue, displayed: false)
sendEvent(name: "saturation", value: value.saturation, displayed: false)
sendEvent(name: "color", value: value.hex, displayed: false)
if (value.level) {
sendEvent(name: "level", value: value.level)
}
if (value.switch) {
sendEvent(name: "switch", value: value.switch)
}
sendEvent(name: "rl", value: Integer.parseInt(value.rh,16))
sendEvent(name: "gl", value: Integer.parseInt(value.gh,16))
sendEvent(name: "bl", value: Integer.parseInt(value.bh,16))
sendRGB()
}
def setAdjustedColor(value) {
log.debug "setAdjustedColor: ${value}"
toggleTiles("off") //turn off the hard color tiles
def level = getLevel()
value.level = level
def c = hexToRgb(value.hex)
value.rh = hex(c.r * (level/100))
value.gh = hex(c.g * (level/100))
value.bh = hex(c.b * (level/100))
value.hex = "#${value.rh}${value.gh}${value.bh}"
setColor(value)
}
private hubGet(def apiCommand) {
//Setting Network Device Id
def iphex = convertIPtoHex(ip)
def porthex = convertPortToHex(port)
device.deviceNetworkId = "$iphex:$porthex"
log.debug "Device Network Id set to ${iphex}:${porthex}"
log.debug("Executing hubaction on " + getHostAddress())
def uri = ""
if(hdcamera == "true") {
uri = "/cgi-bin/CGIProxy.fcgi?" + getLogin() + apiCommand
}
else {
uri = apiCommand + getLogin()
}
log.debug uri
def hubAction = new physicalgraph.device.HubAction(
method: "GET",
path: uri,
headers: [HOST:getHostAddress()]
)
if(device.currentValue("hubactionMode") == "s3") {
hubAction.options = [outputMsgToS3:true]
sendEvent(name: "hubactionMode", value: "local");
}
hubAction
}
//Parse events into attributes
def parse(String description) {
log.debug "Parsing '${description}'"
}
private getHostAddress() {
return "${ip}:${port}"
}
private String convertIPtoHex(ipAddress) {
String hex = ipAddress.tokenize( '.' ).collect { String.format( '%02x', it.toInteger() ) }.join()
return hex
}
private String convertPortToHex(port) {
String hexport = port.toString().format( '%04x', port.toInteger() )
return hexport
}
// Build random block of 32bit integers
byte[] buildRandomData(size) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
writeInt(out, (int)Math.floor(new Date().getTime() / 1000), 32);
for(def i = 0; i < size - 4; i++)
out.write((int)(Math.random() * 0xFF));
out.flush();
return out.toByteArray();
}
// Write int of varying bit-size (8bit, 16bit, 24bit, 32bit, etc)
public static void writeInt(ByteArrayOutputStream out, int value, int bits) {
for(def i = bits - 8; i >= 0; i-=8) {
out.write((byte) (0xFF & (value >> i)));
}
}
// Return hex-string interpretation of byte array
public static String bytesToHex(byte[] bytes) {
final char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
def colorNameToRgb(color) {
final colors = [
[name:"Soft White", r: 255, g: 241, b: 224 ],
[name:"Daylight", r: 255, g: 255, b: 251 ],
[name:"Warm White", r: 255, g: 244, b: 229 ],
[name:"Red", r: 255, g: 0, b: 0 ],
[name:"Green", r: 0, g: 255, b: 0 ],
[name:"Blue", r: 0, g: 0, b: 255 ],
[name:"Cyan", r: 0, g: 255, b: 255 ],
[name:"Magenta", r: 255, g: 0, b: 33 ],
[name:"Orange", r: 255, g: 102, b: 0 ],
[name:"Purple", r: 170, g: 0, b: 255 ],
[name:"Yellow", r: 255, g: 255, b: 0 ],
[name:"Black", r: 0, g: 0, b: 0 ],
[name:"White", r: 255, g: 255, b: 255 ]
]
def colorData = [:]
colorData = colors.find { it.name == color }
colorData
}
private hex(value, width=2) {
def s = new BigInteger(Math.round(value).toString()).toString(16)
while (s.size() < width) {
s = "0" + s
}
s
}
def hexToRgb(colorHex) {
def rrInt = Integer.parseInt(colorHex.substring(1,3),16)
def ggInt = Integer.parseInt(colorHex.substring(3,5),16)
def bbInt = Integer.parseInt(colorHex.substring(5,7),16)
def colorData = [:]
colorData = [r: rrInt, g: ggInt, b: bbInt]
colorData
}
def rgbToHex(rgb) {
def r = hex(rgb.r)
def g = hex(rgb.g)
def b = hex(rgb.b)
def hexColor = "#${r}${g}${b}"
hexColor
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param h The hue
* @param s The saturation
* @param l The lightness
* @return int array, the RGB representation
*/
def hslToRGB(double h, double s, double l){
double r, g, b;
//log.debug "hsl ${h}, ${s}, ${l}"
if (h>1) { h = h/100f }
if (s>1) { s = s/100f }
if (l>1) { l = l/100f }
//log.debug "hsl-adj ${h}, ${s}, ${l}"
if (s == 0f) {
r = g = b = l; // achromatic
} else {
double q = l < 0.5f ? l * (1 + s) : l + s - l * s;
double p = 2 * l - q;
log.debug "pqh ${p}, ${q}, ${h}"
r = hueToRgb(p, q, h + 1f/3f);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1f/3f);
}
//log.debug "rgb-first ${r}, ${g}, ${b}"
int ri = (r * 255)
int gi = (g * 255)
int bi = (b * 255)
//log.debug "rgb-final ${ri}, ${gi}, ${bi}"
def rgb = [:]
rgb = [r: ri, g: gi, b: bi]
rgb;
}
/** Helper method that converts hue to rgb */
def hueToRgb(double p, double q, double t) {
//log.debug "pqt ${p}, ${q}, ${t}"
if (t < 0f)
t += 1f;
if (t > 1f)
t -= 1f;
if (t < 1f/6f)
return p + (q - p) * 6f * t;
if (t < 1f/2f)
return q;
if (t < 2f/3f)
return p + (q - p) * (2f/3f - t) * 6f;
return p;
}
def rgbToHSL(rgb) {
def r = rgb.r / 255
def g = rgb.g / 255
def b = rgb.b / 255
def h = 0
def s = 0
def l = 0
def var_min = [r,g,b].min()
def var_max = [r,g,b].max()
def del_max = var_max - var_min
l = (var_max + var_min) / 2
if (del_max == 0) {
h = 0
s = 0
} else {
if (l < 0.5) { s = del_max / (var_max + var_min) }
else { s = del_max / (2 - var_max - var_min) }
def del_r = (((var_max - r) / 6) + (del_max / 2)) / del_max
def del_g = (((var_max - g) / 6) + (del_max / 2)) / del_max
def del_b = (((var_max - b) / 6) + (del_max / 2)) / del_max
if (r == var_max) { h = del_b - del_g }
else if (g == var_max) { h = (1 / 3) + del_r - del_b }
else if (b == var_max) { h = (2 / 3) + del_g - del_r }
if (h < 0) { h += 1 }
if (h > 1) { h -= 1 }
}
def hsl = [:]
hsl = [h: h * 100, s: s * 100, l: l]
hsl
}
def getColorData(colorName) {
log.debug "getColorData: ${colorName}"
def colorRGB = colorNameToRgb(colorName)
def colorHex = rgbToHex(colorRGB)
def colorHSL = rgbToHSL(colorRGB)
def level = getLevel()
def colorData = [:]
colorData = [hue: colorHSL.h,
saturation: colorHSL.s,
level: level,
red: colorRGB.r,
green: colorRGB.g,
blue: colorRGB.b,
rh: hex(colorRGB.r * (level/100)),
gh: hex(colorRGB.g * (level/100)),
bh: hex(colorRGB.b * (level/100)),
hex: colorHex,
alpha: 1]
colorData
}
def doColorButton(colorName) {
log.debug "doColorButton: '${colorName}()'"
if (getSwitch() == "off") { on() }
def level = getLevel()
toggleTiles(colorName.toLowerCase().replaceAll("\\s",""))
if (colorName.take(1) == "a") {
doAnimations (colorName.substring(1))
}
else {
def c = getColorData(colorName)
setColor(c)
}
}
def doUserButton(UserNumber) {
log.debug "doUserButton: '${UserNumber}()'"
if (getSwitch() == "off") { on() }
int warmWhite = getWarmWhite().toInteger()
int coolWhite = getCoolWhite().toInteger()
def level = getLevel()
sendEvent(name: "warmWhite", value: warmWhite)
sendEvent(name: "coolWhite", value: coolWhite)
toggleTiles(UserNumber.toLowerCase().replaceAll("\\s",""))
def c = getColorData(UserNumber)
setColor(c)
}
def toggleTiles(color) {
state.colorTiles = []
if ( !state.colorTiles ) {
state.colorTiles = ["softwhite","daylight","warmwhite","red","green","blue","cyan","magenta","orange","purple","yellow","black","white","Fade7","Strobe7","Jump7","FadeRed","StrobeRed","FadeGreen","StrobeGreen","FadeBlue","StrobeBlue","user1","user2","user3"]
}
def cmds = []
state.colorTiles.each({
if ( it == color ) {
log.debug "Turning ${it} on"
device.displayName + " was closed"
cmds << sendEvent(name: it, value: "on${it}", display: True, descriptionText: "${device.displayName} ${color} is 'ON'", isStateChange: true)
} else {
//log.debug "Turning ${it} off"
cmds << sendEvent(name: it, value: "off${it}", displayed: false)
}
})
delayBetween(cmds, 2500)
}
def setSpeed(level) {
log.trace "setSpeed($level)"
sendEvent(name: "speed", value: level)
}
def doAnimations(animation) {
log.trace "doAnimations($animation)"
def hosthex = convertIPtoHex(ip);
def porthex = convertPortToHex(port);
def target = "$hosthex:$porthex";
device.deviceNetworkId = target;
byte[] byteHeader = [0x61]
byte[] byteFooter = [0x0F]
byte[] commandSpeed= [0x10]
def speed = getSpeed().toInteger()
if (speed > 0) {
def var1 = (speed-100)
def var2 = var1 * (-1f/3f)
def var3 = (Math.round(var2)-1)
commandSpeed[0] = var3.abs()
}
else {
commandSpeed[0] = 16
}
String commandSpeedStr = commandSpeed.encodeHex()
// speed guess in decimal: =ABS(ROUND((speed-100)*(-1f/3f),0)-1)
def animationFound = animationSwitch(animation)
String commandStr
if (animationFound?.command) { commandStr = animationFound.command } else { commandStr = '25' }
log.debug "Animate ${animation}:${commandStr}@${speed}%=${commandSpeed[0]}:${commandSpeedStr}"
String bodyHeader = byteHeader.encodeHex()
String bodyFooter = byteFooter.encodeHex()
String bodyMain = bodyHeader + commandStr + commandSpeedStr + bodyFooter
def byteMain = bodyMain.decodeHex()
def checksum = 0
byteMain.each {
checksum += it;
}
checksum = checksum & 0xFF
String checksumHex = Integer.toHexString(checksum)
String body = bodyMain + checksumHex
sendHubCommand(new physicalgraph.device.HubAction(body.toString(), physicalgraph.device.Protocol.LAN, getDataValue("mac"))); //"0A0A0A15:15C9"
}
def animationSwitch(val) {
final animations = [
[name:"Fade7", command: '25'],
[name:"FadeRed", command: '26'],
[name:"FadeGreen", command: '27'],
[name:"FadeBlue", command: '28'],
[name:"FadeYellow", command: '29'],
[name:"FadeCyan", command: '2a'],
[name:"FadePurple", command: '2b'],
[name:"FadeWhite", command: '2c'],
[name:"FadeRedGreen", command: '2d'],
[name:"FadeRedBlue", command: '2e'],
[name:"FadeGreenBlue", command: '2f'],
[name:"Strobe7", command: '30'],
[name:"StrobeRed", command: '31'],
[name:"StrobeGreen", command: '32'],
[name:"StrobeBlue", command: '33'],
[name:"StrobeYellow", command: '34'],
[name:"StrobeCyan", command: '35'],
[name:"StrobePurple", command: '36'],
[name:"StrobeWhite", command: '37'],
[name:"Jump7", command: '38'],
]
def animationData = [:]
animationData = animations.find { it.name == val }
animationData
}
// rows of buttons
def softwhite() { doColorButton("Soft White") }
def daylight() { doColorButton("Daylight") }
def warmwhite() { doColorButton("Warm White") }
def red() { doColorButton("Red") }
def green() { doColorButton("Green") }
def blue() { doColorButton("Blue") }
def cyan() { doColorButton("Cyan") }
def magenta() { doColorButton("Magenta") }
def orange() { doColorButton("Orange") }
def purple() { doColorButton("Purple") }
def yellow() { doColorButton("Yellow") }
def black() { doColorButton("Black") }
def white() { doColorButton("White") }
def Fade7() { doColorButton("aFade7") }
def Strobe7() { doColorButton("aStrobe7") }
def Jump7() { doColorButton("aJump7") }
def FadeRed() { doColorButton("aFadeRed") }
def StrobeRed() { doColorButton("aStrobeRed") }
def FadeGreen() { doColorButton("aFadeGreen") }
def StrobeGreen() { doColorButton("aStrobeGreen") }
def FadeBlue() { doColorButton("aFadeBlue") }
def StrobeBlue() { doColorButton("aStrobeBlue") }
def FadeWhite() { doColorButton("aFadeWhite") }
def StrobeWhite() { doColorButton("aStrobeWhite") }
def user1() { refresh() }
def user2() { doUserButton("White") }
def user3() { doUserButton("White") }
You can’t perform that action at this time.