Beta 3.3.10 Problème sur la fonction lastChangeStateDuration

Bonjour,

Depuis le passage en BETA, il semble que lastChangeStateDuration ne renvoie pas la valeur en seconde avant 1mn lors d’un changement d’état. (voir post plus bas ce n’est pas 1mn mais c’est au deuxième renvoit de valeur si on est sur toujours répéter)

Mon NUT BLEA et capté à 17h36 (lancement du scénario povoqué par son changement d’état) mais dans le test, lastChangeStateDuration ne renvoie qqch qu’après 1mn. En Jeedom stable c’était OK depuis longtemps.

Est ce que quelquechose a impacté la fonction lastChangeStateDuration qui pour mon besoin doit être précise dès le changement d’état de l’objet

Ci après mon scénario :

stateDuration(#[Alarme][Alarme][Actif]#,1) > 300 ET (#[Maison][Mode Présence][Mode]# == "Absence" || (#[Alarme][Alarme][Statut]# == 1 ET #[Maison][Mode Présence][Mode]# != "Nuit" ) ) ET (#[xxx][Nut_C3][Present]# == 1 ET (lastChangeStateDuration(#[xxx][Nut_C3][Present]#,1)<45) OU (#[xxx][Nut_C4][Present]# == 1 ET (lastChangeStateDuration(#[xxx][Nut_C4][Present]#,1)<45))) AND !time_between(#time#,0459,0503)

Le log :

[2019-01-25 17:36:00][SCENARIO] Lancement du scénario en mode synchrone

[2019-01-25 17:36:00][SCENARIO] Start : Scénario exécuté automatiquement sur événement venant de : [Ghislain][Nut_C4][Present].

[2019-01-25 17:36:00][SCENARIO] Exécution du sous-élément de type [condition] : if

[2019-01-25 17:36:00][SCENARIO] Evaluation de la condition : [37121 > 300 ET ("Absence" == "Absence" || (0 == 1 ET "Absence" != "Nuit" ) ) ET (0 == 1 ET (86607<45) OU (1 == 1 ET (87347<45))) AND !0] = Faux

[2019-01-25 17:36:00][SCENARIO] Non exécution des actions pour cause de répétition

[2019-01-25 17:36:00][SCENARIO] Fin correcte du scénario

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

[2019-01-25 17:36:46][SCENARIO] Lancement du scénario en mode synchrone

[2019-01-25 17:36:46][SCENARIO] Start : Scénario exécuté automatiquement sur événement venant de : [Ghislain][Nut_C4][Present].

[2019-01-25 17:36:46][SCENARIO] Exécution du sous-élément de type [condition] : if

[2019-01-25 17:36:46][SCENARIO] Evaluation de la condition : [37167 > 300 ET ("Absence" == "Absence" || (0 == 1 ET "Absence" != "Nuit" ) ) ET (0 == 1 ET (86653<45) OU (1 == 1 ET (87393<45))) AND !0] = Faux

[2019-01-25 17:36:46][SCENARIO] Non exécution des actions pour cause de répétition

[2019-01-25 17:36:46][SCENARIO] Fin correcte du scénario

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

[2019-01-25 17:37:02][SCENARIO] Lancement du scénario en mode synchrone

[2019-01-25 17:37:02][SCENARIO] Start : Scénario exécuté automatiquement sur événement venant de : [Ghislain][Nut_C4][Present].

[2019-01-25 17:37:02][SCENARIO] Exécution du sous-élément de type [condition] : if

[2019-01-25 17:37:02][SCENARIO] Evaluation de la condition : [37183 > 300 ET ("Absence" == "Absence" || (0 == 1 ET "Absence" != "Nuit" ) ) ET (0 == 1 ET (86669<45) OU (1 == 1 ET (62<45))) AND !0] = Faux

[2019-01-25 17:37:02][SCENARIO] Non exécution des actions pour cause de répétition

[2019-01-25 17:37:02][SCENARIO] Fin correcte du scénario

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

[2019-01-25 17:37:28][SCENARIO] Lancement du scénario en mode synchrone

[2019-01-25 17:37:29][SCENARIO] Start : Scénario exécuté automatiquement sur événement venant de : [Ghislain][Nut_C4][Present].

[2019-01-25 17:37:29][SCENARIO] Exécution du sous-élément de type [condition] : if

[2019-01-25 17:37:29][SCENARIO] Evaluation de la condition : [37210 >300 ET ("Absence" == "Absence" || (0 == 1 ET "Absence" != "Nuit" ) ) ET (0 == 1 ET (86696<45) OU (1 == 1 ET (89<45))) AND !0] = Faux

[2019-01-25 17:37:29][SCENARIO] Non exécution des actions pour cause de répétition

[2019-01-25 17:37:29][SCENARIO] Fin correcte du scénario

Cordialement…

Pour préciser un peu et confirmer, j’ai crée un virtuel que je passe à 1 ou 0 via une URL. (toujours répéter)
Dans le testeur d’expression j’exécute : lastChangeStateDuration(#[Aucun][test][on]#,1)
Il apparaît que le temps est mis à jour seulement au 2ème renvoi à 1 de la valeur et pas sur le premier d’où dans mon scénario avec le Nut un lancement provoqué mais une condition fausse sur lastChangeStateDuration

Si je le passe en jamais répéter alors la durée est bien décomptée depuis le premier changement.

Tu peux vérifier sur l’historique ?

Savoir si c’est un soucis de la fonction ou de répétition de valeur.
Merci

Sur l’historique la valeur se répète alors que c’est jamais répéter dans le virtuel

J’ai compris le pb, si on imagine un état haut, il lui faut 2 points pour calculer le changement, donc tant que le 2ème point n’est pas là ça ne marche pas sur « toujours répéter ».

J’ai fait un état à 1 à Seconde 55, je teste lastChange… il est toujours à la valeur avant le passage à 0, je refais un état 1 à S+35 environ, il me retourne 37 car il a pu calculer une durée entre le 1er passage à 1 et maintenant

Il y a qqch qui a changé entre la stable et la beta sur ce point.

A ma connaissance aucun changement sur ces fonctions depuis juillet 2018.

Sans doute lié: forum public sujet 33x problème similaire sur lastCommunication()

@Loic y’a du changement sur le moteur d’historisation ?

La je comprends pas, bon après moi et les fonctions qui joue avec des dates j’ai toujours galeré… Mais de mémoire non pas de changement.

Je vais redémarrer ma VM sur Jeedom Stable et faire le test à l’occasion.

La fonction a effectivement changée :

		public static function lastChangeStateDuration($_cmd_id, $_value) {
						$cmd = cmd::byId($_cmd_id);
						if (!is_object($cmd)) {
							throw new Exception(__('Commande introuvable : ', __FILE__) . $_cmd_id);
						}
						if ($cmd->getIsHistorized() != 1) {
							return -2;
						}
						$_value = str_replace(',', '.', $_value);
						$_value = trim($_value);
						$_decimal = strlen(substr(strrchr($_value, '.'), 1));
						$histories = array_reverse(history::all($_cmd_id));
						$c = count($histories);
						if ($c == 0) {
							return -1;
						}
						$currentValue = $histories[0]->getValue();
						if (is_numeric($_value)) {
							$currentValue = round($currentValue, $_decimal);
						}
						$dateTo = date('Y-m-d H:i:s');
						$duration = strtotime($dateTo) - strtotime($histories[0]->getDatetime());
						if ($_value === null) {
							$_value = $currentValue;
						}
						for ($i = 0; $i < $c - 1; $i++) {
							$history = $histories[$i];
							$value = $history->getValue();
							if (is_numeric($_value)) {
								$value = round($value, $_decimal);
							}
							$date = $history->getDatetime();
							//same state as current:
							if ($_value == $currentValue) {
								$nextValue = $histories[$i + 1]->getValue();
								if (is_numeric($_value)) {
									$nextValue = round($nextValue, $_decimal);
								}
								if ($_value != $nextValue && isset($histories[$i - 1])) {
									$duration += strtotime($histories[$i - 1]->getDatetime()) - strtotime($date);
									return $duration;
								}
							}
							//different state as current:
							if ($_value != $currentValue && $i > 0) {
								$nextValue = $histories[$i + 1]->getValue();
								if (is_numeric($_value)) {
									$nextValue = round($nextValue, $_decimal);
								}
								if ($_value == $value && $_value != $nextValue && isset($histories[$i - 1])) {
									$duration += strtotime($histories[$i - 1]->getDatetime()) - strtotime($date);
									return $duration;
								}
							}
							if ($i > 0) {
								$duration += strtotime($histories[$i - 1]->getDatetime()) - strtotime($date);
							}
						}
						return -1;
					}

Il faudrait donc me donner un systeme ou une methode pour que je puisse reproduire coup sur coup pour que je debug.

J’ai regardé rapidement

Effectivement sur la beta 3.3.10 la fonction est différente de mon 3.2.14. Cette dernière est bien celle que j’avais développée en juin 2018 pour résoudre les soucis à l’époque :

	public static function lastChangeStateDuration($_cmd_id, $_value) {
		$cmd = cmd::byId($_cmd_id);
		if (!is_object($cmd)) {
			throw new Exception(__('Commande introuvable : ', __FILE__) . $_cmd_id);
		}

		if ($cmd->getIsHistorized() != 1) {
			return -2;
		}

		$_value = str_replace(',', '.', $_value);
		$_decimal = strlen(substr(strrchr($_value, '.'), 1));
		$histories = array_reverse(history::all($_cmd_id));
		$c = count($histories);
		if ($c == 0) {
			return -1;
		}

		$currentValue = $histories[0]->getValue();
		$dateTo = date('Y-m-d H:i:s');
		$duration = strtotime($dateTo) - strtotime($histories[0]->getDatetime());
		if ($_value === null || $_value == $currentValue) {
			$_value = $histories[0]->getValue();
		}
		for ($i = 0; $i < $c - 1; $i++) {
			$history = $histories[$i];
			$value = $history->getValue();
			$value = round($value, $_decimal);
			$date = $history->getDatetime();
			//same state as current:
			if ($_value == $currentValue) {
				$nextValue = round($histories[$i + 1]->getValue(), $_decimal);
				if ($_value != $nextValue) {
					return $duration;
				}
			}
			//different state as current:
			if ($_value != $currentValue && $i > 0) {
				$prevValue = round($histories[$i - 1]->getValue(), $_decimal);
				$nextValue = round($histories[$i + 1]->getValue(), $_decimal);
				if ($_value == $value && $_value != $nextValue) {
					$duration += strtotime($histories[$i - 1]->getDatetime()) - strtotime($date);
					return $duration;
				}
			}
			if ($i > 0) {
				$duration += strtotime($histories[$i - 1]->getDatetime()) - strtotime($date);
			}

		}
		return -1;
	}

Pourquoi a t elle changé, aucune idée.

A l’époque j’avais refait:
lastStateDuration()
lastChangeStateDuration()
stateDuration()

@Loic je te détaille ce que j’avais écris un peu plus haut en début d’apm. Dans quel fichier se trouve cette fonction que je regarde les diff ?

Qu’est ce qui motive ces diff ?

https://github.com/jeedom/core/blob/master/core/class/history.class.php

Je ne sais pas pourquoi elles changé entre temps, donc remettre les mains dedans ou remettre les anciennes c’est délicat. Il faudrai savoir qui les a modifié depuis Juillet 2018

Github est notre ami :slight_smile:

@Loic les merge d’aujourd’hui (commit be4ff08) sur history.class ne change rien, pb tj là.

Solution pour tester :

Créer un virtuel info binaire, spécifier toujours répéter.

Changer son état de 0 vers 1 via l’URL => via les tester d’expression je teste lastChangeStateDuration(#[Information][test][on]#,1) il doit donner le temps entre le moment où on a envoyé l’URL et le temps ou lance l’expression.
Or tu pourras constater que le temps n’est renvoyé qu’après avoir renvoyé l’url avec l’état à 1 et que le décompte se fait alors entre le premier état 1 et maintenant.

A ma connaissance il n’y a jamais eu de soucis sur ces fonctions depuis qu’on les a refaite.
Je les utilise beaucoup moi même dans pas mal de scenarios …

Je n’en avais pas jusqu’au passage en BETA :slight_smile:

Je viens de peut être trouver le soucis (mais pas sur car il j’arrive pas a le reproduire coup sur coup), peux tu remettre a jour et retester ?

Ca marche :slight_smile: je vais éprouver ça un peu ce soir pour voir s’il n’y a pas de dommages collatéraux, mais en tout cas c’est décompté au premier passage à 1