Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Kamikaze

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    K
    • Profile
    • Following 0
    • Followers 0
    • Topics 22
    • Posts 138
    • Best 1
    • Groups 2

    Kamikaze

    @Kamikaze

    Pro

    1
    Reputation
    53
    Profile views
    138
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Kamikaze Follow
    Pro Starter

    Best posts made by Kamikaze

    • RE: Socket.io und conn.js

      @Homoran Erledigt. Ich hoffe mein English reicht dafür.
      Socket.io and conn.js and example index.html: No states #32

      posted in JavaScript
      K
      Kamikaze

    Latest posts made by Kamikaze

    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @jogibear9988 Danke schön. Jetzt habe ich alles, was ich brauche.
      Deine Lösung mit dem npm-Modul ist natürlich eleganter, was ich auch nutzen werde.
      Die Einbindung meiner Klasse hilft mir bei der zentralen Pflege.

      Grüße

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @jogibear9988 Hallo Jogibear,
      ich musste tatsächlich schmunzeln.

      1. Vielen Dank für deine Lösung. Das hat gut funktioniert.
      2. Du hast aber meine Frage nicht beantwortet.
        Wie würde ich solchen Dinge einbinden, wenn es kein npm-Modul gibt? Insbesondere meine eigenen Klasse?
        <script src="js/chartBuilder.js"></script>
      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      Jetzt ist es wieder an der Zeit, die Experten zu fragen:
      Ich habe mit chart.js mir ein Klasse geschrieben, die mir meine notwendigen Daten in Grafiken umsetzt. Das Ganze habe ich mit rein Javascript gemacht.
      Hierzu eine Index.html erstellt:

      <!DOCTYPE html>
      <html lang="de">
      
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Energieverbrauchs-Diagramm</title>
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
        <script src="js/chartBuilder.js"></script>
        <link rel="stylesheet" href="index.css">
      </head>
      
      <body>
        <div id="chartContainer">
          <div>
            <canvas id="houseYearlyChart"></canvas>
            <div class="legend" id="houseYearlyChartLegend"></div> <!-- Container für die Legende -->
          </div>
          <div>
            <canvas id="roomYearlyChart"></canvas>
            <div class="legend" id="roomYearlyChartLegend"></div> <!-- Container für die Legende -->
          </div>
          <div>
            <canvas id="roomMonthlyChart"></canvas>
            <div class="legend" id="roomMonthlyChartLegend"></div> <!-- Container für die Legende -->
          </div>
          <div>
            <canvas id="grossesDiagramm"></canvas>
            <div class="grossesDiagrammLegend" id="grossesDiagrammLegend"></div> <!-- Container für die Legende -->
          </div>
          <div>
            <canvas id="grossesDiagrammX"></canvas>
            <div class="grossesDiagrammLegend" id="grossesDiagrammXLegend"></div> <!-- Container für die Legende -->
          </div>
      
        </div>
      
        <script src="index.js"> </script>
         
      </body>
      
      </html>
      

      Chart.js als Script-Tag eingebaut, <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
      Meine Klasse hinzugefügt und ein kleines index.js zur Konfiguration der Grafik.

      const diagrammBasiswerte = {
          titlecolor: '#ffffff',
          fontsize: 12, // Schriftgröße: 12px
          fontfamily: 'Arial', // Schriftart: Arial
          fontstyle: 'italic', // Schriftstil: kursiv
          fontweight: 'bold', // Schriftgewicht: fett
          fontcolor: '#ffffff',
          maxRotation: 0,
          minRotation: 0,
      }
      
      
      const diagramConfigs = {
          houseYearlyChart: {
              chartjs_typ: 'bar', // bar oder line
              chartType: 'yearlyChart', // yearlyChart oder dailyChart
              datatype: 'absoluteValue', // 'absoluteValue' oder 'Counter' 
              year: '2025', // Jahr aus der Konfiguration
              month: '', // Nicht erforderlich für yearlyChart
              threshold: 30,
              showLegend: true, // Tabelle mit Legende 
              showPoints: false, // Punkte ausblenden
              devices: JSON.stringify([   // Geräte
                  { id: '7', name: 'Isttemperatur', type: 'absoluteValue', unit: '°C', normalizationFactor: 1, color: '#0000FF' },
              ]),
              options: {
                  datumsformat: { month: 'short' }, // --> 01.Jan.2024 { day: '2-digit', month: 'short', year: 'numeric' }
                  threshold: { label: 'Threshold', type: 'line', borderColor: '#FF0000', borderWidth: 4, fill: false, pointRadius: 0 },
                  durchschnitt: { label: 'Durchschnitt', type: 'line', borderColor: '#FFFFFF', borderWidth: 2, fill: false, pointRadius: 0 },
                  scales: {
                      x: {
                          title: { display: true, text: `Zeitraum 2024`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              maxRotation: diagrammBasiswerte.maxRotation,
                              minRotation: diagrammBasiswerte.minRotation,
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                      y: {
                          title: { display: true, text: `Temperatur (°C)`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                  },
              },
          },
          roomYearlyChart: {
              chartjs_typ: 'bar',
              chartType: 'yearlyChart',
              datatype: 'Counter', // 'absoluteValue' oder 'Counter' 
              year: '2024', // Jahr aus der Konfiguration
              month: '', // Nicht erforderlich für yearlyChart
              threshold: 300,
              showLegend: true,
              showPoints: true, // Punkte einblenden
              devices: JSON.stringify([
                  { id: '36', name: 'ac_energie', type: 'Counter', unit: 'kWh', normalizationFactor: 1000, color: '#00FF00' },
                  { id: '41', name: 'ac_energie_gesamt', type: 'Counter', unit: 'kWh', normalizationFactor: 1000, color: '#FFA500' },
              ]),
              options: {
                  datumsformat: { month: 'short' }, // --> 01.Jan.2024 { day: '2-digit', month: 'short', year: 'numeric' }
                  threshold: { label: 'Threshold', type: 'line', borderColor: '#FF0000', borderWidth: 4, fill: false, pointRadius: 0 },
                  durchschnitt: { label: 'Durchschnitt', type: 'line', borderColor: '#FFFFFF', borderWidth: 2, fill: false, pointRadius: 0 },
                  scales: {
                      x: {
                          title: { display: true, text: `Zeitraum 2024`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              maxRotation: diagrammBasiswerte.maxRotation,
                              minRotation: diagrammBasiswerte.minRotation,
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                      y: {
                          title: { display: true, text: `Energie (kWh)`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                  },
              },
          },
          roomMonthlyChart: {
              chartjs_typ: 'bar',
              chartType: 'dailyChart',
              datatype: 'Counter', // 'absoluteValue' oder 'Counter' 
              year: '2025', // Jahr aus der Konfiguration
              month: '3', // Monat für dailyChart
              threshold: 10,
              showLegend: true,
              showPoints: true, // Punkte einblenden
              devices: JSON.stringify([
                  { id: '41', name: 'ac_energie_gesamt', type: 'Counter', unit: 'kWh', normalizationFactor: 1000, color: '#FFFF00' },
                  { id: '36', name: 'ac_energie', type: 'Counter', unit: 'kWh', normalizationFactor: 1000, color: '#FF00FF' },
              ]),
              options: {
                  datumsformat: { day: '2-digit', month: 'short' }, // --> 01.Apr
                  threshold: { label: 'Threshold', type: 'line', borderColor: '#FF0000', borderWidth: 4, fill: false, pointRadius: 0 },
                  durchschnitt: { label: 'Durchschnitt', type: 'line', borderColor: '#FFFFFF', borderWidth: 2, fill: false, pointRadius: 0 },
                  scales: {
                      x: {
                          title: { display: true, text: `Zeitraum 2025`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              maxRotation: diagrammBasiswerte.maxRotation,
                              minRotation: diagrammBasiswerte.minRotation,
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                      y: {
                          title: { display: true, text: `Energie (kWh)`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                  },
              },
          },
          grossesDiagramm: {
              chartjs_typ: 'line', // bar oder line
              chartType: 'yearlyChart', // yearlyChart oder dailyChart
              datatype: 'Counter', // 'absoluteValue' oder 'Counter' 
              year: '2025', // Jahr aus der Konfiguration
              month: '', // Nicht erforderlich für yearlyChart
              threshold: 25,
              showLegend: true, // Tabelle mit Legende 
              showPoints: true, // Punkte ausblenden
              devices: JSON.stringify([   // Geräte
                  { id: '41', name: 'ac_energie_gesamt', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#0000FF' },
                  { id: '21', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FF0000' },
                  { id: '22', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FFFF00' },
                  { id: '23', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#000000' },
                  { id: '24', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FF00FF' },
                  { id: '25', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FFFFFF' },
      
      
              ]),
              options: {
                  datumsformat: { month: 'short' }, // --> 01.Jan.2024 { day: '2-digit', month: 'short', year: 'numeric' }
                  threshold: { label: 'Threshold', type: 'line', borderColor: '#FF0000', borderWidth: 4, fill: false, pointRadius: 0 },
                  durchschnitt: { label: 'Durchschnitt', type: 'line', borderColor: '#FFFFFF', borderWidth: 2, fill: false, pointRadius: 0 },
                  scales: {
                      x: {
                          title: { display: true, text: `Zeitraum 2024`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              maxRotation: diagrammBasiswerte.maxRotation,
                              minRotation: diagrammBasiswerte.minRotation,
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                      y: {
                          title: { display: true, text: `Temperatur (°C)`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                  },
              },
          },
          grossesDiagrammX: {
              chartjs_typ: 'line', // bar oder line
              chartType: 'yearlyChart', // yearlyChart oder dailyChart
              datatype: 'Counter', // 'absoluteValue' oder 'Counter' 
              year: '2024', // Jahr aus der Konfiguration
              month: '', // Nicht erforderlich für yearlyChart
              threshold: 25,
              showLegend: true, // Tabelle mit Legende 
              showPoints: true, // Punkte ausblenden
              devices: JSON.stringify([   // Geräte
                  { id: '26', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#0000FF' },
                  { id: '27', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FF0000' },
                  { id: '28', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FFFF00' },
                  { id: '29', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#000000' },
                  { id: '30', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FF00FF' },
                  { id: '31', name: 'ac_energie', type: 'Counter', unit: '°C', normalizationFactor: 1, color: '#FFFFFF' },
              ]),
              options: {
                  datumsformat: { month: 'short' }, // --> 01.Jan.2024 { day: '2-digit', month: 'short', year: 'numeric' }
                  threshold: { label: 'Threshold', type: 'line', borderColor: '#FF0000', borderWidth: 4, fill: false, pointRadius: 0 },
                  durchschnitt: { label: 'Durchschnitt', type: 'line', borderColor: '#FFFFFF', borderWidth: 2, fill: false, pointRadius: 0 },
                  scales: {
                      x: {
                          title: { display: true, text: `Zeitraum 2024`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              maxRotation: diagrammBasiswerte.maxRotation,
                              minRotation: diagrammBasiswerte.minRotation,
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                      y: {
                          title: { display: true, text: `Temperatur (°C)`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                  },
              },
          },
      };
      
      // Diagramme erstellen und Daten laden
      Object.keys(diagramConfigs).forEach((chartId) => {
          const config = diagramConfigs[chartId];
          const apiUrl = `/api/sqlData?devices=${encodeURIComponent(config.devices)}&year=${config.year}&chartType=${config.chartType}${config.chartType === 'dailyChart' ? `&month=${config.month}` : ''}`;
      
          fetch(apiUrl)
              .then((response) => {
                  if (!response.ok) throw new Error(`Fehler: ${response.statusText}`);
                  return response.json();
              })
              .then((data) => {
                  const chartBuilder = new ChartBuilder(chartId, `${chartId}Legend`);
                  chartBuilder.create(config.chartjs_typ, config.datatype, data, config.showLegend, config.threshold, config.showPoints, config.year, config.options);
              })
              .catch((error) => console.error(`Fehler beim Laden des Diagramms ${chartId}:`, error));
      });
      

      Jetzt die Frage an die Experten:
      Wo und wie binde ich die externen Elemente in webui ein.
      <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
      <script src="js/chartBuilder.js"></script>

      Meine Klasse habe ich als Beispiel einfach im Javascript-Teil des Controls mit eingebunden. Das geht auch bestimmt anders.
      Aber wie ich das mit chart.js mache erschließt sich mir nicht. Ich erhalte immer die Meldung, dass Chart nicht existiert.

      <script src="http://192.168.110.10:8082/webui.0.data/config/additionalfiles/chart.js"></script>
      <div id="chartContainer" style="position:absolute;left:97px;top:26px;width:476px;height:170px;">
          <div>
              <canvas id="YearlyChart"></canvas>
              <div class="legend" id="YearlyChartLegend"></div>
          </div>
          <script src="http://192.168.110.10:8082/webui.0.widgets/importmap.js"></script>
      </div>
      

      Hier noch das javascript-Modul

      /**
      * @param {BaseScreenViewerAndControl} instance
      */
      
      const diagrammBasiswerte = {
          titlecolor: '#ffffff',
          fontsize: 12, // Schriftgröße: 12px
          fontfamily: 'Arial', // Schriftart: Arial
          fontstyle: 'italic', // Schriftstil: kursiv
          fontweight: 'bold', // Schriftgewicht: fett
          fontcolor: '#ffffff',
          maxRotation: 0,
          minRotation: 0,
      }
      
      const diagramConfigs = {
          YearlyChart: {
              chartjs_typ: 'bar', // bar oder line
              chartType: 'yearlyChart', // yearlyChart oder dailyChart
              datatype: 'absoluteValue', // 'absoluteValue' oder 'Counter' 
              year: '2025', // Jahr aus der Konfiguration
              month: '', // Nicht erforderlich für yearlyChart
              threshold: 30,
              showLegend: true, // Tabelle mit Legende 
              showPoints: false, // Punkte ausblenden
              devices: JSON.stringify([   // Geräte
                  { id: '7', name: 'Isttemperatur', type: 'absoluteValue', unit: '°C', normalizationFactor: 1, color: '#0000FF' },
              ]),
              options: {
                  datumsformat: { month: 'short' }, // --> 01.Jan.2024 { day: '2-digit', month: 'short', year: 'numeric' }
                  threshold: { label: 'Threshold', type: 'line', borderColor: '#FF0000', borderWidth: 4, fill: false, pointRadius: 0 },
                  durchschnitt: { label: 'Durchschnitt', type: 'line', borderColor: '#FFFFFF', borderWidth: 2, fill: false, pointRadius: 0 },
                  scales: {
                      x: {
                          title: { display: true, text: `Zeitraum 2024`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              maxRotation: diagrammBasiswerte.maxRotation,
                              minRotation: diagrammBasiswerte.minRotation,
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                      y: {
                          title: { display: true, text: `Temperatur (°C)`, color: diagrammBasiswerte.titlecolor },
                          ticks: {
                              font: {
                                  size: diagrammBasiswerte.fontsize,
                                  family: diagrammBasiswerte.fontfamily,
                                  style: diagrammBasiswerte.fontstyle,
                                  weight: diagrammBasiswerte.fontweight,
                              },
                              color: diagrammBasiswerte.fontcolor,
                          },
                      },
                  },
              },
          },
      };
      
      export function init(instance,shadowRoot) {
          console.log(instance);
          console.log(shadowRoot);
          console.log(instance.query);
          const cssid = instance._getDomElement('chartContainer');
          console.log(cssid);
          instance.query = "Ich bin blöd";
          console.log(instance.query);
          IOB.setState('0_userdata.0.Funktionen.DatabaseQuery',instance.query);
          const result2 = instance.result;
          console.log(result2);
          const result = IOB.getState('0_userdata.0.Funktionen.DatabaseResult');
          console.log(JSON.stringify(instance,null,2));
          Object.keys(diagramConfigs).forEach((chartId) => {
             const config = diagramConfigs[chartId];
             const data=instance.result
             const chartBuilder = new ChartBuilder(chartId, `${chartId}Legend`,instance);
             chartBuilder.create(instance,config.chartjs_typ, config.datatype, data, config.showLegend, config.threshold, config.showPoints, config.year, config.options);
          });
      }
      
      class ChartBuilder {
          constructor(canvasId, legendId,instance) {
              this.ctx = instance._getDomElement(canvasId).getContext('2d');
              // this.ctx = document.getElementById(canvasId).getContext('2d');
              this.chartInstance = null;
              this.legendId = legendId;
          }
      
          create(instance,chartjs_typ, datatype, data, showLegend, threshold, showPoints, year, options = {}) {
              this.renderChart(instance,chartjs_typ,datatype, data, showLegend, threshold, showPoints, year, options);
          }
      
          renderChart(instance,chartjs_typ, datatype, data, showLegend, threshold, showPoints, year, options) {
              if (this.chartInstance) this.chartInstance.destroy();
      
              const legendContainer = instance._getDomElement(this.legendId);
              // const legendContainer = document.getElementById(this.legendId);
              if (!legendContainer) {
                  console.error(`Legenden-Element mit ID "${this.legendId}" nicht gefunden.`);
                  return;
              }
              legendContainer.style.display = showLegend ? 'block' : 'none';
              legendContainer.innerHTML = ''; // Reset legend
      
              const labels = [...new Set(data.map((entry) => {
                  const formattedDate = new Date(entry.period).toLocaleDateString('de-DE', options.datumsformat);
                  if (isNaN(new Date(entry.period).getTime())) {
                      console.error(`Invalid Date: ${entry.period}`); // Debugging für fehlerhafte Werte
                  }
                  return formattedDate;
              }))];
      
              // Daten nach Geräten gruppieren
              const deviceData = {};
              const statistics = {};
      
              data.forEach((entry) => {
                  if (!deviceData[entry.device_id]) {
                      deviceData[entry.device_id] = {
                          label: entry.device_name || 'Unbekanntes Gerät',
                          unit: entry.unit || 'Einheit unbekannt',
                          color: entry.color || '#000000',
                          data: Array(labels.length).fill(0),
                          backgroundColor: entry.color,
                          borderColor: entry.color,
                          fill: false,
                          pointRadius: showPoints ? 5 : 0,
                      };
      
                      // Statistikinitialisierung
                      statistics[entry.device_id] = {
                          total: 0,
                          count: 0,
                          max: -Infinity,
                          min: Infinity,
                      };
                  }
      
                  // Datenwerte für das Dataset hinzufügen
                  const index = labels.indexOf(new Date(entry.period).toLocaleDateString('de-DE', options.datumsformat));
                  if (index >= 0) {
                      const normalizedValue = datatype === 'absoluteValue' ? entry.average_value / entry.normalizationFactor : entry.total_value / entry.normalizationFactor; // Differenziere Werte basierend auf Diagrammtyp
                      deviceData[entry.device_id].data[index] = normalizedValue;
      
                      // Statistik berechnen
                      statistics[entry.device_id].total += normalizedValue;
                      statistics[entry.device_id].count += 1;
                      statistics[entry.device_id].max = Math.max(statistics[entry.device_id].max, normalizedValue);
                      statistics[entry.device_id].min = Math.min(statistics[entry.device_id].min, normalizedValue);
                  }
              });
      
              // Durchschnittslinien und Threshold als Linien-Datensätze
              const averageData = Array(labels.length).fill(
                  Object.keys(statistics).reduce((avg, deviceId) => avg + (statistics[deviceId].total / statistics[deviceId].count || 0), 0) / Object.keys(statistics).length
              );
              const thresholdData = Array(labels.length).fill(threshold);
      
              // Wenn es sich um ein Balkendiagramm handelt, werden Durchschnitt und Threshold als Linien dargestellt
              const additionalDatasets = (chartjs_typ === 'bar' || chartjs_typ === 'line')
                  ? [
                      {
                          label: options.threshold?.label  ||  'Threshold',
                          data: thresholdData,
                          type: options.threshold?.type  ||  'line', // Linie für Threshold im Balkendiagramm
                          borderColor: options.threshold?.borderColor  ||  '#FF0000',
                          borderWidth: options.threshold?.borderWidth  ||  2,
                          fill: options.threshold?.fill  ||  false,
                          pointRadius: options.threshold?.pointRadius  ||  0,
                      },
                      {
                          label: options.durchschnitt?.label || 'Durchschnitt',
                          data: averageData,
                          type: options.durchschnitt?.type || 'line', // Linie für Durchschnitt im Balkendiagramm
                          borderColor: options.durchschnitt?.borderColor || '#0000FF',
                          borderWidth: options.durchschnitt?.borderWidth || 2,
                          fill: options.durchschnitt?.label || false,
                          pointRadius: options.durchschnitt?.pointRadius || 0,
                      },
                  ]
                  : [];
      
              const datasets = [
                  ...Object.values(deviceData),
                  ...additionalDatasets, // Linien für Balkendiagramme hinzufügen
              ];
      
              this.chartInstance = new Chart(this.ctx, {
                  type: chartjs_typ,
                  data: { labels, datasets },
                  options: {
                      ...options,
                      responsive: true,
                      plugins: {
                          legend: { display: false }, // Deaktiviere interne Diagrammlegende vollständig
                      },
                      scales: {
                          x: {
                              
                              ticks: {
                                  callback: function(value, index, ticks) {
                                      // Verwende die `labels`-Variable direkt in der Callback-Funktion
                                      const date = labels[index];
                                      return date || 'Invalid Date'; // Fallback für fehlerhafte Werte
                                  },
                              },
                              ...options.scales?.x, // Nutze die angepassten X-Achsenoptionen aus der index.html
                          },
                          y: options.scales?.y || {
                              title: { display: true, text: `Werte (${deviceData[Object.keys(deviceData)[0]].unit})` },
                              ticks: {
                                  font: {
                                      size: 24,
                                      family: 'Arial, sans-serif',
                                      weight: 'normal',
                                  },
                                  color: '#ffffff',
                              },
                          },
                      },
                  },
              });
      
              // Tabellarische Legende
              legendContainer.innerHTML = `
              <table style="width:100%; border-collapse:collapse;">
                <tr style="background-color:#f4f4f4; text-align:left;">
                  <th>Gerät</th>
                  <th>Farbe</th>
                  <th>Durchschnitt</th>
                  <th>Maximum</th>
                  <th>Minimum</th>
                </tr>
                ${Object.keys(deviceData).map(deviceId => `
                  <tr>
                    <td>${deviceData[deviceId].label}</td>
                    <td style="background-color:${deviceData[deviceId].color};"></td>
                    <td>${(statistics[deviceId].total / statistics[deviceId].count).toFixed(2)} ${deviceData[deviceId].unit}</td>
                    <td>${statistics[deviceId].max.toFixed(2)} ${deviceData[deviceId].unit}</td>
                    <td>${statistics[deviceId].min.toFixed(2)} ${deviceData[deviceId].unit}</td>
                  </tr>
                `).join('')}
              </table>
            `;
          }
      }
      

      In der Zeile 193 (this.chartInstance = new Chart(this.ctx, {) steigt das Programm aus, mit der Meldung: Chart existiert nicht.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @jogibear9988 Hallo,
      erst einmal vielen Dank für deinen Vorschlag. Zwar noch nicht ganz, was ich mir wünsche, aber schon gut brauchbar.
      Ich werde noch ein wenig experimentieren. Ihr braucht Euch nicht damit aufzuhalten.

      Ich komme noch einmal auf das Problem vom 4 Mar 2025, 18:49 zurück.

      Screenshot 2025-03-15 163004.png

      <webui-elemente--beschriftung-temperatur inputsignal="alias.0.Geräte.Heizung.Heizung_Wohnzimmer.Isttemperatur" status="0_userdata.0.Räume.Wohnzimmer.Geräte.Heizung_Wohnzimmer.eigenschaften.deviceStatus" style="position:absolute;left:23px;top:65px;"></webui-elemente--beschriftung-temperatur>
      <webui-elemente--beschriftung-temperatur inputsignal="alias.0.Geräte.Heizung.Heizung_Wohnzimmer.Solltemperatur" status="0_userdata.0.Räume.Wohnzimmer.Geräte.Heizung_Wohnzimmer.eigenschaften.deviceStatus" bind-prop:inputsignal="alias.0.Geräte.Heizung.Heizung_Wohnzimmer.Solltemperatur;parseFloat(__0).toFixed(1) + ' °C'" style="position:absolute;left:23px;top:122px;"></webui-elemente--beschriftung-temperatur>
      <webui-elemente--beschriftung-temperatur bind-prop:inputsignal="alias.0.Geräte.Heizung.Heizung_Wohnzimmer.Isttemperatur;parseFloat(__0).toFixed(1) + ' °C'" status="0_userdata.0.Räume.Wohnzimmer.Geräte.Heizung_Wohnzimmer.eigenschaften.deviceStatus" style="position:absolute;left:76px;top:90px;width:64px;height:16px;"></webui-elemente--beschriftung-temperatur>
      <webui-elemente--beschriftung-temperatur bind-prop:inputsignal="alias.0.Geräte.Heizung.Heizung_Wohnzimmer.Solltemperatur;parseFloat(__0).toFixed(1) + ' °C'" status="0_userdata.0.Räume.Wohnzimmer.Geräte.Heizung_Wohnzimmer.eigenschaften.deviceStatus" style="position:absolute;left:81px;top:148px;width:64px;height:16px;"></webui-elemente--beschriftung-temperatur>
      
      

      Die Ursache habe ich herausgefunden auch warum ich da bei Euch nicht nachbilden konnte.
      Wenn Ihr die vier Zeilen vergleicht, werdet ihr feststellen, dass die letzten zwei korrekt sind und auch permanent funktionieren.
      Die erste zwei nur nach Zufall gleich beim ersten Aufruf.

      Das kommt davon, wenn man mit den Ergebnisses der ersten Schritte über Copy&Paste arbeitet.
      Aufgefallen ist das, weil ein Raum immer funktionierte und diese Definition habe ich jetzt verglichen.

      Danke für eure Hilfe und bis zum nächsten Mal.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @jogibear9988 Sorry, das Konsolenthema hatte ich nicht erwähnt. Nein, es kommen keine Fehlermeldungen.
      Wir legen das Thema solange auf Eis, bis ich das Nachstellen kann, bzw. ich eine Lösung für den Fernzugriff etabliert habe.
      Derzeit habe ich auch noch andere Projekte, die meine Aufmerksamkeit benötigen.
      Aber vielleicht kannst du ja einem "unfähigen" 😏 bei der anderen Sache noch helfen.
      Ich bin zu blöd, bei dem Dialog, dass CSS so zu stylen, dass alle Rahmenelemente unsichtbar sind.
      Screenshot 2025-03-07 081435.png

      Bedeutet: Alles blaue, gelbe und weisses soll nicht sichtbar sein, inkl. der Kopfzeile.

      Der Screen enthält ein gefülltes Rechteck mit 440*540 Pixel. Nur diesen Inhalt möchte ich sehen, wenn ich OpenDialog verwende.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @kamikaze Ich habe noch etwas herausgefunden:
      Wenn ich einen Screenwechsel mache, sind die Daten daraufhin auf der Homepage verfügbar.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @jogibear9988 Hallo,
      Zu 1.: Ich habe das Vorgehen exakt auf deinem testserver nachgebaut.
      a.) control erstellt (ScreenBeschriftungSignal)
      b.) Screen erstellt der das control verwendet (ScreenBeschriftungSignal)
      b.i) dort inputsignal auf ein Binding gelegt, beinhaltet den anzuzeigenen Wert
      b.ii) status auf ein IOB signal gelegt (steuert den Hintergrund des Wertes
      c.) Screen erstellt (BasicScreen) mit einem Button und dem Screen ScreenBeschriftungSignal
      c.i) den Button habe ich mit einem Click-Event ausgestattet, der eine boolschen Wert vom IOBroker toggelt.
      c.ii) beim Screen ScreenBeschriftungSignal habe ich display genutzt, um in Abhängigkeit von true/false block/none für diesem Screen zu steuern.

      Leider konnte ich bei dir den Problemfall nicht reproduzieren.

      zu 2. Wenn man es richtig macht, geht es auch. Mit dem Styling muss ich erst einmal ein wenig experimentieren um es so hinzubekommen, dass es mir gefällt.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @jogibear9988 Hallo Jogibear,
      Stufe 1 mit meinem Problem scheint wirklich gelöst zu sein, jedoch ist mir in diesem Zusammenhang noch etwas aufgefallen:
      Öffne ich jetzt einige meiner Fenster, dann erhalte ich manchmal keine Werte von den Signalen

      Screenshot 2025-03-04 184103.png

      Öffne ich den Screen direkt, dann sind die Werte da:
      Screenshot 2025-03-04 184123.png

      Danach sind sie auch auf der Homepage verfügbar.

      #####################################
      Stufe 2: OpenDialog
      Ich gehe davon aus, dass du dich nur verschrieben hast (openInDialog). Sowie ich dich verstanden habe, soll ich das Styling in den Stylesheet der Homepage einbauen. Das habe ich gemacht, leider hat das Styling keine Auswirkung.

      Screenshot 2025-03-04 184719.png

      iobroker-webui-dialog.myspecial::part(close) {
          background: red;
      }
      iobroker-webui-dialog.myspecial::part(head) {
          background: yellow;
      }
      iobroker-webui-dialog.myspecial::part(box) {
          border: 5px solid black;
      }
      iobroker-webui-dialog.myspecial::part(content) {
          overflow: hidden;
      }
      

      #####################################
      Btw. Ein fantastisches Produkt und ein gutes hilfbereites Team dahinter.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @smilie108 Das glaube ich gerne. Je Usecase legt man eben andere Massstäbe. Btw. Wenn ich das richtig gelesen habe, bist du dabei Grafana-Grafiken einzubinden?
      Wenn das richtig ist, wäre ich an einigen Informationen interessiert, wie du das machst.

      posted in Visualisierung
      K
      Kamikaze
    • RE: neue Visualisierung "webui" (alternative zu vis & vis-2)

      @smilie108 Das hat geholfen. Leider gefällt mir der obere Balken mit der Titel Beschriftung nicht. Hast du noch eine kreative Idee?

      posted in Visualisierung
      K
      Kamikaze
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo