Scenario en erreur

Bonjour,

J’ai un soucis avec un bloc code de scénario qui refuse de s’exécuter quand il est lancé une deuxième fois…

Pour expliquer :
J’ai un scénario principal qui gère le pilotage du robot aspirateur et qui fait appel à un sous-scénario en mode synchone qui gère le calcul des coordonnées de la zone que le robot doit nettoyer.

J’essaye de faire fonctionner le robot de la façon suivante :

Sélection de la pièce à nettoyer
Aspiration de la pièce → Appel du sous scénario pour calculer les coordonnées : OK

[2024-11-04 14:54:51][SCENARIO] -- Début : Lancement provoqué par le scénario  : [Electroménager][Salle à Manger][Roborock - Nettoyage]. Tags : {"#pass#":"1","#ordre#":"LE_CELLIER"}
[2024-11-04 14:54:51][SCENARIO] - Exécution du sous-élément de type [action] : code
[2024-11-04 14:54:51][SCENARIO] Exécution d'un bloc code
[2024-11-04 14:54:51][SCENARIO] Pré-Nettoyage
[2024-11-04 14:54:51][SCENARIO] Coordonnées : [26010,23700,29400,25700,1]
[2024-11-04 14:54:51][SCENARIO] Point de départ de la zone : 26010,23700
[2024-11-04 14:54:51][SCENARIO] Fin correcte du scénario

puis quand je détecte que le robot retourne à la station ou sur se retrouve sur la base :
Lavage de la pièce → Exécution du sous-scénario : ERREUR

[2024-11-04 15:01:17][SCENARIO] Lancement du scénario en mode synchrone
[2024-11-04 15:01:17][SCENARIO] -- Début : Lancement provoqué par le scénario  : [Electroménager][Salle à Manger][Roborock - Nettoyage]. Tags : {"#pass#":"1","#ordre#":"LE_CELLIER"}
[2024-11-04 15:01:17][SCENARIO] - Exécution du sous-élément de type [action] : code
[2024-11-04 15:01:17][SCENARIO] Exécution d'un bloc code

Le sous-scénario commence comme cela:

$scenario->setlog("Pré-Nettoyage");

$tags=$scenario->getTags();

$pass = $tags['#pass#'];
$ordre = $tags['#ordre#'];

function rotate($x,$y, $angle,$centre) {
...
}

function generer($coordonnees,$quoi,$rotation,$centre) {
...
   }

// Script de contournement des problèmes de rotations de cartes 
// définition des zones (XGauche,Ybas,Xdroite,Yhaut)

On voit bien que le bloc-code ne s’exécute pas du tout mais sans raison apparente.
Comment puis-je débogger ce problème car je ne vois ce qui bloque l’exécution du scénario ?
{4CFBFD99-5C87-469F-8000-A68C59F0E21E}

Merci pour votre aide.


Mes infos de config :

Jeedom Core : 4.4.19 (master)
DNS Jeedom : non
Version OS : debian 11.9
Version PHP : 7.4.33

Bonjour,

Sans voir le code complet… :thinking: :thinking:

Qu’on ne voit pas… Quelle erreur ?

Vous le voyez. pas nous

je vais être moins vindicatif que le modérateur :wink:

  1. je suis étonné que ton bloc de code s’exécute avec des fonctions, dans le code du core, l’exécution du texte est traité par :
...
elseif ($this->getType() == 'code') {
				$this->setLog($scenario, $GLOBALS['JEEDOM_SCLOG_TEXT']['execCode']['txt']);
				return eval($this->getExpression());
			}

pour moi il n’y a aucun moyen de faire plus de logs, à part supprimer des choses et les ajouter petit à petit. je commencerai par virer les fonctions et mettre du code en ligne simple et transférer les fonctions sous forme de classe statique à appeler depuis les fonctions utilisateurs globales.

je ne suis pas modérateur

désolé, relis-toi, je trouve que tu as fait preuve d’autant de bienveillance que l’équipe des modérateurs :wink:

la question je l’ai trouvé claire, je fais pas mal de blocs de code, de codage php et des plugins perso, du coup ça me parle.

maintenant, j’ai peut être pas la bonne réponse, mais ce qui est clair c’est que si le code php ne s’exécute pas, je cite :

[2024-11-04 15:01:17][SCENARIO] - Exécution du sous-élément de type [action] : code
[2024-11-04 15:01:17][SCENARIO] Exécution d'un bloc code

Lavage de la pièce → Exécution du sous-scénario : ERREUR

pour moi c’est peut être qu’il n’est pas interprétable par la fonction eval(), du coup il me semble judicieux de proposer de commenter les fonctions du bloc pour voir. Comme on ne peut pas tracer plus que ça, dès que la syntaxe est non précompilable par l’interpréteur et ça à cause du try/catch encadrant l’eval() dans le core jeedom.

bonne soirée

1 « J'aime »

Me relire…

Quand j’ai besoin d’aide, je donne les infos. Toutes les infos.

Là il y a un bloc code qui pose souci le minimum c’est de poster la totalité du code.

C’est tout ce que je dis.

Mais à priori, la mode actuelle est à la demande minimale, avec des arguments type la page santé est verte, y a pas de logs…
J’ai fait ça mais je le montre pas.

On est même plus dans l’assistanat à ce niveau.
On est dans de l’accompagnement de fénéantise de donner des infos quand on a besoin d’aide.

C’est à celui qui sera le plus nul que la médaille en chocolat sera donnée.

Quel monde merveilleux, quand on voit le nombre de posts où le changelog n’a pas été lu, où la doc est une notion abstraite

C’est vrai, pourquoi tenter de tirer le niveau faire le haut quand on peut le lisser vers le bas.

3 « J'aime »

Merci pour vos réponses.

Je comprends que les fonctions peuvent gênées mais pourquoi le bloc-code s’exécute au premier appel (et interprète correctement les fonctions) et pas au second ?

Comme l’a dit @lperenna on est pas devins, sans voir ce que fait le code personne ne pourra répondre à cette question.

oui désolé .

Voici le bloc-code dans son intégralité. C’est un code que j’avais repris d’un post de la communauté et adapté

$scenario->setlog("Pré-Nettoyage");

$tags=$scenario->getTags();

$pass = $tags['#pass#'];
$ordre = $tags['#ordre#'];

function rotate($x,$y, $angle,$centre) {
  if($angle == 0)
    {
    // ajustement facultatif du centre par défaut en cas de léger déplacement de la base :
    // $x = $x - 80;
    // $y = $y + 80;
    return array($x,$y);
  	}
  	$angle *= M_PI / 180;
 	$xM = $x - $centre[0];
    $yM = $y - $centre[1];
    $x = $xM * cos($angle) + $yM * sin($angle) + $centre[0];
    $y = - $xM * sin($angle) + $yM * cos($angle) + $centre[1];
  	return array(round($x), round($y));
}

function generer($coordonnees,$quoi,$rotation,$centre) {
     if( count($coordonnees[$quoi])<1 ) return "AUCUN";
     $zonedef=array();
     foreach($coordonnees[$quoi] as $lazone)
     	{ // pour chaque zone
        $zone=explode(',', $lazone);
        $coord=array();
        list( $xa , $ya ) = rotate($zone[0],$zone[1],$rotation,$centre);  // Renvoi position debut array(x,y)
        if( $zone[2] > 0 )
            { // Clean zone
            list( $xb , $yb ) = rotate($zone[2],$zone[3],$rotation,$centre); // renvoi position fin array(x,y)
            if( $xa < $xb )
            	{
                $coord[0] = $xa;
                $coord[1] = 0;
                $coord[2] = $xb;
                }
            else{
                $coord[0] = $xb;
                $coord[1] = 0;
                $coord[2] = $xa;
                }
            if( $ya < $yb )
                {
                $coord[1] = $ya;
                $coord[3] = $yb;
                }
            else{ 
                $coord[1] = $yb;
                $coord[3] = $ya;
                }
            $coord[4]=$zone[4];
            $zonedef[]='['.implode(',',$coord).']';
            }
        else{  // Gothere
            $zonedef[] = $xa . "," . $ya;
            }
        }                      
     return implode('-',$zonedef);
   }

// Script de contournement des problèmes de rotations de cartes 
// définition des zones (XGauche,Ybas,Xdroite,Yhaut)
$coordonnees = array();
$coordonnees['LA_CUISINE'][] = "26000,26000,28500,28550,$pass";
$coordonnees['LE_CELLIER'][] = "26010,23700,29400,25700,$pass";
$coordonnees['LA_SALLE_A_MANGER'][] = "20455,24600,26000,29100,$pass";
$coordonnees['L_ENTREE'][] = "23783,18500,26000,19700,$pass";
$coordonnees['LE_SALON_'][] = "20455,19700,26000,24600,$pass";
$coordonnees['LE_COULOIR'][] = "19297,15800,20300,20600,$pass";
$coordonnees['LES_WC'][] = "20219,18700,21930,19600,$pass";
$coordonnees['LA_SALLE_DE_BAIN'][] = "20219,16870,22847,18630,$pass";
$coordonnees['LA_CHAMBRE_DE_MATHIS'][] = "20219,13050,23694,16790,$pass";
$coordonnees['LA_CHAMBRE_DE_JADE'][] = "16500,13050,20300,15800,$pass";
$coordonnees['LE_BUREAU'][] = "16500,17200,19297,20330,$pass";
$coordonnees['LA_CHAMBRE_DES_PARENTS'][] = "16500,20600,20300,24600,$pass";
$coordonnees['LA_SALLE_D___EAU'][] = "16500,20410,18293,21340,$pass";

$coordonnees['LE_COIN_REPAS'][] = $coordonnees['LA_CUISINE'][0];
$coordonnees['LE_COIN_REPAS'][] = $coordonnees['LA_SALLE_A_MANGER'][0];

$coordonnees['LE_SALON'][] = $coordonnees['L_ENTREE'][0];
$coordonnees['LE_SALON'][] = $coordonnees['LE_SALON_'][0];

$coordonnees['LA_PIECE_DE_VIE'][] = $coordonnees['LE_CELLIER'][0];
$coordonnees['LA_PIECE_DE_VIE'][] = $coordonnees['LA_CUISINE'][0];
$coordonnees['LA_PIECE_DE_VIE'][] = $coordonnees['LA_SALLE_A_MANGER'][0];
$coordonnees['LA_PIECE_DE_VIE'][] = $coordonnees['LE_SALON'][0];
$coordonnees['LA_PIECE_DE_VIE'][] = $coordonnees['L_ENTREE'][0];

$coordonnees['LES_CHAMBRES'][] = $coordonnees['LA_CHAMBRE_DES_PARENTS'][0];
$coordonnees['LES_CHAMBRES'][] = $coordonnees['LE_BUREAU'][0];
$coordonnees['LES_CHAMBRES'][] = $coordonnees['LA_CHAMBRE_DE_JADE'][0];
$coordonnees['LES_CHAMBRES'][] = $coordonnees['LA_CHAMBRE_DE_MATHIS'][0];
$coordonnees['LES_CHAMBRES'][] = $coordonnees['LA_SALLE_DE_BAIN'][0];
$coordonnees['LES_CHAMBRES'][] = $coordonnees['LE_COULOIR'][0];

$coordonnees['POUBELLE'][] = "28200,28100";

// Récupération des paramètres stockés dans le virtuel :
// rotation relative de la carte == 0 lors de la création initiale des zones
$cmd = cmd::byString("#[Salle à Manger][Tuile Roborock][rotation_map]#");
$rotation = $cmd->execCmd();
// centre X de la carte :
$cmd = cmd::byString("#[Salle à Manger][Tuile Roborock][centre_x]#");
$centre_x = $cmd->execCmd();
// centre Y de la carte :
$cmd = cmd::byString("#[Salle à Manger][Tuile Roborock][centre_y]#");
$centre_y = $cmd->execCmd();
$centre = array($centre_x,$centre_y); // centre X, Y de la carte (25000,25000)

// on génère les coordonnées corrigées :
$newpos = generer($coordonnees,$tags['#ordre#'],$rotation,$centre);
$scenario->setLog("Coordonnées : " .$newpos);                                                               
// et on sauve ces coordonnées dans notre virtuel (pour qu'ils soient exploitables hors de notre bloc de code)
$cmd = cmd::byString("#[Salle à Manger][Tuile Roborock][coordonnees]#");
$cmd->event($newpos);

$goto = explode (",",$newpos);
$goto = substr($goto[0],1).",".$goto[1];
$scenario -> setlog ("Point de départ de la zone : ".$goto);
$cmd = cmd::byString("#[Salle à Manger][Tuile Roborock][goto_coordonnees]#");
$cmd->event($goto);
  • Mode synchrone : Lance le scénario dans le thread courant au lieu d’un thread dédié. Permet d’augmenter la vitesse de lancement du scénario, mais peut rendre le système instable. Attention a ne surtout pas mettre de scénario complexe ou avec des pauses (sleep) ou wait en synchrone, cela engendre un comportement instable de jeedom et ne pourra être couvert par le support.

Moi je ne mettrai pas ces scénarios en mode synhcrone !

Ok du coup, tu le lances comment ?

En mode « Démarrer (sync) » comme ci dessous ?

Au final tu as pas mal de choses qui peuvent varier dans ton code …
Quand tu dis que la première fois ça passe et pas la seconde : tu as essayé de changer les zones histoire de voir si c’est pas par exemple ta deuxième zone qui pose problème et pas forcément le deuxième appel ?

Oui je lance ce scénario en sync.
En fait, quelque soit la zone demandée le résultat est le même.

Donc je le répète avez vous essayé de le lancer normalement ?
Il n’y a aucune raison de le lancer en sync !

Ben si je comprends bien, il à un scénario qui lance le robot et un autre qui lui donne les positions où aller. Et dans ce contexte le lancer en sync ça fait sens justement.

Ah bon ? Quel intérêt dans le lancer le 2eme scénario dans le même thread ?

  • Mode synchrone : Lance le scénario dans le thread courant au lieu d’un thread dédié. Permet d’augmenter la vitesse de lancement du scénario, mais peut rendre le système instable. Attention a ne surtout pas mettre de scénario complexe ou avec des pauses (sleep) ou wait en synchrone, cela engendre un comportement instable de jeedom et ne pourra être couvert par le support.

Quel intérêt de justement ne pas tester de le lancer en mode normal ?

Quand tu appelle un scénario qui lance un autre scénario, si tu le lances en mode normal, les deux scénarios vivent leur vie en parallèle.
Si tu le lance en mode sync, le scénario principal va attendre que le scénario secondaire ait fini de s’exécuter avant de passer à l’étape d’après.

Il faut dissocier la notion de synchrone pour un scénario purement standalone d’un scénario qui est appellé par un autre.

Donc dans ce cas ci c’est le scénario appelé qui lance le robot, donc je ne vois toujours pas l’intéret

Bonjour Iperenna.
Il y a deux choses qui porte un nom proche / identique mais qui sont totalement différents !
Sinon, ça serait trop simple :rofl:

  1. Le mode synchrone qui est une case à cocher dans les reglages du scénario : c’est ce dont tu parles / la capture que tu as poster. On pourrait parler d’un « Mode d’exécution »
  2. Le fait de lancer, via un premier scénario, un second en mode synchronisation. Dans ce cas, c’est complètement différent. Ça veux juste dire, que le premier scénario, va etre en pose jusqu’à la fin de l’exécution du second scénario. Une fois le second scénario finis, le premier va continuer. On pourrait parler d’un « Mode de lancement »

Donc :

  • Le scénario appelant (le premier, celui qui lance / appel un second scénario) peut donc choisir uniquement le « mode de lancement » (le « mode d’exécution depend des réglage du scénario appelé).
  • La case a cocher dans un scénario règle uniquement le « Mode d’exécution » (quelque soit le mode de lancement)

J’espère que c’est plus clair…?

Tu as 2 actions différentes :

  • 1 : aspiration de la pièce
  • 2 : lavage de la pièce

Au niveau du robot, ces 2 actions fonctionnent de la même manière ?

Si tu lance une 2eme action d’aspiration, ca fonctionne ?
Si tu lance le lavage de la pièce en 1er, ca fonctionne ?

Tu détecte comment ? de manière automatique ? ou tu lance manuellement ?

Une copie du scénario principal nous aiderai aussi

C’est très clair et c’est bien ce que j’avais deja compris.

Mais bon, je laisse tomber vu que si le 1er scénario appelle le second, qui calcule et lance le robot, quel intéret de faire ce mode ?

Pourquoi ne pas tester sans pour voir.