[Resolu] DzVents et mise à jour de dummy counter

Forum dédié aux problématiques concernant les scripts pour DomoticZ.
Entourez votre code et les logs avec les balises nommées code grâce au bouton <\>.
Zang2
Messages : 21
Inscription : 27 févr. 2022, 21:40

[Resolu] DzVents et mise à jour de dummy counter

Message par Zang2 »

Salut,

J'ai une pompe et j'aimerais surveiller sa fréquence d'activation. J'utilise un wattmètre mysensor qui me donne la consommation de la pompe, et grâce à cela, je parviens facilement à détecter les activations dès que la consommation dépasse quelques watts. Ça fonctionne bien, j'envoie des notifications et je les reçois correctement.

Maintenant, j'aimerais incrémenter un compteur à chaque déclenchement et, à long terme, pouvoir obtenir des graphiques dans les logs indiquent le nombre d'activations par mois.

J'ai essayé avec un compteur de type Rain (afin de reproduire quelque chose qui ressemble à ce que mon pluviomètre RTS me fournit). J'ai également essayé avec un compteur simple et un "compteur incrémental". Mais avec ces trois types de compteurs, je n'arrive pas à comprendre leur fonctionnement !

Première question : quel type de compteur me conseillez-vous ?
Deuxième question : comment l'utiliser ? Est-ce que je dois stocker un compteur dans une variable et l'incrémenter pour le donner au compteur ? Est-ce que je dois gérer moi-même la remise à zéro quotidienne ?

Merci d'avance pour votre aide !

PS : J'ai bien lu la documentation de DzEvents, mais c'est vraiment sommaire et il manque cruellement d'exemples.https://www.domoticz.com/wiki/DzVents:_ ... _scripting
Dernière modification par Zang2 le 25 juil. 2023, 19:40, modifié 2 fois.
lost
Messages : 1511
Inscription : 12 nov. 2016, 11:01

Re: DzVents et mise à jour de dummy counter

Message par lost »

Zang2 a écrit : 26 juin 2023, 22:03 J'ai essayé avec un compteur de type Rain (afin de reproduire quelque chose qui ressemble à ce que mon pluviomètre RTS me fournit). J'ai également essayé avec un compteur simple et un "compteur incrémental". Mais avec ces trois types de compteurs, je n'arrive pas à comprendre leur fonctionnement !
Plutôt que le nb de déclenchements, peut-être serait-il plus significatif de compter un temps d'activation total, voir une puissance moyenne consommée (même si elle doit peu varier en fonctionnement) qui pourrait peut-être même s'étalonner en cumul d'eau évacuée approximatif (ou, en tout cas, en donnerait une idée plus précise/synthétique qu'un compteur de déclenchements simple).

Dans ce dernier cas, j'ai un script en Lua que j'avais réalisé afin d'avoir des mesures de conso moyennes par tranche de 10mn (temps cible, vu que c'est un script type device qui va réagir sur des variations de conso ; mais le wattmètre que j'utilise en tête de tableau peut se configurer niveau reports en temporel et/ou en % de variation de la conso, si on mets 1% on est rarement plus de 30s sans recevoir une mesure, donc les 10mn cible restent assez respectées en pratique), que mon wattmètre n'est pas capable de donner lui même (reports de conso instantanées seules).

En résumé, le script quand il reçoit une mesure de puissance va "intégrer" en utilisant le last_update des sommes de "puissance*temps".

Il utilise 2 variables utilisateur et alimente 1 compteur virtuel de type "usage/electric".

Le temps cible de 10mn (600s) est configuré dans une variable, ainsi que les noms des variables/compteur à créer séparément. Par contre, c'est du Lua, je ne me suis jamais mis à dzVent qui était moins développé que maintenant quand j'ai commencé avec Domoticz il y a 7 ans.

Pour une pompe qui déclenche peu, 10mn c'est sans doute un peu beaucoup même si au final cela permettrait d'horodater plus précisément les déclenchements et via la conso donner une idée des volumes pompés sur ces tranches de temps. 30mn (1800s) suffirait peut-être.

J'avais a l'époque tenté d'utiliser un compteur double reportant les valeurs calculées et faisant un total par 24h automatiquement, mais jamais réussi à le faire fonctionner. La fonction de MAJ compteur est codée direct en Lua et cela devait désormais fonctionner, la modif sera triviale.

Code : Tout sélectionner

-- Smart-Meter (per 10mn/600s "targetted" time slice) mean power consumption
-- Only use slices > 5mn Domoticz log/graph record time in DB or some values
-- will be overwritten! Time slice is a target value that may be exceeded by
-- last measurement delay that may be minimised by increasing device reports.
--
-- Changelog:
--   31/01/2023, YL, 1st version.
--   01/02/2023, Change basic mean compute to samples approx integration over time.
--   03/02/2023, Log power mean updates with last slice real duration.

-- User editabe settings:
devSmartMeterPwr='SmartMeter W'    -- Real PWR consumtion measurement device name.
devMeanPwrVrtSen='Puissance MOY'   -- Virtual sensor type "usage/electricity" name.
varPwrSum='pwrSum'   -- User variable, decimal/float type, storing current time slice power ~integral.
varPwrLast='pwrLast' -- User variable, decimal/float type, storing last pwr watt value.
maxLastUpdateVrt=600 -- Virtual sensor update rate.
maxPeakPwr=13000     -- Device limit is 63A, measures exceeding are filtered.

commandArray = {}

--
-- Internal fct :
-- Get current script exec time & compute last 'device' or 'uservariable' update time.
--
local function timeLastUpdate(devOrVar, isUserVar)
    t1  = os.time()
    
    if (isUserVar == true) then
        sT0 = uservariables_lastupdate[devOrVar]
    else
        sT0 = otherdevices_lastupdate[devOrVar]
    end

    -- Returns a date time like 2016-12-02 15:30:10
    -- => Format as os.time & compute diff :

    year    = string.sub(sT0, 1, 4)
    month   = string.sub(sT0, 6, 7)
    day     = string.sub(sT0, 9, 10)
    hour    = string.sub(sT0, 12, 13)
    minutes = string.sub(sT0, 15, 16)
    seconds = string.sub(sT0, 18, 19)
    t0      = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
    tDiff   = os.difftime(t1, t0)

    return(tDiff)
end

--
-- Update virtual sensor
--
local function updateNum(dev, value1)
    local cmd = string.format("%d|0|%d", otherdevices_idx[dev], math.floor(value1))
    table.insert (commandArray, { ['UpdateDevice'] = cmd } )
end

--
-- MAIN
--
if (devicechanged[devSmartMeterPwr]) then
    curPwr = tonumber(devicechanged[devSmartMeterPwr])

    -- Immediately log & return on bad pwr figures...
    if (curPwr > maxPeakPwr) then
        print('WARNING : '..devSmartMeterPwr..' reports '..curPwr..'W !!!')
        return commandArray
    end

    tLastMean = timeLastUpdate(devMeanPwrVrtSen, false)
    
    -- Debug :
    --print(devSmartMeterPwr..': P='..curPwr..'W ; Last : '..tLastMean..'s')

    pwrLast   = uservariables[varPwrLast]
    pwrSum    = uservariables[varPwrSum]
    sumDeltaT = timeLastUpdate(varPwrSum, true)

    -- Calc pwr sum + store. Set current mean pwr if time slice exceeded & reset user vars.
    if (tLastMean > maxLastUpdateVrt) then
       meanPwr = (pwrSum + pwrLast*sumDeltaT) / tLastMean

       --Log update :
       print(string.format('%s : New time slice (after %ds) => Record Pmean=%.2fW', devMeanPwrVrtSen,  tLastMean, meanPwr))

       updateNum(devMeanPwrVrtSen, meanPwr)
       commandArray['Variable:'..varPwrSum]  = '0'
       commandArray['Variable:'..varPwrLast] = tostring(curPwr)
    else
       pwrSum = pwrSum + pwrLast*sumDeltaT

       --Debug :
       --print('Update current Psum='..pwrSum..'Ws ; deltaT='..sumDeltaT..'s')

       commandArray['Variable:'..varPwrLast] = tostring(curPwr)
       commandArray['Variable:'..varPwrSum]  = tostring(pwrSum)
    end
end

return commandArray
Ce qui donnera ce type de graphe:
pMoy.jpg
pMoy.jpg (21.79 Kio) Consulté 1212 fois
On voit bien les heures ou de l’électroménager est mis en marche pour préparer les repas, le début des heures-creuses à 22h (actuellement, belle saison, seul le ballon ECS consomme significativement et surtout en début de plage)... et la conso de fond du reste.

Niveau logs, on a ceci:

Code : Tout sélectionner

$ grep "Record Pmean" /tmp/domoticz.txt | more
2023-06-26 00:02:07.039  Status: LUA: Puissance MOY : New time slice (after 630s) => Record Pmean=1082.18W
2023-06-26 00:12:36.256  Status: LUA: Puissance MOY : New time slice (after 629s) => Record Pmean=640.85W
2023-06-26 00:23:05.450  Status: LUA: Puissance MOY : New time slice (after 629s) => Record Pmean=733.66W
2023-06-26 00:33:34.688  Status: LUA: Puissance MOY : New time slice (after 629s) => Record Pmean=867.63W
2023-06-26 00:44:09.111  Status: LUA: Puissance MOY : New time slice (after 635s) => Record Pmean=859.16W
2023-06-26 00:54:38.313  Status: LUA: Puissance MOY : New time slice (after 629s) => Record Pmean=664.80W
2023-06-26 01:04:51.941  Status: LUA: Puissance MOY : New time slice (after 613s) => Record Pmean=543.72W
2023-06-26 01:15:36.781  Status: LUA: Puissance MOY : New time slice (after 645s) => Record Pmean=581.99W
2023-06-26 01:26:05.986  Status: LUA: Puissance MOY : New time slice (after 629s) => Record Pmean=555.72W
2023-06-26 01:36:24.815  Status: LUA: Puissance MOY : New time slice (after 619s) => Record Pmean=425.39W
2023-06-26 01:48:38.053  Status: LUA: Puissance MOY : New time slice (after 734s) => Record Pmean=601.69W
...
On voit qu'on reste pas trop loin des 600s de temps cible, juste une mesure ici qui excède significativement (la dernière de l'extrait de log présenté) avec 734s mais c'est au milieu de la nuit avec donc peu de variation de conso et n’entache pas la précision du calcul, de toutes manières approché (l'incertitude est ici liée à la configuration du % de variation générant un report du wattmètre). Juste la résolution temporelle mais quand c'est calme plat on s'en fout un peu.

NOTE: Arrivé là, on peut se dire pourquoi faire cela alors qu'on a déjà des courbes de conso dispo? Tout simplement car Domoticz ne prends que des échantillons des mesures toutes les 5mn, afin de limiter la taille de la BDD, et que pour des consommateurs de faible durée d'activation/peu constants, eh bien on a en standard une information peu fiable et hélas aucun calcul de moyenne et véritables min/max en en standard et qu'il faut alors scripter. Ici, avec 10mn de moyennage, on est au dessus des 5mn d'échantillonnage et on a ainsi des moyennes fiables ni ne loupe de moments ou la conso devient non nulle.
Zang2
Messages : 21
Inscription : 27 févr. 2022, 21:40

Re: DzVents et mise à jour de dummy counter

Message par Zang2 »

Bonsoir,

Tout d'abord merci pour ta réponse, et désolé de ne pas avoir réagis plus vite, il me semblait m'être abonné à ce sujet et visiblement ce n'était pas le cas ! du coup j'ai pas eu la notification...

Malheureusement ça fait 2 soirs que je me mets trop tard le soir à la lecture de ton poste pour espérer tout cerner :D

Pourquoi faire un compteur d'activation ? Parce que c'est une pompe a flotteur donc le volume évacué à chaque activation est relativement constant.
Pour être sur de ne pas rater d'activation, dans l'arduino mysensor, je calcul le max de puissance sur 10min et je n'envoie qu'une valeur toutes les 10min. Le script DzVents regarde la valeur et a chaque pic je voulais incrémenter un compteur.
Mon but principale c'est d'avoir à terme un histogramme avec le nombre d'activation part mois (que je peux facilement convertir en volume pompé).

Je viens de créer un device de type usage elec et de mettre ça dans mon code :

Code : Tout sélectionner

     counter = counter + 1;
                domoticz.devices('PompeUsage').updateElectricity(0,counter)
On va voir si ça marche mieux que mes expériences précédent avec les compteurs "normaux" !
Zang2
Messages : 21
Inscription : 27 févr. 2022, 21:40

[Resolu] DzVents et mise à jour de dummy counter

Message par Zang2 »

Bonsoir,

Bon j'ai finalement réussi à faire ce que je voulais.

J'ai crée un dummy sensor de type "Rain".
J'ai crée une variable utilisateur nommée : "CumulPompe".

J'ai crée 2 scripts :
Le 1er qui réinitialise le compteur "CumulPompe" une fois par jour (à 00:05). En dzVents, ça donne ça :

Code : Tout sélectionner

return {
	on = {
		timer = {
			'at 00:05',					-- specific time

		}
	},
	

	execute = function(domoticz, timer)

            domoticz.variables('CumulPompe').set(0)
            domoticz.devices('Pompe').updateRain(0,0)
            
            print('Reset du compteur de la pompe')
            
	end
}
Et le 2e qui met à jour le device "Rain" nommé "Pompe", à chaque activation de la pompe :

Code : Tout sélectionner

return {
	on = {
		timer = {
			'every minute',				-- causes the script to be called every minute
		}
	},
	
	execute = function(domoticz, timer)
	
        local currentUsage = domoticz.devices('Usage').actualWatt
        if (currentUsage > 10) then
    
            if (domoticz.variables('PompeStatus').value == 0) then
            
                domoticz.variables('PompeStatus').set(1)
                
                local cumul = domoticz.variables('CumulPompe').value
                cumul = cumul + 1
                domoticz.variables('CumulPompe').set(cumul)
                
                domoticz.notify('Activation pompe detectee')
                
                domoticz.devices('Pompe').updateRain(1,cumul)      
                
            end
        end    
        
        print('Fin script - Compteur pompe')

    end
}
"Usage" c'est mon wattemetre. J'ai oublié que j'ai aussi crée une variable "PompeStatus" qui permet de détecter des fronts montants sur "Usage", et donc ne pas risque de compter plusieurs activations à la suite.


Au final, ce qui me manquait et que j'ai du trouvé de façon expérimentale c'est :
- le device de type rain doit recevoir au moins une update par jour.
- le 2e paramètre de updateRain() est le cumul journalié (a réinitialiser manuellement 1 fois par jour).

Pour le 1er paramètre je passe 1 à chaque activation. Dans les graphiques du device je vois bien les activations dans le 1er graphique, et le cumul dans les graphiques suivants.
Keros
Messages : 6638
Inscription : 23 juil. 2019, 20:57

Re: [Resolu] DzVents et mise à jour de dummy counter

Message par Keros »

Tu sais qu'avec le DzVents tu peux regrouper tes deux scripts dans un seul en gérant différent trigger ? Regarde dans les petits guides que j'ai rédigés (lien dans ma signature), il y en a un qui explique pourquoi je suis passé au DzVents et je fais mention du regroupement de scripts.

Pour pousser plus loin, tu pourrais utiliser les persistant data à la place de ta variable utilisateur.

Ah, et le print() dans un script DzVents, ça pique un peu les yeux : il a une fonction DzVents pour ça qui permet même de gérer le niveau de débug / log en début de script ;)
Comment bien utiliser le forum : Poser une question, Mettre un script, un fichier, une image ou des logs
Mes petits guides : Débuter en programmation, Le débogage, Le choix de matériel, Les sauvegardes
Ma présentation - Mes Tutos
Zang2
Messages : 21
Inscription : 27 févr. 2022, 21:40

Re: [Resolu] DzVents et mise à jour de dummy counter

Message par Zang2 »

Salut,

Merci pour tes tuyaux, mais honetement j'ai tres peu de temps à consacrer à ma domotique, donc tant que ça fonctionne ... :lol:

Concernant les "multi-triggers", est-ce que je peux écrire ça :

Code : Tout sélectionner

	if item.trigger == 'at 00:05' then
			-- je reset mon compter
	else
			-- je regarde si la pompe a déclacher.
	end
?

Dans ton exemple tu fais ça avec bouton1 et bouton2, est-ce que ça marche aussi avec le timer ?
Keros
Messages : 6638
Inscription : 23 juil. 2019, 20:57

Re: [Resolu] DzVents et mise à jour de dummy counter

Message par Keros »

Oui, tu peux l'écrire comme ça. Maintenant, attention au Else qui prendra tous les autres cas. Tant que tu auras que 2 trigger, c'est bon ;)

Généralement, j'essaye de mettre un elseif if item.trigger == 'le nom du trigger' à chaque fois. C'est plus facile pour déboguer quand tu reviens dessus 6 mois après.
Comment bien utiliser le forum : Poser une question, Mettre un script, un fichier, une image ou des logs
Mes petits guides : Débuter en programmation, Le débogage, Le choix de matériel, Les sauvegardes
Ma présentation - Mes Tutos
Zang2
Messages : 21
Inscription : 27 févr. 2022, 21:40

Re: [Resolu] DzVents et mise à jour de dummy counter

Message par Zang2 »

Ok, merci pour l'info. Peux importe comment tu écrits ton if ou elseif il faut toujours gérer le cas par défaut !

J'ai fait une petite modif sur mon code, je fais maintenant le reset à 23:58.
J'ai eu un cas ou j'avais 2 jours de suite la même valeur et je pense que c'est parce que j'ai eu une écriture des valeurs de la veille entre 00:00 et 00:05...

Info importante : il n'est visiblement pas un probleme de faire plusieurs update dans la meme tranche horaire, avec des valeurs différentes, visiblement le device garde uniquement la valeur la plus importante.
Répondre