0. Infos pour bien débuter

Cette application offre un affichage convivial pour les serveurs domotique Domoticz, Home Assistant, ioBroker & Zigbee2mqtt.

image1775

image1111

0.1 Prérequis, installation : différents choix

0.1.1 installation automatique d’un conteneur LXC +LEMP+ monitor

  • L’installation de Proxmox voir (21.1 Proxmox)

  • Création d’un conteneur LXC

  • Debian 13, et les dépendances sudo, curl

  • Nginx, PHP 8.4, PHP8.4-gd, PHP8.4-ssh2

  • maria db 11.8.2, phpMyAdmin 5.2+snapshot, monitor

  • Bulma v1.0.4 (css)

  • JQuery v 4.0.0 & JQuery UI v 1.14.2

  • Pare-feu UFW, en option Fail2ban

  • Quelques programmes python utiles : pip, PHP-mqtt

  • Quelques utilitaires : dos2unix et unzip

  • Un serveur SSE en PHP (en option SSE NodeJS)

  • Un utilisateur système est crée

  • Un utilisateur MySQL PMA et monitor est aussi crée

Télécharger depuis le Shell de PVE le fichier d’installation monitor.sh :

image1268

https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/install/monitor.sh

Donner des autorisations au fichier « monitor.sh »

chmod +x monitor.sh

image1269

Si des problèmes de lecture existent

convertir le fichier en UNIX

voir le § 8.2.2 Problème de lecture de fichier

Pour utiliser les scripts python inclus dans « share »

  • pour les liaisons séries: pip install python-periphery
    • pour la base de données: pip install mysql-connector-python

Installation :

./monitor.sh

image3

image6

Choisir le langage UTF-8 : fr_FR.UTF-8

Avertissement

image1270

Le choix du langage se fait ou se confirme à l’écran suivant.

image1872

image11

image1873

image7

image1876

Choisir « dhcp » ou indiquer l’IP choisie

image1713

Note

Si IP CIDR : Par exemple, 192.0.2.0/24 est une adresse CIDR IPv4 où les 24 premiers bits, soit 192.0.2, correspondent à l’adresse réseau.

image1713

image1715

image8

image9

0.1.1.a Installation de LEMP & Monitor

image12

Choisir la version de monitor à installer :

image1795

image13

image14

image15

image16

image17

Sécuriser Maria DB, mot passe root

image18

image19

En option, installer Fail2ban : https://scalastic.io/ufw-fail2ban-nginx/

image1796

Note

Pour éviter des erreurs 2 fichiers , fail2ban.local et jail.d/jail.local, ont été ajoutés.

image1798

pour finaliser la configuration de fail2ban, au minimum modifier ces lignes:

image1797

image20

image21

créer un certificat SSL auto-signé pour Nginx

Il suffit de répondre (O)ui pour créer ce certificat, sinon taper (N)on

avec un certificat SSL auto-signé

http reste disponible ce qui permet d’éviter les restrictions CORS pour afficher d’autres serveurs comme Zigbee, Zwave, Nagios, ……

Pour une installation manuelle de ce certificat, voir le paragraphe 0.1.3 – Installation de monitor uniquement

Pour l’utiliser avec HA, ajouter dans /config/configuration.yaml

image22

image23

Fin de l’installation, noter l’IP de monitor:

image24

Quitter le shell de PVE et ouvrir la console du conteneur LXC monitor qui devrait ressempnler à ça:

image1271

http://<IP MONITOR>/monitor, la page affichée devrait ressembler à ceci:

image1273

image1272

  • connecter un serveur domotique (max 3, Domoticz, HomeAssistant, IoBroker, Zigbee2mqtt); Enlever la découverte.

define('DECOUVERTE', false);

image1274

Ce message sera présent tant qu’il n’y aura pas de correspondance entre le serveur et la BD

  • ajouter les dispositifs et variables à la base de données, voir ce § 0.2 La page d’accueil et connexion avec un serveur domotique

Vérifications en cas de problèmes :

avec Filezilla :

image25

Pour accéder en écriture aux fichiers dans /www/html/monitor, donner des droits :

chmod -R 775 /www/html/*

MySQL :

mysql -u root -p -h localhost monitor

image27

phpMyAdmin : Accès par monitor

image28

Ou en ajoutant l’adresse dans le navigateur :

<IP Monitor>/phpmyadmin/

image29

image30

Les tables installées lors de l’installation :

image31

La suite, mode découverte , 0.1.3.1 mode « découverte »

0.1.2 Installation automatique de LEMP et Monitor dans CT existant

La procédure est la même que pour 0.1.1 installation automatique d’un conteneur LXC +LEMP+ monitor

Lors de l’exécution de monitor.sh choisir:Choisur

image1874

image1875

0.1.3 Installation automatique de LEMP et Monitor dans une partition Linux

  • Installer auparavant un système Debian 12 ou supérieur

  • Télécharger le script : build_monitor.sh ,

https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/install/build_monitor.sh

Donner des autorisations au fichier build_monitor.sh

chmod +x  build_monitor.sh

Lancer le script :

./build_monitor.sh

image33

La suite : 0.1.1.a Installation de LEMP & Monitor

0.1.4 Installation de monitor uniquement

Après l’installation d’un OS (Debian, Ubuntu…et LEMP ou LAMP, Maria DB ou MySQL …

Quelques liens utiles :

Installation : plusieurs solutions

0.1.4.1 Télécharger de la version en développement

et soit extraire les fichiers, soit cloner le référentiel avec Git

https://github.com/mgrafr/monitor
https://github.com/mgrafr/monitor.git

image34

cloner le référentiel de monitor

git clone https://github.com/mgrafr/monitor.git  <REPERTOIRE_DESTINATION>

Git doit avoir été installé

sur Debian ou Ubuntu, apt install git

0.1.4.2 Télécharger de la derière version stable

et extraire les fichiers

https://github.com/mgrafr/monitor/releases/latest

image358

0.1.5 mode « découverte »

Note

IMPORTANT : après l’installation le programme est en mode « découverte »,

pour utiliser Domoticz ou Home Assistant et toutes les fonctions nécessitant des tables de la base de données, désactiver le mode « découverte » ;En profiter pour changer le mot de passe actuel 1234

Pour cela soit :

- Utiliser la fonction du programme

image39

image40

- Modifier le fichier /admin/config.php

image41

image42

Pour utiliser Domoticz, Home Assistant ou Io.broker les 3 :

  • Indiquer les serveurs utilisés

    image1224

  • Indiquer l‘ IP et le port

    image43

Logiciels utiles :

  • Logiciel d’édition d’images svg : Adobe Illustrator ou Inkscape

  • Pour les autres images webp, un convertisseur en ligne : https://convertio.co/fr/

0.1.6 -Création d’un certificat SSL auto-signé pour Nginx :

Dans le cas où l’installation n’est pas automatique (en automatique il suffit d’accepter la création du certificat).

Avant de commencer, vous devez avoir un utilisateur non root configuré avec des privilèges ; si vous avez installé Monitor en suivant ce tuto, c’est déjà fait

Étape 1 : Créer le certificat SSL

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

image44

Explications :

  • openssl: l’outil en ligne de commande pour créer et gérer des certificats, clés ,….

  • req : cette commande spécifie que nous voulons utiliser la gestion des demandes de signature de certificat (CSR) X.509. (C’est une norme d’infrastructure à clé publique à laquelle SSL et TLS adhèrent pour sa gestion des clés et des certificats).

  • x509 : pour compléter la commande précédente en indiquant que nous voulons créer un certificat auto-signé.

  • nodes: pour ignorer l’option de sécurisation de notre certificat avec une phrase secrète. Une phrase secrète empêcherait Nginx de démarrer normalement car il faudrait saisir la phrase secrète à chaque

démarrage.

  • days 365 : la durée en jours de validité du certificat

  • newkey rsa:2048 : pour générer un nouveau certificat et une nouvelle clé en une seule fois. Il est indiqué de créer une clé RSA de 2048 bits

  • keyout : emplacement du fichier de la clé privée généré.

  • out: emplacement du certificat créé.

Les deux fichiers créés sont placés dans les sous-répertoires appropriés du répertoire /etc/ssl

image45

Confidentialité persistante

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

image46

C’est assez long

Étape 2 :Configurer Nginx pour utiliser SSL

Créer 2 lignes de configuration dans un fichier pointant vers la clé SSL et le certificat

- Créer le fichier self-signed.conf dans /etc/nginx/snippets

cd /etc/nginx/snippets

sudo nano self-signed.conf

- Ajouter

#certificat et clé privée

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

image47

Ctrl X, Enter, ctrl X

- Créer un bloc de configuration avec des paramètres de chiffrement forts

  • Comme précédemment créer un fichier ssl-params.conf

sudo nano ssl-params.conf

- Ajouter :

 # from https://cipherli.st/
 # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_prefer_server_ciphers on;
 ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
 ssl_ecdh_curve secp384r1;
 ssl_session_cache shared:SSL:10m;
 ssl_session_tickets off;
 ssl_stapling on;
 ssl_stapling_verify on;
 resolver 8.8.8.8 8.8.4.4 valid=300s;
 resolver_timeout 5s;
 # Disable preloading HSTS for now.  You can use the commented out header line that includes
 # the "preload" directive if you understand the implications.
 #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
 add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
 add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

image48

Ajustez la configuration Nginx pour utiliser SSL : extrait de monitor.conf

le fichier sur github : https://raw.githubusercontent.com/mgrafr/monitor/main/share/nginx/monitor.conf

server {

listen 80 ;
listen [::]:80 ;
server_name 192.168.1.127;

# SSL configuration
listen 443 ssl ;
listen [::]:443 ssl;
include /etc/nginx/snippets/selfsigned.conf;
include /etc/nginx/snippets/ssl-params.conf;

root /www/html;
index  index.php index.html index.htm;

location ~ \.php$ {
   fastcgi_split_path_info ^(.+\.php)(/.+)$;
   fastcgi_pass   unix:/var/run/php/php8.2-fpm.sock;
   fastcgi_index  index.php;
   fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
   include        fastcgi_params;
……

Vérifier la configuration

sudo nginx -t

Vous devrez confirmer manuellement que vous faites confiance au serveur pour y accéder.= ; les navigateurs ne peuvent vérifier les certificats auto-signés

Redémarrer le serveur Nginx

sudo systemctl restart nginx

0.1.7 Mise à jour de monitor

modifications en cours….

** NOTE IMPORTANTE**

2 solutions pour les mises à jour :

  • mise à jour complète du conteneur (passage à une nouvelle version de Debian, de Mariadb, etc…

  • mise à jour simple ne necessitant que l’update de quelques fichiers de Monitor

0.1.7.1 Mise à jour complète

Installer un nouveau conteneur LXC

  • avec le shell de PVE:

wget https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/install/update.sh
chmod +×update.sh
./update.sh

image3

voir le § 0.1.1 installation automatique d’un conteneur LXC +LEMP+ monitor

copier la configurationdes E/S de l’ancien monitor vers le nouveau

image1669

un nouveau conteneur est installé, le conteneur actuel hébergeant monitor reste pour l’instant opérationnel.

Modification des ports pour l’accès HPPPS

  • Modifier la redirection de ports; monitor à mettre à jour est redirigé vers le port 444 et le nouveau monitor est dirigé vers le port 443

    image1706

  • Modifier la redirection du port 80 (vers le nouveau monitor)

    image1878

  • Modifier le port dans la configuration actuelle Nginx de monitor :/etc/nginx/conf.d/monitor.conf

    image1707

  • Ajouter une règle:

    image1877

  • Redémarrer Nginx : systemctl restart nginx

Note

Si vous utilisez Nagios ou un autre monitoring, changer provisoirement le nom du nouveau CT monitor dans Proxmox afin d’éviter un conflit de nom.

image1708

  • Répertorier les modules Python à ajouter si besoin;

    image1704

    pour les ajouter avec le script ci-après :

    image1709

Sauvegarde de monitor

Note

Toutes les opérations de sauvegarde peuvent être effectées automatiquement avec le script sauvegarde_maj.sh

wget https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/install/sauvegarde_maj.sh

Le script *

 #!/usr/bin/bash
 #sur le serveur monitor actuel
PHP_VERSION=$(php -r "echo PHP_VERSION;")
echo ${PHP_VERSION:0:3} > /var/www/monitor/version_php.txt
 chmod -R 777 /var/www/monitor/DB_Backup
 chmod -R 777 /etc/letsencrypt/archive/*
 nom_bd=$(whiptail --title "Bases de donnees a sauvegarder" --inputbox "Veuiller entrer les noms separes par un espace" 10 60 3>&1 1>&2 2>&3)
 exitstatus=$?
 if [ $exitstatus = 0 ]; then
 echo "Base(s) de donnees : "$nom_bd
 else
 nom_bd=monitor
 echo "Par defaut, base de donnees : "$nom_bd
 fi
 mysqldump -u root -p --databases $nom_bd  | gzip  > /var/www/monitor/DB_Backup/dump.sql.gz
 pip list --format=json > /var/www/monitor/admin/connect/mod.json
 ufw status > /var/www/monitor/admin/connect/ufw.txt
 xxx=$(hostname -I)
 echo $xxx | cut -d ' ' -f 1 > /var/www/monitor/admin/connect/ip.txt
 choix_https=$(whiptail --title "accès distant" --radiolist \
 "avez vous une adresse distante HTTPS ?" 15 60 4 \
 "Pas de https  " "par defaut " ON \
 "accès https" "voir la doc" OFF 3>&1 1>&2 2>&3)
 if [ $exitstatus = 0 ]; then
   echo "Vous avez choisi  : $choix_https"
 else
 echo "Vous avez annulé  "
 fi
 if [ "$choix_https" = "accès https" ]
 then
 echo "pour letsencrypt remplacement port 443 par 444"
 sed  -i "s/443/444/g" /etc/nginx/conf.d/monitor.conf
 systemctl restart nginx
 echo "------------------------------------------------------------------"
 echo "NE PAS OUBLIER DE MODIFIER LA REDIRECTION DE PORTS DANS LE ROUTEUR"
 echo "------------------------------------------------------------------"
 fi
 cd /etc/systemd/system
 find . -type f -prune > /www/monitor/c.txt

si la maj est manuelle, liste des sauvegardes qui devront être restaurées

sauvegarde de la (ou les) bases de données, monitor et le cas échéant iobroker

image1543

établir la liste des modules python installés (lors de script perso: lgtv, mysql-connector,…)

image1548

image1553

étalir la liste de port utilisés par le pare-feu

image1552

sauvegarder le répertoire /etc/letsencrypt

image1542

sauvegarder les mots de passe /nginx/.htpasswd

image1557

sauvegarder les scripts Python

image1547

sauvegarder les scripts systemd pour le démarrage automatique

image1658

Restauration automatiques des sauvegardesdes

téléchargement depuis le conteneur actuel des fichiers qui concernent les données à conserver( base dedonnées,configuration,certificat,etc…)

Pour cela , on utilise sftp dans le script restore.sh; les fichiers et répertoires sont stockés dans home/<REPERTOIRE CHOISI LORS DU SCRIPT> du nouveau conteneur.

image1544

image1545

Les fichiers téléchargés sont stockés dans un répertoire installé dans /home et vont écraser dans le nouveau monitor les fichiers de données.

Un extrait du script install/restore.sh,

https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/install/restore.sh

#!/usr/bin/bash
    #sur le nouveau serveur monitor
    ip3=$(whiptail --title "IP de monitor à mettre à jour" --inputbox "ip de l'ancien CT TOUJOURS exécuté" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    user_sftp=$(whiptail --title "utilisateur sftp" --inputbox "nom de l'utilisateur autorisé SFTP" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    pass_sftp=$(whiptail --title "Mot de passe sftp" --inputbox "MOT DE PASSE POUR $user_sftp" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    mdir_maj=$(whiptail --title "Création d'un réperoire de travail dans 'home'" --inputbox "veuillez entrer le du répertoire \n\n Entrer répertoire" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    if [ $exitstatus = 0 ]; then
echo "répertoire enregistré : "$mdir_maj
    else
    mdir_maj=/maj_monitor
    echo "Par défaut, répertoire : "$mdir_maj
    fi
    mkdir -p /home/$mdir_maj/monitor/{admin,custom,DB_Backup,include}
    mkdir -p /home/$mdir_maj/monitor/custom/{php,python,js,css,images}
    mkdir -p /home/$mdir_maj/etc/{letsencrypt,ssl,ssh,nginx,cron.d}
    mkdir -p /home/$mdir_maj/etc/systemd/system
    mkdir -p /home/$mdir_maj/root/.ssh
    mkdir -p /home/$mdir_maj/etc/nginx/{conf.d,ssl}
    #read ip3 < /var/www/monitor/admin/connect/ip.txt
    echo "adresse IP old: $ip3"
    xxx=$(hostname -I)
    ip4=$(echo $xxx | cut -d ' ' -f 1)
    echo "adresse IP new : $ip"
    echo $ip4 > /home/$mdir_maj/monitor/ip.txt
    lets=$(whiptail --title "Certificat Letsencrypt" --radiolist \
    "Comment voulez vous mettre à jour monitor ?\n avec les certificat SSL enregistrés\n sans les certificats SSL " 15 60 4 \
    "Avec les certificats déjà enregistrés" "par defaut " ON \
    "Sans certificats" "voir la doc" OFF 3>&1 1>&2 2>&3)
    if [ $exitstatus = 0 ]; then
     echo "Vous avez choisi  : $lets"
    else
    echo "Vous avez annulé  "
    fi
    sleep 1
    lett=$(whiptail --title "clé SSH" --radiolist \
    "Possédez-vous une ou plusieurs clés SSH ? ?\n voulez vous les copier ?" 15 60 4 \
    "Copier les clés déjà enregistrées" "par defaut " ON \
    "Ne pas copier les clés " "voir la doc" OFF  3>&1 1>&2 2>&3)
    if [ $exitstatus = 0 ]; then
     echo "Vous avez choisi  : $lett"
    else
    echo "Vous avez annulé  "
    fi
    sleep 1
    cle_ssh=$(whiptail --title "Ajout $ip3 sur  .ssh/known_hosts " ---radiolist \
    "si $ip3 ne se trouve pas dans le fichier ~/.ssh/known_hosts" 15 60 4 \
    "OUI" "par defaut " ON \
   "NON"  "          " OFF  3>&1 1>&2 2>&3)
    if [ $exitstatus = 0 ]; then
     echo "Vous avez choisi  : $cle_ssh"
     ssh-keyscan -H -t rsa $ip3 >> ~/.ssh/known_hosts
    else
    echo "Vous avez annulé  "
    fi
    cd /home/$mdir_maj/monitor
    sshpass -p $pass_sftp sftp $user_sftp@$ip3<<EOF
    get /var/www/monitor/index_loc.php
    get /var/www/monitor/c.txt
    lcd admin
    get -R /var/www/monitor/admin/*
    lcd ..
    lcd custom
    get -R /var/www/monitor/custom/*
    lcd ..
    lcd DB_Backup
    get /var/www/monitor/DB_Backup/*
    lcd ..
    lcd include
    get /var/www/monitor/include/header.php
    lcd ..
    lcd ..
    lcd etc/nginx
    get /etc/nginx/.htpasswd
    lcd conf.d
    get /etc/nginx/conf.d/*
    lcd ..
    lcd ..
    lcd cron.d
    get /etc/cron.d/*
    lcd ..
    lcd systemd/system
    get /etc/systemd/system/*
    exit
    EOF
    if [[ "$lets" == "Avec les certificats déjà enregistrés" ]];then
    echo $lets
    cd /home/$mdir_maj/etc/nginx/ssl
    sshpass -p $pass_sftp sftp $user_sftp@$ip3<<EOF
    get -p /etc/nginx/ssl/*
    lcd ..
    lcd ..
    lcd letsencrypt
    get -pr /etc/letsencrypt/*
    lcd ..
    lcd ssl
    get -pr /etc/ssl/*
    lcd ..
    lcd ssh
    get -pr /etc/ssh/*
    exit
    EOF
    fi
    if [["$lett" == "Copier les clés déjà enregistrées" ]];then
    echo $lett
    cd /home/$mdir_maj/root/.ssh
    pass_root=$(whiptail --title "Mot de passe root" --inputbox "MOT DE PASSE POUR root" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    sshpass -p $pass_root  sftp root@$ip3<<EOF
    get -pr /root/.ssh/*
    exit
    EOF
    fi
    domaine=`grep $choix'domaine=' /var/www/monitor/admin/connect/connect.py | cut -f 2 -d '='`
    echo "domaine : " $domaine
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/monitor/admin/config.php
    sed -i "s/.\///g"  /home/$mdir_maj/monitor/systemd/c.txt
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/etc/nginx/conf.d/monitor.conf
    sed -i "s/444/443/g" /home/$mdir_maj/etc/nginx/conf.d/monitor.conf
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/monitor/admin/connect/connect.py
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/monitor/admin/connect/connect.lua
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/monitor/admin/connect/connect.js
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/monitor/admin/connect/connect.yaml
    cp /home/$mdir_maj/monitor/admin/connect/connect.py /home/$mdir_maj/monitor/custom/python/connect.py
    cp /home/$mdir_maj/monitor/admin/connect/connect.js /home/$mdir_maj/monitor/custom/js/connect.js
    nbconf=$(whiptail --title "Autre fichier de Config" --inputbox "si il existe sinon laisser vide" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    if [ -n "$nbconf" ]
    then
    sed -i "s/${ip3}/${ip4}/g" /home/$mdir_maj/monitor/admin/$nbconf
    fi
    ipiob=$(whiptail --title "IP de ioBroker" --inputbox "si elle existe sinon laisser vide" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    if [ -n "$ipiob" ]
    then
    # iobrker pour script py
    cd /home/$mdir_maj/monitor/admin/connect
    sshpass -p $pass_sftp sftp $user_sftp@$ipiob<<EOF
    put connect.py /opt/python/connect.py
    exit
    EOF
    fi
    vv=$(pip list --format=json)
    echo $vv
    cp  -R /home/$mdir_maj/etc/ssl/* /etc/ssl/
    cp  -R /home/$mdir_maj/etc/ssh/* /etc/ssh/
    mkdir -p /etc/letsencrypt
    cp -R /home/$mdir_maj/etc/letsencrypt/* /etc/letsencrypt/
    chmod -R 777 /etc/letsencrypt
    rm -R /etc/letsencrypt/live
    cd /etc/letsencrypt
    mkdir -p live
    chmod -R 777 live
    cd archive
    for f in * ; do  echo $f;  done > /home/$mdir_maj/a.txt;
    while read l; do nn=$(find /home/$mdir_maj/etc/letsencrypt/archive/$l -type f -printf '%T@ %p\n' | sort -n | tail -n 1 | cut -d' ' -f2-);
    nb=${nn##*/}; a=$(echo "$nb" | grep -Eo '[0-9]+(\.[0-9]+)?' | head -n 1); echo $a;
    mkdir -p /etc/letsencrypt/live/$l;
    chmod -R 777 /etc/letsencrypt/live/$l;
    ln -s /etc/letsencrypt/archive/$l/privkey$a.pem /etc/letsencrypt/live/$l/privkey.pem;
    ln -s /etc/letsencrypt/archive/$l/fullchain$a.pem /etc/letsencrypt/live/$l/fullchain.pem;
    ln -s /etc/letsencrypt/archive/$l/cert$a.pem /etc/letsencrypt/live/$l/cert.pem;
    ln -s /etc/letsencrypt/archive/$l/chain$a.pem /etc/letsencrypt/live/$l/chain.pem;
    done  < /home/$mdir_maj/a.txt
    if [ $a = 0 ]; then
    echo "erreur  vérifier lles autorisations pour etc/letsencrypt/archive=644"
    exit
    fi
    sleep 2
    cp /home/$mdir_maj/monitor/include/header.php /var/www/monitor/include/header.php
    cp /home/$mdir_maj/monitor/index_loc.php /var/www/monitor/index_loc.php
    cp /home/$mdir_maj/monitor/c.txt /var/www/monitor/c.txt
    cp -R /home/$mdir_maj/etc/systemd/system/* /etc/systemd/system/
    cp -R /home/$mdir_maj/monitor/custom/python/* /var/www/monitor/custom/python/
    cp -R /home/$mdir_maj/monitor/custom/php/* /var/www/monitor/custom/php/
    cp -R /home/$mdir_maj/monitor/custom/images/* /var/www/monitor/custom/images/
    cp -R /home/$mdir_maj/monitor/custom/js/* /var/www/monitor/custom/js/
    cp -R /home/$mdir_maj/monitor/custom/css/* /var/www/monitor/custom/css/
    cp -R /home/$mdir_maj/monitor/admin/* /var/www/monitor/admin/
    cp /var/www/monitor/admin/connect/connect.py /var/www/monitor/custom/python/
    chmod -R 777 /var/www/monitor/DB_Backup
    cp /home/$mdir_maj/monitor/DB_Backup/dump.sql.gz /var/www/monitor/DB_Backup/
    gunzip -c /var/www/monitor/DB_Backup/dump.sql.gz > /var/www/monitor/DB_Backup/dump.sql
    mysql --user=$user_sftp --password=$pass_sftp < dump.sql
    # ufw allow 444
    # systemctl restart ufw
    sudo apt install certbot python3-certbot-nginx -y
    cp  /home/$mdir_maj/etc/nginx/conf.d/* /etc/nginx/conf.d/
    cp  /home/$mdir_maj/etc/nginx/.htpasswd /etc/nginx/
    mkdir -p /etc/nginx/ssl
    cp  /home/$mdir_maj/etc/nginx/ssl/* /etc/nginx/ssl/
    chmod -R 777 /etc/cron.d
    cp /home/$mdir_maj/etc/cron.d/* /etc/cron.d
    systemctl restart nginx
    # chmod -R 777 /root/.ssl
    cp /home/$mdir_maj/root/.ssh/* /root/.ssh
    certbot update_symlinks
    certbot renew --dry-run
    echo "fin de cerbot"
    sleep 1
    while read L; do
    systemctl enable $L
    systemctl start $L
    done  < /etc/systemd/system/c.txt
    sleep 5
    mod_py=$(whiptail --title "Installation de module(s) python" --inputbox "Les Modules  doivent être séparés par un espace" 10 60 3>&1 1>&2 2>&3)
    exitstatus=$?
    if [ -n "$mod_py" ]
    then
    sudo apt update
    sudo apt install $mod_py
    fi
    file=/www/monitor/custom/php/accueil.php
    if [ -e $file ]; then mv /www/monitor/include/accueil.php /www/monitor/include/_accueil.bak; fi

Note

Si le fichier accueil.php a été placé dans /custom/php, le fichier original dans /include est renommé en _accueil.bak

image1942

image1671

image1672

image1673

image1674

Note

Pour une restauration manuelle queques conseils :

ci-dessous dans le répertoire archive les clés, certificats ,… utilisés (les + récents sont ceux avec le nombre le plus élevé , ex: privkey17);

si les virtualhosts sont peu nombreux , utiliser les fichiers les plus récents (ex: privkey7);si les répertoires sont très nombreux , choisir l’indice 1 pour tous, le script update_symlinks rétabliera la bonne configuration.

Le script restore.sh choisit les bons cerificats automatiquement

image1546

** Après la restauration**

Important

Avant de basculer définitivement sur le nouveau conteneur, faire une maj virtuelle, pour indiquer aux différent serveurs domotiques la nouvelle IP de monitor;

Le fichier connect.py a dèjà été modifié , cette maj sert à modifier les fichiers distants connect.lua, connect.js et connect.py.

image1549

Important

les iframes en accès distant ne fonctionneront seulement quand la redirection du port 443 aura été effectuée sur l’IP du nouveau monitor.

image1559

si tout fonctionne correctement arrêter l’ancien monitor et dans quelques jour le supprimer.

0.1.7.2 Mise à jour partielle

Ne concerne que Monitor et les versions > 3.2.2

Avertissement

Seules les versions supérieures à 3.2.2 peuvent être mises à jour partiellement; pour les versions inférieures ou égales à 3.2.2:

En utilisant les scripts décrits dans ce paragraphe, la mise à jour s’effectue automatiquement

Obtenir la dernière version de update.sh , avec la console :

cd /www/monitor
wget https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/install/update.sh

Rendre éxécutable le fichier et le lancer

sudo chmod +x update.sh
sudo ./update.sh

image51

image1818

En cas de problème avec le chemin de bash en root:

/usr/bin/bash ./update.sh

0.2 La page d’accueil et connexion avec un serveur domotique :

0.2.1 page d’accueil :

Pour modifier l’image, les titres et slogan de la page d’accueil : voir ce paragraphe 1.1.1.a Pour l’image de fond suivant la résolution d’écran et le logo

image52

0.2.2 Connexion au serveur domotique

3 serveurs possibles:

  • Domoticz

  • Home Assistant

  • IoBroker

  • z2m

Home Assistant, Domoticz et z2m sont quelque peu limités dans leurs options de personnalisation, le ioBroker vis et vis2 peuvent être considérés comme très complexes d’où la création de monitor.

La combinaison Monitor + Iobroker offre un affichage très agréable.

image1520

Il suffit de cliquer sur les lampes pour les allumer ou les éteindre.

J’ai commencé par utiliser Domoticz et comme je ne suis pas fan des fichiers YAML, je préfère utilisé io.broker avec lequel il est facile d’utiliser également Blocky ou de convertir facilement les scripts Lua de Domoticz en Javascript.

Par rapport à ioBroker, Home Assistant utilise moins de ressources, Z2m en utilise encore moins ce qui est un avantage sur les systèmes les plus légers.Avec un mini PC il est possible avec Proxmox d’utiliser les 4 systèmes simultanément.

Note

Le choix se fait dans /admin/config.php:

// Domoticz ou HA ou iobroker
define('DOMOTIC', 'DZ');//DZ ou HA ou IOB ou ZB ou "" (non utlisé)
define('DOMOTIC1', 'HA');//DZ ou HA ou IOB ou ZB ou ""
define('DOMOTIC2', '');//DZ ou HA ou IOB ou ZB ou ""

le Javascript reçoit ces informations:

image1537

0.2.3. Premier dispositif

0.2.3.1 pour Domoticz

Température extérieure : le matériel

Avertissement

Depuis le 1 avril 2023 le service Darsky n’est assuré que pour des appareil Apple !!! J’ai donc provisoirement migré vers Météo Concept que j’utilise pour ma météo à 14 jours ; Je n’utilise pas ces valeurs dans Domoticz

A la place OpenWeatherMap peut être utilisé :

Pour la météo actuelle laisser les curseurs en rouge

image53

Le dispositif :

image54

Création d’un plan :

image55

image56

image57

Noter :

  • l’Idx du plan Domoticz

  • L’Idx (Domoticz) du dispositif 285

l’Idm (Id monitor) , il est le premier dispositif : 1

Ajoutons ces données dans la base SQL , soit avec phpmyadmin ou plus simplement avec l’appli :

image4

Ajout d’un dispositif:

image58

image59

image60

Modification d’un dispositif

image1329

image1330

Avec OpenWeather l’API fournit la température ressentie, pour l’ajouter enregistrer le dispositif et ajouter à accueil.php :

<p class="text-centre">T° ressentie :<span id="temp_ressentie" style="color:#ffc107;"></span></p>

La classe « text-centre » :

.text-centre {
 margin-right: 2px;
 margin-left: 2px;
 margin-bottom: 2px;
 display: block;
 float: none;}

Script de remplacement

Indépendant de Domoticz, la fonction PHP

case 2:// relevé temps réel station la pus proche (40Km)
$url = 'https://api.meteo-concept.com/api/observations/around?param=temperature&radius=40&token='.TOKEN_MC.'&insee='.INSEE;
//$url2 = 'https://api.meteo-concept.com/api/forecast/nextHours?token='.TOKEN_MC.'&insee='.INSEE;
$prevam = file_get_curl($url);//echo $prevam;return;
$forecastam = json_decode($prevam);$info=array();
  //$info['time']=$forecastam[0]->observation->time;
  $info['temp']=$forecastam[0]->observation->temperature->value;
  $info['hPa']=$forecastam[0]->observation->atmospheric_pressure->value;
return json_encode($info);
break;

lien Github du fichier avec les fonctions PHP : https://raw.githubusercontent.com/mgrafr/monitor/main/fonctions.php

exemple d’appel, depuis Monitor de la fonction PHP(fonctions.php) dans footer.php; cet exemple concerne la météo.

mc(1,"#meteo_concept");
mc(0,"#meteo_concept_am");
//mc(3,"#temp_ext");      //pour la T° locale
setTimeout(pluie, 3600000, 2);
function mc(variable,id){
  $.ajax({
  type: "GET",
  url: "ajax.php",
  data: "app=meteo_concept&variable="+variable,
  success: function(data){
  if (variable==3 || variable==2) $(id).html(data.data);
          else $(id).html(data);
  }
});
//setTimeout(mc, 1800000, 3,"#temp_ext");//:red:`pour la T° locale rafraichissement toutes les 30mn`
 };

footer.php et ajax.php sont dans le référentiel : https://github.com/mgrafr/monitor

image64

0.2.3.2 pour Home Assistant

La météo est installée lors de l’installation du programme.

Pour visualiser la température extérieure sur monitor :

image65

Enregistrement du dispositif :

image66 image67

Affichage sue la page d’accueil :

image68

Les données json de ce dispositif :

image69

0.2.3.3 pour IoBroker

Important

REST-API adapter , https://github.com/ioBroker/ioBroker.rest-api, doit être installé.

image1396

Pour afficher la température extérieure sur monitor : Installer l’adaptateur pour la météo et renseigner les paramètres , ici l’opérateur norgégien:

image1397

Note

Pour limiter la recherche de l’ID dans les données fournies par l’adaptateur et aussi si on le souhaite utiliser, dans une app perso, une une partie importante de ces données, il faut indiquer dans admin/config.php le chemin de recherche:

image1561

exemples pour zigbee et la météo yr

image1562

image1560

Enregistrer le dispositif dans la base de données

image1398

Extrait du fichier json avec les adaptateurs zigbee2mqtt.0 et yr.0.forecastHourly.0h :

image1563

Extrait du fichier json avec l’adaptateurs worx.123456…..5678 :

image1399

Pour consulter le json des adaptateurs voir cette page : 14. ADMINISTRATION

Le json de la température utilisé par monitor:

image1400

0.2.3.3 Affichage sur la page d’accueil de Monitor :

Extrait du fichier /include/accueil.php

image70

L’ID html est ici : temp_ext

0.3 _ Base de données Maria DB

La base de données a été créée lors de l’installation du serveur : nom=monitor (donnée lors de la création, il peut être différent)

Note

Pour modifier la configuration , necessaire si la base de données est utilisée par une autre application “iobroker par exemple)

le socket local n’utilise aucun port , le port par défaut est le 3306 et il faut le déclarer dans : nano /etc/mysql/mariadb.cnf

Il faut aussi autoriser ce port dans le pare-feu si la base est utilisée par un serveur distant (ex iobroker) :

ufw allow 3306

image1555

Si votre serveur possède plusieurs interfaces réseau, vous pouvez mettre 0.0.0.0 à la place de l’adresse IP dans nano /etc/mysql/mysql.conf.d/mysqld.cnf mais cela concerne toutes les adresse IP

image1556

ou si mariadb est d’une version récente , voir le § 0.3.5 Configurer MariaDB pour les connexions distantes.

image1564

Pour vérifier la connexion distante après avoir donné des droits à n utilisateur :

image1554

Connexion en local : IP/phpmyadmin

image72

Pour les autorisations d’accès, voir le paragraphe concernant la configuration /admin/config.php

Elles ont été créées lors de l’installation automatique, pour l’installation manuelle :

Extrait de config.php:

// parametres serveur DBMaria
define('SERVEUR','localhost');
define('MOTDEPASSE','<MOT DE PASSE>');
define('UTILISATEUR','<UTILISATEUR>');
define('DBASE','monitor');

Avertissement

En cas d ‘absence de base de données ou de mauvais paramétrages ,sur la page d” accueil :

«  pas de connexion à la BD « 

plus d’info sur test_db.php 14.2 admin.php, info_admin.php, test_db.php et backup_bd

Ajout à la base de données des données fournie par Domoticz

0.3.1 Les Tables « dispositifs(variables) », « text-image », « messages » & « sse »

Ces tables sont installées lors de l’installation automatique.

La correspondance entre les variables Domoticz , HA, IoBroker ou monitor ou des applications tierces et l’affichage sur les pages perso se fait par l’intermédiaire de la BD « monitor » ;

Avertissement

pour IoBroker , contrairement à Domoticz ou Home Assistant, il faut créer une base de données (ou uttiliser la base « monitor ») pour les variables et utliser l’adaptateur : io.broker.sql.

image1393

Note

voir ce lien pour la création d’une BD pour IoBroker:

https://www.iobroker.net/docu/index-85.htm?page_id=4184&lang=en

image1391

Monitor possède déja une BD mySQL aussi pour uniquement les variables iobroker la BD SQLite suffit (si la BD msql monitor n’est pas utilisée);

pour installer SQLLite :

sudo apt-get update
sudo apt-get install sqlite3

image1392

Pour créer la base de donnés « data.db3 », la table « variables » et la variable « essai » :

sqlite3 data.db3
create table variables(id INT, nom TEXT, content TEXT);
insert into variables values(0,"essai","12345");

image1394

Test :image1395

Important

Correction de l’erreur SQLite « tentative d’écriture d’une base de données en lecture seule »

le dossier qui héberge le fichier de base de données doit être accessible en écriture.

  • tables :

    . text-image

    . dispositifs

    . messages

    . sse

    image75

0.3.1.1 Table text-image

quelques explications

Pour un texte contenu dans une variable correspond une image ou 0 ou « none »

image76

ex: le texte « poubelle jaune » dans la variable poubelle aura un alias : l’image d’une poubelle jaune

0.3.1.2 Table dispositifs pour les variables

A l’installation de la table une variable « upload » est préinstallée; elle permet d’indiquer à Domoticz ou Home Assistant que des fichiers de configuration ont été mis à jour par monitor.

image1361

Note

pour plus de lisibilité, il est préférable de numéroter les variables à partir de 1000 ce qui évite les doublons idm.

ne sont concernés pour les variables que les champs :

image1390

image78

num : ne sert qu’à éditer plus facilement la BD

Pour modifier plus facilement la table, ajouter au début un champ (num utilisé ici) afin de pouvoir éditer les enregistrements.

image79

. Nom appareil : non obligatoire

. nom_objetnom de la variable du serveur domotique (dz, ha ou iob);

mot réservé: BASH, commande Bash; sous Docker l’accès au Shell du serveur n’est pas possible, la parade consiste à passer par monitor; voir ci-après un exemple de commande bash.

Avertissement

IMPORTANT : le nom de la variable Domoticz ne doit pas comporter d’espace

(le programme fonctionne mais l’API renvoie « NULL »)

. Idx , id de la variable du serveur Domoticz

ex : idx de Domoticz

image87

. ID, identity_id (ha & iob & monitor) ; ex : Home Assistant, nom essai, ID input_text.essai; ex : monitor : pp[XXX].values.xxxxxx

EXEMPLE DE VARIABLE MONITOR (faire F12 avec un navigateur) : pp est le nom du tableau des variables dans monitor

image1950

voir ce paragraphe 0.13 Les fichiers JSON reçu par monitor

Avertissement

IMPORTANT : le contenu de la variable texte ne doit pas dépasser 255 caractères en cas de dépassement possible, utiliser un message (voir ci-après)

image88

. idm , id de la variable dans monitor ; souvent utilisé avec l’id html « annul_<texte>, rel=idm

image1384

. Actif , 2=domoticz, 3=home assistant, 4=iobroker, 5=monitor

. maj_js : variable= variables dz ou ha, var_sql= variables monitor

. Id1_html : ID de l’image dans la page ou #shell (voir ci-dessous)

. Id2_html : ID du texte dans la page, concerne surtout l’alarme mais peut afficher d’autres notifications ;

Important

des ID sont réservés , voir à la fin de ce praragraphe la liste des ID à ne pas utiliser pour des ajouts personnels.

un exemple bash concret : redémarrer un script après modifications

Ici systemctl restart sms_dz (script chargé de l’envoi des sms et qui doit être redémarré si le fichier « connect.py » a été modifié (ajout, remplacement de N° de tel)

Dans Domoticz : créer une variable avec les données ci-dessous et l’exploiter dans un script LUA

image80

scrpt LUA:

-- le fichier connect.py est modifié `
f = io.open("userdata/scripts/python/connect.py", "w")
              env="#!/usr/bin/env python3"
              f:write(env.." -*- coding: utf-8 -*-".."\n"..fich)
              f:close()
-- on modifie la variable
              domoticz.variables('BASH').set("restart_sms_dz")

Dans SQL :

image81

Ou par Monitor :

image82

image83

Dans monitor, PHP-SSH2

raw.githubusercontent.com/mgrafr/monitor/main/include/ssh_scp.php

Extrait du fichier :

image85

Monitor surveille les modifications de variables, si une variable avec une ID_img =#shell apparait, si la valeur est !=0 le nom du script indiqué dans Value est exécuté :

Appel ajax depuis footer.php vers ajax.php->ssh_scp.php->serveur dz ou ha->exécution du fichier Bash

#!/usr/bin/bash
echo "MOT DE PASSE" | sudo -S systemctl restart sms_dz

Le mot de passe peut être ajouté à connect.py

Mots réservés, utilisables

  • pour le nom de variable (nom_objet) :BASH

  • pour les ID javascript (affichage des textes et images :

    ping_rasp : ping non réussi vers un raspberry ou un autre serveur effacement image1372

    bl : boite lettres , confirmation de la notification image1373

    pression_chaud , confirmation de la notification image1374

    pilule , confirmation de la notification image1375

    fosse , confirmation de la notification image1376

poubelle , affichage poubelles grises et jaunes image1377

pl, pluie , txt_pluie , affichage image et texte image1378

aff_anni , prenom , affichage image et texte image1379

alarme_nuit , affichage alarme nuit automatique image1380

batterie , affichage alarme batterie dispositifs faible image1382

lastseen , affichage message « vu pour la dernière fois » image1381

notify , not, , affichage des erreurs ou alertes

temp_ext, temp_ressentie , image1383

annul_<texte> : annul_ est réservé, ne pas utiliser avec les id si dessus

0.3.1.3 Table messages

image1179

Cette table permet avec HA de recevoir des textes supérieur à 255 caractères( Rest_command de HA) ou à des app tierces d’envoyer à monitor des notifications( par l’API de monitor , voir ce § 0.12 API de monitor

Exemple d’utilisation avec Home Assistant

image1180

REST_API :

rest_command:
  monitor_1:
    url: "http://192.168.1.9/monitor/api/json.php?app=messages&name=message1&contenu={{svalue}}&maj=1=0"

0.3.1.4 Table sse

Table avec un enregistrement unique utilisé par l’API monitor

image1303

0.3.1.5 Pourquoi une correspondance ?

cela évite, lors d’une modification dans Domoticz ou HA, de modifier tous les ID (idm) dans monitor

Installation des tables : lors de l’installation automatique, elles sont installées, sinon télécharger le référentiel :

image89

Les API de Domoticz et Home assistant pour les variables :

  • DZ , URL : PORT/json.htm?type=command&param=getuservariables ,( renvoie la liste de toutes les variables et leurs valeurs)

  • HA , URL : 8123/api/states/sensor.liste_var (renvoie la liste des dispositifs enregistrés comme input text)

Le template sensor : sensor.liste_var pour HA

template:
  -  sensor:
       -  name: "liste_var"
          unique_id : listvar001
          state: >
            {% for input_text in states.input_text %}
             {{input_text.entity_id ~ "=" ~ input_text.state ~ ", " }}
            {% endfor %}

image143

0.3.2 Les Dispositifs

Comme pour les variables, la table fournie une correspondance entre les dispositifs dans Domoticz, HA ou Io.Broker et Monitor et une info sur le matériel (Zgbee, Zwave, et n° de nœud.) (Pour les dispositifs Domoticz n’enregistre pas le type de matériel)

Note

En règ En règle générale : un numéro(idm) par fonction sauf pour temerature, humidité, % batterie rassemblés dans le même dispositif

Table « dispositifs »

image91

image92

La table permet en plus de gérer et modifier si besoin l’affichage de tous les dispositifs sans intervenir sur la page HTML ; pour les switches, les scripts pour commander l’allumage ou l’extinction sont générés automatiquement à partir des données de cette table.

  • numne sert qu’à éditer plus facilement la BD

    voir le paragraphe précédent 0.3.1.2 Table dispositifs pour les variables

  • Nom appareil : nom usuel

  • nom_objet : nom pour Domoticz optionnel pour io.broker & Home Assistant (objet_id (friendly_name)

Note

il est plus facile de donner le même nom d’un dispositif à Zigbee2mqtt, Zwave-JS, Domoticz , Home Assistant ou iobroker

  • idx : celui de Domoticz

  • ID : entity_id de Home Assistant ou _id de Io.broker ou de z2m

  • idm : 1 à 999 ; pour les dispositifs ayant plusieurs fonctions les idm sont de la forme xxx_1, xxx_2, xxx_3, …

    idm de monitor peut-être le même que idx ; c’est utile pour l’affichage des infos concernant un dispositif ; de plus cela permet de retrouver facilement un dispositif dans l’image svg du plan en faisant une recherche ;dans l’image cet idm est indiqué par « rel=idm »: Voir le paragraphe concernant les images svg

  • Actif : 0 = inactif , Domoticz=1 ou 2, Home Assistant=3 io.broker=4, monitor=5, z2m=6; 1 dispositif peut avoir un idx de Domoticz et un ID de Home Assistant mais il ne peut y avoir qu’un seul des 2 ACTIF , dans ce cas Actif = 1 ou 2 ou 3 ou 4 ou 5 ou 6.

Important

  • Actif: le chiffre 2 est à privilégier pour Domoticz, le chiffre 1 sera supprimé dans le futur. Le chiffre 6 concerne zigbee2mqtt (utilisé seul sans Dz, Ha ou Iob) , projet en cours de développement.

  • idm: iob+ concerne un dispositif io.Broker avec beaucoup d’ID, c’est le cas d’un robot tondeuse ou l’ID de l’appareil regroupe un nombre important d’IDs secondaires;c’est également le cas pour z2m: zb+.

    image1417

    image1977

    image1952

image1325

  • param : pour le type d’appareil (zwave ou Zigbee) et le json pour les souscription et publication mqtt(pour z2m pour l’instant).

    type matériel:payload de souscription:pyload de publication ex: zigbee:state:hue,saturation

    image1978

  • ls : lastseen, vu la dernière fois 1 si le dispositif est concerné plus d’infos : 1.8.2.1 Ecriture d’un script Dzvent(Dz) ou yaml(HA)

  • maj_jstypes de mise à jour java script
    • control // détecteur présence(on/off)

    • etat //porte, volet ,(closed/open)

    • temp // température, température + humidité, …..il est souvent préférable d’utiliser « data »

    • data // température, ph, M3/h, orp,…. toutes données ; .il est préférable d’utiliser « data »

    image473

    image93

    image94

    • onoff commandes

    • onoff+stop commandes (volets par exemple)

    • on // poussoir momentané (sonnette)

    • on_level //onoff + réglage une lumière sur une certaine couleur

    image1702

    image1405

    image1426

    • popup //ouverture d’une fenêtre (commandes particulières)

    extrait de mur_inter.php avec la fonction test_rgb()

    image1703

  • id1_html , Id2_html : id d’affichage html pour un idm, souvent 1 seul ID, le 2eme lorsque l’image comporte 2 zones avec le même style;si plus de 2 zones ou des styles différents, utiliser une classe(class_lamp), voir l’exemple ci-dessous

    image1777

    image1778

  • car_max_id1 : nb de caractères maximum affichés (concerne Data avec plusieurs données (T°,%hum)

  • F() N° case(1à99) de la fonction « pour_data() » , fichier fonctions.php

    . -1 : indique qu’un lien existe avec une variable à mettre à jour en temps réel; concerne des textes de notification comme pour l’alarme « activer ou désactiver »

    image1348

    . >0 : N° de la fonction à exécuter

    . 0 ou null : pas de fonction

    image1538

  • class_lamp : utilisé pour les lampes en plus de l’interrupteur associé ; c’est une class car il peut y avoir plusieurs lampes

  • coul_id1_id2_ON, coul_id1_id2_OFF, coul_lamp_ON, coul_lamp_ON : couleur des ID ou de la class des dispositifs suivant leur position, (class_lamp pour les lampes des différents interrupteurs)

  • pass : par défaut « 0 » pas de mot de passe , pwalarm pour mot de passe de l’alarme et pwcommand pour les commandes (on/off ,…)

  • doc : pour associer un document au dispositif

Important

exemple des scripts générés automatiquement

/* switchOnOff*  */

  $("#coul_sirene1").click(function(){switchOnOff_setpoint("2","13","231","On","0");});
  $("#coul_al_absence").click(function(){switchOnOff_setpoint("2","65","41","On","pwdalarm");});
  $("#coul_al_nuit").click(function(){switchOnOff_setpoint("2","66","42","On","pwdalarm");});
  $("#patha5645").click(function(){switchOnOff_setpoint("1","68","43","On","pwdalarm");});
  $("#coul_modect").click(function(){switchOnOff_setpoint("1","69","44","On","pwdalarm");});
  $("#raz_dz").click(function(){switchOnOff_setpoint("1","70","45","On","pwdalarm");});
  $("#sw8").click(function(){switchOnOff_setpoint("1","10","79","On","0");});
  $("#ping_pi").click(function(){switchOnOff_setpoint("1","14","80","On","0");});
  $("#coul_al_nuit-2").click(function(){switchOnOff_setpoint("2","15","81","On","pwdalarm");});
  $("#sw2").click(function(){switchOnOff_setpoint("1","11","85","On","0");});
  $("#gsm").click(function(){switchOnOff_setpoint("2","8","86","group on","pwdalarm");});
  $("#sw4").click(function(){switchOnOff_setpoint("1","16","167","On","0");});
  $("#sw1").click(function(){switchOnOff_setpoint("1","17","169","On","0");});
  $("#volet_bureau,#volet_bureau1").on("click", function (){$("#popup_vr").fadeIn(300);document.getElementById("VR").setAttribute("title","31");document.getElementById("VR").setAttribute("rel","177");})
  $("#act-sir").click(function(){switchOnOff_setpoint("2","36","230","On","pwdalarm");});
  $("#sw9").click(function(){switchOnOff_setpoint("1","73","307","On","0");});
  $("#sw10").click(function(){switchOnOff_setpoint("1","74","164","On","0");});
  $("#sw11").click(function(){switchOnOff_setpoint("1","9","407","On","0");});
  $("#sc1").click(function(){switchOnOff_setpoint("1","G1","417","On","0");});
  $("#sw12").click(function(){switchOnOff_setpoint("1","24","418","On","0");});
  $("#sw22").click(function(){switchOnOff_setpoint("1","76","448","On","0");});
  $("#sw21,#lamp_porche").click(function(){switchOnOff_setpoint("1","22","431","On","0");});
  $("#sw20").click(function(){switchOnOff_setpoint("1","77","306","On","0");});
  $("#sw23").click(function(){switchOnOff_setpoint("1","78","450","On","pwdcommand");});
  $("#SOS").click(function(){switchOnOff_setpoint("2","91","464","On","0");});
  $("#sw24").click(function(){switchOnOff_setpoint("1","79","465","On","0");});
  $("#sw3").click(function(){set_state("4","18","alias.0.zigbee2mqtt.0.0xb40ecfd30b7d0000","On","0");});
  $("#sw5").click(function(){set_state("4","19","","On","0");});

le script dans footer.php pour ajouter le javascript automatiquement:

<?php
require("fonctions.php");
if ($_SESSION["exeption_db"]=="" &&  DECOUVERTE==false)   {sql_plan('0');}
?>

le script dans fonctions.php pour créer automatiquement le javasript dans HTML:

function sql_plan($t1,$s="",$s1=""){global $L_dz, $l_dz, $L_ha, $l_ha,$L_iob, $l_iob, $L_zb, $l_zb, $IP_dz,$IP_ha,$IP_iob,$IP_zb,$idm_erreur;
          $n=0;$al_bat=0;$p=0;$l_mo="";//$l_mo , en attente de update
          //$row['nom_objet']=$s;return $row;
          // SERVEUR SQL connexion
          $conn = new mysqli(SERVEUR,UTILISATEUR,MOTDEPASSE,DBASE);
          if ($t1=='4')  {
          $sql="SELECT * FROM ".DISPOSITIFS." WHERE ID = '".$s."' AND Actif = '".$s1."' AND maj_js <> 'variable';";
          $result = $conn->query($sql);$n=0;$nb_rows=$result->num_rows;
      $ligne = $result->fetch_assoc();
          $ligne['zbplus']=$nb_rows;
  return $ligne;}
          else if ($t1=='3')  {
                  $sql="SELECT * FROM ".DISPOSITIFS." WHERE ID = '".$s1."' AND nom_objet = '".$s."' AND maj_js <> 'variable';";
                  $result = $conn->query($sql);
                  $row = $result->fetch_assoc();
            return $row;}
          else if ($t1=='2') {
          $sql="SELECT * FROM `".DISPOSITIFS."` WHERE ID = '$s' AND maj_js <> 'variable';";
          $result = $conn->query($sql);//if ($result === FALSE) {echo "pas id";return "";}
          $row = $result->fetch_assoc();
          return $row;}
          else if ($t1=='1')  {$error1=="";
          $sql="SELECT * FROM `".DISPOSITIFS."` WHERE idx = '$s' AND maj_js <> 'variable';";
          $result = $conn->query($sql);$nb_rows=$result->num_rows;
          if ($nb_rows<1) {$row =  ['idx' => $s,
                                                           'idm' => strval($idm_erreur),
                                                           'Actif' => '9',
                                                           'values' => 'non enregitré'
                                                          ];$idm_erreur++;}
          else {$row = $result->fetch_assoc();if ($row['idm']=="") {$row['idm']=NULL;}
                  if ($row['idm']===NULL) {$error1='enregitré sans idm';}
                  if ($row['car_max_id1']<1 || $row['car_max_id1']=='') {$error1='car_max_id1 qbsent';}
                  if ($error1!="") {$row =  ['idx' => $s,
                                                           'idm' => strval($idm_erreur),
                                                           'Actif' => '9',
                                                           'values' => $error1
                                                          ];$idm_erreur++;}
          }
          return $row;}
          else if ($t1=='5')  {
          $sql="SELECT * FROM ".DISPOSITIFS." WHERE idm= '".$s."'";
          $result = $conn->query($sql);$row = $result->fetch_assoc();return $row;
          }
          else if ($t1=='0') {
          $sql1="SELECT * FROM dispositifs WHERE (`maj_js` LIKE '%on%' AND `Actif` = ";
          if ($l_dz != "") {$u=2;
          $sql=$sql1.$u.");";$result = $conn->query($sql);
          while($row = $result->fetch_array(MYSQLI_ASSOC)){sql_1($row,'switches','dz');
          }
          }
      if ($l_ha != ""){$u=3;
          $sql=$sql1.$u.");";$result = $conn->query($sql);
          while($row = $result->fetch_array(MYSQLI_ASSOC)){sql_1($row,'switches','ha');
          }
          }
          if ($l_iob != ""){$u=4;
          $sql=$sql1.$u.");";$result = $conn->query($sql);
          while($row = $result->fetch_array(MYSQLI_ASSOC)){sql_1($row,'switches','iob');
          }
          }
          if ($l_mo != ""){$u=5;// en attente de mes
          $sql=$sql1.$u.");";$result = $conn->query($sql);
          while($row = $result->fetch_array(MYSQLI_ASSOC)){sql_1($row,'switches','mo');
          }
          }
          if ($l_zb != ""){$u=6;
                  $sql=$sql1.$u.");";$result = $conn->query($sql);
                  while($row = $result->fetch_array(MYSQLI_ASSOC)){sql_1($row,'switches','zb');
          }
          }
          return;}
          else echo "pas de serveur";
          }
          function sql_1($row,$f1,$ser_dom){
          $commande="On";$query="#";
          if ($row['maj_js']=="on"  && $ser_dom=="dz"){$commande="group on";}
          if ($row['maj_js']=="on_level" && $ser_dom=="dz"){$commande="Set Level";}
          if ($row['maj_js']=="on="){$query=".";$f='var command=$(this).attr("rel");'.$f1;$commande="command";}
          else $f=$f1;
          if ($row['Actif']=="6"){$str=explode(':',$row['param']);$commande=$str[1];}
          $id_dom=$row['ID'];$id_dom=str_replace("\r\n","",$id_dom);
          if($ser_dom=="dz"){$id_dom=$row['idx'];}
          if($row['id1_html']!='' && $row['id1_html']!='#' ){$s='$("'.$query.$row["id1_html"];
          if($row['id2_html']!=''){$s=$s.','.$query.$row['id2_html'];}
          if ($row['maj_js']=="onoff+stop") {$sl='").on("click", function (){$("#popup_vr").fadeIn(300);
          document.getElementById("VR").setAttribute("title","'.$row['idm'].'");document.getElementById("VR").setAttribute("rel","'.$row['idx'].'");})';}
  if ($row['maj_js']=="on=") {$sl='").click(function(){'.$f.'("'.$row['Actif'].'","'.$row['idm'].'","'.$id_dom.'",command,"'.$row['pass'].'");});';}
          else {$sl='").click(function(){'.$f.'("'.$row['Actif'].'","'.$row['idm'].'","'.$id_dom.'","'.$commande.'","'.$row['pass'].'");});';}
          $s=$s.$sl;
          echo $s."\r\n" ;}
          return;
          }

Voir chapitre 1. Configuration minimum : la page d’accueil

Il est possible d’ajouter des types

Pour créer cette table l’importer depuis le référentiel « monitor »

0.3.3 caméras

On crée une table dans la base de données : cameras

Si l’on veut un accès extérieur il est utile d’indiquer également le domaine; Si l’on utilise Zoneminder, il est nécessaire d’assurer la correspondance des Numéros de dispositifs

image98

  • num : n° auto incrémenté pour faciliter les modifications

  • Idx : N° idx celui qui correspond au onclick du plan,

  • Id_zm : optionnel, utilisé avec Zoneminder, option à définir dans admin/config.php

  • id_fr : optionnel utilisé avec Frigate, option à définir dans admin/config.php

  • Ip : IP locale

  • url : url locale de la caméra

  • marque : dahua ou generic, option à définir dans admin/config.php

  • type : VTO ou vide concerne uniquement les portier VTO Dahua

  • localisation :

téléchargement de la table « cameras.sql » : https://raw.githubusercontent.com/mgrafr/monitor/main/bd_sql/cameras.sql

0.3.4 Autres tables SQL

0.3.4.1 Table 2fa_token pour l’Authentification 2 étapes

voir le Paragraphe 1.9.1.3.b la table SQL 2fa_token

image1682

0.3.4.2 Tables perso

Enregistrements de températures, tension ,….

image99

Exemple pour une table temp_meteo :

-- Structure de la table `temp_meteo`
--
CREATE TABLE `temp_meteo` (
  `num` int(11) NOT NULL,
  `date` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `valeur` varchar(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
-- Index pour la table `temp_meteo`
ALTER TABLE `temp_meteo`
  ADD PRIMARY KEY (`num`);
-- AUTO_INCREMENT pour la table `temp_meteo`
ALTER TABLE `temp_meteo`
  MODIFY `num` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=21294;
COMMIT;
  • num : n° auto incrémenté pour faciliter les modifications

  • date : la date et l’heure

  • valeur : la température

0.3.5 Configurer MariaDB pour les connexions distantes

Les fichiers de configuration à modifier :

image1539

cd /etc/mysql/mariadb.conf.d/
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

image1540

Important

  • Pour MariaDB version 10.11 et supérieure , vous pouvez spécifier une liste d’adresses IP séparées par des virgules:

    bind-address = 10.0.0.1,10.0.1.1,10.0.2.1

  • Pour MariaDB version inférieure à 10.11 :

    bind-address = 0.0.0.0 , vous pouvez vous lier à toutes les adresses IP disponibles

Redémarrer

sudo service mariadb restart

0.4 Serveur Nginx & Fichiers de configuration

image101

0.4.1 Un seul fichier de configuration

Configuration de monitor : /admin/config.php

Extrait du fichier, fichier complet : https://raw.githubusercontent.com/mgrafr/monitor/main/admin/config.php

<?php
// NE PAS MODIFIER LES VALEURS EN MAJUSCULES------
//general monitor
define('URLMONITOR', 'monitor.xxxxxxx.ovh');//domaine
define('IPMONITOR', '192.168.1.7');//ip
define('MONCONFIG', 'admin/config.php');//fichier config
define('DZCONFIG', 'admin/dz/temp.lua');//fichier temp
define('FAVICON', 'favicon.ico');//fichier favicon  , icone du domaine dans barre url
// répertoire des images
$rep='images/';//ne pas changer
// images logo et titres
define('IMAGEACCUEIL', $rep.'maison.jpg');//image page accueil pour écrans >534 px
define('IMAGEACCUEILSMALL', $rep.'maison_small.jpg');//image page accueil pour écrans <535 px
define('IMGLOGO', $rep.'logo.png');//image logo
define('NOMSITE', 'Domoticz');//nom principal du site
define('NOMSLOGAN', xxxxxx');//nom secondaire ou slogan
//

Les fichiers à la racine du site :

image103

  • ajax.php : appels ajax depuis javascript, explications dans les divers paragraphes

    extrait du script :

<?php
require ("fonctions.php");
$retour=array();
//POST-------------------
$appp = isset($_POST['appp']) ? $_POST['appp'] : '';
$variablep = isset($_POST['variable']) ? $_POST['variable'] : '';
$commandp = isset($_POST['command']) ? $_POST['command'] : '';
//GET----------------------
$app = isset($_GET['app']) ? $_GET['app'] : '';
$idx = isset($_GET['idx']) ? $_GET['idx'] : '';
$device = isset($_GET['device']) ? $_GET['device'] : '';
$name = isset($_GET['name']) ? $_GET['name'] : '';
$variable = isset($_GET['variable']) ? $_GET['variable'] : '';
$command = isset($_GET['command']) ? $_GET['command'] : '';
$type = isset($_GET['type']) ? $_GET['type'] : '';
$table = isset($_GET['table']) ? $_GET['table'] : '';
// APPEL A des FONCTIONS PHP 'fonctions.php
if ($app=="aff_th") {$retour= status_devices($device,'Temp','Humidity');echo json_encode($retour); }
else if ($app=="devices_plan") {if (DECOUVERTE==true) {include('include/json_demo/devices_plan_json.php');return;}
     else {$retour=devices_plan($variable);echo json_encode($retour); }}
else if ($app=="turn") {$retour=devices_id($device,$command);echo $retour; }
else if ($app=="OnOff") {$retour=switchOnOff_setpoint($device,$command,$type,$variable,$name);echo json_encode($retour); }
else if ($app=="meteo_concept") {if (DECOUVERTE==true) {include('include/json_demo/meteo_concept_json.php');return;}
     else {echo $retour=meteo_concept($variable); }}
  • Cookies.txt & cookie.txt : utilisés par Zoneminder suivant les versions de l’API

  • favicon.ico : l’icône associée à la barre de l’url

  • fonctions.php : toutes les fonctions PHP appelées au démarrage et lors des appels Ajax

  • Index.php : le ficher appelé lors du chargement du site ; pour les écrans > 768x1024 ce fichier gère un affichage de 768x1024 appelant la page dans une iframe ; Pour appeler cette page :

    • en local :<IP>/monitor

    • en distant : <DOMAINE>

<?php
session_start();
echo '<!DOCTYPE html><html><body style="background-color: cornsilk;">';
$rep="/"; $domaine=$_SERVER['HTTP_HOST'];$port=$_SERVER['SERVER_PORT'];
$seg = $_SERVER['REQUEST_URI'];
$reg=str_replace('/monitor/','',$seg);
$reg=str_replace('?','',$reg);
$_SESSION["conf"]=$reg;
if (substr($domaine, 0, 7)=="192.168") $rep="/monitor/";
header('Location: '.$rep.'index_loc.php');
exit();
?>
  • Index_loc.php : la page d’accueil réelle du site ; sauf pour ajouter des pages non incluses dans le programme, ne pas modifier ce fichier.

image106

image1764

0.4.2 Un fichier de configuration par écran de contrôle

A partir du fichier de configuration principal, faire une ou plusieurs copie(s) dans le répertoire admin en le(s) nommant:

index_<config_<EXT>.php ex: config_1.php, config_essai.php

Dans le PC, la tablette,… appeler monitor en précisant <EXT> de la config

<IP de Monitor>/monitor?:red:<EXT> , exemple 192.168.1.113/monitor?1, 192.168.1.113/monitor?essai

image1679

La configuration choisie est placé dans une variable de session et dans un cookie:

image1680

POur supprimer le cookie et revenir à la configuration par défault:

image1880

Le Javascript dans footer.php

image1881

image1882

0.5 Le Framework BULMA

Remplace Bootstrap depuis la version 4.1.3

Pour des mises en page faciles, des fenêtres modales ,…..

image107

0.6 Les styles CSS

image108

Note

le fichier styles.php concerne des styles modifiableS par php, par exemple l’image d’accueil

image1230

Un extrait de mes_css.css :

body {
    font-size: 15px;
    line-height: 1.50;
    color: #333333;
    position: relative;
    font-family: 'Open Sans', sans-serif;
}
html, body {height: 100%;}
.table td{border:0}
#menu {width:17em;}
#maison1{margin-top:12%;}
.header {height: 150px;color: #ffffff;background-color: rgba(8, 55, 70, 0.7);
     padding: 10px 0;-webkit-transition: all 0.2s ease-in-out;
     -moz-transition: all 0.2s ease-in-out;  -o-transition: all 0.2s ease-in-out;
     -ms-transition: all 0.2s ease-in-out;

Les Media queries pour les différents écrans

image110

0.7 Les images

Toutes sont au format svg ou webp sauf les caméras

Note

Avantages du format SVG Les images SVG peuvent être créées et modifiées un éditeur de texte Les images SVG peuvent contenir du javascript Les images SVG sont zoomables Les graphiques SVG ne perdent aucune qualité s’ils sont zoomés ou redimensionnés SVG est open source Les fichiers SVG sont du pur XML

image111

Webp est un format d’image moderne qui offre une compression supérieure avec perte et sans perte pour les images du Web

Les caméras sont au format jpg :

image112

0.8 Les fichiers PHP

Ils sont regroupés dans le dossier « include », sauf - fonctions.php, ajax.php, à la racine de monitor - /admin/config. PHP - /jpgraph

image113

Affichage de graphique avec jpgraph

image114

fonctions.php est le fichier le plus important du serveur; il regroupe toutes les fonctions et organise l’appel des serveurs domotique (Domoticz,Home Assistant et io.broker) indépendamment de l’ordre choisi dans admin/config.php

image1500

0.9 Les fichiers Javascript & Python

Utilisation de jQuery

image115 image116

0.10 API Domoticz , Home Assistant & Io.Broker

pour les dispositifs :

DZ : URL:PORT/json.htm?type=getdevices&plan=NUMERO DU PLAN

HA : URL:8123/api/states

IOB :

  • URL:8093/v1/objects?filter=zigbee2mqtt.0*&type=device

  • URL:8093/v1/states?filter=zigbee2mqtt.0.0x00124b002228d561.*

Attention

le dispositif doit être du type device dans IOB; dans le cas contraire (state) , le modifier:

image1412

pour les variables (input_text pour HA):

DZ : URL:PORT/json.htm?type=command&param=getuservariables

HA : URL:8123/api/states/sensor.liste_var

Note

un unique_id du sensor doit être indiqué , voir ce paragraphe 1.8.2.1 Ecriture d’un script Dzvent ou yaml

image1365

Dans les 2 cas, l’API concernée envoie un fichier json de tous les dispositifs ou les variables.

……..ha, un dispositif :

image97

Important

pour Home Assistant ,un jeton est obligatoire; pour faire des essai avec un navigateur, utiliser un client pour API comme par exemple ci dessous l” addon RESTer:

image1364

0.11 Les fichiers ajoutés par l’utilisateur

4 sous dossiers sont créés pour ajouter des pages personnelles avec les styles , les images et le Javascript

image102

0.11.1 javascript d’une page perso

Exemple de fichier custom/JS.js

// JavaScript Document

function custom_js(){
if (typeof custom != 'undefined' & custom==1) {
     worx=pp[200].value;maj_worx(pp[200].Name,pp[200].Data);}
}

la fonction custom_js est réservée; elle est appelée si besoin dans la fonction devices_plan() (mise à jour des dispositifs)

voir également les § 21.14.4 Le Javascript concerné et 1.3.5.2 Quelques infos supplémentaires

0.12 API de monitor

Pour l’utiliser, dans admin/config.php: mettre sur true

image118

Appel GET : http://192.168.1.9/monitor/api/json.php?<DATA>

image407

le fichier conf.php est un lien symbolique de config.php

image1751

0.12.1 Les fonctions possibles

  • app== »messages » : function message($contenu,$nom,$maj)

    image1275

    maj=1

  • app== »maj » : maj($id,$state)

    mise à jour temps réel SSE-PHP

    voir les § 18.10.2 L’API de monitor & 18.10.3 L’API de monitor depuis HA ou DZ

  • app== »api_rest_ha » : envoi_data($name)

    uniquement pour Home Assistant

image1276

l” API renvoi un objet de Monitor , voir la fonction /api/f_pour_api/envoi_data()

  • app== »envoi_sms » : sms($contenu)

ex: http://<IP_MONITOR>/monitor/api/json.php?app=envoi_sms&contenu=pour_essai

voir le $ 18.12.1 Envoi de notifications par SMS

0.13 Les fichiers JSON reçu par monitor

Utilisé par les fonctions javascript dans /include/footer.php:

function maj_services(index)

image1216

function maj_devices(plan)

image1217

function maj_mqtt(id_x,state,ind,level,champ=””) ; retour json pour une correspondance idm : idx ou id

image1218

function pluie(idx)

image1219

function mc(variable,id)

image1221

image1220