[Release] Magic Home Wifi Devices - 0.86


#161

Hello Adam,

Sorry to bother you again, I noticed the driver is slowing the hub, I don't know what is the difference between this and the older driver but I don't have this problem with the older driver. I also noticed, I installed the driver to my secondary hub, I just have Xiaomi sensors and Tradfri plugs on it, so maybe there will work better, but then when I was going to link the lights to the primary hub they doesn't show up as RGBW, they appear as RGB, I believe this is something in the driver, could you take a look? Thanks.

image

I use the RGBW controller


#162

Can you send a URL?


#163

I’ll take a look, thanks!


#164

I can confirm the driver is slowing the hub, I deleted the 2 controllers(lights) from my main hub and immediately without a reboot it is fast again, I installed the driver to my second hub and I notice the hub is slower, I'm attaching the driver that works fine, I'm not sure if you lost it, maybe just fixing the buttons to this driver you get better results. By the way, my wife is fine, she see the lights turn on so no problem, just her husband is problematic this time... Thanks a lot.


import hubitat.helper.HexUtils
import hubitat.device.HubAction
import hubitat.helper.InterfaceUtils
import hubitat.device.Protocol

metadata {
	definition (name: "MagicHome Wifi β€” Controller (RGBW)", namespace: "MagicHome", author: "Adam Kempenich") {
        capability "Switch Level"
        capability "Actuator"
        capability "Switch"
        capability "Polling"
        capability "Refresh"
        capability "Sensor"
        capability "Color Temperature"
        capability "Color Control"
	capability "Initialize"
		
	command "on"
        command "off" 

        command "setColorTemperature", [ "number" ] // Kelvin ( Light Minimum Color Temperature - Light Maximum Color Temperature )
        command "setWhiteLevel", [ "number" ] // 0 - 100

        command "sendPreset", ["number", "number"]       // 0 (off), 1-20 (other presets)
        command "presetSevenColorDissolve", [ "number" ] // 0 - 100 (speed)
        command "presetRedFade",            [ "number" ] // 0 - 100 (speed)
        command "presetGreenFade",          [ "number" ] // 0 - 100 (speed)
        command "presetBlueFade",           [ "number" ] // 0 - 100 (speed)
        command "presetYellowFade",         [ "number" ] // 0 - 100 (speed)
        command "presetCyanFade",           [ "number" ] // 0 - 100 (speed)
        command "presetPurpleFade",         [ "number" ] // 0 - 100 (speed)
        command "presetWhiteFade",          [ "number" ] // 0 - 100 (speed)
        command "presetRedGreenDissolve",   [ "number" ] // 0 - 100 (speed)
        command "presetRedBlueDissolve",    [ "number" ] // 0 - 100 (speed)
        command "presetGreenBlueDissolve",  [ "number" ] // 0 - 100 (speed)
        command "presetSevenColorStrobe",   [ "number" ] // 0 - 100 (speed)
        command "presetRedStrobe",          [ "number" ] // 0 - 100 (speed)
        command "presetGreenStrobe",        [ "number" ] // 0 - 100 (speed)
        command "presetBlueStrobe",         [ "number" ] // 0 - 100 (speed)
        command "presetYellowStrobe",       [ "number" ] // 0 - 100 (speed)
        command "presetCyanStrobe",         [ "number" ] // 0 - 100 (speed)
        command "presetPurpleStrobe",       [ "number" ] // 0 - 100 (speed)
        command "presetWhiteStrobe",        [ "number" ] // 0 - 100 (speed)
        command "presetSevenColorJump",     [ "number" ] // 0 - 100 (speed)
        
    	attribute "currentPreset", "string" // 0 (off), 1-20 (other presets)
        attribute "presetSpeed", "string" 
        attribute "whiteLevel", "number"
	}
    
    preferences {  
        input "deviceIP", "text", title: "Server", description: "Device IP (e.g. 192.168.1.X)", required: true, defaultValue: "192.168.1.X"
        input "devicePort", "number", title: "Port", description: "Device Port (Default: 5577)", required: true, defaultValue: 5577

		
	    input(name:"powerOnBrightnessChange", type:"bool", title: "Turn on this light when brightness changes?",
       		  description: "Makes devices behave like other switches. (Default: Off)", defaultValue: false,
              required: true, displayDuringSetup: true)

        input(name:"neutralWhite", type:"number", title: "Point where the light changes between cold and warm white hues",
            description: "Temp in K (Default: 4000)", defaultValue: 4000,
            required: false, displayDuringSetup: true)

		input(name:"cwHue", type:"number", title: "Hue that Cold White (bluish light) uses",
			description: "Hue (0 - 100). Default 55", defaultValue: 55)
		input(name:"cwSaturationLowPoint", type:"number", title: "Cold White Saturation closest 4000k (or the neutral white point).",
			description: "Saturation: (0-100) Default: 0", defaultValue: 0)
		input(name:"cwSaturationHighPoint", type:"number", title: "Cold White Saturation at ~6000k.",
			description: "Saturation: (0-100) Default: 50", defaultValue: 50)

		input(name:"wwHue", type:"number", title: "Hue that Warm White (orangeish light) uses",
			description: "Hue (0 - 100). Default 100 (Bulb's White LEDs)", defaultValue: 100)
		input(name:"wwSaturationLowPoint", type:"number", title: "Cold White Saturation closest 4000k (or the neutral white point).",
			description: "Saturation: (0-100) Default: 0", defaultValue: 0)
		input(name:"wwSaturationHighPoint", type:"number", title: "Cold White Saturation at ~2700k.",
			description: "Saturation: (0-100) Default: 50", defaultValue: 50)

        // Add a setting to use the white channel in lieue of warm white/cold white
        input(name:"deviceWhiteTemperature", type:"number", title: "White channel's color temperature .",
            description: "Temp in K (default 3000)", defaultValue: 3000,
            required: false, displayDuringSetup: true)

        input(name:"whiteFollowsBrightness", type:"bool", title: "White channel follows device brightness for color temperature?",
            description: "Default: On", defaultValue: true,
            required: false, displayDuringSetup: true)
	}
}

def on() {
    // Turn on the device

    sendEvent(name: "switch", value: "on")
   // log.debug "MagicHome - Switch set to " + device.currentValue("switch")
    byte[] data = [0x71, 0x23,  0x0F, 0xA3]
    sendCommand(data)
}

def off() {
    // Turn off the device

	sendEvent(name: "switch", value: "off")
   // log.debug "MagicHome - Switch set to " + device.currentValue("switch")
    byte[] data = [0x71, 0x24,  0x0F, 0xA4]
    sendCommand(data)
}

def setHue(hue, transmit=true){
    // Set the hue of a device (0-100)

   	hue = normalizePercent(hue) 
	sendEvent(name: "hue", value: hue)
   // log.debug "MagicHome - Hue set to " + device.currentValue("hue")
    if( transmit ) {
    	setColor([hue:hue])
    }
    else {
    	return device.currentValue( "hue" )
    }
}

def setSaturation(saturation, transmit=true){
    // Set the saturation of a device (0-100)

    saturation = normalizePercent(saturation)
	sendEvent(name: "saturation", value: saturation)    
//	log.debug "MagicHome - Saturation set to " + device.currentValue("saturation")
    if( transmit ) {
    	setColor([saturation:saturation])
    }
    else{
    	return device.currentValue( "saturation" )
    }
}

def setLevel(level, transmit=true) {
    // Set the brightness of a device (0-100)

    level = normalizePercent(level)
    sendEvent(name: "level", value: level)
//    log.debug "MagicHome - Level set to " + device.currentValue( "level" )

    if( transmit ) {
        setColor([level:level])
    }
    else{
    	return device.currentValue( "level" )   
    }
}

def setWhiteLevel(whiteLevel, transmit=true){
    // Set the dedicated white channel's brightness of a device (0-100)

   	whiteLevel = normalizePercent(whiteLevel) 
	sendEvent(name: "whiteLevel", value: whiteLevel)
//    log.debug "MagicHome - white level set to " + device.currentValue("whiteLevel")
    if( transmit ) {
    	setColor( [ whitelevel : whiteLevel ] )
    }
    else {
    	return device.currentValue( "whiteLevel" )
    }
}

def setAdjustedColor( parameters ){
	// This is an old function from the SmartThings days. Pass its values to setColor

	setColor( parameters )
}

def setColor(parameters){
	// Set the color of a device. Hue (0 - 100), Saturation (0 - 100), Level (0 - 100). If Hue is 16.6, use the white LEDs.

	byte[] msg
	byte[] data

	if(parameters.hue == null){
		if( device.currentValue( "hue" ) == null ){
			sendEvent( name: "hue", value: 100 )
			parameters.hue = 100
		}
		else{
			parameters.hue = device.currentValue( "hue" )
		}
	}
	else{
		sendEvent( name: "hue", value: normalizePercent(parameters.hue))
	}
	if(parameters.saturation == null){
		if( device.currentValue( "saturation" ) == null ){
			sendEvent( name: "saturation", value: 100 )
			parameters.saturation = 100
		}
		else{
			parameters.saturation = device.currentValue( "saturation" )
		}
	}
	else{
		sendEvent( name: "saturation", value: normalizePercent(parameters.saturation))
	}
	if(parameters.level == null){
        if( device.currentValue( "level" ) == null ){
            sendEvent( name: "level", value: 100 )
            parameters.level = 100
        }
        else{
            parameters.level = device.currentValue( "level" )
        }
    }
    else{
        sendEvent( name: "level", value: normalizePercent(parameters.level))
    }
    if(parameters.whiteLevel == null){
        if( device.currentValue( "whiteLevel" ) == null ){
            sendEvent( name: "whiteLevel", value: 100 )
            parameters.whiteLevel = 100
        }
        else{
            parameters.whiteLevel = device.currentValue( "whiteLevel" )
        }
    }
    else{
        sendEvent( name: "level", value: normalizePercent(parameters.level))
    }


	if(settings.powerOnBrightnessChange){
    	device.currentValue("status") == "on" ? on() : ( null )
    }
    // Register that presets are disabled
    sendEvent( name: "currentPreset", value: 0 )


	rgbColors = hsvToRGB( parameters.hue, parameters.saturation, parameters.level )

	msg =  [ 0x31, rgbColors.red, rgbColors.green, rgbColors.blue, parameters.whiteLevel * 2.55, 0xf0, 0x0f ]
	data = [ 0x31, rgbColors.red, rgbColors.green, rgbColors.blue, parameters.whiteLevel * 2.55, 0xf0, 0x0f, calculateChecksum( msg ) ]

    sendCommand( data )
}

def setColorTemperature(setTemp, transmit=true){
    // Using RGB and the WW/CW channels, adjust the color temperature of a device

    // If a level isn't set, create it
    device.currentValue( "level" ) == null ? ( deviceLevel = setLevel( 100, false )): ( deviceLevel = device.currentValue( "level" ))
    device.currentValue( "whiteLevel" ) == null ? ( deviceWhiteLevel = setWhiteLevel( 100, false )): ( deviceWhiteLevel = device.currentValue( "whiteLevel" ))
	// If the percentage is above zero, but less than one (for some reason), set it to one
    roundUpIfBetweenTwoNumbers( deviceLevel )

    // If no color temperature was passed through, use the current device's color temperature, and check if it's in bounds
    if(setTemp == null){
        if(device.currentValue( "colorTemperature") != null){
            setTemp = device.currentValue( "colorTemperature" )
        }
        else{
            sendEvent( name: "colorTemperature", value: 2700 )
            setTemp = device.currentValue( "colorTemperature" )
        }
    }
    else{
		sendEvent( name: "colorTemperature", value: setTemp )
	}
    // Set the colorTemperature's value between the device's maximum range, if it's out of bounds
    setTemp = normalizePercent( setTemp, settings.deviceWWTemperature, settings.deviceCWTemperature )
    log.info 'MagicHome - Color Temperature set to ' + setTemp
	 


    // β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” Start RGB CT Handling β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” //
    // Initialize base variables
	def ( float newSaturation, float newHue ) = [ 0, 0 ]
   	def ( double setCoolWhiteHue, double setWarmWhiteHue, int neutralWhite ) = [normalizePercent( settings.cwHue ), normalizePercent( settings.wwHue ), normalizePercent( settings.neutralWhite, 2000, 8000 )]
   	def ( int cwSaturationLowPoint, int cwSaturationHighPoint, int wwSaturationLowPoint, int wwSaturationHighPoint ) = [ normalizePercent( settings.cwSaturationLowPoint ), normalizePercent( settings.cwSaturationHighPoint ), normalizePercent( settings.wwSaturationLowPoint ), normalizePercent( settings.wwSaturationHighPoint ) ]

    if(setTemp >= neutralWhite){
    	// Set cold white temperature if above the user's neutral white point

    	int offset = setTemp - neutralWhite
        	if( cwSaturationLowPoint < cwSaturationHighPoint ){
    			newSaturation = (((( 100 - cwSaturationLowPoint)/100 ) * ( 1.8 * Math.sqrt( offset ))) + cwSaturationLowPoint ) * cwSaturationHighPoint / 100
        	}
            else{
    			newSaturation = (((( 100 - cwSaturationHighPoint)/100 ) * ( 1.8 * Math.sqrt( offset ))) + cwSaturationHighPoint ) * cwSaturationLowPoint / 100
            }
        newHue =  setCoolWhiteHue
    }
    else{
    	// set warm white temperature if below the user's neutral white point

    	int offset = neutralWhite - setTemp
        	if(wwSaturationLowPoint < wwSaturationHighPoint ){
    			newSaturation = (((( 100 - wwSaturationLowPoint ) / 100) * ( 2.166666 * Math.sqrt( offset ))) + wwSaturationLowPoint ) * wwSaturationHighPoint / 100
            }
            else{
    			newSaturation = (((( 100 - wwSaturationHighPoint ) / 100) * ( 2.166666 * Math.sqrt( offset ))) + wwSaturationHighPoint ) * wwSaturationLowPoint / 100
            }
        newHue =  setWarmWhiteHue
    }

    // β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” Start White Channel CT Handling β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” //

    if(normalizePercent(settings.deviceWhiteTemperature, 2000, 7000) < 4000){
        brightnessWhite = (( 100 )/( settings.deviceWhiteTemperature - 6000 )) * setTemp + ( 100 - ( 100 /( settings.deviceWhiteTemperature - 6000 )) * settings.deviceWhiteTemperature )
    }
    else{
        brightnessWhite = (( 100) /( settings.deviceWhiteTemperature - 2700 )) * setTemp + ( 100 - ( 100 /( settings.deviceWhiteTemperature - 2700 )) * settings.deviceWhiteTemperature )
    }


    // Adjust the brightness by using device level as modifier
    if(settings.whiteFollowsBrightness){
        brightnessWhite = roundUpBetweenZeroAndOne( normalizePercent( brightnessWhite * deviceLevel / 100 ) )
    }
    else{
        normalizePercent( brightnessWhite )
    }
    // β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” End White Channel CT Handling β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” //

    // If powerOnBrightnessChange is enabled, ensure the device is on
    settings.powerOnBrightnessChange ? ( device.currentValue("status") == "on" ? on() : null ) : null
    
    // Update WW/CW
	def parameters = [hue: newHue, saturation: newSaturation, whitelevel: brightnessWhite]
	setColor( parameters )
}


// ------------------- Begin Preset Handling ------------------------- //
def sendPreset( turnOn, preset = 1, speed = 100, transmit = true ){
    // Turn on preset mode (true), turn off preset mode (false). Preset (1 - 20), Speed (1 (slow) - 100 (fast)).

    // Presets:
    // 1 Seven Color Dissolve, 2 Red Fade, 3 Green Fade, 4 Blue Fade, 5 Yellow Fade, 6 Cyan Fade, 7 Purple Fade, 8 White Fade, 9 Red Green Dissolve
    // 10 Red Blue Dissolve, 11 Green Blue Dissolve, 12 Seven Color Strobe, 13 Red Strobe, 14 Green Strobe, 15 Blue Strobe, 16 Yellow Strobe
    // 17 Cyan Strobe, 18 Purple Strobe, 19 White Strobe, 20 Seven Color Jump

    byte[] msg
    byte[] data

    if(turnOn){
        normalizePercent( preset, 1, 20 )
        normalizePercent( speed )
        
        // Hex range of presets is (int) 37 - (int) 57. Add the preset number to get that range.
        preset += 36
        speed = (100 - speed)

        msg =  [ 0x61, preset, speed, 0x0F ]
        data = [ 0x61, preset, speed, 0x0F, calculateChecksum(msg) ]
        if(settings.powerOnBrightnessChange){
            device.currentValue("status") == "on" ? on() : (null)
        }

        sendEvent( name: "currentPreset", value: preset )
        sendEvent( name: "presetSpeed", value: speed )

        sendCommand( data )
    }
    else{
        // Return the color back to its normal state

        sendEvent( name: "currentPreset", value: 0 )
        setColor( null )
    }
}

def presetSevenColorDissolve( speed = 100 ){
    sendPreset( true, 1, speed )
}
def presetRedFade( speed = 100 ){
    sendPreset( true, 2, speed )
}
def presetGreenFade( speed = 100 ){
    sendPreset( true, 3, speed )
}
def presetBlueFade( speed = 100 ){
    sendPreset( true, 4, speed )
}
def presetYellowFade( speed = 100 ){
    sendPreset( true, 5, speed )
}
def presetCyanFade( speed = 100 ){
    sendPreset( true, 6, speed )
}
def presetPurpleFade( speed = 100 ){
    sendPreset( true, 7, speed )
}
def presetWhiteFade( speed = 100 ){
    sendPreset( true, 8, speed )
}
def presetRedGreenDissolve( speed = 100 ){
    sendPreset( true, 9, speed )
}
def presetRedBlueDissolve( speed = 100 ){
    sendPreset( true, 10, speed )
}
def presetGreenBlueDissolve( speed = 100 ){
    sendPreset( true, 11, speed )
}
def presetSevenColorStrobe( speed = 100 ){
    sendPreset( true, 12, speed )
}
def presetRedStrobe( speed = 100 ){
    sendPreset( true, 19, speed )
}
def presetGreenStrobe( speed = 100 ){
    sendPreset( true, 14, speed )
}
def presetBlueStrobe( speed = 100 ){
    sendPreset( true, 15, speed )
}
def presetYellowStrobe( speed = 100 ){
    sendPreset( true, 16, speed )
}
def presetCyanStrobe( speed = 100 ){
    sendPreset( true, 17, speed )
}
def presetPurpleStrobe( speed = 100 ){
    sendPreset( true, 18, speed )
}
def presetWhiteStrobe( speed = 75 ){
    sendPreset( true, 19, speed )
}
def presetSevenColorJump( speed = 100 ){
    sendPreset( true, 20, speed )
}

// ------------------- End Preset Handling ------------------------- //


// ------------------- Begin Helper Functions ------------------------- //
def normalizePercent(value, lowerBound=0, upperBound=100){
    // Takes a value and ensures it's between two defined thresholds

    // If the value doesn't exist, create it
    value == null ? value = upperBound : null

    if(lowerBound < upperBound){
        if(value < lowerBound ){ value = lowerBound}
        if(value > upperBound){ value = upperBound}
    }
    else if(upperBound < lowerBound){
        if(value < upperBound){ value = upperBound}
        if(value > lowerBound ){ value = lowerBound}
    }

    return value
}

def roundUpIfBetweenTwoNumbers(number, lowPoint = 0, highPoint = 1){
    if(number > lowPoint && number < highPoint){
        return highPoint
    }
    else{
        return number
    }
}

def hsvToRGB(float conversionHue = 0, float conversionSaturation = 100, float conversionValue = 100, resolution = "low"){
    // Accepts conversionHue (0-100 or 0-360), conversionSaturation (0-100), and converstionValue (0-100), resolution ("low", "high")
    // If resolution is low, conversionHue accepts 0-100. If resolution is high, conversionHue accepts 0-360
    // Returns RGB map ([ red: 0-255, green: 0-255, blue: 0-255 ])
    
    // Check HSV limits
    resolution == "low" ? ( hueMax = 100 ) : ( hueMax = 360 ) 
    conversionHue > hueMax ? ( conversionHue = 1 ) : ( conversionHue < 0 ? ( conversionHue = 0 ) : ( conversionHue /= hueMax ) )
    conversionSaturation > 100 ? ( conversionSaturation = 1 ) : ( conversionSaturation < 0 ? ( conversionSaturation = 0 ) : ( conversionSaturation /= 100 ) )
    conversionValue > 100 ? ( conversionValue = 1 ) : ( conversionValue < 0 ? ( conversionValue = 0 ) : ( conversionValue /= 100 ) ) 
        
    int h = (int)(conversionHue * 6);
    float f = conversionHue * 6 - h;
    float p = conversionValue * (1 - conversionSaturation);
    float q = conversionValue * (1 - f * conversionSaturation);
    float t = conversionValue * (1 - (1 - f) * conversionSaturation);
    
    conversionValue *= 255
    f *= 255
    p *= 255
    q *= 255
    t *= 255
            
    if      (h==0) { rgbMap = [red: conversionValue, green: t, blue: p] }
    else if (h==1) { rgbMap = [red: q, green: conversionValue, blue: p] }
    else if (h==2) { rgbMap = [red: p, green: conversionValue, blue: t] }
    else if (h==3) { rgbMap = [red: p, green: q, blue: conversionValue] }
    else if (h==4) { rgbMap = [red: t, green: p, blue: conversionValue] }
    else if (h==5) { rgbMap = [red: conversionValue, green: p,blue: q]  }
    else           { rgbMap = [red: 0, green: 0, blue: 0] }

    return rgbMap
}

def rgbToHSV( r = 255, g = 255, b = 255, resolution = "low" ) {
	// Takes RGB (0-255) and returns HSV in 0-360, 0-100, 0-100
	// resolution ("low", "high") will return a hue between 0-100, or 0-360, respectively.
  
	r /= 255
	g /= 255
	b /= 255

	float h
	float s
	
	float max =   Math.max( Math.max( r, g ), b )
	float min = Math.min( Math.min( r, g ), b )
	float delta = ( max - min )
	float v = ( max * 100.0 )

	max != 0.0 ? ( s = delta / max * 100.0 ) : ( s = 0 )

	if (s == 0.0) {
		h = 0.0
	}
	else{
		if (r == max){
        		h = ((g - b) / delta)
		}
		else if(g == max) {
        		h = (2 + (b - r) / delta)
		}
		else if (b == max) {
        		h = (4 + (r - g) / delta)
		}
	}

	h *= 60.0
    	h < 0 ? ( h += 360 ) : null
  
  	resolution == "low" ? h /= 3.6 : null
  	return [ hue: h, saturation: s, value: v ]
}

def calculateChecksum(bytes){
    // Totals an array of bytes
    int sum = 0;
    for(int d : bytes)
	    sum += d;
    return sum & 255
}

def parse( response ) {
	// Parse data received back from this device

	def responseArray = HexUtils.hexStringToIntArray(response)
	if( responseArray.length == 4 ) {
		// Does the device say it's on?
		
		responseArray[ 2 ] == 35 ? sendEvent(name: "switch", value: "on") : sendEvent(name: "switch", value: "off")
	}
	else if( responseArray.length == 14 ) {
		// Full set received. Check received colors
		
		responseArray[ 2 ] == 35 ? ( sendEvent(name: "switch", value: "on") ) : ( sendEvent(name: "switch", value: "off") )
		
		// Convert integers to percentages
		double white = responseArray[ 9 ] / 2.55
		hsvMap = rgbToHSV( responseArray[ 6 ], responseArray[ 7 ], responseArray[ 8 ] )
		
		//log.info "HSV conversion: Map:${hsvMap} HSV ${hsvMap.hue}, ${hsvMap.saturation}, ${hsvMap.value}"

		
		// If values differ from HE, change them
		device.currentValue( "whiteLevel" ).toDouble() 	    != white.toDouble() 		            ? ( setWhiteLevel( white, false ) ) : null
		device.currentValue( "level" ).toDouble() 			!= ( hsvMap.value ).toDouble() 		    ? setLevel( hsvMap.value, false ) : null
		device.currentValue( "saturation" ).toDouble() 		!= ( hsvMap.saturation ).toDouble() 	? setSaturation( hsvMap.saturation, false ) : null
		device.currentValue( "hue" ).toDouble() 			!= ( hsvMap.hue ).toDouble() 			? setHue( hsvMap.hue, false ) : null
		
		// Calculate the color temperature, based on what data was received
		if(settings.highBrightnessMode){
			// Calculate CT if HSL is in line with the settings
		}
		else{
			// Calculate CT based on WW/CW channels
		}
	}
	else if( response == null ){
//		log.debug "${settings.deviceIP}: No response received from device"
		initialize()
	}
	else{
//		log.debug "${settings.deviceIP}: Received a response with an unexpected length of " + responseArray.length
	}
}

def sendCommand(data) {
    // Sends commands to the device
    
    telnetConnect([byteInterface: true], "${settings.deviceIP}", settings.devicePort.toInteger(), null, null)
    
    String stringBytes = HexUtils.byteArrayToHexString(data)
    // log.debug "" +  data + " was converted. Transmitting: " + stringBytes

    def transmission = new HubAction(stringBytes, Protocol.TELNET)
    sendHubCommand(transmission)
}

def refresh( parameters ) {
    byte[] msg =  [ 0x81, 0x8A, 0x8B ]
    byte[] data = [ 0x81, 0x8A, 0x8B, calculateChecksum( msg )]

    sendCommand( data )
}

def telnetStatus(status) { log.debug "telnetStatus:${status}" }
def socketStatus(status) { 
//	log.debug "socketStatus:${status}"
	if(status == "send error: Broken pipe (Write failed)") {
		// Cannot reach device
//		log.debug "Cannot reach ${settings.deviceIP}, attempting to reconnect in 10s..."
		runIn( 10, initialize )
	}
	
}

def poll() {
    parent.poll(this)
}


def updated(){
	//initialize()
}
def initialize() {
	//InterfaceUtils.socketConnect(device, settings.deviceIP, settings.devicePort.toInteger(), byteInterface: true)
	//unschedule()
	//runIn(20, keepAlive)
}

def keepAlive(){
	// Poll the device every 250 seconds, or it will lose connection.
	
	//refresh()
	//runIn(150, keepAlive)
}

#165

Hi! I got this bulb working: MagicLight WiFi Smart Light Bulb, Dimmable, Multicolor, Wake-Up Lights, No Hub Required, Magic Light Compatible with Alexa and Google Assistant https://www.amazon.com/dp/B07DNQGV1B/ref=cm_sw_r_cp_apa_i_HIFCCb89YPB44

About as well as it works with their own app..

These show up on my router as ESP_(end of MAC which appears when you configure these lights in the magichome app), so finding the IP was easy enough.

How would I know if my hub is slowing down other than casually observing things aren't responsive?


#166

@adamkempenich I don't have a smoking gun pointing at this driver by any means but I had the first hub lock up in a long time after I updated my drivers.

I just got back from travel so I'll check out the logs. I'll PM you with any useful info I can find.


#167

I had to revert to the older driver I posted above, I moved the controllers to the hub for Xiaomi, this hub has nothing on it, just about 12 devices and no other apps than hub to link, I was testing drivers for one xiaomi device and the hub was very slow, it was taking more than 10 secs to open a page, I reverted to the older driver on both controllers and problem solved. Not sure how you are doing the test but I hope you are using more than one controller at the same time. Thanks again.


#168

Interesting, I’m not sure what would be causing it, at this time. Let me take a look once I get back into town. I’m very sorry this is affecting your hubsβ€”and I’ll do what I can to get it fixed!


#169

So I thought I had updated to 8.1.
They were both 8.0.

My unreported lack of color control is fixed.
I'll report if the slowdown is fixed.


#170

Thank you, Keith! 0.81 added supplemental try/catching for errors, and I’m hoping solved the slowdown.

Let me know your experiences.:slight_smile:


#171

Just to clarifyβ€”you were using 0.81, correct?


#172

Yes.


#173

With much thanks to @vjv's alert that this driver has been slowing down hubs, I've released a new update to 0.82.

The additional slowdown is related to the parse() method, I'm pretty certain. I've been running a stress test with the new drivers where parse() is disabled and a refresh is performed across 15 devices every 10 seconds, and it seems to be working much better.

As a result, this new version is stable and fast, but will not reflect changes made outside of Hubitat.

I've also added another device type. Dimmable-only controllers are now supported. I had no idea these even existed until someone pointed them out to me.

Now that I know the (hopefully) final source of the problem, I'll be able to move forward for a fix.

As always, your patience and support is appreciated!


#174

Testing 0.82, thank you, fingers crossed.


#175

Will refresh pull status from the devices?
If I'm understanding it doesn't auto update of changed externally.


#176

In 0.81, yes.

0.82 will notβ€”but it will still send a command to say hello to the bulb.


#177

Adam, I think you will hate me... unfortunately I have to say that the new 0.82 driver is working fine and apparently you nailed with this one, so far so good. Thanks so much. ( when I said unfortunately is because now I don't have anything to play with :joy: )


#178

This is great to hear!

Just wait until 0.83 when I break everything for you again---then, you will have another project :laughing:

Additionally --- I think I have a solution for the slowdown caused by parse() ... give me a few days to write it and test it :slight_smile:


#179

Here's something funny.

I've been running some heavier tests on 0.83. It's pretty much completed. No slowdown, parse() works again.

I was testing it at the office today---where I have a rule that turns on our overhead lights if they're digitally turned off. I kept turning the light off to test the new driver, but it kept turning itself back on.

At first, I thought I'd introduced some bizarre new bug, but it wasn't doing this on all of our lights.

So much for turning the light back on or off after toggling power just being a joke :laughing:

Expect a working launch tomorrow.


#180

So if you turn them off through an app it was supposed to turn them back on?
Is this some cruel torture for your SO?
:joy: