Besoin d'aide pour comprendre la fonction send_change_immediate d'un daemon

Bonjour a tous,

Je n’ai jamais utilise de daemon dans un plugin et j’aurais besoin d’un petit coup de pouce pour comprendre ou est l’erreur dans l’utilisation de la fonction ‹ send_change_immediate ›…
J’ai suivi le tuto du plugin template mais je ne trouve pas comment resoudre mon soucis.

Je cherche a comprendre comment la partie PHP envoi des donnees vers le daemon (ceci fonctionne) et aussi comment le daemon retourne des donnees a PHP (la j’ai le probleme).

Voici un log de ce que produit mon plugin ‹ template › :

[2024-01-17 21:03:28]INFO : Start demond
[2024-01-17 21:03:28]INFO : Log level: debug
[2024-01-17 21:03:28]INFO : Socket port: 58387
[2024-01-17 21:03:28]INFO : Socket host: localhost
[2024-01-17 21:03:28]INFO : PID file: /tmp/jeedom/template/deamon.pid
[2024-01-17 21:03:28]INFO : Device: auto
[2024-01-17 21:03:28]INFO : Writing PID 25853 to /tmp/jeedom/template/deamon.pid
[2024-01-17 21:03:28]INFO : Socket interface started
[2024-01-17 21:03:28]INFO : LoopNetServer Thread started
[2024-01-17 21:03:28]INFO : Listening on: [localhost:58387]
[2024-01-17 21:04:03]INFO : Client connected to [127.0.0.1:59278]
[2024-01-17 21:04:03]INFO : Message read from socket: b'{"apikey":"mEF2RTrLCCdE1jHWxBnctl9QbrqQZVFSXmHTJpLbMrRQCrRxOwCIIA14aKwqMJOu","action":"discover","login":"test1","password":"test2","address":"test3"}'
[2024-01-17 21:04:03]INFO : Client disconnected from [127.0.0.1:59278]
[2024-01-17 21:04:03]DEBUG : Message received in socket JEEDOM_SOCKET_MESSAGE
[2024-01-17 21:04:03]INFO : Message sent by PHP and received by PYTHON -> action: discover
[2024-01-17 21:04:03]INFO : Message sent by PHP and received by PYTHON -> login: test1
[2024-01-17 21:04:03]ERROR : Send command to demon error: send_change_immediate() missing 1 required positional argument: 'change'

On voit bien la reception sur le socket d’un message pour un parametre ‹ action › et ‹ login ›.
Mais ensuite lorsque j’utilise la fonction ‹ send_change_immediate › provenant de jeedom.py il y a cette erreur : missing 1 required positional argument: ‹ change ›
Je vois bien que la fonction send_change_immediate demande 2 arguments mais je ne trouve pas d’exemple indiquant comment les renseigner.

Voici la partie read_socket() de du fichier ‹ templated.py › du plugin template de mes essais:

def read_socket():
	global JEEDOM_SOCKET_MESSAGE
	if not JEEDOM_SOCKET_MESSAGE.empty():
		logging.debug("Message received in socket JEEDOM_SOCKET_MESSAGE")
		#message = json.loads(jeedom_utils.stripped(JEEDOM_SOCKET_MESSAGE.get()))
		message = json.loads(JEEDOM_SOCKET_MESSAGE.get().decode('utf-8'))
		if message['apikey'] != _apikey:
			logging.error("Invalid apikey from socket: %s", message)
			return
		try:
			print ('read')
			#logging.info('Message sent by PHP and received by PYTHON -> apikey: %s', message['apikey'])
			logging.info('Message sent by PHP and received by PYTHON -> action: %s', message['action'])
			logging.info('Message sent by PHP and received by PYTHON -> login: %s', message['login'])
			jeedom_com.send_change_immediate({'apikey' : '1234','action' : '5678'})
		except Exception as e:
			logging.error('Send command to demon error: %s' ,e)

Dans la fonction ‹ deamon_start › j’ai mis le callback sur ‹ /plugins/template/core/php/jeetemplate.php › qui devrait donc etre appele pour decoder le json retourne par le daemon, c’est juste?
Mais le script n’arrive pas jusque la vu l’erreur avec la fonction send_change_immediate …

PS: desole pour les accents, clavier US …

Merci pour votre support!

Sebastien

Salut

Tu parles de cette doc ??

https://doc.jeedom.com/fr_FR/dev/daemon_plugin

Salut,

Oui exactement !
Ici c’est écrit d’utiliser la fonction telle que:

Mais cette fonction attend 2 arguments.
Quelqu’un peut me donner la solution ?

Merci,

Sebastien

Salut,

La signature de la méthode du plugin template aurait changé?
Sinon regardes le code et l’historique du code?

J’ai fait une autre demo sinon, qui tourne puisque c’est un plugin; voir ici Présentation / tuto python & asyncio

Pas exactement …

jeedom_com est correctement instancié ?

1 « J'aime »

je viens de vérifier mais donc non rien n’a changé.

Je pense qu’il faudrait reprendre les bases de python (y a des tuto en lignes pour démarrer).

En python, les méthodes de class vont toujours recevoir comme premier argument l’instance (l’objet) sur laquelle la méthode est appelée.
Par convention on nomme l’argument self mais en réalité on pourrait donner le nom qu’on veut puisqu’on est bien dans le scope de la méthode (mais il faut respecter la convention et l’appeler self !); c’est la position de l’argument qui compte et pas son nom.

donc les « vrais » arguements « utiles » d’une méthode sont après, ici l’objet change

(un peu l’équivalent du $this en php)

complètement l’équivalent et il y a ca dans tous les langages mais mon point était que en python l’argument est explicitement déclaré dans la signature de la méthode ce qui n’est pas le cas dans la plupart des autres langages (que je connais); c’est un peu perturbant au début.

1 « J'aime »

Bonjour!

Merci pour vos réponses.
Désolé mais je ne comprends toujours pas …
J’ai essayé avec différentes alternative du type:

jeedom_com.send_change_immediate(self,{'apikey' : '1234','action' : '5678'})
ou
jeedom_com.send_change_immediate(self.thread_change,{'apikey' : '1234','action' : '5678'})
etc...

Pourriez-vous me donner un exemple fonctionnel?

Merci,

Sébastien

l’exemple est dans la doc et il est correcte, je ne comprend pas pq tu essaies de passer 2 arguments, il n’y en a qu’un seul: « change »

Salut,

Tu as bien cette ligne dans le code de ton démon ? jeedom_com = jeedom_com(apikey=_apikey, url=_callback) ?

Le code est visible sur un repo ? Il serait sûrement plus simple de pouvoir le consulter afin d’être en mesure de t’aider.

Toujours rien …
@Mips , j’avais pourtant initialement mis qu’un seul argument si tu regardes mon premier post.
N’est-ce pas bien écrit? (en fait je souhait envoyer une chaine json)

@Salvialf , j’ai essayé de rajouter ce que tu proposes mais rien non plus. (je l’ai commenté)

voici le def:

def read_socket():
	global JEEDOM_SOCKET_MESSAGE
	if not JEEDOM_SOCKET_MESSAGE.empty():
		logging.debug("Message received in socket JEEDOM_SOCKET_MESSAGE")
		#message = json.loads(jeedom_utils.stripped(JEEDOM_SOCKET_MESSAGE.get()))
		message = json.loads(JEEDOM_SOCKET_MESSAGE.get().decode('utf-8'))
		if message['apikey'] != _apikey:
			logging.error("Invalid apikey from socket: %s", message)
			return
		try:
			print ('read')
			logging.info('Message sent by PHP and received by PYTHON -> action: %s', message['action'])
			logging.info('Message sent by PHP and received by PYTHON -> login: %s', message['login'])
			#jeedom_com = jeedom_com(apikey=_apikey, url=_callback)
			jeedom_com.send_change_immediate({'apikey' : '1234','action' : '5678'})
		except Exception as e:
			logging.error('Send command to demon error: %s' ,e)

si si moi j’ai bien tout lu.

vraiment arrêtes d’essayer des trucs aux hasards, relis bien le code d’origine du plugin template car il est correcte, le tuto car tout y est écrit (surtout cette partie https://doc.jeedom.com/fr_FR/dev/daemon_plugin#Squelette%20du%20démon%20python ) ainsi que mes réponses ci-dessus.

Si tu lis et suis ce qui s’y trouve, ca fonctionnera.

2 « J'aime »

On va pas s en sortir.
Partage tout ton fichier ou rien du tout, pcq la ca aide pas.

Ma question, et celle de @Salvialf, s instancie dans la partie « main » de ton fichier. En remplacant le _api, et _callback par les arguments qui auront ete passés par ton appel php.

Bref partage tout ton fichier ou un repo, ca sera + simple

Plutôt dans le try à la fin :

try:
    jeedom_utils.write_pid(str(_pidfile))
    jeedom_com = jeedom_com(apikey=_apikey, url=_callback)
    if not jeedom_com.test():
        logging.error(
            'Network communication issues. Please fixe your Jeedom network configuration.')
        shutdown()
    # Ta fonction main
except Exception as e:
    logging.error('Fatal error : '+str(e))
    shutdown()

Et oui si on pouvait avoir accès au code ce serait bcp plus simple à débuguer et effectivement tout est déjà indiqué dans la documentation !

@tomitomas Je n’avais pas vu que tu avais déjà posé la question :sweat_smile:

Effectivement avec cette ligne ‹ jeedom_com › que j’ai oublie ca fonctionne bien mieux!

try:
	jeedom_utils.write_pid(str(_pidfile))
	jeedom_com = jeedom_com(apikey = _apikey,url = _callback,cycle=_cycle) # création de l'objet jeedom_com
	if not jeedom_com.test(): #premier test pour vérifier que l'url de callback est correcte
		logging.error('Network communication issues. Please fixe your Jeedom network configuration.')
		shutdown()
	jeedom_socket = jeedom_socket(port=_socket_port,address=_socket_host)
	listen()
except Exception as e:
	logging.error('Fatal error: %s', e)
	logging.info(traceback.format_exc())
	shutdown()

Maintenant les logs affichent:

[2024-01-18 18:34:02]INFO : Client connected to [127.0.0.1:33776]
[2024-01-18 18:34:02]INFO : Message read from socket: b'{"apikey":"blablabla","action":"discover","login":"test1","password":"test2","address":"test3"}'
[2024-01-18 18:34:02]INFO : Client disconnected from [127.0.0.1:33776]
[2024-01-18 18:34:02]DEBUG : Message received in socket JEEDOM_SOCKET_MESSAGE
[2024-01-18 18:34:02]INFO : Message sent by PHP and received by PYTHON -> action: discover
[2024-01-18 18:34:02]INFO : Message sent by PHP and received by PYTHON -> login: test1
[2024-01-18 18:34:02]INFO : Send to jeedom : {'apikey': '1234', 'action': '5678'}
[2024-01-18 18:34:02]DEBUG : Starting new HTTP connection (1): 127.0.0.1:80
[2024-01-18 18:34:02]DEBUG : http://127.0.0.1:80 "POST /plugins/template/core/php/jeetemplate.php?apikey=blablabla HTTP/1.1" 200 0

Il ne me reste plus qu’a recuperer les valeur depuis php avec jeetemplate.php

Oulala, desole pour tout …

Sebastien

On est bien d accord aucun fichier ne doit s appeler « xxxxtemplate.xxxx » par contre …!?

C’est pour essayer… comme c’est ecrit dans le tuto:

Pour cela on doit ajouter un fichier à notre plugin dans le dossier ./core/php/. Par convention, on va nommer ce fichier jee[pluginId].php. /plugins/[pluginId]/core/php/jee[pluginId].php sera donc le chemin à utiliser comme url de callback dans la méthode deamon_start()

Donc si mon plugin d’apprentissage s’appelle ‹ template › alors ce fichier doit s’appeler ‹ jeetemplate.php › non?

Aussi je debute en Python … pas evident…

Merci pour tout!

Sebastien

Pour tester tu peux l’appeler comme tu veux, comme indiqué dans cette documentation très bien rédigée il s’agit juste d’une convention de nommage.

Donc pour résumer, comme tu n’avais pas instancié jeedom_com il manquait l’argument self d’où l’erreur à laquelle tu faisais face.

Edit :

Tous les plugins avec démon python sont des exemples fonctionnels :wink:

le reste aussi était écrit dans le tuto … :sweat_smile:
donc c’est pour ca que je fais la remarque / pose la question :slight_smile: