My dzVents Bathroom Humidity Control script

User avatar
BakSeeDaa
Posts: 434
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi
Domoticz version: beta
Contact:

My dzVents Bathroom Humidity Control script

Post by BakSeeDaa » Wednesday 22 March 2017 15:57

Below is my dzVents Bathroom Humidity Control script version 1.3.1
EDIT: Now modified to work with dzVents version 2.0.0 and higher

I've been inspired by this script: Lua script for controlling humidity in the bathroom and I got some design tips from @dannybloe.

My house has a single fan that extracts air from all the rooms in the house. I can force that single fan to work at a higher speed in case of that the humidity in one of my bathrooms rises quickly. My script currently supports only a single fan but multiple humidity sensors. The script also supports a button that can be pushed manually in case that the air quality in the bathroom requires that. I may improve my script and update this first post if I get any suggestions for improvements from you guys. Please feel free to suggest improvements etc.

Here it goes:

Code: Select all

--[[
bathroomHumControl.lua by BakSeeDaa
Version 1.3.1
	This script controls the humidity in a typical bathroom setting by detecting
	relative rises in humidity in a short period.
--]]

local FAN_DEVICE = 'Nibe F750 Force Fan' -- Fan device
local FORCE_FAN_DEVICE = 'Flatulence Button' -- (Optional)
local FORCE_FAN_TIME = 10 -- Minutes to force the fan when button pushed
local HUMIDITY_SENSORS =  {'Badrum 1 C+RH', 'Badrum 2 C+RH'}
local FAN_DELTA_TRIGGER = 3 -- % Rise in humidity that will trigger the fan
local FAN_MAX_TIME = 24 -- Maximum minutes that the fan can be on in case we never reach the target humidity
local TARGET_OFFSET = 2 -- Fan goes off if target + offset is reached
local TEST_MODE_HUMIDITY_READING = 0 -- Set to a value between 1 and 100. Set to 0 to disable test mode
local READING_SAMPLES = 15

-- Create the data declarations
local data = {}
for i, device in pairs(HUMIDITY_SENSORS) do
	data[device] = {history = true, maxItems = READING_SAMPLES + 1}
	data['dehumidProgramActive'..i] = {history = true, maxItems = 1} -- Need history to get time stamp
	data['forceFan'] = {history = true, maxItems = 1} -- Need history to get time stamp
	data['targetHum'..i] = {initial=0}
end

return {
	active = true,
	logging = {
		--level = domoticz.LOG_DEBUG, -- Select one of LOG_DEBUG, LOG_INFO, LOG_ERROR, LOG_FORCE to override system log level
		marker = "bathRoom"
	},
	on = {
		devices = {
			FORCE_FAN_DEVICE
		},
		timer = {
			'every 1 minutes'
		}
	},
	data = data,
	execute = function(domoticz, device, triggerInfo)
		local forceFanReadings = domoticz.data.forceFan

		if (triggerInfo.type == domoticz.EVENT_TYPE_TIMER) then
			local fanCmd = 'Off'
			for i = 1, #HUMIDITY_SENSORS do
				local humidityReadings = domoticz.data[HUMIDITY_SENSORS[i]]
				-- Store the read value in the persistant data
				for j = 1, (humidityReadings.size == 0 and READING_SAMPLES + 1 or 1) do
					humidityReadings.add((TEST_MODE_HUMIDITY_READING == 0
						and domoticz.devices(HUMIDITY_SENSORS[i]).humidity or TEST_MODE_HUMIDITY_READING))
				end

				-- INIT
				local programActiveReadings = domoticz.data['dehumidProgramActive'..i]
				if (programActiveReadings.size == 0) then
					domoticz.log('programActiveReadings, Initialization was needed', domoticz.LOG_INFO)
					programActiveReadings.add(false)
				end
				local targetHum = domoticz.data['targetHum'..i]
				if (targetHum == nil) then
					domoticz.log('targetHum'..i..', Initialization was needed', domoticz.LOG_INFO)
					domoticz.data['targetHum'..i] = 0
					targetHum = 0
				end
				if (forceFanReadings.size == 0) then
					domoticz.log('forceFanReadings, Initialization was needed', domoticz.LOG_INFO)
					forceFanReadings.add('Init')
				end

				local programActiveState = programActiveReadings.getLatest()
				if (programActiveState.data) then -- The fan control program is active
					-- Has the fan control program timed out or have we reached the target humidity?
					local maxTime = (programActiveState.time.minutesAgo > FAN_MAX_TIME)
					local targetHumReached = (humidityReadings.getLatest().data <= targetHum)
					if (maxTime or targetHumReached) then
						domoticz.log('Dehumidification program stops for: '..HUMIDITY_SENSORS[i], domoticz.LOG_INFO)
						domoticz.log('Reason(s): '..(maxTime and 'Max time. ' or '')..(targetHumReached and 'Target humidity reached.' or ''), domoticz.LOG_INFO)
						programActiveReadings.add(false)
						programActiveState = programActiveReadings.getLatest()
					else
						domoticz.log('Dehumidification program is active for: '..HUMIDITY_SENSORS[i], domoticz.LOG_INFO)
						fanCmd = 'On'
					end
				else -- The fan is currently not running under the control of this program
					-- Has there been a significant rise in humidity lately?
					local humDelta = humidityReadings.getLatest().data - humidityReadings.min(2, READING_SAMPLES + 1)
					-- Calculate a target humidity but never try to push humidity below 40
					targetHum = math.max(humidityReadings.min(2, READING_SAMPLES + 1) + TARGET_OFFSET, 40)
					if (humDelta > FAN_DELTA_TRIGGER and humidityReadings.getLatest().data > targetHum) then
						domoticz.data['targetHum'..i] = targetHum
						programActiveReadings.add(true)
						programActiveState = programActiveReadings.getLatest()
						fanCmd = 'On'
						domoticz.log('Dehumidification program starts as a respond to: '..HUMIDITY_SENSORS[i], domoticz.LOG_INFO)
					else
						domoticz.log('Dehumidification program doesn\'t run  for: '..HUMIDITY_SENSORS[i], domoticz.LOG_INFO)
					end
					domoticz.log('targetHum: '..targetHum..', Current humidity: '..humidityReadings.getLatest().data..', humDelta: '..humDelta, domoticz.LOG_INFO)
				end
			end

			if ((forceFanReadings.getLatest().time.minutesAgo < FORCE_FAN_TIME)
			and (forceFanReadings.getLatest().data == 'On')) then fanCmd = 'On' end

			if (domoticz.devices(FAN_DEVICE).state ~= fanCmd) then
				domoticz.log('Turning the fan '..fanCmd, domoticz.LOG_INFO)
				domoticz.devices(FAN_DEVICE).toggleSwitch()
			end
		else
			-- The script gets executed due to a device-change event
			if (device.name == FORCE_FAN_DEVICE and device.state == 'On') then
				forceFanReadings.add('On')
				domoticz.log('The fan has been forced on for '..FORCE_FAN_TIME..'minutes.', domoticz.LOG_INFO)
				-- domoticz.helpers.speak(domoticz, 'joke sting')
				if (domoticz.devices(FAN_DEVICE).state ~= 'On') then domoticz.devices(FAN_DEVICE).switchOn() end
			end
		end

	end
}
Change log and release notices

Version 1.3.1.
  • Corrected an issue where the force button made the script run a faulty number of minutes.
Last edited by BakSeeDaa on Thursday 07 September 2017 15:35, edited 5 times in total.
Best wishes

// บักสีดา

User avatar
remb0
Posts: 811
Joined: Thursday 11 July 2013 22:21
Target OS: Raspberry Pi
Domoticz version: Beta
Location: The Netherlands
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by remb0 » Wednesday 22 March 2017 19:48

Hi BakseeDaa,
nice work!

I wanted to use your script because it's a lot cleaner, then my script.
But it's not easy to use in my case.. (and with my skills)
Some points i'm struggling with, and point you can maybe use:

-I use a virtual selector with 4 states. 3 speed modes and a max modus for 10 minute (this are the buttons of my remote)
this makes it more complicated because my fan is never off, but must go back to fanspeed 1
-the rise in hum is very nice.. But I also use: a temperature sensor that detects rising temperatures on a warm water pipe and when more then x min + somebody is home I am probably showering :P
- variables from the user variables, but with the new editor it is not needed anymore because it makes it a little bit more complicated
- a function for printing, logging to a csv so I can check in excel after a week when the script worked and how and why)





my script (also with components of others)

Code: Select all

--[[ 
....
]]--
--------------------------------------------------------------------------------
Script		  = 'Ventilatie'	
Version       = 1				
VersionLog	  = 1
Man_or_Auto   = 'Auto'		-- Default
package.path = package.path .. ';' .. '/home/pi/domoticz/scripts/lua/?.lua'
My = require('MyFunc')
------- Functions--------------------------------------------------------------------------
function SendANotification()
	commandArray['SendNotification']='Ventilatie ' .. Stand .. '#Ventilatie  was in state ' .. Stand .. ' new state is ' .. NewState .. ', reason for change is ' .. My.EnumClear(Reason) .. ' / '.. os.date("%Y-%m-%d;%H:%M:%S").. '#0#pushover'
end

function LogActions()
	LogFile=string.gsub(LogFile,"~d",os.date("%Y-%m-%d"))
	LogFile=string.gsub(LogFile,"~m",os.date("%Y-%m"))
	if not My.File_exists(LogFile) then
	 f=io.open(LogFile,"a")
	 f:write("Datum ; Tijd ; Man_or_Auto ; Stand ;  Reason  ; HumidityTmin10; HumidityTmin5; HumDelta; LeidingTmin10; LeidingTmin5; LeidingDelta; FanRuntime; FanAanVoor; target")
     f:write("\r\n")
	 else
	 f=io.open(LogFile,"r")
	 c=f:read("*line")
	 f:close()
	 f=io.open(LogFile,"a")
   end
    f:write(os.date("%Y-%m-%d;%H:%M:%S") .. ";" .. Man_or_Auto .. ";" .. Stand .. ";" .. My.EnumClear(Reason) ..  ";"  .. HumidityTmin10 .. ";" .. HumidityTmin5 .. ";" .. HumDelta .. ";" .. LeidingTmin10 .. ";" .. LeidingTmin5 .. ";" .. LeidingDelta .. ";" .. FanRuntime .. ";" .. FanAanVoor .. ";" .. target)
    f:write("\r\n")
    f:close()
end

-- Functions
function Debug_msg (msg)
    if (Debug == 'Y') then print('>> Fan: '.. msg)     end
end

commandArray= {} -- default variables

	UserVarErr      = 0
	Reason          ="" 
	LogFile        	= My.GetUserVar("FAN_LogFile")			-- /home/pi/domoticz/log/FAN.csv
	ShAfterAction  = My.GetUserVar("FAN_ShAfterAction")		-- sudo /home/pi/domoticz/scripts/bash/log-dropbox.sh
-- debugging
	Debug	      	= 'Y'		-- 'Y'  show prints Y of N
	LogAction      	= My.GetUserVar("FAN_LogAction")		-- 'A' 	A=All, Y=Only on change

-- offsets
	target_OFFSET 			= 3   -- ventilator goes off if target + offset is reached 
	FAN_HumDelta_TRIGGER 	= 5   -- rise in humidity needed for a bath that will trigger the fan
	targetOffHumidity 		= tonumber(uservariables['Fan_TargetOffHumidity']) + 0   -- target humidity (72)
	WarmWaterTriggerTemp 	= tonumber(57) --42 temperature of hotwater pipe where fan should start running
	WarmWaterLowerTrigger 	= tonumber(52) --33 temperature of hotwater pipe where fan should STOP running

-- Devices
	IemandThuis		= otherdevices['Iemand_thuis'] 
	
	Fan	   	        = otherdevices['Fan'] 	
	LastChange_fan 	= otherdevices_lastupdate["Fan"]
	Stand 			= tonumber(otherdevices_svalues['Fan'])/10  --Stand4 = otherdevices['Fan_4']  dit is een tijdelijke Stand 10 minuten maximaal
	
	Badkamer	   	= My.GetUserVar("FAN_HumBadkamer")		-- 18.4 C, 73 %	 Hum is on position 2
	warmwater	   	= My.GetUserVar("FAN_Warmwater")
	WaterleidingTemp= My.Round(tonumber(My.GetValue(otherdevices_svalues[warmwater],1)))
	   
-- cycle instellingen  (allemaal type=integer, value=0)
	Fan_CycleInterval 	= 3   -- time in minutes when the script logic will happen	
	Counter 	= tonumber(uservariables['Fan_Counter'])+ 0 			

	HumidityTmin5 	= tonumber(uservariables['Fan_HumidityTmin5'])    -- youngest reading
	LeidingTmin5	= tonumber(uservariables['Fan_LeidingTmin5'])  
	HumidityTmin10	= tonumber(uservariables['Fan_HumidityTmin10'])    -- oldest reading
	LeidingTmin10	= tonumber(uservariables['Fan_LeidingTmin10'])              
	
	FanMaxRuntime 	= 10
	FanRuntime      = tonumber(uservariables['Fan_MaxRuntime'])	--10 maximum amount of sample cycles the fan can be on, in case we never reach target humidity
	FanAanVoor 		= My.Round(My.TimeDiff(os.time(),LastChange_fan)/60,0)
	target 			= 0 -- will hold the target humidity when the program starts

	-- als het if blok niet draait en er toch gelogd wordt
	HumDelta = 0 
	LeidingDelta = 0
	
	-- foutafhandeling
    if UserVarErr> 0 then 	Debug_msg(".  Please check user variables for ".. Script .. " script.") end
    if UserVarErr> 0 then goto done end

	
 -- get the CurrentHum humidity value and check if the sensor is on or has some weird reading
	CurrentHum = otherdevices_humidity[Badkamer] 
	CurrentLeiding = tonumber(WaterleidingTemp)
    if (CurrentHum == 0 or CurrentHum == nil) then print('CurrentHum is 0 or nil. Skipping this reading') return commandArray end
    if (CurrentLeiding == 0 or CurrentLeiding == nil) then print('CurrentLeiding is 0 or nil. Skipping this reading') return commandArray end
 
	Debug_msg("______________________________________________________________________")
	Debug_msg(">> ".. Script .. ".......v" .. Version .. "...Debug = " .. Debug .. ' Run:' .. Counter .. '/' .. Fan_CycleInterval)

-- Checks  en berekeningen die altijd worden uitgevoerd.
--	if (timeofday['Daytime'])   			then Res_Dayl=1   			else Res_Dayl=0 Reason=Reason .. "buiten dagtijd, " end
	if HumDelta 		> FAN_HumDelta_TRIGGER then Res_Hum_Badkamer=1   	Reason=Reason .. "Badkamer vochtig: " .. HumidityTmin5 .. " ,"	else Res_Hum_Badkamer=0  end
	if LeidingTmin10 	> WarmWaterTriggerTemp and LeidingTmin5 > WarmWaterTriggerTemp  	then Res_Leiding=1   Reason=Reason .. "Leiding is warm: " .. WaterleidingTemp .. " ,"	else Res_Leiding=0  end

     -- pick the lowest history value
    HumDelta 	 = tonumber(CurrentHum -     math.min(HumidityTmin10, HumidityTmin5))
	LeidingDelta = tonumber(CurrentLeiding - math.min(LeidingTmin10,  LeidingTmin5))
	target = math.min(HumidityTmin10, HumidityTmin5) + target_OFFSET
    -- shift the previous measurements and store the CurrentHum
    HumidityTmin10 	= HumidityTmin5
    HumidityTmin5 	= CurrentHum
	LeidingTmin10 	= LeidingTmin5
    LeidingTmin5 	= CurrentLeiding

---LOGICA START, increase cycle Counter
Counter = Counter + 1
FanRuntime = FanRuntime +1 

if (Counter >= Fan_CycleInterval) then
	if (Stand == 0) then print('Fan is manueel, er wordt niets gedaan.') goto done end
    if ((HumidityTmin5 == 0) or (LeidingTmin5 == 0)) then -- initialization, assume this is the first time
        HumidityTmin5 = CurrentHum        HumidityTmin10 = CurrentHum		LeidingTmin5 = CurrentLeiding	LeidingTmin10 = CurrentLeiding
    end
    
    Counter = 0 -- reset the cycle Counter. gaat alleen draaien als hij fan_cycleintervan haalt en mag daarna weer opnieuw beginnen.
	-- leiding moet boven trigger zijn maar de delta moet er ook zijn..
	if Res_Leiding == 1 then 
		Debug_msg('--someone is showering. ')
		if (Stand == 1 ) then
		commandArray['Fan']='Set Level: 30'
		Debug_msg('Douche: van Stand 1 naar 3') 
		FanRuntime = 0
		Reason=Reason .. "Waterleiding is: " .. WaterleidingTemp .. ", van stand 1>3," else
			if(Stand == 2 ) then 
			commandArray['Fan']='Set Level: 30'
			Debug_msg('Douche: van Stand 2>3') 
			FanRuntime = 0
			Reason=Reason .. "Waterleiding is: " .. WaterleidingTemp .. ", van stand 2>3," else
				if (Stand == 3 ) then 
				Debug_msg('Douche: op Stand 3 laten') 
				FanRuntime = FanRuntime + 1
				Reason=Reason .. "Waterleiding is: " .. WaterleidingTemp .. ", van stand 3  blijft 3 ," else
					if (Stand == 4) then  
					Debug_msg('staat al op Stand 4')  
					FanRuntime = FanRuntime + 1
					Reason=Reason .. "Waterleiding is: " .. WaterleidingTemp .. ", Blijft stand 4 ," else  
					end
				end
			end
		end
	else
				-- als de leidingtemperatuur onder de afkoelwaarde is.
				if (Stand >= 2) and (WaterleidingTemp >= WarmWaterLowerTrigger) then 
					Debug_msg('<b style="color:Blue">Fan is naventilatie stand.</b>') 
					Reason=Reason .. ": Fan in afkoelstand, leiding is " .. WaterleidingTemp .. " en gaat uit als " .. WarmWaterLowerTrigger .. " bereikt is ,"
				else 
					if (Stand >= 2) and (FanRuntime >= FanMaxRuntime) then 
					Debug_msg('<b style="color:Blue">Fan has exceeded max runtime (' .. FanMaxRuntime .. ' min), turn fan off</b>')
					commandArray['Fan']='Set Level: 10'
					FanRuntime = 0
					Reason=Reason .. "Fan staat te lang aan: " .. FanRuntime .. " / " .. FanMaxRuntime .. " ,"
					end
					if (Stand >= 2) and (WaterleidingTemp <= WarmWaterLowerTrigger) then 
					Debug_msg('<b style="color:Blue">Leiding afgekoeld, Fan uit</b>')
					commandArray['Fan']='Set Level: 10'
					FanRuntime = 0
					Reason=Reason .. "Leiding afgekoeld, Fan uit: " .. WaterleidingTemp .. " >= " .. WarmWaterLowerTrigger .. " ,"
					end	
				end
		end 
		
    -- op basis van Humidity
    if (Stand >= 1 ) then
       -- see if we have to turn it on for the shower
        if (HumDelta >= FAN_HumDelta_TRIGGER) then
            -- time to start the  fan
            commandArray['Fan']='Set Level: 30'
			Reason=Reason .. "Fan aan, vochtigheid is gestegen met" .. HumDelta .." procent,"
            targetOffHumidity = target
            -- set the safety stop
            FanRuntime = 0
			if (Stand >= 2) then
				Debug_msg('Ventilator was already on but we start the de-humidifying program')
            end		
        end
    else
        if (Stand == 1) then -- not manually started
            if (HumDelta >= FAN_HumDelta_TRIGGER) then
                -- ok, there is another FAN_HumDelta_TRIGGER rise in humidity
                -- when this happen we reset the FanMaxRuntime to a new count down
                -- because we have to ventilate a bit longer due to the extra humidity
				Debug_msg('Another large increase detected, resetting max timer. HumDelta: ' .. HumDelta)
                --FanRuntime = FanMaxRuntime
            end
 
            -- first see if it can be turned off
            if (CurrentHum <= targetOffHumidity or FanRuntime >= FanMaxRuntime) then
				commandArray['Fan']='Set Level: 10'
                if (FanAanVoor >= FanMaxRuntime and CurrentHum > targetOffHumidity) then
					Debug_msg('target not reached but safety time-out is triggered.')
                else
					Debug_msg('target humidity reached')
                end
				Debug_msg('Turning off the ventilator')
                targetOffHumidity = 0
                FanRuntime = 0
                commandArray['Fan']='Set Level: 10'
                -- reset history in this case.. we start all over
                -- Tmin10 is still in the 'ventilator=On'-zone
                HumidityTmin10 = HumidityTmin5
                else
                -- we haven't reached the target yet
			   Debug_msg('Humidity HumDelta: ' .. HumDelta)
            end
        end
    end  

	if Debug == 'Y' then
	Debug_msg("Stand:   " .. Stand .. " sinds " .. FanAanVoor .. ' Minuten, FanRuntime: ' .. FanRuntime)
	Debug_msg("IemandThuis:   " .. IemandThuis )
	Debug_msg('Waterleiding is nu ' ..  CurrentLeiding .. ' Graden, Fan gaat aan boven  ' .. WarmWaterTriggerTemp .. ' en mag afkoelen tot ' .. WarmWaterLowerTrigger .. ' graden')
	Debug_msg('HumDelta: ' .. HumDelta .. ' LeidingDelta: ' .. LeidingDelta)
    Debug_msg('HumidityTmin5: ' .. HumidityTmin5 .. ' HumidityTmin10: ' .. HumidityTmin10 .. ' TargetOffHumidity: ' .. targetOffHumidity)
	Debug_msg('LeidingTmin5: ' .. LeidingTmin5 .. ' LeidingTmin10: ' .. LeidingTmin10)
	Debug_msg( "reden: " .. My.EnumClear(Reason))
	end

end

-- save the globals
commandArray['Variable:Fan_Counter'] =  tostring(Counter)
commandArray['Variable:Fan_HumidityTmin10'] = tostring(HumidityTmin10)
commandArray['Variable:Fan_HumidityTmin5'] = tostring(HumidityTmin5)
commandArray['Variable:Fan_LeidingTmin10'] = tostring(LeidingTmin10)
commandArray['Variable:Fan_LeidingTmin5'] = tostring(LeidingTmin5)
commandArray['Variable:Fan_targetOffHumidity'] = tostring(targetOffHumidity)
commandArray['Variable:Fan_MaxRuntime'] = tostring(FanRuntime)

if LogAction=='A' or ((LogAction=='C') and (LeidingDelta <= -2 or LeidingDelta >= 4 )) then LogActions() end
-- om de 1 uur naar log-dropbox
-- if (string.len(ShAfterAction)) > 1 then os.execute(ShAfterAction) end

::done::
Debug_msg("______________________________________________________________________")
return commandArray

User avatar
BakSeeDaa
Posts: 434
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi
Domoticz version: beta
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by BakSeeDaa » Thursday 23 March 2017 8:31

remb0 wrote:Hi BakseeDaa,
nice work!

I wanted to use your script because it's a lot cleaner, then my script.
But it's not easy to use in my case.. (and with my skills)
Some points i'm struggling with, and point you can maybe use:
...
That's a huge script @remb0 :D

Many of the features are a bit beyond the scope of my script but I will consider to add a better logging function. I think it would also be nice to make it work with multiple fans.

Cheers!
Best wishes

// บักสีดา

dannybloe
Posts: 945
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi
Domoticz version:
Location: Ermelo
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by dannybloe » Thursday 23 March 2017 10:17

BakSeeDaa wrote:Below is my dzVents Bathroom Humidity Control script version 1.0.0

I've been inspired by this script: Lua script for controlling humidity in the bathroom and I got some design tips from @dannybloe.

My house has a single fan that extracts air from all the rooms in the house. I can force that single fan to work at a higher speed in case of that the humidity in one of my bathrooms rises quickly. My script currently supports only a single fan but multiple humidity sensors. The script also supports a button that can be pushed manually in case that the air quality in the bathroom requires that. I may improve my script and update this first post if I get any suggestions for improvements from you guys. Please feel free to suggest improvements etc.
Very nice!
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Thursday 30 March 2017 17:07

I love the script and want to use it but I require and override option.

I have a script running now and that checks if the override switch (dummy device with timer) is off before putting the fan in max mode.
This is needed because when i get home late I don't want to wake up the wife who is sleeping on the other side of the wall where the fan (central suction unit) is located because that makes a lot of noise at 100%.

I tried to look at the code to figure it out myself but I am not able to find where to put the "check if override = off" line.
Can someone help me out here please?

So when hum rises but override is on, then don't trigger fan switch.
Hope my story makes sense.

Keep up the great work!

User avatar
BakSeeDaa
Posts: 434
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi
Domoticz version: beta
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by BakSeeDaa » Friday 31 March 2017 7:56

mcmikev wrote:I love the script and want to use it but I require and override option.

I have a script running now and that checks if the override switch (dummy device with timer) is off before putting the fan in max mode.
This is needed because when i get home late I don't want to wake up the wife who is sleeping on the other side of the wall where the fan (central suction unit) is located because that makes a lot of noise at 100%.

I tried to look at the code to figure it out myself but I am not able to find where to put the "check if override = off" line.
Can someone help me out here please?

So when hum rises but override is on, then don't trigger fan switch.
Hope my story makes sense.

Keep up the great work!
You can try something like the following. It has not been tested though but it should give you some idea...

Code: Select all

--[[
bathroomHumControl.lua by BakSeeDaa
Version 1.2.0- Customized
	This script controls the humidity in a typical bathroom setting by detecting
	relative rises in humidity in a short period.
--]]

local FAN_DEVICE = 'Nibe F750 Force Fan' -- Fan device
local FORCE_FAN_DEVICE = 'Flatulence Button' -- (Optional)
local BLOCK_FAN_DEVICE = 'XXXXXXXX' -- (Optional) When this device is on, it will block the FAN_DEVICE from turning on
local FORCE_FAN_TIME = 10 -- Minutes to force the fan when button pushed
local HUMIDITY_SENSORS =  {'Badrum 1 C+RH', 'Badrum 2 C+RH'}
local FAN_DELTA_TRIGGER = 3 -- % Rise in humidity that will trigger the fan
local FAN_MAX_TIME = 24 -- Maximum minutes that the fan can be on in case we never reach the target humidity
local TARGET_OFFSET = 2 -- Fan goes off if target + offset is reached
local TEST_MODE_HUMIDITY_READING = 0 -- Set to a value between 1 and 100. Set to 0 to disable test mode
local READING_SAMPLES = 15

-- Create the data declarations
local data = {}
for i, device in pairs(HUMIDITY_SENSORS) do
	data[device] = {history = true, maxItems = READING_SAMPLES + 1}
	data['dehumidProgramActive'..i] = {history = true, maxItems = 1} -- Need history to get time stamp
	data['forceFan'] = {history = true, maxItems = 1} -- Need history to get time stamp
	data['targetHum'..i] = {initial=0}
end

return {
	on = {
		['timer'] = 'every 1 minutes',
		FORCE_FAN_DEVICE
	},
	data = data,
	active = true,
	execute = function(domoticz, device, triggerInfo)
		local LOG_LEVEL = domoticz.LOG_DEBUG -- Script default log level. You may change this.
		local forceFanReadings = domoticz.data['forceFan']

		if (triggerInfo.type == domoticz.EVENT_TYPE_TIMER) then
			local fanCmd = 'Off'
			for i = 1, #HUMIDITY_SENSORS do
				local humidityReadings = domoticz.data[HUMIDITY_SENSORS[i]]
				-- Store the read value in the persistant data
				for j = 1, (humidityReadings.size == 0 and READING_SAMPLES + 1 or 1) do
					humidityReadings.add((TEST_MODE_HUMIDITY_READING == 0
						and domoticz.devices[HUMIDITY_SENSORS[i]].humidity or TEST_MODE_HUMIDITY_READING))
				end

				-- INIT
				local programActiveReadings = domoticz.data['dehumidProgramActive'..i]
				if (programActiveReadings.size == 0) then
					domoticz.log('programActiveReadings, Initialization was needed', LOG_LEVEL)
					programActiveReadings.add(false)
				end
				local targetHum = domoticz.data['targetHum'..i]
				if (targetHum == nil) then
					domoticz.log('targetHum'..i..', Initialization was needed', LOG_LEVEL)
					domoticz.data['targetHum'..i] = 0
					targetHum = 0
				end
				if (forceFanReadings.size == 0) then
					domoticz.log('forceFanReadings, Initialization was needed', LOG_LEVEL)
					forceFanReadings.add('Init')
				end

				programActiveState = programActiveReadings.getLatest()
				if (programActiveState.data) then -- The fan control program is active
					-- Has the fan control program timed out or have we reached the target humidity?
					local maxTime = (programActiveState.time.minutesAgo > FAN_MAX_TIME)
					local targetHumReached = (humidityReadings.getLatest().data <= targetHum)
					if (maxTime or targetHumReached or (domoticz.devices[BLOCK_FAN_DEVICE].state == 'On')) then
						domoticz.log('Dehumidification program stops for: '..HUMIDITY_SENSORS[i], LOG_LEVEL)
						domoticz.log('Reason(s): '..(maxTime and 'Max time. ' or '')..(targetHumReached and 'Target humidity reached. ' or '')..((domoticz.devices[BLOCK_FAN_DEVICE].state == 'On') and 'Blocking device is on.' or ''), LOG_LEVEL)
						programActiveReadings.add(false)
						programActiveState = programActiveReadings.getLatest()
					else
						domoticz.log('Dehumidification program is active for: '..HUMIDITY_SENSORS[i], LOG_LEVEL)
						fanCmd = 'On'
					end
				else -- The fan is currently not running under the control of this program
					-- Has there been a significant rise in humidity lately?
					local humDelta = humidityReadings.getLatest().data - humidityReadings.min(2, READING_SAMPLES + 1)
					-- Calculate a target humidity but never try to push humidity below 40
					targetHum = math.max(humidityReadings.min(2, READING_SAMPLES + 1) + TARGET_OFFSET, 40)
					if (humDelta > FAN_DELTA_TRIGGER and humidityReadings.getLatest().data > targetHum) then
						domoticz.data['targetHum'..i] = targetHum
						programActiveReadings.add(true)
						programActiveState = programActiveReadings.getLatest()
						fanCmd = 'On'
						domoticz.log('Dehumidification program starts as a respond to: '..HUMIDITY_SENSORS[i], LOG_LEVEL)
					else
						domoticz.log('Dehumidification program doesn\'t run  for: '..HUMIDITY_SENSORS[i], LOG_LEVEL)
					end
					domoticz.log('targetHum: '..targetHum..', Current humidity: '..humidityReadings.getLatest().data..', humDelta: '..humDelta, LOG_LEVEL)
				end
			end

			if ((forceFanReadings.getLatest().time.minutesAgo < FAN_MAX_TIME)
			and (forceFanReadings.getLatest().data == 'On')) then fanCmd = 'On' end

			if (domoticz.devices[FAN_DEVICE].state ~= fanCmd) then
				domoticz.log('Turning the fan '..fanCmd, LOG_LEVEL)
				domoticz.devices[FAN_DEVICE].toggleSwitch()
			end
		else
			-- The script gets executed due to a device-change event
			if (device.name == FORCE_FAN_DEVICE and device.state == 'On') then
				forceFanReadings.add('On')
				domoticz.log('The fan has been forced on for '..FORCE_FAN_TIME..'minutes.', LOG_LEVEL)
				--domoticz.speak('joke sting')
				if (domoticz.devices[FAN_DEVICE].state ~= 'On') then domoticz.devices[FAN_DEVICE].switchOn() end
			end
		end

	end
}
Best wishes

// บักสีดา

gerard76
Posts: 64
Joined: Wednesday 22 March 2017 10:13
Target OS: Raspberry Pi
Domoticz version: 3.8153
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by gerard76 » Friday 31 March 2017 14:46

I like and am inspired by your scripts. My situation is a little bit different, but I have some stuff somebody else might be inspired by.

I wanted to know if venting was actually useful, because if there is more moist outside then what we have on the inside, its no use to vent. I added a "Weather Underground" device that gives me temp and humidity from outside, but this might as well be your own weather station. The code calculates the absolute moisture content based on temp and relative humidity because we can not use the relative values when there is a temperature difference. There is one unused function dew_point but because these humidity functions will be extracted to a separate file in the future I have left it in.

The original code was too slow to react for me (max 10 minutes) so I sped things up by triggering the script by 'device' and check if the set interval (default 10 secs) has expired. In my situation the fan turns on in about 40 secs after I turn on the shower. My mirror stays clean this way.

I store a humidity measurement every interval in a user variable string and 'explode' and 'compact' this in a table to manipulate it. This saves creating a lot of variables with only 2 lines of code. The initial value of this string determines how many intervals are stored. A reasonable default is 58;58;58;58;58;58;58;58;58;58;58;58. This is 2 minutes worth of readings. If this is not enough for your situation you can make it longer or increase the interval.

Because I have no central venting system in my house, the fan doubles as a dehumidifier for my top floor. When it is not running for the shower it makes sure relative humidity never exceeds max_humidity.

Manual override (only off for now) is done by setting my local Z-Wave switch (parameter 20) for the fan to 'Toggle switch (contact closed - On, contact open - Off)', but I really want to add a window sensor so the fan will not turn on when the window is open. Trying to save energy after all...

Code: Select all

commandArray   = {}
measurements   = {}

-- adjust these:
fan_name       = 'Badkamer ventilator'
inside_sensor  = 'Badkamer'
outside_sensor = 'Buiten'
max_humidity   = 58    -- max humidity in room
interval       = 10    -- seconds between samples
max_run_time   = 60*60 -- seconds
humidity_rise  = 2     -- rise in humidity that will trigger the fan

--[[ create these user variables:
target_humidity = 58 (integer)
humidity_over_time = "58;58;58;58;58;58;58;58;58;58;58;58" (string)
--]]

inside_hum   = tonumber(otherdevices_humidity[inside_sensor])
inside_temp  = tonumber(otherdevices_temperature[inside_sensor])
outside_temp = tonumber(otherdevices_temperature[outside_sensor])
outside_hum  = tonumber(otherdevices_humidity[outside_sensor])

function dew_point(temp, hum)
  local a = math.log(hum / 100) + (17.62 * temp / (243.12 + temp))
  return 243.12 * a / (17.62 - a)
end

function saturation_pressure(temp)
  local a = 7.5
  local b = 237.3
  
  if (temp < 0) then
    a = 7.6
    b = 240.7
  end

  return (6.1078 * math.exp(math.log(10) * ((a * temp) / (b + temp))))
end

function vapor_pressure(temp, hum)
  return (hum / 100 * saturation_pressure(temp))
end

function abs_humidity(temp, hum)
  local tk = temp + 273.15
  return (math.exp(math.log(10) * 5) * 18.016/8314.3 * vapor_pressure(temp, hum)/tk)
end

-- returns seconds elapsed since timestamp
function seconds_since(timestamp)
   y, m, d, H, M, S = timestamp:match("(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)")
   return os.difftime (os.time(), os.time{year=y, month=m, day=d, hour=H, min=M, sec=S})
end

if seconds_since(uservariables_lastupdate['humidity_over_time']) >= interval then
  fan_on = otherdevices[fan_name] == "On"
  target = uservariables['target_humidity']
  
  -- put all previous readings in measurements table
  uservariables['humidity_over_time']:gsub("(%d+)", function(c) table.insert(measurements,c) end)
  table.remove(measurements)                -- pop oldest value
  table.insert(measurements, 1, inside_hum) -- push new value
  commandArray['Variable:humidity_over_time'] = table.concat(measurements, ';')
  
  if not fan_on then
    min_hum = math.min(table.unpack(measurements))
    if inside_hum - min_hum >= humidity_rise then
      -- shower is on
      target = min_hum
    end
    
    if uservariables['target_humidity'] ~= tonumber(target) then
      -- we have a new target
      commandArray['Variable:target_humidity'] = tostring(target)
    end
  end
  
  too_moist   = inside_hum > target
  useful      = abs_humidity(inside_temp, inside_hum) > abs_humidity(outside_temp, outside_hum)
  on_too_long = fan_on and seconds_since(otherdevices_lastupdate[fan_name]) > max_run_time
  
  if not fan_on and too_moist and useful then
    commandArray[fan_name] = "On"
  elseif fan_on and (not useful or not too_moist or on_too_long) then
    commandArray[fan_name] = "Off"
    commandArray['Variable:target_humidity'] = tostring(max_humidity)
  end
end

return commandArray

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 15:34

Right now after changing all the things to the new formats for version 2.0 I cannot get it to work.
Compar with nil keeps showing up.

Here is my script. Maybe someone can see what I don't see.

Code: Select all

-- assumptions:
-- the setpoint is set by a selector dummy device where the values are numeric temperatures
-- but you can easily change it to a setpoint device

local BOILER_DEVICE = 'State-CV-WK' -- switch device
local SETPOINT_DEVICE = 'Thermostaat WK' -- selector dummy device
local TEMPERATURE_SENSOR = 'TH-Woonkamer'
local HYSTERESIS = 0.1 -- temp has to drop this value below setpoint before boiler is on again
local SMOOTH_FACTOR = 3
local LOGGING = false
local OVERRIDE_SWITCH = 'CV-WK-Override' -- override switch


return {
	on = {
		timer = {
		'every minute',
		TEMPERATURE_SENSOR,
		SETPOINT_DEVICE
		}
	},
	data = {
		temperatureReadings = { history = true, maxItems = SMOOTH_FACTOR }
	},
	active = true,
	execute = function(domoticz, device, triggerInfo)

		local avgTemp
		local temperatureReadings = domoticz.data.temperatureReadings

		-- first check if the sensor got a new reading or the setpoint was changed:
		if (triggerInfo.type == domoticz.EVENT_TYPE_DEVICE) then

			local sensor = domoticz.devices(TEMPERATURE_SENSOR)

			if (sensor.changed and sensor.attributeChanged('temperature')) then
				-- sensor just reported a new reading
				-- add it to the readings table

				local current = sensor.temperature

				if (current ~= 0 and current ~= nil) then
					temperatureReadings.add(current)
				else
					-- no need to be here, weird state detected
					domoticz.log('Strange sensor reading.. skiping', domoticz.LOG_ERROR)
					return
				end

			elseif (domoticz.devices(SETPOINT_DEVICE).changed) then
				-- a new setpoint was set
				if LOGGING then domoticz.log('Setpoint was set to ' .. device.state) end
			else
				-- no business here, bail out...
				return
			end
		end

		-- now determine what to do

		local boiler = domoticz.devices(BOILER_DEVICE)
		local setpoint = domoticz.devices(SETPOINT_DEVICE)
		local override = domoticz.devices(OVERRIDE_SWITCH)

		if (setpoint.state == nil or setpoint.state == 'Off') then
			boiler.switchOff()
			return -- we're done here
		end

		local setpointValue = tonumber(setpoint.state)

		-- determine at which temperature the boiler should be
		-- switched on
		local switchOnTemp = setpointValue - HYSTERESIS

		-- don't use the current reading but average it out over
		-- the past <SMOOTH_FACTOR> readings (data smoothing) to get rid of noise, wrong readings etc
		local avgTemp = temperatureReadings.avg(1, SMOOTH_FACTOR)

		if LOGGING then
			domoticz.log('Average: ' .. avgTemp, domoticz.LOG_INFO)
			domoticz.log('Setpoint: ' .. setpointValue, domoticz.LOG_INFO)
			domoticz.log('Current boiler state: ' .. boiler.state, domoticz.LOG_INFO)
			domoticz.log('Switch-on temperature: ' .. switchOnTemp, domoticz.LOG_INFO)
		end

		if (avgTemp >= setpointValue and boiler.state == 'On') then
			if LOGGING then domoticz.log('Target temperature reached, boiler off') end
			boiler.switchOff()
			boiler.switchOff().afterMin(2)
		end

		if (avgTemp < setpointValue and boiler.state == 'Off' and override.state == 'Off') then
			if (avgTemp < switchOnTemp) then
				if LOGGING then domoticz.log('Heating is required, boiler switched on') end
				boiler.switchOn()
				boiler.switchOn().afterMin(2)
			else
				if LOGGING then domoticz.log('Average temperature below setpoint but within hysteresis range, waiting for temperature to drop to ' .. switchOnTemp) end
			end
		end
		if (boiler.state == 'On' and override.state == 'On') then
			if LOGGING then domoticz.log('Override is aan, CV Woonkamer UIT') end
			boiler.switchOff()
			boiler.switchOff().afterMin(2)
		end

	end
}
the error

Code: Select all

2017-07-07 15:34:00.889  dzVents: Info:  ------ Start internal script: dz_cv_woonkamer:, trigger: every minute
2017-07-07 15:34:00.921  dzVents: Debug: Device-adapter found for State-CV-WK: Switch device adapter
2017-07-07 15:34:00.934  dzVents: Debug: Processing device-adapter for State-CV-WK: Switch device adapter
2017-07-07 15:34:00.934  dzVents: Debug: Device-adapter found for Thermostaat WK: Thermostat setpoint device adapter
2017-07-07 15:34:00.935  dzVents: Debug: Processing device-adapter for Thermostaat WK: Thermostat setpoint device adapter
2017-07-07 15:34:00.935  dzVents: Debug: Device-adapter found for CV-WK-Override: Switch device adapter
2017-07-07 15:34:00.935  dzVents: Debug: Processing device-adapter for CV-WK-Override: Switch device adapter
2017-07-07 15:34:00.936  Error: dzVents: Error: An error occured when calling event handler dz_cv_woonkamer
2017-07-07 15:34:00.936  Error: dzVents: Error: ...cz/scripts/dzVents/generated_scripts/dz_cv_woonkamer.lua:87: attempt to compare number with nil
2017-07-07 15:34:00.936  dzVents: Info:  ------ Finished dz_cv_woonkamer

randytsuch
Posts: 87
Joined: Sunday 20 March 2016 19:56
Target OS: Raspberry Pi
Domoticz version: Beta
Location: LA, Ca USA
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by randytsuch » Friday 07 July 2017 16:40

So this is line 87
if (avgTemp >= setpointValue and boiler.state == 'On') then

I didn't try to figure out why it doesn't like this line.
If it was me, I'd split it into two separate if statements, and see which one it complains about. Then you "just" have to figure why.

Unless you already know which variable is generating the error?

One other thing, although it doesn't seem to be causing your problem

I could not do this
local temperatureReadings = domoticz.data.temperatureReadings

I had to use domoticz.data.variablename everywhere to make my script work. I haven't gone back yet to verify this was really the problem, but it works fine now, and that's what I did.

Randy

dannybloe
Posts: 945
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi
Domoticz version:
Location: Ermelo
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by dannybloe » Friday 07 July 2017 17:08

randytsuch wrote:So this is line 87
One other thing, although it doesn't seem to be causing your problem

I could not do this
local temperatureReadings = domoticz.data.temperatureReadings
That is strange as this should definitely work. I'll look into it.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 19:33

I see that I posted some other issue in this place. OEPS.
That code is for turning heating on and off and not the humidity control .

I enabled this script in the event editor in domoticz and I see it running and it seems to be working but the fan keeps running for ever.
maybe you can see if all the new version 2.0 stuff is in there and is looks fine?

Code: Select all

-- This script controls the humidity in a typical bathroom setting by detecting
-- relative rises in humidity in a short period.

local FAN_DEVICE = 'State-AfzuigingBadkamer' -- Fan device
local FORCE_FAN_DEVICE = '$DIM-Badkamer-R2x Status' -- (Optional)
local FORCE_FAN_TIME = 10 -- Minutes to force the fan when button pushed
local AFZUIGING_OVERRIDE = 'Afzuiging-Override' -- (Optional) When this device is on, it will block the FAN_DEVICE from turning on
local HUMIDITY_SENSORS =  {'TH-Badkamer'}
local FAN_DELTA_TRIGGER = 2 -- % Rise in humidity that will trigger the fan
local FAN_MAX_TIME = 60 -- Maximum minutes that the fan can be on in case we never reach the target humidity
local TARGET_OFFSET = 2 -- Fan goes off if target + offset is reached
local TEST_MODE_HUMIDITY_READING = 0 -- Set to a value between 1 and 100. Set to 0 to disable test mode
local DEBUG = true
local READING_SAMPLES = 15

-- Create the data declarations
local data = {}
for i, device in pairs(HUMIDITY_SENSORS) do
   data[device] = {history = true, maxItems = READING_SAMPLES + 1}
   data['dehumidProgramActive'..i] = {history = true, maxItems = 1} -- Need history to get time stamp
   data['forceFan'] = {history = true, maxItems = 1} -- Need history to get time stamp
   data['targetHum'..i] = {initial=0}
end

return {
   on = {
      timer = {
        'every 1 minutes',
      FORCE_FAN_DEVICE
      }
   },
   data = data,
   active = true,
   execute = function(domoticz, device, triggerInfo)

      local forceFanReadings = domoticz.data['forceFan']

      if (triggerInfo.type == domoticz.EVENT_TYPE_TIMER) then
         local fanCmd = 'Off'
         for i = 1, #HUMIDITY_SENSORS do
            local humidityReadings = domoticz.data[HUMIDITY_SENSORS[i]]
            -- Store the read value in the persistant data
            for j = 1, (humidityReadings.size == 0 and READING_SAMPLES + 1 or 1) do
               humidityReadings.add((TEST_MODE_HUMIDITY_READING == 0
                  and domoticz.devices(HUMIDITY_SENSORS[i]).humidity or TEST_MODE_HUMIDITY_READING))
            end

            -- INIT
            local programActiveReadings = domoticz.data['dehumidProgramActive'..i]
            if (programActiveReadings.size == 0) then
               print('programActiveReadings, Initialization was needed')
               programActiveReadings.add(false)
            end
            local targetHum = domoticz.data['targetHum'..i]
            if (targetHum == nil) then
               print('targetHum'..i..', Initialization was needed')
               domoticz.data['targetHum'..i] = 0
               targetHum = 0
            end
            if (forceFanReadings.size == 0) then
               print('forceFanReadings, Initialization was needed')
               forceFanReadings.add('Init')
            end

            programActiveState = programActiveReadings.getLatest()
            if (programActiveState.data) then -- The fan control program is active
               -- Has the fan control program timed out or have we reached the target humidity?
               local maxTime = (programActiveState.time.minutesAgo > FAN_MAX_TIME)
               local targetHumReached = (humidityReadings.getLatest().data <= targetHum)
               if (maxTime or targetHumReached or (domoticz.devices(AFZUIGING_OVERRIDE).state == 'On')) then
                  print('Dehumidification program stops for: '..HUMIDITY_SENSORS[i])
                  domoticz.log('Reason(s): '..(maxTime and 'Max time. ' or '')..(targetHumReached and 'Target humidity reached. ' or '')..((domoticz.devices(AFZUIGING_OVERRIDE).state == 'On') and 'Afzuiging Override is on.' or ''), LOG_LEVEL)
                  programActiveReadings.add(false)
                  programActiveState = programActiveReadings.getLatest()
               else
                  print('Dehumidification program is active for: '..HUMIDITY_SENSORS[i])
                  fanCmd = 'On'
               end
            else -- The fan is currently not running under the control of this program
               -- Has there been a significant rise in humidity lately?
               local humDelta = humidityReadings.getLatest().data - humidityReadings.min(2, READING_SAMPLES + 1)
               -- Calculate a target humidity but never try to push humidity below 40
               targetHum = math.max(humidityReadings.min(2, READING_SAMPLES + 1) + TARGET_OFFSET, 40)
               if (humDelta > FAN_DELTA_TRIGGER and humidityReadings.getLatest().data > targetHum) then
                  domoticz.data['targetHum'..i] = targetHum
                  programActiveReadings.add(true)
                  programActiveState = programActiveReadings.getLatest()
                  fanCmd = 'On'
                  if (DEBUG) then
                     print('Dehumidification program starts as a respond to: '..HUMIDITY_SENSORS[i])
                  end
               else
                  if (DEBUG) then print('Dehumidification program doesn\'t run  for: '..HUMIDITY_SENSORS[i]) end
               end
               if (DEBUG) then print('targetHum: '..targetHum..', Current humidity: '..humidityReadings.getLatest().data..', humDelta: '..humDelta) end
            end
         end

         if ((forceFanReadings.getLatest().time.minutesAgo < FAN_MAX_TIME)
         and (forceFanReadings.getLatest().data == 'On')) then fanCmd = 'On' end

         if (domoticz.devices(FAN_DEVICE).state ~= fanCmd) then
            if (DEBUG) then print('Turning the fan '..fanCmd) end
            domoticz.devices(FAN_DEVICE).toggleSwitch()
         end
      else
         -- The script gets executed due to a device-change event
         if (device.name == FORCE_FAN_DEVICE and device.state == 'On') then
            forceFanReadings.add('On')
            print('The fan has been forced on for '..FORCE_FAN_TIME..'minutes.')
            -- domoticz.speak('joke sting')
            if (domoticz.devices(FAN_DEVICE).state ~= 'On') then domoticz.devices(FAN_DEVICE).switchOn() end
         end
      end

   end
}

dannybloe
Posts: 945
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi
Domoticz version:
Location: Ermelo
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by dannybloe » Friday 07 July 2017 19:40

Pff, that's a complex script. Unfortunately I don't have time to fully understand it and analyse it. Sorry.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 19:42

Hi, thx for the response.

The other code for the heating does not work for me at least.
I get compare to nil. I can't seem to find out why.

Maybe you see why?

dannybloe
Posts: 945
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi
Domoticz version:
Location: Ermelo
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by dannybloe » Friday 07 July 2017 19:46

I looks like you on-section is wrong, You combine timer and device triggers in the timer sub-section. Try this:

Code: Select all

return {
	on = {
		timer = { 'every minute'},
		device = { TEMPERATURE_SENSOR, SETPOINT_DEVICE}
	}
	...
}
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 19:57

It seems to not find the average anymore.
I editted the code with your suggestion but still the same error

Code: Select all

2017-07-07 19:56:01.324 dzVents: Info: ------ Start internal script: dz_cv_badkamer:, trigger: every minute
2017-07-07 19:56:01.326 Error: dzVents: Error: An error occured when calling event handler dz_cv_badkamer
2017-07-07 19:56:01.326 Error: dzVents: Error: ...icz/scripts/dzVents/generated_scripts/dz_cv_badkamer.lua:83: attempt to compare number with nil
2017-07-07 19:56:01.326 dzVents: Info: ------ Finished dz_cv_badkamer

dannybloe
Posts: 945
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi
Domoticz version:
Location: Ermelo
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by dannybloe » Friday 07 July 2017 20:03

Can you try to add a default to the avg() method as when there is no data yet it returns nil:

Code: Select all

local avgTemp = temperatureReadings.avg(1, SMOOTH_FACTOR, 0) -- when there's no average, return 0 (or whatever you want it to return)
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 20:08

no error anymore but keeps turning heating on even though the setpoint is lower then temp measured.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 20:11

the average is 0 now but that should be the temo average.

BTW: the script is from the example folder (1.x version) and editted. (simple room heating with hysteresis control)

So maybe you can see what the issue is with the temp reading?

dannybloe
Posts: 945
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi
Domoticz version:
Location: Ermelo
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by dannybloe » Friday 07 July 2017 20:19

Yes, just dawned to me that it really resembles my own heating script that I used a while ago. Hahaha.
So, as I have been running that script for quite some time it should work (famous last words).
Anyway,

Code: Select all

boiler.switchOff()
boiler.switchOff().afterMin(2)
This looks weird. I don't know what Domoticz will do with these two commands.
But, what I would do is put print statements in the various locations and see if you get to the proper if-branches and what the values are. And I'd get rid of those weird double switch commands.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.

mcmikev
Posts: 118
Joined: Tuesday 26 May 2015 8:11
Target OS: Raspberry Pi
Domoticz version: beta
Location: right here
Contact:

Re: My dzVents Bathroom Humidity Control script

Post by mcmikev » Friday 07 July 2017 20:23

Hi all, seems like i hijacked this topic. I created a topic for the issue.
https://www.domoticz.com/forum/viewtop ... 8#p140658

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest