hybride hvac with cv and airco

Moderator: leecollings

Post Reply
zicht
Posts: 300
Joined: Sunday 11 May 2014 11:09
Target OS: Windows
Domoticz version: 2023.1+
Location: NL
Contact:

hybride hvac with cv and airco

Post by zicht »

I have a hybrid hvac system running with mitsh.heavy airco and remeha avanta CV with thermostat (NEST in my case, but the brand does not matter) To use it you need your thermostat and airco values available and create an extra virtual housesetpoint

Code: Select all

function Aircoverwarming()

    if otherdevices["Airco Master"]=="On" then
        local buiten = otherdevices_temperature["Buiten"]
        local binnen = otherdevices_temperature["Binnen"]

        -- hoofdblok
        local od = otherdevices
        local dc = devicechanged or {}
        local uv = uservariables or {}
        local timenow = os.date("*t")

        ----------------------------------------------------
        -- Allowed devices check (CPU sparen)
        ----------------------------------------------------
        local allowed_devices_list = {
            ["Binnen"] = true, ["Buiten"] = true, ["Woonkamer tmp"] = true,
            ["Heating mode"] = true, ["Cv koud"] = true, ["Cv koud 2"] = true,
            ["Target Setpoint Beneden"] = true,
            ["Target Setpoint 1e"] = true, ["Target Setpoint Zolder"] = true,
            ["Airco Power Beneden"] = true, ["Airco Power 1e"] = true,
            ["Airco Power Zolder"] = true, ["Operation Mode Beneden"] = true,
            ["Operation Mode 1e"] = true, ["Operation Mode Zolder"] = true,
            ["Swing Up/Down Beneden"] = true, ["Swing Up/Down 1e"] = true,
            ["Swing Up/Down Zolder"] = true, ["LivingFlame"] = true,
            ["Huis Setpoint"] = true
        }

        local skip = false
        if device ~= nil and not allowed_devices_list[device] then skip = true end
        if skip == false then

			local function AircoExtraLogging()
				----------------------------------------------------
				-- MHI DEFROST DETECTOR (robust, 1 uservar)
				----------------------------------------------------
				local usage = tonumber(otherdevices_utility["Airco Beneden Usage"] or "0")
				local defrost_active = 0
				-- Detectie defrost actief (13–50 W)
				if od["Airco Power Beneden"] == "On" and usage >= 13 and usage <= 50 then
					defrost_active = 1
					if dc["Binnen"] then print("❄️ DEFROST (Usage="..usage.."W)") end
				end
				----------------------------------------------------
				-- PLUGIN REFRESH DETECTOR (haunted house edition)
				----------------------------------------------------
				--if dc["Target Setpoint Beneden"] ~= nil 	then print("👻 Plugin refresh: Target Setpoint Beneden = "..tostring(dc["Target Setpoint Beneden"])) end
				--if dc["Target Setpoint 1e"] ~= nil 			then print("👻 Plugin refresh: Target Setpoint 1e = "..tostring(dc["Target Setpoint 1e"])) end
				--if dc["Target Setpoint Zolder"] ~= nil 		then print("👻 Plugin refresh: Target Setpoint Zolder = "..tostring(dc["Target Setpoint Zolder"])) end
			end
			
            ----------------------------------------------------
            -- helpers
            ----------------------------------------------------
            local abort_airco_logic = false

            local function set_if_needed(dev, value, reden)
                if otherdevices[dev] ~= value then 
					commandArray[dev] = value 
					if dev=="Airco Power Beneden" then set_var_if_needed("AircoHardGuard", "1", "HardGuard on") set_var_if_needed("AircoHardGuard_since", tostring(now), "HardGuard timestamp set") end
					if debugprint==true then print("🔥❄️ Airco&Nest: "..dev.." = "..value.." -> "..tostring(reden)) printdone=true end
				end
			end

            local function set_var_if_needed(var, value, reden)
                if uservariables[var] ~= value then 
					commandArray["Variable:"..var] = value 
					if debugprint==true then print("🔥❄️ Airco&Nest: "..var.." = "..value.." -> "..tostring(reden)) printdone=true end
				end
            end

            -- Setpoint helper:
            -- - gebruikt één centrale uservariable (airco_heating_setpoint)
            -- - alleen Beneden (idx 6352) MAG die variable updaten
            -- - 1e en Zolder LEZEN alleen de variable om te volgen
            local function set_setpoint_if_needed(idx, target_sp, reden)
                local target_str = tostring(target_sp)
                -- Alleen iets doen als het centrale setpoint wijzigt
                if uservariables["airco_heating_setpoint"] ~= target_str then
                    commandArray["SetSetPoint:"..idx] = target_str
                    -- Alleen Beneden schrijft de centrale uservariable
                    if idx == "6352" then commandArray["Variable:airco_heating_setpoint"] = target_str end
					if debugprint==true then print("🔥❄️ Airco&Nest: "..idx.." = "..target_sp.." -> "..tostring(reden)) printdone=true end

                end
            end

			local function timing_helper(dev)
				local status=od[dev]
				local duration = 9999
				local v1, d1, v2, d2, v3, d3 = showHistory(dev, 3, false)
				if v1 == status then duration = d1 elseif v2 == status then duration = d2 end
				return duration
			end
			
			local function robust_tdiff(dev)
				local status=od[dev]
				local t = TDiff(dev) if t > 5 then return t else return timing_helper(dev) end
			end
			
            ----------------------------------------------------
            -- Loop preventie: radiator vents blokkeren
            ----------------------------------------------------
            if device and string.find(device,"radiator vent") ~= nil then abort_airco_logic = true end

            ----------------------------------------------------
            -- CV usage
            ----------------------------------------------------
            local CV_usage = od["CV Usage"]
            CV_usage = tonumber(string.sub(CV_usage,1,string.find(CV_usage,";")-1))

            ----------------------------------------------------
            -- Setpoint
            ----------------------------------------------------
			local Setpoint = od["Huis Setpoint"]

			----------------------------------------------------
            -- diversen
            ----------------------------------------------------
            local debugprint 			 = false
            local debugprinttotal		 = false
			
            local Setpoint_offset        = 0.5
            local Setpoint_offset_start  = 4
            local current_temp 			 = round((tonumber(otherdevices_temperature["Woonkamer tmp"]) + tonumber(otherdevices_temperature["Binnen"])) / 2, 1)

            local Heating      			 = (od["Cv koud"] == "Off" or od["NEST heating"] == "On")
            local HeatingMode  			 = od["Heating mode"] or "Off"
            local airco_heating_startup  = uv["airco_heating_startup"]

            local Cvlu     = controleer("Cv koud") 				or TDiff("Cv koud")
            local radlu    = controleer("radiator vent rechts") or TDiff("radiator vent rechts")
            local aircolu  = controleer("Airco Power Beneden") 	or robust_tdiff("Airco Power Beneden")
            local aircolu2 = controleer("Airco Power 1e") 		or robust_tdiff("Airco Power 1e")
            local aircolu3 = controleer("Airco Power Zolder") 	or robust_tdiff("Airco Power Zolder")

			----------------------------------------------------
            -- Setpoint mirror
            ----------------------------------------------------
            local SetpointHuis = round(otherdevices_svalues["Huis Setpoint"],1)
			local SetpointNest = round(otherdevices_svalues["NEST setpoint"],1)
			local varHuis=tonumber(uservariables["Airco_setpoint"])
			local varNest=tonumber(uservariables["Nest_setpoint"])

			--local transfer_offset = math.abs(round(current_temp-otherdevices_temperature["NEST temp"],1)) + 0.1
			local transfer_offset = 0.9		-- match sensoren offset met NEST
			local NestChanged=(tonumber(SetpointNest)~=tonumber(varNest))
			local HuisChanged=(tonumber(SetpointHuis)~=tonumber(varHuis))			
			
			if NestChanged then 
				print("Nestchanged - old:"..varNest.." new:"..SetpointNest)
				commandArray["Variable:Nest_setpoint"]=tostring(SetpointNest)
				print("Huissetpoint aangepassen naar: "..tostring(tonumber(SetpointNest)+transfer_offset))
				commandArray["SetSetPoint:8599"] = tostring(SetpointNest+transfer_offset)
			end
			if HuisChanged then 
				print("HuisChanged - old:"..varHuis.." new:"..SetpointHuis)
				commandArray["Variable:Airco_setpoint"]=tostring(SetpointHuis)
			end

            ----------------------------------------------------
            -- Thresholds
            ----------------------------------------------------
            local airco_on_threshold   = Setpoint + 0.1
            local airco_hold_threshold = Setpoint + 0.3
            local airco_off_threshold  = Setpoint + 0.7
            local airco_hard_guard     = airco_off_threshold + 0.7  -- overshoot-correctie

            local airco_Min_time_On    = 1200
            local airco_Min_time_Off   = 900
            --local airco_Max_runtime    = 21600

			if debugprint  then AircoExtraLogging() end

			----------------------------------------------------
			-- SETPOINT REALIGNMENT (mode-agnostisch, HVAC-safe)
			-- Wordt uitgevoerd zodra Huis Setpoint is gewijzigd.
			-- Doel: alle airco-targets opnieuw afleiden uit HuisSetpoint,
			-- zonder on/off, zonder HardGuard-conflict.
			----------------------------------------------------
			if HuisChanged then
				local desired_b, desired_1e, desired_z

				----------------------------------------------------
				-- BENEDEN (leidend toestel)
				----------------------------------------------------
				if od["Airco Power Beneden"] == "On" then
					if HeatingMode == "X" then
						desired_b = Setpoint                         -- exact volgen
					elseif HeatingMode == "Normal" or HeatingMode == "Turbo" then
							desired_b = Setpoint + Setpoint_offset_start
					elseif HeatingMode == "Turb+" or HeatingMode == "Max" then
							desired_b = Setpoint + Setpoint_offset_start
					end
				end

				----------------------------------------------------
				-- 1e VERDIEPING
				----------------------------------------------------
				if od["Airco Power 1e"] == "On" then
					if HeatingMode == "X" then
						desired_1e = Setpoint - 1
					elseif HeatingMode == "Turb+" or HeatingMode == "Max" then
							desired_1e = Setpoint + Setpoint_offset_start
					elseif HeatingMode == "Normal" or HeatingMode == "Turbo" then
						-- In Normal/Turbo volgt 1e alleen als hij aan staat
						desired_1e = Setpoint + Setpoint_offset
					end
				end

				----------------------------------------------------
				-- ZOLDER
				----------------------------------------------------
				if od["Airco Power Zolder"] == "On" then
					if HeatingMode == "X" then
						desired_z = Setpoint - 2
					elseif HeatingMode == "Turb+" or HeatingMode == "Max" then
							desired_z = Setpoint + Setpoint_offset_start
					elseif HeatingMode == "Normal" or HeatingMode == "Turbo" then
						desired_z = Setpoint + Setpoint_offset
					end
				end
				----------------------------------------------------
				-- APPLY (alleen setpoints, nooit power!)
				----------------------------------------------------
				if desired_b then set_setpoint_if_needed("6352", desired_b, "Realign Beneden") print("setpointB doen") end
				if desired_1e then set_setpoint_if_needed("6361", desired_1e, "Realign 1e") print("setpoint1e doen") end
				if desired_z then set_setpoint_if_needed("6367", desired_z, "Realign Zolder") print("setpointZ doen") end
			end

			--===========================================================
			-- HARD GUARD (100% HVAC-safe, onafhankelijk van TDiff)
			--===========================================================
			local now = os.time()
			local hg_since = tonumber(uservariables["AircoHardGuard_since"] or "0") or 0
			local elapsed = now - hg_since

			-- Detecteer wijziging van Airco Power Beneden (intern of extern)
			if dc["Airco Power Beneden"] ~= nil then
				set_var_if_needed("AircoHardGuard", "1", "HardGuard on (change detected)")
				set_var_if_needed("AircoHardGuard_since", tostring(now), "HardGuard timestamp set")
				hg_since = now
				elapsed = 0
			end

			-- Guard actief zolang <300 sec
			if elapsed < 300 then
				set_var_if_needed("AircoHardGuard", "1", "HardGuard active (<300s)")
				if dc["Binnen"] then print("🔥❄️ Airco&Nest: HardGuard actief !") end
				return -- return: script mag niet verder
			else
				set_var_if_needed("AircoHardGuard", "0", "HardGuard released (>300s)")
			end
			
			--extra guard : clickson rf433 "uit" gemist
			if TDiff("Cv koud")>3600 and od["Cv koud"]=="Off" and od["NEST heating"] == "Off" then 
					commandArray["Cv koud"]="On" 
					print("🔥❄️ Airco&Nest: CV koud correctie na 3600 sec")
			end

            ----------------------------------------------------
            -- compressor protection timers (op basis van TDiff)
            ----------------------------------------------------
            local Min_On_b  = (TDiff("Airco Power Beneden") > airco_Min_time_On  and od["Airco Power Beneden"]=="On")
            local Min_On_1e = (TDiff("Airco Power 1e")      > airco_Min_time_On  and od["Airco Power 1e"]=="On")
            local Min_On_z  = (TDiff("Airco Power Zolder")  > airco_Min_time_On  and od["Airco Power Zolder"]=="On")

            local Min_Off_b = (TDiff("Airco Power Beneden") > airco_Min_time_Off and od["Airco Power Beneden"]=="Off")
            local Min_Off_1e= (TDiff("Airco Power 1e")      > airco_Min_time_Off and od["Airco Power 1e"]=="Off")
            local Min_Off_z = (TDiff("Airco Power Zolder")  > airco_Min_time_Off and od["Airco Power Zolder"]=="Off")

            ----------------------------------------------------
            -- koude dag
            ----------------------------------------------------
            local tempbuiten = otherdevices_temperature["Buiten"]
            local tempbinnen = otherdevices_temperature["Binnen"]
            local deltatemp  = tempbinnen - tempbuiten
            local coldday 	 = (tempbuiten < 10 and deltatemp > 10 and timenow.hour >= 8 and timenow.hour < 22)

            ----------------------------------------------------
            -- cv "real on" guard
            ----------------------------------------------------
            local CV_On = od["CV ingebruik"]=="On"
            local CV_On_lu = TDiff("CV ingebruik") > 1800
            if CV_On and CV_On_lu then Heating = Heating and (CV_usage > 50) end

            ----------------------------------------------------
            -- startup offset resetten naar normale offset als Airco beneden uit
            ----------------------------------------------------
			reden="startup offset resetten naar normale offset "
            if od["Airco Power Beneden"]=="Off" then set_var_if_needed("airco_heating_setpoint", "0",reden) end

            ----------------------------------------------------
            -- Radiatorventilatoren
            ----------------------------------------------------
            if Heating and od["Radiator vent Master"]=="On" then
                if od["radiator vent achter"] == "Off" then 
					commandArray["radiator vent achter"] = "On REPEAT 2 INTERVAL 10" 
					if debugprint==true then print("Airco&Nest: Radiatorvent = On") end
				end
                if od["radiator vent rechts"] == "Off" then commandArray["radiator vent rechts"] = "On REPEAT 2 INTERVAL 11" end
                if od["radiator vent links"] == "Off"  then commandArray["radiator vent links"] = "On REPEAT 2 INTERVAL 12" end
            elseif Cvlu >= 1200 and od["Radiator vent Master"]=="On" then
                if od["radiator vent achter"] == "On" then commandArray["radiator vent achter"] = "Off REPEAT 2 INTERVAL 10" end
                if od["radiator vent rechts"] == "On" then commandArray["radiator vent rechts"] = "Off REPEAT 2 INTERVAL 11" end
                if od["radiator vent links"] == "On"  then commandArray["radiator vent links"] = "Off REPEAT 2 INTERVAL 12" end
            end

            ----------------------------------------------------
            -- Startup / Keepon / coldday / mode logica voorbereiden
            ----------------------------------------------------
            local startup_flag = tonumber(uv["airco_heating_startup"] or "0") or 0

            local ontime_b  = controleer("Airco Power Beneden") or 0
            local ontime_1e = controleer("Airco Power 1e") or 0
            local ontime_z  = controleer("Airco Power Zolder") or 0

            local offtime_b  = TDiff("Airco Power Beneden") or 0    if od["Airco Power Beneden"]=="On" 	then  offtime_b=0 end
            local offtime_1e = TDiff("Airco Power 1e") or 0			if od["Airco Power 1e"]=="On" 		then  offtime_1e=0 end
            local offtime_z  = TDiff("Airco Power Zolder") or 0		if od["Airco Power Zolder"]=="On" 	then  offtime_z=0 end


            local KeepOn_b  = (ontime_b  > 0 and ontime_b  < 1800)
            local KeepOn_1e = (ontime_1e > 0 and ontime_1e < 1800)
            local KeepOn_z  = (ontime_z  > 0 and ontime_z  < 1800)

            if current_temp >= airco_off_threshold then
                KeepOn_b  = false
                KeepOn_1e = false
                KeepOn_z  = false
            end

            ----------------------------------------------------
            -- Startup reset (10 min) alleen voor beneden
            ----------------------------------------------------
            if startup_flag == 1 and od["Airco Power Beneden"]=="On" and ontime_b > 600 then
				reden="Startup reset (10 min)"
                set_setpoint_if_needed("6352", Setpoint + Setpoint_offset,reden)
                set_var_if_needed("airco_heating_startup", "0",reden)
            end

            ----------------------------------------------------
            -- Heating mode Off → alles uit
            ----------------------------------------------------
            if dc["Heating mode"]=="Off" then
				reden="Heating mode Off"
                if od["Airco Power Beneden"] ~= "Off" and Min_On_b 	then set_if_needed("Airco Power Beneden","Off",reden) end
                if od["Airco Power 1e"] ~= "Off" and Min_On_1e 		then set_if_needed("Airco Power 1e","Off",reden) end
                if od["Airco Power Zolder"] ~= "Off" and Min_On_z 	then set_if_needed("Airco Power Zolder","Off",reden) end
                abort_airco_logic = true
				if debugprint==true then print("Airco&Nest: heatingmode off gezet") end
            end

            ----------------------------------------------------
            -- HARDE VEILIGHEID (A2)
            -- current_temp > airco_hard_guard → airco mag NIET starten
            -- airco moet UIT zodra Min_On gehaald is
            ----------------------------------------------------
            if current_temp > airco_hard_guard then
				reden="current_temp > airco_hard_guard"
                if od["Airco Power Beneden"]=="On" and Min_On_b then set_if_needed("Airco Power Beneden","Off",reden) set_var_if_needed("AircoHardGuard", "1", "HardGuard on") set_var_if_needed("AircoHardGuard_since", tostring(now), "HardGuard timestamp set") end
                if od["Airco Power 1e"]=="On" and Min_On_1e 	then set_if_needed("Airco Power 1e","Off",reden) end
                if od["Airco Power Zolder"]=="On" and Min_On_z 	then set_if_needed("Airco Power Zolder","Off",reden) end

                -- LivingFlame uit
                if od["LivingFlame"]=="On" then
                    commandArray[#commandArray+1] = { ["LivingFlame"] = "Set level 30" }
                    commandArray[#commandArray+1] = { ["LivingFlame"] = "Set level 10 AFTER 10" }
                end

                -- Fan naar Auto (Off)
				reden="Fan naar Auto"
                set_if_needed("Fan Beneden","Off",reden)
                set_if_needed("Fan 1e","Off",reden)
                set_if_needed("Fan Zolder","Off",reden)

                -- Mode-logica overslaan
                abort_airco_logic = true
            end

            ----------------------------------------------------
            -- MODE-LOGICA (alleen uitvoeren als niet geaborteerd)
            ----------------------------------------------------
            -- Allow-flags alvast declareren voor debugscope
            local allow_start_b  = false
            local allow_start_1e = false
            local allow_start_z  = false

            if not abort_airco_logic then

                ----------------------------------------------------
                -- MINIMUM OFF-TIME GUARD (voorkomt directe herstart)
                ----------------------------------------------------
                allow_start_b  = (od["Airco Power Beneden"]=="Off"  and Min_Off_b  and commandArray["Airco Power Beneden"] ~= "Off")
                allow_start_1e = (od["Airco Power 1e"]=="Off"      and Min_Off_1e and commandArray["Airco Power 1e"]      ~= "Off")
                allow_start_z  = (od["Airco Power Zolder"]=="Off"  and Min_Off_z  and commandArray["Airco Power Zolder"] ~= "Off")

                ----------------------------------------------------
                -- NORMAL MODE
                ----------------------------------------------------
                if HeatingMode == "Normal" then

                    -- Start vlak voor setpoint (airco voor CV)
                    if current_temp <= airco_on_threshold then
					reden="Normal: Start vlak voor setpoint"
                        if allow_start_b then
                            set_if_needed("Airco Power Beneden", "On",reden)
                            set_setpoint_if_needed("6352", Setpoint + Setpoint_offset_start,reden)
                            set_var_if_needed("airco_heating_startup", "1",reden)
                            set_if_needed("Swing Up/Down Beneden", "Set Level 50",reden)
                            set_if_needed("Operation Mode Beneden", "Set Level 20",reden)
                        end
                    end

                    -- Coldday hold: airco zachtjes aan om CV te ontlasten
                    if coldday and current_temp >= airco_hold_threshold and not Heating then
					reden="Normal: Coldday hold: airco zachtjes aan om CV te ontlasten"
                        if od["Airco Power Beneden"] == "On" then
                            set_if_needed("Fan Beneden", "Off",reden)
                            set_setpoint_if_needed("6352", airco_hold_threshold,reden)
                            set_var_if_needed("airco_heating_startup", "0",reden)
                        end
                    end

                    -- Normale uitschakelconditie (boven setpoint, CV niet meer warm)
                    if current_temp >= airco_off_threshold and not Heating then
						reden="Normal: Normale uitschakelconditie (boven setpoint, CV niet meer warm)"
                        if od["Airco Power Beneden"] == "On" and Min_On_b then
                            if not KeepOn_b then set_if_needed("Airco Power Beneden", "Off", reden) end
                        end
                    end

                ----------------------------------------------------
                -- TURBO MODE
                ----------------------------------------------------
                elseif HeatingMode == "Turbo" then

                    if Heating then
                        if allow_start_b then
						reden="Turbo: Opstarten met heating"
                            set_if_needed("Airco Power Beneden", "On",reden)
                            set_setpoint_if_needed("6352", Setpoint + Setpoint_offset_start,reden)
                            set_var_if_needed("airco_heating_startup", "1",reden)
                            set_if_needed("Swing Up/Down Beneden", "Set Level 50",reden)
                            set_if_needed("Fan Beneden", "Off",reden)
                            set_if_needed("Operation Mode Beneden", "Set Level 20",reden)
                        end
                    else
                        if od["Airco Power Beneden"] == "On" and Min_On_b then
                            if current_temp >= airco_off_threshold and not KeepOn_b then
								reden="Turbo: current_temp >= airco_off_threshold and not KeepOn_b"
                                set_if_needed("Airco Power Beneden", "Off",reden)
                            elseif coldday and current_temp >= airco_off_threshold then
								reden="Turbo: coldday and current_temp >= airco_off_threshold"
                                set_if_needed("Fan Beneden", "Off",reden)
                                set_setpoint_if_needed("6352", airco_hold_threshold,reden)
                                set_var_if_needed("airco_heating_startup", "0",reden)
                            elseif ontime_b >= 1800 and not KeepOn_b then
								reden="Turbo: ontime_b >= 1800 and not KeepOn_b"
                                set_if_needed("Airco Power Beneden", "Off",reden)
                            end
                        end
                    end

                ----------------------------------------------------
                -- TURB+ MODE (alle airco’s volgen CV, met boost boven)
                ----------------------------------------------------
                elseif HeatingMode == "Turb+" then

                    if Heating then
                        -- Beneden (met startup-boost via airco_heating_startup)
                        if allow_start_b then
                            set_if_needed("Airco Power Beneden", "On")
                            set_setpoint_if_needed("6352", Setpoint + Setpoint_offset_start)
                            set_var_if_needed("airco_heating_startup", "1")
                            set_if_needed("Swing Up/Down Beneden", "Set Level 50")
                            set_if_needed("Fan Beneden", "Off")
                            set_if_needed("Operation Mode Beneden", "Set Level 20")
                        end

                        -- 1e (startup-boost via ontime_1e)
                        if allow_start_1e then
                            set_if_needed("Airco Power 1e", "On")
                            set_if_needed("Swing Up/Down 1e", "Set Level 50")
                            set_if_needed("Operation Mode 1e", "Set Level 20")
                            set_if_needed("Fan 1e", "Off")
                        end
                        if od["Airco Power 1e"] == "On" and commandArray["Airco Power 1e"] ~= "Off" then
                            if ontime_1e < 600 then
                                set_setpoint_if_needed("6361", Setpoint + Setpoint_offset_start)
                            else
                                set_setpoint_if_needed("6361", Setpoint + Setpoint_offset)
                            end
                        end
						
                        -- Zolder (startup-boost via ontime_z)
                        if allow_start_z then
                            set_if_needed("Airco Power Zolder", "On")
                            set_if_needed("Swing Up/Down Zolder", "Set Level 50")
                            set_if_needed("Operation Mode Zolder", "Set Level 20")
                            set_if_needed("Fan Zolder", "Off")
                        end
                        if od["Airco Power Zolder"] == "On" and commandArray["Airco Power Zolder"] ~= "Off" then
                            if ontime_z < 600 then
                                set_setpoint_if_needed("6367", Setpoint + Setpoint_offset_start)
                            else
                                set_setpoint_if_needed("6367", Setpoint + Setpoint_offset)
                            end
                        end

                    else
                        if od["Airco Power Beneden"] == "On" and Min_On_b and not KeepOn_b 	then set_if_needed("Airco Power Beneden", "Off") end
                        if od["Airco Power 1e"] == "On" and Min_On_1e and not KeepOn_1e 	then set_if_needed("Airco Power 1e", "Off") end
                        if od["Airco Power Zolder"] == "On" and Min_On_z and not KeepOn_z 	then set_if_needed("Airco Power Zolder", "Off") end
                    end

                ----------------------------------------------------
                -- MAX MODE (Turb+ + LivingFlame)
                ----------------------------------------------------
                elseif HeatingMode == "Max" then

                    if Heating then
                        -- Beneden (met startup-boost via airco_heating_startup)
                        if allow_start_b then
                            set_if_needed("Airco Power Beneden", "On")
                            set_setpoint_if_needed("6352", Setpoint + Setpoint_offset_start)
                            set_var_if_needed("airco_heating_startup", "1")
                            set_if_needed("Swing Up/Down Beneden", "Set Level 50")
                            set_if_needed("Fan Beneden", "Off")
                            set_if_needed("Operation Mode Beneden", "Set Level 20")
                        end

                        -- 1e (startup-boost via ontime_1e)
                        if allow_start_1e then
                            set_if_needed("Airco Power 1e", "On")
                            set_if_needed("Swing Up/Down 1e", "Set Level 50")
                            set_if_needed("Operation Mode 1e", "Set Level 20")
                            set_if_needed("Fan 1e", "Off")
                        end
                        if od["Airco Power 1e"] == "On" and commandArray["Airco Power 1e"] ~= "Off" then
                            if ontime_1e < 600 then
                                set_setpoint_if_needed("6361", Setpoint + Setpoint_offset_start)
                            else
                                set_setpoint_if_needed("6361", Setpoint + Setpoint_offset)
                            end
                        end

                        -- Zolder (startup-boost via ontime_z)
                        if allow_start_z then
                            set_if_needed("Airco Power Zolder", "On")
                            set_if_needed("Swing Up/Down Zolder", "Set Level 50")
                            set_if_needed("Operation Mode Zolder", "Set Level 20")
                            set_if_needed("Fan Zolder", "Off")
                        end
                        if od["Airco Power Zolder"] == "On" and commandArray["Airco Power Zolder"] ~= "Off" then
                            if ontime_z < 600 then
                                set_setpoint_if_needed("6367", Setpoint + Setpoint_offset_start)
                            else
                                set_setpoint_if_needed("6367", Setpoint + Setpoint_offset)
                            end
                        end

                        -- LivingFlame aan (alleen in Max)
                        if od["LivingFlame"] == "Off" then
                            commandArray[#commandArray+1] = { ["LivingFlame"] = "Set level 20" }
                            commandArray[#commandArray+1] = { ["LivingFlame"] = "Set level 50 AFTER 10" }
                        end

                    else
                        if od["Airco Power Beneden"] == "On" and Min_On_b and not KeepOn_b 	then set_if_needed("Airco Power Beneden", "Off") end
                        if od["Airco Power 1e"] == "On" and Min_On_1e and not KeepOn_1e 	then set_if_needed("Airco Power 1e", "Off") end
                        if od["Airco Power Zolder"] == "On" and Min_On_z and not KeepOn_z 	then set_if_needed("Airco Power Zolder", "Off") end

                        -- LivingFlame uit (alleen in Max)
                        if od["LivingFlame"] == "On" then
                            commandArray[#commandArray+1] = { ["LivingFlame"] = "Set level 30" }
                            commandArray[#commandArray+1] = { ["LivingFlame"] = "Set level 10 AFTER 10" }
                        end
                    end

                ----------------------------------------------------
                -- X MODE (permanent aan, maar harde guard OVERRULET)
                ----------------------------------------------------
                elseif HeatingMode == "X" then

                    -- Beneden
                    if allow_start_b then
                        set_if_needed("Airco Power Beneden", "On")
                        set_setpoint_if_needed("6352", Setpoint)
                        set_var_if_needed("airco_heating_startup", "0")
                        set_if_needed("Swing Up/Down Beneden", "Set Level 50")
                        set_if_needed("Fan Beneden", "Set Level 10")
                        set_if_needed("Operation Mode Beneden", "Set Level 20")
                    end

                    -- 1e
					if allow_start_1e then set_if_needed("Airco Power 1e", "On") end
					if od["Airco Power 1e"]=="On" and commandArray["Airco Power 1e"] ~= "Off" then
						set_setpoint_if_needed("6361", Setpoint - 1)
						set_var_if_needed("airco_heating_startup", "0")
						set_if_needed("Swing Up/Down 1e", "Set Level 50")
						set_if_needed("Operation Mode 1e", "Set Level 20")
						set_if_needed("Fan 1e", "Off")
					end

                    -- Zolder
					if allow_start_z then set_if_needed("Airco Power Zolder", "On") end
					if od["Airco Power Zolder"]=="On" and commandArray["Airco Power Zolder"] ~= "Off" then
						set_setpoint_if_needed("6367", Setpoint - 2)
					    set_var_if_needed("airco_heating_startup", "0")
                        set_if_needed("Swing Up/Down Zolder", "Set Level 50")
                        set_if_needed("Operation Mode Zolder", "Set Level 20")
                        set_if_needed("Fan Zolder", "Off")
                    end

                end -- einde mode-logica
            end -- einde abort_airco_logic

            ----------------------------------------------------
            -- EINDE SCRIPT (GEEN return!)
            ----------------------------------------------------
			if (debugprinttotal== true and dc["Binnen"]) or printdone then
				print(
					"🔥❄️ HVAC Airco&Nest",
					" | NestTemp="..round(otherdevices_temperature["NEST temp"],1).."*C"..
					" | NestSp="..round(otherdevices_svalues["NEST setpoint"],1).."*C"..
					" | TransferOffset="..round(transfer_offset,1).."*C",
					" | Mode="..HeatingMode..
					" | Temp="..current_temp.."*C"..
					" | SP="..Setpoint.."*C"..
					" | ThrOn="..airco_on_threshold.."*C"..
					" | ThrHold="..airco_hold_threshold.."*C"..
					" | ThrOff="..airco_off_threshold.."*C"..
					" | Hard="..airco_hard_guard.."*C",
					" | Heating="..tostring(Heating)..
					" | CVuse="..CV_usage.."W"..
					" | Coldday="..tostring(coldday)..
					" | Guard="..tostring(current_temp > airco_hard_guard)..
					" | Hold="..tostring(coldday and current_temp >= airco_hold_threshold and not Heating),

					-- Runtimes ON
					" | onB="..ontime_b.." sec"..
					" | on1e="..ontime_1e.." sec"..
					" | onZ="..ontime_z.." sec"..

					-- Runtimes OFF
					" | offB="..offtime_b.." sec"..
					" | off1e="..offtime_1e.." sec"..
					" | offZ="..offtime_z.." sec",

					-- Boost
					" | BoostB="..tostring(startup_flag==1 and od["Airco Power Beneden"]=="On" and ontime_b < 600)..
					" | Boost1e="..tostring(od["Airco Power 1e"]=="On" and ontime_1e < 600)..
					" | BoostZ="..tostring(od["Airco Power Zolder"]=="On" and ontime_z < 600)..

					-- KeepOn
					" | KeepB="..tostring(KeepOn_b)..
					" | Keep1e="..tostring(KeepOn_1e)..
					" | KeepZ="..tostring(KeepOn_z),

					-- Min_On
					" | MinOnB="..tostring(Min_On_b)..
					" | MinOn1e="..tostring(Min_On_1e)..
					" | MinOnZ="..tostring(Min_On_z)..

					-- Min_Off
					" | MinOffB="..tostring(Min_Off_b)..
					" | MinOff1e="..tostring(Min_Off_1e)..
					" | MinOffZ="..tostring(Min_Off_z),

					-- Allow start (Min_Off guard)
					" | AllowB="..tostring(allow_start_b)..
					" | Allow1e="..tostring(allow_start_1e)..
					" | AllowZ="..tostring(allow_start_z),

					-- Airco status
					" | B="..od["Airco Power Beneden"]..
					" | 1e="..od["Airco Power 1e"]..
					" | Z="..od["Airco Power Zolder"]
				)
			end
        end -- skip
    end -- master
end -- function
my external helperfunction tdiff :

Code: Select all

function TDiff(input)
    local prev = difference
    local name, idx
    for i, v in pairs(otherdevices_idx) do
        if v == input or i == input then
            name = i; idx = v
        end
    end
    if name == nil then name = input end

    local s = otherdevices_lastupdate and otherdevices_lastupdate[name]
    if s ~= nil and name ~= "" then
        local t2 = _parse_ts(s)
        if t2 then
            local t1 = _time()
            if type(round) == "function" then
                difference = round(_difftime(t1, t2), 0)
            else
                difference = math.floor(_difftime(t1, t2) + 0.5)
            end
        else
            -- keep 'difference' unchanged if parse failed (matches original behavior)
        end
    else
        print("TDIFF " .. tostring(input) .. " -- " .. tostring(name) .. "=nil")
        -- keep 'difference' unchanged (matches original)
    end
    return difference
end
why an extra setpoint : well this way it keeps running even if the cloud is down. You always have your local housesetpoint that you can use.
The only thing youll miss is the link between thermostat and airco setpoint when cloud is down (CV still works and airco also sill works, just not linked) this way its failsafe as long as you have power to feed the airco. I also have a virtual mode switch "normal", "turbo", "turbo+"
Normal = self explaining.
Turbo -> airco livingroom is turned on together with cv to reduce gas use.
Turbo+ -> same as turbo but also turns on airco on 1st and 2th floor.
Max = also switch on electric heater ( i never use it)
x = always on. decoupled keep airco always on in heating mode.

I have a couple of redundant things : i check also "Cv koud" and cv and airco power usage, those are just expirimental (seem to work with my poweplugs) just in case something fails as a "late backup" but it should run without it. Maybe couple of things not as nice as i have running it

:ugeek: Dont think this is an out of the box routine, i adjusted the offset values to my home, you have a warmup curve for cv and airco + an the heatbuffer in every home wich is very specific. So you'll need to adjust till you have the comfort you want. :ugeek:

(a good reader notices i have a sensor "Cv koud" what is kaku doorsensor with a 30*C clickson mounted at the place of the reed contact. It was just for testing and diagnostic, but since i have i keep using it as backup).

What is that part at the beginning with the table at the beginning ? Well i have a lot of devices in domoticz, this is my common way to have script parts only running and using time if relevant sensors are triggering the event system. I want to reduce cpu use as much as possible to keep things smooth and fast. (i have about 80 devices a minute that trigger the event system, so a lot & i need to keep up performance)

Why plain lua ? because i know the language and use lua also on other things. So just to lazy to learn dzevents (sorry)
So not out of the box working but a source of inspiration that needs tweaking and adjustment ... Have fun with it.

p.s. I also have my curtains opening when solar >1000W to let sunwarmt in and closing when <400W with a min. timewindow.
Rpi & Win x64. Using : cam's,RFXCom, LaCrosse, RFY, HuE, google, standard Lua, Tasker, Waze traveltime, NLAlert&grip2+,curtains, vacuum, audioreceiver, smart-heating&cooling + many more (= automate all repetitive simple tasks)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest