Bonjour Ă tous,
il y a quelques temps jâavais rĂ©digĂ© un tutoriel montrant comment utiliser Jeedom en Data-logger.
Jeedom : data-logger pour IPX800
Ce nouveau tutoriel vous montrera comment lire les donnĂ©es historisĂ©es sur Jeedom pour afficher un Graphique sur Dashboard ou Liveview de lâIPX800 V5.
Ce rĂ©sultat a nĂ©cessitĂ© un gros travail de recherche et dâoptimisation, câest pourquoi je vous le partage ici.
Nous aurons besoin du plugin Data Export pour générer un fichier CSV avec les datas.
Nous aurons Ă©galement besoin du plugin Script pour envoyer le contenu du CSV sous forme de Json, Ă lâinitiative de lâIPX800.
Le Plugin Data Export
- Connectez-vous Ă Jeedom : Ouvrez votre interface Jeedom dans un navigateur.
- Accédez à la gestion des plugins : Allez dans le menu
Plugins
âGestion des plugins
. - Installez le plugin Data Export :
- activez le plugin.
Configurer le plugin Data Export
- Accédez à la configuration du plugin : Allez dans
Plugins
âData Export
âConfiguration
.
Cochez la case Horodatage pour exporter les dates au format Timestamp.
-
Activez la commande puis configurez la pĂ©riode durant laquelle les datas seront extraites. Personnellement jâextrais les donnĂ©es sur 1 jour pour avoir un graphe rapide sur IPX800.
Activez lâEnvoi programmĂ© et programmez la rĂ©currence
-
SĂ©lectionnez la commande Ă extraire
Cliquez sur puis sélectionnez la donnée à extraire. Pensez à valider en haut de la liste.
Mon tutoriel concerne lâextraction dâune donnĂ©e unique, veillez Ă ne sĂ©lectionner quâune seule commande dans la liste. -
Allez sur lâonglet Archivage
Renseignez la rétention des fichiers CSV. Personnellement je ne conserve que le dernier fichier généré par le script. Il est donc remplacé toutes les 5minutes selon ma configuration CRON.
-
Exécutez un export CSV
Cliquez sur le bouton ![image|117x38,50%] pour générer le premier fichier csv.
Si vous sélectionnez le fichier généré, vous pourrez vérifier son contenu
-
Cliquez sur le bouton et relevez lâID de lâexport dont vous aurez besoin ultĂ©rieurement.
Dans notre exemple lâid est 38
Le plugin Script
Nous allons crĂ©er un script en php, que nous exĂ©cuterons directement Ă partir de son URL via le serveur Web de Jeedom. Nous utiliserons pour cela le plugin Script qui nous facilitera la mise en place du script et la gestion des droits dâaccĂšs.
Installez le plugin depuis le Market. Pensez Ă lâactiver.
-
Ajoutez un Ă©quipement en cliquant sur le bouton
-
Donnez un nom Ă lâĂ©quipement
-
Rattachez lâĂ©quipement Ă un Dashboard (parent) activez le puis rendez le visible.
-
Cliquez sur le bouton
configurez comme suit
Cliquez sur le crayon au dessus du champ requĂȘte afin dâouvrir lâĂ©diteur de script.
Ajoutez un nouveau fichier nommĂ© json.php puis collez ce code dans lâĂ©diteur
<?php
// RĂ©cupĂ©ration du paramĂštre `subfolder` passĂ© dans la requĂȘte
$subfolder = isset($_GET['subfolder']) ? $_GET['subfolder'] : '32';
// DĂ©finir le chemin vers le dossier DataExport
$basePath = realpath('/var/www/html/plugins/dataexport/data');
$folderPath = $basePath . '/' . $subfolder;
// VĂ©rifier si le dossier existe
if (!is_dir($folderPath)) {
echo json_encode(['error' => "Dossier inexistant : $subfolder"]);
return;
}
// Trouver le fichier CSV le plus récent
$latestFile = '';
$latestTime = 0;
foreach (glob($folderPath . '/*.csv') as $file) {
if (filemtime($file) > $latestTime) {
$latestFile = $file;
$latestTime = filemtime($file);
}
}
// Vérification si un fichier a été trouvé
if (!$latestFile) {
echo json_encode(['error' => 'Aucun fichier CSV trouvé']);
return;
}
// Lecture du contenu du fichier CSV et conversion en JSON
$data = [];
if (($handle = fopen($latestFile, 'r')) !== false) {
$headers = fgetcsv($handle, 0, ';'); // Lire les en-tĂȘtes
if ($headers === false) {
echo json_encode(['error' => 'Impossible de lire les en-tĂȘtes du fichier CSV']);
return;
}
// Supprimer le BOM des en-tĂȘtes
$headers[0] = preg_replace('/\x{FEFF}/u', '', $headers[0]);
while (($row = fgetcsv($handle, 0, ';')) !== false) {
$row = array_map(function ($value) {
return str_replace(',', '.', $value); // Convertit ',' en '.'
}, $row);
$rowData = array_combine($headers, $row);
if (isset($rowData['Date']) && isset($rowData['Commande']) && isset($rowData['Valeur']) && isset($rowData['Unité'])) {
$rowData['Date'] = intval($rowData['Date']); // Convertir le timestamp en entier
$rowData['Valeur'] = floatval($rowData['Valeur']); // Convertir la valeur en nombre flottant
$data[] = [
'Date' => $rowData['Date'],
'Commande' => $rowData['Commande'],
'Valeur' => $rowData['Valeur'],
'Unité' => $rowData['Unité']
];
}
}
fclose($handle);
} else {
echo json_encode(['error' => 'Impossible d\'ouvrir le fichier CSV']);
return;
}
// DĂ©finir l'en-tĂȘte Content-Type pour le texte brut
header('Content-Type: text/plain; charset=ISO-8859-1');
// Vérifier si des données ont été trouvées
if (empty($data)) {
echo json_encode(['error' => 'Aucune donnée trouvée dans le fichier CSV']);
return;
}
// Retourner les données en JSON encodé en texte brut
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
?>
Le script peut traiter nâimporte quel csv du plugin Data Export car il reçoit un ID en paramĂštre dans son URL. Il rĂ©cupĂšre le nom du fichier csv le plus rĂ©cent dans un sous-dossier de plugin\script\dataexport\data puis convertit son contenu au format Json.
Un seul script suffit, nul besoin dâen crĂ©er plusieurs mĂȘme si vous crĂ©ez plusieurs Ă©quipements Data Exports.
Revenez sur lâonglet Ă©quipement puis sĂ©lectionnez votre script en cliquant sur lâicone âč Dossier âș au dessus du champ âč RequĂȘte âș.
Cliquez sur le bouton âč configuration avancĂ©e âș puis relevez lâid du script (39 dans notre exemple)
Remarque : dans le code php, jâai renseignĂ© '32'
comme valeur par dĂ©faut Ă la variable subfolder. Câest lâid de mon export, cela me permet de vĂ©rifier le bon fonctionnement Ă partir du dashboard Jeedom directement (sans Tag dans lâURL).
Les CORS
Testez le script en entrant son URL dans votre navigateur :
http://<IP_JEEDOM>/plugins/script/data/json.php?subfolder=<subfolder>
Remplacez <IP_JEEDOM> par lâadresse IP de votre Jeedom, puis la variable <subfolder>
par lâid de lâĂ©quipement Data Export relevĂ© prĂ©cĂ©demment (32 dans mon cas).
Vous devriez obtenir des données json comme ceci:
[
{
"Date": 1734735656,
"Commande": "TEMP AIR",
"Valeur": 5.08,
"Unité": "ðC"
},
{
"Date": 1734739256,
"Commande": "TEMP AIR",
"Valeur": 5.19,
"Unité": "ðC"
},
{
"Date": 1734742857,
"Commande": "TEMP AIR",
"Valeur": 5.246666666,
"Unité": "ðC"
},
{
"Date": 1734746457,
"Commande": "TEMP AIR",
"Valeur": 5.1,
"Unité": "ðC"
}]
Si la page ne retourne pas les données au format JSON, il se peut que le dossier plugin/script/data ait des droits restreints.
Vous devez Ă©diter le fichier .htaccess de ce dossier.
Retournez sur lâonglet Ă©quipement de votre script, cliquez sur lâicone crayon au dessus du champ requĂȘte. Editez le fichier .htaccess et remplacez son contenu par le code suivant:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
</IfModule>
Widget simple graphique sur ipx800 V5
- Créez un widget de type HTML sur votre dashboard, puis collez ce code:
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
JS
Ce widget initialise la librairie nécessaire à la construction du graphique.
2. créez un autre widget HTML avec ce code:
<script>
// Variables globales pour la personnalisation
const jeedomUrl = 'http://<ip_Jeedom>/plugins/script/data/json.php';
const pointStyle = 'rect';
const pointRadius = 0.5;
const pointRadiusModal = 2;
const pointBackgroundColor = 'red';
const defaultSubfolder = '32';
const graphTitle="Température de l'eau";
let modal;
function convertTimestampToTime(t) {
const date = new Date(t * 1000);
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${hours}:${minutes}:${seconds}`;
}
function convertTimestampToDateTime(t) {
const date = new Date(t * 1000);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
async function startScenarioAndGetVariable(d) {
const subfolder = d; // Sous-dossier passé en paramÚtre
// Construire l'URL pour appeler directement le script qui génÚre le JSON
const startScriptUrl = `${jeedomUrl}?subfolder=${encodeURIComponent(subfolder)}`;
try {
// Appeler le script qui gĂ©nĂšre le JSON avec les en-tĂȘtes CORS
const response = await fetch(startScriptUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
mode: 'cors'
});
if (!response.ok) {
throw new Error('Erreur lors de l\'exécution du scénario');
}
// Extraire le contenu JSON directement depuis la réponse
const jsonData = await response.json();
// Vérification des données
if (!Array.isArray(jsonData) || jsonData.length === 0) {
throw new Error('Aucune donnée trouvée dans le JSON');
}
// Vérifier si la propriété 'Date' existe dans la premiÚre ligne
if (!jsonData[0].hasOwnProperty('Date')) {
throw new Error('La propriété "Date" est absente dans le JSON');
}
// Trier les données par date
jsonData.sort((a, b) => parseInt(a.Date, 10) - parseInt(b.Date, 10));
// Afficher les données sous forme de graphique
displayGraph(jsonData);
} catch (error) {
alert(`Erreur : ${error.message}`);
}
}
function displayGraph(data) {
// Extraire les labels (dates) et les valeurs
const labels = data.map(item => {
const timestamp = parseInt(item.Date, 10); // Convertir le timestamp Unix en millisecondes
return convertTimestampToTime(timestamp);
});
const values = data.map(item => {
const valeur = item.Valeur.toString().replace(',', '.'); // Convertir en chaĂźne et remplacer ',' par '.'
return parseFloat(valeur);
});
// Créer le graphique
const ctx = document.getElementById('dataChart').getContext('2d');
graph = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: graphTitle, // Utiliser le texte de l'option sélectionnée comme titre du graphique
data: values,
borderColor: 'blue',
borderWidth: 0.3,
fill: true,
backgroundColor: 'rgba(255, 255, 0, 0.7)',
pointRadius: pointRadius,
pointStyle: pointStyle,
pointBackgroundColor: pointBackgroundColor
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
title: {
display: true,
text: graphTitle, // Utiliser le texte de l'option sélectionnée comme titre du graphique
color:'blue',
font: { size: 18 // Taille de police du titre
}
}
},
scales: {
x: {
title: {
display: false
},
grid: { color: 'rgba(211, 211, 211, 0.6)' // Couleur de la grille en RGBA
},
ticks: {
color: 'blue'
}
},
y: {
title: {
display: false
},
grid: { color: 'rgba(211, 211, 211, 0.6)' // Couleur de la grille en RGBA
},
ticks: {
color: 'blue'
}
}
}
}
});
// Ajouter un Ă©vĂ©nement de clic pour ouvrir la fenĂȘtre modale
document.getElementById('dataChart').addEventListener('click', function() {
openModal(data);
});
}
function openModal(data) {
if (modal) {
document.body.removeChild(modal);
}
const labels = data.map(item => {
const timestamp = parseInt(item.Date, 10);
return convertTimestampToDateTime(timestamp);
});
const values = data.map(item => {
const valeur = item.Valeur.toString().replace(',', '.');
return parseFloat(valeur);
});
// CrĂ©er la fenĂȘtre modale
modal = document.createElement('div');
modal.style.position = 'fixed';
modal.style.top = '0';
modal.style.left = '0';
modal.style.width = '100%';
modal.style.height = '100%';
modal.style.backgroundColor = 'rgba(0, 0, 0, 0.95)'; // Diminuer la transparence
modal.style.display = 'flex';
modal.style.justifyContent = 'center';
modal.style.alignItems = 'center';
modal.style.zIndex = '1000';
// CrĂ©er le canvas pour le graphique dans la fenĂȘtre modale
const modalCanvas = document.createElement('canvas');
modalCanvas.id = 'modalChart';
modalCanvas.width = 1200;
modalCanvas.height = 600;
modal.appendChild(modalCanvas);
// Ajouter la fenĂȘtre modale au document
document.body.appendChild(modal);
// CrĂ©er le graphique dans la fenĂȘtre modale
const modalCtx = modalCanvas.getContext('2d');
new Chart(modalCtx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '', // Supprimer le titre du graphique
data: values,
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1, // Lignes fines
fill: true,
pointRadius: pointRadiusModal,
pointStyle: pointStyle,
pointBackgroundColor: pointBackgroundColor
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false // Supprimer la légende
},
},
scales: {
x: {
title: {
display: false // Supprimer le titre de l'axe X
},
ticks: {
color: 'white' // Mettre les heures en blanc
}
},
y: {
title: {
display: false // Supprimer le titre de l'axe Y
}
}
}
}
});
// Ajouter un Ă©vĂ©nement de clic pour fermer la fenĂȘtre modale
modal.addEventListener('click', function() {
document.body.removeChild(modal);
});
}
// Lancer la récupération des données pour un sous-dossier spécifique
startScenarioAndGetVariable(defaultSubfolder);
</script>
<meta charset="UTF-8">
<canvas id="dataChart" width="100%" height="100%"></canvas>
Modifiez ces 7 lignes de code
// Variables globales pour la personnalisation
const jeedomUrl = 'http://<ip_Jeedom>/plugins/script/data/json.php';
const pointStyle = 'rect';
const pointRadius = 0.5;
const pointRadiusModal = 2;
const pointBackgroundColor = 'red';
const defaultSubfolder = '32';
const graphTitle="Température de l'eau";
Renseignez les variables globales :
- <ip_jeedom> est lâadresse ip de votre installation Jeedom.
- pointStyle est la variable qui conditionne la forme des repĂšres sur la courbe. Les valeurs possibles peuvent ĂȘtre les suivantes:
- circle : Un cercle (valeur par défaut).
- cross : Une croix.
- crossRot : Une croix inclinée à 45 degrés.
- dash : Un tiret.
- line : Une ligne horizontale.
- rect : Un rectangle.
- rectRounded : Un rectangle avec des coins arrondis.
- rectRot : Un rectangle incliné à 45 degrés.
- star : Une Ă©toile.
- triangle : Un triangle.
- pointRadius est la taille du repĂšre sur la courbe
- pointBackgroundColor est la couleur du repĂšre
- defaultSubfolder : renseignez lâid du Data Export relevĂ© prĂ©cĂ©demment (âč 32 âș dans mon cas). Lâid correspond au nom du sous-dossier crĂ©Ă© par Data Export.
Si vous cliquez sur le graphique, une modale sâouvre en plein Ă©cran pour afficher le graph.
Widget multi-graphiques
Si vous souhaitez afficher le graphique de plusieurs données, préférez le widget suivant qui permettra la sélection de chaque graphique à afficher (1 à la fois), ne dupliquez pas le widget simple graphique sur le dashboard.
Créez le widget HTML et collez ce code:
<style>
/* Styles pour le panneau latéral */
#settings-panel {
position: absolute;
top: 20;
left: 20;
width: 0;
height: 100%;
background-color: rgba(111,111,111,0.8);
box-shadow: 2px 0 5px rgba(0,0,0,1);
transition: width 0.3s ease;
overflow: hidden;
}
#settings-panel.open {
width: 95%;
}
.close-btn {
position: absolute;
top: 10px;
right: 10px;
background-color: transparent;
border: none;
font-size: 1.5em;
cursor: pointer;
}
#gear-icon {
position: absolute;
top: 10px;
left: 12px;
font-size: 1.1em;
cursor: pointer;
}
.form-label {
font-size: 0.9em;
margin-left: 1em;
}
.form-select, .form-input {
margin: 10px 0;
margin-left: 1em;
}
</style>
<script>
// Variables globales pour la personnalisation
const jeedomUrl = 'http://<ip_jeedom>/plugins/script/data/json.php';
const pointStyle = 'rectRot';
const pointRadius = 0.5;
const pointRadiusModal = 2.5;
const pointBackgroundColor = 'red';
const defaultSubfolder = '32';
const sel2Options = [
{ value: '32', text: 'Température eau' },
{ value: '37', text: 'Température AIR' }
];
let graph, subfolder = defaultSubfolder, modal;
function togglePanel() {
const panel = document.getElementById('settings-panel');
panel.classList.toggle('open');
}
function populateSel2Options() {
const sel2 = document.getElementById('sel2');
sel2Options.forEach(option => {
const opt = document.createElement('option');
opt.value = option.value;
opt.text = option.text; sel2.appendChild(opt);
}); }
function convertTimestampToTime(t) {
const date = new Date(t * 1000);
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${hours}:${minutes}:${seconds}`;
}
function convertTimestampToDateTime(t) {
const date = new Date(t * 1000);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
async function fetchAndDisplayData() {
// Récupérer le texte de l'option sélectionnée
const selectElement = document.getElementById('sel2');
subfolder = selectElement.options[selectElement.selectedIndex].value;
const apiUrl = `${jeedomUrl}?subfolder=${encodeURIComponent(subfolder)}`;
try {
const response = await fetch(apiUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error('Erreur lors de la récupération des données');
}
const jsonData = await response.json();
if (!Array.isArray(jsonData) || jsonData.length === 0) {
throw new Error('Aucune donnée trouvée dans le JSON');
}
jsonData.sort((a, b) => parseInt(a.Date, 10) - parseInt(b.Date, 10));
if (graph) {
graph.destroy();
}
displayGraph(jsonData);
} catch (error) {
alert(`Erreur : ${error.message}`);
}
}
function displayGraph(data) {
const labels = data.map(item => {
const timestamp = parseInt(item.Date, 10);
return convertTimestampToTime(timestamp);
});
const values = data.map(item => {
const valeur = item.Valeur.toString().replace(',', '.');
return parseFloat(valeur);
});
// Récupérer le texte de l'option sélectionnée
const selectElement = document.getElementById('sel2');
const selectedText = selectElement.options[selectElement.selectedIndex].text;
const ctx = document.getElementById('dataChart').getContext('2d');
graph = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: selectedText, // Utiliser le texte de l'option sélectionnée comme titre du graphique
data: values,
borderColor: 'blue',
borderWidth: 0.3,
fill: true,
backgroundColor: 'rgba(255, 255, 0, 0.7)',
pointRadius: pointRadius,
pointStyle: pointStyle,
pointBackgroundColor: pointBackgroundColor
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
title: {
display: true,
text: selectedText, // Utiliser le texte de l'option sélectionnée comme titre du graphique
color:'blue',
font: { size: 18 // Taille de police du titre
}
}
},
scales: {
x: {
title: {
display: false
},
grid: { color: 'rgba(211, 211, 211, 0.6)' // Couleur de la grille en RGBA
},
ticks: {
color: 'blue'
}
},
y: {
title: {
display: false
},
grid: { color: 'rgba(211, 211, 211, 0.6)' // Couleur de la grille en RGBA
},
ticks: {
color: 'blue'
}
}
}
}
});
// Ajouter un Ă©vĂ©nement de clic pour ouvrir la fenĂȘtre modale
document.getElementById('dataChart').addEventListener('click', function() {
openModal(data);
});
}
function openModal(data) {
// Supprimer la fenĂȘtre modale prĂ©cĂ©dente si elle existe
if (modal) {
document.body.removeChild(modal);
}
const labels = data.map(item => {
const timestamp = parseInt(item.Date, 10);
return convertTimestampToDateTime(timestamp);
});
const values = data.map(item => {
const valeur = item.Valeur.toString().replace(',', '.');
return parseFloat(valeur);
});
// CrĂ©er la nouvelle fenĂȘtre modale
modal = document.createElement('div');
modal.style.position = 'fixed';
modal.style.top = '0';
modal.style.left = '0';
modal.style.width = '100%';
modal.style.height = '100%';
modal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; // Diminuer la transparence
modal.style.display = 'flex';
modal.style.justifyContent = 'center';
modal.style.alignItems = 'center';
modal.style.zIndex = '1000';
// CrĂ©er le canvas pour le graphique dans la fenĂȘtre modale
const modalCanvas = document.createElement('canvas');
modalCanvas.id = 'modalChart';
modalCanvas.width = '95%';
modalCanvas.height = '95%';
modal.appendChild(modalCanvas);
// Ajouter la fenĂȘtre modale au document
document.body.appendChild(modal);
// CrĂ©er le graphique dans la fenĂȘtre modale
const modalCtx = modalCanvas.getContext('2d');
new Chart(modalCtx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '', // Supprimer le titre du graphique
data: values,
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1, // Lignes fines
fill: true,
pointRadius: pointRadiusModal,
pointStyle: pointStyle,
pointBackgroundColor: pointBackgroundColor
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false // Supprimer la légende
},
},
scales: {
x: {
title: {
display: false // Supprimer le titre de l'axe X
},
ticks: {
color: 'white' // Mettre les heures en blanc
}
},
y: {
title: {
display: false // Supprimer le titre de l'axe Y
}
}
}
}
});
// Ajouter un Ă©vĂ©nement de clic pour fermer la fenĂȘtre modale
modal.addEventListener('click', function() {
document.body.removeChild(modal);
modal = null; // RĂ©initialiser la variable modal
});
}
function SelChange(){
togglePanel();
fetchAndDisplayData();
}
// Charger le graphique avec la premiÚre valeur par défaut
setTimeout(populateSel2Options, 300);
setTimeout(fetchAndDisplayData, 500);
setInterval(fetchAndDisplayData, 300000); // RafraĂźchir toutes les 5 minutes
</script>
<div id="gear-icon" onclick="togglePanel();">
âïž
</div>
<div id="settings-panel">
<button class="close-btn" onclick="togglePanel();">×</button>
<label class="form-label" for="sel2">Sélectionnez une donnée :</label>
<select class="form-select" id="sel2" onchange='SelChange()'></select>
</div>
<canvas id="dataChart" width="100%" height="100%"></canvas>
- Modifiez ces 9 lignes de code (vous trouverez le rĂŽle de chaque variable dans le descriptif plus haut) :
- La variable sel2Options est constituĂ©e dâun tableau contenant les diffĂ©rents graphiques Ă afficher. Value prend la valeur de lâid du Data Export pour chacun dâeux.
// Variables globales pour la personnalisation
const jeedomUrl = 'http://<ip_jeedom>/plugins/script/data/json.php';
const pointStyle = 'rectRot';
const pointRadius = 2;
const pointBackgroundColor = 'blue';
const defaultSubfolder = '32';
const sel2Options = [
{ value: '32', text: 'Température eau' },
{ value: '37', text: 'Température AIR' }
];
Dans cet exemple, nous souhaitons afficher 2 graphiques. Nous avons donc crĂ©Ă© 2 Data Export, respectivement pour la tempĂ©rature de lâeau et la tempĂ©rature de lâair.
lâattribut value prend lâid du Data Export crĂ©Ă© pour chaque donnĂ©e.
La roue dentĂ©e permet lâouverture dâun panneau latĂ©ral afin de sĂ©lectionner le graphique Ă afficher.
Comme prĂ©cĂ©demment, une modale est affichĂ©e lors dâun clic sur le graphique.
Une bulle dâinformation est affichĂ©e lors du survol de la courbe.
Adaptation au Liveview
les 2 widgets ci-dessus sont compatibles Liveview, ils se crĂ©ent de la mĂȘme façon que sur Dashboard et nĂ©cessitent aussi la mise en place de la librairie graph.js.
Il faut placer donc un widget et y mettre la référence de la librairie graph.js.
Remarque globale:
jâai choisi dâafficher des courbes simples, pour lâaffichage dâune seule donnĂ©e Ă la fois, afin de conserver un code lĂ©ger et privilĂ©gier les performances.
Si des graphiques plus complexes (multi-donnĂ©es, fonctions rĂ©capitulatives, âŠ) sont souhaitĂ©s, Jeedom reste lâoutil Ă utiliser.
Jâai remarquĂ© que parfois certaines valeurs sortaient de la sĂ©quence triĂ©e, je ne sais pas encore dâoĂč cela peut venir. Des glitch dans le csv ? un conflit dâaccĂšs aux donnĂ©es CSV (mĂ j par Jeedom pendant une rĂ©cupĂ©ration) ?
Bons graphiques.