I have a virtual switch device (defined by SCHEDULE_DEVICE) that I have put a schedule on. When that device turns on, dimming up will start and vice versa.
I have a Fibaro RGBW controller to which I have connected 4 bluewhite LED Strips. The Domoticz Devices are named '375L LED Strip 1'...'375L LED Strip 4'
The script supports multiple RGBW controllers. In this script, the LED Strips must have device names in the following form: 'XXX LED Strip n' where XXX can be any string of your choice and n is number 1 to 4.
Even at the minimum dimming level set to 1, it's quite bright in the aquarium if all 4 led strips are lit. Therefore, to allow darker the script can handle to turn of the strips one by one.
The script tries to calculate the brightness of the LED Strips linearly to Human eye (or the fish eye???)
Code: Select all
--[[
aquariumLights.lua by BakSeeDaa
Version 1.0.1
--]]
local logPre = 'aquariumLights '
local SCHEDULE_DEVICE = 'schAquariumLights'
-- First part of the aquarium lights device names you've used in your system
-- Second part should be ' LED Strip n' where n is 1 to 4.
-- E.g. First LED strip full device name is '375L LED Strip 1'
local aquaLights = {'375L'} -- Array, You can put multiple RGBW devices here
local DIMMER_MIN_LEVEL = 1
local DIMMER_MAX_LEVEL = 22
local DIMMING_DURATION = 45 -- Minutes
return {
active = true,
on = {
SCHEDULE_DEVICE,
['timer'] = 'every minute',
},
data = {
dimmingInProgress = {history = true, maxItems = 1},
lastSentDimLevel = {initial = 0}
},
execute = function(domoticz, device, triggerInfo)
local LOG_LEVEL = domoticz.LOG_ERROR -- Script default log level. You may change this.
local pDimmingInProgress = domoticz.data.dimmingInProgress
function sendLEDCommand(ledName, newVal)
local curval = tonumber(domoticz.devices[ledName].rawData[1])
if (newVal ~= curval) then
domoticz.devices[ledName].dimTo(newVal)
domoticz.log(logPre..'Setting '..ledName..' to value '..newVal..'. Old value was: '..curval, LOG_LEVEL)
end
end
function setAquaLight(ledName, ledBrightness, dimStage, belowMinDimLevel)
local testValue, decimal
testValue, decimal = math.modf(belowMinDimLevel/4+0.5)
if (dimStage <= 0) then
for i=1,4 do sendLEDCommand(ledName..' LED Strip '..i, 0) end
elseif (dimStage <= testValue) then
for i=1,1 do sendLEDCommand(ledName..' LED Strip '..i, DIMMER_MIN_LEVEL) end
for i=2,4 do sendLEDCommand(ledName..' LED Strip '..i, 0) end
elseif (dimStage <= testValue * 2) then
for i=1,2 do sendLEDCommand(ledName..' LED Strip '..i, DIMMER_MIN_LEVEL) end
for i=3,4 do sendLEDCommand(ledName..' LED Strip '..i, 0) end
elseif (dimStage <= testValue * 3) then
for i=1,3 do sendLEDCommand(ledName..' LED Strip '..i, DIMMER_MIN_LEVEL) end
for i=4,4 do sendLEDCommand(ledName..' LED Strip '..i, 0) end
elseif (dimStage <= belowMinDimLevel) then
for i=1,4 do sendLEDCommand(ledName..' LED Strip '..i, DIMMER_MIN_LEVEL) end
else
for i=1,4 do sendLEDCommand(ledName..' LED Strip '..i, ledBrightness) end
end
end
-- DEVICE TYPE EVENTS
if triggerInfo.type == domoticz.EVENT_TYPE_DEVICE then
if device.name == SCHEDULE_DEVICE then
pDimmingInProgress.add(true)
if device.state == 'On' then
domoticz.log(logPre..'Time for aquarium inhabitants to wake up', LOG_LEVEL)
elseif device.state == 'Off' then
domoticz.log(logPre..'Time for aquarium inhabitants to sleep', LOG_LEVEL)
pDimmingInProgress.add(true)
end
end
-- TIMER TYPE EVENTS
elseif triggerInfo.type == domoticz.EVENT_TYPE_TIMER then
-- Init data if missing (e.g. the first time that the scripts runs after boot)
if (pDimmingInProgress.size == 0) then pDimmingInProgress.add(false) end
local itemDimmingInProgress = pDimmingInProgress.getLatest()
if not itemDimmingInProgress.data then domoticz.log(logPre..'Not dimming', LOG_LEVEL) end
if itemDimmingInProgress.data then
local dimmingDirection = (domoticz.devices[SCHEDULE_DEVICE].state == 'On' and 'up' or 'down')
-- dimStage varying from 0-100 (or 100-0) is calculated based on how long time it was since dimming started
local dimStage = (itemDimmingInProgress.time.minutesAgo/DIMMING_DURATION) * 100
if dimmingDirection == 'down' then
dimStage = 100 - (itemDimmingInProgress.time.minutesAgo/DIMMING_DURATION) * 100
end
local incr_step = 100/DIMMING_DURATION
dimStage = (dimmingDirection == 'up' and (dimStage + incr_step) or (dimStage - incr_step))
dimStage = math.floor(dimStage+.5) -- Make it an integer ...
domoticz.log(logPre..'Internal dimStage counter: '..dimStage..'. Currently dimming '..dimmingDirection..'.', LOG_LEVEL)
-- Calculate brightness of LED linearly to Human eye, take into account the maximum dimmer level
local newDimmerLevel, decimal
newDimmerLevel, decimal = math.modf(((math.floor((math.pow(dimStage, 2)/100) +0.5)) * (DIMMER_MAX_LEVEL/100))+0.5)
-- Normally all LED Strips will be set to the same dim level.
-- Find out at what dimStage the perceived light reaches above the value specified in DIMMER_MIN_LEVEL
-- When that occurs, some LED Strips will be turned off individually.
local i, testValue, belowMinDimLevel
for i = 1, 100 do
testValue, decimal = math.modf(((math.floor((math.pow(i, 2)/100) +0.5)) * (DIMMER_MAX_LEVEL/100))+0.5)
if (testValue > DIMMER_MIN_LEVEL) then
belowMinDimLevel = i-1
break
end
end
local lastSentDimLevel = domoticz.data.lastSentDimLevel -- The last set dim level, used to avoid setting the same value twice
domoticz.log(logPre..'\n\ndimStage: '..dimStage..'\ndimmingDirection: '..dimmingDirection..'\nlastSentDimLevel: '..lastSentDimLevel..'\nnewDimmerLevel: '..newDimmerLevel..'\n\n', LOG_LEVEL)
if ((newDimmerLevel ~= lastSentDimLevel) or (dimStage <= belowMinDimLevel)) then
domoticz.log(logPre..'\nSetting a new value\n', LOG_LEVEL)
domoticz.data.lastSentDimLevel = newDimmerLevel
for k, v in pairs(aquaLights) do setAquaLight(v, newDimmerLevel, dimStage, belowMinDimLevel) end
end
if (dimStage <= 0 or dimStage >= 100) then
pDimmingInProgress.add(false)
end
end
end
end
}