Disclaimer important
La procédure ci-dessous modifie un fichier du core Jeedom :
/var/www/html/core/class/jeedom.class.php
C’est totalement volontaire, mais non supporté officiellement.
Vous devez savoir ce que vous faites avant de l’appliquer.
Nécessite PHP 7 minimum.
La modification est réversible facilement via une simple commande SSH (voir plus bas).
Vérifiez que vous savez lancer une connexion SSH avant de lancer ce patch !!
Ne modifie pas le fonctionnement de Jeedom (ajoute juste une entrée dans un log).
Ce Patch sera écrasé à chaque mise à jour de Jeedom (il faudra le réinstaller).
Pourquoi ce patch ?
Depuis PHP 8, certaines expressions sont devenues invalides ou génèrent des exceptions alors qu’elles étaient tolérées auparavant, par exemple :
float + stringint + string- expressions mal formées dans des virtuels
- expressions de scénarios contenant du texte concaténé par erreur
- erreurs de calcul internes non capturées
Le problème :
Jeedom ne capture pas certaines exceptions PHP dans les expressions, notamment celles transmises à jeedom::evaluateExpression()
Résultat : aucune visibilité sur les erreurs → très difficile de déboguer.
Ce patch ajoute une journalisation détaillée de toutes les erreurs d’expression rencontrées par Jeedom, afin de repérer facilement les commandes ou scénarios fautifs.
Ce que fait le patch
Il modifie la fonction :
jeedom::evaluateExpression()
pour :
remplacer catch (Exception $exc) par catch (\Throwable $e)
→ permet de capturer toutes les erreurs PHP 8 (TypeError, ValueError, etc.)
générer un log détaillé dans :
/var/www/html/log/http.error_evaluateExpression
afficher une erreur visible en haut à droite dans Jeedom
→ pratique pour repérer immédiatement les expressions cassées
Comment revenir en arrière ? (restaurer le core propre)
En SSH, exécuter simplement :
POUR LA DERNIERE VERSION :
sudo php /var/www/html/install/update.php
puis
sudo chown -R www-data:www-data /var/www/html
puis
sudo reboot
POUR UNE AUTRE VERSION exemple la 4.4.20 :
sudo php /var/www/html/install/update.php mode=force version=4.4.20
puis
sudo chown -R www-data:www-data /var/www/html
puis
sudo reboot
Cela réinstalle le core Jeedom officiel,
et restaure le fichier jeedom.class.php intact,
Résultat attendu (exemple de sortie de log)
Expression en erreur : #12163#+#14464#
Expression décodée : [Conso EDF][Tableau Electrique Studio][Puissance](816.7)
+
[Dehors][Portail][Puissance]()
Message : Unsupported operand types: float + string
Grâce à cela, vous pouvez retrouver exactement quelle expression est incorrecte et la corriger en quelques secondes.
Il vous suffit d’aller dans l’équipement qui provoque l’erreur, puis en face de sa commande cliquer sur la roue crantée et voir la section Utilisé par pour savoir où est utilisé la commande et corriger l’erreur.
Installation
Créer un scénario, ajouter un bloc code, puis coller le code ci-dessous :
(ne pas mettre de <?php ni ?>)
$file = '/var/www/html/core/class/jeedom.class.php';
$scenario->setLog('--- Patch evaluateExpression() démarré ---');
// Lire le fichier
$content = file_get_contents($file);
if ($content === false) {
$scenario->setLog("Impossible de lire le fichier : $file");
return;
}
// Si déjà patché, on sort
if (strpos($content, 'http.error_evaluateExpression') !== false) {
$scenario->setLog('Patch déjà présent, rien à faire.');
return;
}
// 1) Trouver la fonction evaluateExpression
$funcSignature = 'public static function evaluateExpression(';
$funcPos = strpos($content, $funcSignature);
if ($funcPos === false) {
$scenario->setLog('Signature de evaluateExpression() introuvable.');
return;
}
// 2) Chercher le catch à partir de la position de la fonction
$catchSearch = "} catch (Exception \$exc) {";
$catchPos = strpos($content, $catchSearch, $funcPos);
if ($catchPos === false) {
$scenario->setLog('Bloc "} catch (Exception $exc) {" introuvable dans evaluateExpression().');
return;
}
// 3) Vérifier que ce catch est bien avant le "return $_input;"
$returnSearch = 'return $_input;';
$returnPos = strpos($content, $returnSearch, $funcPos);
if ($returnPos === false) {
$scenario->setLog('"return $_input;" introuvable après evaluateExpression().');
return;
}
if (!($catchPos < $returnPos)) {
$scenario->setLog('Incohérence : le catch n\'est pas avant "return $_input;". Abandon.');
return;
}
// 4) Préparer le nouveau bloc catch (on ne remplace QUE la ligne de catch)
$newCatch = <<<PHP
//} catch (Exception \$exc) {
\t\t} catch (\\Throwable \$e) {
\t\t\t// --- Décodage des #CMD_ID# en noms humains ---
\t\t\t\$_input_names = \$_input;
\t\t\tif (is_string(\$_input)) {
\t\t\t\t\$_input_names = \$_input;
\t\t\t\tif (preg_match_all('/#(\\d+)#/', \$_input, \$m)) {
\t\t\t\t\tforeach (\$m[1] as \$cmdId) {
\t\t\t\t\t\t\$cmd = cmd::byId(\$cmdId);
\t\t\t\t\t\tif (is_object(\$cmd)) {
\t\t\t\t\t\t\t\$name = \$cmd->getHumanName() . '(' . \$cmd->execCmd() . ')';
\t\t\t\t\t\t} else {
\t\t\t\t\t\t\t\$name = '[Commande inconnue ID=' . \$cmdId . ']';
\t\t\t\t\t\t}
\t\t\t\t\t\t\$_input_names = str_replace('#' . \$cmdId . '#', \$name, \$_input_names);
\t\t\t\t\t}
\t\t\t\t}
\t\t\t}
\t\t\tlog::add(
\t\t\t\t'http.error_evaluateExpression',
\t\t\t\t'error',
\t\t\t\t"Expression en erreur : " . print_r(\$_input, true) . "\\n" .
\t\t\t\t"Expression décodée : " . print_r(\$_input_names, true) . "\\n" .
\t\t\t\t((\$_scenario!==null) ? "Scenario : " . print_r(\$_scenario, true) . "\\n" : "") .
\t\t\t\t"Message : " . \$e->getMessage() . "\\n"
\t\t\t);
PHP;
// 5) Remplacement uniquement de la ligne "} catch (Exception $exc) {"
$newContent = substr_replace($content, $newCatch, $catchPos, strlen($catchSearch));
if ($newContent === null) {
$scenario->setLog('Erreur lors du substr_replace().');
return;
}
// 6) Sauvegarde
if (file_put_contents($file, $newContent) === false) {
$scenario->setLog("Impossible d'écrire dans le fichier : $file");
return;
}
$scenario->setLog('Patch evaluateExpression() appliqué avec succès.');
$scenario->setLog('--- Fin du patch ---');



