thermostat for cooling and heating

Easy to use, 100% Lua-based event scripting framework.
Post Reply
megamarco83
Posts: 20
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi
Domoticz version:
Contact:

thermostat for cooling and heating

Post by megamarco83 » Thursday 11 October 2018 15:45

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: 1061
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren » Thursday 11 October 2018 19:37

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
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

User avatar
waaren
Posts: 1061
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren » 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!

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
}
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

User avatar
emme
Posts: 892
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: thermostat for cooling and heating

Post by emme » Friday 12 October 2018 11:14

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: 20
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: thermostat for cooling and heating

Post by megamarco83 » Friday 12 October 2018 15:10

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 117 times
Image3.jpg
Image3.jpg (49.24 KiB) Viewed 117 times
Image5.jpg
Image5.jpg (88.92 KiB) Viewed 117 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: 1061
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren » Friday 12 October 2018 16:54

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
}
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

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

Re: thermostat for cooling and heating

Post by megamarco83 » Friday 12 October 2018 18:27

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: 1061
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: thermostat for cooling and heating

Post by waaren » 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,
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
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

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

Re: thermostat for cooling and heating

Post by megamarco83 » Friday 12 October 2018 19:34

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: 20
Joined: Friday 21 September 2018 15:07
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: thermostat for cooling and heating

Post by megamarco83 » 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!

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest