Je viens partager aujourd'hui mon script pour adapter automatiquement le planning chauffage à la température ambiante, et ainsi optimiser au mieux les temps de chauffe.
En effet, selon la température extérieure, au moment de passer du mode ECO au mode CONFORT (pour une programmation standard sans capteurs de mouvements), la température intérieure n'est pas forcément tous les jours la même, et donc le temps de chauffe nécessaire non plus.
Un exemple basé sur mon installation :
Le mode CONFORT est réglé par thermostat à 20°C. Le mode ECO est réglé par script à CONFORT - 3°C, soit 17°C.
Je règle une plage CONFORT le matin, le midi et le soir (quand on est à la maison).
- Avec une température extérieure de 10°C, au moment de remettre en route le mode CONFORT, ma température intérieure n'a pas eu le temps de redescendre à 17°C et se trouve vers 18/19°C. Le temps de chauffe nécessaire pour remonter à 20°C est de 10/20 minutes.
- Avec une température extérieure de 0°C, en mode ECO la température intérieure retombe à 17°C. Le temps de chauffe nécessaire pour remonter à 20°C est de 30 minutes.
Avec un planning standard, on anticipe manuellement le temps de chauffe, mais ce n'est pas optimisé pour ne chauffer que le strict nécessaire. C'est là que le script entre en action.
I - PREREQUIS
Côté Domoticz :
Créer une variable de type entier, ici Mode_planning_RDC :

Les interrupteurs :

- Un interrupteur de type sélecteur. Sur lequel nous allons enregistrer le planning :


- Un interrupteur de type sélecteur. Qui récupérera les différentes infos (absence, marche forcée, planning, variable) pour en faire le tri par script LUA et donner le bon ordre :

/!\ Régler les mêmes niveaux sur les deux sélecteurs pour les modes ECO et CONFORT.
- Un interrupteur type On/Off pour allumer ou non le radiateur (ici par fil pilote).
- Une sonde température et un thermostat.
Côté Raspberry :
- Installer jq :
Code : Tout sélectionner
wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-1.5.tar.gz
tar xfvz jq-1.5.tar.gz
cd jq-1.5
./configure
make
make installCode : Tout sélectionner
sudo apt-get install bcA placer dans /home/pi/domoticz/scripts/sh/
Code : Tout sélectionner
#!/bin/bash
################################
###### Variables à éditer ######
################################
ip="192.168.0.38" # ip locale
port="8080" # port Domoticz
idx_planning="15" # idx de l'interrupteur Planning
lvl_confort="10" # Level du mode confort des interrupteurs Planning et Mode
lvl_eco="20" # Level du mode éco des interrupteurs Planning et Mode
idx_sonde="7" # idx de la sonde de température
idx_thermostat="6" # idx du thermostat
tps_chauffe_1deg="10" # Temps de chauffe nécessaire pour gagner 1°C en partant de radiateurs froids, en minutes.
tps_chauffe_2deg="20" # Temps de chauffe nécessaire pour gagner 2°C en partant de radiateurs froids, en minutes.
tps_chauffe_3deg="30" # Temps de chauffe nécessaire pour gagner 3°C en partant de radiateurs froids, en minutes.
var_mode="Mode_planning_RDC" # Nom de la variable utilisateur, préférer les underscores _ aux espaces dans le nom
idx_var_mode="5" # idx de la variable utilisateur
################################
## Fin des variables à éditer ##
################################
#echo "====================" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# On détermine si on est un jour de semaine ou le weekend (weekend:512 / semaine:256)
# Possible d'adapter à un planning plus complexe en récupérant les valeurs "Days" en consultant dans un navigateur : http://ip:port/json.htm?type=schedules
if [ $(date +%u) -gt 5 ]
then
jour_sem=512
echo_jour_sem="Weekend"
#echo "weekend" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
else
jour_sem=256
echo_jour_sem="Semaine"
#echo "semaine" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
fi
# On récupère le prochain timer sur le planning
timer=$(curl -s "http://$ip:$port/json.htm?type=schedules" | jq '[.result[] | select((.DeviceRowID | contains ('$idx_planning')) and (.Days | contains('$jour_sem')) and (.Level | contains('$lvl_confort')))]' | jq '[.[].ScheduleDate | strptime("%Y-%m-%d %H:%M:%S") | mktime]' | jq 'min')
#echo "Timestamp prochain timer: $timer" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# On récupère la date du serveur
date_serveur=$(curl -s "http://$ip:$port/json.htm?type=command¶m=getSunRiseSet" | jq -r '.ServerTime | strptime("%Y-%m-%d %H:%M:%S") | mktime')
#echo "Timestamp date serveur: $date_serveur" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# Calcul du délai avant timer
delai=$((($timer-$date_serveur)/60))
#echo "Délai avant timer: $delai min" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# On récupère la température intérieure
temp_int=$(curl -s "http://$ip:$port/json.htm?type=devices&rid=$idx_sonde" | jq -r '.result[].Temp | tonumber')
#echo "Température intérieure: $temp_int °C" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# On récupère la température de consigne confort
consigne_conf=$(curl -s "http://$ip:$port/json.htm?type=devices&rid=$idx_thermostat" | jq -r '.result[].SetPoint | tonumber')
#echo "Thermostat confort: $consigne_conf °C" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# Calcul de la différence de température
delta_temp=$(bc -l <<<"scale=2;$consigne_conf-$temp_int")
#echo "Delta température: $delta_temp °C" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# On récupère la variable actuelle en base de données
var_init=$(curl -s "http://$ip:$port/json.htm?type=command¶m=getuservariable&idx=$idx_var_mode" | jq -r '.result[].Value | tonumber')
#echo "Variable initiale: $var_init" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
# On détermine le mode de chauffe et on modifie la variable utilisateur
if [ 1 -eq `echo "${delta_temp} > 0" | bc` ] && [ $delai -le $tps_chauffe_1deg ]
then
curl "http://$ip:$port/json.htm?type=command¶m=updateuservariable&vname=$var_mode&vtype=0&vvalue=$lvl_confort"
if [ $var_init -ne $lvl_confort ]
then
echo -e "=============================================================\n$(date '+%H:%M:%S - %d-%m-%Y') - $echo_jour_sem\nDélai avant timer: $delai min\nTempérature intérieure: $temp_int °C\nDelta température: $delta_temp °C\nCondition 1: Delta > 0 et délai timer <= temps de chauffe 1°C.\nModification de la variable en level confort" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
fi
elif [ 1 -eq `echo "${delta_temp} > 1" | bc` ] && [ $delai -le $tps_chauffe_2deg ]
then
curl "http://$ip:$port/json.htm?type=command¶m=updateuservariable&vname=$var_mode&vtype=0&vvalue=$lvl_confort"
if [ $var_init -ne $lvl_confort ]
then
echo -e "=============================================================\n$(date '+%H:%M:%S - %d-%m-%Y') - $echo_jour_sem\nDélai avant timer: $delai min\nTempérature intérieure: $temp_int °C\nDelta température: $delta_temp °C\nCondition 2: Delta > 1 et délai timer <= temps de chauffe 2°C.\nModification de la variable en level confort" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
fi
elif [ 1 -eq `echo "${delta_temp} > 2" | bc` ] && [ $delai -le $tps_chauffe_3deg ]
then
curl "http://$ip:$port/json.htm?type=command¶m=updateuservariable&vname=$var_mode&vtype=0&vvalue=$lvl_confort"
if [ $var_init -ne $lvl_confort ]
then
echo -e "=============================================================\n$(date '+%H:%M:%S - %d-%m-%Y') - $echo_jour_sem\nDélai avant timer: $delai min\nTempérature intérieure: $temp_int °C\nDelta température: $delta_temp °C\nCondition 3: Delta > 2 et délai timer <= temps de chauffe 3°C.\nModification de la variable en level confort" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
fi
else
lvl_planning=$(curl -s "http://$ip:$port/json.htm?type=devices&rid=$idx_planning" | jq -r '.result[].Level | tonumber')
curl "http://$ip:$port/json.htm?type=command¶m=updateuservariable&vname=$var_mode&vtype=0&vvalue=$lvl_planning"
if [ $var_init -ne $lvl_planning ]
then
echo -e "=============================================================\n$(date '+%H:%M:%S - %d-%m-%Y') - $echo_jour_sem\nAucune condition remplie: On respecte le planning" >> /home/pi/domoticz/scripts/sh/logs_planning.txt
fi
fiLes "echo" ne sont là que pour le débug, à commenter ou dé-commenter selon son besoin. La sortie se fait dans un fichier nommé logs_planning.txt dans le dossier /scripts/sh/.
On donne les droits nécessaires pour l'exécution du fichier :
Code : Tout sélectionner
chmod +x planning.shCode : Tout sélectionner
crontab -eCode : Tout sélectionner
# Lancement du script Mode Planning
* * * * * /home/pi/domoticz/scripts/sh/planning.shCode : Tout sélectionner
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binLà il va falloir adapter à votre script chauffage principal.
Dans mon cas, c'est un script LUA lié à tout un tas d'interrupteurs pour avoir une config totalement paramétrable côté client.
En gros :
- Un inter général pour couper complètement ou non le chauffage.
- Un inter "marche forcée" pour forcer le mode CONFORT.
- Un inter "absence" pour forcer le mode ECO.
- Un planning.
- Un sélecteur de mode, "cœur" du système.
Mon script LUA pour l'exemple :
Code : Tout sélectionner
--------------------------------
------ Variables à éditer ------
--------------------------------
local zone = 'RDC' -- Nom de la zone de chauffe
local inter = 'Interrupteur général chauffage' -- Nom de l'interrupteur virtuel général des radiateurs de la maison
local absence = 'Absence' -- Nom de l'interrupteur virtuel d'absence
local boost = 'Marche forcée RDC' -- Nom de l'interrupteur virtuel de marche forcée
local planning = 'Planning chauffage RDC' -- Nom du sélecteur virtuel de planning chauffage
local radiateur = 'Fil pilote RDC' -- Nom de l'interrupteur virtuel d'action fil pilote
local puissance = 3500 -- Puissance du chauffage en watt
local conso = 'Consommation chauffage RDC' -- Nom du compteur virtuel de consommation électrique
local conso_id = 20 -- idx du compteur virtuel de consommation électrique
local sonde = 'RDC' -- Nom de la sonde de température
local consigne_conf = 'Thermostat RDC' -- Nom de thermostat virtuel de gestion de la température de confort
local diff_eco = 3 -- Différence de température entre les modes Confort et Eco
local selec_mode = 'Mode chauffage RDC' -- Nom du sélecteur virtuel d'indication de mode de chauffage Off/Confort/Eco
local lvl_off = 00 -- Niveaux du sélecteur virtuel de mode de chauffage
local lvl_conf = 10
local lvl_eco = 20
local tarifhp = 'Tarif HP' -- Nom de la variable utilisateur
local tarifhc = 'Tarif HC' -- Nom de la variable utilisateur
local hp_hc = 'EDF HP / HC' -- Nom du sélecteur Heures pleines/Heures creuses
local lvl_hp = 10 -- Niveaux du sélecteur HP/HC
local lvl_hc = 20
local inc_meter = 'Coût chauffage RDC' -- Nom du compteur virtuel de coût EDF
local inc_meter_id = 23 -- idx du compteur virtuel de coût EDF
local tps_confort = 'Temps Confort RDC' -- Nom de la variable utilisateur
local var_cout = 'Coût chauffage RDC' -- Nom de la variable utilisateur
local var_planning = 'Mode_planning_RDC' -- Nom de la variable utilisateur
--------------------------------
-- Fin des variables à éditer --
--------------------------------
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
-- Date du dernier relevé de température
local lastSeen = string.sub(os.date("!%X", timedifference(sonde)), 1, 5)
commandArray = {}
-- Relevé de température
local temperature = tonumber(string.sub(otherdevices_svalues[sonde],1,4))
-- Récupération de la valeur du thermostat et du planning
consigne_conf = tonumber(otherdevices_svalues[consigne_conf])
consigne_eco = tonumber(consigne_conf - diff_eco)
planning = tonumber(otherdevices_svalues[planning])
-- Incrémentation de la variable Temps Confort pour les stats
tps_confort_init = tonumber(uservariables[tps_confort])
if planning == lvl_conf then
tps_confort_maj = tps_confort_init + 1
else
tps_confort_maj = tps_confort_init
end
commandArray['Variable:'..tps_confort] = tostring(tps_confort_maj)
-- Modification du sélecteur de mode
var_planning = uservariables[var_planning] -- Récupération de la variable mode planning générée par le script planning.sh
if (otherdevices[inter] == 'Off') then -- Si l'interrupteur général est coupé :
commandArray[selec_mode]='Set Level: '..lvl_off..'' -- On passe le sélecteur sur Off,
mode = tonumber(lvl_off) -- Et on enregistre le niveau correspondant pour la suite du script.
elseif (otherdevices[absence] == 'On') or (lastSeen > '00:10') then -- Si mode absence activé ou sonde muette depuis +10 min :
commandArray[selec_mode]='Set Level: '..lvl_eco..'' -- On passe le sélecteur sur ECO,
mode = tonumber(lvl_eco) -- Et on enregistre le niveau correspondant pour la suite du script.
elseif (otherdevices[boost] == 'On') then -- Si marche forcée activée :
commandArray[selec_mode]='Set Level: '..lvl_conf..'' -- On passe le sélecteur sur CONFORT,
mode = tonumber(lvl_conf) -- Et on enregistre le niveau correspondant pour la suite du script.
else
commandArray[selec_mode]='Set Level: '..var_planning..'' -- Si aucune de ces conditions n'est remplie, on passe sur la variable mode planning,
mode = tonumber(var_planning) -- Et on enregistre le niveau correspondant pour la suite du script.
print('Level mode planning: '..var_planning) -- logs
end
-- Récupération de la consigne à appliquer
if mode == lvl_conf then -- Si le mode enregistré correspond au mode CONFORT :
consigne = consigne_conf -- Consigne confort.
else -- Sinon :
consigne = consigne_eco -- Consigne ECO.
end
-- Comparaison température/consigne et action fil pilote
if (mode == lvl_off or temperature >= consigne) then
commandArray[radiateur]='Off'
-- Envoi de la conso dans le capteur virtuel d'énergie
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
commandArray[radiateur]='On'
-- Envoi de la conso dans le capteur virtuel d'énergie
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
-- Mise à jour du compteur conso
commandArray[1]={['UpdateDevice'] = conso_id .. '|0|' .. power .. ';' .. energy}
-- Calcul du coût EDF
if (otherdevices[radiateur] == 'On') then
instant_energy = tonumber(puissance / 60) -- Consommation instantanée
else
instant_energy = 0
end
hp_hc = tonumber(otherdevices_svalues[hp_hc]) -- Récupération du planning HP/HC
tarifhp = tonumber(uservariables[tarifhp]) -- Récupération des tarifs HP/HC
tarifhc = tonumber(uservariables[tarifhc])
if hp_hc == lvl_hp then
instant_cout = instant_energy * tarifhp / 1000
elseif hp_hc == lvl_hc then
instant_cout = instant_energy * tarifhc / 1000
end
compteur_init = tonumber(otherdevices_svalues[inc_meter]) -- Récupération de la valeur initiale du compteur
compteur_maj = compteur_init + instant_cout -- On ajoute la conso instantanée au compteur
-- Mise à jour compteur tarif
commandArray[2]={['UpdateDevice'] = inc_meter_id .. '|0|' .. compteur_maj}
-- Mise à jour variable tarif pour stats quotidiennes
var_cout_init = tonumber(uservariables[var_cout]) -- Récupération de la valeur initiale de la variable
var_cout_maj = var_cout_init + instant_cout -- Ajout du coût instantanée
commandArray['Variable:'..var_cout] = tostring(var_cout_maj) -- Mise à jour de la variable
-- Logs
print('Température '..zone..': '..temperature..' °C / Consigne : '..consigne..' °C')
print('Coût chauffage '..zone..': '..compteur_maj..' €')
return commandArrayCode : Tout sélectionner
-- Modification du sélecteur de mode
var_planning = uservariables[var_planning] -- Récupération de la variable mode planning générée par le script planning.sh
if (otherdevices[inter] == 'Off') then -- Si l'interrupteur général est coupé :
commandArray[selec_mode]='Set Level: '..lvl_off..'' -- On passe le sélecteur sur Off,
mode = tonumber(lvl_off) -- Et on enregistre le niveau correspondant pour la suite du script.
elseif (otherdevices[absence] == 'On') or (lastSeen > '00:10') then -- Si mode absence activé ou sonde muette depuis +10 min :
commandArray[selec_mode]='Set Level: '..lvl_eco..'' -- On passe le sélecteur sur ECO,
mode = tonumber(lvl_eco) -- Et on enregistre le niveau correspondant pour la suite du script.
elseif (otherdevices[boost] == 'On') then -- Si marche forcée activée :
commandArray[selec_mode]='Set Level: '..lvl_conf..'' -- On passe le sélecteur sur CONFORT,
mode = tonumber(lvl_conf) -- Et on enregistre le niveau correspondant pour la suite du script.
else
commandArray[selec_mode]='Set Level: '..var_planning..'' -- Si aucune de ces conditions n'est remplie, on passe sur la variable mode planning,
mode = tonumber(var_planning) -- Et on enregistre le niveau correspondant pour la suite du script.
print('Level mode planning: '..var_planning) -- logs
end
-- Récupération de la consigne à appliquer
if mode == lvl_conf then -- Si le mode enregistré correspond au mode CONFORT :
consigne = consigne_conf -- Consigne confort.
else -- Sinon :
consigne = consigne_eco -- Consigne ECO.
endPour ma part, j'ai attendu avant de modifier mon script LUA que tout fonctionne correctement. J'ai fait tourner le script BASH quelque temps en modifiant les valeurs de thermostat et de planning pour vérifier que le fichier logs renvoie systématiquement les bonnes valeurs.
Et maintenant le réglage du planning se fait selon les heures de présence, plus besoin de programmer des temps de chauffe préalables, le script le fera automatiquement selon la température ambiante.
J'espère avoir été assez clair dans mes explications, et n'avoir rien oublié.
J'en profite pour remercier l'équipe du forum et ses membres pour toute l'aide qu'ils nous apportent quotidiennement.
Et merci à vil1driver pour son fameux script chauffage qui sert de base à tout le monde ^^