If somebody is interested, I've managed to convert Humidity control script from
https://www.domoticz.com/wiki/Humidity_control. Thanks to dannybloe for nice script!
Code: Select all
--[[
This script controls the humidity in a typical bathroom setting by detecting
relative rises in humidity in a short period.
Of course it requires a humidity sensor and a binary switch controlling a fan/ventilator.
(there is no provision for variable speed ventilators here!)
How it works (assuming the default constants as defined below):
Every 5 minutes a reading is done. Every reading is stored together
with the previous reading and is stored in two user variables (humidityTmin5 and humidityTmin10).
So it has two reading over the past 10 minutes.
It then takes the lowest of the two and compares it with the latest reading and
calculates a delta.
If the delta is 3 or higher (see constants) then the fan will be turned
on, it calculates the target humidity and the 'humidity-decrease program' is started (fanFollowsProgram=1).
From then on, every 5 minutes the current humidity is compared to the
stored target humidity. Basically if that target is reached, the fan is turned off
and the 'program' is ended.
Of course, it is possible that the target is never reached (might start raining outside
or whatever). Then there is a failsafe (FANMAXTIME) after which the ventilator
will be turned off.
Also, it will detect if the ventilator is manually switched off during a program
or when it is switched on before the program starts.
Along the lines it prints to the log and sends notifications
but of course you can turn that off by removing those lines.
--]]
return {
active = true, -- set to true to activate this script
on = {
['timer'] = 'every minute',
},
execute = function(domoticz)
-- declare some constants
-- adjust to your specific situation
local SAMPLEINTERVAL = 3 -- time in minutes when a the script logic will happen
local FANDELTATRIGGER = 5 -- rise in humidity that will trigger the fan
local FANMAXTIME = 24 -- maximum amount of sample cycles the fan can be on,
-- in case we never reach the target humidity
local TARGETOFFSET = 10 -- ventilator goes off if target+offset is reached
-- (maybe it takes too long to reach the true target due to wet towels etc)
local FANNAME = 'V_Fan' -- exact device name of the switch turning on/off the ventilator
local SENSORNAME = 'bathroom' -- exact device name of the humidity sensor
local TESTMODE = false -- when true TESTMODEHUMVAR is used instead of the real sensor
local TESTMODEHUMVAR = 'testHumidity' -- fake humidity value, give it a test value in domoticz/uservars
local PRINTMODE = true -- when true wil print output to log and send notifications
if PRINTMODE == true then
domoticz.log('Fan control', domoticz.LOG_INFO)
end
-- get the global variables:
-- this script runs every minute, humCounter is used to create SAMPLEINTERVAL periods
local humCounter = domoticz.variables['humCounter'].nValue
local humidityTmin5 = domoticz.variables['humidityTmin5'].nValue -- youngest reading
local humidityTmin10 = domoticz.variables['humidityTmin10'].nValue -- oldest reading
local targetFanOffHumidity = domoticz.variables['targetFanOffHumidity'].nValue -- target humidity
local fanMaxTimer = domoticz.variables['fanMaxTimer'].nValue
local fanFollowsProgram = domoticz.variables['fanFollowsProgram'].nValue -- marker indicating that the
-- decrease program is started
local target = 0 -- will hold the target humidity when the program starts
-- get the current humidity value
if (TESTMODE) then
current = domoticz.variables[TESTMODEHUMVAR].nValue
else
current = domoticz.devices[SENSORNAME].humidity
end
-- check if the sensor is on or has some weird reading
if (current == 0 or current == nil) then
domoticz.log('current is 0 or nil. Skipping this reading', domoticz.LOG_ERROR)
return
end
if PRINTMODE == true then
domoticz.log('Current humidity:' .. current, domoticz.LOG_INFO)
domoticz.log('targetFanOffHumidity:' .. targetFanOffHumidity, domoticz.LOG_INFO)
domoticz.log('humidityTmin5: ' .. humidityTmin5, domoticz.LOG_INFO)
domoticz.log('humidityTmin10: ' .. humidityTmin10, domoticz.LOG_INFO)
domoticz.log('fanMaxTimer: ' .. fanMaxTimer, domoticz.LOG_INFO)
domoticz.log('humCounter:' .. humCounter, domoticz.LOG_INFO)
domoticz.log('fanFollowsProgram:' .. fanFollowsProgram, domoticz.LOG_INFO)
end
-- increase cycle counter
humCounter = humCounter + 1
if (humCounter >= SAMPLEINTERVAL) then
if (humidityTmin5 == 0) then
-- initialization, assume this is the first time
humidityTmin5 = current
humidityTmin10 = current
end
humCounter = 0 -- reset the cycle counter
-- pick the lowest history value to calculate the delta
-- this also makes sure that two relative small deltas in the past 2*interval minutes are treated as one larger rise
-- and therefore will still trigger the ventilator
-- I don't want to use a longer interval instead because I want the ventilator to start as soon as possible
-- (so rather after 5 minutes instead of after 15 minutes because the mirrors in the bathroom become kinda useless ;-)
delta = current - math.min(humidityTmin10, humidityTmin5)
if PRINTMODE == true then
domoticz.log('Delta: ' .. delta, domoticz.LOG_INFO)
end
-- pick the lowest history value
target = math.min(humidityTmin10, humidityTmin5) + TARGETOFFSET
-- shift the previous measurements
humidityTmin10 = humidityTmin5
-- and store the current
humidityTmin5 = current
if (domoticz.devices[FANNAME].state=='Off' or (domoticz.devices[FANNAME].state=='On' and fanFollowsProgram==0)) then
-- either the fan is off or it is on but the decrease program has not started
-- in that latter case we start the program anyway. This could happen if someone turns on the ventilator
-- manually because he/she is about to take a shower and doesn't like damp mirrors.
-- I don't do this because the ventilator removes heat from the bathroom and I want this to happen
-- as late as possible ;-)
if (fanFollowsProgram == 1 and domoticz.devices[FANNAME].state=='Off') then
-- likely someone turned off the ventilator while the program was running
fanFollowsProgram = 0
end
-- see if we have to turn it on
if (delta >= FANDELTATRIGGER) then
-- time to start the fan
domoticz.devices[FANNAME].setState('On')
targetFanOffHumidity = target
if (fanFollowsProgram == 1) then
domoticz.log('Ventilator was already on but we start the de-humidifying program', domoticz.LOG_INFO)
end
fanFollowsProgram = 1
-- set the safety stop
fanMaxTimer = FANMAXTIME
if PRINTMODE == true then
domoticz.log('Rise in humidity. Turning on the vents. Delta: ' .. delta, domoticz.LOG_INFO)
domoticz.log('Target humidity for turning the ventilator: ' ..targetFanOffHumidity, domoticz.LOG_INFO)
domoticz.log('Ventilator is on#The ventilator was activated at humidity level ' .. current .. '#0', domoticz.LOG_INFO)
end
end
else
if (fanMaxTimer > 0) then
-- possible that someone started the ventialator manually
fanMaxTimer = fanMaxTimer - 1
end
if (fanFollowsProgram == 1) then -- not manually started
if (delta >= FANDELTATRIGGER) then
-- ok, there is another FANDELTATRIGGER rise in humidity
-- when this happen we reset the fanMaxTimer to a new count down
-- because we have to ventilate a bit longer due to the extra humidity
if PRINTMODE == true then
domoticz.log('Another large increase detected, resetting max timer. Delta: ' .. delta, domoticz.LOG_INFO)
end
fanMaxTimer = FANMAXTIME
end
-- first see if it can be turned off
if (current <= targetFanOffHumidity or fanMaxTimer==0) then
domoticz.devices[FANNAME].setState('Off')
local msg = ''
if (fanMaxTimer == 0 and current > targetFanOffHumidity) then
msg = 'Target not reached but safety time-out is triggered.'
if PRINTMODE == true then
domoticz.log(msg, domoticz.LOG_INFO)
end
else
msg = 'Target humidity reached'
if PRINTMODE == true then
domoticz.log(msg, domoticz.LOG_INFO)
end
end
if PRINTMODE == true then
domoticz.log('Turning off the ventilator', domoticz.LOG_INFO)
msg = msg .. '\nTurning off the ventilator'
end
targetFanOffHumidity = 0
fanMaxTimer = 0
fanFollowsProgram = 0
-- reset history in this case.. we start all over
-- Tmin10 is still in the 'ventilator=On'-zone
humidityTmin10 = humidityTmin5
if PRINTMODE == true then
domoticz.log('Ventilator is off#' .. msg .. '#0', domoticz.LOG_INFO)
end
else
-- we haven't reached the target yet
if PRINTMODE == true then
domoticz.log('Humidity delta: ' .. delta, domoticz.LOG_INFO)
end
end
end
end
if PRINTMODE == true then
domoticz.log('New values >>>>>>>>>>>', domoticz.LOG_INFO)
domoticz.log('humidityTmin5: ' .. humidityTmin5, domoticz.LOG_INFO)
domoticz.log('humidityTmin10: ' .. humidityTmin10, domoticz.LOG_INFO)
domoticz.log('fanMaxTimer: ' .. fanMaxTimer, domoticz.LOG_INFO)
domoticz.log('humCounter:' .. humCounter, domoticz.LOG_INFO)
domoticz.log('fanFollowsProgram:' .. fanFollowsProgram, domoticz.LOG_INFO)
domoticz.log('------ target: ' .. targetFanOffHumidity, domoticz.LOG_INFO)
end
end
-- save the globals
domoticz.variables['humCounter'].set(humCounter)
domoticz.variables['humidityTmin10'].set(humidityTmin10)
domoticz.variables['humidityTmin5'].set(humidityTmin5)
domoticz.variables['targetFanOffHumidity'].set(targetFanOffHumidity)
domoticz.variables['fanMaxTimer'].set(fanMaxTimer)
domoticz.variables['fanFollowsProgram'].set(fanFollowsProgram)
end
}
All variables in script declared as local except variable
current. Then
current is declared as local it's value become 0 in following check:
Code: Select all
-- check if the sensor is on or has some weird reading
if (current == 0 or current == nil) then
domoticz.log('current is 0 or nil. Skipping this reading', domoticz.LOG_ERROR)
return
end
Otherwise it's working as it should. Looks very strange for me.
Also I'm not using notifications in the script, so I've changed all
print statements to
domoticz.log
I wanted to have possibility to override Fan switch from humidity script and for that I have another script:
Code: Select all
--[[
This script controls ventilation logic.
--]]
return {
active = true, -- set to true to activate this script
on = {
'Fan',
'Ventilation_Force',
'Ventilation_Off',
'V_Fan',
'timer'
},
execute = function(domoticz, mySwitch)
if (domoticz.devices['Fan'].state =='Off' and domoticz.devices['Ventilation_Force'].state =='On' and domoticz.devices['Ventilation_Off'].state =='On' and domoticz.devices['V_Fan'].state =='On') then domoticz.devices['Fan'].switchOn()
elseif (domoticz.devices['Fan'].state =='On' and domoticz.devices['Ventilation_Force'].state =='On' and domoticz.devices['Ventilation_Off'].state =='On' and domoticz.devices['V_Fan'].state =='Off') then domoticz.devices['Fan'].switchOff()
elseif (domoticz.devices['Fan'].state =='On' and domoticz.devices['Ventilation_Force'].state =='On' and domoticz.devices['Ventilation_Off'].state =='Off' and domoticz.devices['V_Fan'].state =='On') then domoticz.devices['Fan'].switchOff()
elseif (domoticz.devices['Fan'].state =='Off' and domoticz.devices['Ventilation_Force'].state =='Off' and domoticz.devices['Ventilation_Off'].state =='On' and domoticz.devices['V_Fan'].state =='Off') then domoticz.devices['Fan'].switchOn()
elseif (domoticz.devices['Fan'].state =='On' and domoticz.devices['Ventilation_Force'].state =='Off' and domoticz.devices['Ventilation_Off'].state =='On' and domoticz.devices['V_Fan'].state =='On') then domoticz.devices['Fan'].switchOn()
end
if(domoticz.devices['V_Fan'].lastUpdate.minutesAgo>50) and domoticz.devices['V_Fan'].state =='Off' then
domoticz.devices['V_Fan'].switchOn().for_min(10)
end
end
}
In this script
Fan is switch controlling fan, V_fan - virtual switch from humidity script, Ventilation_Force and Ventilation_Off - switches to force ventilation and to disable it completely.
Also in this script fan is switched on for 10 min every 50 min after last 'On' state to refresh air.