Scenario s'exécute plusieurs fois

Je viens de tester ce code.

Lorsque je me connecte avec mon login, il me mets 3 utilisateurs connectés dans le log (et donc dans le mail aussi).

Curieux non?

------------------------------------
[2025-07-26 09:35:00][SCENARIO] -- Début : Scenario execute sur evenement : #user_connect#.
[2025-07-26 09:35:00][SCENARIO] - Exécution du sous-élément de type [condition] : if !variable(connected)
[2025-07-26 09:35:00][SCENARIO] Evaluation de la condition : [!""] = Vrai
[2025-07-26 09:35:00][SCENARIO] - Exécution du sous-élément de type [action] : then
[2025-07-26 09:35:00][SCENARIO] Exécution d'un bloc élément : 1059
[2025-07-26 09:35:00][SCENARIO] - Exécution du sous-élément de type [action] : code
[2025-07-26 09:35:00][SCENARIO] Exécution d'un bloc code
[2025-07-26 09:35:00][SCENARIO] Connexion de : drs enfant ipad1
[2025-07-26 09:35:00][SCENARIO] Exécution de la commande [supervision][mail 1and1][supervision] avec comme option(s) : {"background":"0","title":"Connexion \u00e0 l'interface JEEDOM","message":"drs enfant ipad1 "}
[2025-07-26 09:35:01][SCENARIO] Fin correcte du scénario

Tu as un problème quelque part ! on filtre les connexions de moins de 10 secondes donc bon… Soit erreur dans la recopie du code, soi Jeedom multiverse !

Eurekâ !
En fouillant dans le code du core j’ai trouvé un truc non documenté :face_with_monocle: et là je pense que ton problème est réglé.
Il « suffit » de faire :


NB : oui oui c’est bien un tag sans # de fin : #user_connected

1 « J'aime »

J’ai fait un copier-coller du code pourtant.

Donc comme ceci, sans le code?

Oui et pas dans une boucle Si, il n’y a plus de condition ! Juste un bloc action avec le sleep et le mailto.

Bonjour,

Tu aurais le lien vers ce code que j’y jette un oeil, car j’ai pas trouvé, et en testant, le tag ne semble pas être remplacé.

Sinon je propose un autre code, celui-ci est extrait (juste un peu transformé) du plugin plugin-discordlink qui propose cette option dans son code.

on gardera le déclencheur #user_connect#

Bloc code
$cron = 20; // secondes
///////////////////////////////////////////////////////////////////
$tags = $scenario->getTags(); // Récupération de la liste des tags
$tags['#connected#'] = ' '; // Initialisation du tag connected
$tags['#type#'] = ' '; // Initialisation du tag type
$tags['#time#'] = ' '; // Initialisation du tag time
$timeNow = date("Y-m-d H:i:s"); // Date/heure actuelle
$maxLine = log::getConfig('maxLineLog'); // Nbre de ligne max des log en config.
$logConnection = log::get('connection', 0, $maxLine); // Récupération du log connection
$logLevel = log::getLogLevel('connection');
$convertLogLevel = log::convertLogLevel($logLevel);
if ($logLevel > 200) {
  $scenario->setLog("Veuillez mettre le log 'connection' sur 'info' dans 'Configuration/Logs' (niveau actuel : ". $convertLogLevel .")");
} else if (is_array($logConnection)) {
  foreach ($logConnection as $value) {
    $valueTime = explode("]", $value);
    $valueTime = substr($valueTime[0], 1);
    if ((strtotime($timeNow) - strtotime($valueTime)) <= $cron) {
      $logConnectionList = explode(" : ", $value);
      $tags['#connected#'] = strtolower($logConnectionList[2]);
      $tags['#time#'] = $valueTime;
      if (strpos($logConnectionList[1], 'clef') !== false) $tags['#type#'] = 'clef';
      elseif (strpos($logConnectionList[1], 'API') !== false) $tags['#type#'] = 'api';
      elseif (strpos($logConnectionList[1], 'REMOTE_USER') !== false) $tags['#type#'] = 'REMOTE_USER';
      else $tags['#type#'] = 'navigateur';
      break;
    }
  }
}
$scenario->setTags($tags);

Info :
la condition permet de faire l’action que si le code a bien trouvé un nouvel user connecté, il faut donc ajouter tes action (envoi de mail) dans ce même bloc.

Ce code ne gère pas le cas ou plusieurs utilisateurs se connecteraient dans les même 20 secondes, il en sortira seulement le dernier utilisateur.

Ouhla ce serait trop long à expliquer, j’y ai passé un moment ! Mais en gros j’ai vu des pistes dans le user.class bien sûr avec le user_connect

jeedom::event('user_connect');
log::add('event', 'info', __('Local account found for', __FILE__) . ' ' . $_login);

l’objet user dans le user.ajax,
dans le utils.class avec le _ de

$name = $property->getName();
if ('_' !== $name[0]) {

et surtout le jeedom.ajax avec le retour d’un ‹ connected › qui m’a intrigué

if (!isConnect()) {
  $return['connected'] = false;
  ajax::success($return);
}
$return['user_id'] = $_SESSION['user']->getId();

Tout ça a fait une soupe et jai testé plusieurs choses…

Après le code de discordlink fait un parsing du log de connexion, why not c’est assez efficace en théorie mais c’est lourd beaucoup de code pour un petit truc.

Je peut le condensé pour n’en sortir que 14 lignes :crazy_face:, mais plus possibilité de savoir si c’est une connection API, navigateur…

Sinon pour ton code pour qu’il fonctionne correctement, il faut juste ajouter un défaut

$d = new DateTime($user->getOptions('lastConnection'));

$d = new DateTime($user->getOptions('lastConnection', '1970-01-01 00:00:00'));

Car si un user ne c’est jamais connecté, lastConnection renvoi rien et donc tous les calculs de DateTime renvois 0, donc < au 10 secondes

dans ce log je suppose que « drs » est bien celui qui a trigger le scénario, mais « enfant » et « ipad » sont des users qui ne ce sont encore jamais connecté. Facilement identifiable en allant dans
Réglages / Sytème / Utilisateurs puis dans le tableau Liste des utilisateurs colonne Dernière connexion

Alors je dois pas être doué, car ça ne fonctionne pas comme attendu. J’ai construit le scenario comme ceci:

Je me connecte avec drs, et voici le résultat:

------------------------------------
[2025-07-26 16:48:36][SCENARIO] -- Début : Scenario execute sur evenement : #user_connect#.
[2025-07-26 16:48:36][SCENARIO] - Exécution du sous-élément de type [action] : action
[2025-07-26 16:48:36][SCENARIO] Pause de 5 seconde(s)
[2025-07-26 16:48:41][SCENARIO] - Exécution du sous-élément de type [action] : code
[2025-07-26 16:48:41][SCENARIO] Exécution d'un bloc code
[2025-07-26 16:48:41][SCENARIO] Veuillez mettre le log 'connection' sur 'info' dans 'Configuration/Logs' (niveau actuel : error)
[2025-07-26 16:48:42][SCENARIO] - Exécution du sous-élément de type [condition] : if tag(connected) != " "
[2025-07-26 16:48:42][SCENARIO] Evaluation de la condition : [" " != " "] = Faux
[2025-07-26 16:48:42][SCENARIO] - Exécution du sous-élément de type [action] : else
[2025-07-26 16:48:42][SCENARIO] Fin correcte du scénario

Tu as tout à fait raison. Jamais connectés.

Tu as l’info dans le log :wink:

Sinon le code de @Pax24 fait aussi l’affaire, le voici avec la correction :

$utilisateurs = '';
$now = new DateTime();
$users = user::all();
foreach ($users as $user) {
	$d = new DateTime($user->getOptions('lastConnection', '1970-01-01 00:00:00'));
	$diff = $now->diff($d);
 	$seconds = ($diff->days * 86400) + ($diff->h * 3600) + ($diff->i * 60) + $diff->s;
	if ($seconds < 10 && $user->getLogin() != 'internal_report') $utilisateurs .= $user->getLogin().' ';
}
$tag['connected']=$utilisateurs;
$scenario->setTags($tag);
$scenario->setLog('Connexion de : ' . $utilisateurs);
1 « J'aime »

C’est pire que tout! C’est pas que je suis pas doué, c’est juste que je ne sais pas lire :rofl:

Effectivement, ça à l’air de fonctionner bien. Ci dessous les logs de deux connexions avec deux users différents:

------------------------------------
[2025-07-26 17:06:18][SCENARIO] -- Début : Scenario execute sur evenement : #user_connect#.
[2025-07-26 17:06:18][SCENARIO] - Exécution du sous-élément de type [action] : action
[2025-07-26 17:06:18][SCENARIO] Pause de 5 seconde(s)
[2025-07-26 17:06:23][SCENARIO] - Exécution du sous-élément de type [action] : code
[2025-07-26 17:06:23][SCENARIO] Exécution d'un bloc code
[2025-07-26 17:06:23][SCENARIO] Connexion de : drs
[2025-07-26 17:06:23][SCENARIO] - Exécution du sous-élément de type [condition] : if tag(connected) != " "
[2025-07-26 17:06:23][SCENARIO] Evaluation de la condition : ["drs " != " "] = Vrai
[2025-07-26 17:06:23][SCENARIO] - Exécution du sous-élément de type [action] : then
[2025-07-26 17:06:23][SCENARIO]    Log : drs  -  -
[2025-07-26 17:06:23][SCENARIO] Fin correcte du scénario
------------------------------------
[2025-07-26 17:07:13][SCENARIO] -- Début : Scenario execute sur evenement : #user_connect#.
[2025-07-26 17:07:13][SCENARIO] - Exécution du sous-élément de type [action] : action
[2025-07-26 17:07:13][SCENARIO] Pause de 5 seconde(s)
[2025-07-26 17:07:18][SCENARIO] - Exécution du sous-élément de type [action] : code
[2025-07-26 17:07:18][SCENARIO] Exécution d'un bloc code
[2025-07-26 17:07:18][SCENARIO] Connexion de : admin
[2025-07-26 17:07:18][SCENARIO] - Exécution du sous-élément de type [condition] : if tag(connected) != " "
[2025-07-26 17:07:18][SCENARIO] Evaluation de la condition : ["admin " != " "] = Vrai
[2025-07-26 17:07:18][SCENARIO] - Exécution du sous-élément de type [action] : then
[2025-07-26 17:07:18][SCENARIO]    Log : admin  -  -
[2025-07-26 17:07:18][SCENARIO] Fin correcte du scénario

Un grand merci à vous 2. La grande question est maintenant: à qui je mets la solution?

il y a un soucis avec les tags, tu as utilisé mon code ?

Si tu utilise le code de Pax24 attend qu’il modifie simplement son post, et tu le met en solution.

1 « J'aime »

J’avais laissé le tag type dedans.
En le retirant, je n’ai plus que le nom du user connecté

Ok donc tu utilise le code de Pax24 ?

Si oui, attend son intervention sur son Post pour lui attribuer la solution.

Ah oui en fait. Avec tout ça, je ne savais plus où j’en étais (mais j’ai quand même gardé le tien pour un usage futur :slight_smile: )

Ah oui mais ça fausse les choses ça ! lol :sweat_smile:
Je ne comprends pas pourquoi le code simple avec juste #user_connected ne marcherait pas chez toi (aucune idée du résultat avec des users jamais connectés).

J’ai ajouté le défaut date pour ton cas de users jamais connectés.

Je ne voit toujours pas ou ce tag est censé être remplacé dans le core.

Je vais proposer un PR sur le core pour que user_connect soit aussi bien un déclencheur qu’un tag contenant le login.

Edit : PR fait, pas grand chose a modifier :wink:, j’ai préféré le tag #trigger_value#, qui est déja un nom de tag existant dans le core.

Question nomenclature (mais en fait c’est important ici vu comment part la discussion), #user_connect# ici n’est pas un tag mais un événement (oui c’est le même format mais ce n’est pas du tout la même chose);
Il n’a donc pas de valeur (et il n’y a donc rien à « remplacer »);
n’importe qui ou n’importe quoi (je le fais dans certain plugin) peut « lancer » un événement qui pourra ensuite servir de déclencheur (par exemple): jeedom::event('my_event');

#start# est un autre exemple d’événement

3 « J'aime »

Ah mais j’avais bien saisi la différence, c’est comme cela que je l’ai proposé dans la PR :

Lors d’un déclenchement d’un scénario via le déclencheur spécifique #user_connect# le tag #trigger_value# contiendra le nom de l’utilisateur venant de se connecter.

Mais il fait pas de mal de le rappeler hein :wink:

1 « J'aime »