{ "name": "IA Gemini - QR", "isActive": "1", "group": "", "mode": "provoke", "schedule": "", "trigger": [ "" ], "timeout": "0", "object_id": null, "isVisible": "0", "display": { "name": "" }, "order": "9999", "description": "", "configuration": { "timeDependency": 0, "has_return": 0, "logmode": "default", "allowMultiInstance": "0", "syncmode": "0", "timeline::enable": "0", "timeline::folder": "" }, "elements": [ { "name": "", "type": "action", "options": [], "order": "0", "subElements": [ { "name": "", "type": "action", "subtype": "action", "options": { "collapse": "0", "enable": "1" }, "order": "0", "expressions": [ { "type": "element", "subtype": "", "expression": "2285", "options": [], "order": "0", "element": { "name": "", "type": "comment", "options": [], "order": "0", "subElements": [ { "name": "", "type": "comment", "subtype": "comment", "options": { "collapse": "0" }, "order": "0", "expressions": [ { "type": "comment", "subtype": "", "expression": "1\/ gemini_api_key : clé API de Gemini\n2\/ jeedom_question : l'ID de la commande Question\n3\/ jeedom_sortie : l'ID de la commande Réponse", "options": [], "order": "0" } ] } ] } }, { "type": "action", "subtype": "", "expression": "variable", "options": { "enable": "1", "background": "0", "name": "gemini_api_key", "value": "" }, "order": "1" }, { "type": "action", "subtype": "", "expression": "variable", "options": { "enable": "1", "background": "0", "name": "jeedom_question", "value": "339805" }, "order": "2" }, { "type": "action", "subtype": "", "expression": "variable", "options": { "enable": "1", "background": "0", "name": "jeedom_sortie", "value": "339806" }, "order": "3" }, { "type": "element", "subtype": "", "expression": "2286", "options": [], "order": "4", "element": { "name": "", "type": "comment", "options": [], "order": "0", "subElements": [ { "name": "", "type": "comment", "subtype": "comment", "options": { "collapse": "0" }, "order": "0", "expressions": [ { "type": "comment", "subtype": "", "expression": "Récupération des capteurs par pièces :\nLister l'ensemble des pièces dont vous souhaitez envoyer les capteurs à l'IA séparées par des ;\nBien respecter la syntaxe. Si vous ne souhaitez pas utiliser ce mode de liste, écrire ainsi $scenario->setData(\"jeedom_piece_id\", \"\");", "options": [], "order": "0" } ] } ] } }, { "type": "element", "subtype": "", "expression": "2287", "options": [], "order": "5", "element": { "name": "", "type": "code", "options": [], "order": "0", "subElements": [ { "name": "", "type": "code", "subtype": "action", "options": { "collapse": "0", "enable": "1" }, "order": "0", "expressions": [ { "type": "code", "subtype": "", "expression": "$scenario->setData(\"jeedom_piece_id\", \"\");", "options": [], "order": "0" } ] } ] } }, { "type": "element", "subtype": "", "expression": "2288", "options": [], "order": "6", "element": { "name": "", "type": "comment", "options": [], "order": "0", "subElements": [ { "name": "", "type": "comment", "subtype": "comment", "options": { "collapse": "0" }, "order": "0", "expressions": [ { "type": "comment", "subtype": "", "expression": "Récupération des capteurs :\nLister à partir de la ligne 2 l'ensemble des capteurs que vous souhaiter envoyer à l'IA séparées par des ;\nBien respecter la syntaxe. Si vous ne souhaitez pas utiliser ce mode de liste, écrire ainsi $scenario->setData(\"jeedom_capteurs\", \"\");", "options": [], "order": "0" } ] } ] } }, { "type": "element", "subtype": "", "expression": "2289", "options": [], "order": "7", "element": { "name": "", "type": "code", "options": [], "order": "0", "subElements": [ { "name": "", "type": "code", "subtype": "action", "options": { "collapse": "0", "enable": "1" }, "order": "0", "expressions": [ { "type": "code", "subtype": "", "expression": "$scenario->setData(\"jeedom_capteurs\", \"\n#[Piscine][Piscine Plugin][Température]#;\n#[Salle de bain][Capteur][Température]#\n\");", "options": [], "order": "0" } ] } ] } }, { "type": "element", "subtype": "", "expression": "2290", "options": [], "order": "8", "element": { "name": "", "type": "comment", "options": [], "order": "0", "subElements": [ { "name": "", "type": "comment", "subtype": "comment", "options": { "collapse": "0" }, "order": "0", "expressions": [ { "type": "comment", "subtype": "", "expression": "Bloc code de gestion", "options": [], "order": "0" } ] } ] } }, { "type": "element", "subtype": "", "expression": "2291", "options": [], "order": "9", "element": { "name": "", "type": "code", "options": [], "order": "0", "subElements": [ { "name": "", "type": "code", "subtype": "action", "options": { "collapse": "0", "enable": "1" }, "order": "0", "expressions": [ { "type": "code", "subtype": "", "expression": "$scenario->setLog(\" Début du script Assistant Domotique avec Gemini AI.\");\n\n\/\/ 1. Vérification de l’environnement PHP\nerror_reporting(E_ALL);\nini_set('display_errors', 1);\n$scenario->setLog(\" Test : Environnement PHP chargé avec succès.\");\n\n\/\/ 2. Pause\nsleep(2);\n\n\/\/ 3. Récupération des variables\n$apiKeyGemini = $scenario->getData(\"gemini_api_key\");\n$pieceIds = $scenario->getData(\"jeedom_piece_id\");\n$jeedomCapteurs = $scenario->getData(\"jeedom_capteurs\");\n$jeedomQuestionID = $scenario->getData(\"jeedom_question\");\n$jeedomSortieID = $scenario->getData(\"jeedom_sortie\");\n\n\/\/ 4. Vérification des valeurs\nif (\n empty($apiKeyGemini) ||\n empty($jeedomQuestionID) ||\n empty($jeedomSortieID) ||\n (empty($jeedomCapteurs) && empty($pieceIds))\n) {\n $scenario->setLog(\" Erreur : Une ou plusieurs variables essentielles sont manquantes.\");\n exit;\n}\n$scenario->setLog(\" API Key : OK\");\n$jeedomQuestion = cmd::byString($jeedomQuestionID)->execCmd();\n$scenario->setLog(\" Question posée : \\\"$jeedomQuestion\\\"\");\n\n\/\/ 5. Récupération des capteurs\n$listeCapteurs = [];\n\n\/\/ 5a. Si capteurs manuels définis, on les ajoute\nif (!empty($jeedomCapteurs)) {\n $scenario->setLog(\"Ajout des capteurs manuels.\");\n foreach (explode(\";\", $jeedomCapteurs) as $cap) {\n $listeCapteurs[] = trim($cap);\n }\n}\n\n\/\/ 5b. Si pièces définies, on récupère leurs capteurs\nif (!empty($pieceIds)) {\n foreach (explode(\";\", $pieceIds) as $pieceId) {\n $objet = jeeObject::byId((int)trim($pieceId));\n if (is_object($objet)) {\n $scenario->setLog(\"Pièce détectée : \" . $objet->getName());\n foreach (eqLogic::byObjectId($objet->getId()) as $eq) {\n foreach ($eq->getCmd('info') as $cmd) {\n if ($eq->getName() !== \"Résumé\") {\n $prefix = '#';\n\t\t\t\t\t\t$suffix = '#';\n\t\t\t\t\t\t$cmdFormat = $prefix . '[' . $objet->getName() . '][' . $eq->getName() . '][' . $cmd->getName() . ']' . $suffix;\n $listeCapteurs[] = $cmdFormat;\n }\n }\n }\n } else {\n $scenario->setLog(\"Pièce ID $pieceId introuvable.\");\n }\n }\n}\n\n\/\/ 5c. Sauvegarde de la liste fusionnée et affichage\nif (empty($listeCapteurs)) {\n $scenario->setLog(\"Erreur : aucune source de capteurs définie.\");\n exit;\n}\n$jeedomCapteurs = implode(\";\", $listeCapteurs);\n$scenario->setData(\"jeedom_capteurs\", $jeedomCapteurs);\n\/\/$scenario->setLog(\"Liste finale des capteurs : $jeedomCapteurs\");\n$scenario->setLog(\"Liste finale :\");\n\n\/\/ 5d. Extraction des données pour chaque capteur\n$capteursData = [];\nforeach ($listeCapteurs as $cap) {\n $cmd = cmd::byString(trim($cap));\n if (is_object($cmd) && $cmd->execCmd() !== '') {\n $valeur = $cmd->execCmd();\n $unite = $cmd->getUnite();\n $id = $cmd->getId();\n $nom = $cmd->getHumanName();\n $nomAvecId = \"$nom [ID: $id]\";\n $scenario->setLog(\"Capteur récupéré : $nomAvecId → $valeur$unite\");\n $capteursData[] = [\n \"id\" => $id,\n \"nom\" => $nomAvecId,\n \"valeur\"=> $valeur,\n \"unite\" => $unite\n ];\n }\n}\n\n\/\/ 6. Construction du prompt\n$prompt = \"Tu es un assistant domotique Jeedom qui analyse les relevés des capteurs.\\n\\n\";\n$prompt .= \"Capteurs détectés :\\n\";\nforeach ($capteursData as $d) {\n $prompt .= \"- {$d['nom']} : {$d['valeur']}{$d['unite']}\\n\";\n}\n$prompt .= \"\\nSi l'utilisateur fournit un ID (ex : 339805), utilise ce tableau pour faire la correspondance.\\n\\n\";\n$prompt .= \"Question : \\\"{$jeedomQuestion}\\\"\\n\\n\";\n$prompt .= \"Réponds en une seule phrase claire et pertinente.\\n\";\n\n\/\/ 7. Envoi à Gemini\n$payload = [\n \"contents\" => [\n [\n \"parts\" => [\n [\"text\" => $prompt]\n ]\n ]\n ]\n];\n\n$jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE);\nif ($jsonPayload === false) {\n $scenario->setLog(\" Erreur : JSON mal formé.\");\n exit;\n}\n\n$ch = curl_init();\ncurl_setopt($ch, CURLOPT_URL, \"https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-2.5-flash:generateContent?key=$apiKeyGemini\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n \"Content-Type: application\/json\",\n \"User-Agent: Jeedom-Gemini\"\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $jsonPayload);\ncurl_setopt($ch, CURLOPT_TIMEOUT, 30);\n\n$response = curl_exec($ch);\n$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n$curlError = curl_error($ch);\ncurl_close($ch);\n\n\/\/ 8. Lecture réponse\n$assistantResponse = \"Erreur : Aucune réponse générée.\";\n\nif ($response === false) {\n $scenario->setLog(\" Erreur CURL : \" . $curlError);\n $scenario->setLog(\" Code HTTP : $httpCode\");\n exit;\n} else {\n $scenario->setLog(\" Réponse HTTP reçue : $httpCode\");\n $responseData = json_decode($response, true);\n if (isset($responseData['candidates'][0]['content']['parts'][0]['text'])) {\n $assistantResponse = trim($responseData['candidates'][0]['content']['parts'][0]['text']);\n } else {\n $scenario->setLog(\" Réponse Gemini invalide : \" . print_r($responseData, true));\n }\n}\n\n\/\/ 9. Envoi dans Jeedom\n$cmdSortie = cmd::byId($jeedomSortieID);\nif (is_object($cmdSortie)) {\n $cmdSortie->event($assistantResponse);\n $scenario->setLog(\" Réponse envoyée : \\\"$assistantResponse\\\" à la question $jeedomQuestion\");\n} else {\n $scenario->setLog(\" Erreur : commande ID $jeedomSortieID introuvable.\");\n}\n\n$scenario->setLog(\" Fin du script Assistant Domotique Gemini AI.\");", "options": [], "order": "0" } ] } ] } } ] } ] } ] }