18. Divers ------------ 18.1 Debian : Installer un serveur LAMP (Apache MySQL PHP) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image983| https://www.linuxtricks.fr/wiki/debian-installer-un-serveur-lamp-apache-mysql-php 18.2 Installer Paho-mqtt ^^^^^^^^^^^^^^^^^^^^^^^^ *paho-mqtt est le code source pour la bibliothèque Python MQTT* .. code-block:: sudo pip3 install paho-mqtt 18.2.1 Le script pour envoyer des messages (mqtt.py) ==================================================== .. code-block:: #!/usr/bin/env python3.7 # -*- coding: utf-8 -*- import paho.mqtt.client as mqtt import json import sys # Variables et Arguments topic= str(sys.argv[1]) etat= str(sys.argv[2]) valeur= str(sys.argv[3]) MQTT_HOST = "192.168.1.42" MQTT_PORT = 1883 MQTT_KEEPALIVE_INTERVAL = 45 MQTT_TOPIC = topic MQTT_MSG=json.dumps({etat: valeur}); # def on_publish(client, userdata, mid): print ("Message Publié...") def on_connect(client, userdata, flags, rc): client.subscribe(MQTT_TOPIC) client.publish(MQTT_TOPIC, MQTT_MSG) def on_message(client, userdata, msg): print(msg.topic) print(msg.payload) payload = json.loads(msg.payload) # convertion en json print(payload['state_l2']) client.disconnect() # Initiatlisation MQTT Client mqttc = mqtt.Client() # callback function mqttc.on_publish = on_publish mqttc.on_connect = on_connect mqttc.on_message = on_message # Connection avec le serveur MQTT mqttc.connect(MQTT_HOST, MQTT_PORT, MQTT_KEEPALIVE_INTERVAL) # Loop forever mqttc.loop_forever() .. IMPORTANT:: Pour être sûr que le fichier est au bon format (Unix) : utiliser dos2unix , § :ref:`8.2.1.1 Problème de lecture de fichier` 18.3 Liaison série Domoticz-PI ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Voir aussi le § :ref:`21.1.10 Liaison directe PROXMOX-PI5` qui concerne une liaison PC-PC directe en ethernet *Scripts dans Domoticz* Ils sont exécutés en dehors du conteneur si Domoticz est sous Docker. .. attention:: **La passerelle Zigbee 3.0 SonOff utilise le même driver série CP2102 -donc pour /dev/serial/by-id = IDENTIQUE** - **sms_dz.py** : https://raw.githubusercontent.com/mgrafr/monitor/main/share/scripts_dz/py/sms_dz.py |image987| .. note:: *Modifier si besoin le numéro de la variable et le port de domoticz* Le démarrage automatique est assuré par systemd (voir § :ref:`13.6.2.1 Enregistrement des n° de téléphone` .. seealso:: *voir http://domo-site.fr/accueil/dossiers/70 *(liaison série)* - **aldz.py** voir § :ref:`13.6.2 émission SMS` |image988| aldz.bak.dz, en absence de message |image989| .. admonition:: **Scripts PI** - **rec_sms_serie.py** : https://raw.githubusercontent.com/mgrafr/monitor/main/share/scripts_PI8/rec_sms_serie.py extrait: |image990| .. IMPORTANT:: :red:`Utiliser localhost et non 127.0.0.1` .. warning:: **Si ce massage en bash** |image991| C'est un problème de mot de passe |image992| |image993| - *start_rec_sms.sh** |image994| Démarrage auto avec systemd : .. code-block:: [Unit] Description=start rec sms pour Domoticz [Service] Type=simple ExecStart=/home/michel/start_rec_sms.sh Restart=on-failure RestartSec=10 KillMode=process [Install] WantedBy=multi-user.target 18.4 Commandes de l’alarme à partir d’un GSM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *Pour faciliter l’activation ou l’arrêt de l’alarme* il est facile d’ajouter des codes au script du paragraphe précédent :ref:`18.3 Liaison série Domoticz-PI` Extrait de **rec_sms_serie.py** installé sur le PI qui assure le monitoring , les notifications GSM et les sauvegardes ù .. code-block:: if params[0]=="Alon": domoticz=ip_domoticz ip_se=1 params[1]= '41' params[2]='switch' params[3]='On' if params[0]=="Aloff": domoticz=ip_domoticz ip_se=1 params[1]= '41' params[2]='switch' params[3]='Off' .. note:: :red:`Alon et Aloff` = Marche/Arrêt de l'alarme |image996| Le switch domoticz : |image997| voir le $ :ref:`5.1 Dans Domoticz, les interrupteurs virtuels, les variables` 18.5 Données compteur Linky ^^^^^^^^^^^^^^^^^^^^^^^^^^^ *Configuration après installation du plugin: https://github.com/guillaumezin/DomoticzLinky* |image998| .. Important:: Pour la correspondance avec ENEDIS : Ne pas copier toute l'adresse http, s’arrêter après le code |image999| |image1000| - **Dans monitor** |image1001| |image1002| .. seealso:: § :ref:`15.1 ajout d’un dispositif` |image1003| .. seealso:: § :ref:`6. GRAHIQUES & BASE DE DONNEES` - **Les modifications dans Domoticz** *export_sql* pour enregistrer dans la BD SQL, voir § :ref:`6.2 Dans Domoticz` .. admonition:: **Avec Lua** |image1004| .. admonition:: **Avec DzVent & l'API Domoticz** counter et usage du Device sont restés bloqués au jour ou le plugin s'est arrêté lors d'une mise à jour ENEDIS.j'ai donc utilisé l'API et item.result.json.Counter & item.result.json.Usage.L'utilisation de l'API peut être utilisée lors d'autres occasions.Le port de mon Domoticz est 8086 avec une IP 192.168.X.X mais Domotice est installé sous Docker d'où l'adresse 127.0.0.1:8080. |image1215| .. code-block:: local function split(s, delimiter) local result = {} for match in (s..delimiter):gmatch('(.-)'..delimiter) do table.insert(result, match) end return result end --function tointeger( x ) -- num = tonumber( x ) -- return num < 0 and math.ceil( num ) or math.floor( num ) --end function envoi_fab(don) local command = "/bin/bash userdata/scripts/bash/./fabric.sh"..don.." > /home/michel/fab.log 2>&1"; os.execute(command); end function round(num,numDecimal) local mult = 10^(numDecimal or 0) return math.floor(num * mult + 0.5) / mult end -- local scriptVar = 'linky_sql' return { on = { timer = {'at 16:12'}, httpResponses = { scriptVar }}, logging = { level = domoticz.LOG_ERROR, marker = scriptVar }, execute = function(dz, item) if (item.isTimer) then local url = 'http://127.0.0.1:8080/json.htm?type=command¶m=getdevices&rid=427'; print(url); dz.openURL({ url = url, method = 'GET', callback = scriptVar, }) end if (item.isHTTPResponse ) then local results = item.json.result -- loop through the nodes and print some info for i, node in pairs(results) do print('Data'.. node.Data);m=split(node.Data, ';') local mCounter = m[1] ; print("compteur_kwh:"..mCounter);--mCounter=tointeger(mCounter)/1000; local mUsage = m[5] ; print("compteur_kw:"..mUsage) ; libelle="energie#conso" don=" "..libelle.."#"..tostring(round(tonumber(mCounter)/1000,1)) .."#"..datetime.."#pmax#"..tostring(round(tonumber(mUsage)/1000,1)); print("energie"..don); envoi_fab(don) end end end } |image1005| - **Le compteur est ajouté au plan** , les données sont disponibles pour monitor : voir § :ref:`1.2.1.1 status_variables , devices_zone et device_plan` - **Table dispositifs** : *création du dispositif* |image1006| .. seealso:: le § :ref:`0.3.2 Les Dispositifs` - **Table energie** : création de la table |image1007| voir un exemple : :ref:`17.1.2. Création des tables PH, Redox, temp, ...` - **Fichier json** envoyé par domoticz : |image1008| .. admonition:: **Les fichiers modifiés dans monitor** - **Interieur.php** : *ajout de l’image svg* .. code-block::
|image1009| - **graphiques.php** |image1010| 18.6 Complément sur l’utilisation des Mots de Passe cryptés dans Domoticz ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *Une des solutions pour crypter et décrypter les mots de passe* .. seealso:: Codage : https://www.base64encode.org/ |image1011| - **Décodage** , *Extrait du script maj-services.lua* .. code-block:: -- chargement fichier contenant les variables de configuration package.path = package.path..";www/modules_lua/?.lua" require 'connect' local base64 = require'base64' local user_free = base64.decode(login_free);local passe_free = base64.decode(pass_free); local sms_free="curl --insecure 'https://smsapi.free-mobile.fr/sendmsg?user="..user_free.."&pass="..passe_free.."&msg=poubelle' >> /home/michel/OsExecute.log 2>&1" voir ce § :ref:`14.6.1.1 connect.lua` 18.7 pages sans rapport avec la domotique ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 18.7.1 Les recettes de cuisines sur la tablette domotique ========================================================== |image1015| .. important:: **Comme pour chaque ajout de page , il faut modifier les fichiers** : - mes.css.css - config.php - index_loc.php - header.php *et parfois le fichier* :darkblue:`big-Slide.js` , si l’on doit modifier la largeur du menu § :ref:`1.7 Ajuster le menu au nombre de pages` |image1016| - **le fichier recettes.php** https://raw.githubusercontent.com/mgrafr/monitor/main/include/recettes.php |image1018| - **Dans fonctions.php** *sql_app()* |image1019| 18.8 migration de Domoticz différentes étapes pour ne rien oublier ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. admonition:: **Exemple migration vers Docker .** - faire une suvegarde e la base de bonnées domoticz.db - Modifier les IP/PORT de Domoticz, Zwavejs2mqtt, Zigbee2mqtt,…dans le fichier de configuration de monitor. - Pour les scripts externes non gérés dans le conteneur Domoticz ,installer les versions de python, node, … nécessaires, et les dépendances nécessaires ;par exemple pour la communication série de Domoticz , l’installation de :darkblue:`python-periphery` , de :darkblue:`fabric` pour l'export des données,de :darkblue:`paho-mqtt` pour les topic mqtt,.. , le démarrage auto sur systemd ,…. Si l’API de Domoticz est utilisée dans ces scripts , modifier le Port de Domoticz |image1278| - Pour les scripts ajoutès à des dispositifs, modifer le chemin: |image1320| - Pour VOIP asterisk, modifier ip de domoticz pour la capture d’image (portier) ; pour appeler json de Domoticz depuis Docker, autoriser dans les paramètres de Domoticz le réseau 172.*.*.* |image1321| - Pour le monitoring Nagios, il faut indiquer les IP/PORT qui sont modifiés et les noms des VM Proxmox si Proxmox est utilisé. - Si une nouvelle page doit être ajoutée à monitor, par exemple pour Zwave (OZW n’étant plus maintenu) : créer le sous-domaine pour l’accès distant et le certificat pour HTTPS (Letsencrypt-cerbot) - Les dispositifs sont souvent difficiles à réveiller, s’ils sont réinstallés, modifier l’ID de Domoticz dans la base de données de monitor - Pour les cripts LUA ou DzVent sous Docker le fichier Config s'appelle userdata; les sous répertoires sont attachés à Config et non directement à domoticz . |image1279| .. admonition:: **Exemple migration vers un conteneur LXC .** Si aucune clés Zwave ou Zigbee ne sont installés sur le conteneur (Zigbee2mqtt et Zwave-JS-UI sont installés dans des conteneurs séparés), l'installation se résume à installer Curl et à lancer la commande bash: .. code-block:: apt install curl sudo bash -c "$(curl -sSfL https://install.domoticz.com)" - Pour une migration depuis Docker, lire le § précédent et modifier les scripts Lua et DZvent pour revenir à un schéma classique des répertoires. - Installer les modules Python(:darkblue:`python-periphery`, :darkblue:`fabric`, :darkblue:`paho-mqtt`...) , les modules nodejs (:darkblue:`lgtv`, :darkblue:`superagent`, ...) .. warning:: le port sous docker peut être différent alors que sous LXC c'est le même |image1281| - Une sauvegarde suivi d'un backup sur le nouveau serveur et Domoticz sera de nouveau opérationnel. **Si une clé USB est installée, ne pas oublier de la déconnecter d'une machine virtuelle sinon elle n'apparaitra pas avec** :darkblue:`ls -ln /dev/ttyUSB*` .. admonition:: **Pour tout changement de serveur.** Ne pas oublier d'exporter les scripts Debian, de les modifier si besoin (:red:`sup config pour domoticz auparavant sous docker` )exemple: **Systemd**: |image1304| |image1305| Si un serveur HA BRIDGE est installé, ne pas oublier de changer les IP des dispositifs (changer l'IP su serveur Domoticz ne suffit pas) |image1307| .. warning:: la version 2024.1 ne fonctionne pas sous Debian 12 qui utilise openssl 3.0 (domoticz utilise opebssl 1.1) 18.9 des commandes linux & yaml utiles ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 18.9.1 Commandes Linux ====================== - Le port est déjà utilisé : .. code-block:: lsof -i tcp: kill -9 |image1264| - Pour modifier le fuseau horaire d'un serveur Linux (ex: UTC+2), il suffit d'exécuter la commande suivante : .. code-block:: timedatectl set-timezone Europe/Paris |image1277| - Pour publier un message sur Mosquitto: .. code-block:: mosquitto_pub --username NOM --pw MOT_PASSE -t 'TOPIC' -m 'MESSAGE' |image1322| - Pour éviter de redémarrer après modification de fstab, ... .. code-block:: systemctl daemon-reload |image1301| 18.9.2 Commandes yaml ===================== **split** *divise une chaîne en une liste de chaînes* split(‘caractère de séparation pour créer liste’)[indice dans la liste [0]=1er] Exemple : :darkblue:`binary_sensor.pir_salon` --> :green:`pir_salon` .. code-block:: {{trigger.entity_id.split('.')[1] }}" 18.9.3 Commandes Python ======================= - Pour installer un package Python non disponible avec pip et apt Télécharger le code source , faire un build suivi d'un install: exemple pour Python-mysql-connector .. code-block:: # télécharger la source ,ici sur le site de mysql :https://dev.mysql.com/downloads/connector/python/ wget https://cdn.mysql.com//Downloads/Connector-Python/mysql-connector-python-9.1.0-src.tar.gz gzip mysql-connector-python-9.1.0-src.tar.gz -d tar -x -f mysql-connector-python-9.1.0-src.tar cd mysql-connector-python-9.1.0-src cd mysql-connector-python python3 setup.py build python3 setup.py install |image1550| |image1551| 18.9.4 Commandes Debian ======================= .. admonition:: **wireless-tools : configuration wifi** https://wiki.debian.org/WiFi/HowToUse .. code-block:: apt remove network-manager wicd apt update && apt-get install wpasupplicant wireless-tools |image1737| .. admonition:: **Wifi , mode Ad-Hoc** https://wiki.debian.org/WiFi/AdHoc **Sur Debian 12 et Proxmox** Rechercher le nom de l'interface wifi .. code-block:: iwconfig |image1742| Modifier l'interface de chacun des noeuds sans-fil; si le 2eme noeud est un Raspberry , voir ci- après le mode d'emploi à utiliser. .. code-block:: nano /etc/network/interfaces Ajouter ces lignes: .. code-block:: auto wlan0 # interface de iwconfig iface wlan0 inet static # modifier l'interface trouvée acec iwconfig address 192.168.x.x # IP à modifier netmask 255.255.255.0 wireless-channel 1 # channel identique pour les 2 noeuds wireless-essid MYNETWORK # nom du Réseau wireless-mode ad-hoc |image1743| Sur chacun des noeuds, activer l'interface .. code-block:: ifup |image1744| *Pour le 2eme noeud seul l'IP est à modifier* **sur Rasbian rpi5 : executer**, .. code-block:: nmtui |image1738| |image1739| |image1740| |image1741| Activer l'interface wifi |image1745| Autre façon d'activer l'interface : .. code-block:: sudo ifconfig wlan0 up **Scannez à la recherche des cellules ad-hoc à portée** |image1746| |image1747| **Pour tester, effectuez un "ping" du noeud A à partir du noeud B** : |image1748| 18.10 Serveur SSE installé dans Monitor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pour communiquer entre les diverses applications (Domoticz, Home Assistant, les Clients et le serveur Web) nous utiliserons la base de données SQL; nous créons une nouvelle table avec un enregistrement: .. code block:: CREATE TABLE `sse` ( `num` int(1) NOT NULL, `id` varchar(20) NOT NULL, `state` varchar(5) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; INSERT INTO `sse` (`num`, `id`, `state`) VALUES (0, '0', ''); COMMIT; ce fichier sse.sql peut être importé depuis le référentiel. |image1265| 18.10.1 Le serveur SSE PHP =========================== fichier :darkblue:`serveur_sse.php` .. code-block:: header('Connection: keep-alive'); header("Access-Control-Allow-Origin: *"); require_once('../fonctions.php'); ignore_user_abort(true); // Empêche PHP de vérifier la déconnexion de l'utilisateur connection_aborted(); // Vérifie si l'utilisateur s'est déconnecté ou non // en cas de reconnexion du client, il enverra Last_Event_ID dans les en-têtes // ceci n'est évalué que lors de la première requête et de la reconnexion ultérieure du client $lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0); if ($lastEventId == 0) { $lastEventId = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : false); } // conserve également notre propre dernier identifiant pour les mises à jour normales mais favorise last_event_id s'il existe // puisqu'à chaque reconnexion, cette valeur sera perdue // Get the current time on server date_default_timezone_set('Europe/Paris'); $currentTime = date("H:i:s", time()); $event= 'message'; if(connection_aborted()){ exit();} // importation des données si il en existent de nouvelles $donnees=[ 'command'=> '5', 'id' => "", 'state' => "", 'date' => $currentTime ]; $retour=mysql_app($donnees); $d = array("heure"=>$currentTime, "id"=>$retour['id'], "state"=>$retour['state']); $id=$retour['id']; if($id !="" ){ echo "event: " . $event . "\n"; echo "data: ".json_encode($d)." \n\n"; ob_flush(); flush(); $donnees1=[ 'command'=> '6', 'id' => "", 'state' => "" ];mysql_app($donnees1); } else sleep(SSE_SLEEP); ?> |image1266| Le client reçoit: |image1223| 18.10.2 L'API de monitor ========================= 18.10.2.1 Mise à jour des dispositifs """"""""""""""""""""""""""""""""""""" *http://192.168.1.9/monitor/api/json.php?app=maj&id=xxx&state=XX* la fonction :darkblue:`maj()` dans /api/f_pour_api.php .. code-block:: function maj($id,$state){ $donnees=array(); $donnees=[ 'command'=> '4', 'id' => $id, 'state' => $state, 'date' => date("H:i:s", time()) ]; mysql_app($donnees); return 'OK'; } la fonction mysql_app() dans /fonctions.php |image1267| 18.10.3 L'API de monitor depuis HA ou DZ ========================================= 18.10.3.1 depuis Domoticz """""""""""""""""""""""""" .. code-block:: package.path = package.path..";www/modules_lua/?.lua" require 'connect' -- fichier contenant l'IP de monitor function send_sse(txt,txt1) local api_mon="curl --insecure 'http://'..ip_monitor..'/monitor/api/json.php?app=maj&id="..txt.."&state="..txt1.."' > sse.log 2>&1" os.execute(api_mon) end |image1302| 18.10.3.2 depuis Home Assistant """""""""""""""""""""""""""""""" Dans configuration yaml, la :darkblue:`rest_command` .. code-block:: rest_command: monitor_2: url: "http://192.168.1.9/monitor/api/json.php?app=maj&id={{id}}&state={{value}}" Dans automations.yaml, .. code-block:: action: - service: rest_command.monitor_1 data: value: "{{ trigger.to_state.state }}" id: "{{ trigger.entity_id }} " 18.11 Comment générer des clés SSH ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 18.11.1 Générer une clé SSH =========================== 2 algorithmes sont utilisés pour générer des clés d’authentification : - RSA – Une clé RSA SSH est considérée comme hautement sécurisée de 2048 ou 4096 bits. Compatible avec les anciens systèmes d’exploitation. - Ed25519 – plus moderne avec une taille de clé standard plus petite de 256 bits. Aussi sûr et efficace qu’une clé RSA en raison de ses propriétés cryptographiques. Avec la console : .. code-block:: ssh-keygen -t ed25519 |image1565| Le fichier de clé publique doit avoir une extension PUB. Les clés privées RSA se terminent RSA . Le fichier pour Ed25519 n’a pas d’extension |image1566| 18.11.2 Vérifier que openssh-client est installé sur l'IP distante ================================================================== .. code-block:: apt-cache show openssh-client |image1568| 18.11.3 Transfert de la clé publique SSH vers un serveur distant ================================================================ .. code-block:: ssh-copy-id @ |image1567| 18.12 Complément sur l'API Monitor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 18.12.1 Envoi de notifications par SMS ======================================= *http://192.168.1.9/monitor/api/json.php?app=envoi_sms&contenu=xxxxxxxxxxxxxxx* la fonction :darkblue:`sms()` dans /api/f_pour_api.php .. code-block:: function sms($contenu){ $file="/www/monitor/python/aldz.py"; $content="#!/usr/bin/env python3 -*- coding: utf-8 -*- x='".$contenu."' priority=0"; file_put_contents($file,$content); return "envoi_sms:"; |image1640| le richier sms_mo.py : :darkblue:`https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/share/python/sms_mo.py` le fichier sms_mo.service , pour un démarrage automatique: :darkblue:`https://raw.githubusercontent.com/mgrafr/monitor/refs/heads/main/share/python/sms_mo.service` 18.13 Glossaire ^^^^^^^^^^^^^^^ .. admonition:: **Points de données ou data points** Ce sont des chaînes uniques de données envoyée par un dispositif, un compteur ou un capteur installé dans une maison. .. admonition:: **timestamp et horodatage** Un timestamp désigne un compteur numérique représentant une quantité de temps écoulée depuis un instant de référence, comme dans le système de l'heure Unix .. |image983| image:: ../media/image983.webp :width: 200px .. |image987| image:: ../media/image987.webp :width: 700px .. |image988| image:: ../media/image988.webp :width: 468px .. |image989| image:: ../media/image989.webp :width: 412px .. |image990| image:: ../media/image990.webp :width: 645px .. |image991| image:: ../media/image991.webp :width: 644px .. |image992| image:: ../media/image992.webp :width: 413px .. |image993| image:: ../media/image993.webp :width: 643px .. |image994| image:: ../media/image994.webp :width: 410px .. |image996| image:: ../media/image996.webp :width: 700px .. |image997| image:: ../media/image997.webp :width: 400px .. |image998| image:: ../media/image998.webp :width: 570px .. |image999| image:: ../media/image999.webp :width: 601px .. |image1000| image:: ../media/image1000.webp :width: 596px .. |image1001| image:: ../media/image1001.webp :width: 700px .. |image1002| image:: ../media/image1002.webp :width: 650px .. |image1003| image:: ../media/image1003.webp :width: 519px .. |image1004| image:: ../media/image1004.webp :width: 596px .. |image1005| image:: ../media/image1005.webp :width: 478px .. |image1006| image:: ../media/image1006.webp :width: 700px .. |image1007| image:: ../media/image1007.webp :width: 700px .. |image1008| image:: ../media/image1008.webp :width: 406px .. |image1009| image:: ../media/image1009.webp :width: 700px .. |image1010| image:: ../media/image1010.webp :width: 700px .. |image1011| image:: ../media/image1011.webp :width: 593px .. |image1015| image:: ../media/image1015.webp :width: 528px .. |image1016| image:: ../media/image1016.webp :width: 279px .. |image1018| image:: ../media/image1018.webp :width: 700px .. |image1019| image:: ../media/image1019.webp :width: 620px .. |image1215| image:: ../img/image1215.webp :width: 427px .. |image1223| image:: ../img/image1223.webp :width: 398px .. |image1264| image:: ../img/image1264.webp :width: 482px .. |image1265| image:: ../img/image1265.webp :width: 526px .. |image1266| image:: ../img/image1266.webp :width: 700px .. |image1267| image:: ../img/image1267.webp :width: 650px .. |image1267| image:: ../img/image1267.webp :width: 650px .. |image1277| image:: ../img/image1277.webp :width: 550px .. |image1278| image:: ../img/image1278.webp :width: 350px .. |image1279| image:: ../img/image1279.webp :width: 700px .. |image1281| image:: ../img/image1281.webp :width: 600px .. |image1301| image:: ../img/image1301.webp :width: 310px .. |image1302| image:: ../img/image1302.webp :width: 541px .. |image1304| image:: ../img/image1304.webp :width: 384px .. |image1305| image:: ../img/image1305.webp :width: 650px .. |image1307| image:: ../img/image1307.webp :width: 538px .. |image1320| image:: ../img/image1320.webp :width: 526px .. |image1321| image:: ../img/image1321.webp :width: 516px .. |image1322| image:: ../img/image1322.webp :width: 652px .. |image1550| image:: ../img/image1550.webp :width: 600px .. |image1551| image:: ../img/image1551.webp :width: 573px .. |image1565| image:: ../img/image1565.webp :width: 570px .. |image1566| image:: ../img/image1566.webp :width: 527px .. |image1567| image:: ../img/image1567.webp :width: 700px .. |image1568| image:: ../img/image1568.webp :width: 638px .. |image1640| image:: ../img/image1640.webp :width: 544px .. |image1737| image:: ../img/image1737.webp :width: 600px .. |image1738| image:: ../img/image1738.webp :width: 600px .. |image1739| image:: ../img/image1739.webp :width: 350px .. |image1740| image:: ../img/image1740.webp :width: 400px .. |image1741| image:: ../img/image1741.webp :width: 550px .. |image1742| image:: ../img/image1742.webp :width: 500px .. |image1743| image:: ../img/image1743.webp :width: 420px .. |image1744| image:: ../img/image1744.webp :width: 350px .. |image1745| image:: ../img/image1745.webp :width: 350px .. |image1746| image:: ../img/image1746.webp :width: 600px .. |image1747| image:: ../img/image1747.webp :width: 600px .. |image1748| image:: ../img/image1748.webp :width: 500px