PowerFlow [animiertes SVG, dummy, javascript]

Begonnen von schwatter, 20 Oktober 2024, 21:56:34

Vorheriges Thema - Nächstes Thema

schwatter

Nah jut, dann werd ich das rückbauen  :)

Gruß schwatter

schwatter

#121
Ok,

Update in Post #1. Housering Autarkie entfernt und dafür freies Feld hinzugefügt.

edit:
Ich habe im Post #1 im Bereich notify ein Beispiel dazu gepackt um Autarkie zu berechnen. Oder man nimmt das Reading von SolarForecast.

Gruß schwatter

Virsacer


schwatter

Mahlzeit,

ich habe den Text jetzt im SVG zentral per <style></style> gesetzt. Dadurch gibt es keine Probleme mehr,
wenn sich ein Fhem-SVG-Chart mit im Raum befindet. Für das Update müssen das powergrid.svg sowie das
devStateIcon ersetzt werden. Update im ersten Post.

Gruß schwatter

Virsacer

Ah, sehr schön :)

Nur aktualisiert sich jetzt der Haus-Freitext nicht mehr...

Gruß Virsacer

schwatter

Nabend,

ich habe es wieder zurückgezogen und anstatt den Textstyle zentral zu setzen, wird dieser wieder direkt in jedem
Element einzeln platziert. Aber nun robuster gegenüber einem Fhem-SvgChart.

Zum Test hatte ich auch kurz mit Dark und Brightstyle experimentiert. Hat gut funktioniert,
je nachdem was gesetzt wurde. Aber die Farben der Ringe und Linien sind bei einen Brightstyle zu grell.
Dann hätte ich alles umbauen müssen. Daher erstmal nicht. Update im ersten Post.

Gruß schwatter

Virsacer

Ok, der Haus-Freitext, bleibt aber immernoch stehen wenn das Reading aktualisiert wird.

schwatter

Ok, danke.

Hatte ständig die Webseite aktualisiert, um Änderungen beim Skinning zusehen. Der Perlteil devStateIcon aktualsiert dann
immer genau einmal. Ist für den ersten Aufruf, damit die Werte sofort da sind. Jedenfalls, im SVG fehlte der addInformIdHandler...
Nachgeholt und als Update in Post #1.

Gruß schwatter

carlos

Übrigens:


Invalid SVG
Line 713:37
Unencoded <

und weitere Fehler bei <, <=

Gruß
FHEM svn auf Intel NUC mit proxmox, 3 Raspberry Pi, signalduino, nanoCUL,  toom Baumarkt Funksteckdosen, einige sonoffs, hue, shelly

schwatter

Morgen,

ich habe ein Update im ersten Post#1 angeheftet. Probier das mal. Hast du das SVG durch einen Validator gejagt?

Gruß schwatter

carlos

Nein, einfach mit deinen Link: https://www.svgviewer.dev/ getestet.

Jetzt kommt kein Fehler mehr.

Gruß

Hubert
FHEM svn auf Intel NUC mit proxmox, 3 Raspberry Pi, signalduino, nanoCUL,  toom Baumarkt Funksteckdosen, einige sonoffs, hue, shelly

schwatter

#131
Chrome ist mal wieder eine B****....
Das letzte Update haut die SVG-Skalierung kaputt. Aber nur in Mobile. Desktop ist ok.
Firefox und älter Versionen von Chrome sind noch ok. Ich hatte eben auf die schnelle versucht die Skalierung
im SVG zu setzen, aber da benötige ich etwas Zeit  >:(
Habe erstmal eine ältere Chrome drauf und Autoupdate off im Playstore.

Edit:
Es liegt an "Nested SVG". Mal sehen wie ich es final löse. DataUriSvg funktionieren schon. Die injecte ich direkt.
Fhem SVG sind etwas zickiger.

Gruß schwatter

schwatter

Nabend,

Update im ersten Post.

- die neue Version ist jetzt auch mit Chrome und Co. >= 141 kompatibel.

Bitte SVG und Raw-Definition vom Dummy erneuern.


Gruß schwatter

schwatter

Moin,

Update im ersten Post.

- FhemSvg-einfärben angepasst.

Einige SVG's benötigen mehr Aufmerksamkeit. Bearbeitet habe ich nur powergrid_dummy.txt.


Gruß schwatter

schwatter

Nabend,

ein kleines Update. Da ich an anderer Stelle an einem Kachel-Skin tüddel.
https://forum.fhem.de/index.php?topic=145229.0

  • forceMobile(on/off) hinzugefügt. Dadurch immer klein. Wird nach eine Seitenrefresh aktiv.
  • Circle1 und Circle2 immer sichtbar

Aktualisiert werden müssen devStateIcon + powergrid.svg
{

    use URI::Escape;

    # Lese die Werte aus den Readings und setze Standardwerte
    my %values = map {
        my $default =
            ($_ =~ /Free_s$/) ? '' :
            ($_ =~ /Name_s|Link_s/) ?
                ($_ =~ /Link_s/ ? 'no link' : 'n/a') :
            0;
        $_ => ReadingsVal($name, $_, $default)
    } qw(
        lowcarbon_i lowcarbon_v gridLink_s grid_v grid_in_v grid_out_v
        house_i house_v solar_i solarLink_s solar_v batteryLink_s battery_v
        battery_p batteryState_v cCircle1Icon_i cCircle1Link_s cCircle1Name_s cCircle1Power_v
        cCircle2Icon_i cCircle2Link_s cCircle2Name_s cCircle2Power_v cCircle3Icon_i
        cCircle3Link_s cCircle3Name_s cCircle3Power_v cCircle4Icon_i cCircle4Link_s
        cCircle4Name_s cCircle4Power_v cCircle5Icon_i cCircle5Link_s cCircle5Name_s
        cCircle5Power_v cCircle6Icon_i cCircle6Link_s cCircle6Name_s cCircle6Power_v
        cCircle7Icon_i cCircle7Link_s cCircle7Name_s cCircle7Power_v cCircle8Icon_i
        cCircle8Link_s cCircle8Name_s cCircle8Power_v cCircle9Icon_i cCircle9Link_s
        cCircle9Name_s cCircle9Power_v
        cCircle1Free_s cCircle2Free_s cCircle3Free_s cCircle4Free_s cCircle5Free_s
        cCircle6Free_s cCircle7Free_s cCircle8Free_s cCircle9Free_s
        batteryFree_s houseFree_s solarFree_s forceMobile_s
    );

    # Hole das SVG als Template
    my $svg = FW_makeImage('powergrid');

    # Setze die Werte im SVG
    foreach my $key (keys %values) {
        $svg =~ s/(<tspan class="informId_ringSVG:$key">)(.*?)(<\/tspan>)/$1$values{$key}$3/;
    }

    # Bearbeite die SVG-Icons basierend auf der Art (intern oder extern)
    my @icons = (
        [$values{solar_i},     'solarCircleIcon',       '#FFE74B', 1],
        [$values{lowcarbon_i}, 'fossilfreeCircleIcon',  '#30FF24', 1],
        [$values{house_i},     'houseCircleIcon',       'yellow',  1],
        [$values{cCircle1Icon_i}, 'cCircle1Icon',        '#32AFFF', ($values{cCircle1Name_s} ne 'n/a')],
        [$values{cCircle2Icon_i}, 'cCircle2Icon',        '#32AFFF', ($values{cCircle2Name_s} ne 'n/a')],
        [$values{cCircle3Icon_i}, 'cCircle3Icon',        '#2AB5C7', ($values{cCircle3Name_s} ne 'n/a')],
        [$values{cCircle4Icon_i}, 'cCircle4Icon',        '#2AB5C7', ($values{cCircle4Name_s} ne 'n/a')],
        [$values{cCircle5Icon_i}, 'cCircle5Icon',        '#32AFFF', ($values{cCircle5Name_s} ne 'n/a')],
        [$values{cCircle6Icon_i}, 'cCircle6Icon',        '#32AFFF', ($values{cCircle6Name_s} ne 'n/a')],
        [$values{cCircle7Icon_i}, 'cCircle7Icon',        '#2AB5C7', ($values{cCircle7Name_s} ne 'n/a')],
        [$values{cCircle8Icon_i}, 'cCircle8Icon',        '#32AFFF', ($values{cCircle8Name_s} ne 'n/a')],
        [$values{cCircle9Icon_i}, 'cCircle9Icon',        '#2AB5C7', ($values{cCircle9Name_s} ne 'n/a')]
    );

    foreach my $entry (@icons) {
        my ($icon_raw, $id, $fill, $should_process) = @$entry;
        next unless $should_process && $icon_raw;
        my $raw = $icon_raw;
        my $icon;

        if ($raw =~ s/:fhem$//) {
            $icon = FW_makeImage("$raw\@$fill");
            next unless defined $icon && $icon ne '';
            if ($icon =~ /<svg[^>]*>/) {
                my $svg_tag = $&;
                $svg_tag =~ s/\bwidth\s*=\s*"[^"]*"//i;
                $svg_tag =~ s/\bheight\s*=\s*"[^"]*"//i;
                my ($x,$y,$w,$h) = (0,0,100,100);
                if ($svg_tag =~ /viewBox\s*=\s*"([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)"/i) {
                    ($x,$y,$w,$h) = ($1,$2,$3,$4);
                } else {
                    $svg_tag =~ s/<svg\b/<svg viewBox="0 0 100 100"/i;
                }
                my $scale = 20 / ($w > $h ? $w : $h);
                my $offset_x = (20 - $w * $scale) / 2 - $x * $scale + 2;
                my $offset_y = (20 - $h * $scale) / 2 - $y * $scale + 2;
                $svg_tag =~ s/<svg\b/<svg class="icon"/ unless $svg_tag =~ /class=/;
                $svg_tag =~ s/<svg\b/<svg width="20" height="20"/i;
                $icon =~ s{<svg[^>]*>}{$svg_tag};
                $icon =~ s{(<svg[^>]*>)}{$1<g transform="translate($offset_x,$offset_y) scale($scale)">}i;
                $icon =~ s{</svg>}{</g></svg>}i;

                # --- alle <path> einfärben ---
                #$icon =~ s/<path(?![^>]*fill)/<path fill="$fill"/g;
                $icon =~ s/\bfill="[^"]*"/fill="$fill"/gi;
                for my $tag (qw(path rect circle ellipse polygon polyline line)) {
                    $icon =~ s{<$tag(?![^>]*\bfill=)}{<$tag fill="$fill"}gi;
                }
            }
        } else {
            $icon = uri_unescape($raw);
            $icon =~ s/fill="[^"]*"/fill="$fill"/g;
            $icon =~ s/<path(?![^>]*fill)/<path fill="$fill"/g;
            next unless defined $icon;
        }

        my $inner = "";
        if ($icon =~ m{<svg[^>]*>(.*)</svg>}s) {
            $inner = $1;
        } else {
            $inner = $icon;
        }

        $svg =~ s{<g id="$id"([^>]*)>}{<g id="informId_ringSVG:$id"$1>$inner};
    }

    # Weblink Links
    my @links = (
        [ "do_weblink", "/fhem?detail=powergrid", 55, 30, "Energyflow", "Click here for DeviceOverview" ],
        [ "gridLink", $values{gridLink_s}, 100, 250, "Grid", $values{gridLink_s} ],
        [ "solarLink", $values{solarLink_s}, 250, 100, "Solar", $values{solarLink_s} ],
        [ "batteryLink", $values{batteryLink_s}, 250, 400, "Battery", $values{batteryLink_s} ],
        [ "cCircle1Link", $values{cCircle1Link_s}, 400, 100, "Circle1", $values{cCircle1Link_s} ],
        [ "cCircle2Link", $values{cCircle2Link_s}, 400, 400, "Circle2", $values{cCircle2Link_s} ],
        [ "cCircle3Link", $values{cCircle3Link_s}, 550, 100, "Circle3", $values{cCircle3Link_s} ],
        [ "cCircle4Link", $values{cCircle4Link_s}, 550, 400, "Circle4", $values{cCircle4Link_s} ],
        [ "cCircle5Link", $values{cCircle5Link_s}, 700, 100, "Circle5", $values{cCircle5Link_s} ],
        [ "cCircle6Link", $values{cCircle6Link_s}, 700, 400, "Circle6", $values{cCircle6Link_s} ],
        [ "cCircle7Link", $values{cCircle7Link_s}, 850, 100, "Circle7", $values{cCircle7Link_s} ],
        [ "cCircle8Link", $values{cCircle8Link_s}, 850, 250, "Circle8", $values{cCircle8Link_s} ],
        [ "cCircle9Link", $values{cCircle9Link_s}, 850, 400, "Circle9", $values{cCircle9Link_s} ]
    );

    foreach my $link (@links) {
        my ($id, $href, $cx, $cy, $title, $tooltip) = @$link;

        my $weblink;
        if ($id eq 'do_weblink') {
            $weblink = qq(<a xlink:href="$href" target="_blank"><text class="do_weblink" x="$cx" y="$cy" style="font-size:24px; fill:white; font-family:Arial; font-weight:normal; cursor:pointer;">$title<title>$tooltip</title></text></a>);
        } else {
            $weblink = qq(<a xlink:href="$href" target="_blank"><circle cx="$cx" cy="$cy" r="45" style="fill:transparent;stroke:none;"/><title>$tooltip</title></a>);
        }

        $svg =~ s{<g id="$id"([^>]*)>}{<g id="$id"$1>$weblink};
    }

    # CSS hinzufügen
    #my $extras = 'style="width: 90vw !important;height: auto !important;max-height: 600px;background-color: #1C1C1C !important;"';
    #$svg =~ s/<svg([^>]*)\s*(style="[^"]*")?/<svg$1$extras/;

    #my $extrasMobile = 'style="width: 90vw !important; height: auto !important; max-height: 600px; background-color: #1C1C1C !important;"';
    #my $extrasNormal = 'style="width: 40vw !important; height: auto !important; max-height: 600px; background-color: #1C1C1C !important;"';

    my $mobileViewBox = '0 0 450 480';

    my $extras;

    if ($values{forceMobile_s} eq 'on') {
        $extras = 'style="width: 40vw !important; height: auto !important; min-width: 350px !important; max-height: 600px; background-color: #1C1C1C !important;"';

        # Klasse force-mobile hinzufügen / anhängen
        if ($svg =~ /class="([^"]*)"/) {
            $svg =~ s/class="([^"]*)"/class="$1 force-mobile"/;
        } else {
            $svg =~ s/<svg\b/<svg class="force-mobile"/;
        }

        # viewBox ersetzen oder neu einfügen
        if ($svg =~ /viewBox="[^"]*"/) {
            $svg =~ s/viewBox="[^"]*"/viewBox="$mobileViewBox"/;
        } else {
            $svg =~ s/<svg\b/<svg viewBox="$mobileViewBox"/;
        }
    } else {
        $extras = 'style="width: 90vw !important; height: auto !important; max-height: 600px; background-color: #1C1C1C !important;"';
    }

    $svg =~ s/<svg([^>]*)\s*(style="[^"]*")?/<svg$1 $extras/;

    return $svg;
}

Gruß schwatter