FHEM Forum

FHEM => Codeschnipsel => Thema gestartet von: schwatter am 09 Juni 2025, 23:37:53

Titel: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 09 Juni 2025, 23:37:53
Tag,

ich habe an einer Minichartcard gebastelt.

Die erste Variante ist ein Mix aus HTML, SVG und Perl (Mehr Performance, schwieriger anzupassen) . Die zweite Variante ist ein Mix aus HTML, SVG und Echart (Weniger Performance, leichter anzupassen).
Zum Datensammeln nutze ich eine Perl-Sub in 99_myUtils.pm plus 2 at. Das eine schreibt kontinuierlich ein Array, das andere nullt um Mitternacht. Anstatt einem at
für das Array, kann auch ein notify verwendet werden. Dadurch ergeben sich dann eher Livedaten,
aber als Nachteil viel mehr Daten.


1. Daten sammeln (Array)

1.1. Error abfangen

Neues Reading in dem Device eurer Wahl anlegen

setreading <mydevice> chartArray 0
Damit wird eine Fehlermeldung verhindert.

1.2.1 Ringbuffer,in Perl-Sub in 99_myUtils.pm einfügen

Hiermit wird ein Ringbuffer der letzten 50 Werte erzeugt. Kommt einer dazu, wird der Älteste gekickt.
Dadurch entfällt Löschen um Mitternacht.

sub AppendToFixedArray {
  my ($dev, $reading, $newVal, $maxSize) = @_;
  $maxSize //= 50;
  my $current = ReadingsVal($dev, $reading, '');
  my @values = split(',', $current);
  if (@values >= $maxSize) {
    @values = @values[-($maxSize - 1) .. -1];
  }
  push @values, $newVal;
  return join(',', @values);
}

1.2.2. Das passende at für Ringbuffer

defmod chartUpdate at +*00:05 {\
  my $val = ReadingsVal("Smartmeter_2E1F50", "APOX_Power", 0);;\
  my $new = AppendToFixedArray("Smartmeter_2E1F50", "chartArray", $val);;\
  fhem("setreading Smartmeter_2E1F50 chartArray $new");;\
}

1.3.1. Kontinuierliches Array, in Perl-Sub in 99_myUtils.pm einfügen

sub AppendToArray {
  my ($dev, $reading, $newVal) = @_;
  my $current = ReadingsVal($dev, $reading, '');
  my @values = split(',', $current);
  push @values, $newVal;
  return join(',', @values);
}

1.3.2. at für array

defmod chartUpdate at +*00:05 {\
  my $val = ReadingsVal("Smartmeter_2E1F50", "APOX_Power", 0);;\
  my $new = AppendToArray("Smartmeter_2E1F50", "chartArray", $val);;\
  fhem("setreading Smartmeter_2E1F50 chartArray $new");;\
}

1.3.3. at zum nullen um Mitternacht

defmod chartReset at *00:00:00 {\
  my $val = ReadingsVal("Smartmeter_2E1F50", "APOX_Power", 0);;\
  fhem("setreading Smartmeter_2E1F50 chartArray $val");;\
}


2. Chartcard mit Perl. Mehr Performance, schwieriger zu modifizieren

2.1. Chartcard Line

im Anhang

2.2. Chartcard Bar

im Anhang


3. Chartcard mit Echarts. Weniger Performnace, einfacher zu modifizieren

3.1. echarts kopieren

echarts.min.js aus dem Anhang nach /fhem/www/codemirror/echarts.min.js. Eigentümer:fhem,Gruppe:dialout

3.2. Neustart

"shutdown restart"


3.3. stateformat

stateformat im Device anlegen

<style>
  div#NamevonEuremDevice {
      pointer-events: none;
  }
</style>

<!-- Lade echarts direkt -->
<script src="/fhem/www/codemirror/echarts.min.js"></script>

<!-- Chart-Container -->
<div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
 
  <!-- Labels -->
  <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
    <div>Currently</div>
    <div>Today in</div>
    <div>Today out</div>
  </div>

  <!-- Werte -->
  <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; white-space: normal; word-wrap: break-word; display: flex; flex-direction: column;">
    <div>APOX_Power W</div>
    <div>statAPOX_E_inDay kWh</div>
    <div>statAPOX_E_outDay kWh</div>
  </div>

  <!-- Chart -->
  <div style="position:absolute; top:10px; right:10px; width:160px; height:72px; overflow:hidden;">
    <div id="minichart2" style="width:160px; height:72px;"></div>
  </div>
</div>

<script>
  var chart = echarts.init(document.getElementById('minichart2'));
  var fullData = [chartArray];
  var finalArray = fullData.slice(-30);
  var option = {
    grid: { top: 3, bottom: 0, left: 0, right: 0 },
    xAxis: { type: 'category', show: false, data: [] },
    yAxis: { type: 'value', show: false },
    series: [{
      data: finalArray,
      type: 'line',
      smooth: true,
      symbol: 'none',
      lineStyle: { width: 2, color: '#3b82f6' },
      areaStyle: { color: 'rgba(59,130,246,0.2)' }
    }],
    animation: false,
    tooltip: { show: false }
  };
  chart.setOption(option);
</script>

- In <div class="label" wird der Readingname gesetzt.
- In <div class="value" einfach ein Reading vom Device eintragen.
- Den Devicenamen in div#NamevonEuremDevice eintragen. Damit wird der Mousehover unterdrückt.




3.4. Beispiele mit dummys

3.4.1. Netzfequenz mit einem Reading

defmod Netzfrequenz dummy
attr Netzfrequenz room miniChart
attr Netzfrequenz stateFormat <style>\
  div#Netzfrequenz {\
      pointer-events: none;;\
  } \
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:180px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:100px;; position:relative;;">\
 \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Netzfrequenz</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>49.999 Hz</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:45px;; left:10px;; width:160px;; height:50px;; overflow:hidden;;">\
    <div id="minichart" style="width:160px;; height:50px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('minichart'));;\
  var fullData = [chartArray];;\
  var finalArray = fullData.slice(-130);;\
  var option = {\
    grid: { top: 3, bottom: 3, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: [] },\
    yAxis: { type: 'value',\
            show: false,\
                min: function(value) {\
                  return value.min;;\
                },\
                max: function(value) {\
              return value.max;;\
                }\
              },\
    series: [{\
      data: finalArray,\
      type: 'line',\
      smooth: true,\
      symbol: 'none',\
      lineStyle: { width: 2, color: '#3b82f6' },\
      areaStyle: { color: 'rgba(59,130,246,0.2)' }\
    }],\
    animation: false,\
    tooltip: { show: false }\
  };;\
  chart.setOption(option);;\
</script>

setstate Netzfrequenz <style>\
  div#Netzfrequenz {\
      pointer-events: none;;\
  } \
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:180px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:100px;; position:relative;;">\
 \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Netzfrequenz</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>49.999 Hz</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:45px;; left:10px;; width:160px;; height:50px;; overflow:hidden;;">\
    <div id="minichart" style="width:160px;; height:50px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('minichart'));;\
  var fullData = [50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999];;\
  var finalArray = fullData.slice(-130);;\
  var option = {\
    grid: { top: 3, bottom: 3, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: [] },\
    yAxis: { type: 'value',\
            show: false,\
                min: function(value) {\
                  return value.min;;\
                },\
                max: function(value) {\
              return value.max;;\
                }\
              },\
    series: [{\
      data: finalArray,\
      type: 'line',\
      smooth: true,\
      symbol: 'none',\
      lineStyle: { width: 2, color: '#3b82f6' },\
      areaStyle: { color: 'rgba(59,130,246,0.2)' }\
    }],\
    animation: false,\
    tooltip: { show: false }\
  };;\
  chart.setOption(option);;\
</script>
setstate Netzfrequenz 2025-06-11 18:46:49 chartArray 50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999



3.4.2. Netzfequenz mit 1 Reading und Icon oben rechts

defmod Netzfrequenz dummy
attr Netzfrequenz room miniChart
attr Netzfrequenz stateFormat <style>\
  div#Netzfrequenz {\
      pointer-events: none;;\
  } \
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:100px;; position:relative;;">\
 \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Netzfrequenz</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>49.999 Hz</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:45px;; left:10px;; width:350px;; height:50px;; overflow:hidden;;">\
    <div id="minichart" style="width:350px;; height:50px;;"></div>\
  </div>\
\
  <!-- SVG-Logo oben rechts -->\
  <img src="/fhem/www/images/default/icoBlitz.png" style="position:absolute;; top:10px;; right:10px;; width:24px;; height:24px;;" alt="Logo">\
\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('minichart'));;\
  var fullData = [chartArray];;\
  var finalArray = fullData.slice(-130);;\
  var option = {\
    grid: { top: 3, bottom: 3, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: [] },\
    yAxis: { type: 'value',\
            show: false,\
                min: function(value) {\
                  return value.min;;\
                },\
                max: function(value) {\
              return value.max;;\
                }\
              },\
    series: [{\
      data: finalArray,\
      type: 'line',\
      smooth: true,\
      symbol: 'none',\
      lineStyle: { width: 2, color: '#3b82f6' },\
      areaStyle: { color: 'rgba(59,130,246,0.2)' }\
    }],\
    animation: false,\
    tooltip: { show: false }\
  };;\
  chart.setOption(option);;\
</script>

setstate Netzfrequenz <style>\
  div#Netzfrequenz {\
      pointer-events: none;;\
  } \
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:100px;; position:relative;;">\
 \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Netzfrequenz</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>49.999 Hz</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:45px;; left:10px;; width:350px;; height:50px;; overflow:hidden;;">\
    <div id="minichart" style="width:350px;; height:50px;;"></div>\
  </div>\
\
  <!-- SVG-Logo oben rechts -->\
  <img src="/fhem/www/images/default/icoBlitz.png" style="position:absolute;; top:10px;; right:10px;; width:24px;; height:24px;;" alt="Logo">\
\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('minichart'));;\
  var fullData = [50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999];;\
  var finalArray = fullData.slice(-130);;\
  var option = {\
    grid: { top: 3, bottom: 3, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: [] },\
    yAxis: { type: 'value',\
            show: false,\
                min: function(value) {\
                  return value.min;;\
                },\
                max: function(value) {\
              return value.max;;\
                }\
              },\
    series: [{\
      data: finalArray,\
      type: 'line',\
      smooth: true,\
      symbol: 'none',\
      lineStyle: { width: 2, color: '#3b82f6' },\
      areaStyle: { color: 'rgba(59,130,246,0.2)' }\
    }],\
    animation: false,\
    tooltip: { show: false }\
  };;\
  chart.setOption(option);;\
</script>
setstate Netzfrequenz 2025-06-11 18:46:49 chartArray 50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999

3.4.3. Netzfequenz mit 3 Readings

defmod Netzfrequenz dummy
attr Netzfrequenz room miniChart
attr Netzfrequenz stateFormat <style>\
  div#Netzfrequenz {\
      pointer-events: none;;\
  } \
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:90px;; position:relative;;">\
 \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Aktuell</div>\
    <div>Zeit</div>\
    <div>Datum</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>49.999 Hz</div>\
    <div>18:55</div>\
    <div>11.06.25</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:10px;; right:10px;; width:160px;; height:72px;; overflow:hidden;;">\
    <div id="minichart" style="width:160px;; height:72px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('minichart'));;\
  var fullData = [chartArray];;\
  var finalArray = fullData.slice(-130);;\
  var option = {\
    grid: { top: 3, bottom: 3, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: [] },\
    yAxis: { type: 'value',\
            show: false,\
                min: function(value) {\
                  return value.min;;\
                },\
                max: function(value) {\
              return value.max;;\
                }\
              },\
    series: [{\
      data: finalArray,\
      type: 'line',\
      smooth: true,\
      symbol: 'none',\
      lineStyle: { width: 2, color: '#3b82f6' },\
      areaStyle: { color: 'rgba(59,130,246,0.2)' }\
    }],\
    animation: false,\
    tooltip: { show: false }\
  };;\
  chart.setOption(option);;\
</script>

setstate Netzfrequenz <style>\
  div#Netzfrequenz {\
      pointer-events: none;;\
  } \
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:90px;; position:relative;;">\
 \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Aktuell</div>\
    <div>Zeit</div>\
    <div>Datum</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>49.999 Hz</div>\
    <div>18:55</div>\
    <div>11.06.25</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:10px;; right:10px;; width:160px;; height:72px;; overflow:hidden;;">\
    <div id="minichart" style="width:160px;; height:72px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('minichart'));;\
  var fullData = [50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999];;\
  var finalArray = fullData.slice(-130);;\
  var option = {\
    grid: { top: 3, bottom: 3, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: [] },\
    yAxis: { type: 'value',\
            show: false,\
                min: function(value) {\
                  return value.min;;\
                },\
                max: function(value) {\
              return value.max;;\
                }\
              },\
    series: [{\
      data: finalArray,\
      type: 'line',\
      smooth: true,\
      symbol: 'none',\
      lineStyle: { width: 2, color: '#3b82f6' },\
      areaStyle: { color: 'rgba(59,130,246,0.2)' }\
    }],\
    animation: false,\
    tooltip: { show: false }\
  };;\
  chart.setOption(option);;\
</script>
setstate Netzfrequenz 2025-06-11 18:46:49 chartArray 50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999


3.4.4. Smartmeter Line positive rot/ negative grün

defmod miniSmartmeter dummy
attr miniSmartmeter room miniChart
attr miniSmartmeter stateFormat <style>\
  div#miniSmartmeter {\
      pointer-events: none;;\
  }\
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:90px;; position:relative;;">\
  \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Currently</div>\
    <div>Today in</div>\
    <div>Total out</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>currently_01 W</div>\
    <div>todayIn_01 kWh</div>\
    <div>todayOut_01 kWh</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:10px;; right:10px;; width:160px;; height:72px;; overflow:hidden;;">\
    <div id="miniSmartmeterChart" style="width:160px;; height:72px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('miniSmartmeterChart'));;\
  var rawData = [chartArray];;\
  var finalArray = rawData.slice(-30);;\
  var positiveData = [];;\
  var negativeData = [];;\
\
  for (var i = 0;; i < finalArray.length;; i++) {\
    var v = finalArray[i];;\
    if (v >= 0) {\
      positiveData.push(v);;\
      negativeData.push(i > 0 && finalArray[i - 1] < 0 ? 0 : null);;\
    } else {\
      negativeData.push(v);;\
      positiveData.push(i > 0 && finalArray[i - 1] >= 0 ? 0 : null);;\
    }\
  }\
\
  var option = {\
    grid: { top: 3, bottom: 0, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: finalArray.map((_, i) => i) },\
    yAxis: { type: 'value', show: false },\
    series: [\
      {\
        data: positiveData,\
        type: 'line',\
        smooth: true,\
        symbol: 'none',\
        lineStyle: { width: 2, color: 'red' },\
        areaStyle: { color: 'rgba(255,0,0,0.2)' },\
        markLine: {\
          silent: true,\
          symbol: 'none',\
          data: [{ yAxis: 0 }],\
          lineStyle: { color: 'grey', width: 1, type: 'solid' }\
        }\
      },\
      {\
        data: negativeData,\
        type: 'line',\
        smooth: true,\
        symbol: 'none',\
        lineStyle: { width: 2, color: 'green' },\
        areaStyle: { color: 'rgba(0,255,0,0.2)' }\
      }\
    ],\
    animation: false,\
    tooltip: { show: false }\
  };;\
\
  chart.setOption(option);;\
</script>\


setstate miniSmartmeter <style>\
  div#miniSmartmeter {\
      pointer-events: none;;\
  }\
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:90px;; position:relative;;">\
  \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Currently</div>\
    <div>Today in</div>\
    <div>Total out</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>-800 W</div>\
    <div>200 kWh</div>\
    <div>3200 kWh</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:10px;; right:10px;; width:160px;; height:72px;; overflow:hidden;;">\
    <div id="miniSmartmeterChart" style="width:160px;; height:72px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('miniSmartmeterChart'));;\
  var rawData = [200,200,250,200,200,100,50,0,0,-50,-100,-150,-200,-200,-300,-350,-410,-455,-510,-630,-800];;\
  var finalArray = rawData.slice(-30);;\
  var positiveData = [];;\
  var negativeData = [];;\
\
  for (var i = 0;; i < finalArray.length;; i++) {\
    var v = finalArray[i];;\
    if (v >= 0) {\
      positiveData.push(v);;\
      negativeData.push(i > 0 && finalArray[i - 1] < 0 ? 0 : null);;\
    } else {\
      negativeData.push(v);;\
      positiveData.push(i > 0 && finalArray[i - 1] >= 0 ? 0 : null);;\
    }\
  }\
\
  var option = {\
    grid: { top: 3, bottom: 0, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: finalArray.map((_, i) => i) },\
    yAxis: { type: 'value', show: false },\
    series: [\
      {\
        data: positiveData,\
        type: 'line',\
        smooth: true,\
        symbol: 'none',\
        lineStyle: { width: 2, color: 'red' },\
        areaStyle: { color: 'rgba(255,0,0,0.2)' },\
        markLine: {\
          silent: true,\
          symbol: 'none',\
          data: [{ yAxis: 0 }],\
          lineStyle: { color: 'grey', width: 1, type: 'solid' }\
        }\
      },\
      {\
        data: negativeData,\
        type: 'line',\
        smooth: true,\
        symbol: 'none',\
        lineStyle: { width: 2, color: 'green' },\
        areaStyle: { color: 'rgba(0,255,0,0.2)' }\
      }\
    ],\
    animation: false,\
    tooltip: { show: false }\
  };;\
\
  chart.setOption(option);;\
</script>\

setstate miniSmartmeter 2025-06-12 15:48:19 chartArray 200,200,250,200,200,100,50,0,0,-50,-100,-150,-200,-200,-300,-350,-410,-455,-510,-630,-800
setstate miniSmartmeter 2025-06-12 15:50:24 currently_01 -800
setstate miniSmartmeter 2025-06-12 13:11:19 todayIn_01 200
setstate miniSmartmeter 2025-06-12 13:11:37 todayOut_01 3200


3.4.5. Smartmeter Bar positive rot/ negative grün

defmod miniSmartmeter1 dummy
attr miniSmartmeter1 room miniChart
attr miniSmartmeter1 stateFormat <style>\
  div#miniSmartmeter1 {\
      pointer-events: none;;\
  }\
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:90px;; position:relative;;">\
  \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Currently</div>\
    <div>Today in</div>\
    <div>Total out</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>currently_01 W</div>\
    <div>todayIn_01 kWh</div>\
    <div>todayOut_01 kWh</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:10px;; right:10px;; width:160px;; height:72px;; overflow:hidden;;">\
    <div id="miniSmartmeterChart1" style="width:160px;; height:72px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('miniSmartmeterChart1'));;\
  var rawData = [chartArray];;\
  var finalArray = rawData.slice(-30);;\
  var positiveData = finalArray.map((v, i) => v >= 0 ? v : (i > 0 && finalArray[i - 1] >= 0 ? 0 : null));;\
  var negativeData = finalArray.map((v, i) => v < 0 ? v : (i > 0 && finalArray[i - 1] < 0 ? 0 : null));;\
\
  var option = {\
    grid: { top: 3, bottom: 0, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: finalArray.map((_, i) => i) },\
    yAxis: { type: 'value', show: false },\
    series: [\
      {\
        data: positiveData,\
        type: 'bar',\
        symbol: 'none',\
        smooth: true,\
        itemStyle: { color: 'red' },\
        markLine: {\
          silent: true,\
          symbol: 'none',\
          data: [{ yAxis: 0 }],\
          lineStyle: { color: 'grey', width: 1, type: 'solid' }\
        }\
      },\
      {\
        data: negativeData,\
        type: 'bar',\
        smooth: true,\
        symbol: 'none',\
        itemStyle: { color: 'green' }\
      }\
    ],\
    animation: false,\
    tooltip: { show: false }\
  };;\
\
  chart.setOption(option);;\
</script>

setstate miniSmartmeter1 <style>\
  div#miniSmartmeter1 {\
      pointer-events: none;;\
  }\
</style>\
\
<!-- Lade echarts direkt -->\
<script src="/fhem/www/codemirror/echarts.min.js"></script>\
\
<!-- Chart-Container -->\
<div style="width:365px;; padding:10px;; border:1px solid #ddd;; border-radius:6px;; font-family:sans-serif;; box-shadow:0 2px 4px rgba(0,0,0,0.1);; box-sizing:border-box;; height:90px;; position:relative;;">\
  \
  <!-- Labels -->\
  <div style="position:absolute;; top:10px;; left:10px;; width:90px;; font-size:14px;; text-align:left;; line-height:26px;;">\
    <div>Currently</div>\
    <div>Today in</div>\
    <div>Total out</div>\
  </div>\
\
  <!-- Werte -->\
  <div style="position:absolute;; top:10px;; left:80px;; width:120px;; font-size:14px;; font-weight:bold;; text-align:center;; line-height:26px;; white-space: normal;; word-wrap: break-word;; display: flex;; flex-direction: column;;">\
    <div>-800 W</div>\
    <div>200 kWh</div>\
    <div>3200 kWh</div>\
  </div>\
\
  <!-- Chart -->\
  <div style="position:absolute;; top:10px;; right:10px;; width:160px;; height:72px;; overflow:hidden;;">\
    <div id="miniSmartmeterChart1" style="width:160px;; height:72px;;"></div>\
  </div>\
</div>\
\
<script>\
  var chart = echarts.init(document.getElementById('miniSmartmeterChart1'));;\
  var rawData = [200,200,250,200,200,100,50,0,0,-50,-100,-150,-200,-200,-300,-350,-410,-455,-510,-630,-800];;\
  var finalArray = rawData.slice(-30);;\
  var positiveData = finalArray.map((v, i) => v >= 0 ? v : (i > 0 && finalArray[i - 1] >= 0 ? 0 : null));;\
  var negativeData = finalArray.map((v, i) => v < 0 ? v : (i > 0 && finalArray[i - 1] < 0 ? 0 : null));;\
\
  var option = {\
    grid: { top: 3, bottom: 0, left: 0, right: 0 },\
    xAxis: { type: 'category', show: false, data: finalArray.map((_, i) => i) },\
    yAxis: { type: 'value', show: false },\
    series: [\
      {\
        data: positiveData,\
        type: 'bar',\
        symbol: 'none',\
        smooth: true,\
        itemStyle: { color: 'red' },\
        markLine: {\
          silent: true,\
          symbol: 'none',\
          data: [{ yAxis: 0 }],\
          lineStyle: { color: 'grey', width: 1, type: 'solid' }\
        }\
      },\
      {\
        data: negativeData,\
        type: 'bar',\
        smooth: true,\
        symbol: 'none',\
        itemStyle: { color: 'green' }\
      }\
    ],\
    animation: false,\
    tooltip: { show: false }\
  };;\
\
  chart.setOption(option);;\
</script>
setstate miniSmartmeter1 2025-06-12 15:48:19 chartArray 200,200,250,200,200,100,50,0,0,-50,-100,-150,-200,-200,-300,-350,-410,-455,-510,-630,-800
setstate miniSmartmeter1 2025-06-12 15:50:24 currently_01 -800
setstate miniSmartmeter1 2025-06-12 13:11:19 todayIn_01 200
setstate miniSmartmeter1 2025-06-12 13:11:37 todayOut_01 3200


Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: carlos am 10 Juni 2025, 11:01:13
Hallo Schwatter,
Gleich mal ausprobiert, gefällt mir gut.
Problem gab es gleich mit den styles, die ich verwende.

Beim F18 sieht es so aus:
Bildschirmfoto 2025-06-10 um 10.48.44.png

Beim Flex leider so:
Bildschirmfoto 2025-06-10 um 10.49.01.png

Hab beim Flex leider öfter Probleme auch die doif charts funktionieren nicht so gut.

Erweiterungsvorschlag:
Eine 0 linie da power auch negativ wrden kann.


Ansonsten gute Arbeit.

Gruß

Hubert
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 10 Juni 2025, 11:36:40
Moin,

ja der flex wieder. Hatte gestern kurz geschaut und gleich die Augen verdreht  :)
Mal sehen was das wieder ist.
Das mit der 0 Line ist nicht unbedingt nötig. Da dreht sich der blaue Schleier.
Aber ich schaue.

Danke für die Rückmeldung. Btw, einfach 2mal den Code so in einem Raum verwendet funktioniert nicht.
Da müssen ein paar Klassen und Co. geändert werden.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 10 Juni 2025, 14:32:45
Next try,

ausgedünnt + funktioniert bei mir in f18 und flex

<div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
 
  <!-- Labels -->
  <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
    <div>Currently</div>
    <div>Today</div>
    <div>Total out</div>
  </div>

  <!-- Werte -->
  <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; white-space: normal; word-wrap: break-word; display: flex; flex-direction: column;">
    <div>total.Power.v W</div>
    <div>total.YieldDay.v Wh</div>
    <div>total.YieldTotal.v kWh</div>
  </div>

  <!-- Chart -->
  <div style="position:absolute; top:10px; right:10px; width:160px; height:72px; overflow:hidden;">
    <div id="chart1" style="width:160px; height:72px;"></div>
  </div>

</div>

<script>
  if (typeof echarts === "undefined") {
    var script = document.createElement("script");
    script.src = "https://cdn.jsdelivr.net/npm/echarts@5";
    script.onload = initChart;
    document.head.appendChild(script);
  } else {
    initChart();
  }

  function initChart() {
    var chart1 = echarts.init(document.getElementById('chart1'));
    var option = {
      grid: { top: 3, bottom: 0, left: 0, right: 0 },
      xAxis: { type: 'category', show: false, data: [] },
      yAxis: { type: 'value', show: false },
      series: [{
        data: [1, 2, 3, 2, 5, 3, 2, 4],
        type: 'line',
        smooth: true,
        symbol: 'none',
        lineStyle: { width: 2, color: '#3b82f6' },
        areaStyle: { color: 'rgba(59,130,246,0.2)' }
      }],
      animation: false,
      tooltip: { show: false }
    };
    chart1.setOption(option);
  }
</script>

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: carlos am 10 Juni 2025, 15:06:22
Super sehr gut, bei mir auch.
Danke
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 10 Juni 2025, 19:45:54
Manchmal mag Fhem die letzte Anpassung nicht im stateformat. Eigentlich müsste es ausgelagert werden.
Mal sehen. Also nicht verwundert sein wenn es knallt, ich weiß Bescheid.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: JoWiemann am 10 Juni 2025, 20:39:34
Hallo,

gefällt mir. Ich habe zwei Punkte:

- wie kann ich die Skalierung ändern. Ich monitore die Netzfrequenz und die schwankt ja eher zwischen 49.x und 50.x

- es werden ja Daten von https://cdn.jsdelivr.net/npm/echarts geholt. Ich würde die lieber lokal halten.

Grüße Jörg
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 10 Juni 2025, 21:03:41
So ich denke ich hab es,

- Prüfung entfernt. Script wird direkt am Anfang geladen.
- @JoWiemann Script herunterladen. In einen Fhempfad legen, Neustart und Pfad im Script auf Lokal ändern. Müsste funktionieren.
- @JoWiemann Zu Netz Frequenz. Normalerweise passt sich die Höhe dem größten Wert an. Funktioniert nicht so wie gewünscht?
- Abgesehen davon habe ich jetzt fullData.slice(-30) hinzugefügt. Damit kann die Zeitspanne beeinflusst werden.
Bedeutet in Verbindung mit dem at 5min x 30 = 150min. Bzw die letzten 150min. Vorher waren es immer 24std. Bisschen viel.
- Damit die Readings funktionieren, weiterhin einfach den Readingnamen unter Werte eintragen.
- Sowie unter Labels den Namen vergeben.
- Damit der Minichart in einen anderen Device funktioniert, müssen nur noch 2 Stellen einzigartig sein:

<div id="minichartEinzigartig " style="width:160px; height:72px;"></div>
var chart = echarts.init(document.getElementById('minichartEinzigartig '));


<!-- Lade echarts direkt -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5"></script>

<!-- Chart-Container -->
<div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
 
  <!-- Labels -->
  <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
    <div>Currently</div>
    <div>Today</div>
    <div>Today out</div>
  </div>

  <!-- Werte -->
  <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; white-space: normal; word-wrap: break-word; display: flex; flex-direction: column;">
    <div>total.Power.v W</div>
    <div>total.YieldDay.v Wh</div>
    <div>total.YieldTotal.v kWh</div>
  </div>

  <!-- Chart -->
  <div style="position:absolute; top:10px; right:10px; width:160px; height:72px; overflow:hidden;">
    <div id="minichart" style="width:160px; height:72px;"></div>
  </div>
</div>

<script>
  var chart = echarts.init(document.getElementById('minichart'));
  var fullData = [chartArray];
  var finalArray = fullData.slice(-30);
  var option = {
    grid: { top: 3, bottom: 0, left: 0, right: 0 },
    xAxis: { type: 'category', show: false, data: [] },
    yAxis: { type: 'value', show: false },
    series: [{
      data: finalArray,
      type: 'line',
      smooth: true,
      symbol: 'none',
      lineStyle: { width: 2, color: '#3b82f6' },
      areaStyle: { color: 'rgba(59,130,246,0.2)' }
    }],
    animation: false,
    tooltip: { show: false }
  };
  chart.setOption(option);
</script>

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: JoWiemann am 10 Juni 2025, 21:37:34
Hallo,

anbei das js in der Version 5.0

Bei einer Standardinstallation von fhem:

<script src="http://xxx.xxx.xxx.xxx:8083/fhem/www/echarts.min.js"></script>


Grüße Jörg
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: JoWiemann am 10 Juni 2025, 21:41:17
Hallo,

leider funktioniert die Skalierung nicht. Anbei mal der Inhalt eines Readings chartArray.

50.00,49.997,49.996,49.996,49.996,49.996,49.996,49.995,49.995,49.995,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.994,49.993,49.993,49.993,49.993,49.994,49.994,49.995,49.995,49.995,49.996,49.998,49.999,49.999,49.999,50.000,50.000,50.000,50.000,50.000,50.000,50.000,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999,49.999

Danke und Grüße

Jörg

PS: mit folgender Änderung funktioniert es jetzt:
yAxis: { type: 'value',
    show: false,
             min: function(value) {
               return value.min;
             },
             max: function(value) {
               return value.max;
             }
          },
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 10 Juni 2025, 22:26:27
Super,

haste schnell hinbekommen. Wenn man ein bisschen in der eCharts Doku schmökert findet man einiges.
Den Pfad ändere mal so
<script src="/fhem/www/codemirror/echarts.min.js"></script>Bzw. ab /fhem reicht. Dann wohin du willst. Ich werde morgen den ersten Post überarbeiten und auch eChart lokal
mit einpflegen. Nehme dein Beispiel mit auf.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 11 Juni 2025, 20:41:10
Nabend,

erstes Post überarbeitet und auch ein paar Beispiele als dummy's hinzugefügt.


Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 12 Juni 2025, 16:25:43
@carlos

Hier 2 dummys zum testen. Beide für Smartmeter. Positive rot, negative grün und eine Linie für 0.

Code entfernt. Angepasst und hinzugefügt in #1. Das "if" im Code wurde ab und zu von Fhem beim erzeugen gelöscht.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: carlos am 12 Juni 2025, 16:36:22
Cool, gefält mir. Das wird ja immer besser.
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: Damian am 12 Juni 2025, 18:52:19
Eine nette Idee. Die hatte ich auch schon vor paar Jahren, deswegen hatte ich damals schon Perlfunktionen definiert, die das gleiche leisten und noch einiges mehr. Da kommt man dann mit wenigen Zeilen aus.

Aber es ist immer schön, wenn man selber was auf die Beine stellt.
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 12 Juni 2025, 19:48:06
Deine Ringe nutze ich auch gerne. Zum Beispiel im devStateIcon.

{ui_Table::temp_hum_ring(ReadingsVal("THsensorBk","temperature",0),ReadingsVal("THsensorBk","humidity",0))}

Aber ich wollte mal ausbrechen und schauen.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: Damian am 12 Juni 2025, 20:04:47
Zitat von: schwatter am 12 Juni 2025, 19:48:06Deine Ringe nutze ich auch gerne. Zum Beispiel im devStateIcon.

{ui_Table::temp_hum_ring(ReadingsVal("THsensorBk","temperature",0),ReadingsVal("THsensorBk","humidity",0))}

Aber ich wollte mal ausbrechen und schauen.

Gruß schwatter

Ja, es ist immer gut selber was zu machen, oft entwickelt sich ein größeres Projekt mit der Zeit.

P.S. Man kann übrigens im deviStateIcon eines Devices auch die ui_Table::card-Funktion verwenden, die solche Verläufe visualisiert

Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 12 Juni 2025, 22:47:34
Das habe ich aufm Schirm. Wollte es aber absichtlich spartanischer und visuell flexibel.
Funktional is deine Card natürlich besser.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 02 Juli 2025, 22:17:12
Nabend,

hier ein Beispiel für stateFormat ohne Echarts. Nur Html, SVG und Perl. Dadurch viel effizienter.

{
  my @v = (split /,/, ReadingsVal('Smartmeter_2E1F50','chartArray',''))[-40..-1];  # letzte 40 Werte

  my ($min, $max) = (sort {$a <=> $b} @v)[0,-1];
  $max //= 0; $min //= 0;
  my $range = $max - $min || 1;

  # SVG-Zielgröße (angepasst!)
  my $width  = 160;
  my $height = 70;

  my $w = $width / (@v - 1 || 1);

  # y-Position der Null-Linie
  my $y0 = $height - ((0 - $min) / $range * $height);

  # Punkte vorbereiten
  my @points = map {
    [ $_ * $w, $height - (($v[$_] - $min)/$range * $height), $v[$_] ]
  } 0..$#v;

  my $bar_width = $w * 0.6;

  my $bars_svg = join "", map {
    my ($x, $y, $val) = @{$points[$_]};
    my $color = $val >= 0 ? 'red' : 'green';

    if ($val >= 0) {
      my $bar_height = $y0 - $y;
      sprintf(
        '<rect x="%.2f" y="%.2f" width="%.2f" height="%.2f" fill="%s" opacity="0.8" />',
        $x - $bar_width/2, $y, $bar_width, $bar_height, $color
      );
    } else {
      my $bar_height = $y - $y0;
      sprintf(
        '<rect x="%.2f" y="%.2f" width="%.2f" height="%.2f" fill="%s" opacity="0.8" />',
        $x - $bar_width/2, $y0, $bar_width, $bar_height, $color
      );
    }
  } 0..$#points;

  my $current_power = ReadingsVal('Smartmeter_2E1F50','APOX_Power', '--');
  my $todayIn       = ReadingsVal('Smartmeter_2E1F50','statAPOX_E_inDay', '--');
  my $todayOut      = ReadingsVal('Smartmeter_2E1F50','statAPOX_E_outDay', '--');

  return qq{
    <style>
      div#Smartmeter_2E1F50 { pointer-events:none; }
    </style>
    <div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
      <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
        <div>Currently</div><div>Today in</div><div>Total out</div>
      </div>
      <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; display:flex; flex-direction:column; white-space:normal; word-wrap:break-word;">
        <div>${current_power} W</div><div>${todayIn} Wh</div><div>${todayOut} kWh</div>
      </div>
      <div style="position:absolute; top:10px; right:10px; width:160px; height:70px; overflow:hidden;">
        <svg style="width:160px!important; height:70px!important; display:block;" viewBox="0 0 160 70" preserveAspectRatio="none">
          $bars_svg
        </svg>
      </div>
    </div>
  };
}


Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 03 Juli 2025, 13:40:44
Tag,

und hier noch als Line mit Html,SVG und Perl + Farbschleier. Das Post vorher habe ich auch nochmal angepasst. Die Viewbox war falsch skaliert.

{
  my @v = (split /,/, ReadingsVal('OpenDTU','chartArray',''))[-40..-1];  # letzte 40 Werte

  my ($min, $max) = (sort {$a <=> $b} @v)[0,-1];
  $max //= 0; $min //= 0;
  my $range = $max - $min || 1;

  # Zielgröße der SVG
  my $width = 155;
  my $height = 65;

  my $w = $width / (@v - 1 || 1);  # Abstand zwischen Punkten

  # Punkte berechnen
  my @points = map {
    my $x = $_ * $w;
    my $y = $height - (($v[$_] - $min) / $range * $height);
    [$x, $y]
  } 0..$#v;

  # Linie (Pfade) erzeugen
  my $path_d = "M" . join(" L", map { sprintf("%.2f,%.2f", @$_) } @points);

  # Fläche unter der Linie
  my $area_path_d = $path_d . sprintf(" L%.2f,%.2f L0,%.2f Z", $width, $height, $height);

  # Werte auslesen
  my $current_power = ReadingsVal('OpenDTU','total.Power.v', '--');
  my $todayIn = ReadingsVal('OpenDTU','total.Power.v', '--');
  my $todayOut = ReadingsVal('OpenDTU','total.YieldTotal.v', '--');

  return qq{
    <style>
      div#OpenDTU { pointer-events:none; }
    </style>
    <div style="width:365px; padding:10px; border:1px solid #ddd; border-radius:6px; font-family:sans-serif; box-shadow:0 2px 4px rgba(0,0,0,0.1); box-sizing:border-box; height:90px; position:relative;">
     
      <!-- Labels -->
      <div style="position:absolute; top:10px; left:10px; width:90px; font-size:14px; text-align:left; line-height:26px;">
        <div>Currently</div><div>Today in</div><div>Total out</div>
      </div>

      <!-- Werte -->
      <div style="position:absolute; top:10px; left:80px; width:120px; font-size:14px; font-weight:bold; text-align:center; line-height:26px; display:flex; flex-direction:column; white-space:normal; word-wrap:break-word;">
        <div>${current_power} W</div><div>${todayIn} Wh</div><div>${todayOut} kWh</div>
      </div>

      <!-- SVG-Chart -->
      <div style="position:absolute; top:10px; right:10px; width:160px; height:70px; overflow:hidden;">
        <svg style="width:160px!important; height:70px!important; display:block;" viewBox="0 0 160 70" preserveAspectRatio="xMidYMid meet">
          <path d="$area_path_d" fill="rgba(59,130,246,0.2)" />
          <path d="$path_d" fill="none" stroke="#3b82f6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
        </svg>
      </div>
    </div>
  };
}


Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 05 Juli 2025, 12:03:18
Mahlzeit,

ich habe Post #1 überarbeitet. Es ist jetzt nach Perl und Echart gegliedert. Für Perl habe ich 2 Beispieldummys erstellt.
Das Board hat gemeckert beim Code einfügen, daher als Anhang.

Perlvariante.
- alle wichtigen Variablen am Anfang
- Bei chartCardLinePerl ist Moving Average enthalten. Wer das nicht braucht kann den Codeblock # Moving Average löschen.
- Bei chartCardLinePerl ist eine gepunktete Nulllinie enthalten. Wer das nicht braucht, einfach #<!-- Null-Linie --> löschen.

Gruß schwatter
Titel: Aw: [Mini-Chart-Card] Schätzeisen bzw. grobe Visualisierung von Daten
Beitrag von: schwatter am 06 Juli 2025, 09:47:40
Morgen,

erstes Post überarbeitet.
- Unter 1.2 Ringbuffer hinzugefügt.
- Dadurch werden die letzten 50 Werte gespeichert. Kommt ein Neuer dazu, fliegt der letzte Alte raus.
- Ein Überlauf wird dadurch verhindert.
- Das at um Mitternacht fällt weg.
- Dadurch besser für Livevalues.

Gruß schwatter