Page 1 sur 6

[LUA] Script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 13:26
par vil1driver
Bonjour,

un script parmi tant d'autres.... mais je l'aime bien et madame également :p
il colle parfaitement à nos horaires extrêmement variables et absence impromptues..

Image
ce script permet de maintenir une température choisie et réglée sur un capteur virtuel de consigne de thermostat,
dans une plage horaire de 7h à 23h ou sur 24h grâce à un bouton marche forcée,
et cela uniquement si notre présence est détectée via un capteur de mouvement (PIR pour les intimes),

- principe copié sur un produit du commerce -

dès que nous sommes présent dans la pièce, le chauffage se met en route, et uniquement dans cette pièce.
si nous nous absentons, le script va progressivement faire baisser la consigne sur une durée de 3h pour arriver à la consigne économique (-2°C ou -3°C)
dans cette période, toute nouvelle détection de présence remontera instantanément la consigne à sa valeur initiale.

si vous souhaitez que le chauffage se mette en route avant votre réveil ou votre retour de ballade,
vous n'avez simplement qu'a programmer le changement d'état de votre capteur PIR grâce à la fonction planning de domoticz,
ou bien vous connecter à distance pour manuellement le faire changer d'état.

il m'est arrivé de ne plus recevoir d'info de mes sondes de température, alors j'ai ajouté une sécurité qui coupe le chauffage le temps du blackout radio et envoie un mail d'alerte.

cerise sur le gâteau, il est prévu de 'mesurer' la consommation électrique de vos chauffage et d'alimenter un capteur virtuel de consommation.
ce n'est pas vraiment de la mesure mais le script s'exécutant toutes les minutes et la consommation d'un radiateur étant quelque-chose de stable et connu, il était aisé de faire les calculs nécessaires.
si vous avez comme moi plusieurs pièces et donc plusieurs script de chauffages (typiquement 1 par pièce/zone), il est possible d'utiliser le même capteur de conso pour tout le monde. le code est prévu pour.

voici le script:

Code : Tout sélectionner

--[[ 

Type: 			time
Name: 			chauffage
 
Description:	Ce script permet de maintenir une température de confort,
				suivant la détection de notre présence (dans une plage horaire donnée),
				puis de progressivement abaisser la température en notre abscence.

Usage:			un interrupteur général 'mode' permet de passer du mode auto (conf/éco) au mode hors gêle.
				un second 'boost' permet de chauffer hors plage horaire (toujours sur détection de présence)
				un troisième 'guess' permet de forcer notre présence

				si nous faisons la fête, pour avoir du chauffage tant que la soirée à lieu
				activer 'boost'
				'boost' se désactivera de lui même après une heure sans détection de présence
				
				si vous voulez chauffer(confort) même sans détection de mouvement (bébé, personne alitée)
				activer 'guess'
				
				le script permet également de renseigner un capteur virtuel de consommation électrique.
				
Inertie:		lorsque le chauffage est allumé, on incrémente un compteur +1/min
				suivant ce compteur, la consigne à atteindre est abaissée de 0.1°C toutes les 10 minutes, avec un abaissement maxi de 0.5°C
				donc plus le temps passe, plus la température de la pièce augmente et plus la consigne baisse..

				lorsque la température rejoint la consigne(modifiée), on arrête de chauffer.
				on laisse un peu la pièce profiter de l'énergie accumulée dans les radiateurs.
				et on décrémente le compteur -1/min ce qui va remonter la consigne de 0.1°C toutes les 10 minutes
				donc plus le temps passe et plus la température continue de monter et plus la consigne augmente (jusqu'à relancer la chauffe)

				lorsque l'on atteint et/ou dépasse la consigne initiale le compteur est remis à zéro.
				au bout de 10 minutes à la consigne voulue, on remet en route le chauffe pour 2min puis on le stop 2min et on recommence.
				si cela nous fait dépasser la consigne on arrête.
				si on tombe sous la consigne, on aura gagné en réactivité car le radiateur sera préchauffé.

--]]
 
----------------------------------------------
------ 			Configuration 			------
----------------------------------------------

-- nom de zone
local zone = 'salon'						-- nom de la zone pour affichage dans les logs et alerte mail

-- consignes
local consigne_conf = 'th_salon'  			-- nom de thermostat virtuel de gestion de la température de confort
local consigne_abs = 10  					-- Température lors d'abscence prolongée (hors gêle)
local consigne_1h = 0.5						-- valeur d'abaissement de la consigne après 1 heure d'abscence
local consigne_2h = 1.5						-- valeur d'abaissement de la consigne après 2 heure d'abscence
local consigne_3h = 2.5						-- valeur d'abaissement de la consigne après 3 heure d'abscence

-- capteurs
local sonde = 'salon' 						-- Nom de la sonde de température
local presence = 'mv salon' 				-- Nom du capteur de mouvement
local mode = 'chauffage' 					-- Nom de l'interrupteur virtuel général (On=auto Off=hors gêle)
local boost = 'boost'						-- Nom de l'interrupteur virtuel pour déroger au couvre feu (chauffer hors plage de chauffe définie) 
local guess = 'guess'						-- Nom de l'interrupteur virtuel pour forcer notre présence

-- période de chauffage
-- pour une période de 24h, mettre debut = '00:00' et fin = '24:00'
-- bien respecter le format hh:mm
local debut = 	'07:00'
local fin = 	'23:00'

-- radiateur
local radiateur = 'radiateur salon' 		-- Nom de l'interrupteur de chauffage
local puissance = 2700						-- puissance du chauffage en watt
local conso = 'conso chauffage'				-- nom du capteur virtuel de consommation électrique (type= instant + counter)
local conso_id = 107						-- idx du capteur virtuel de consommation électrique
local reset = false							-- force la mise à zero de la consomation instantané (laisser à false pour un fonctionnement normal) true/false

-- inertie (beta)
local inertie = true						-- radiateur à inertie true/false
local up = 1.5								-- incrément du compteur par minute (vitesse d'abaissement de la consigne)
local down = 1.9							-- décrément du compteur par minute (vitesse de remontée de la consigne)

-- email
local mail = '******@*****'			-- pour réception alerte sonde muette (chauffage coupé)

-- domoticz
local url = '192.168.22.100:8080'			-- user:pass@ip:port de domoticz, pour la création des variables

----------------------------------------------
-- 		Fin de la partie configuration 		--
----------------------------------------------
 
function timedifference(d)
	s = otherdevices_lastupdate[d]
	year = string.sub(s, 1, 4)
	month = string.sub(s, 6, 7)
	day = string.sub(s, 9, 10)
	hour = string.sub(s, 12, 13)
	minutes = string.sub(s, 15, 16)
	seconds = string.sub(s, 18, 19)
	t1 = os.time()
	t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
	difference = os.difftime (t1, t2)
	return difference
end

-- quelle heure est-il
local heure = string.sub(os.date("%X"), 1, 5)
-- on regarde depuis combien de temps on est abscent
local abscence = string.sub(os.date("!%X", timedifference(presence)), 1, 5)
-- si demandé on simule une présence constante
if (otherdevices[guess] == 'On') then
	abscence = '00:00'
end	
-- notre dernière apparition était elle dans la plage horaire ?
if ((60*tonumber(string.sub(heure,1,2)) + tonumber(string.sub(heure,4,5))) - (60*tonumber(string.sub(abscence,1,2)) + tonumber(string.sub(abscence,4,5))) >= 60*tonumber(string.sub(debut,1,2)) + tonumber(string.sub(debut,4,5))) then
	inScope = true
else
	inScope = false
end
-- on regarde de quand date la dernière relève de température
local lastSeen = string.sub(os.date("!%X", timedifference(sonde)), 1, 5)

commandArray = {}

	--envoie d'une alerte mail si la sonde reste muette (pas de valeur reçue sur les 30 dernières minutes)
	if (lastSeen >= '00:30' and lastSeen < '00:32') then
		commandArray['SendEmail']='Domoticz Alerte#Alerte sonde '..zone..' muette#'..mail
	end
	
	-- création variable pour mémoriser la durée de chauffe,
	-- servant à éviter un fort dépassement de consigne suite à une longue période de chauffe (inertie des radiateurs)
	if (uservariables['chauffage_'..zone] == nil) then
		commandArray['OpenURL']=url..'/json.htm?type=command&param=saveuservariable&vname=chauffage_'..zone..'&vtype=2&vvalue=0'
		print('script chauffage '..zone..' interrompu pour création variable manquante')
		return commandArray
	end	
	
		
	-- gestion de la consigne
	-- récupération de la valeur du thermostat
	consigne_conf = tonumber(otherdevices_svalues[consigne_conf])
	-- si le thermostat général est actif
    if (otherdevices[mode] == 'On') then
		-- si il y a absence de moins d'une heure, la journée ou jusqu'au landemain matin si boost actif
        if ((inScope or otherdevices[guess] == 'On') and abscence <= '01:00' and ((heure >= debut and heure < fin) or otherdevices[boost] == 'On')) then 
			consigne = consigne_conf
		-- si absence de 1 à 2 heures la journée, abaissement de la consigne de 1°C
		elseif (inScope and abscence > '01:00' and abscence <= '02:00' and heure >= debut and heure < fin) then 
			consigne = consigne_conf - consigne_1h
		-- si absence de 2 à 3 heures la journée, abaissement de la consigne de 2°C	
		elseif (inScope and abscence > '02:00' and abscence <= '03:00' and heure >= debut and heure < fin) then
			consigne = consigne_conf - consigne_2h
		-- sinon, passage en consigne éco (3°C en dessous de la consigne confort)
		else
			consigne = consigne_conf - consigne_3h
			-- annulation boost, soirée terminée
			commandArray[boost] = 'Off'
		end
	else
		consigne = consigne_abs
	end	
	
	
	-- adaptation de la consigne pour tenir compte de l'inertie des radiateurs
	-- on soustrait/ajoute 0.1°C à la consigne, par tranche de 10 du compteur
	local count = tonumber(uservariables['chauffage_'..zone])
	if (count > 0) then
		adj = math.ceil(count / 10) / 10 - 0.1
	else
		adj = math.ceil(count / 10) / 10
	end	
	if (inertie) then
		consigne = consigne - adj
	end

	
	-- on récupère la température fournie par la sonde
    local temperature = math.floor(10*tonumber(otherdevices_temperature[sonde]))/10

	
	-- si la température est supérieure ou égale à la consigne,
	-- ou que la sonde semble muette (10 min sans relève),
	if (temperature >= consigne or lastSeen > '00:10') then	
	
		-- on stop la chauffe 
		commandArray[radiateur]='Off'
		log = 'Radiateur -. OFF .-'


		-- calcul de la conso
		npower, energy = string.match(otherdevices_svalues[conso], "(%d+%.*%d*);(%d+%.*%d*)")
		if (otherdevices[radiateur] == 'On') then
			power = tonumber(npower - puissance)
			if (power < 0) then
				power = 0
			end
		else
			power = tonumber(npower)
		end	
		energy = tonumber(energy)
		
		
		-- si on dépasse la consigne voulue on remet le compteur à zero
		if (temperature > consigne + adj) then
			commandArray['Variable:chauffage_'..zone] = '0'
		-- on décrémente progessivement le compteur durée de chauffe (on ne passe sous zero que si on est à la consigne voulue)	
		elseif (otherdevices[radiateur] == 'Off' and (count > 0 or temperature == consigne + adj)) then
			commandArray['Variable:chauffage_'..zone] = tostring(count - down)
		end

		
	-- si la température est inférieur à la consigne et que la sonde est OK
	else
	
		-- on chauffe
		commandArray[radiateur]='On'
		log = 'Radiateur -. ON .-'


		
		-- calcul de la conso
		npower, energy = string.match(otherdevices_svalues[conso], "(%d+%.*%d*);(%d+%.*%d*)")
		if (otherdevices[radiateur] == 'On') then
			power = tonumber(npower)
		else
			power = tonumber(npower + puissance)
		end	
		energy = tonumber(energy + (puissance / 60))
		
		
		-- si on tombe sous la consigne voulue et que le compteur est negatif, on le remet à zero
		if (temperature < consigne + adj and tonumber(uservariables['chauffage_'..zone]) < 0) then
			commandArray['Variable:chauffage_'..zone] = '0'
		-- sinon on incrémente le compteur durée de chauffe (max 100)
		elseif (otherdevices[radiateur] == 'On' and count + up <= 100) then	
			commandArray['Variable:chauffage_'..zone] = tostring(count + up)
		end
		
		
	end
	
	-- envoie de la conso dans le capteur virtuel d'énergie
	if (reset) then
		power = 0
	end	
	commandArray[3]={['UpdateDevice'] = conso_id .. '|0|' .. power .. ';' .. energy}
	
	-- logs
	print('*** Chauffage '..zone..' ***')
	print(log)
	if inertie then
		print('Gestion de l\'inertie: count '..count)
	end
	if (otherdevices[boost] == 'On') then
		print('Couvre feu désactivé')
	end	
	if (inScope and otherdevices[guess] == 'Off')then
		print('Absence '..zone..' : '..abscence)
	elseif (otherdevices[guess] == 'On') then
		print('Présence continue activée')
	end	
	if (otherdevices[mode] == 'Off') then
		print('Thermostat général sur Off')
	elseif (lastSeen > '00:10') then
		print('Sonde muette !')
	else	
		print('il fait '..temperature..'°C pour '..consigne..'°C souhaité')
	end	
	print('*** *** *** *** *** ***')
return commandArray


Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 15:50
par chandler45
Super comme script ! Bon j'ai pas de PIR, mais je pense que je vais m'inspirer de ton idée pour calculer la conso des radiateurs ! Et grâce à toi, je viens de découvrir qu'il était beaucoup plus sympa de cliquer sur le logo d'une consigne de thermostat pour changer la valeur plutôt que de cliquer sur "Editer" !! :D

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 19:49
par nickos
salut
super le scripts, je l'ai un peut modifié car je n'est pas de capteur PIR mais des inter virtuel avec le ping des telephone et mon chauffage est une chaudière a gaz, pas des radiateurs electrique.
mais, car oui il faut toujours un mais sinon c'est pas marrant j'ai une erreur

Code : Tout sélectionner

Error: /home/pi/domoticz/scripts/lua/script_device_chauffage.lua:82: attempt to compare number with nil
mon scripts

Code : Tout sélectionner

-- script_time_chauffage.lua
-- 
-- Ce script permet de maintenir la température
 
--------------------------------
------ Variables à éditer ------
--------------------------------
local consigne_conf = tonumber(otherdevices_svalues['th_salon'])  -- Température de consigne
local consigne_abs = 10  -- Température de consigne lors d'abscence prolongée (hors gêle)

local sonde = 'Salon' -- Nom de la sonde de température
local presence = 'Telephone 1' -- Nom du capteur de mouvement
local presence = 'Telephone 2' -- Nom du capteur de mouvement
local thermostat = 'Thermostat' -- Nom de l'interrupteur virtuel de thermostat (Off = abscence prolongée)
local boost = 'Chauffage'   -- Nom de l'interrupteur virtuel pour déroger au couvre feu (marche forcée)

local radiateur = 'Chauffage' -- Nom de l'interrupteur de chauffage
local puissance = 3500   -- puissance du chauffage en watt
local conso = 'Compteur Gaz Chauffage'   -- nom du capteur virtuel de consommation électrique
local conso_id = 948   -- idx du capteur virtuel de consommation de Gaz

--------------------------------
-- Fin des variables à éditer --
--------------------------------
 
time = os.date("*t")  

function timedifference(d)
   s = otherdevices_lastupdate[d]
   year = string.sub(s, 1, 4)
   month = string.sub(s, 6, 7)
   day = string.sub(s, 9, 10)
   hour = string.sub(s, 12, 13)
   minutes = string.sub(s, 15, 16)
   seconds = string.sub(s, 18, 19)
   t1 = os.time()
   t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
   difference = os.difftime (t1, t2)
   return difference
end

-- on regarde depuis combien de temps l'on est abscent
local abscence = timedifference(presence)
-- on regarde de quand date la dernière relève de température
local lastSeen = timedifference(sonde)


commandArray = {}

--envoie d'une alerte mail si la sonde reste muette (pas de valeur reçue sur les 10 dernières minutes)
if (lastSeen >= 600 and lastSeen < 660 ) then
      commandArray['SendEmail']='Domoticz Alerte#Alerte sonde salon muette#*********@gmail.com'
end
   
   
   -- si le thermostat général est actif
    if (otherdevices[thermostat] == 'On') then
      -- si il y a absence de moins d'une heure, la journée ou jusqu'au landemain matin si boost actif
        if (abscence <= 3600 and ((time.hour >= 7 and time.hour < 23) or otherdevices[boost] == 'On')) then 
         consigne = consigne_conf
      -- si absence de 1 à 2 heures la journée, abaissement de la consigne de 1°C   
      elseif (abscence > 3600 and abscence <= 7200 and time.hour >= 7 and time.hour < 23) then 
         consigne = consigne_conf - 1
      -- si absence de 2 à 3 heures la journée, abaissement de la consigne de 1.5°C   
      elseif (abscence > 7200 and abscence <= 10800 and time.hour >= 7 and time.hour < 23) then
         consigne = consigne_conf - 1.5
      -- sinon, passage en consigne éco (2°C en dessous de la consigne confort)
      else
         consigne = consigne_conf - 2
      end
   else
         consigne = consigne_abs
   end   
   
   
   
   -- on récupère la température fournie par la sonde
    local temperature = tonumber(string.sub(otherdevices_svalues[sonde],1,4)) 
   
   -- si la température est supérieur ou égale à la consigne, ou que la sonde semble muette, on stop la chauffe 
   
   if (temperature >= consigne or lastSeen > 600) then   
      
      commandArray[radiateur]='Off'
      print('Chauffage -. OFF .-')
               
      -- calcul de la conso
      npower, energy = string.match(otherdevices_svalues[conso], "(%d+%.*%d*);(%d+%.*%d*)")
      if(otherdevices[radiateur] == 'On') then
         power = tonumber(npower - puissance)
         if(power < 0) then power = 0 end
      else
         power = tonumber(npower)
      end   
      energy = tonumber(energy)
      
      
   else   -- sinon on chauffe
   
      commandArray[Chauffage]='On'
      print('Chauffage -. ON .-')
                        
      -- calcul de la conso
      npower, energy = string.match(otherdevices_svalues[conso], "(%d+%.*%d*);(%d+%.*%d*)")
      if(otherdevices[radiateur] == 'On') then
         power = tonumber(npower)
      else
         power = tonumber(npower + puissance)
      end   
      energy = tonumber(energy + (puissance / 60))
      
         
   end
   
   -- envoie de la conso dans le capteur virtuel d'énergie
   commandArray['UpdateDevice'] = conso_id .. '|0|' .. power .. ';' .. energy   
   
   print('il fait '..temperature..'°C pour '..consigne..'°C souhaité')
      
return commandArray

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 20:00
par vil1driver
il y a un prérequis, la consigne =) et tu nomes 2 inters avec le même nom... ça ne risque pas de fonctionner.
d'autre part, ce script n'est peut être pas au idéal pour une chaudière...

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 20:15
par mulot35
Vil1driver il me semble que tu avais aussi signalé qu'il fallait le nommé en "script_time_blabla.lua" et dans le message d erreur il y a de marqué "script_device_chauffage.lua"

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 20:17
par vil1driver
Ah ouiii bien vu :-) effectivement

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 20:36
par nickos
merci pour toutes ces réponse

Bon j'ai renommé mes inters correctement,ma consigne et mon scripts

2015-03-10 20:52:00.125 Error: /home/pi/domoticz/scripts/lua/script_time_chauffage.lua:9: syntax error near 'local'

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 20:58
par vil1driver
Ce message t'indique que ton erreur se trouve ligne 9 pret du mot local.

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 21:03
par nickos
la ligne 9 c'est

Code : Tout sélectionner

local consigne_abs = 10  -- Température de consigne lors d'abscence prolongée (hors gêle)
:?

Re: script de chauffage avec détection PIR et retour de conso

Publié : 10 mars 2015, 21:30
par vil1driver
Humm,.,

Il faut que tu te creuses un peu la tête, l'erreur n'y était pas avant...
Reviens en arrière sur ta dernière modif....
Là comme ça je ne sais pas..