I'm sharing this DZVents scripts : a collection of functions to animate lights, from transitionning to blinking, alternating scenes...
For instance you want to be notified when someone comes home by having a light blinking you can do it like this. Note this is also
using my Restore State script to put back the light to the state it was before we start blinking it...
Code: Select all
return {
on = {
devices = { 'Phone Sensor' }
},
logging = {
level = domoticz.LOG_INFO,
marker = 'BLINKING TEST',
},
execute = function(domoticz, device)
if(device.isDevice) then
domoticz.log('XXXX got home, blink our living room light', domoticz.LOG_INFO)
-- Store the state of the living room light and restore it after 35 sec.
domoticz.helpers.restoreStateAfter(domoticz, 'Living Room Light', 35)
-- Start binking the living room light for 30 sec (here it blink off and red, every 0.5 sec
-- the color change off / red / off / red ....)
domoticz.helpers.blink(domoticz, 'Living Room Light',
{ ['r']=0,['g']=0,['b']=0,['br']=100,['cw']=0,['ww']=0,['t']=0,['m']=3 },
{ ['r']=255,['g']=0,['b']=0,['br']=100,['cw']=0,['ww']=0,['t']=0,['m']=3 },
0.5, 30)
end
end
}
Blinking
Transitionning to another color
Swapping colors of the lamps in a group : to create Xmas light effects and easy animation design thanks to the group / scene editor in domoticz)
Alternating scene / group : to create more complex animation.
To install this script, you'll need the CURL utility, you can download CURL here if you don't have it already installed on your system. CURL is available for many platforms (windows / linux).This is a command line utility to make http requests (and other), that will be used by the script to make synchronous http requests (DZVents does offer asynchronous requests, taht's why CURL is needed). Once you downloaded the binary, put it on the folder of your choice and take note of the path you put CURL, we will need it later.
You need to have the "global_data" DZVents scripts. If you don't have a "global_data" script, go into "Setup" -> "More Options" -> "Events", click on "+" and select "DZVENTS" -> "GLOBAL DATA". Instead of "Script #1" type "global_data" (without the quotes). You can now copy and paste the code below and click on "SAVE" (check in the domoticz log for any errors, sometimes on Windows you have to make sure Domoticz can save the scripts file correctly)
If you do have an existing "global_data" script, then you'll need to add the functions and global variables you'll find in the code below.
Code: Select all
-- this scripts holds all the globally persistent variables and helper functions
-- see the documentation in the wiki
-- NOTE:
-- THERE CAN BE ONLY ONE global_data SCRIPT in your Domoticz install.
return {
-- Variables Globales Persistentes
data = {
-- ANIMATE COLOR VARS --
cancelTransition = { initial = { [0] = nil } }
-- END ANIMATE COLOR VARS --
},
-- Fonction Globales
helpers = {
-- Does the argument is a number
-- x : the value to check
isNumber = function (x)
if tonumber(x) ~= nil then return true end
return false
end,
-- get the color of a light
-- deviceId : IDX or device name
getColor = function(domoticz, deviceId)
local idx = deviceId
if(not domoticz.helpers.isNumber(deviceId)) then idx = domoticz.devices(deviceId).idx end
cmd='"C:\\Program Files (x86)\\Domoticz\\scripts\\lua\\curl.exe" '..domoticz.settings.url..'/json.htm?type=devices^&rid='..idx
local httpRequest = assert(io.popen(cmd))
local html = httpRequest:read('*all')
local json = domoticz.utils.fromJSON(html)
-- adding brigthness to the color object
local color = domoticz.utils.fromJSON(json.result[1].Color)
color.br = domoticz.devices(deviceId).level
-- returning the result
return color
end,
-- ANIMATE COLOR FUNC --
--
cap255 = function(x)
if(x>255) then return 255 end
if(x<=0) then return nil end
return math.floor(x)
end,
cap100 = function(x)
if(x>100) then return 100 end
if(x<=0) then return nil end
return math.floor(x)
end,
-- Transition a light to a new color over time
-- device : light to be transitionned
-- color : the new color and brightness : { ['r']=0, ['g']=0, ['b']=0, ['br']=0, ['cw']=0, ['ww']=0, ['t']=0, ['m']=1/2/3/4 }
-- m = 1, white only br means something, br 0 to 100
-- m = 2, white temp only t mean something, t 0 to 255
-- m = 3, color only r,g,b mean something, rgb 0 to 255
-- m = 4, extended color only r,g,b,cw,ww mean something, cw,ww,rgb 0 to 255
-- duration : duration of the effect in seconds
-- NOTE : if the light is off, no transition is done other
-- than brightness (basically Off = color 0,0,0)
transitionTo = function(domoticz, device, color, duration)
-- compute the number of steps needed
-- minimum duration : 1 sec.
-- max. steps number : 30
local timeLapse = 1
local totalSteps = 30
if(duration >= 30) then
timeLapse = duration / 30
totalSteps = 30
else
timeLapse = 1
totalSteps = duration
end
-- creating array of steps
local startColor = domoticz.helpers.getColor(domoticz, device)
-- special case : device is off
if(domoticz.devices(device).inActive) then
startColor.r = 0
startColor.g = 0
startColor.b = 0
startColor.cw = 0
startColor.ww = 0
startColor.t = 0
startColor.br = 0
end
-- filling the array will all steps states
local colorSteps = { ['next'] = nil, ['color'] = color}
for step = totalSteps,1,-1 do
local stepColor = { ['r']=domoticz.helpers.cap255(startColor.r + (step * (color.r-startColor.r)/totalSteps)),
['g']=domoticz.helpers.cap255(startColor.g + (step * (color.g-startColor.g)/totalSteps)),
['b']=domoticz.helpers.cap255(startColor.b + (step * (color.b-startColor.b)/totalSteps)),
['br']=domoticz.helpers.cap100(startColor.br + (step * (color.br-startColor.br)/totalSteps)),
['cw']=domoticz.helpers.cap255(startColor.cw + (step * (color.cw-startColor.cw)/totalSteps)),
['ww']=domoticz.helpers.cap255(startColor.ww + (step * (color.ww-startColor.ww)/totalSteps)),
['t']=domoticz.helpers.cap255(startColor.t + (step * (color.t-startColor.t)/totalSteps)),
['m']=startColor.m }
colorSteps = { ['next'] = colorSteps, ['color'] = stepColor}
end
-- start the transition effect
domoticz.emitEvent('transitionState', { ['steps'] = colorSteps, ['delay'] = timeLapse, ['device'] = device })
end,
-- make a light blink
-- device : idx or device name to blink
-- color1 : first color { ['r']=0, ['g']=0, ['b']=0, ['br']=0, ['cw']=0, ['ww']=0, ['t']=0, ['m']=1/2/3/4 }
-- color2 : other color (blink = alternate color1 and color2)
-- if one of the color has br=0 or r=0 and g=0 and b=0 then light is turn off (blinking on / off)
-- speed : in seconds time between each color change
-- duration : total duration of the effect in seconds (if 60 : the light will blink for a minute)
blink = function(domoticz, device, color1, color2, speed, duration)
local colorSteps = { ['next'] = color2, ['color'] = color1}
domoticz.emitEvent('alternateState', { ['steps'] = colorSteps, ['delay'] = speed, ['duration'] = duration, ['device'] = device })
end,
-- swap the colors of each light in a group scenes
-- group : idx or name of group / scene
-- speed : in seconds, time between each color change
-- duration : total duration of the effect in seconds
animateGroup = function(domoticz, group, speed, duration)
-- create the list of colors and states of all device in group
-- when the animation starts
local colors = {}
local devices = {}
local count = 0
local idx = nil
if(domoticz.utils.sceneExists(group)) then idx = domoticz.scenes(group).idx
elseif(domoticz.utils.groupExists(group)) then idx = domoticz.groups(group).idx end
-- We have a valid group or scene
if(idx) then
-- get the devices and state in the group / scene
local cmd='"C:\\Program Files (x86)\\Domoticz\\scripts\\lua\\curl.exe" '..domoticz.settings.url..'/json.htm?type=command^¶m=getscenedevices^&isscene=true^&idx='..idx
local httpRequest = assert(io.popen(cmd))
local html = httpRequest:read('*all')
local json = domoticz.utils.fromJSON(html)
-- results are valid JSON
if(json.status == 'OK') then
-- review each device and store its id and state (color / on/off...) in array
for i, device in ipairs(json.result) do
count = count + 1
-- device ID
devices[count] = device.DevID
-- device state : color / on/off / Level
if(device.Color) then device.Color = domoticz.utils.fromJSON(device.Color) end
if(device.Color) then device.Color.br = device.Level else device.Color = { ['br'] = device.Level } end
-- if device is not On then the device is off, we simplify by stating its brightness is 0
if(device.Command == "On") then colors[count] = device.Color else colors[count] = { ['br'] = 0 } end
end
end
end
-- starting the transition
domoticz.emitEvent('switchState', { ['devices'] = devices, ['colors'] = colors, ['step'] = 0, ['delay'] = speed, ['duration'] = duration })
end,
-- alternate scenes : change a scene each xx sec.
-- scenes : scenes / groups array to alternat ex : {'Scene 1', 'Scene 2', 'Scene 3'}
-- speed : in seconds, time between each scene change
-- duration : total duration of the effect in seconds
animateScenes = function(domoticz, scenes, speed, duration)
domoticz.emitEvent('sceneChangeState', { ['scenes'] = scenes, ['step'] = 0, ['delay'] = speed, ['duration'] = duration })
end,
-- cancel a running transition
-- work only for "transitionTo" et "blink"
cancelTransition = function(domoticz, device)
if(not domoticz.helpers.isNumber(device)) then device = domoticz.devices(device).id end
-- signal the transition to end early
domoticz.globalData.cancelTransition[device] = true
end,
--
-- END ANIMATE COLOR FUNC
}
}
cmd='"C:\\Program Files (x86)\\Domoticz\\scripts\\lua\\curl.exe" '..domoticz.settings.url..'/json.htm?type=devices^&rid='..idx
Replace the current path with the path on your system.
Once this is done you can create the script that will hande all the animations : in the script editor, click on "+" then select "DZVENTS" -> "CUSTOM EVENTS", give it the name you want instead of "Script #1", for instance "Transition State", copy and paste the code below and click on "SAVE".
Code: Select all
return {
on = { customEvents = { 'transitionState', 'alternateState', 'switchState', 'sceneChangeState' } },
logging = { level = domoticz.LOG_ERROR,
marker = 'TRANSITION STATE', },
execute = function(domoticz, item)
-- TRANSITION
if (item.isCustomEvent and item.trigger == 'transitionState') then
-- Get JSON in event data
local eventData = domoticz.utils.fromJSON(item.data)
-- should we cancel our transition ?
local deviceId = domoticz.devices(eventData.device).id
if(domoticz.globalData.cancelTransition[deviceId]) then
domoticz.globalData.cancelTransition[deviceId] = nil
return
end
-- color data for the transition
local currentColor = eventData.steps.color
local nextColorSteps = eventData.steps.next
-- checking colors values (we use nil instead of 0
-- as it shortens the string for the custom event)
if(not currentColor.r) then currentColor.r = 0 end
if(not currentColor.g) then currentColor.g = 0 end
if(not currentColor.b) then currentColor.b = 0 end
if(not currentColor.br) then currentColor.br = 0 end
if(not currentColor.cw) then currentColor.cw = 0 end
if(not currentColor.ww) then currentColor.ww = 0 end
if(not currentColor.t) then currentColor.t = 0 end
-- setting color / state
if(domoticz.devices(eventData.device).deviceType == 'Color Switch') then
domoticz.helpers.setColor(domoticz, eventData.device,
currentColor.r,currentColor.g,currentColor.b,
currentColor.br,
currentColor.cw,currentColor.ww,
currentColor.m,currentColor.t)
elseif(domoticz.devices(eventData.device).switchType =='Dimmer') then
domoticz.devices(eventData.device).dimTo(currentColor.br)
end
-- schedule next transition
if(nextColorSteps) then
domoticz.emitEvent('transitionState', { ['steps'] = nextColorSteps, ['delay'] = eventData.delay, ['device'] = eventData.device }).afterSec(eventData.delay)
end
end
-- BLINKING
if (item.isCustomEvent and item.trigger == 'alternateState') then
-- Get JSON in event data
local eventData = domoticz.utils.fromJSON(item.data)
-- should we cancel our transition ?
if(eventData.duration <= 0) then return end
local deviceId = domoticz.devices(eventData.device).id
if(domoticz.globalData.cancelTransition[deviceId]) then
domoticz.globalData.cancelTransition[deviceId] = nil
return
end
-- color date for the transition
local currentColor = eventData.steps.color
local nextColorSteps = eventData.steps.next
-- swappping
eventData.steps.color = nextColorSteps
eventData.steps.next = currentColor
-- reducing duration
eventData.duration = eventData.duration - eventData.delay
-- checking colors values (we use nil instead of 0
-- as it shortens the string for the custom event)
if(not currentColor.r) then currentColor.r = 0 end
if(not currentColor.g) then currentColor.g = 0 end
if(not currentColor.b) then currentColor.b = 0 end
if(not currentColor.br) then currentColor.br = 0 end
if(not currentColor.cw) then currentColor.cw = 0 end
if(not currentColor.ww) then currentColor.ww = 0 end
if(not currentColor.t) then currentColor.t = 0 end
-- setting color / state
if((currentColor.r == 0 and currentColor.g == 0 and currentColor.b == 0 and currentColor.m == 3) or
(currentColor.br == 0)) then
domoticz.devices(eventData.device).switchOff()
elseif(domoticz.devices(eventData.device).deviceType == 'Color Switch') then
domoticz.helpers.setColor(domoticz, eventData.device,
currentColor.r,currentColor.g,currentColor.b,
currentColor.br,
currentColor.cw,currentColor.ww,
currentColor.m,currentColor.t)
elseif(domoticz.devices(eventData.device).switchType =='Dimmer') then
domoticz.devices(eventData.device).dimTo(currentColor.br)
end
--scheduling next event
domoticz.emitEvent('alternateState', { ['steps'] = eventData.steps, ['delay'] = eventData.delay, ['duration'] = eventData.duration, ['device'] = eventData.device }).afterSec(eventData.delay)
end
-- GROUP SWAPPING
if (item.isCustomEvent and item.trigger == 'switchState') then
-- Get JSON in event data
local eventData = domoticz.utils.fromJSON(item.data)
-- should we cancel our transition ?
if(eventData.duration <= 0) then return end
-- compute number of steps
local colorCount = 0
for i, color in ipairs(eventData.colors) do
colorCount = colorCount + 1
end
-- setting color and state
-- enum devices and choose state based on step number
for i, deviceId in ipairs(eventData.devices) do
deviceId = tonumber(deviceId)
if(eventData.step >= colorCount) then eventData.step = 0 end
local colorIndex = i + eventData.step
if(colorIndex > colorCount) then colorIndex = colorIndex - colorCount end
if(eventData.colors[colorIndex].br == 0)then
-- turning off
domoticz.devices(deviceId).switchOff()
elseif(eventData.colors[colorIndex].m) then
-- set color if device is capable of color
if(domoticz.devices(deviceId).deviceType == 'Color Switch') then
domoticz.devices(deviceId).setColor(eventData.colors[colorIndex].r,eventData.colors[colorIndex].g,eventData.colors[colorIndex].b,
eventData.colors[colorIndex].br,
eventData.colors[colorIndex].cw,eventData.colors[colorIndex].ww,
eventData.colors[colorIndex].m,eventData.colors[colorIndex].t)
else
-- at least set brightness or turn the device on...
if(domoticz.devices(deviceId).switchType =='Dimmer') then
domoticz.devices(deviceId).Level = eventData.colors[colorIndex].br
else
domoticz.devices(deviceId).switchOn()
end
end
else
-- set level / turning on
if(domoticz.devices(deviceId).switchType =='Dimmer') then
domoticz.devices(deviceId).Level = eventData.colors[colorIndex].br
else
domoticz.devices(deviceId).switchOn()
end
end
end
-- schedule next transition
domoticz.emitEvent('switchState', { ['devices'] = eventData.devices, ['colors'] = eventData.colors, ['step'] = eventData.step + 1, ['delay'] = eventData.delay, ['duration'] = eventData.duration - eventData.delay }).afterSec(eventData.delay)
end
-- CHANGEMENT DE SCENE
if (item.isCustomEvent and item.trigger == 'sceneChangeState') then
-- Get JSON in event data
local eventData = domoticz.utils.fromJSON(item.data)
-- should we cancel our transition ?
if(eventData.duration <= 0) then return end
-- compute number of steps
local sceneCount = 0
for i, scene in ipairs(eventData.scenes) do
sceneCount = sceneCount + 1
end
-- selecting scene to apply / group to turn on
if(eventData.step >= sceneCount) then eventData.step = 0 end
local sceneIndex = 1 + eventData.step
if(sceneIndex > sceneCount) then sceneIndex = sceneIndex - sceneCount end
-- applying
if(domoticz.utils.sceneExists(eventData.scenes[sceneIndex])) then
domoticz.scenes(eventData.scenes[sceneIndex]).switchOn()
elseif(domoticz.utils.groupExists(eventData.scenes[sceneIndex])) then
domoticz.groups(eventData.scenes[sceneIndex]).switchOn()
end
-- schedule next transition
domoticz.emitEvent('sceneChangeState', { ['scenes'] = eventData.scenes, ['step'] = eventData.step + 1, ['delay'] = eventData.delay, ['duration'] = eventData.duration - eventData.delay }).afterSec(eventData.delay)
end
end
}
domoticz.helpers.transitionTo(domoticz, device, color, duration)
Transition a light to a new color over time. The light will fade from its current state to the new color. You can choose the duration of the transition (in seconds). Color is in the usual format { ['r']=0, ['g']=0, ['b']=0, ['br']=0, ['cw']=0, ['ww']=0, ['t']=0, ['m']=1/2/3/4 }.
You can do a transition to off also by using a black color or a brightness of 0.
domoticz.helpers.blink(domoticz, device, color1, color2, speed, duration)
Make a light blink. You can alternate between two colors with the speed and duration of your choice. If one color is black or brightness is zero, means the lamp will turn off. There is no smooth transition between colors.
domoticz.helpers.animateGroup(domoticz, group, speed, duration)
swap the colors of each light in a group scenes. You can choose the speed and duration of the effect
domoticz.helpers.animateScenes(domoticz, scenes, speed, duration)
alternate scenes : change a scene each xx sec. Again you can choose speed and duration
domoticz.helpers.cancelTransition(domoticz, device)
cancel a running transition for a device. It currently works only for blink and transitionTo.