[LUA+Bash] Calcul de DJU

Vous avez créé un script LUA dont vous êtes fier, un .sh génial, un programme Python hors du commun, un Tuto, c'est ici que vous pouvez les partager.
Répondre
papoo
Messages : 2029
Inscription : 10 janv. 2016, 11:29
Localisation : Limoges (87)
Contact :

[LUA+Bash] Calcul de DJU

Message par papoo »

Afin de surveiller sa consommation de chauffage, la facture ou les kwh consommés ne permettent pas de savoir si son installation fonctionne correctement.
il manque pour cela une constante à laquelle se référer pour comparer les consommations : la rigueur climatique. Si un hiver est particulièrement doux, la facture est moins salée que d'habitude et on pense que notre installation fonctionne correctement. A l'inverse un hiver très froid nous fait craindre un quelconque dérèglement lors de la réception de la facture. Les professionnels, pour mesurer la constance des performances énergetiques d'une installation, utilisent les DJU. (pour Degré Jour Unifié) ils sont fournis via un abonnement payant par météo France ou le COSTIC. j'ai pour ma part essayé de reproduire la methode de calcul la plus simple, celle de météo France.
le principe :
Un degré jour est calculé à partir des températures météorologiques extrêmes du lieu et du jour J : 
- Tn : température minimale du jour J mesurée à 2 mètres du sol sous abri et relevée entre J-1 (la veille) à 18h et J à 18h UTC. 
- Tx : température maximale du jour J mesurée à 2 mètres du sol sous abri et relevée entre J à 6h et J+1 (le lendemain) à 6h UTC. 
- S : seuil de température de référence choisi. 
- Moy = (Tn + Tx)/2 Température Moyenne de la journée
Pour un calcul de déficits de température par rapport au seuil choisi : 
- Si S > TX (cas fréquent en hiver) : DJ = S - Moy 
- Si S ≤ TN (cas exceptionnel en début ou en fin de saison de chauffe) : DJ = 0 
- Si TN < S ≤ TX (cas possible en début ou en fin de saison de chauffe) : DJ = ( S –TN ) * (0.08 + 0.42 * ( S –TN ) / ( TX – TN ))
vous l'avez compris, il nous faut donc pour calculer les DJU d'une sonde extérieure placée sur l'exposition la plus défavorable (généralement la façade nord) à l'abri du soleil, si possible sous abri.
Il nous faut commencer par créer un capteur virtuel compteur, et quatre variables de type chaine Tn, Tx, Tn_Hold et Nb Jours de Chauffage
ensuite créez un fichier tn_hold.sh

Code : Tout sélectionner

#!/bin/bash

# Settings
#crontab -e
# 0 6 * * * sudo /home/pi/domoticz/scripts/sh/tn_hold.sh
# chmod +x /home/pi/domoticz/scripts/sh/tn_hold.sh



DOMO_IP="192.168.10.240"      # Domoticz IP Address
DOMO_PORT="8080"         # Domoticz Port

Tn_IDX="16"               # Idx de la variable Tn
Tn_uservariablename="Tn"  # Nom de la variable Tn

Tn_hold_IDX="17"        # Idx de la variable Tn_hold
Tn_hold_uservariablename="Tn_Hold"  # Nom de la variable Tn_hold

	
        Tn=$(curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command&param=getuservariable&idx=$Tn_IDX"| jq -r .result[].Value)
		echo "Recuperation valeur variable Tn"
		echo $Tn
		curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command&param=updateuservariable&idx=$Tn_hold_IDX&vname=$Tn_hold_uservariablename&vtype=2&vvalue=$Tn"
		echo "Mise a jour valeur variable Tn_hold avec la Temperature mini"		
       curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command&param=updateuservariable&idx=$Tn_IDX&vname=$Tn_uservariablename&vtype=2&vvalue=150"
		echo "Changement valeur variable Tn a 150 pour débuter un nouveau jour"
suivez les commandes de la rubrique setting afin lancer ce fichier via un crontab, et le rendre executable via chmod +x. indiquez enfin l'idx des variables Tn et Tn_hold et l'ip de domoticz.
ensuite créez un fichier script_variable_calcul_dju.lua

Code : Tout sélectionner

--[[     Calcul DJU du jour

~/domoticz/scripts/lua_parsers/calcul_dju.lua
Un degré jour est calculé à partir des températures météorologiques extrêmes du lieu et du jour J : 
- Tn : température minimale du jour J mesurée à 2 mètres du sol sous abri et relevée entre J-1 (la veille) à 18h et J à 18h UTC. 
- Tx : température maximale du jour J mesurée à 2 mètres du sol sous abri et relevée entre J à 6h et J+1 (le lendemain) à 6h UTC. 
- S : seuil de température de référence choisi. 
- Moy = (Tn + Tx)/2 Température Moyenne de la journée
Pour un calcul de déficits  de température par rapport au seuil choisi : 
- Si S > TX (cas fréquent en hiver) : DJ = S - Moy 
- Si S ≤ TN (cas exceptionnel en début ou en fin de saison de chauffe) : DJ = 0 
- Si TN < S ≤ TX (cas possible en début ou en fin de saison de chauffe) : DJ = ( S –TN ) * (0.08 + 0.42 * ( S –TN ) / ( TX – TN ))
]]--
---------------------------------------------------------------------------
-- Variables 
---------------------------------------------------------------------------
local S = 18 -- seuil de température de non chauffage (par convention : 18°C)
local temp_ext  = 'Temp+Hum extérieure' -- nom de la sonde extérieure
local var_chauffage="Nb Jours de Chauffage" -- nom de la variable permettant de compter le nombre de jour de chauffage et de connaitre l'état du chauffage  0 = Arret, >0 Nb de jours
local url = '192.168.10.240:8080'   -- user:pass@ip:port de domoticz
local idx_dju = 474 -- IDX du compteur virtuel DJU à créer avant de lancer ce script
local name_dju = "DJU" -- Nomp du compteur virtuel DJU à créer avant de lancer ce script
local indexArray=0
------------------------------------------------------------------------------
local debugging = true  -- true ou false
------------------------------------------------------------------------------ 
function voir_les_logs (s)
    if (debugging) then 
        print (s);
    end
end

function url_encode(str)
  if (str) then
    str = string.gsub (str, "\n", "\r\n")
    str = string.gsub (str, "([^%w %-%_%.%~])",
        function (c) return string.format ("%%%02X", string.byte(c)) end)
    str = string.gsub (str, " ", "+")
  end
  return str   
end 

function round(n)
    return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
end

commandArray = {}

if uservariablechanged[var_chauffage] then

voir_les_logs("=========== Calcul DJU (v1.0) ===========",debugging);
	
	total_dju = string.match(otherdevices_svalues[name_dju], "%d+%.*%d*")
			voir_les_logs("--- --- --- Total DJU : ".. total_dju .." DJU",debugging);
		
			if (tonumber(uservariables[var_chauffage]) > 0) then --le chauffage est allumé, calcul des DJU
			voir_les_logs("--- --- --- Nb de jour de chauffage : " .. tonumber(uservariables[var_chauffage]) .." --- --- --- ",debugging);
		
max_min = string.match(otherdevices_svalues[temp_ext], "%d+%.*%d*")
t_max_min = tonumber(max_min)
voir_les_logs("--- --- --- Température Ext : "..t_max_min,debugging);

TN = tonumber(uservariables['Tn_Hold'])
TX = tonumber(uservariables['Tx'])
MOY = tonumber((TN + TX) / 2)

	if (S > TX) then
		voir_les_logs("--- --- --- Température de référence supérieure à Variable Tx : ".. TX,debugging);
		voir_les_logs("--- --- --- Température de référence : ".. S,debugging);
		voir_les_logs("--- --- --- Variable TX : ".. TX,debugging);
		voir_les_logs("--- --- --- Moyenne : ".. MOY,debugging);
DJ = round(S - MOY)
		voir_les_logs("--- --- --- DJU : ".. DJ,debugging);
-- commandArray['UpdateDevice']= idx_dju ..'|0|'.. tostring(DJ)
DJ = tonumber(DJ) + tonumber(total_dju) -- on ajoute les DJU du jour à l'index précédent
 commandArray[indexArray] = {['UpdateDevice'] = idx_dju..'|0|'..tostring(DJ)}
 indexArray=indexArray+1
 commandArray[indexArray] = {['Variable:Tx'] = tostring(-50)} -- Réinitialisation variable Tx
 indexArray=indexArray+1

	elseif (S <= TN) then
		voir_les_logs("--- --- --- Température de référence inférieure ou égale à Variable Tn : ".. TN,debugging);
	--commandArray['Variable:Tx'] = tostring(t_max_min) -- mise à jour de la variable tx
		voir_les_logs("--- --- --- Température de référence : ".. S,debugging);
		voir_les_logs("--- --- --- Variable Tn : ".. TN,debugging);
		voir_les_logs("--- --- --- Moyenne : ".. MOY,debugging);
DJ = 0
		voir_les_logs("--- --- --- DJU : ".. DJ,debugging);	
DJ = tonumber(total_dju) -- on renvoi l'index du jour précédent
-- commandArray['UpdateDevice']= idx_dju ..'|0|'.. tostring(DJ)
DJ = tonumber(DJ) + tonumber(total_dju) -- on ajoute les DJU du jour à l'index précédent
 commandArray[indexArray] = {['UpdateDevice'] = idx_dju..'|0|'..tostring(DJ)}
 indexArray=indexArray+1
 commandArray[indexArray] = {['Variable:Tx'] = tostring(-50)} -- Réinitialisation variable Tx
 indexArray=indexArray+1
	else 
		voir_les_logs("--- --- --- Température de référence comprise entre Tn et Tx",debugging);
	-- commandArray['Variable:Tx'] = tostring(t_max_min) -- mise à jour de la variable tx
		voir_les_logs("--- --- --- Température de référence : ".. S,debugging);
		voir_les_logs("--- --- --- Variable TN : ".. TN,debugging);
		voir_les_logs("--- --- --- Variable TX : ".. TX,debugging);
		voir_les_logs("--- --- --- Moyenne : ".. MOY,debugging);

S_TN = 	S - TN
		voir_les_logs("--- --- --- S - TN : ".. S_TN,debugging);
TX_TN = TX - TN
		voir_les_logs("--- --- --- TX - TN : ".. TX_TN,debugging);
DJ =  round(S_TN  * ("0.08" + "0.42" * S_TN / TX_TN))
	--DJ = ( S – TN ) * ('0.08' + '0.42' * ( S – TN ) / ( TX - TN ))
		voir_les_logs("--- --- --- DJU : ".. DJ,debugging);
--commandArray['UpdateDevice']= idx_dju ..'|0|'.. tostring(DJ)
DJ = tonumber(DJ) + tonumber(total_dju) -- on ajoute les DJU du jour à l'index précédent
 commandArray[indexArray] = {['UpdateDevice'] = idx_dju..'|0|'..tostring(DJ)}
 indexArray=indexArray+1
 commandArray[indexArray] = {['Variable:Tx'] = tostring(-50)} -- Réinitialisation variable Tx
 indexArray=indexArray+1
	end
--commandArray['Variable:'.. var_chauffage]=tostring(tonumber(uservariables[var_chauffage])+1)  -- Ajoute un jour de chauffage supplémentaire dans la variable			
				else -- Le chauffage est éteint, pas de calcul de DJU
		voir_les_logs("--- --- --- Nb de jour de chauffage : " .. tonumber(uservariables[var_chauffage]) .." --- --- --- ",debugging);
		voir_les_logs("--- --- --- Le chauffage est arrêté --- --- --- ",debugging);
 commandArray[indexArray] = {['Variable:Tx'] = tostring(-50)} -- Réinitialisation variable Tx
 indexArray=indexArray+1				
		end

		
voir_les_logs("=========== Fin Calcul DJU (v1.0) ===========",debugging);	
end	
return commandArray


idem que pour le premier script , personnalisez les idx des variables l'ip de domoticz le nom de de votre sonde de température...
Vient en dernier la création d'un script de lancement du calcul à 18h00 chaque jour. J'ai choisi de conditionner le lancement de ce script au fait que le chauffage est allumé. je teste donc si la variable de Nb Jours de Chauffage et supérieure à 0. Lors de l’arrêt du chauffage, il faudra donc remettre cette variable à 0. et bien sur la mettre à 1 le jour de l'allumage du chauffage.

Code : Tout sélectionner

#!/bin/bash

# Settings
#crontab -e
# 0 18 * * * sudo /home/pi/domoticz/scripts/sh/lance_calcul_dju.sh
# chmod +x /home/pi/domoticz/scripts/sh/lance_calcul_dju.sh
DOMO_IP="192.168.10.240"      # Domoticz IP Address
DOMO_PORT="8080"         # Domoticz Port
nb_IDX="18" # IDX variable Nb Jours de Chauffage 18
uservariablename="Nb Jours de Chauffage"
uservariabletype="2"

urlencode() {
    # urlencode <string>

    local LANG=C
    local length="${#1}"
    for (( i = 0; i < length; i++ )); do
        local c="${1:i:1}"
        case $c in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            *) printf '%%%02X' "'$c" ;; 
        esac
    done
}
       nb=$(curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command&param=getuservariable&idx=$nb_IDX"| jq -r .result[].Value)
		echo $nb
			if expr "$nb" '>' 0
			then
			echo "test condition avant calcul"
			echo $nb
		nb=$((nb+1))
		echo "test condition apres calcul"
		echo $nb
		uservariablename=$( urlencode "$uservariablename" )
		#curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command&param=udevices&script=calcul_dju.lua"
		curl -s -i -H "Accept: application/json" "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command&param=updateuservariable&idx=$nb_IDX&vname=$uservariablename&vtype=$uservariabletype&vvalue=$nb"
					else
				echo $nb
		fi
Comme pour le fichier bash précédent suivez les commandes de la rubrique setting afin lancer ce fichier via un crontab, et le rendre exécutable via chmod +x. Renseignez les caractéristiques de la variables Nb Jours de Chauffage et l'ip de domoticz.

Vos premiers DJU ne seront visibles qu'après une période de 24 h après le calcul de 18 heures
A vous de jouer
A vous de jouer
domoticz beta/RaspBerry PI3 stretch
https://pon.fr github
papoo
Messages : 2029
Inscription : 10 janv. 2016, 11:29
Localisation : Limoges (87)
Contact :

Re: Calcul de DJU

Message par papoo »

J'ai oublié le script pour enregistrer les températures minimale et maximale dans les variables adhoc

Code : Tout sélectionner

--[[   
~/domoticz/scripts/lua/script_device_temp_ext.lua
 tx = température maximale du jour J mesurée à 2 mètres du sol sous abri et relevée entre J à 6h et J+1 (le lendemain) à 6h UTC. 
 tn = température minimale du jour J mesurée à 2 mètres du sol sous abri et relevée entre J-1 (la veille) à 18h et J à 18h UTC. 
]]--
------------------------------------------------------------------------------

--------------------------------
------ Tableau à éditer ------
--------------------------------
local debugging = false  -- true ou false
local url = '192.168.10.240:8080'   -- user:pass@ip:port de domoticz
local temp_ext  = 'Temperature exterieure' -- nom de la sonde extérieure
------------------------------------------------------------------------------
--------------------------------------------------------------------------- 
function voir_les_logs (s)
    if (debugging) then 
        print (s);
    end
end

---------------------------------------------------------------------------

commandArray = {}
if (devicechanged[temp_ext])then
voir_les_logs("=========== Mini/Maxi Température Extérieure (v1.0) ===========",debugging);
		if(uservariables['Tx'] == nil) then
		-- Création de la variable Tx si elle n'existe pas
         commandArray['OpenURL']=url..'/json.htm?type=command&param=saveuservariable&vname=Tx&vtype=2&vvalue=150'
            voir_les_logs("--- --- --- Création Variable Tx manquante --- --- --- ",debugging);
        print('script supendu')
		end
		if(uservariables['Tn'] == nil) then
         commandArray['OpenURL']=url..'/json.htm?type=command&param=saveuservariable&vname=Tn&vtype=2&vvalue=-150'
		 -- Création de la variable Tn si elle n'existe pas
            voir_les_logs("--- --- --- Création Variable Manquante Tn --- --- --- ",debugging);
        print('script supendu')
		end
max_min = string.match(otherdevices_svalues[temp_ext], "%d+%.*%d*")
t_max_min = tonumber(max_min)
voir_les_logs("--- --- --- Température Ext : "..t_max_min,debugging);
	if (t_max_min < tonumber(uservariables['Tn'])) then
		        voir_les_logs("--- --- --- Température Extérieure inférieure à Variable Tn : "..uservariables['Tn'],debugging);
	commandArray['Variable:Tn'] = tostring(t_max_min) -- mise à jour de la variable tn
voir_les_logs("--- --- --- mise à jour de la Variable Tn  --- --- --- ",debugging);
	elseif (t_max_min > tonumber(uservariables['Tx'])) then
		        voir_les_logs("--- --- --- Température Extérieure supérieure à Variable Tx : "..uservariables['Tx'],debugging);
	commandArray['Variable:Tx'] = tostring(t_max_min) -- mise à jour de la variable tx
voir_les_logs("--- --- --- mise à jour de la Variable Tx  --- --- --- ",debugging);	
	end
end
return commandArray
désolé
domoticz beta/RaspBerry PI3 stretch
https://pon.fr github
benbidouille
Messages : 102
Inscription : 11 déc. 2017, 11:48

Re: Calcul de DJU

Message par benbidouille »

Bonjour,
Bien belle implémentation, je soutiens à 200% l'importance que de disposer d'un indicateur de rigueur de la saison de chauffe, et le DJU est un indicateur parfaitement adapté qu'il convient de rapprocher du nombre de KWh consommé sur la période pour faire les bilans.

Toutefois, je m'interroge de la pertinence de la méthode de Météo France qui historiquement moyenne les min et max aboutissant donc a une approximation, je suppose que cette méthode est héritée de l'époque ou nous ne disposions pas d'outils informatiques donc de relevés en manuel de thermomètres enregistreurs avec min et max à horaire constant.

N'est il pas temps d'évoluer et dès lors que domoticz dispose d'un "device" de température extérieur, pourquoi ne pas lui préférer un device virtuel de type compteur qui calculerait a chaque intervalle de temps définit dans domoticz DJU_base_18 = DJU_base_18 + ( 18 - Temp_Ext ) * Intervalle_de_temps / 1440

Tout ceci à condition que l'on soit en période de chauffe et que la température extérieure soit inférieure à 18, l'intervalle_de_temps étant en minutes.

J'avais implémenté cette méthodologie qui me parait beaucoup plus précise et moins approximative dans un ancien système que je souhaite obsoleter au dépend de domoticz.

Totalement bizu en scripts, je vais en tenter une implémentation dans domoticz, aussi je n'exclue pas d'avoir recours aux aides de ce forum pour y parvenir.

Bilan:
- 1 device virtuel de type switch pour remettre les compteur DJU a zero et sauvegarder quelques donnée en variable utilisateur
- 1 compteur pour le cumul des DJU sur la période
- Sauvegarde des index du compteurs de circuit de chauffage en variable utilisateurs pour le calcul de KWh / DJU

Il est bien difficile de faire son choix dans les multiples type de device virtuels proposés et surtout d'appréhender le type de graphique qui sera mis a disposition par domoticz .....

Que me recommanderiez vous, plutot bash ou lua ? Quel type de device virtuel domoticz utiliser ?
Cordialement.
RPI3 + WDPiDrive + UPS Pico HV3.0B HAT + Teleinfo USB (6) + 1Wire GPIO + DS18B20 (15)+ Gateway MySensor NRF24, Sensors , Relais ... + Gateway Velux .... + Gestion Pompe à Chaleur + NRFDoctor .... tout en DIY
papoo
Messages : 2029
Inscription : 10 janv. 2016, 11:29
Localisation : Limoges (87)
Contact :

Re: Calcul de DJU

Message par papoo »

pour moi il faut dissocier le calcul de dju (que l'on peut injecter dans un simple capteur virtuel/compteur) du ratio kwh/dju
pour ce qui est du script, cela doit être faisable en lua. je vais essayer de faire ça voir ce que cela donne.
domoticz beta/RaspBerry PI3 stretch
https://pon.fr github
benbidouille
Messages : 102
Inscription : 11 déc. 2017, 11:48

Re: Calcul de DJU

Message par benbidouille »

Heureux de voir que l'idée te séduit.
C'est tout a fait comme cela que je l'envisageait avec les DJU rapproché des KWh en phase 2.

Dans un premier temps et pour me familiariser avec LUA, je vais implémenter tes scripts en mode Meteo France, puis aborderai la version en mode Integrale, cela permettra de comparer les résultats obtenus.

Débutant et en phase d'observation des fonctionnalités, je trouve qu'il y a des interruptions de services ou d’erreur de lecture de device ce qui nécessitera probablement d'ajouter un peu d'intelligence dans le calcul en mode integrale pour compenser notamment l'absence de mesure pendant un laps de temps, c'est l’inconvénient de cette méthode intégrale qui nécessite une bonne fi&bilité du flux device et donc un traitement des erreurs adapté.
RPI3 + WDPiDrive + UPS Pico HV3.0B HAT + Teleinfo USB (6) + 1Wire GPIO + DS18B20 (15)+ Gateway MySensor NRF24, Sensors , Relais ... + Gateway Velux .... + Gestion Pompe à Chaleur + NRFDoctor .... tout en DIY
Antori91

Re: Calcul de DJU

Message par Antori91 »

-
Dernière modification par Antori91 le 03 avr. 2021, 16:58, modifié 2 fois.
papoo
Messages : 2029
Inscription : 10 janv. 2016, 11:29
Localisation : Limoges (87)
Contact :

Re: Calcul de DJU

Message par papoo »

joli projet bravo
par contre tes degrés jour n'en sont pas vraiment, il te faudrait calculer avec ton intervalle de 5 mn les degrés jour comme cela
Degrés Jours[Temp] = ( 18 - Temp_Ext ) * 5 / 1440 et faire la somme une fois par jour.
avec la méthode météofrance çà donne ça chez moi
2017-12-27 14_42_12-Domoticz.png
2017-12-27 14_42_12-Domoticz.png (128.24 Kio) Consulté 11435 fois
Dernière modification par papoo le 27 déc. 2017, 15:04, modifié 1 fois.
domoticz beta/RaspBerry PI3 stretch
https://pon.fr github
papoo
Messages : 2029
Inscription : 10 janv. 2016, 11:29
Localisation : Limoges (87)
Contact :

Re: Calcul de DJU

Message par papoo »

benbidouille a écrit :je trouve qu'il y a des interruptions de services ou d’erreur de lecture de device ce qui nécessitera probablement d'ajouter un peu d'intelligence dans le calcul en mode integrale pour compenser notamment l'absence de mesure pendant un laps de temps, c'est l’inconvénient de cette méthode intégrale qui nécessite une bonne fi&bilité du flux device et donc un traitement des erreurs adapté.
je finalise un script qui calcule chaque minute . meme si l'on perd quelques mesures je ne pense pas que cela impacte excessivement le résultat journalier. actuellement chez moi Température extérieure de 6.4°C le calcul donne chaque minute 0.0080555555555556°
2017-12-27 15_01_46-Domoticz.png
2017-12-27 15_01_46-Domoticz.png (4.42 Kio) Consulté 11433 fois
domoticz beta/RaspBerry PI3 stretch
https://pon.fr github
Antori91

Re: Calcul de DJU

Message par Antori91 »

-
Dernière modification par Antori91 le 03 avr. 2021, 16:58, modifié 1 fois.
papoo
Messages : 2029
Inscription : 10 janv. 2016, 11:29
Localisation : Limoges (87)
Contact :

Re: Calcul de DJU

Message par papoo »

Antori91 a écrit : Pour faire plus simple, ma courbe des valeurs instantanées ne sont pas des degrés jours.
exactement. du coup difficile d'exploiter les données journalières dans un autre script
domoticz beta/RaspBerry PI3 stretch
https://pon.fr github
Répondre