Programmation démon, exemple de code

bonjour,

je n’ai jamais fait de codage de démon sur jeedom et je cherche un exemple qui se rapproche de ce dont j’ai besoin pour éviter de trop galérer.

voilà mon besoin en espérant qu’un module existant pas trop compliqué puisse m’inspirer sans trop transpirer :slight_smile:

à certaines occasion sur mon plugin, je veux pouvoir lui envoyer des éléments venant d’un eqlogic en particulier et en même temps démarrer une routine ou lui demander d’arrêter la routine pour l’eqlogic donné

  • cette routine est une boucle qui se met à envoyer une requete http toutes les 10s et récupère un json pour mettre à jour les commandes de l’eqlogic à but de rafraichir l’affichage plus vite que le cron

j’ai donc besoin d’un exemple qui boucle simplement avec requête REST toutes les X secondes et la logique pour parser le json et aller écrire les commandes infos sur jeedom

merci par avance de votre aide.

1 « J'aime »

Bonjour,

La doc dev ca va pas? https://doc.jeedom.com/fr_FR/dev/

si pas, peux-tu préciser ce qu’il te faudrait?

1 « J'aime »

merci mips, j’ai lu cette page, j’ai même chargé les morceaux de codes pour essayer de comprendre comment ça s’utilise et plus particulièrement : https://doc.jeedom.com/fr_FR/dev/daemon_plugin

je t’avoue que je ne suis pas certain d’avoir tout compris, je vais juste poser des questions plus ciblées différentes et qui seront plus facile pour vous.

PHP->DEMON:
pour envoyer une valeur formatée au démon, si je veux passer plusieurs choses, est-ce que je dois faire un tableau ou coder autrement ?

$ip ='N.N.N.N.';
$token='lfkr45flckfxxxx`;
$cmd='start';
$ret = sendToDaemon(['ip'=>$ip, 'token' => $token, 'cmd'=>$start]);

du côté du démon pour réceptionner dans read_socket(name) :

global JEEDOM_SOCKET_MESSAGE
if not JEEDOM_SOCKET_MESSAGE.empty():
	message = JEEDOM_SOCKET_MESSAGE.get().decode('utf-8')
	message =json.loads(message)

et après pour accéder aux éléments reçus je fais message[ip], message[token], etc …?

DEMON->PHP
ensuite dans l’autre sens, pour envoyer du démon vers jeedom, le démon ne sait pas écrire directement vers jeedom, il envoie donc uniquement un flux d’information (payload) à travers une socket ouverte sur le port à définir en entête.

du coup si je veux récupérer un tableau, je vais décoder via un truc du style :
$result['retour']; suivi d’une bordée de cmd->event() ou ce que je veux.

et pour l’envoyer côté démon je dois construire un json et l’envoyer comme ça ?

jeedom_com.send_change_immediate({'id' : '1', 'json' : {[...]} })

et c’est un tableau json envoyé qui sera décompté, c’est bien ça ?

mon $retour[« id »] sera égal à 1 et en faisant un json_decode($retour[« json »], true) je récupère un tableau des valeurs contenu dans la chaine « json ».

j’ai tout compris ou il y a une subtilité supplémentaire à laquelle je dois faire attention ?

Bonjour,

  • à certaines occasions = sur événement ?
  • je veux pouvoir lui envoyer : à qui ? Si c’est au démon que vous voulez envoyer quelque chose, pour qu’il en fasse quoi ?
  • des éléments venant d’un eqlogic en particulier : quoi ?
  • cette routine : le démon, je suppose
  • est une boucle qui se met à envoyer une requete http toutes les 10s : elle ne fait rien puis se réveille et se met à envoyer quelque chose avec un polling de 10s ? Elle repasse en veille comment ?
  • et récupère un json pour mettre à jour les commandes de l’eqlogic à but de rafraichir l’affichage plus vite que le cron : de l’eqLogic du plugin que vous souhaitez développer ? Plus vite que quel cron ? Il existe un cron à la seconde…

Voilà, je voulais montrer qu’avec vos explications, on peut se poser encore plus de questions. Peut-être qu’il faudrait expliquer clairement pour quelle application, quel matériel, quel but plutôt que de partir de la solution que vous imaginez et de poser les questions sur cette solution.

Là, tout me fait penser au problème XY si souvent souligné par Mips.

Ca se trouve, l’utilisation du plugin script ou d’un scénario avec un (ou plusieurs) bloc(s) de code ferait l’affaire de manière élégante.

A+
Michel

michel, le script php n’est pas adapté tout comme le scénario. mon use case est en temps réel et websockets. je suis loin d’être débutant en programmation, je veux juste des guidelines sur les nouvelles méthodes en debian 12 jeedom 4.5.

j’ai suivi scrupuleusement les recos de MIPS ainsi que sa technote pour déployer l’environnement. après avoir un peu galéré, j’ai fini par comprendre l’ensemble donc maintenant ça marche, mais :

l’arbo est à priori ok, à moins que j’ai loupé quelque chose :

sachant que tout est au vert sur les dépendances :

j’ai importé le code de base des démons et regardé blea comme exemple, voilà le début du code qui bloque, inutile de surcharger car il va pas plus loin que les imports. pourtant au niveau du visual studio, je n’ai pas d’erreur de résolution et il compile bien le sous rep jeedom :

import subprocess
import os,re
import logging
import sys
import argparse
import time
import datetime
import signal
import json
import traceback
import threading
import globals

try:
	from jeedom.jeedom import *
except ImportError:
	print("Error: importing module from jeedom folder")
	sys.exit(1)

try:
	import queue
except ImportError:
	import Queue as queue

1 « J'aime »

Tu peux regarder ceci également: jeedomdaemon · PyPI
c’est une alternative au template python de jeedom que j’ai réalisée

et ce plugin qui est un exemple: GitHub - Mips2648/jeedom-aiodemo

merci Mips, beaucoup plus simple à mettre en oeuvre en effet. j’ai effacé toute mes bricoles et posé proprement du noveau code.

il marche, compile et persiste une erreur que je ne comprends pas :

0001|[2024-10-15 05:15:24] INFO : Starting daemon with log level: debug
0002|[2024-10-15 05:15:24] DEBUG : Writing PID 17375 to /tmp/jeedom/jee4lm/deamon.pid
0003|[2024-10-15 05:15:24] INFO : Listening on 127.0.0.1:55444
0004|[2024-10-15 05:15:24] ERROR : Please check your network configuration page: 403-Forbidden
0005|[2024-10-15 05:15:24] INFO : Listening cancelled
0006|[2024-10-15 05:15:24] INFO : Shutdown
0007|[2024-10-15 05:15:24] DEBUG : Removing PID file /tmp/jeedom/jee4lm/deamon.pid
0008|[2024-10-15 05:15:24] DEBUG : Exit 0

pourtant une petite liste des usages donne :

Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:PortProcess
tcp   LISTEN 0      80         127.0.0.1:3306       0.0.0.0:*
tcp   LISTEN 0      511          0.0.0.0:80         0.0.0.0:*
tcp   LISTEN 0      5          127.0.0.1:42449      0.0.0.0:*    users:(("python3",pid=26271,fd=3))

j’ai essayé quelques autres numéro de ports sans succès.
aurais-tu une idée de ce qui peut bloquer d’écouter sur un port local ? à priori il y a d’autres trucs qui tournent dessus. C’est le fait d’être en docker pour cette instance ?

C’est sans doute l’adresse callback qui génère cette erreur 403. Il faudrait vérifier dans cette direction, je pense.

NB: il faudrait mettre les log aussi en texte préformaté

Vérifies le log http.error.

Peut-être un fichier .htacces qui manque?

j’ai fait la chasse aux .htaccess un peu partout, certes il en manquait mais j’ai du louper un truc :

0008|[Tue Oct 15 07:21:03.216595 2024] [access_compat:error] [pid 24006:tid 24006] [client 10.0.3.2:57824] AH01797: client denied by server configuration: /var/www/html/plugins/template

pourquoi il me parle de template… bon j’ai trouvé, un chemin pas renommé…

merci, je continue à tracer !

autre question MIPS, je sèche toujours dans la continuité du sujet

le code semble maintenant bien fonctionner, par contre le statut du démon sur l’écran reste « NOK » du coup j’ai mis des tests un peu partout dans deamon_info

le code php cherche le démon sur /tmp/jeedom/jee4lm/daemon.pid
le fichier est bien là car lorsque je fais un ls /tmp/jeedom/jee4lm je le vois et il est en a+r.

le démon est bien démarré et écoute sur le port en question :

0040|[2024-10-15 07:50:04] INFO  : Starting daemon with log level: debug
0041|[2024-10-15 07:50:04] DEBUG  : Writing PID 1211 to /tmp/jeedom/jee4lm/deamon.pid
0042|[2024-10-15 07:50:04] INFO  : Listening on 127.0.0.1:50044
0043|[2024-10-15 07:50:04] INFO  : Send async started with a cycle of 2.0s

voilà le code que j’ai qui me semble identique à celui que j’ai pris sur ton exemple

 public static function deamon_info() {
    $return = array();
        $return['log'] = __CLASS__;
        $return['launchable'] = 'ok';
        $return['state'] = 'nok';
        $pid_file = jeedom::getTmpFolder(__CLASS__) . '/daemon.pid';
        log::add(__CLASS__, 'debug', 'démon search pid ={'.$pid_file.')');
        if (file_exists($pid_file)) {
          log::add(__CLASS__, 'debug', 'found file');
          if (@posix_getsid(trim(file_get_contents($pid_file)))) {
            log::add(__CLASS__, 'debug', 'file ok');
            $return['state'] = 'ok';
            } else {
              log::add(__CLASS__, 'debug', 'removing');
              shell_exec(system::getCmdSudo() . 'rm -rf ' . $pid_file . ' 2>&1 > /dev/null');
            }
        }
        return $return;  
    }

la fonction file_exists ne voit pas le fichier car le log boucle :

0299|[2024-10-15 14:50:14] ERROR  Impossible de lancer le démon, vérifiez le log
0300|[2024-10-15 14:50:14] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0301|[2024-10-15 14:50:20] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0302|[2024-10-15 14:50:26] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0303|[2024-10-15 14:50:32] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0304|[2024-10-15 14:50:38] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0305|[2024-10-15 14:50:44] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0306|[2024-10-15 14:50:50] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0307|[2024-10-15 14:50:56] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)
0308|[2024-10-15 14:51:02] DEBUG  démon search pid ={/tmp/jeedom/jee4lm/daemon.pid)

Bonjour,

deamon.pid dans le 1er log puis
daemon.pid dans deamon_info

1 « J'aime »

je suis dislexique :slight_smile:

1 « J'aime »

merci à tous, je vais pouvoir avancer sur le code python le corps du système de démon est enfin fonctionnel !

pour info mes devs perso sont dispo sur mon github. si ça peut faire des exemples à d’autres n’hésitez pas à aspirer le code :slight_smile:

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