Détecter coupure et arrêt de l'alimentation électrique via Lixee.Zlinky

Merci à toi Phpvarious.
J’ai mis en place ton scenario.
Dans ton code, est-ce l’expression is_object($eqlogic)) qui permet de savoir si l’objet est toujours joignable ?
J’ai modifié un peu le code pour m’y retrouver avec tous ces timeout, n’étant pas familier avec ce langage.
Timeout_de_.$eqLogicId = la variable qui est définie dans Jeedom par ce scenario pour cet équipement (exemple ligne 6)
#timeout# = tag = « variable » dont la portée est uniquement dans le scenario (ligne 4)
timeout = valeur du timeout défini dans l’équipement (ligne 7)

$eqLogicId = 1509; // id de l'équipement a surveiller

$eqLogic = eqLogic::byId($eqLogicId);
$tags['#timeout#'] = -1;
if (is_object($eqLogic)){
  $varStatus = $scenario->getData('Timeout_de_'.$eqLogicId,0);
  $prevStatus = $eqLogic->getStatus('timeout', 0);
  if ($prevStatus == 1 && $varStatus == 0) {
    $tags['#timeout#'] = 1;
    $scenario->setData('Timeout_de_'.$eqLogicId, 1);
  }
  else if ($prevStatus == 0 && $varStatus == 1) 
  {
    $tags['#timeout#'] = 0;
    $scenario->setData('Timeout_de_'.$eqLogicId, 0);
  }
}
$scenario->setTags($tags);

Afin de mieux comprendre et suivre l’évolution des variables, comment fait-on pour forcer l’écriture du nom et du contenu des variables dans le log du scenario ?

$scenario->setLog("Status: $varStatus Précédent: $prevStatus");

Merci jpty.

$eqLogicId = 1509; // id de l'équipement a surveiller

$eqLogic = eqLogic::byId($eqLogicId);
$tags['#timeout#'] = -1;
//$Nom =  $eqLogic->getHumanName();
$Nom =  $eqLogic->getName();
$scenario->setLog("Equipement : $eqLogicId - $Nom");
if (is_object($eqLogic)){
  $varStatus = $scenario->getData('Timeout_de_'.$eqLogicId,0);
  $prevStatus = $eqLogic->getStatus('timeout', 0);
  $scenario->setLog("Status: $varStatus Précédent: $prevStatus");
  if ($prevStatus == 1 && $varStatus == 0) {
    $tags['#timeout#'] = 1;
    $scenario->setData('Timeout_de_'.$eqLogicId, 1);
  }
  else if ($prevStatus == 0 && $varStatus == 1) 
  {
    $tags['#timeout#'] = 0;
    $scenario->setData('Timeout_de_'.$eqLogicId, 0);
  }
}
$scenario->setTags($tags);

Question basique : on doit obligatoirement mettre dans une variable le résultat d’une commande pour l’afficher dans le log comme j’ai fait avec $Nom ? Il n’y a pas moyen de faire le setlog suivi de la bonne syntaxe pour écrire le getName() sans devoir créer une variable ?

Et n’y aurait-il pas une inversion des noms de variables ?
$varStatus = $scenario->getData(‹ Timeout_de_ ›.$eqLogicId,0); → C’est bien la variable qui est écrite dans Jeedom à la fin du script ? Si oui, c’est donc elle la précédente, non ?
$prevStatus = $eqLogic->getStatus(‹ timeout ›, 0); → valeur du timeout à l’instant t = status ?

J’ai trouvé une version serveur de NUT pour Windows, mais c’est très peu documenté pour arriver à la mettre en place proprement.
Serveur NUT sous Windows
C’est en allemand, j’essaye de comprendre mais je ne le pratique pas. Je suis arrivé à démarrer le service sous Windows mais pour l’instant rien de plus, je ne sais comment accéder aux infos déjà sous Windows… Alors, à distance via un plugin Nut ou Nut_Free…

Hello, je remet le même style de scénario, mais celui-ci un peu plus parlant dans les commentaires et les log en espérant que sa puisse t’aider dans la compréhension de celui-ci :

Bloc code
$eqLogicId = 25; // id de l'équipement a surveiller

$scenario->setLog('┌─────────────────── [ DEBUT BLOC CODE ] ───────────────────'); // log scénario
$eqLogic = eqLogic::byId($eqLogicId); // appel de la class eqLogic
$tags['#timeout#'] = -1; // on initie le tag a -1
if (is_object($eqLogic)){ // on verifie si l'eqLogic existe bien
  $scenario->setLog('| Verification de Timeout pour l\'équipement : '.$eqLogic->getHumanName().' (id = '.$eqLogic->getId().')'); // log scénario
  $varStatus = $scenario->getData('timeout'.$eqLogicId,0); // on récupère la variable Jeedom (si elle existe pas, on l'initie a 0)
  $eqStatus = $eqLogic->getStatus('timeout', 0); // on récupère l'état du timeout de l'équipement (empty ou 0 = ok, 1 = en timeout)
  
  if ($eqStatus == 1 && $varStatus == 0) { // Si l'équipement est en timeout et que la variable Jeedom n'est pas en timeout.
    ///////////////////////// ACTION EQUIPEMENT EN TIMEOUT ////////////////////
    $scenario->setLog('| Attention l\'équipement est en timeout ('.$eqStatus.')'); // log scénario
    // ici on aurait très bien pu exécuter une autre action (message, action sur une commande ...)
    $tags['#timeout#'] = 1; // on modifie le tag (pour la sortie) à 1.
    $scenario->setData('timeout'.$eqLogicId, 1); // on l'inscrit dans la variable Jeedom pour ne pas répéter lors du prochain lancement du scénario. 
  }
  else if ($eqStatus == 0 && $varStatus == 1) // Si l'équipement n'est pas en timeout et que la variable Jeedom est en timeout.
  {
    ///////////////////////// ACTION EQUIPEMENT SORTI DE TIMEOUT ////////////////////
    $scenario->setLog('| l\'équipement N\'est plus en timeout ('.$eqStatus.')'); // log scénario
    // ici on aurait très bien pu executer une autre action (message, action sur une commande ...)
    $tags['#timeout#'] = 0; // on modifie le tag (pour la sortie) à 1.
    $scenario->setData('timeout'.$eqLogicId, 0); // on l'inscrit dans la variable Jeedom pour ne pas répéter lors du prochain lancement du scénario. 
  }
  else
  {
    ////// ici on aurait pu ne rien faire, je l'ai rajouter, juste pour pouvoir écrire quelque chose dans le log du scénario
    if ($eqStatus == 1) {
      $scenario->setLog('| L\'équipement est en timeout ('.$eqStatus.') mais il a déja été notifié lors d\'un précédent lancement du scénario.'); // log scénario
    }
    else
    {
      $scenario->setLog('| L\'équipement n\'est pas en timeout ('.$eqStatus.') mais il a déja été notifié lors d\'un précédent lancement du scénario.'); // log scénario
    }
  }
}
else
{
  $scenario->setLog('| Attention il semble que l\'équipement portant l\'id '.$eqLogicId.' n\'existe pas !!!'); // log scénario
}
$scenario->setLog('└─────────────────── [ FIN BLOC CODE ]  ───────────────────');
$scenario->setTags($tags); // on enregistre les tag, pour pouvoir l'utiliser hors bloc code, comme ci-dessous.

Bonjour à tous,

Je m’incruste par ici, car j’ai aussi ce cas d’usage, mais je le gère différemment.

En effet, je trouve que les onduleurs ne sont pas forcément fiable pour remonter une perte et un retour du courant, car les valeurs remontées ne sont pas mis à jour fréquemment par le plugin nut et souvent trop tard à mon goût.

Donc, je me base sur la connectivité de 4 équipements sur des circuits électriques complètement différents et non ondulés, 2 en filaire et 2 en wifi.
Alors oui, les équipements en question sont en MQTT et remontent donc leur état de connectivité à travers le LWT (Last Will and Testament) sur 2 brokers, ça pourrait aussi être un simple ping sur leurs IP, mais le LWT est bien plus rapide à remonter.

Dans un virtuel, j’ai une commande info binaire « État secteur » où je fais un OU entre l’etat des 4 équipements : s’ils sont tous offline, je considère que le courant est coupé, si un est online, il y a du courant. A ça j’ai ajouté une commande info binaire « Maintenance », pour gérer le cas où je ne veux pas que la domotique détecte une coupure, il est dans le même OU. Je n’ai pas fait de commande info binaire « Simulation Coupure » qui aurait l’effet inverse, mais on peut aussi imaginer ça.

Ne reste plus qu’à faire un scénario sur changement de l’info « État secteur » et d’y mettre les actions sur perte et retour.

My 2 cents,
Bad

1 « J'aime »

Merci encore à toi pour la peine que tu t’es donnée à documenter ton code.
En début d’après-midi, j’ai eu avec l’« ancien code » 2 faux positifs. Il faut que je regarde ce que ça donne sur la durée, le script est relancé toutes les 5 minutes.

Merci @Bad pour ce retour , effectivement un simple virtuel pourrait suffire. :wink:.

@JC38

Faux positif ! j’ai un doute car le scénario se charge juste de récupérer l’info existante getStatus('timeout') et de faire une comparaison avec la variable jeedom, si tu as eu un message du scénario c’est que celle-ci a bien changé d’état.
Attention a bien adapter la valeur « Alertes Communications » dans la configuration de ton équipement, ne pas mettre une valeur trop basse.
Se qui semble étonnant c’est que tu applique le scenario sur l’équipement Zlinky, je suppose que tu as au moins une communication par minutes :thinking:.

Bonjour, Le plugin NUT se rafraîchit toutes les 15 minutes ce qui n’est pas gérable.
Par contre, lors d’une coupure ou au retour du courant, l’onduleur (NUT plus précisément) fait appel à une API de Jeedom et c’est instantané. C’est la solution la plus simple et fiable que j’ai trouvé.

L’alerte comm sur le Zlinky est réglée à 1 minute et le scenario tourne toutes les 5. Dommage, depuis j’ai effacé le centre du contenu des messages.
Ce soir, je viens de passer 1 update du plugin zigbee, j’ai vu que ça générait une alerte vis à vis du Zlinky, ce qui est normal si le daemon zigbee est ko. Par contre, côté dernier démarrage, il était horodaté à ce matin, donc les faux positifs de ce début d’après-midi n’étaient pas consécutifs à un arrêt/redémarrage du daemon sur cette période.

ce qu’il faut vérifier, c’est si le Zlinky communique bien dans ces 1 min, car sinon jeedom le passe en timeout.
Pour info jeedom utilise un Cron5 pour vérifier le last communication et ainsi passer l’équipement en timeout.
Ex: dernier com a 21:17 avec « alerte timeout » a 1min :
a 21:18, l’équipement ne sera pas encore en timeout (21h17 - 1min <= 21h17)
a 21h19, l’équipement ne sera pas encore en timeout, malgré que les 1mn soit dépassé, car la fonction du core (checkAlive()) qui fait ce contrôle ne s’est pas encore lancée
a 21h20 le cron5 s’exécute et part la même occasion lance la fonction checkAlive(), celle-ci vérifiera le lastcom en fonction de « alerte timeout » et mettra le timeout a 1.

Edit :
Attention il se peut que tu es le même soucis, je sais pas si sa joue sur le lastcommunication :

Bonjour,
Il y a des onduleurs qui peuvent envoyer une commande API ?
Ils sont donc sur le reseau ethernet !
Une marque / modèle à soumettre ?

N’importe quel onduleur avec un port USB, raccordé à un PI Zero ou PI3 et le logiciel NUT fourni de base dans la distribution.
Une ligne dans un fichier de configuration et tu déclenche un scenario à la coupure de courant et au retour.

Attention aux confusions sur les lastcommunication, comme je l’ai écrit au début du post, Jeedom nomme de manière identique (Dernière communication) 2 champs d’horodatages différents.
https://community.jeedom.com/t/info-dernieres-communication/70981/13

D’où le plugin https://market.jeedom.com/index.php?v=d&p=market_display&id=4207

Sa change rien au comportement, a partir du moment ou une commande est mise à jour le lastCommunication et le timeout de l’équipement sont normalement MàJ aussi.

le champs disponible dans le « reseaux zigbee » est une autre méthode qui consiste a questionner directement le controleur sur la dernière fois ou il a vu l’équipement.


cette info semble être disponible exclusivement dans le log (error) et avec un CRON15 ou alors en visu sur la page « reseaux zigbee »

Bonsoir,
Pour info, ce soir le scenario a remonté cela :


Sans qu’il y ait de coupure.
Dans le log du contrôleur, filtré sur le Zlinky, j’ai ça :

	Ligne 1882: [2022-06-28 21:45:03][INFO] : [00:15:8d:00:05:d2:85:70][zdevices.serialize] Serialize device with attributes : 1
	Ligne 1979: [2022-06-28 21:46:37][INFO] : [00:15:8d:00:05:d2:85:70][listener.cluster_command] Cluster: <zigpy.zcl.clusters.general.Ota object at 0x7f6c6e0b7438> ClusterId: 0x0019 tsn: 151 args: (1, query_next_image(field_control=<FieldControl.0: 0>, manufacturer_code=4151, image_type=1, current_file_version=5))
	Ligne 1980: [2022-06-28 21:46:37][INFO] : [00:15:8d:00:05:d2:85:70][listener.cluster_command] Use specific decode funtion of cluster id 25
	Ligne 1981: [2022-06-28 21:46:37][INFO] : [00:15:8d:00:05:d2:85:70][chanels.general.Ota.cluster_command] Received command query_next_image
	Ligne 2156: [2022-06-28 21:51:14][INFO] : [00:15:8d:00:05:d2:85:70][listener.cluster_command] Cluster: <zigpy.zcl.clusters.general.Ota object at 0x7f6c6e0b7438> ClusterId: 0x0019 tsn: 12 args: (1, query_next_image(field_control=<FieldControl.0: 0>, manufacturer_code=4151, image_type=1, current_file_version=5))
	Ligne 2157: [2022-06-28 21:51:14][INFO] : [00:15:8d:00:05:d2:85:70][listener.cluster_command] Use specific decode funtion of cluster id 25
	Ligne 2158: [2022-06-28 21:51:14][INFO] : [00:15:8d:00:05:d2:85:70][chanels.general.Ota.cluster_command] Received command query_next_image
	Ligne 2406: [2022-06-28 21:55:29][INFO] : [00:15:8d:00:05:d2:85:70][listener.cluster_command] Cluster: <zigpy.zcl.clusters.general.Ota object at 0x7f6c6e0b7438> ClusterId: 0x0019 tsn: 107 args: (1, query_next_image(field_control=<FieldControl.0: 0>, manufacturer_code=4151, image_type=1, current_file_version=5))
	Ligne 2407: [2022-06-28 21:55:29][INFO] : [00:15:8d:00:05:d2:85:70][listener.cluster_command] Use specific decode funtion of cluster id 25

Le Zlinky a donc arrêté de causer pendant un peu plus de 4 min (lignes 2158 à 2406).
Dans le centre de messages, j’ai eu une alerte du core qui a disparu quand le timeout a cessé.
Le timeout du Zlinky est réglé à 2 min, et le scenario tourne toutes les 5 min.
Voici le log du scenario sur la période

[2022-06-27 21:50:01][SCENARIO] Start : Scenario execute automatiquement sur programmation.
[2022-06-27 21:50:01][SCENARIO] Exécution du sous-élément de type [action] : code
[2022-06-27 21:50:01][SCENARIO] Exécution d'un bloc code
[2022-06-27 21:50:01][SCENARIO] ┌─────────────────── [ DEBUT BLOC CODE ] ───────────────────
[2022-06-27 21:50:01][SCENARIO] | Verification de Timeout pour l'équipement : [Maison][LiXee.ZLinky] (id = 1509)
[2022-06-27 21:50:01][SCENARIO] | L'équipement n'est pas en timeout (0) mais il a déja été notifié lors d'un précédent lancement du scénario.
[2022-06-27 21:50:01][SCENARIO] └─────────────────── [ FIN BLOC CODE ]  ───────────────────
[2022-06-27 21:50:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=0
[2022-06-27 21:50:01][SCENARIO] Evaluation de la condition : [-1=0] = Faux
[2022-06-27 21:50:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 21:50:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=1
[2022-06-27 21:50:01][SCENARIO] Evaluation de la condition : [-1=1] = Faux
[2022-06-27 21:50:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 21:50:01][SCENARIO] Fin correcte du scénario
------------------------------------
[2022-06-27 21:55:01][SCENARIO] Start : Scenario execute automatiquement sur programmation.
[2022-06-27 21:55:01][SCENARIO] Exécution du sous-élément de type [action] : code
[2022-06-27 21:55:01][SCENARIO] Exécution d'un bloc code
[2022-06-27 21:55:01][SCENARIO] ┌─────────────────── [ DEBUT BLOC CODE ] ───────────────────
[2022-06-27 21:55:01][SCENARIO] | Verification de Timeout pour l'équipement : [Maison][LiXee.ZLinky] (id = 1509)
[2022-06-27 21:55:01][SCENARIO] | L'équipement n'est pas en timeout (0) mais il a déja été notifié lors d'un précédent lancement du scénario.
[2022-06-27 21:55:01][SCENARIO] └─────────────────── [ FIN BLOC CODE ]  ───────────────────
[2022-06-27 21:55:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=0
[2022-06-27 21:55:01][SCENARIO] Evaluation de la condition : [-1=0] = Faux
[2022-06-27 21:55:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 21:55:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=1
[2022-06-27 21:55:01][SCENARIO] Evaluation de la condition : [-1=1] = Faux
[2022-06-27 21:55:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 21:55:01][SCENARIO] Fin correcte du scénario
------------------------------------
[2022-06-27 22:00:01][SCENARIO] Start : Scenario execute automatiquement sur programmation.
[2022-06-27 22:00:01][SCENARIO] Exécution du sous-élément de type [action] : code
[2022-06-27 22:00:01][SCENARIO] Exécution d'un bloc code
[2022-06-27 22:00:01][SCENARIO] ┌─────────────────── [ DEBUT BLOC CODE ] ───────────────────
[2022-06-27 22:00:01][SCENARIO] | Verification de Timeout pour l'équipement : [Maison][LiXee.ZLinky] (id = 1509)
[2022-06-27 22:00:01][SCENARIO] | L'équipement n'est pas en timeout (0) mais il a déja été notifié lors d'un précédent lancement du scénario.
[2022-06-27 22:00:01][SCENARIO] └─────────────────── [ FIN BLOC CODE ]  ───────────────────
[2022-06-27 22:00:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=0
[2022-06-27 22:00:01][SCENARIO] Evaluation de la condition : [-1=0] = Faux
[2022-06-27 22:00:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 22:00:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=1
[2022-06-27 22:00:01][SCENARIO] Evaluation de la condition : [-1=1] = Faux
[2022-06-27 22:00:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 22:00:01][SCENARIO] Fin correcte du scénario
------------------------------------
[2022-06-27 22:05:01][SCENARIO] Start : Scenario execute automatiquement sur programmation.
[2022-06-27 22:05:01][SCENARIO] Exécution du sous-élément de type [action] : code
[2022-06-27 22:05:01][SCENARIO] Exécution d'un bloc code
[2022-06-27 22:05:01][SCENARIO] ┌─────────────────── [ DEBUT BLOC CODE ] ───────────────────
[2022-06-27 22:05:01][SCENARIO] | Verification de Timeout pour l'équipement : [Maison][LiXee.ZLinky] (id = 1509)
[2022-06-27 22:05:01][SCENARIO] | L'équipement n'est pas en timeout (0) mais il a déja été notifié lors d'un précédent lancement du scénario.
[2022-06-27 22:05:01][SCENARIO] └─────────────────── [ FIN BLOC CODE ]  ───────────────────
[2022-06-27 22:05:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=0
[2022-06-27 22:05:01][SCENARIO] Evaluation de la condition : [-1=0] = Faux
[2022-06-27 22:05:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 22:05:01][SCENARIO] Exécution du sous-élément de type [condition] : if tag(timeout,-1)=1
[2022-06-27 22:05:01][SCENARIO] Evaluation de la condition : [-1=1] = Faux
[2022-06-27 22:05:01][SCENARIO] Exécution du sous-élément de type [action] : else
[2022-06-27 22:05:01][SCENARIO] Fin correcte du scénario

Et le scenario

Faut donc trouver aussi le bon réglage du timeout pour pouvoir conclure si perte EDF ou pas de discussion entre Zlinky et le contrôleur.

Hello.

comme j’ai dis, si « alerte timeout » est trop bas, tu aura un équipement en timeout mais cela ne veut pas dire que tu as perdu le secteur !

Edit : Je pense que la solution de @Bad est plus viable, car elle s’appuie sur 2 protocoles différent et plusieurs équipements.
On est jamais a l’abris d’un protocole qui tombe (demon hs, équipement out …) et dans ce cas le last communication ne sera pas mis a jour.

1 « J'aime »

Oui, il faut trouver le bon réglage pour le timeout pour éviter des fausses alertes. Je vais attendre encore et je l’augmenterai progressivement. Je veux voir à quelle fréquence ces « fausses alertes » arrivent avec les valeurs en cours.
Je vais regarder la solution de Bad, en //, j’avais travaillé sur une solution de surveillance de l’onduleur. J’ai galéré mais je suis arrivé à mettre NUT sur mon serveur Windows et à configurer la connexion avec le plugin NUT_Free. Maintenant, faut que je trouve comme ce plugin gère l’évènement de coupure du secteur sur l’onduleur pour pouvoir le monitorer et l’exploiter dans un scenario.

J’ai fait un 1er test de on/off de l’alimentation de mon onduleur devant mon serveur Windows. L’info est remontée relativement rapidement dans Jeedom.
J’ai trouvé un autre onduleur avec une prise USB, je vais le mettre devant mon seveur Jeedom cette fois et créer un équipement de plus dans Nut_Free.
Si tout ok, un scenario qui teste si les 2 onduleurs sont ou ne sont plus sur secteur devrait permettre de trouver l’état de l’alim générale sans trop de risque.
Merci à tous et à Phpvarious dont j’ai adopté le scenario

Ce sujet a été automatiquement fermé après 24 heures suivant le dernier commentaire. Aucune réponse n’est permise dorénavant.