LUA Fibaro RGBW,

Moderator: Telldus

Post Reply
geirbakkw
Posts: 15
Joined: Fri Mar 17, 2023 9:45 am

LUA Fibaro RGBW,

Post by geirbakkw »

Hi, are there anyone how has looked into the possibility to make a lua script for controlling a RBGW unit?

I´m trying to find what Z-wave device command to send for changing RGB colours.

I found a reference for colours, but without the device command it not easy to change any colours :)

Not tested:

local COMMAND_CLASS_COLOR_CONTROL = 0x33


colorsRGB = {
aliceblue = {240, 248, 255},
antiquewhite = {250, 235, 215},
aqua = { 0, 255, 255},
aquamarine = {127, 255, 212},
azure = {240, 255, 255},
beige = {245, 245, 220},
bisque = {255, 228, 196},
black = { 0, 0, 0},
blanchedalmond = {255, 235, 205},
blue = { 0, 0, 255},
blueviolet = {138, 43, 226},
brown = {165, 42, 42},
burlywood = {222, 184, 135},
cadetblue = { 95, 158, 160},
chartreuse = {127, 255, 0},
chocolate = {210, 105, 30},
coral = {255, 127, 80},
cornflowerblue = {100, 149, 237},
cornsilk = {255, 248, 220},
crimson = {220, 20, 60},
cyan = { 0, 255, 255},
darkblue = { 0, 0, 139},
darkcyan = { 0, 139, 139},
darkgoldenrod = {184, 134, 11},
darkgray = {169, 169, 169},
darkgreen = { 0, 100, 0},
darkgrey = {169, 169, 169},
darkkhaki = {189, 183, 107},
darkmagenta = {139, 0, 139},
darkolivegreen = { 85, 107, 47},
darkorange = {255, 140, 0},
darkorchid = {153, 50, 204},
darkred = {139, 0, 0},
darksalmon = {233, 150, 122},
darkseagreen = {143, 188, 143},
darkslateblue = { 72, 61, 139},
darkslategray = { 47, 79, 79},
darkslategrey = { 47, 79, 79},
darkturquoise = { 0, 206, 209},
darkviolet = {148, 0, 211},
deeppink = {255, 20, 147},
deepskyblue = { 0, 191, 255},
dimgray = {105, 105, 105},
dimgrey = {105, 105, 105},
dodgerblue = { 30, 144, 255},
firebrick = {178, 34, 34},
floralwhite = {255, 250, 240},
forestgreen = { 34, 139, 34},
fuchsia = {255, 0, 255},
gainsboro = {220, 220, 220},
ghostwhite = {248, 248, 255},
gold = {255, 215, 0},
goldenrod = {218, 165, 32},
gray = {128, 128, 128},
grey = {128, 128, 128},
green = { 0, 128, 0},
greenyellow = {173, 255, 47},
honeydew = {240, 255, 240},
hotpink = {255, 105, 180},
indianred = {205, 92, 92},
indigo = { 75, 0, 130},
ivory = {255, 255, 240},
khaki = {240, 230, 140},
lavender = {230, 230, 250},
lavenderblush = {255, 240, 245},
lawngreen = {124, 252, 0},
lemonchiffon = {255, 250, 205},
lightblue = {173, 216, 230},
lightcoral = {240, 128, 128},
lightcyan = {224, 255, 255},
lightgoldenrodyellow = {250, 250, 210},
lightgray = {211, 211, 211},
lightgreen = {144, 238, 144},
lightgrey = {211, 211, 211},
lightpink = {255, 182, 193},
lightsalmon = {255, 160, 122},
lightseagreen = { 32, 178, 170},
lightskyblue = {135, 206, 250},
lightslategray = {119, 136, 153},
lightslategrey = {119, 136, 153},
lightsteelblue = {176, 196, 222},
lightyellow = {255, 255, 224},
lime = { 0, 255, 0},
limegreen = { 50, 205, 50},
linen = {250, 240, 230},
magenta = {255, 0, 255},
maroon = {128, 0, 0},
mediumaquamarine = {102, 205, 170},
mediumblue = { 0, 0, 205},
mediumorchid = {186, 85, 211},
mediumpurple = {147, 112, 219},
mediumseagreen = { 60, 179, 113},
mediumslateblue = {123, 104, 238},
mediumspringgreen = { 0, 250, 154},
mediumturquoise = { 72, 209, 204},
mediumvioletred = {199, 21, 133},
midnightblue = { 25, 25, 112},
mintcream = {245, 255, 250},
mistyrose = {255, 228, 225},
moccasin = {255, 228, 181},
navajowhite = {255, 222, 173},
navy = { 0, 0, 128},
oldlace = {253, 245, 230},
olive = {128, 128, 0},
olivedrab = {107, 142, 35},
orange = {255, 165, 0},
orangered = {255, 69, 0},
orchid = {218, 112, 214},
palegoldenrod = {238, 232, 170},
palegreen = {152, 251, 152},
paleturquoise = {175, 238, 238},
palevioletred = {219, 112, 147},
papayawhip = {255, 239, 213},
peachpuff = {255, 218, 185},
peru = {205, 133, 63},
pink = {255, 192, 203},
plum = {221, 160, 221},
powderblue = {176, 224, 230},
purple = {128, 0, 128},
red = {255, 0, 0},
rosybrown = {188, 143, 143},
royalblue = { 65, 105, 225},
saddlebrown = {139, 69, 19},
salmon = {250, 128, 114},
sandybrown = {244, 164, 96},
seagreen = { 46, 139, 87},
seashell = {255, 245, 238},
sienna = {160, 82, 45},
silver = {192, 192, 192},
skyblue = {135, 206, 235},
slateblue = {106, 90, 205},
slategray = {112, 128, 144},
slategrey = {112, 128, 144},
snow = {255, 250, 250},
springgreen = { 0, 255, 127},
steelblue = { 70, 130, 180},
tan = {210, 180, 140},
teal = { 0, 128, 128},
thistle = {216, 191, 216},
tomato = {255, 99, 71},
turquoise = { 64, 224, 208},
violet = {238, 130, 238},
wheat = {245, 222, 179},
white = {255, 255, 255},
whitesmoke = {245, 245, 245},
yellow = {255, 255, 0},
yellowgreen = {154, 205, 50}
}

colorsRGB.R = function (name)
return colorsRGB[name][1]
end

colorsRGB.G = function (name)
return colorsRGB[name][2]
end

colorsRGB.B = function (name)
return colorsRGB[name][3]
end

colorsRGB.RGB = function (name)
return colorsRGB[name][1],colorsRGB[name][2],colorsRGB[name][3]
end


function setFibaroColor(device, Red, Green, Blue)
if (device:typeString() ~= 'zwave') then
print("Device %s is not a Z-Wave device", device:name())
return
end

-- Get the raw zwave node
local zwaveNode = device:zwaveNode()
-- Extract the rgb color setpoint command class
local cmdClass = zwaveNode:cmdClass(COMMAND_CLASS_COLOR_CONTROL)
if (cmdClass == nil) then
print("Device %s does not support COMMAND_CLASS_COLOR_CONTROL", device:name())
return
end
-- Set new value to be sent the next time the device is awake
cmdClass:setSetpoint(COMMAND_CLASS_COLOR_CONTROL, Red, Green, Blue)


end
micke.prag
Site Admin
Posts: 2243
Joined: Fri Mar 17, 2023 9:45 am
Location: Lund
Contact:

Re: LUA Fibaro RGBW,

Post by micke.prag »

You can use the experimental device method rgbw. This will set to red:

Code: Select all

device:command('rgbw', 0xFF000000, "lua")
One warning though, this command will change from rgbw to rgb in a later firmware...
Micke Prag
Software
Telldus Technologies
geirbakkw
Posts: 15
Joined: Fri Mar 17, 2023 9:45 am

Re: LUA Fibaro RGBW,

Post by geirbakkw »

I did some changes to my script to be able to convert colour name to hex, now I just have to find a way to use it.

Code: Select all

local deviceManager = require "telldus.DeviceManager"
local RGBLYS = "RGB" --RGB Controller


function onInit()
	
	print(ChangeColorRGBToHex(colorsRGB["aliceblue"]))

	--print(hexadecimal)
	--device:command('rgbw', 0xFF000000, "lua")

end


function controlDevice(device, action)
	local device = deviceManager:findByName(device)
	if device == nil then
		return
	end
	if action == "ON" and device:state() == 2 then
		print("%s - %s", device:name(), action)
		device:command("turnon", nil, "RGB")
	elseif action == "OFF" and device:state() == 1 then
		print("%s - %s", device:name(), action)
		device:command("turnoff", nil, "RGB")
	end
end



colorsRGB = {
aliceblue = {240, 248, 255},
antiquewhite = {250, 235, 215},
aqua = { 0, 255, 255},
aquamarine = {127, 255, 212},
azure = {240, 255, 255},
beige = {245, 245, 220},
bisque = {255, 228, 196},
black = { 0, 0, 0},
blanchedalmond = {255, 235, 205},
blue = { 0, 0, 255},
blueviolet = {138, 43, 226},
brown = {165, 42, 42},
burlywood = {222, 184, 135},
cadetblue = { 95, 158, 160},
chartreuse = {127, 255, 0},
chocolate = {210, 105, 30},
coral = {255, 127, 80},
cornflowerblue = {100, 149, 237},
cornsilk = {255, 248, 220},
crimson = {220, 20, 60},
cyan = { 0, 255, 255},
darkblue = { 0, 0, 139},
darkcyan = { 0, 139, 139},
darkgoldenrod = {184, 134, 11},
darkgray = {169, 169, 169},
darkgreen = { 0, 100, 0},
darkgrey = {169, 169, 169},
darkkhaki = {189, 183, 107},
darkmagenta = {139, 0, 139},
darkolivegreen = { 85, 107, 47},
darkorange = {255, 140, 0},
darkorchid = {153, 50, 204},
darkred = {139, 0, 0},
darksalmon = {233, 150, 122},
darkseagreen = {143, 188, 143},
darkslateblue = { 72, 61, 139},
darkslategray = { 47, 79, 79},
darkslategrey = { 47, 79, 79},
darkturquoise = { 0, 206, 209},
darkviolet = {148, 0, 211},
deeppink = {255, 20, 147},
deepskyblue = { 0, 191, 255},
dimgray = {105, 105, 105},
dimgrey = {105, 105, 105},
dodgerblue = { 30, 144, 255},
firebrick = {178, 34, 34},
floralwhite = {255, 250, 240},
forestgreen = { 34, 139, 34},
fuchsia = {255, 0, 255},
gainsboro = {220, 220, 220},
ghostwhite = {248, 248, 255},
gold = {255, 215, 0},
goldenrod = {218, 165, 32},
gray = {128, 128, 128},
grey = {128, 128, 128},
green = { 0, 128, 0},
greenyellow = {173, 255, 47},
honeydew = {240, 255, 240},
hotpink = {255, 105, 180},
indianred = {205, 92, 92},
indigo = { 75, 0, 130},
ivory = {255, 255, 240},
khaki = {240, 230, 140},
lavender = {230, 230, 250},
lavenderblush = {255, 240, 245},
lawngreen = {124, 252, 0},
lemonchiffon = {255, 250, 205},
lightblue = {173, 216, 230},
lightcoral = {240, 128, 128},
lightcyan = {224, 255, 255},
lightgoldenrodyellow = {250, 250, 210},
lightgray = {211, 211, 211},
lightgreen = {144, 238, 144},
lightgrey = {211, 211, 211},
lightpink = {255, 182, 193},
lightsalmon = {255, 160, 122},
lightseagreen = { 32, 178, 170},
lightskyblue = {135, 206, 250},
lightslategray = {119, 136, 153},
lightslategrey = {119, 136, 153},
lightsteelblue = {176, 196, 222},
lightyellow = {255, 255, 224},
lime = { 0, 255, 0},
limegreen = { 50, 205, 50},
linen = {250, 240, 230},
magenta = {255, 0, 255},
maroon = {128, 0, 0},
mediumaquamarine = {102, 205, 170},
mediumblue = { 0, 0, 205},
mediumorchid = {186, 85, 211},
mediumpurple = {147, 112, 219},
mediumseagreen = { 60, 179, 113},
mediumslateblue = {123, 104, 238},
mediumspringgreen = { 0, 250, 154},
mediumturquoise = { 72, 209, 204},
mediumvioletred = {199, 21, 133},
midnightblue = { 25, 25, 112},
mintcream = {245, 255, 250},
mistyrose = {255, 228, 225},
moccasin = {255, 228, 181},
navajowhite = {255, 222, 173},
navy = { 0, 0, 128},
oldlace = {253, 245, 230},
olive = {128, 128, 0},
olivedrab = {107, 142, 35},
orange = {255, 165, 0},
orangered = {255, 69, 0},
orchid = {218, 112, 214},
palegoldenrod = {238, 232, 170},
palegreen = {152, 251, 152},
paleturquoise = {175, 238, 238},
palevioletred = {219, 112, 147},
papayawhip = {255, 239, 213},
peachpuff = {255, 218, 185},
peru = {205, 133, 63},
pink = {255, 192, 203},
plum = {221, 160, 221},
powderblue = {176, 224, 230},
purple = {128, 0, 128},
red = {255, 0, 0},
rosybrown = {188, 143, 143},
royalblue = { 65, 105, 225},
saddlebrown = {139, 69, 19},
salmon = {250, 128, 114},
sandybrown = {244, 164, 96},
seagreen = { 46, 139, 87},
seashell = {255, 245, 238},
sienna = {160, 82, 45},
silver = {192, 192, 192},
skyblue = {135, 206, 235},
slateblue = {106, 90, 205},
slategray = {112, 128, 144},
slategrey = {112, 128, 144},
snow = {255, 250, 250},
springgreen = { 0, 255, 127},
steelblue = { 70, 130, 180},
tan = {210, 180, 140},
teal = { 0, 128, 128},
thistle = {216, 191, 216},
tomato = {255, 99, 71},
turquoise = { 64, 224, 208},
violet = {238, 130, 238},
wheat = {245, 222, 179},
white = {255, 255, 255},
whitesmoke = {245, 245, 245},
yellow = {255, 255, 0},
yellowgreen = {154, 205, 50}
}

function ChangeColorRGBToHex(rgb)
	
	local hexadecimal = '0X'

	for key, value in pairs(rgb) do
		local hex = ''

		while(value > 0)do
			local index = math.fmod(value, 16) + 1
			value = math.floor(value / 16)
			hex = string.sub('0123456789ABCDEF', index, index) .. hex			
		end

		if(string.len(hex) == 0)then
			hex = '00'

		elseif(string.len(hex) == 1)then
			hex = '0' .. hex
		end
	
			hexadecimal = hexadecimal .. hex
		end

		--print(hexadecimal)
	
		return hexadecimal
		
end

	


	
	

ColdCreak
Posts: 1
Joined: Fri Mar 17, 2023 9:45 am

Re: LUA Fibaro RGBW,

Post by ColdCreak »

Any progress on finding a way to use it? :D
ushac
Posts: 3
Joined: Fri Mar 17, 2023 9:45 am

Re: LUA Fibaro RGBW,

Post by ushac »

micke.prag, why change it from RGBW to just RGB? Will you have an alternative to also set the W channel in the future?
I'm hovering the mouse over the buy-button for an RGBW-unit with higher output than RGB one I currently have, but if I will be unable to use it properly soon...

My first time code lua, so this code is ugly as frig (and not really accurate), but it does a decently satisfying job of emulating a color temperature with the RGB LED strip I have. Maybe someone here will find it useful too.
I plan to tidy it up and control it via a 1-10V dimmer unit, or potentially do a "wake up light" thingy and smoothly increase both intensity and color temperature during the rampup.
Props to Tanner Helland for the K to RGB mapping. http://www.tannerhelland.com/4435/conve ... ithm-code/

Code: Select all

local deviceManager = require "telldus.DeviceManager"

local rgb_device = nil;  -- lazy initialized

MAX_VALUE = 0xFF  -- Max value for 8-bit unsigned.
-- Factors for RGB that achieves an approximate white light with the particular model of led stripe being used.
RED_FACTOR = 1.0
GREEN_FACTOR = 0.9
BLUE_FACTOR = 0.7

function getRgbControllerDevice()
	if rgb_device == nil then
		rgb_device = deviceManager:findByName("rgbw")
		if rgb_device == nil then
			print "Unable to find RGB controller"
		end
	end
	return rgb_device
end

-- Clamps to an unsigned 8-bit range.
function clamp(x)
	if (x < 0) then
		return 0
	elseif (x > MAX_VALUE) then
		return MAX_VALUE
	else
		return math.floor(x + 0.5)
	end
end

function rgbToHex(r, g, b, w)
	-- Mask together four 8-bit integers into a single 32-bit value.
	-- Why no bit-shift operator?!
	rgbw_val = clamp(r * RED_FACTOR)
	rgbw_val = rgbw_val * (MAX_VALUE + 1)
	rgbw_val = rgbw_val + clamp(g * GREEN_FACTOR)
	rgbw_val = rgbw_val * (MAX_VALUE + 1)
	rgbw_val = rgbw_val + clamp(b * BLUE_FACTOR)
	rgbw_val = rgbw_val * (MAX_VALUE + 1)
	rgbw_val = rgbw_val + clamp(w)
	-- sign extension 32 to 64 bit two's complement. There's gotta be a better way...
	if (rgbw_val >= 2147483648) then
		rgbw_val = rgbw_val - 4294967296
	end
	return rgbw_val
end

-- Color temperatur in degrees K, intensity as factor (0.0 to 1.0)
function setColorTemp(temp_kelvin, intensity)
    temp = temp_kelvin / 100

	local red = 0;
	local green = 0;
	local blue = 0;

    if temp <= 66 then
        red = 255
    else
        red = temp - 60
		red = clamp(329.698727446 * (red ^ -0.1332047592))
    end

    if temp <= 66 then
        green = temp
        green = clamp(99.4708025861 * math.log(green) - 161.1195681661)
    else
        green = temp - 60
        green = clamp(288.1221695283 * (green ^ -0.0755148492))
    end

    if temp >= 66 then
        blue = 255
    elseif temp <= 19 then
        blue = 0
    else
        blue = temp - 10
        blue = clamp(138.5177312231 * math.log(blue) - 305.0447927307)
    end
	
	setRgb(red * intensity, green * intensity, blue * intensity)
end

-- RGB each in 0-255 range.
function setRgb(r, g, b)
	-- print("@Setting r " .. r .. ", g " .. g .. ", b " .. b)
	local device = getRgbControllerDevice()
	-- Why does the device seem to treat this as an RBG value rather than RGB?!
	device:command('rgbw', rgbToHex(r, b, g, 0), "lua")
end

function onInit()
	-- 1000K Dull red glow
	-- 2000K Retro "Edison"-style filament bulb
	-- 2700K "Normal" warm-white light bulb
	-- 3000K Bright white
	-- 4000K Cool white
	-- 5000K Daylight
	setColorTemp(2000, 1.0)
	
	--setRgb(100, 90, 75)
end
micke.prag
Site Admin
Posts: 2243
Joined: Fri Mar 17, 2023 9:45 am
Location: Lund
Contact:

Re: LUA Fibaro RGBW,

Post by micke.prag »

ushac wrote:micke.prag, why change it from RGBW to just RGB? Will you have an alternative to also set the W channel in the future?
Yes. Of course.
The reason is that there are RGB lamps not supporting color temperatures. Also there is white lamps supporting color temperature but not colors.
Have this combined does not make sense and makes it too complicated. The plan is to separate RGB and color temperature into two different methods.
Micke Prag
Software
Telldus Technologies
ushac
Posts: 3
Joined: Fri Mar 17, 2023 9:45 am

Re: LUA Fibaro RGBW,

Post by ushac »

I see. Thanks for the response!
It would be great if I was able to do this as python plugin instead, so we don't have to hard-code device names in the scripts etc. :wink:
Anyway, here's an updated version of the script. I use it as a wakeup light which changes both intensity and also color from reddish yellow (1000K) to daylight (5000K), and can be triggered via the schedule manager.

Code: Select all

local deviceManager = require "telldus.DeviceManager"

-- Made for Fibaro RGBW dimmer. Adding it will create 6 device in Telldus
-- device manager: 4x for R, G, B and W. A "main" RGB device which takes the
-- joint RGB commands. (This is the device that also displays the power usage.)
-- It also creates an additional DIM capable device. Unclear what the intent
-- is with this device, be we use it here to trigger the wakeup-light func.
-- This allows us to separate a state change for the main unit and an explicit
-- dim command. Schedule the wakeup at desired time in the schedule manager and
-- set the action to set the dimmer device to 1%.
-- Use TURNOFF command on dimmer device to abort wakeup, and use it's on state
-- to detect wakeup-light in progress for events in main panel.
 
local rgb_main_device_name = "RGB"  -- main device
local rgb_dim_device_name = "RGB Intensity"  -- dimmer device

-- individual channels, used to query rgbw state before running wakeup, so that
-- we can restore them before shutting down again.
local rgb_red_device_name = "RGB Red"
local rgb_green_device_name = "RGB Green"
local rgb_blue_device_name = "RGB Blue"
local rgb_white_device_name = "RGB White"

-- Wakeup light time parameters:
-- Dim from 0 to 100% over this many minutes
WAKUP_DURATION_MIN = 30
-- After dimming up to 100%, stay on for this many mintues, then turn off.
ONTIME_AFTER_WAKUP = 10

-- Factors for RGB that achieves an approximate white light with my particular
-- model of led stripe. (At 100% for all channels, there was a significant
-- blue tint).
RED_FACTOR = 1.0
GREEN_FACTOR = 0.9
BLUE_FACTOR = 0.7

-- Types of state change events. Do not change!
TURNON = 1
TURNOFF = 2
DIM = 16
RGBW = 1024

MAX_VALUE = 0xFF  -- Max value for 8-bit unsigned. Do not change!

-- State value use to check if wakeup is in progress or to abort ongoing.
local wakeup_in_progress = false

-- Clamps to an unsigned 8-bit range.
function clamp(x)
	if (x < 0) then
		return 0
	elseif (x > MAX_VALUE) then
		return MAX_VALUE
	else
		return math.floor(x + 0.5)
	end
end

function rgbToHex(r, g, b, w)
	-- Mask together four 8-bit integers into a single 32-bit value.
	-- Why no bit-shift operator?!
	rgbw_val = clamp(r * RED_FACTOR)
	rgbw_val = rgbw_val * (MAX_VALUE + 1)
	rgbw_val = rgbw_val + clamp(g * GREEN_FACTOR)
	rgbw_val = rgbw_val * (MAX_VALUE + 1)
	rgbw_val = rgbw_val + clamp(b * BLUE_FACTOR)
	rgbw_val = rgbw_val * (MAX_VALUE + 1)
	rgbw_val = rgbw_val + clamp(w)
	-- Sign extension 32 to 64 bit two's complement.
	-- There's gotta be a better way...
	if (rgbw_val >= 2147483648) then
		rgbw_val = rgbw_val - 4294967296
	end
	return rgbw_val
end

-- Color temperatur in degrees K, intensity as factor (0.0 to 1.0)
	-- 1000K Dull red glow
	-- 2000K Retro "Edison"-style filament bulb
	-- 2700K "Normal" warm-white light bulb
	-- 3000K Bright white
	-- 4000K Cool white
	-- 5000K Daylight
function setColorTemp(temp_kelvin, intensity)
    temp = temp_kelvin / 100

	local red = 0;
	local green = 0;
	local blue = 0;

    if temp <= 66 then
        red = MAX_VALUE
    else
        red = temp - 60
		red = clamp(329.698727446 * (red ^ -0.1332047592))
    end

    if temp <= 66 then
        green = temp
        green = clamp(99.4708025861 * math.log(green) - 161.1195681661)
    else
        green = temp - 60
        green = clamp(288.1221695283 * (green ^ -0.0755148492))
    end

    if temp >= 66 then
        blue = MAX_VALUE
    elseif temp <= 19 then
        blue = 0
    else
        blue = temp - 10
        blue = clamp(138.5177312231 * math.log(blue) - 305.0447927307)
    end
	
	setRgb(red * intensity, green * intensity, blue * intensity)
end

-- RGB each in 0-255 range. Convenience with w = 0
function setRgb(r, g, b)
	setRgbw(r, g, b, 0)
end

-- RGB each in 0-255 range.
function setRgbw(r, g, b, w)
	--print("@Setting r " .. r .. ", g " .. g .. ", b " .. b .. ", w " .. w)
	local device = deviceManager:findByName(rgb_main_device_name)
	-- Why does the device seem to treat this as an RBG value rather than RGB?!
	device:command('rgbw', rgbToHex(r, b, g, 0), "lua")
end

-- Used to query each of the r, g, b, w channels for current dim state.
function getChannelState(device_name)
	local device = deviceManager:findByName(device_name)
	state, stateValue = device:state()
	if (state == TURNOFF) then
		return 0
	elseif (state == DIM) then
		return stateValue
	elseif (state == TURNON) then
		return MAX_VALUE
	else
		print("Warning: Can get state for device " .. device_name)
		return 0
	end
end

-- A function parameter i will span from startSpan to endSpan,
-- produce an output of startValue if i = startSpan, endValue if i = endSpan,
-- otherwise linearly interpolate between those ends.
function linearInterpolate(startSpan, endSpan, startValue, endValue, i)
	local pos = i + 0.0
	if (i < startSpan) then
		pos = startSpan
	elseif (i > endSpan) then
		pos = endSpan
	end
	local frac = (pos - startSpan) / (endSpan - startSpan)
	return startValue + (frac * (endValue - startValue))
end

function runWakeUpLight()
	-- Dim from 1000K
	local color_temp = 1000
	local intensity = 1  / MAX_VALUE
	for i = 1,MAX_VALUE do
		-- Check if wakeup has been aborted by user.
		if (not wakeup_in_progress) then
			return
		end
		-- Some arbitrary piece-wise liner interpolation between points
		-- I happen to find pleasing :)
		if i < 75 then
			color_temp = linearInterpolate(1, 74, 1000, 1800, i)
		elseif i < 150 then
			color_temp = linearInterpolate(75, 149, 1800, 2700, i)
		else
			color_temp = linearInterpolate(150, MAX_VALUE, 2700, 5000, i)
		end
		-- Intensity is just scaled linearly during the whole rampup.
		intensity = linearInterpolate(0, MAX_VALUE, 0, 1, i)
		
		-- Update color and sleep until the next cycle.
		setColorTemp(color_temp, intensity)
		sleep((WAKUP_DURATION_MIN * 60 * 1000) / MAX_VALUE)
	end
	
	-- Wait for specified time at full power.
	local ms_to_sleep = ONTIME_AFTER_WAKUP * 60 * 1000
	local ms_slept = 0
	while (ms_slept < ms_to_sleep) do
		-- Sleep up to 1s at a time, then wake up and check if timer
		-- has been aborted by user.
		local sleep_this_cycle = math.min(ms_to_sleep - ms_slept, 1000)
		sleep(sleep_this_cycle)
		ms_slept = ms_slept + sleep_this_cycle
		if (not wakeup_in_progress) then
			return
		end
	end
end

function onInit()
	--setRgb(255, 0, 255)
	--setColorTemp(1984, 0.05)
	
	wakeup_in_progress = false
end

function onDeviceStateChanged(device, state, stateValue)
	local rgb_dimmer_device = deviceManager:findByName(rgb_dim_device_name)
	if (device:id() == rgb_dimmer_device:id()) then
		if ((state == RGBW or state == DIM or state == TURNON) and (wakeup_in_progress == false)) then
			wakeup_in_progress = true
		
			-- Poll the current rgbw state
			local r = getChannelState(rgb_red_device_name)
			local g = getChannelState(rgb_green_device_name)
			local b = getChannelState(rgb_blue_device_name)
			local w = getChannelState(rgb_white_device_name)
	
			runWakeUpLight()  -- Run the wake-up light!
			
			-- Restore original state and shut down.
			setRgbw(r, g, b, w)
			device:command("turnoff", nil, "Wakeup")
			wakeup_in_progress = false		
		elseif (state == TURNOFF) then
			-- Use TURNOFF command on dimmer device to abort wakeup.
			wakeup_in_progress = false
		end
	end
end
ushac
Posts: 3
Joined: Fri Mar 17, 2023 9:45 am

Re: LUA Fibaro RGBW,

Post by ushac »

Btw micke.prag, do you know why the fibaro controller registers that extra DIM device?
I also have a normal 230v dimmer from fibaro, and it also registers like three dimmer devices for some non-apparent reason.
micke.prag
Site Admin
Posts: 2243
Joined: Fri Mar 17, 2023 9:45 am
Location: Lund
Contact:

Re: LUA Fibaro RGBW,

Post by micke.prag »

ushac wrote:Btw micke.prag, do you know why the fibaro controller registers that extra DIM device?
My guess is that they do that to support controllers not supporting RGB. Just a guess though.
Micke Prag
Software
Telldus Technologies
Post Reply