Tuto : Monitorer son infra domotique (serveur / batterie / last communication) sur JeedomConnect

Un autre petit tutoriel (certains diraient sans doute qu’il est trop loooooong :upside_down_face:)

  • Version n°2 du 29/04/2022 pour mise à jour de quelques captures en 2.4 (demande de @mld.sebastien et modification du bloc code pour permettre de choisir si on ne veux vérifier que les batteries, que les last communications ou les 2 (demande de @Margab)
  • Version n°3 du 30/04/2022 qui integre le fait que les modeles de device ne sont pas sur le même libellé de configuration en fonction des plugins *
  • Version n°4 du 27/04/2023 : refonte du scenario, l’ensemble des paramètres sont passés par des TAG, plus besoin de modifier le bloc code, et refonte des logs, notamment pour que les last com soient plus lisibles (<1 min, x min, x h, x j). le scenario est livré sous forme de Template de scenario

Introduction
Il vous expliquera comment monitorer son infrastructure domotique :
éléments monitorés :

  • niveaux de batterie (je n’utilise pas les infos jeedom car elles sont sur certains équipements erronées)
  • dernières communications
  • mise à jour des systeme + diverses opérations sur les systèmes (arrêts/redémarrages de services si disponible)

Il gère l’envoi d’une notif (paramétrable) 1 fois par jour pour alerter sur des pbs de batteries ou d’équipements qui ne communiquent plus

Ce tuto ne réinvente pas la roue, il utilise des plugins déjà existants et vise juste à donner quelques idées (comme pour chacun des tutos de tout ce qu’on peut faire avec plugin-jeedomconnect , mais ca peut sans doute être fait avec d’autres plugins qui ont tout à fait le droit de s’en inspirer :upside_down_face:)

Voilà le résultat finale pour vous donner quelques idée de présentation sous plugin-jeedomconnect

Vous aurez besoin des plugins Jeedom suivants


Pour la partie monitoring des serveurs

1 - il convient de monitorer ces serveurs via plugin-monitoring. je ne détaille pas ce point :slightly_smiling_face:
Quelques modifs à faire sur les paramétrages par défaut. il faut historiser les commandes ci-dessous pour pouvoir générer des graphiques. par défaut, elles ne le sont pas toutes.

Charge système 15 min
Espace disque Utilisé (pourcentage)
Mémoire libre (pourcentage)
Température CPU

Vous pouvez bien sur intégrer d’autres valeurs mais celles-là me semblent les plus importantes

2 - création des commandes de gestion du serveur (je présume que toutes sont sur debian (à adapter donc pour d’autres distributions)
Par défaut, pour chacun de mes serveurs, je crée un certain nombre de commandes pour quelques actions basiques. ces commandes sont créées dans sshcommander (1 équipement / serveur )

2.1 - commande de recherche de mises à jours disponibles (NB_Update) :

Commande action avec retour, le retour est au format numérique :
LANG=C apt-get upgrade -s | grep -P '^\d+ upgraded'| cut -d" " -f1

Rappel : la commande info de retour est créée AUTOMATIQUEMENT au premier lancement de la commande.

2.2 - commande de listing des mises à jour (sera utiliser dans un scenario pour lister les maj si le nb de MAJ est >= 1)
Cette commande est très utile pour savoir si je lance ou pas une MAJ de mon debian à distance (si il y a beaucoup de maj ou si la MAJ touche le NOYAU, JE NE LANCERAI PAS LA MAJ à DISTANCE

Commande action avec retour, le retour est au format defaut:
LANG=CC apt list --upgradable -qq 2>/dev/null | cut -d"/" -f1 | sed 's/$/<br>/'

2.3 - commande de reboot de mon serveur (reboot)

Commande action SANS retour:
sudo reboot

ps : Il y a aussi possibilité de gérer le reboot via l’équipement créé avec le plugin-monitoring

2.4 - commande de mise à jour du serveur

Commande action SANS retour:
sudo apt-get update -qq ; sudo apt-get upgrade -y -qq

En actions post-exécution de cette commande (accessible via le bouton config encadré en rouge au dessus puis configuration), je renseigne la commande de recherche du nb de MAJ et de listing des MAJ afin de remettre à jour les valeurs après la MAJ :

Vous pouvez ici créer d’autres commandes en fonction de votre serveur/service à gérer

reproduisez ceci pour tout vos serveurs

3 - Création du scenario de gestion :
C’ets un scenario assez simple, planifié à 6h et 18h et qui m’envoie une notif jeedom Connect (à créer donc si vous souhaitez la personnaliser avec une image).
Je ne le detaillerai pas plus que ca, il lance une detection des MAJ, si le nb de maj est > à 0 il liste les MAJ et envoie une notif avec en parametre le widgetId de l’equipement concerné et le nb de mises à jour

4 - Création des widgets Jeedom :
4.1 - creation des widgets de type historique pour avoir des graphs de monitoring. pour ma part, j’ai créé :
image
avec les commandes info suivantes (cf celle historisées plus haut) ;

Charge système 15 min
Espace disque Utilisé (pourcentage)
Mémoire libre (pourcentage)
Température CPU

rien de sorcier, un exemple de paramétrage. vous pouvez dupliquer une commande pour créer les autres :

4.2 - création d’un widget de type générique texte avec comme commande info la commande sshcommander de listing des MAJ (cf 2.2). ce widget nous affichera la liste des mise à jour dispo si il y en a

4.3 - création du widget global de monitoring de mon serveur.
C’est un widget action qui possède 2 commandes (en standard) pour mettre à jour le serveur et le rebooter + les widgets que nous venons de créer et quelques autres astuces sympas comme les images sous condition :

Un autre exemple avec mon serveur adguard qui gère aussi la désactivation du filtrage et la mise à jour de l’applicatif AdGuard via le plus plugin-adguard (Merci @nebz )


Pour la partie vérification des batteries et des dernières communications.
1 - on commence par créer les virtuels qui nous serviront ensuite :
rien de bien compliquer, je vous laisse reproduire ma config

Si vous personnalisez les noms de commande, il faudra mettre à jour le bloc code du scenario en consequence

2 - le scenario
Scenario lancé toutes les heures (12 * * * *)- j’ai mis 12 pour qu’il se lance à xh12 et eviter que tout ne se lance à xh00

Le template du scenario :
Alertes Infra - Com et Batteries V2.json.txt (21,4 Ko)
(supprimier le .txt pour le rechargement.

le bloc code au cas où :

// version bloc code
$version = '20/04/2023 20:00' ;
$scenario->setLog('┌──────────── Logs bloc code - version du '.$version);

// Recupération des tags
$tags = $scenario->getTags(); //récupère la liste des tags
$eqVirtuelId = str_replace(array("#", "eqLogic"),array("", ""),$tags['#eqVirtuel#']);
$plugins = explode(',',str_replace(' ','',$tags['#plugins#']));
$eqIdExclude = explode(',',str_replace(' ','',$tags['#eqIdExclude#']));
$checkBatteryEnable = $tags['#checkBatteryEnable#'];
$checkComEnable = $tags['#checkComEnable#'];
$checkComEnable = $tags['#checkComEnable#'];
$enableNotifJC = $tags['#enableNotifJC#'];
$alertPageIdJC = $tags['#alertPageIdJC#'];
$heureNotifJC = $tags['#heureNotifJC#'];
$cmdNotifJC = cmd::byId(str_replace('#','',$tags['#cmdNotifJC#']));

//Seuils d'alerte
$seuilBatteryWarning       = config::byKey('battery::warning', 'core'); // recupéré de la page equipement de la config générale Jeedom
$seuilBatteryDanger        = config::byKey('battery::danger', 'core'); // recupéré de la page equipement de la config générale Jeedom
$seuilComWarning           = 86400; // 86400 = 1 jour
$seuilComDanger            = 86400 * 2; // 2 jours

//initialisation des variables
$nbBatteryOK               = 0;
$nbBatteryWarning          = 0;
$nbBatteryDanger           = 0;
$nbBatteryTotal            = 0;
$listBatteryWarning        = '';
$listBatteryDanger         = '';
$nbComOK                   = 0;
$nbComWarning              = 0;
$nbComDanger               = 0;
$nbComTotal                = 0;
$listComWarning            = '';
$listComDanger             = '';

function convertDuree($_second) {
  if ( $_second < 60 ) return "< 1min" ;
  elseif ( $_second < 3600 ) return round($_second / 60).'min' ;
  elseif ( $_second < 86400 ) return round($_second / 3600).'h' ;
  else return round($_second / 86400).'j' ;
}


//$eqVirtuelBatteryWarning   = '#' . $eqVirtuel . '[Batterie Warning]#';
$cmdBatteryWarning   = cmd::byEqLogicIdCmdName($eqVirtuelId,'Batterie Warning');
$cmdBatteryDanger    = cmd::byEqLogicIdCmdName($eqVirtuelId,'Batterie Danger');
$cmdBatteryNbOK      = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Batterie OK');
$cmdBatteryNbWarning = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Batterie Warning');
$cmdBatteryNbDanger  = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Batterie Danger');
$cmdBatteryNbTotal   = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Equipements batterie');
$cmdComWarning       = cmd::byEqLogicIdCmdName($eqVirtuelId,'Com Warning');
$cmdComDanger        = cmd::byEqLogicIdCmdName($eqVirtuelId,'Com Danger');
$cmdComNbOK          = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Com OK');
$cmdComNbWarning     = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Com Warning');
$cmdComNbDanger      = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Com Danger');
$cmdComNbTotal       = cmd::byEqLogicIdCmdName($eqVirtuelId,'NB Equipements Com');

$checksEnable = 1 * $checkBatteryEnable  + 2 * $checkComEnable ;  // 0 - pas de check, 1 - check batt, 2 ; check com, 3 check batt + com

if ( $checksEnable >= 1 ) {
foreach ($plugins as $plugin) { // Pour chaque plugin
  $scenario->setLog('| Plugin : '.$plugin);
  foreach (eqLogic::byType($plugin, true) as $eqLogic) { // pour chaque equipement du plugin
    $eqId              = $eqLogic->getId();

    if (in_array($eqId, $eqIdExclude) == false)  { // Si l'equipememnt n'et spas dans les equipements exclus des verifs
      $eqLogicName       = $eqLogic->getName();
      $eqId              = $eqLogic->getId();
      $eqLogicHumaneName = $eqLogic->getHumanName();
      $eqLogicId         = $eqLogic->getId();
      $eqLogicType       = $eqLogic->getEqType_name();
      $objID             = $eqLogic->getObject_id();
      switch ($plugin)       {
        case "zigbee":
          $deviceModel = $eqLogic->getConfiguration('device');
        break;
        case "openzwave":
          $deviceModel = $eqLogic->getConfiguration('product_name');
        break;
        case "jMQTT":
          $deviceModel = $eqLogic->getConfiguration('commentaire');
        break;
        case "JeedomConnect":
          $deviceModel = $eqLogic->getConfiguration('deviceName');
        break;
        default:
          $deviceModel = $eqLogic->getConfiguration('device_model');
        break;
      }

      // Calcul des niveau d'alarmes des batteries
      if ($checkBatteryEnable) {
        $batteryStatus     = "" ;
         //if (!empty($deviceModel)) {         // si il n'y a pas de numero de model, on considere que ce n'est pas un equipement matériel, donc pas de batterie !!
          switch ($deviceModel) {
            case 'TS0601_thermostat':       // je fais un test dans ma sitution perso sur ce modele qui ne renvoie pas un % de batterie, mais un booleen batterie faible, ous pouvez integrer des exceptions de gesiton de batterie ici
              $batteryLowBinaire = cmd::byEqLogicIdCmdName($eqId,'Batterie faible')->execCmd();
              if ($batteryLowBinaire) $batteryStatus = 0;
              else $batteryStatus = 100;
              break;
            default:
              $batteryStatus = $eqLogic->getStatus('battery');
              break;
            }

            if (isset($batteryStatus) and $batteryStatus !== "")
            { // comptabilisation des batteries OK ou en warning ou en critical
              $nbBatteryTotal++;
              if ($batteryStatus <= $seuilBatteryDanger)
              {
                $nbBatteryDanger++;
                $listBatteryDanger = $listBatteryDanger . "<span style=\"font-size:13px\"><b>" . $eqLogicHumaneName . "</b> (" . $eqLogicType . "): " . $batteryStatus . "%<br></span>";
              }
              elseif ($batteryStatus <= $seuilBatteryWarning)
              {
                $nbBatteryWarning++;
                $listBatteryWarning = $listBatteryWarning . "<span style=\"font-size:13px\"><b>" . $eqLogicHumaneName . "</b> (" . $eqLogicType . "): " . $batteryStatus . "%<br></span>";
              }
              else
              {
                $nbBatteryOK++;
              }
            }
          //}
      }

      // calcul des niveaux d'alarme des lastCom
      if ($checkComEnable) {
        $lastCom     = strtotime($eqLogic->getStatus('lastCommunication'));
        $elapsedTime = time() - $lastCom;

        if (isset($lastCom) and $lastCom !== "")
        { // comptabilisation des LastCom OK ou en warning ou en critical
          $nbComTotal++;
          if ($elapsedTime >= $seuilComDanger)
          {
            $nbComDanger++;
            $listComDanger = $listComDanger . "<span style=\"font-size:13px\"><b>" . $eqLogicHumaneName . "</b> (" . $eqLogicType . "): " . convertDuree($elapsedTime) . "<br></span>";
          }
          elseif ($elapsedTime >= $seuilComWarning)
          {
            $nbComWarning++;
            $listComWarning = $listComWarning . "<span style=\"font-size:13px\"><b>" . $eqLogicHumaneName . "</b> (" . $eqLogicType . "): " . convertDuree($elapsedTime) . "<br></span>";
          }
          else
          {
            $nbComOK++;
          }
        }
      }
      if ( $checksEnable != 0 ) {
        $log = "|	 " . $eqLogicHumaneName ;
        if ( $deviceModel != '' ) $logDeviceModel = " (" . $deviceModel . ")" ;
        else $logDeviceModel = "" ;
      	switch ($checksEnable) {
          case 1:
            if ( isset($batteryStatus) and $batteryStatus !== "" ) {
              $log .= $logDeviceModel . " => batterie : " . $batteryStatus . "%" ;
              $scenario->setLog($log) ;
            }
            break;
          case 2:
            $log .= $logDeviceModel . " => Last com : " . convertDuree($elapsedTime) ;
            $scenario->setLog($log) ;
            break;
          case 3:
            if ( isset($batteryStatus) and $batteryStatus !== "" ) $log .= $logDeviceModel . " => batterie : " . $batteryStatus . "% , Last com : " . convertDuree($elapsedTime);
            else $log .= $logDeviceModel . " => Pas de batterie , Last com : " . convertDuree($elapsedTime);
            $scenario->setLog($log) ;
            break;
        }

      }     
    }
  }
}

// Affichage-formatage des resultats dans les virtuels
if ($checkBatteryEnable) {
  if ($nbBatteryWarning == 0) $listBatteryWarning = "<span style=\"font-size:13px\"><b>Aucun équipement en warning</b></span>";
  if ($nbBatteryDanger == 0) $listBatteryDanger  = "<span style=\"font-size:13px\"><b>Aucun équipement en critical</b></span>";
  $cmdBatteryNbOK->event($nbBatteryOK);
  $cmdBatteryNbWarning->event($nbBatteryWarning);
  $cmdBatteryNbDanger->event($nbBatteryDanger);
  $cmdBatteryNbTotal->event($nbBatteryTotal);
  $cmdBatteryWarning->event($listBatteryWarning);
  $cmdBatteryDanger->event($listBatteryDanger);
}
else $scenario->setLog("| Check batterie desactivé");

if ($checkComEnable) {
  if ($nbComWarning == 0) $listComWarning = "<span style=\"font-size:13px\"><b>Aucun équipement en warning</b></span>";
  if ($nbComDanger == 0) $listComDanger  = "<span style=\"font-size:13px\"><b>Aucun équipement en critical</b></span>";
  $cmdComNbOK->event($nbComOK);
  $cmdComNbWarning->event($nbComWarning);
  $cmdComNbDanger->event($nbComDanger);
  $cmdComNbTotal->event($nbComTotal);
  $cmdComWarning->event($listComWarning);
  $cmdComDanger->event($listComDanger);
}
else $scenario->setLog("| Check Last Communication desactivé");

// Envoi d'une notif JC
if ($enableNotifJC && date("G") == $heureNotifJC) {
  if ($nbBatteryDanger >= 1 || $nbComDanger >= 1)   {
    switch ($checksEnable)     {
      case 1:
        $cmdNotifJC->execCmd($options = array('title'         => 'title=Defaut infrastructure | gotoPageId=' . $alertPageIdJC, 'message'         => "Batteries -><span style=\"color: green\"> OK : " . $nbBatteryOK . ",</span><span style=\"color: orange\"> Warning : " . $nbBatteryWarning . ", </span><span style=\"color: red\">Critical : " . $nbBatteryDanger . "</span>"), $cache   = 0);
      break;
      case 2:
        $cmdNotifJC->execCmd($options = array('title'         => 'title=Defaut infrastructure | gotoPageId=' . $alertPageIdJC, 'message'         => "Com -><span style=\"color: green\"> OK : " . $nbComOK . ",</span><span style=\"color: orange\"> Warning : " . $nbComWarning . ", </span><span style=\"color: red\">Critical : " . $nbComDanger . "</span>"), $cache   = 0);
     break;
      case 3:
        $cmdNotifJC->execCmd($options = array('title'         => 'title=Defaut infrastructure | gotoPageId=' . $alertPageIdJC, 'message'         => "Batteries -><span style=\"color: green\"> OK : " . $nbBatteryOK . ",</span><span style=\"color: orange\"> Warning : " . $nbBatteryWarning . ", </span><span style=\"color: red\">Critical : " . $nbBatteryDanger . "</span><br>Com       -><span style=\"color: green\"> OK : " . $nbComOK . ",</span><span style=\"color: orange\"> Warning : " . $nbComWarning . ", </span><span style=\"color: red\">Critical : " . $nbComDanger . "</span>"), $cache   = 0);
      break;
    }
  }
}
elseif ( $enableNotifJC ) $scenario->setLog("| Pas de notif, prochaine notif à " . $heureNotifJC . "h");
else $scenario->setLog("| Pas de notif paramétrée");
}
else $scenario->setLog('| Aucun check n\'est paramétré, sortie sans actions');
$scenario->setLog('└───────────────────────────');

Les éléments à personnaliser se trouvent dans les tags en tête de scenario :
1 - les plugins dont on souhaite vérifier les équipements
2 - les équipements (ID de l’équipement) à exclure (si nécessaire)
3 - l’équipement virtuel précédemment créé
4 - les checks que l’on souhaite réaliser (batterie + Communication, batterie seulement ou communication seulement
5 - si on souhaite avoir des notifs et leur paramétrage

3 - on crée les widgets à afficher
image
et
image

Les widgets batterie liste Warning, batterie liste danger, com liste warning et com liste danger sont des widgets de type generique texte et qui ont comme commande état les virtuels correspondant (com warning et com danger, batterie warning et batterie danger).
Les widgets batterie OK, batterie warning, batterie crtical, com OK, com Warning, et com critical sont des widget de type générique numérique avec comme commande etat les virtuels correspondants

l’icone est sous condition avec un icone grisé si la valeur est == 0 [#value# == 0 )
je rajoute en info supplémentaire le virtuel Nb équipements pour pouvoir mettre en sous-titre le nb d’équipements / au nb d’équipements total

#value# sur #[Jeedom Connect][Batteries Verif][NB Equipements batterie]#

et pour finir, les icones utilisés :
icones.zip.txt (1,0 Mo)

Voilà, tout a été créé, ne reste plus que la mise en page en mode grille avancée + personnalisation pour avoir une belle page de supervision de son infrastructure - cf les screenshot du début de tuto

Bon courage et encore une fois, n’hésitez pas à poster votre résultat (Montrez vos créations sur l'appli)

… et si vous avez d’autres idées, elles sont les bienvenues

13 « J'aime »

Merci pour ce nouveau tutoriel. Je vais lire ça à tête reposée.

Bonjour,

Merci pour le tuto, je bug sur le 2.4 pour données le nom de cela et les commande actions post-exécution pourrais-tu mettre le screen complet des commandes comme le 2.1 mais en totalités, merci par avance.
Cordialement.

J’ai mis à jour le tuto avec des screenshots sur le 2.4. N’hésites pas à revenir vers moi en cas de souci
Norbert

Désole encore te déranger, j’ai fait cela pour le 2.2 et 4.2 mais j’ai un gros doute sur le résultat en bas

Merci pour le Tuto.
je vais profiter de mes vacances pour l’étudier et l’adapter à ma domotique :ok_hand:

Bonjour à tous,

Je vois sur cette capture qu’il y a un lien vers la page Infra.
De mon côté, je n’ai pas ça. Comment faites-vous ?

Merci

Il lit la doc !? :slight_smile:

https://jared-94.github.io/JeedomConnectDoc/fr_FR/#quelles-sont-les-options-possibles-dans-les-notifications-

1 « J'aime »

As-tu dans le bloc code mis à jour la ligne encadrée avec l’Id de ta page Infra pour ton équipement JC ?
image

1 « J'aime »

J’suis passé à côté … C’est la même chose que dans le Tuto des alertes méteo.

Merci @ngrataloup

Bonjour ngrataloup,
Je te remercie de nous avoir partagé cet excellent tuto. J’ai appris pas mal de choses sur le paramétrage des widgets de JeedomConnect et j’ai réussi à pratiquement tout mettre en oeuvre dans mon Jeedom.

J’aurais juste 2 petites questions pour savoir :

  1. Comment tu as fait pour ajouter des images pour séparer les parties « serveurs », « batterie » et « lastcom » dans JeedomConnect (encadré en bleu)

  2. Comment tu fais pour changer le nom du widget qui sera affiché. Par exemple, pour ton widget qui a comme nom « Batterie Danger » et qui se transforme en « Critical » (encadré en vert)

Merci d’avance.

Bonjour @Chanchan_BZH ,

De rien ! Tu en trouveras d’autres en cherchant plugin-jeedomconnect tutoriel

J’utilise un groupe sur lequel je ne mets aucun widget, pas de nom, et une image en image de fond, édition via l’App, clic long >> gérer les widgets >> +groupe

Via l’App, clic long sur le widget>> personnaliser >> général >> nom, là, tu peux personnaliser le nom sans impact sur le nom du widget dans le plugin

Bon courage,

Norbert

Salut,

est-ce qu’un widget image ne peut pas faire l’affaire?

Non, pas exactement, car un widget image conserve une bordure
Mais n’importe quel widget avec un arrière-plan image fait aussi l’affaire (accessible via les personnalisations)
Le groupe est un peu plus simple à mettre en place qu’un widget qu’il faut créer puis personnaliser

1 « J'aime »

Merci beaucoup pour ta réponse.

J’ai réussi pour le changement de nom mais je n’arrive pas à mettre une image dans un groupe.

L’image est sélectionnée mais l’aperçu au moment de la modification et le groupe restent noir. Le mode grille du menu est sur « Avancée ».

Pour info, je suis en :

Jeedom Core : 4.2.19
Version JC : [beta] 1.2.3
DNS Jeedom : non

Equipements :
  JeedomConnect - BZH Land 08 : v1.2.3 sur android (polling)

Tu pourrais partager ton image ? Tu n’as pas de bandes noires en haut et en bas de ton image ?
Voilà ce que j’ai comme affichage de mon côté :

L’image que j’utilise est celle que j’ai récupéré dans ton fichier zip :

BG_Serveurs

Rm : Peut importe l’image que je prenne (icônes perso que j’utilise dans l’application), l’aperçu reste désespérément noir.
Exemple d’icône :
BZH_lampe_suspension_marine_on

Par contre, si j’utilise une des icônes qui sont installées de base avec l’application, l’image s’affiche bien.

Je n’ai rien configuré dans la partie « Fond d’écran » dans l’application.

1 « J'aime »

Le PB n’est pas lié à ce sujet, peux tu en créer un spécifique en remettant bien toutes les infos ?

1 « J'aime »

Oui pas de problème.
Encore merci

Bonjour,

Je m’aperçois que ADGUARD ne remonte plus les mise à jour via ssh command Nb update et liste sur ton tuto, es pareille chez toi?