thermostat for cooling and heating

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

megamarco83
Posts: 108
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

thermostat for cooling and heating

Post by megamarco83 »

hi, i created a lua thermostat that is able to menage:
hysterisys modificable
set if it's heating or cooling mode
i simply created:
1) dummy device named "temp dummi mqtt" with a ds18b20 that is the probe to read the temperature
2) dummy device as switch named "prova termostato" (that is the switch connected to the room that i want to cool or heat)
3) a summy device as thermostat named "termostato mansarda" that is the set point

Code: Select all

--
-- Domoticz passes information to scripts through a number of global tables
--
--
-- 
--

local heating_probe = 'temp dummi mqtt' 
local thermostat_setpoint = 'termostato mansarda'
local heating_unit = 'prova termostato'

-- Use when a combined sensor (e.g. temperature and humidity) is used
-- Replace in "otherdevices[heating_probe]" to "otherdevices[heating_probe]" by "temp_only" (in the 2nd "if" and in the "elseif".
-- Remove the -- in the next two lines: 

--local naartekst = (tostring (otherdevices[heating_probe]))
--local temp_only = (string.sub(naartekst,1,4)) -- the digits (1,4) do point out what characters of the string are needed.


local hysteresis = 0.5
local season = 2  -- 1=winter(heating) 2=summer(cooling)

commandArray = {}





-- loop through all the devices
for deviceName,deviceValue in pairs(otherdevices) do
  if (season ~= 2) then
    if (deviceName== thermostat_setpoint ) then

        if tonumber(deviceValue) < tonumber(otherdevices[heating_probe]-hysteresis) then
        
            if (otherdevices[heating_unit] == "On") then
             --   commandArray['SendNotification']='Heating is off'
                commandArray[heating_unit]='Off'
                print("Heating is Off")
            end
            
        elseif tonumber(deviceValue) > tonumber(otherdevices[heating_probe]+hysteresis) then
            if (otherdevices[heating_unit] == "Off") then
                commandArray[heating_unit]='On'
            --    commandArray['SendNotification']='Heating is on'
                print("Heating is On")
            end
        end
    end
    elseif (deviceName== thermostat_setpoint ) then
        if tonumber(deviceValue) > tonumber(otherdevices[heating_probe]+hysteresis) then
        
            if (otherdevices[heating_unit] == "On") then
             --   commandArray['SendNotification']='Cooling is off'
                commandArray[heating_unit]='Off'
                print("Cooling is Off")
            end
            
        elseif tonumber(deviceValue) < tonumber(otherdevices[heating_probe]-hysteresis) then
            if (otherdevices[heating_unit] == "Off") then
                commandArray[heating_unit]='On'
            --    commandArray['SendNotification']='Cooling is on'
                print("Cooling is On")
            end
        end    
    end
    
end  


-- loop through all the variables
for variableName,variableValue in pairs(uservariables) do

end

return commandArray
now i would like to implement in dzvents adding:
1) i have every room of my house that is indipendent (every room has one temperature sensor, and every room is able to heat/cooling without triggering the other) so using a code that could be mody adding rooms
2) the possibility to plan the days and hours where i want to have different set point for every room
is it possible to have only one dzvents to perform that?
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

megamarco83 wrote: Thursday 11 October 2018 15:45 I created a lua thermostat that is able to manage:
hysterisys modificable
set if it's heating or cooling mode
now i would like to implement in dzVents adding:
1) I have every room of my house that is independent (every room has one temperature sensor, and every room is able to heat/cooling without triggering the other) so using a code that could be mody adding rooms
2) the possibility to plan the days and hours where i want to have different set point for every room
is it possible to have only one dzvents to perform that?
1) Yes this is possible. My approach would be to use a multilevel table with room names and device ID's. Something like:
{"room":[temperature sensor, setpoint device, radiator valve],"next room":[temperature sensor, setpoint device, radiator valve], .... }
{"Living":[490,491,492],"Kitchen":[493,94,495],"master bedroom":[496,497,498],.....}
and loop over the rooms in a time triggered script.

Question is, do you want to define this table in a domoticz variable or direct in the dzVents script.
The advantage of the variable is that you can even control it from outside domoticz with a JSON call and do not have to modify the script when you want add or modify something.

2) this is a standard possibility for thermostat devices in domoticz; just like timers for switches. No need to script this
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

Could be something like the script below.
You first have to create a uservar like described in the script. I tried to copy the logic from your Lua script but I am not sure I completely understand so it might be that you have to switch < to > or vice versa.
You can use the Thermostat Setpoint timer area to enter your setpoint schedules per day/time.

Have Fun!

Code: Select all

--[[ 
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":2088,"t":244,"v":2093},{"room":"room3","s":3088,"t":344,"v":3093}]}
    
    where the strings rooms, room, s, t, v are keys and must not be changed.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    
]]--
return {
   
    on     = {  timer       = { "every 5 minutes" },                    -- adjust to your needs
                  devices     = { "zoneTrigger" },                          -- Only to trigger during test and development
             },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,          -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        -- initialize table
        t = {}
                
        -- do everything :-)
        local function processRooms(t)
            local hysteresis = 0.5
            local season = "on 20/3-31/10"  -- Warm season 

            for i=1,#t.rooms do                            -- loop trought the rooms
                 local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                
                if dz.time.matchesRule(season) then
                    -- Cooling
                    if      setPoint < ( temperature - hysteresis ) then
                            radiatorValve.switchOff().checkFirst()
                    elseif  setPoint > ( temperature + hysteresis ) then
                            radiatorValve.switchOn().checkFirst()
                    end  
                else
                    -- Heating
                    if      setPoint > ( temperature + hysteresis ) then
                            radiatorValve.switchOff().checkFirst()
                    elseif  setPoint < ( temperature - hysteresis ) then
                            radiatorValve.switchOn().checkFirst()
                    end 
                end  
               
            end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: thermostat for cooling and heating

Post by emme »

Ciao,

I've done something similar:
I created some virtual thermostat for each room (where I have thermos and zWave valves)
each room has it own setpoint, temp sensors and behaviour...
more, I have a window sensor that enable or disable the temp (if window is open, heating is disable)
this is the script that handle all:

Code: Select all

--[[
+--------------------------------------------+
|    Script Per aggiustamento temperatura    |
|  - - - - - - - - - - - - - - - - - - - - - |

]]

-- Caricamento Array camera e impostazioni
--                         Nome Temp,        Nome SetPoint, Voluta, tdelta, Range temperature setPoint Off, min, Max, step, offset, mag finestra per disabilitazione, minuti prima di disabilitare
local roomAdjust  = {}
roomAdjust['Camera']    = { {'TEM_Camera', 'TEM_Camera_na'},     'SPC_Camera',    'TEMP-Camera',    0.3, 4, 7, 28, 0.5, 0, 'MAG_Camera_Finestra',    15 }
roomAdjust['Cameretta'] = {'TEM_Cameretta',                      'SPC_Cameretta', 'TEMP-Cameretta', 0.3, 4, 7, 28, 0.5, 0, 'MAG_Cameretta_Finestra', 15 }
roomAdjust['Sala']      = { {'TEM_Sala_Pranzo_na', 'TEM_Sala'} , 'SPC_Sala',      'TEMP-Sala',      0.3, 4, 7, 28, 0.5, -1, 'MAG_Sala_Finestra',      15 }
roomAdjust['Cucina']    = {'TEM_Cucina',                         'SPC_Cucina',    'TEMP-Cucina',    0.3, 4, 7, 28, 0.5, 0, 'MAG_Cucina_Finestra',    15 }

local tRif   = 0
local stpAct = 0
local stpNew = 0
local dBoost = 10 --BOOSTER: se il setpoint scende oltre i 10° di delta con la TVoluta al raggiungimento della temperatura risale più rapidamente

return {
	on = {
		timer = { 'every 3 minutes on -15/4,15/10-'	},
	    },
	
	logging = {
        level = domoticz.LOG_INFO,
        marker = "[TEMP-KEEPER] ==> "
        },
    
	execute = function(dz, tmrNull)
        for roomId, roomInfo in pairs(roomAdjust) do
            if type(roomInfo[1]) == 'table' then 
                local tTot = 0
                for k = 1, #roomInfo[1] do
                    tTot = tTot + dz.utils.round(dz.devices(roomInfo[1][k]).temperature,1)
                end 
                actTemp = tTot / #roomInfo[1]
                dz.log('['..roomId..']'..' ambiente con più sonde temperature, indicazione media: '..tostring(actTemp)..'°C')
            else
                actTemp = dz.utils.round(dz.devices(roomInfo[1]).temperature,1)
            end 

            if dz.devices(roomInfo[3]).levelName == 'Off' then
                tWnt = 4
            else
                tWnt = tonumber(dz.devices(roomInfo[3]).levelName)
            end 
            
            tRif   = dz.utils.round(actTemp,1) + roomInfo[9]
            stpAct = dz.devices(roomInfo[2]).setPoint
            stpNew = stpAct
            finSts = dz.devices(roomInfo[10])
            if finSts.state == 'On' and finSts.lastUpdate.minutesAgo > roomInfo[11] then
                if stpAct ~= roomInfo[5] then
                    dz.log('['..roomId..']: Finestra di riferimento aperta, spegnimento Termo!!')
                    dz.devices(roomInfo[2]).updateSetPoint(roomInfo[5])
                end
            elseif math.abs(tRif - tWnt) > roomInfo[4] then
                dz.log('['..roomId..']:T rilevata: '..tRif..'  T impostata: '..tWnt..'  Delta: '..(tRif - tWnt))
                if tRif > tWnt then
                    stpNew = stpAct - roomInfo[8]
                    if stpNew < roomInfo[6] then stpNew = roomInfo[6] end 
                elseif tRif < tWnt then
                    if (tRif - stpAct) > dBoost then  
                        stpNew = dz.utils.round(stpAct + ((tWnt - stpAct ) / 2), 0)
                        dz.log('['..roomId..']: Booster Up '..stpAct..' ==> '..stpNew)
                    else
                        stpNew = stpAct + roomInfo[8]
                    end 
                    if stpNew > roomInfo[7] then stpNew = roomInfo[7] end 
                end 
            
                if stpAct ~= stpNew then
                    dz.log('['..roomId..']:Intevento sul termostato, da '..stpAct..' a '..stpNew)
                    dz.devices(roomInfo[2]).updateSetPoint(stpNew)
                end 
            end
        end 
	end
}
The most dangerous phrase in any language is:
"We always done this way"
megamarco83
Posts: 108
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: thermostat for cooling and heating

Post by megamarco83 »

waaren wrote: Friday 12 October 2018 1:37 Could be something like the script below.
You first have to create a uservar like described in the script. I tried to copy the logic from your Lua script but I am not sure I completely understand so it might be that you have to switch < to > or vice versa.
You can use the Thermostat Setpoint timer area to enter your setpoint schedules per day/time.

Have Fun!
thanks Waaren to your script!! amazing idea using user variable
i study your code (i'm a beginner so it's a good way to understand code) and i play with it just to learn.

Code: Select all

--[[ 
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":2088,"t":244,"v":2093},{"room":"room3","s":3088,"t":344,"v":3093}]}
    
    where the strings rooms, room, s, t, v are keys and must not be changed.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    
     define a switch for chiller (COOLER_UNIT)
    define a switch for PDC  (HEATER_UNIT)
]]--
return {
   
    on     = {  timer       = { "every 1 minutes" },                    -- adjust to your needs
                  devices     = { "zoneTrigger" },                          -- Only to trigger during test and development
             },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,          -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        local heating = dz.devices("HEATER_UNIT") --NAME OF SWITCH FOR HEATER UNIT
        local cooling = dz.devices("COOLER_UNIT") --NAME OF SWITCH FOR COLER UNIT
        -- initialize table
        t = {}
                
        -- do everything :-)
        local function processRooms(t)
            local hysteresis = 0.5
            local season = "on 20/3-31/10"  -- Warm season (cooling)

            for i=1,#t.rooms do                            -- loop trought the rooms
                 local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                
                if dz.time.matchesRule(season) then
                    -- Cooling
                    if      temperature < ( setPoint ) then  -- stop cooling
                            radiatorValve.switchOff().checkFirst()
                            cooling.switchOff().checkFirst() --stop chiller
                    elseif  temperature > ( setPoint + hysteresis ) then  --start cooling
                            radiatorValve.switchOn().checkFirst()
                            cooling.switchOn().checkFirst() --start chilller
                    end  
                else
                    -- Heating
                    if      temperature > ( setPoint ) then  -- stop heating
                            radiatorValve.switchOff().checkFirst()
                            heating.switchOff().checkFirst() --stop PDC
                    elseif  temperature < ( setPoint - hysteresis ) then --start heating
                            radiatorValve.switchOn().checkFirst()
                            heating.switchOn().checkFirst() --start PDC
                    end 
                end  
               
            end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
Image4.jpg
Image4.jpg (87.6 KiB) Viewed 4491 times
Image3.jpg
Image3.jpg (49.24 KiB) Viewed 4491 times
Image5.jpg
Image5.jpg (88.92 KiB) Viewed 4491 times


some consideration:
1) i change the way of controlling heater / cooling just modify the code. now i compare the temperature read from the probe to setpoint. For me is more simple to understand :)


2)i forgot one important thing:
every valve is corrisponding to a circuit, so i open the valve to the related ciruit, but i have also to trigger the relay for heater unit (that is idx48) or when i cooling i need to activate the relay of cooler unit (that is idx49)
in other words, if one or more of valve switch (idx45,46,47) are on -> i need also to turn on: idx48(if i'm heating) - idx49(if i'm cooling)
i solve using:
local heating = dz.devices("HEATER_UNIT") --NAME OF SWITCH FOR HEATER UNIT
local cooling = dz.devices("COOLER_UNIT") --NAME OF SWITCH FOR COLER UNIT
cooling.switchOff().checkFirst() --stop chiller
cooling.switchOn().checkFirst() --start chiller
heating.switchOff().checkFirst() --stop PDC
heating.switchOn().checkFirst() --start PDC

anyway i do not know it they are "elegant" way to proceed :-) but point 1) and 2) are working



now point 3) and $) i would like to implement but i not succeed on that :(
3) in the future, if i want for example to control room_C with the same probe of room_B.
So when the valve B (idx46) is triggered i need to trigger also the valve C (idx47)
i can modify the string like this?

{"rooms":[{"room":"room_A","s":42,"t":39,"v":45},{"room":"room_B","s":43,"t":40,"v":46},{"room":"room_C","s":44,"t":41,"v":47}]}
become
{"rooms":[{"room":"room_A","s":42,"t":39,"v":45},{"room":"room_B+C","s":43,"t":40,"v":46,47}]}
is it possible?
i'm not so confident on array usage :(

4) i do not like so much the solution of putting in the code

Code: Select all

 local season = "on 20/3-31/10"  -- Warm season (cooling)
some years could be colder( or warmer) than the previous and so on
and during some month you could have not to use cooling or heating systems :)
so i create a dummy switch (idx=50 name=season) and i set it as a selector
inside the selector i create 3 levels:
0=heating
10=cooling
20=stop
now inside the action i could ser:

Code: Select all

0 = 	http://192.168.0.105:8085/json.htm?type=command&param=updateuservariable&vname=season&vtype=0&vvalue=1
10 = 	http://192.168.0.105:8085/json.htm?type=command&param=updateuservariable&vname=season&vtype=0&vvalue=2
20 = 	http://192.168.0.105:8085/json.htm?type=command&param=updateuservariable&vname=season&vtype=0&vvalue=0
and create a user variable named=season

inside the code how i can implement the control:
if season = 1 -> set code to use heater_unit (idx 48)
if season=2 -> set code to use cooler_unit (idx 49)
if season = 0 -> for every value of every temperature probe (idx39 idx40 idx41 ....) never switch on heater_unit (idx 48) or cooler_unit (idx 49). This could be usefull for example during holidays, vacation...etc etc

5) just to learn

Code: Select all

on     = {  timer       = { "every 1 minutes" }
it activate the dzvent every minute, i see that inside wiki of dzvents in timer trigger rules, there is not the possibility to use seconds.
if i need to use for example the script every 30seconds, how i can do?
i try to use for example:

Code: Select all

on     = {  timer       = { "every 0.5 minutes" }
but is not working :D
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

megamarco83 wrote: Friday 12 October 2018 15:10 i study your code (i'm a beginner so it's a good way to understand code) and i play with it just to learn.

some consideration:
1) i change the way of controlling heater / cooling just modify the code. now i compare the temperature read from the probe to setpoint. For me is more simple to understand :)


2)i forgot one important thing:
every valve is corrisponding to a circuit, so i open the valve to the related ciruit, but i have also to trigger the relay for heater unit (that is idx48) or when i cooling i need to activate the relay of cooler unit (that is idx49)
in other words, if one or more of valve switch (idx45,46,47) are on -> i need also to turn on: idx48(if i'm heating) - idx49(if i'm cooling)

now point 3) and 4) i would like to implement but i not succeed on that :(
3) in the future, if i want for example to control room_C with the same probe of room_B.
So when the valve B (idx46) is triggered i need to trigger also the valve C (idx47)

4) i do not like so much the solution of putting in the code
so i create a dummy switch (idx=50 name=season) and i set it as a selector
inside the selector i create 3 levels:
0=heating
10=cooling
20=stop
now inside the action i could ser:

Code: Select all

0 = 	http://192.168.0.105:8085/json.htm?type=command&param=updateuservariable&vname=season&vtype=0&vvalue=1
10 = 	http://192.168.0.105:8085/json.htm?type=command&param=updateuservariable&vname=season&vtype=0&vvalue=2
20 = 	http://192.168.0.105:8085/json.htm?type=command&param=updateuservariable&vname=season&vtype=0&vvalue=0
and create a user variable named=season

inside the code how i can implement the control:
if season = 1 -> set code to use heater_unit (idx 48)
if season=2 -> set code to use cooler_unit (idx 49)
if season = 0 -> for every value of every temperature probe (idx39 idx40 idx41 ....) never switch on heater_unit (idx 48) or cooler_unit (idx 49). This could be usefull for example during holidays, vacation...etc etc

5) just to learn

Code: Select all

on     = {  timer       = { "every 1 minutes" }
it activate the dzvent every minute, i see that inside wiki of dzvents in timer trigger rules, there is not the possibility to use seconds.
if i need to use for example the script every 30seconds, how i can do?
i try to use for example:

Code: Select all

on     = {  timer       = { "every 0.5 minutes" }
but is not working :D
Very good that you are playing with the script and try to change. For me that is the best way to learn !
1. Top
2. Top
3. {"rooms":[{"room":"room_A","s":42,"t":39,"v":45},{"room":"room_B","s":43,"t":40,"v":46},{"room":"room_C","s":44,"t":41,"v":47}]} would become
{"rooms":[{"room":"room_A","s":42,"t":39,"v":45},{"room":"room_B","s":43,"t":40,"v":46},{"room":"room_C","s":43,"t":40,"v":47}]}
-- In this way valve 47 will "follow" valve 46 because they use the same temperature sensor and setpoint.
4. You could also just read the levelName from the selector switch. -- if dz.devices("selectorName").levelName == "heating" then
5. One way of doing this is using HTTPResponse (see below)

Code: Select all

--[[ 
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":2088,"t":244,"v":2093},{"room":"room3","s":3088,"t":344,"v":3093}]}
    
    where the strings rooms, room, s, t, v are keys and must not be changed.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    
]]--
local HTTPResponseString = "zonebasedTemperatureManagement"
return {
    on     = {  timer           = { "every 5 minutes" },                    -- adjust to your needs
                httpResponses   = { HTTPResponseString },    
                devices         = { "zoneTrigger" },                          -- Only to trigger during test and development
             },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,          -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz,trigger)
        -- initialize table
        t = {}
                
        local function repeatAfter(delay)
            dz.openURL({
                url =  dz.settings['Domoticz url'] .. "/json.htm?type=command&param=getversion",
                method = "GET",
                callback = HTTPResponseString }).afterSec(delay)
        end        
                
        -- do everything :-)
        local function processRooms(t)
            local hysteresis = 0.5
            local season = "on 20/3-31/10"  -- Warm season 

            for i=1,#t.rooms do                            -- loop trought the rooms
                 local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                
                if dz.time.matchesRule(season) then
                    -- Cooling
                    if      setPoint < ( temperature - hysteresis ) then
                            radiatorValve.switchOff().checkFirst()
                    elseif  setPoint > ( temperature + hysteresis ) then
                            radiatorValve.switchOn().checkFirst()
                    end  
                else
                    -- Heating
                    if      setPoint > ( temperature + hysteresis ) then
                            radiatorValve.switchOff().checkFirst()
                    elseif  setPoint < ( temperature - hysteresis ) then
                            radiatorValve.switchOn().checkFirst()
                    end 
                end  
               
            end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
        
        -- repeat after 30 seconds
        if not trigger.isHTTPResponse then
           repeatAfter(30)
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
megamarco83
Posts: 108
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: thermostat for cooling and heating

Post by megamarco83 »

waaren wrote: Friday 12 October 2018 16:54
4. You could also just read the levelName from the selector switch. -- if dz.devices("selectorName").levelName == "heating" then
5. One way of doing this is using HTTPResponse (see below)
4)
good idea!!
i modify the code:

Code: Select all

--[[ 
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":2088,"t":244,"v":2093},{"room":"room3","s":3088,"t":344,"v":3093}]}
    
    where the strings rooms, room, s, t, v are keys and must not be changed.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    
     define a switch for chiller (COOLER_UNIT)
    define a switch for PDC  (HEATER_UNIT)
]]--
return {
   
    on     = {  timer       = { "every 1 minutes" },                    -- adjust to your needs
                  devices     = { "zoneTrigger" },                          -- Only to trigger during test and development
             },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,          -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        local heating = dz.devices("HEATER_UNIT") --NAME OF SWITCH FOR HEATER UNIT
        local cooling = dz.devices("COOLER_UNIT") --NAME OF SWITCH FOR COLER UNIT
        -- initialize table
        t = {}
                
        -- do everything :-)
        local function processRooms(t)
            local hysteresis = 0.5
           -- local season = "on 20/3-31/10"  -- Warm season (cooling)

            for i=1,#t.rooms do                            -- loop trought the rooms
                 local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                
                if dz.devices("Season").levelName == "Cooling" then
                    -- Cooling
                    if      temperature < ( setPoint ) then  -- stop cooling
                            radiatorValve.switchOff().checkFirst()
                            cooling.switchOff().checkFirst() --stop chiller
                    elseif  temperature > ( setPoint + hysteresis ) then  --start cooling
                            radiatorValve.switchOn().checkFirst()
                            cooling.switchOn().checkFirst() --start chilller
                    end  
                end
                if dz.devices("Season").levelName == "Heating" then
                    -- Heating
                    if      temperature > ( setPoint ) then  -- stop heating
                            radiatorValve.switchOff().checkFirst()
                            heating.switchOff().checkFirst() --stop PDC
                    elseif  temperature < ( setPoint - hysteresis ) then --start heating
                            radiatorValve.switchOn().checkFirst()
                            heating.switchOn().checkFirst() --start PDC
                    end 
                end  
                if dz.devices("Season").levelName == "Stop" then
                    cooling.switchOff().checkFirst()
                    heating.switchOff().checkFirst()
                end    
            end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
it's a smart way to write that?
in this way there is a "bug" if i'm on heating for example, and there is swithced on the HEATER_UNIT and i switch the selector (Season) to colling, the HEATER_UNIT will be never swithced off
to correct that i have to call something like that:


if dz.devices("Season").levelName == "Cooling" then
-- Cooling
if temperature < ( setPoint ) then -- stop cooling
radiatorValve.switchOff().checkFirst()
cooling.switchOff().checkFirst() --stop chiller
heating.switchOff().checkFirst() --stop PDC
elseif temperature > ( setPoint + hysteresis ) then --start cooling
radiatorValve.switchOn().checkFirst()
cooling.switchOn().checkFirst() --start chilller
heating.switchOff().checkFirst() --stop PDC
end
end
if dz.devices("Season").levelName == "Heating" then
-- Heating
if temperature > ( setPoint ) then -- stop heating
radiatorValve.switchOff().checkFirst()
heating.switchOff().checkFirst() --stop PDC
cooling.switchOff().checkFirst()
elseif temperature < ( setPoint - hysteresis ) then --start heating
radiatorValve.switchOn().checkFirst()
heating.switchOn().checkFirst() --start PDC
cooling.switchOff().checkFirst()
end
end

i put in red
there is a smart way to menage that?

5)...ehmmmm i do not undestand the code:(

6) how i can launch from web brawser a JSON call to modify for example the setpoint of a room, or switching the selector to sto / cooling whitout using domoticz, but updating the domoticz status?
thanks
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

The stuff that you put in red is not special to dzVents and too dependent on your specific situation for me to comment. You have to figure out the logic for that,
5. What I do here is trigger a JSON call to domoticz after 30 seconds if the script is started because of the timer setting. Domoticz returns this call allmost immediate and because is now also triggered by httpResponses = { HTTPResponseString }, it will execute again in 30.x seconds.
6. Have a look at the domoticz API/JSON wiki
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
megamarco83
Posts: 108
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: thermostat for cooling and heating

Post by megamarco83 »

waaren wrote: Friday 12 October 2018 19:04 The stuff that you put in red is not special to dzVents and too dependent on your specific situation for me to comment. You have to figure out the logic for that,
thanks waaren for your support!
i'm learing so much!
...now i'm in a truble, because with this code:

Code: Select all

--[[ 
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":2088,"t":244,"v":2093},{"room":"room3","s":3088,"t":344,"v":3093}]}
    
    where the strings rooms, room, s, t, v are keys and must not be changed.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    
     define a switch for chiller (COOLER_UNIT)
    define a switch for PDC  (HEATER_UNIT)
]]--
return {
   
    on     = {  timer       = { "every 1 minutes" },                    -- adjust to your needs
                  devices     = { "zoneTrigger" },                          -- Only to trigger during test and development
             },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,          -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        local heating = dz.devices("HEATER_UNIT") --NAME OF SWITCH FOR HEATER UNIT
        local cooling = dz.devices("COOLER_UNIT") --NAME OF SWITCH FOR COLER UNIT
        -- initialize table
        t = {}
                
        -- do everything :-)
        local function processRooms(t)
            local hysteresis = 0.5
           -- local season = "on 20/3-31/10"  -- Warm season (cooling)

            for i=1,#t.rooms do                            -- loop trought the rooms
                 local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                
                if dz.devices("Season").levelName == "Cooling" then
                    -- Cooling
                    if      temperature < ( setPoint ) then  -- stop cooling
                            radiatorValve.switchOff().checkFirst()
                           -- heating.switchOff().checkFirst() --stop PDC (just to be sure)
                           -- cooling.switchOff().checkFirst() --stop chiller
                    elseif  temperature > ( setPoint + hysteresis ) then  --start cooling
                            radiatorValve.switchOn().checkFirst()
                           -- cooling.switchOn().checkFirst() --start chilller
                           -- heating.switchOff().checkFirst() --stop PDC (just to be sure)
                    end  
                end
                if dz.devices("Season").levelName == "Heating" then
                    -- Heating
                    if      temperature > ( setPoint ) then  -- stop heating
                            radiatorValve.switchOff().checkFirst()
                           -- cooling.switchOff().checkFirst() --stop chiller (just to be sure)
                            --heating.switchOff().checkFirst() --stop PDC
                    elseif  temperature < ( setPoint - hysteresis ) then --start heating
                            radiatorValve.switchOn().checkFirst()
                            --heating.switchOn().checkFirst() --start PDC
                           -- cooling.switchOff().checkFirst() --stop chiller (just to be sure)
                    end 
                end  
                if dz.devices("Season").levelName == "Stop" then
                    cooling.switchOff().checkFirst()
                    heating.switchOff().checkFirst()
                end    
            end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
i want to trigger in case of heating
heating.switchOff().checkFirst() --stop PDC when ALL valve are off
heating.switchOn().checkFirst() --start PDC when just one or more valve are ON

in case of cooling i want to trigger:
cooling.switchOff().checkFirst() --stop chiller when ALL valve are off
cooling.switchOn().checkFirst() --start chiller when just one or more valve are ON

but written as my proposal is wrong (i put trigegring line as comment --), because the heating or cooling trigger is mixed with valve activation
maybe it's required another "if" putted outside the reading of valve where we put:
if season is == Heating and one or more valve going ON -> heating.switchOn().checkFirst() --start PDC
otherwise -> heating.switchOff().checkFirst() --stop PDC
if season is == Cooling and one or more valve going ON -> cooling.switchOn().checkFirst() --start chiller
otherwise -> cooling.switchOff().checkFirst() --stop chiller

but i'm not able to put it in the correct way
thanks
megamarco83
Posts: 108
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: thermostat for cooling and heating

Post by megamarco83 »

hi, thanks to Waaren i attach you the code that is working with every room that has it's corresponding setpoint, temperature sensor, and valve
there is also the possibility to have trigegred heater unit or cooling unit (if it's needed)

Code: Select all

--[[ 
    version: 20181014-01
    
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    define a switch for chiller if there is a main switch
    define a switch for heater if there is a main switch
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"heater":1095,"cooler":1096,"selector":"Season","rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":1088,"t":892,"v":1093},{"room":"room3","s":1088,"t":766,"v":1093}]}
    
    where the strings heater,cooler, selector,rooms, room, s, t, v are keys and must not be changed.
    the value heater is the idx or name of the main heater switch. If your system does not have this, leave it out completely
    the value heater is the idx or name of the main cooler switch. If your system does not have this, leave it out completely. 
    the value selector is the idx or name of the selector switch that control if the heating or cooling system is active or stopped both.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    idx are without "" and names are with ""

    Change history:
    20181012-01 Initial setup
    20181012-02 Add Season selector
    20181012-03 Add optional control for main heater / cooler device. Moved some code to functions
    20181012-04 Add optional control for main heater / cooler device
    20181013-01 Moved heater, cooler and selector idx to (JSON) uservariable
    20181014-01 Bugfixes:   defined local heating inside if block causing it to be nil. 
        	            return false from open and shut function could overwrite previous true state

]]--
return {
   	         on     = {  timer       = { "every minute" },    -- adjust to your needs
            },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,        -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        -- initialize table
        t = {}

        -- do everything :-)
        local function processRooms(t)
            local heating if t.heater ~= nil then heating = dz.devices(t.heater) end
            local cooling if t.cooler ~= nil then cooling = dz.devices(t.cooler) end
            local action if t.selector ~= nil then action  = dz.devices(t.selector).levelName else action = "Heating" end  -- defaults to "Heating"
            
            local hysteresis         = 0.5
            local openHeatingValves 
            local openCoolingValves 

            local function open(device) 
                if device == nil then return openHeatingValves end
                device.switchOn().checkFirst()
                return true
            end

            local function shut(device)
                if device == nil then return openCoolingValves end
                device.switchOff().checkFirst()
            end
            
            for i=1,#t.rooms do                            -- loop trough the rooms
                local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                if  action == "Cooling" then
                    if      temperature <  setPoint                 then shut(radiatorValve)  -- stop cooling
                    elseif  temperature > ( setPoint + hysteresis ) then openCoolingValves = open(radiatorValve) end --start cooling
                elseif action == "Heating" then
                    if      temperature >  setPoint                 then shut(radiatorValve)  -- stop heating
                    elseif  temperature < ( setPoint - hysteresis ) then openHeatingValves = open(radiatorValve) end --start heating
                elseif action == "Stop" then 
                    shut(cooling) shut(heating) shut(radiatorValve)
                end 
            end
            if openCoolingValves then open(cooling) else shut(cooling) end
            if openHeatingValves then open(heating) else shut(heating) end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
thanks to Waaren that is the author of the code!
uzturre
Posts: 14
Joined: Wednesday 13 June 2018 10:41
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Basque Country
Contact:

Re: thermostat for cooling and heating

Post by uzturre »

Good morning:
I have installed this script and I get this result, but I can not activate the boiler relay.

Code: Select all

 2018-11-13 10:29:00.633 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for RELE -1-: Switch device adapter
2018-11-13 10:29:00.636 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for RELE -4-: Switch device adapter
2018-11-13 10:29:00.639 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for Season: Switch device adapter
2018-11-13 10:29:00.642 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for SET_A: Thermostat setpoint device adapter
2018-11-13 10:29:00.645 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for TEMPERATURA SALA: Temperature device adapter
2018-11-13 10:29:00.645 Status: dzVents: Debug: zoneTemperatures: Constructed timed-command: Off
2018-11-13 10:29:00.646 Status: dzVents: Debug: zoneTemperatures: Constructed timed-command: Off
2018-11-13 10:29:00.646 Status: dzVents: Info: zoneTemperatures: ------ Finished BEROGAILU -2- 
Thanks.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

uzturre wrote: Tuesday 13 November 2018 10:31 I have installed this script and I get this result, but I can not activate the boiler relay.
I need a bit more information on this. To start with the content of the uservariable "myRooms" and if you modified anything in the script also those modifications. Also the deviceNumber , Type and subType of the boiler relay might be helpful.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
uzturre
Posts: 14
Joined: Wednesday 13 June 2018 10:41
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Basque Country
Contact:

Re: thermostat for cooling and heating

Post by uzturre »

@waaren
I tell you my installation, I have two pi zero w, one pi zero for the temperature probe installed in the room and the other pi zero with the relay modules next to the boiler, in this pi zero I have a module with 2 relays (relay 1 and relay 3) when the relay 1 is activated its contact closes to give way to the current and activate the relay 3. The relay 3 is subject to the start of the relay 1. This I did because it used blockly and in this way I could do the boiler operated at certain times activating relay 1 (relay 1 with time condition) and this way activate relay 3 which in turn had to meet the temperature condition of the room probe. The idx 17 is the temperature probe of the room and for read the temperture in this pi zero I use a Domoticz-remote server.
1.- The script I have not modified anything.
2.- My Uservariable=

Code: Select all

{"heater":5,"cooler":8,"selector":"Season","rooms":[{"room":"room1","s":58,"t":17}]}
3.- I do not have cooler and valves, I have kept the cooler to check that it reads me the idx 8 of the relay correctly

Thanks in advance.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

uzturre wrote: Tuesday 13 November 2018 13:19 @waaren
I tell you my installation, I have two pi zero w, one pi zero for the temperature probe installed in the room and the other pi zero with the relay modules next to the boiler, in this pi zero I have a module with 2 relays (relay 1 and relay 3) when the relay 1 is activated its contact closes to give way to the current and activate the relay 3. The relay 3 is subject to the start of the relay 1. This I did because it used blockly and in this way I could do the boiler operated at certain times activating relay 1 (relay 1 with time condition) and this way activate relay 3 which in turn had to meet the temperature condition of the room probe. The idx 17 is the temperature probe of the room and for read the temperture in this pi zero I use a Domoticz-remote server.
1.- The script I have not modified anything.
2.- My Uservariable=

Code: Select all

{"heater":5,"cooler":8,"selector":"Season","rooms":[{"room":"room1","s":58,"t":17}]}
3.- I do not have cooler and valves, I have kept the cooler to check that it reads me the idx 8 of the relay correctly

Thanks in advance.
Sorry but I don't see how the script can be useful for your situation. It was created to control valves for radiatorvalves in different rooms and optional control main heater / cooler devices.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
uzturre
Posts: 14
Joined: Wednesday 13 June 2018 10:41
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Basque Country
Contact:

Re: thermostat for cooling and heating

Post by uzturre »

@wareen
My intention is that my heating system works with a smart thermostat as a reference for heat control in my house, I thought that your script could work without the valves.
In the forum I found a script for a smart thermostat, but I could not get it to work properly.
Sorry for taking the time to answer me.
Skippiemanz
Posts: 230
Joined: Sunday 14 July 2013 20:21
Target OS: Linux
Domoticz version: 4.10233
Location: Alkmaar, The Netherlands
Contact:

Re: thermostat for cooling and heating

Post by Skippiemanz »

megamarco83 wrote: Sunday 14 October 2018 15:57 hi, thanks to Waaren i attach you the code that is working with every room that has it's corresponding setpoint, temperature sensor, and valve
there is also the possibility to have trigegred heater unit or cooling unit (if it's needed)

Code: Select all

--[[ 
    version: 20181014-01
    
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    define a switch for chiller if there is a main switch
    define a switch for heater if there is a main switch
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"heater":1095,"cooler":1096,"selector":"Season","rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":1088,"t":892,"v":1093},{"room":"room3","s":1088,"t":766,"v":1093}]}
    
    where the strings heater,cooler, selector,rooms, room, s, t, v are keys and must not be changed.
    the value heater is the idx or name of the main heater switch. If your system does not have this, leave it out completely
    the value heater is the idx or name of the main cooler switch. If your system does not have this, leave it out completely. 
    the value selector is the idx or name of the selector switch that control if the heating or cooling system is active or stopped both.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve device in that room
    idx are without "" and names are with ""

    Change history:
    20181012-01 Initial setup
    20181012-02 Add Season selector
    20181012-03 Add optional control for main heater / cooler device. Moved some code to functions
    20181012-04 Add optional control for main heater / cooler device
    20181013-01 Moved heater, cooler and selector idx to (JSON) uservariable
    20181014-01 Bugfixes:   defined local heating inside if block causing it to be nil. 
        	            return false from open and shut function could overwrite previous true state

]]--
return {
   	         on     = {  timer       = { "every minute" },    -- adjust to your needs
            },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,        -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        -- initialize table
        t = {}

        -- do everything :-)
        local function processRooms(t)
            local heating if t.heater ~= nil then heating = dz.devices(t.heater) end
            local cooling if t.cooler ~= nil then cooling = dz.devices(t.cooler) end
            local action if t.selector ~= nil then action  = dz.devices(t.selector).levelName else action = "Heating" end  -- defaults to "Heating"
            
            local hysteresis         = 0.5
            local openHeatingValves 
            local openCoolingValves 

            local function open(device) 
                if device == nil then return openHeatingValves end
                device.switchOn().checkFirst()
                return true
            end

            local function shut(device)
                if device == nil then return openCoolingValves end
                device.switchOff().checkFirst()
            end
            
            for i=1,#t.rooms do                            -- loop trough the rooms
                local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)
                
                if  action == "Cooling" then
                    if      temperature <  setPoint                 then shut(radiatorValve)  -- stop cooling
                    elseif  temperature > ( setPoint + hysteresis ) then openCoolingValves = open(radiatorValve) end --start cooling
                elseif action == "Heating" then
                    if      temperature >  setPoint                 then shut(radiatorValve)  -- stop heating
                    elseif  temperature < ( setPoint - hysteresis ) then openHeatingValves = open(radiatorValve) end --start heating
                elseif action == "Stop" then 
                    shut(cooling) shut(heating) shut(radiatorValve)
                end 
            end
            if openCoolingValves then open(cooling) else shut(cooling) end
            if openHeatingValves then open(heating) else shut(heating) end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
thanks to Waaren that is the author of the code!
First let me say it looks really promising!

I have a hot water boiler and radiator valves in every room.

I've created the user variables and set up 3 test rooms.

When ther is a heat demand i see that the script turns al my valves open(28degrees), but the main heater switch is'nt been activated.

Here is my uservariable input:

Code: Select all

{"heater":4,"cooler":221,"selector":"Seizoen","rooms":[{"room":"WoonkamerLi","s":33,"t":45,"v":13},{"room":"WoonakmerRe","s":33,"t":45,"v":15},{"room":"Gang","s":34,"t":187,"v":17}]}
Ive created a selector switch called Seizoen with 3 values, 0 Off, 10 Zomer, 20 Winter

Any clue where i should look?
Skippiemanz
Posts: 230
Joined: Sunday 14 July 2013 20:21
Target OS: Linux
Domoticz version: 4.10233
Location: Alkmaar, The Netherlands
Contact:

Re: thermostat for cooling and heating

Post by Skippiemanz »

Skippiemanz wrote: Tuesday 13 November 2018 22:26
First let me say it looks really promising!

I have a hot water boiler and radiator valves in every room.

I've created the user variables and set up 3 test rooms.

When ther is a heat demand i see that the script turns al my valves open(28degrees), but the main heater switch is'nt been activated.

Here is my uservariable input:

Code: Select all

{"heater":4,"cooler":221,"selector":"Seizoen","rooms":[{"room":"WoonkamerLi","s":33,"t":45,"v":13},{"room":"WoonakmerRe","s":33,"t":45,"v":15},{"room":"Gang","s":34,"t":187,"v":17}]}
Ive created a selector switch called Seizoen with 3 values, 0 Off, 10 Zomer, 20 Winter

Any clue where i should look?
i Think i found it! The values in the selector switch have been renamed to Heating and Cooling. But now an other error comes in the log:

Code: Select all

2018-11-13 22:37:00.303 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for Airco Relais: Switch device adapter
2018-11-13 22:37:00.304 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for Seizoen: Switch device adapter
2018-11-13 22:37:00.305 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for Setpoint Kamer - Normaal: Thermostat setpoint device adapter
2018-11-13 22:37:00.305 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for Temp Woonkamer: Temperature device adapter
2018-11-13 22:37:00.306 Status: dzVents: Debug: zoneTemperatures: Processing device-adapter for TRV Kamer Li: Thermostat setpoint device adapter
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: Method switchOn is not available for device "TRV Kamer Li" (deviceType=Thermostat, deviceSubType=SetPoint). If you believe this is not correct, please report.
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: An error occured when calling event handler Verwarming
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: ...omoticz/scripts/dzVents/generated_scripts/Verwarming.lua:55: attempt to index a nil value
2018-11-13 22:37:00.306 Status: dzVents: Info: zoneTemperatures: ------ Finished Verwarming
I have POPP Z-wave trv valves witch can be triggered by a setpoint so for example off 8 degrees and on 28 degrees
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren »

Skippiemanz wrote: Tuesday 13 November 2018 22:38 i Think i found it! The values in the selector switch have been renamed to Heating and Cooling. But now an other error comes in the log:

Code: Select all

2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: Method switchOn is not available for device "TRV Kamer Li" (deviceType=Thermostat, deviceSubType=SetPoint). If you believe this is not correct, please report.
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: An error occured when calling event handler Verwarming
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: ...omoticz/scripts/dzVents/generated_scripts/Verwarming.lua:55: attempt to index a nil value
I have POPP Z-wave trv valves witch can be triggered by a setpoint so for example off 8 degrees and on 28 degrees
What happens here is that the script wants to switch a device to an on state. But in your setup this device is not switchable by a dzVents switchOn() or switchOff() function because it is recognized as a setPoint device. So you need an updateSetPoint(setPoint) for that.
If you send me a PM with the types and subtypes of the devices you entered in the uservariable I might be able to amend the script in such a way that it will work for your setup.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Skippiemanz
Posts: 230
Joined: Sunday 14 July 2013 20:21
Target OS: Linux
Domoticz version: 4.10233
Location: Alkmaar, The Netherlands
Contact:

Re: thermostat for cooling and heating

Post by Skippiemanz »

waaren wrote: Tuesday 13 November 2018 23:26
Skippiemanz wrote: Tuesday 13 November 2018 22:38 i Think i found it! The values in the selector switch have been renamed to Heating and Cooling. But now an other error comes in the log:

Code: Select all

2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: Method switchOn is not available for device "TRV Kamer Li" (deviceType=Thermostat, deviceSubType=SetPoint). If you believe this is not correct, please report.
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: An error occured when calling event handler Verwarming
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: ...omoticz/scripts/dzVents/generated_scripts/Verwarming.lua:55: attempt to index a nil value
I have POPP Z-wave trv valves witch can be triggered by a setpoint so for example off 8 degrees and on 28 degrees
What happens here is that the script wants to switch a device to an on state. But in your setup this device is not switchable by a dzVents switchOn() or switchOff() function because it is recognized as a setPoint device. So you need an updateSetPoint(setPoint) for that.
If you send me a PM with the types and subtypes of the devices you entered in the uservariable I might be able to amend the script in such a way that it will work for your setup.
Thanks! PM is on it's way!

If it works ill update this post with the working solution!
Skippiemanz
Posts: 230
Joined: Sunday 14 July 2013 20:21
Target OS: Linux
Domoticz version: 4.10233
Location: Alkmaar, The Netherlands
Contact:

Re: thermostat for cooling and heating

Post by Skippiemanz »

Skippiemanz wrote: Wednesday 14 November 2018 0:01
waaren wrote: Tuesday 13 November 2018 23:26
Skippiemanz wrote: Tuesday 13 November 2018 22:38 i Think i found it! The values in the selector switch have been renamed to Heating and Cooling. But now an other error comes in the log:

Code: Select all

2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: Method switchOn is not available for device "TRV Kamer Li" (deviceType=Thermostat, deviceSubType=SetPoint). If you believe this is not correct, please report.
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: An error occured when calling event handler Verwarming
2018-11-13 22:37:00.306 Status: dzVents: Error (2.4.7): zoneTemperatures: ...omoticz/scripts/dzVents/generated_scripts/Verwarming.lua:55: attempt to index a nil value
I have POPP Z-wave trv valves witch can be triggered by a setpoint so for example off 8 degrees and on 28 degrees
What happens here is that the script wants to switch a device to an on state. But in your setup this device is not switchable by a dzVents switchOn() or switchOff() function because it is recognized as a setPoint device. So you need an updateSetPoint(setPoint) for that.
If you send me a PM with the types and subtypes of the devices you entered in the uservariable I might be able to amend the script in such a way that it will work for your setup.
Thanks! PM is on it's way!

If it works ill update this post with the working solution!
Waaren provided me thsi working setup for operatingf thermostat radiator vales with setpoints instead of on/of switching.

I added a on and off hysterisis to flatten out the large temp spikes

The script checks witch type of device it is.

Only downside to this script is that the amount of characters in the user variable is limited! so i can only switch 3 rooms instead of the derired 6 rooms.

Code: Select all

--[[ 
    version: 20181014-01
    
    This script manage the different heating zones 
    
    Before making this script active you should first create a uservariable type string, named myRooms.
    define a switch for chiller if there is a main switch
    define a switch for heater if there is a main switch
    The name and value of this variable are case sensitive and the value must follow this lay-out:
   {"heater":1095,"cooler":1096,"selector":"Season","rooms":[{"room":"room1","s":1088,"t":144,"v":1093},{"room":"room2","s":1088,"t":892,"v":1093},{"room":"room3","s":1088,"t":766,"v":1093}]}
    
    where the strings heater,cooler, selector,rooms, room, s, t, v are keys and must not be changed.
    the value heater is the idx or name of the main heater switch. If your system does not have this, leave it out completely
    the value heater is the idx or name of the main cooler switch. If your system does not have this, leave it out completely. 
    the value selector is the idx or name of the selector switch that control if the heating or cooling system is active or stopped both.
    the values room1, room2 etc, are the zonenames or roomnames and can be changed
    the value after "s" is the id of the setpoint device in that room
    the value after "t" is the id of the temperature sensor in that room
    the value after "v" is the id of the radiator valve in that room (can be valvetype switch or valvetype setPoint  )
    idx are without "" and names are with ""

    Change history:
    20181012-01 Initial setup
    20181012-02 Add Season selector
    20181012-03 Add optional control for main heater / cooler device. Moved some code to functions
    20181012-04 Add optional control for main heater / cooler device
    20181013-01 Moved heater, cooler and selector idx to (JSON) uservariable
    20181014-01 Bugfixes:   defined local heating inside if block causing it to be nil. 
                            return false from open and shut function could overwrite previous true state
    20181114-01 Open and Shut also for setPoint TRV's
    20181130-01 Add On and Off Hysterisis

]]--
return {
   	         on     = {  timer       = { "every minute" },    -- adjust to your needs
            },
             
    logging =   {   level   =   domoticz.LOG_DEBUG,        -- Comment this and the next line if script execute as expected  
                    marker  =   "zoneTemperatures" },

    execute = function(dz)
        -- initialize table
        t = {}
        openTemperature    = 28 
        closeTemperature   = 16.5
        
        -- do everything :-)
        local function processRooms(t)
            local heating if t.heater ~= nil then heating = dz.devices(t.heater) end
            local cooling if t.cooler ~= nil then cooling = dz.devices(t.cooler) end
            local action if t.selector ~= nil then action  = dz.devices(t.selector).levelName else action = "Heating" end  -- defaults to "Heating"
            
            local hysteresisOn      = 0.5
            local hysteresisOff     = 0.2
            local openHeatingValves 
            local openCoolingValves 

            local function open(device) 
                if device == nil then return openHeatingValves end
                if device.deviceSubType == "SetPoint" then
                    device.updateSetPoint(openTemperature)
                else
                    device.switchOn().checkFirst()
                end
                return true
            end

            local function shut(device)
                if device == nil then return openCoolingValves end
                if device.deviceSubType == "SetPoint" then
                    device.updateSetPoint(closeTemperature)
                else
                    device.switchOff().checkFirst()
                end
            end
            
            
            for i=1,#t.rooms do                            -- loop trough the rooms
                local roomName      = t.rooms[i].room
                local setPoint      = dz.devices(t.rooms[i].s).setPoint
                local temperature   = dz.devices(t.rooms[i].t).temperature
                local radiatorValve = dz.devices(t.rooms[i].v)

                if  action == "Cooling" then
                    if      temperature <  setPoint                 then shut(radiatorValve)  -- stop cooling
                    elseif  temperature > ( setPoint + hysteresis ) then openCoolingValves = open(radiatorValve) end --start cooling
                elseif action == "Heating" then
                    if      temperature > ( setPoint - hysteresisOff ) then shut(radiatorValve)  -- stop heating
                    elseif  temperature < ( setPoint - hysteresisOn ) then openHeatingValves = open(radiatorValve) end --start heating
                elseif action == "Stop" then 
                    shut(cooling) shut(heating) shut(radiatorValve)
                end 
            end
            if openCoolingValves then open(cooling) else shut(cooling) end
            if openHeatingValves then open(heating) else shut(heating) end
        end
        
        -- Get table from domoticz uservariable
        dz.log(dz.variables("myRooms").value,dz.LOG_DEBUG)
        processRooms(dz.utils.fromJSON(dz.variables("myRooms").value))
    end
}
Maybe anyone has a idea for the user variables limitation
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest