Publication d'un json calculé par une user function

Bonjour,

J’utilise un équipement jMQTT pour publier un json que je calcule dans une user function

	public static function jsonAlarmState() {
		$alarm = cmd::byString('#[Maison][Myalarm][alarm]#')->execCmd();
		$zone1 = cmd::byString('#[Maison][Myalarm][zone1]#')->execCmd();
		$zone2 = cmd::byString('#[Maison][Myalarm][zone2]#')->execCmd();
		$sound = cmd::byString('#[Maison][Myalarm][sound]#')->execCmd();
		$siren = cmd::byString('#[Maison][Myalarm][siren]#')->execCmd();
		$arr =  array (
					'alarm' => ($alarm ? 'armed' : 'disarmed'),
					'zone1' => ($zone1 ? 'enabled' : 'disabled'),
					'zone2' => ($zone2 ? 'enabled' : 'disabled'),
					'sound' => ($sound ? 'enabled' : 'disabled'),
					'siren' => ($siren ? 'enabled' : 'disabled')
				);
		return json_encode($arr);

La fonction retourne bien (testée dans un scenario) :

{"alarm":"disarmed","zone1":"disabled","zone2":"enabled","sound":"disabled","siren":"disabled"}

mais mon broker reçoit cela :

jeedom/jeealarm/state "{"alarm":"disarmed","zone1":"disabled","zone2":"enabled","sound":"disabled","siren":"disabled"}"

Le problème c’est l’apostrophe en début et en fin de chaine qui font du message un json malformé. Autant dire que les abonnés au message MQTT de l’autre côté n’apprécient pas beaucoup :wink:

Si je saisis à la main la chaine retrournée par la fonction dans la valeur de la commande, les données sont correctement formatées :

jeedom/jeealarm/state {"alarm":"disarmed","zone1":"disabled","zone2":"enabled","sound":"disabled","siren":"disabled"}

Pourquoi cet " en début et fin s’ajoute t-elle ?

Pour info si je fais la même chose avec le plugin MQTT Manager j’ai la même punition :frowning:

Merci d’avance pour vos réponses avisées :wink:

Hello,

Du coup, il manque la quote en début :wink:

Donc ce n’est pas un problème avec jMQTT, mais un fonctionnement normal su Core :stuck_out_tongue:
Mais, blague à part, oui, je suis au courant de cet effet de bord.
Pour que « ça marche », supprime simplement le json_encode de ton code perso et retourne l’array.

Explication : depuis la v4.3, Jeedom autorise le type Array dans une commande. Je ne me souviens plus exactement du pourquoi du comment, mais l’effet de bord est qu’un string est quoté une fois de trop à la sortie, alors autant laisser le Core faire le json_encode au moment ou l’Array se présente.

Test et dit-moi,
Bad

1 « J'aime »

Merci @Bad pour ta réponse rapide.
Malheureusement ça le fait pas, je retourne l’array directement mais le message produit devient (null). Mon array est bon si je m’en tiens au test réalisé dans un scenario et sur lequel je lui applique un json_encode avec succès.

Les copies d’écran pour plus de détails :

	public static function jsonAlarmState() {
		$alarm = cmd::byString('#[Maison][Myalarm][alarm]#')->execCmd();
		$zone1 = cmd::byString('#[Maison][Myalarm][zone1]#')->execCmd();
		$zone2 = cmd::byString('#[Maison][Myalarm][zone2]#')->execCmd();
		$sound = cmd::byString('#[Maison][Myalarm][sound]#')->execCmd();
		$siren = cmd::byString('#[Maison][Myalarm][siren]#')->execCmd();
		$arr =  array (
					'alarm' => ($alarm ? 'armed' : 'disarmed'),
					'zone1' => ($zone1 ? 'enabled' : 'disabled'),
					'zone2' => ($zone2 ? 'enabled' : 'disabled'),
					'sound' => ($sound ? 'enabled' : 'disabled'),
					'siren' => ($siren ? 'enabled' : 'disabled')
				);
		return $arr;
	}

ce que reçoit le broker :

jeedom/jeealarm/state (null)

Ok, autant pour moi.

Essaye simplement ce payload dans ta commande action dans jMQTT :

{"alarm": #[Maison][Myalarm][alarm]#?'armed':'disarmed', "zone1": #[Maison][Myalarm][zone1]#?'enabled':'disabled', "zone2": #[Maison][Myalarm][zone2]#?'enabled':'disabled', "sound": #[Maison][Myalarm][sound]#?'enabled':'disabled', "siren": #[Maison][Myalarm][siren]#?'enabled':'disabled'}

En plus, tu peux faire en sorte de le publier automatiquement le payload quand une des valeurs change en cochant « Pub. Auto ».

Ce n’est pas jMQTT, c’est une commande virtuelle ?

1 « J'aime »

Pour le coup c’est vraiment la meilleure solution. Pour tout te dire j’étais parti la dessus au départ mais je trouvais l’écriture un peu lourde pour une malheureuse zone de texte peu adaptée à des lignes aussi longues. Ton texte marche nickel en tous cas :+1:

Je trouve quand même complètement dingue qu’un cas aussi basique d’utilisation d’une user function pose autant de question et surtout n’aboutisse pas… Je n’ai pas été regardé le code du core mais je trouve que ça mériterait un PR.

C’est pas jMQTT en effet. On te la fait pas à toi :joy: C’est MQTT manager. Tant que jMQTT ne m’apporte pas de réel valeur ajoutée par rapport à mon besoin, je préfère rester sur un plugin officiel. La publication automatique sur changement des commandes infos aurait pu être sympa mais je peux faire autrement…

Tu as choisi quoi de ton coté ?

Pour finir un grand merci pour cet échange et pour m’avoir apporter la solution sur un plateau. Quand il n’y a plus qu’à faire un copier/coller c’est quand même royal :wink:

Hello,

Ravi que tu ais trouvé chaussure à ton pied :grin:

Une autre option, moins élégante, était de retirer les {} dans la fonction et de les rajouter dans la commande.
Ton besoin est assez simple, je pense d’ailleurs que, dans ce cas, écrire le json « à la main » est plus optimisé que d’utiliser json_encode.

Perso, j’aurais fait une publication MQTT par commande, plutôt que de les mettre dans un json, car les valeurs ne sont pas « intimement liées », à contrario de {"val": 42, "changeTime": 1234556} par exemple.

C’est une partie super sensible de Jeedom, je fais assez peu de PR sur des choses aussi impactantes, mais libre à toi en effet :slightly_smiling_face:

Je développe jMQTT avec Domochip, donc c’est tout choisi :wink:

Bad

2 « J'aime »

Bonjour,

Pourriez-vous préciser?
Avec Jeedom 4.3 et 4.4, ce bloc code:

$arr = array('alarm' => 'armed', 'zone1' => 'enabled');

// 36382 = #[Météo][Virtuel cmd de meteofrance][ArrayCmd]#
$cmd = cmd::byId(36382);

$cmd->event($arr);
$value = $cmd->execCmd();
$scenario->setLog("ValeurArray? : [".$value 
    ."] ".(is_null($value) ? "NULL":"!null") 
    ." ".(is_array($value) ? "Array":"!array") 
    ." ".(is_string($value) ? "String":"!string"));

$cmd->event(json_encode($arr));
$scenario->setLog("ValeurJson : ".$cmd->execCmd());

donne ce résultat:
image
Quand on met une array dans une commande, on récupère une chaine vide.

Vous parliez des commandes Jeedom ?

Hello @jpty,

Depuis ce changement :

evaluateExpression() peut retourner autre chose qu’un type int, bool ou string et notamment null ou array.

jMQTT, et probablement tous les plugins qui interprètent des commandes info dans la champ request, utilise cette fonction du Core pour faire la transformation du champ pour obtenir une valeur « finale », d’où mon commentaire.

Par contre, il doit y avoir un effet de bord avec les fonctions custom et l’ajout automatique de quote par le Core, qui transforme le résultat de la fonction en string, voir en chaîne vide dans le cas d’un array.

Bad

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