FHEM Forum

FHEM - Energiemanagement und Energieerzeugung => Solaranlagen => Thema gestartet von: schwatter am 20 Oktober 2024, 21:56:34

Titel: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 20 Oktober 2024, 21:56:34
Klick Mich. Vorschauanimation! (https://raw.githubusercontent.com/schwatter/PowerFlow/refs/heads/main/images/animation.gif) <-veraltet

Update:
04.05.25 - Beispiel mit notify hinzugefügt

Hallo zusammen,

ich habe die Tage an einem animierten PowerFlow gebastelt. Optisch liebäugelt er mit der Powerflow Card Plus von HA.
Zusammengesetzt ist er aus einem dummy-Device, welches die Werte beherbergt und das SVG lädt sowie füttert.

Danke an @Torxgewinde, welcher mir den Weg per setValue(d) sehr gut erläutert hat.

Mit dem Baukasten können noch nicht alle, aber doch schon viele Situationen abgebildet
werden. Bzw. bis jetzt ist es mehr auf meine Bedürfnisse angepasst.

Anwendung
- Echte und fiktive Werte werden im powergrid dummy gesetzt.
- Die animierten Linien folgen der Regel größer oder kleiner als 0.
- Der Batteriering ist die Ausnahme mit stop,gridLoad,gridUnload,solarLoad und houseUnload.
- Der Hausring zeigt prozentual die Leistung von Battery,Grid und Solar an.
- Zum setzen eines Wertes in dem jeweiligen Ring, muss eine Zahl angegeben werden. Zum Beispiel "300". Das Script ergänzt das "W".
- Um einen von den Customringen auszublenden, einfach den ReadingNamen auf n/a setzen.
- Von außen könnt ihr mit einem notify, DOIF oder dem Mittel eurer Wahl die Werte setzen.
- Um Low-Carbon, bzw jetzt FossilFree zu nutzen, bietet sich https://electricitymaps.com/ an. Siehe Punkt 4.
- Um zum DeviceOverview zu kommen, versteckt sich hinter dem Logo "Powerflow" ein Link.
- Icons von fhem müssen so gesetzt werden: aurora:fhem
- Externe SVG als Data-URL von hier: https://pictogrammers.com/libraries/ . Nicht downloaden! Rechte Maustaste, Url kopieren + einfügen.

Um das SVG an euren Geschmack anzupassen, empfehle ich diese SVG-Editors:
- https://www.svgviewer.dev/
- https://boxy-svg.com/app

1. powergrid.svg

- Das Svg aus dem Anhang nach /opt/fhem/www/images/fhemSVG kopieren.
- Rechte: Eigentümer fhem / Gruppe dialout
set WEB rereadicons
set WEBphone rereadicons
set WEBtablet rereadicons


2. dummy

Das dummy-Device ist in der Raw im Anhang. Anlegen oben links mit dem Pluszeichen.

3. Werte setzen mit notify oder DOIF
3.1 notify

defmod notify_Powergrid notify (Smartmeter_2E1F50:APOX_Power:.*|Smartmeter_2E1F50:statAPOX_E_inDay:.*|Smartmeter_2E1F50:statAPOX_E_outDay:.*|OpenDTU:total.Power.v:.*|electricitymap:fossilFreePercentage:.*|Luftentfeuchter:ENERGY_Power:.*|MQTT2_zigbee_Waschmaschine:power:.*|MQTT2_zigbee_Trockner:power:.*|MQTT2_zigbee_Geschirrspueler:power:.*|MQTT2_zigbee_Kuehlschrank:power:.*|Heizstab_BW_Pwr:power:.*|Server:ENERGY_Power:.*) \
{\
\
  # Smartmeter\
  if ($NAME eq "Smartmeter_2E1F50") {\
    fhem("set powergrid grid_v [Smartmeter_2E1F50:APOX_Power:d]" );;\
    fhem("set powergrid grid_in_v  →[Smartmeter_2E1F50:statAPOX_E_inDay:d]" );;\
    fhem("set powergrid grid_out_v ←[Smartmeter_2E1F50:statAPOX_E_outDay:d]" );;\
    fhem("set powergrid house_v " . (ReadingsNum("Smartmeter_2E1F50","APOX_Power", 0) + ReadingsNum("OpenDTU","total.Power.v", 0)));;\
    fhem("set powergrid lowcarbon_v  [electricitymap:fossilFreePercentage:d]" );;\
\
  # Solarinverter\
  } elsif ($NAME eq "OpenDTU") {\
    fhem("set powergrid solar_v [OpenDTU:total.Power.v:d]" );;\
\
  # Airdryer\
  } elsif ($NAME eq "Luftentfeuchter") {\
    fhem("set powergrid cCircle1Power_v [Luftentfeuchter:ENERGY_Power:d]" );;\
\
  # Washer\
  } elsif ($NAME eq "MQTT2_zigbee_Waschmaschine") {\
    fhem("set powergrid cCircle2Power_v [MQTT2_zigbee_Waschmaschine:power:d]" );;\
\
  # Dryer\
  } elsif ($NAME eq "MQTT2_zigbee_Trockner") {\
    fhem("set powergrid cCircle3Power_v [MQTT2_zigbee_Trockner:power:d]" );;\
\
  # Dishwasher\
  } elsif ($NAME eq "MQTT2_zigbee_Geschirrspueler") {\
    fhem("set powergrid cCircle4Power_v [MQTT2_zigbee_Geschirrspueler:power:d]" );;\
\
  # Fridge\
  } elsif ($NAME eq "MQTT2_zigbee_Kuehlschrank") {\
    fhem("set powergrid cCircle5Power_v [MQTT2_zigbee_Kuehlschrank:power:d]" );;\
\
  # Boiler\
  } elsif ($NAME eq "Heizstab_BW_Pwr") {\
    fhem("set powergrid cCircle6Power_v [Heizstab_BW_Pwr:power:d]" );;\
\
  # Server\
  } elsif ($NAME eq "Server") {\
    fhem("set powergrid cCircle7Power_v [Server:ENERGY_Power:d]" );;\
\
  }\
\
}



3.2 DOIF

defmod Powergrid_DOIF DOIF ## Grid + House\
([Smartmeter_2E1F50:"APOX_Power"])\
        ( set powergrid grid_v {(ReadingsNum("Smartmeter_2E1F50","APOX_Power", 0))} )\
        ( set powergrid grid_in_v {(sprintf("→ %.1f", ReadingsNum("Smartmeter_2E1F50","statAPOX_E_inDay",0)))})\
        ( set powergrid grid_out_v {(sprintf("←  %.1f",ReadingsNum("Smartmeter_2E1F50","statAPOX_E_outDay",0)))})\
        ( set powergrid house_v {(ReadingsNum("Smartmeter_2E1F50","APOX_Power", 0, 1) + ReadingsNum("OpenDTU","total.Power.v", 0, 1))} )\
        ( set powergrid lowcarbon_v {(ReadingsNum("electricitymap","fossilFreePercentage", 0))} )\
\
## Solar\
DOELSEIF  ([OpenDTU:"total.Power.v"] )\
        ( set powergrid solar_v {(ReadingsNum("OpenDTU","total.Power.v", 0, 1))} )\
\
## Airdryer\
DOELSEIF  ([Luftentfeuchter:"ENERGY_Power"])\
        ( set powergrid cCircle1Power_v {(ReadingsNum("Luftentfeuchter","ENERGY_Power",0))} )\
\
## Washer\
DOELSEIF  ([MQTT2_zigbee_Waschmaschine:"power"])\
        ( set powergrid cCircle2Power_v {(ReadingsNum("MQTT2_zigbee_Waschmaschine","power",0))} )\
\
## Dryer\
DOELSEIF  ([MQTT2_zigbee_Trockner:"power"])\
        ( set powergrid cCircle3Power_v {(ReadingsNum("MQTT2_zigbee_Trockner","power",0))} )\
\
## Dishwasher\
DOELSEIF  ([MQTT2_zigbee_Geschirrspueler:"power"])\
        ( set powergrid cCircle4Power_v {(ReadingsNum("MQTT2_zigbee_Geschirrspueler","power",0))} )\
\
## Fridge\
DOELSEIF  ([MQTT2_zigbee_Kuehlschrank:"^power:.*$"])\
        ( set powergrid cCircle5Power_v {(ReadingsNum("MQTT2_zigbee_Kuehlschrank","power",0))} )\
\
## Boiler\
DOELSEIF  ([Heizstab_BW_Pwr:"^power:.*$"])\
        ( set powergrid cCircle6Power_v {(ReadingsNum("Heizstab_BW_Pwr","power",0))} )\
\
\
\
\

4. Electricmap - Erzeugt das Reading für FossilFree

Laut Webseite wird ein Apikey benötigt. Es funktioniert aber auch ohne.
Update:
API-Key kann jetzt im HTTPMOD eingefügt werden. Die erforderlichen Header habe ich unten eingefügt.
Nach dem registrieren findet ihr euren API-Key unter https://portal.electricitymaps.com/dashboard.
defmod electricitymap HTTPMOD none 60
attr electricitymap event-on-change-reading .*
attr electricitymap extractAllJSON 1
attr electricitymap get1Header1 accept: */*
attr electricitymap get1Header2 auth-token: XpiDeinGeheimerTokenAut
attr electricitymap get1Name carbon-intensity
attr electricitymap get1Poll 1
attr electricitymap get1URL https://api.electricitymap.org/v3/carbon-intensity/latest?zone=DE
attr electricitymap get2Header1 accept: */*
attr electricitymap get2Header2 auth-token: XpiDeinGeheimerTokenAut
attr electricitymap get2Name power-breakdown
attr electricitymap get2Poll 1
attr electricitymap get2URL https://api.electricitymap.org/v3/power-breakdown/latest?zone=DE


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Gisbert am 20 Oktober 2024, 22:30:21
Hallo schwatter,

das sieht sehr interessant aus. Ich versuche es bei mir zum Laufen zu bringen. Ich benötige aber nur Grid, Solar, House und Battery - kann ich alles aus der readingsList weglassen, was ich nicht benötige?
Wie bringe ich meine Readings für Grid, Solar, House und Battery in deine Definition am geschicktesten hinein?

Viele Grüße Gisbert
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 20 Oktober 2024, 22:50:16
Um zum Beispiel einen Wert mit einem notify im myDummy1 zu setzen

defmod MQTT2_Smartmeter_2E1F50_notify_4 notify MQTT2_Smartmeter_2E1F50:StatusSNS_APOX_Power:.* {fhem"setreading myDummy1 grid $EVTPART1"}

setstate MQTT2_Smartmeter_2E1F50_notify_4 2024-10-20 22:38:34
setstate MQTT2_Smartmeter_2E1F50_notify_4 2024-10-20 11:04:22 state active
setstate MQTT2_Smartmeter_2E1F50_notify_4 2024-10-20 22:38:34 triggeredByDev MQTT2_Smartmeter_2E1F50
setstate MQTT2_Smartmeter_2E1F50_notify_4 2024-10-20 22:38:34 triggeredByEvent StatusSNS_APOX_Power: 229

Für die Linien muss dann ein kleiner (<) oder größer (>) als Vergleich gemacht werden. Als Beispiel hier ein Auszug aus meinem anderen DOIF. Bis jetzt habe ich den dummy hier selber noch nicht in Betrieb. Nur fiktive Werte. Werde die Tage umstellen.
Die Werte hier aus dem DOIF nicht übernehmen. Da ja nur 0 und 1 gesetzt werden muss.

## Animierter Punkt von Haus zu Kühlschrank (an|aus)
   (IF ([MQTT2_zigbee_Kuehlschrank:power] > 0)
({CommandSetReading(undef,'svgDOIF style_fridge ')}  ) )
   (IF ([MQTT2_zigbee_Kuehlschrank:power] == 0)
(setreading svgDOIF style_fridge style="display: none;;") )

## Animierter Punkt von Haus zu Trockner (an|aus)
   (IF ([MQTT2_zigbee_Trockner:power] > 0)
({CommandSetReading(undef,'svgDOIF style_dryer ')}) )
   (IF ([MQTT2_zigbee_Trockner:power] == 0)
(setreading svgDOIF style_dryer style="display: none;;") )

## Animierter Punkt von Haus zu Luftentfeuchter (an|aus)
   (IF ([Luftentfeuchter:ENERGY_Power] > 0)
({CommandSetReading(undef,'svgDOIF style_airdryer ')}))
   (IF ([Luftentfeuchter:ENERGY_Power] == 0)
(setreading svgDOIF style_airdryer style="display: none;;") )

## Animierter Punkt von Haus zu Geschürrspüler (an|aus)
   (IF ([MQTT2_zigbee_Geschirrspueler:power] > 0)
({CommandSetReading(undef,'svgDOIF style_dishwascher ')})  )
   (IF ([MQTT2_zigbee_Geschirrspueler:power] == 0)
(setreading svgDOIF style_dishwasher style="display: none;;") )

## Animierter Punkt von Haus zu Waschmaschine (an|aus)
   (IF ([MQTT2_zigbee_Waschmaschine:power] > 0)
(setreading svgDOIF style_washer '') )
   (IF ([MQTT2_zigbee_Waschmaschine:power] == 0)
(setreading svgDOIF style_washer style="display: none;;") )

## Animierter Punkt von Solar zu Haus (an|aus)
   (IF ([MQTT2_OpenDTU_585584:power] > 0)
({CommandSetReading(undef,'svgDOIF style_solarToHouse ')}) )
   (IF ([MQTT2_OpenDTU_585584:power] == 0)
(setreading svgDOIF style_solarToHouse style="display: none;;") )

## Animierter Punkt von  Netz zu Haus (an|aus)
   (IF ([MQTT2_Smartmeter_2E1F50:APOX_Power] > 0 )
({CommandSetReading(undef,'svgDOIF style_gridToHouse ')}))
   (IF  ([MQTT2_Smartmeter_2E1F50:APOX_Power] <= 0 )
(setreading svgDOIF style_gridToHouse style="display: none;;") )

## Animierter Punkt von Solar zu Netz (an|aus)
   (IF ([MQTT2_Smartmeter_2E1F50:APOX_Power] < 0)
({CommandSetReading(undef,'svgDOIF style_solarToGrid ')}) )
   (IF ([MQTT2_Smartmeter_2E1F50:APOX_Power] > 0)
(setreading svgDOIF style_solarToGrid style="display: none;;") )

Und wegen dem anpassen, bzw verkleinern auf 4 Ringe. Einfach alles aus dem SVG und dem Javascript schmeißen,
was du nicht benötigst. Wenn du etwas gelöscht hast, was falsch war, dann siehst du es schon. Dann kommen keine Werte.

Gruß schwatter

Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 21 Oktober 2024, 09:44:42
Bei 1.myDummy habe ich nochmal Einrückung und Groß/Kleinschreibung angepasst.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 22 Oktober 2024, 00:02:26
Update im ersten Post.

- der Ring vom Haus wird aus 3 Farben zusammengesetzt. Die verantwortlichen Readings sind Grid, Solar und Battery.
- Battery hat jetzt erstmal die Angabe Watt. Diese muss ich noch um eine 2te Wattangabe ergänzen.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 23 Oktober 2024, 18:28:00
Update im ersten Post

Alle 3 Dateien müssen ersetzt werden.

- Diverse Linien überarbeitet
- Animierten Batteriering eingefügt (batteryState). Dieser dreht vorwärts, rückwärts + stop. Idee, vorwärts laden und rückwärts entladen. Farben alle türkis. Könnt ihr euch selber einfärben im SVG. (laden grün, entladen rot?)
- Dadurch kann die Linie gridToBattery jetzt vorwärts, rückwärts + stop. Habe ich aber nicht gekoppelt. Sollte beim ansteuern beachtet werden.
- Hat der "batteryState" den Status "backward" und "stop" wird "battery" automatisch vom Housering abgezogen.
- Fix beim Housering. Vorher waren negative Zahlen nicht abgefangen. Das hat die prozentuale Aufteilung durcheinander gewürfelt.
- Setup in myDummy1 der Widgets geändert. Viel select für Linien mit on|off, ..., ... .


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 23 Oktober 2024, 20:26:52
Oh, das Wichtigste vergessen.
Damit überhaupt etwas funktioniert, muss im jeweiligen FHEMWEB Device noch der Javascriptpfad angegeben werden.

attr WEB JavaScripts pgm2/svg_update.js
Ich füge das oben unter Punkt 4 ein.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 24 Oktober 2024, 12:13:47
Sieht gut aus, so etwas wollte ich schon lange.
Fragen:
1. Bei der Batterie würde ich gerne 2 Werte sehen: Füllstand in % und Ladung/Entladung.
2. Bei Grid evtl gleich 3 Werte:
   Momentaner Grid Export/import mit + oder -
   Heutiger Export
   Heutiger Import
3. Die Punkt Animation muss ich die von Hand setzen?
   Könnte man die auf Grund der Werte nicht berechnen?
4. Die Devices myDummy und myDummy1 könnte man doch auch zusammenfassen oder geht das nicht wegen dem .js?

Alles keine Kritik, nur Anregung zum weiteren optimieren.
Wie gesagt, ansonsten gefällt mir das sehr gut.

Gruß

Hubert
 
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 24 Oktober 2024, 19:19:26
Nabend,
das freut mich.

Zu 1. Füge ich hinzu.

Zu.2 Muss ich mal schauen wie ich das einfüge. Der Platz ist etwas begrenzt. Die Ringgröße hätte ich gerne beibehalten. Vielleicht die Namen wie bei HA außerhalb vom Kreis.

Zu 3. Momentan ja. Mal sehen ob ich das noch ändere bzw. ich bin kein Dev. Ich lese sehr viel :) Daher kann es klappen oder auch nicht.

Zu 4. Jein. Das Problem ist, das ich verhindern muss, das irgendetwas dazu führt, das das Device refreshed wird.
Du kannst einfach das SVG in den myDummy1 in das stateFormat kopieren. Sobald in myDummy1 ein Reading aktualisiert wird,
wird das SVG kurz unterbrochen.

Nimmt man z.B setreading dann passiert es auch:
Der Befehl setzt das Reading <reading> auf den Wert <value> ohne Signale an das betroffene Gerät zu senden, generiert aber Ereignisse und die übliche eventMap und stateFormat Umwandlung wird auch durchgeführt.

Vielleicht hast du eine simple Lösung, die mir gerade nicht einfällt. An Fhem mach ich nur noch etwas, wenn ich was neues brauche. Das kommt selten vor, daher vergesse ich auch vieles wieder mit der Zeit.

Ich habe auch schon an ein Modul gedacht. War da auch schon am Gange. Aber mir fehlt als Laie noch die Idee, wie ich das
ohne trigger am Besten umsetzen kann.
Und ein Modul ist gut und schön, würde im Moment aber auch meinen Rahmen sprengen. Aber ganz weg ist der Gedanke noch nicht.
Ich hatte zum Beispiel schon ein Modul etwas zusammengeschustert. Das hat mir aus den einzelnen Ringen die per attr gesetzt waren, das fertige SVG gebaut.
So könnten Ringe dynamisch hinzugefügt oder deaktiviert werden.
Die internen Funktionen von Fhem gucke ich mir jetzt auch nach und nach an. Um zum Beispiel mal im Modul das Device anzugeben
und auf das das Reading triggert.

Aber die wichtigste Frage an dich oder jemand anderen. Funktioniert der Kram überhaupt so, wie ich ihn oben hochgeladen und
dokumentiert habe?


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 25 Oktober 2024, 09:49:09
Hallo Schwatter,
Danke für die Erläuterungen.
Meine Idee wäre das alles in ein doif (mit den entsprechenden DI Readings) zu packen z.b. so:
defmod myDummy1 DOIF ([myFronius:"^power:.*$"])\
    ( setreading $SELF solar {(ReadingsNum("myFronius","power",0))} )\
    ( setreading $SELF Zyklus solar  ) \
DOELSEIF  ( [mySenec:"^speicherleistung:.*$"] or [mySenec:"^netzleistung:.*$"] or [mySenec:"^stromverbrauch:.*$"] ) \
    ( setreading $SELF battery {(ReadingsNum("mySenec","speicherleistung",0))} ) \
    ( setreading $SELF grid {(ReadingsNum("mySenec","netzleistung",0))} ) \
    ( setreading $SELF house {(ReadingsNum("mySenec","stromverbrauch",0))} )\
( setreading $SELF Zyklus battery/grid/house )\
DOELSEIF  ( [Waschmaschine:"^ENERGY_Power:.*$"] or [Trockner:"^ENERGY_Power:.*$"] or [Spuelmaschine:"^ENERGY_Power:.*$"] ) \
    ( setreading $SELF washer {(ReadingsNum("Waschmaschine","ENERGY_Power",0))} ) \
    ( setreading $SELF dryer {(ReadingsNum("Trockner","ENERGY_Power",0))} ) \
    ( setreading $SELF dishwasher {(ReadingsNum("Spuelmaschine","ENERGY_Power",0))} )\
( setreading $SELF fridge {(fridge("Spuelmaschine","ENERGY_Power","N/A"))} )\
    ( setreading $SELF airdryer {(ReadingsNum("airdryer","ENERGY_Power","N/A"))} )\
( setreading $SELF Zyklus washer/dryer/dishwasher/fridge/airdryer )\
DOELSE\
( setreading $SELF Zyklus nothing  )
attr myDummy1 DOIF_Readings current_total:[myTibber:current_total],\
current_level:[myTibber:current_level],\
speicherfuellstand:[mySenec:speicherfuellstand],\
grid:[mySenec:netzleistung],\
solar:[mySenec:stromerzeugung_total],\
battery:[mySenec:speicherleistung],\
house:[mySenec:stromverbrauch],\
\
dishwasher:[Spuelmaschine:ENERGY_Power],\
washer:[Waschmaschine:ENERGY_Power],\
dryer:[Trockner:ENERGY_Power]\
\

attr myDummy1 room Energy
attr myDummy1 stateFormat <svg width='650' height='500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: auto;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\


setstate myDummy1 <svg width='650' height='500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: auto;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\

setstate myDummy1 2024-10-25 09:45:37 Device mySenec
setstate myDummy1 2024-10-25 09:45:37 Zyklus nothing
setstate myDummy1 2024-10-25 09:44:50 airdryer N/A
setstate myDummy1 2024-10-25 09:45:37 battery 91.76
setstate myDummy1 2024-10-25 09:45:37 cmd 4
setstate myDummy1 2024-10-25 09:45:37 cmd_event mySenec
setstate myDummy1 2024-10-25 09:45:37 cmd_nr 4
setstate myDummy1 2024-10-25 09:39:26 current_level NORMAL
setstate myDummy1 2024-10-25 09:39:26 current_total 0.3388
setstate myDummy1 2024-10-25 09:44:50 dishwasher 0
setstate myDummy1 2024-10-25 09:44:50 dryer 0
setstate myDummy1 2024-10-25 09:45:01 e_Trockner_events ENERGY_Current: 0.026,ENERGY_ReactivePower: 6,ENERGY_Factor: 0.02,ENERGY_Voltage: 235,ENERGY_ApparentPower: 6
setstate myDummy1 2024-10-25 09:45:26 e_myFronius_events Inverter_System_YEAR_ENERGY_Values_1: 8129062,Inverter_System_YEAR_ENERGY_Unit: Wh,Inverter_System_DAY_ENERGY_Values_1: 580,Inverter_System_DAY_ENERGY_Unit: Wh,Inverter_System_TOTAL_ENERGY_Unit: Wh,Inverter_System_TOTAL_ENERGY_Values_1: 33899300,Inverter_System_PAC_Values_1: 771,Inverter_System_PAC_Unit: W,Einspeisung: 43.07,Bezug: 0,Einspeisung_curr: 0,power: 0.771
setstate myDummy1 2024-10-25 09:45:37 e_mySenec_events ERROR: none,lastUpdate: 2024-10-25 09:45:37,connected
setstate myDummy1 2024-10-25 09:45:37 grid -32.78
setstate myDummy1 2024-10-25 09:45:37 house 650.46
setstate myDummy1 2024-10-25 09:44:52 mode enabled
setstate myDummy1 2024-10-25 09:45:36 solar 8128.13
setstate myDummy1 2024-10-25 09:38:37 speicherfuellstand 0.00
setstate myDummy1 2024-10-25 09:45:37 state cmd_4
setstate myDummy1 2024-10-25 09:44:50 washer 0

Über das javascript attribut in WEB könnte man dann parameter übergeben für die Animation.
JavaScripts
Leerzeichen getrennte Liste von JavaScript Dateien, die geladen werden. Die Dateinamen sind relativ zum www Verzeichnis anzugeben. Für jede Datei wird ein zusätzliches Attribut angelegt, damit der Benutzer dem Skript Parameter weiterreichen kann. Bei diesem Attributnamen werden Verzeichnisname und fhem_ Präfix entfernt und Param als Suffix hinzugefügt. Beispiel:
attr WEB JavaScripts codemirror/fhem_codemirror.js
attr WEB codemirrorParam { "theme":"blackboard", "lineNumbers":true }

Aber da kenne ich mich zuwenig mit JS FHEM aus.

Ich habe das jetzt mal ausprobiert, habe aber wie bei deiner jetzigen Lösung das gleiche Problem, da nach einiger Zeit keine Werte mehr angezeigt werden.
Keina Ahnung an was das liegt, die Werte sind alle durch das di gesetzt.

Gruß

Hubert
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 25 Oktober 2024, 14:04:13
Dein Ansatz mit DOIF hatte ich ja mehr oder weniger schon versucht, siehe DOIF- Bereich. Problem ist immer, der Refresh vom STATE.
Das mit dem JavaCode übergeben im WEB Device, mal sehen ob das uns weiter bringt.

Das die Werte mit der Zeit ausbleiben, hatte ich bis jetzt noch nie. Entweder sie sind da, dann findet das Javascript
alle Readings. Fehlt eins, kommt kommentarlos einfach nichts. Da im Javascript bis jetzt keine Prüfung drinne ist.
Muss ich ergenzen.

Also nochmal ganz dumm gefragt, wenn du es alles so wie im ersten Post anlegst, dann bleiben auch dann irgendwann die Werte aus?
Wie schaut es bei deinem WEB-Device aus. Da habe ich, aber unbewusst von anderen Sachen, z.B das gesetzt:

attr WEB longpoll 1
attr WEB longpollSVG 1
attr WEB plotEmbed 2
attr WEB plotfork 1

Vielleicht liegt es an longpollSVG?

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 25 Oktober 2024, 14:34:04
Ja, die Werte waren gestern da und heute bleiben sie aus.
Ich kann einstellen was ich will.
Im DI myDummy1 sind die Werte da und werden aktualisiert.

Ich hatte bei longpoll auf websocket gestellt.
Ich denke aber, dass es eher am csrfToken attribute liegt.
Habe ich aber auch auch schon none, random ausprobiert.

Gruß

Hubert
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 25 Oktober 2024, 15:09:35
Ok, hast du beide bzw alle Devices in einem Raum?
Dann wird das SVG nur bei dem ersten oberen Device aktualisiert.
Das 2te darunter bekommt dann keine Werte. Da die Readings die gleichen sind.

edit:
bzw ich meine gleiche ID's im SVG. Zum Beispiel  id='solarPower'.
Dann verschluckt sich das. Da müsste bei mehreren SVG eine eindeutige Zuordung pro SVG stattfinden.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 27 Oktober 2024, 12:45:07
Mahlzeit,


ich habe jetzt erst bemerkt, das ich nicht auf eindeutige, bzw abweichende Readings geachtet habe.
Das fiel mir jetzt bei der Suche, 98_dummy.pm so zu modifizieren, das er STATE nicht updatet, auf die Füße.

Bedeutet, der dummy darf kein Reading haben, welches als gridToHouse benannt ist, da das SVG <animateMotion id='gridToHouse'
auch verwendet. Das führt zwangsläufig zu Konflikten, da Fhem sich das Reading automatisch mit in den STATE zieht.
Bei den 2 dummys hat das irgendwie funktioniert. Das werde ich im .ersten Post nochmal umstellen.

Jetzt habe ich mir zum testen von 98_dummy.pm den Code in 98_dummyNew.pm gepackt. Dann alles im dummy auf dummyNew geändert.
Und diesen Teil:

  my @rl = split(" ", AttrVal($name, "readingList", ""));
  my $doRet;
  eval {
    if(@rl && grep /^$a[0]$/, @rl) {
      my $v = shift @a;
      readingsSingleUpdate($hash, $v, join(" ",@a), 1);
      $doRet = 1;
    }
  };
  return if($doRet);


zu diesen geändert:

  my @rl = split(" ", AttrVal($name, "readingList", ""));
  my $doRet;
  eval {
    if(@rl && grep /^$a[0]$/, @rl) {
      my $v = shift @a;
      readingsBeginUpdate($hash);
      readingsBulkUpdate($hash, $v, join(" ",@a), 1);
      readingsEndUpdate($hash, 0);  # Verhindert das Aktualisieren des STATE
      $doRet = 1;
    }
  };
  return if($doRet);


Dadurch kann ich jetzt das aktualisieren des STATE unterdrücken.
Bedeutet, damit ist alles in einem dummy.

98_dummyNew.pm hänge ich nicht an. Wenn würde ich rudolfkoenig fragen, ob er gewillt wäre, das in 98_dummy.pm so ähnlich einzubauen.

Hier meine Raw von meinem dummyNew und die passende svg_update.js

defmod powerGrid dummyNew
attr powerGrid readingList airdryer_v battery_v batteryState_v batteryToHouse_v dishwasher_v dryer_v fridge_v grid_v gridToBattery_v gridToBatteryState_v gridToLowCarbon_v gridToHouse_v house_v houseToAirdryer_v houseToDishwasher_v houseToDryer_v houseToFridge_v houseToWasher_v solar_v solarToBattery_v solarToGrid_v solarToHouse_v washer_v
attr powerGrid room Energy1
attr powerGrid setList airdryer_v:textField battery_v:textField batteryState_v:select,backward,stop,forward batteryToHouse_v:select,on,off dishwasher_v:textField dryer_v:textField fridge_v:textField grid_v:textField gridToBattery_v:select,backward,stop,forward gridToLowCarbon_v:select,on,off gridToHouse_v:select,on,off house_v:textField houseToAirdryer_v:select,on,off houseToDishwasher_v:select,on,off houseToDryer_v:select,on,off houseToFridge_v:select,on,off houseToWasher_v:select,on,off solar_v:textField solarToBattery_v:select,on,off solarToGrid_v:select,on,off solarToHouse_v:select,on,off washer_v:textField
attr powerGrid stateFormat <svg width='650' height='500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: auto;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\


setstate powerGrid <svg width='650' height='500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: auto;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\

setstate powerGrid 2024-10-27 12:18:18 airdryer_v 799
setstate powerGrid 2024-10-27 12:17:49 batteryState_v backward
setstate powerGrid 2024-10-27 12:09:51 batteryToHouse_v off
setstate powerGrid 2024-10-27 12:09:55 battery_v 50
setstate powerGrid 2024-10-27 12:10:01 dishwasher_v 50
setstate powerGrid 2024-10-27 12:10:05 dryer_v 50
setstate powerGrid 2024-10-27 12:10:08 fridge_v 50
setstate powerGrid 2024-10-27 12:18:38 gridToBattery_v forward
setstate powerGrid 2024-10-27 12:10:28 gridToHouse_v off
setstate powerGrid 2024-10-27 12:17:28 gridToLowCarbon_v off
setstate powerGrid 2024-10-27 12:10:42 grid_v 50
setstate powerGrid 2024-10-27 12:10:44 houseToAirdryer_v off
setstate powerGrid 2024-10-27 12:10:47 houseToDishwasher_v off
setstate powerGrid 2024-10-27 12:10:50 houseToDryer_v off
setstate powerGrid 2024-10-27 12:10:53 houseToFridge_v off
setstate powerGrid 2024-10-27 12:10:55 houseToWasher_v off
setstate powerGrid 2024-10-27 12:10:58 house_v 50
setstate powerGrid 2024-10-27 12:11:01 solarToBattery_v off
setstate powerGrid 2024-10-27 12:11:03 solarToGrid_v off
setstate powerGrid 2024-10-27 12:33:53 solarToHouse_v on
setstate powerGrid 2024-10-27 12:11:09 solar_v 50
setstate powerGrid 2024-10-27 12:12:04 state gridToLowCarbon_v off
setstate powerGrid 2024-10-27 12:11:12 washer_v 50



Gruß schwatter
 
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 29 Oktober 2024, 21:25:18
Nabend,

hier ein Update auf Basis des dummyNew.pm, ein Post höher.


1. das SVG steckt in etwas HTML. Dadurch ist eine automatische Skalierung möglich.
2. das JS erweitert
   - Linien die jetzt bei einem Wert > 0 automatisch gestartet werden: solarToHouse,houseToAirdryer,houseToWasher,houseToDryer,houseToDishwasher,houseToFridge.
   - Linien die jetzt bei einem Wert < 0 automatisch gestartet werden: solarToGrid.
   - Linien die noch keine Logik haben: solarToBattery,gridToBattery,batteryToHouse.
   - Batteryringanimation muss auch manuell gesetzt werden.
3. Low-Carbon ist weiterhin ein dummy

Durch die Anpassung im JS, wird jetzt weniger Logik auf Basis eines notify, DOIF's,..., benötigt.
Verbrauchs- oder Erzeugungswerte müssen auch weiterhin gesetzt werden.

defmod powerGrid dummyNew
attr powerGrid readingList airdryer_v battery_v batteryState_v batteryToHouse_v dishwasher_v dryer_v fridge_v grid_v gridToBattery_v gridToBatteryState_v gridToLowCarbon_v gridToHouse_v house_v houseToAirdryer_v houseToDishwasher_v houseToDryer_v houseToFridge_v houseToWasher_v solar_v solarToBattery_v solarToGrid_v solarToHouse_v washer_v
attr powerGrid room Energy1
attr powerGrid setList airdryer_v:textField battery_v:textField batteryState_v:select,backward,stop,forward batteryToHouse_v:select,on,off dishwasher_v:textField dryer_v:textField fridge_v:textField grid_v:textField gridToBattery_v:select,backward,stop,forward gridToLowCarbon_v:select,on,off gridToHouse_v:select,on,off house_v:textField houseToAirdryer_v:select,on,off houseToDishwasher_v:select,on,off houseToDryer_v:select,on,off houseToFridge_v:select,on,off houseToWasher_v:select,on,off solar_v:textField solarToBattery_v:select,on,off solarToGrid_v:select,on,off solarToHouse_v:select,on,off washer_v:textField
attr powerGrid stateFormat <!DOCTYPE html>\
<html>\
<head>\
<title>powerGrid</title>\
<style>\
#wrapper {\
    background: black;;\
}\
svg {\
    width: 100%;;\
    height: auto;;\
}\
</style>\
</head>\
<body>\
\
<div id="wrapper">\
<svg viewBox='0 0 650 500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: 90%;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\
</div>\
</body>\
</html>\


setstate powerGrid <!DOCTYPE html>\
<html>\
<head>\
<title>powerGrid</title>\
<style>\
#wrapper {\
    background: black;;\
}\
svg {\
    width: 100%;;\
    height: auto;;\
}\
</style>\
</head>\
<body>\
\
<div id="wrapper">\
<svg viewBox='0 0 650 500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: 90%;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\
</div>\
</body>\
</html>\

setstate powerGrid 2024-10-29 20:57:56 airdryer_v 0
setstate powerGrid 2024-10-27 12:48:04 battery 235
setstate powerGrid 2024-10-29 21:05:59 batteryState_v stop
setstate powerGrid 2024-10-29 21:05:41 batteryToHouse_v off
setstate powerGrid 2024-10-29 17:35:22 battery_v 0
setstate powerGrid 2024-10-29 20:59:20 dishwasher_v 0
setstate powerGrid 2024-10-29 20:58:35 dryer_v 0
setstate powerGrid 2024-10-29 20:58:41 fridge_v 0
setstate powerGrid 2024-10-29 17:35:32 gridToBattery_v stop
setstate powerGrid 2024-10-29 18:13:45 gridToHouse_v on
setstate powerGrid 2024-10-29 17:25:37 gridToLowCarbon_v off
setstate powerGrid 2024-10-29 21:19:34 grid_v 2385
setstate powerGrid 2024-10-29 18:13:45 houseToAirdryer_v off
setstate powerGrid 2024-10-29 18:13:45 houseToDishwasher_v off
setstate powerGrid 2024-10-29 18:13:45 houseToDryer_v off
setstate powerGrid 2024-10-29 18:13:45 houseToFridge_v off
setstate powerGrid 2024-10-29 18:13:45 houseToWasher_v off
setstate powerGrid 2024-10-29 17:59:27 house_v 539
setstate powerGrid 2024-10-29 17:25:59 solarToBattery_v off
setstate powerGrid 2024-10-29 18:13:45 solarToGrid_v on
setstate powerGrid 2024-10-29 18:13:45 solarToHouse_v off
setstate powerGrid 2024-10-29 21:00:10 solar_v 1
setstate powerGrid 2024-10-29 20:58:18 washer_v 0



Tip: Prüfungen im JS, um allen Mist abzufangen sind noch nicht komplett umgesetzt. Bleiben Werte aus, einmal im powerGrid Dummy alle "set" durchschalten. Fehlt ein Reading, kommen keine Werte.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 31 Oktober 2024, 11:31:51
Moin,

ein weiteres Update auf Basis des dummyNew.pm.

- setList und readingList ausgedünnt.
- neue setList für batteryState_v: stop, gridLoad, gridUnload, solarLoad, houseUnload. Je nach Status werden die Linien angesteuert.
- Battery wird zum Housering nur dazugerechnet, wenn der Status houseUnload ist.
- Battery um %-Wert erweitert. Setzen mit battery_p.
- Low-Carbon funktioniert jetzt und kann gesetzt werden.


1.dummy
defmod powerGrid dummyNew
attr powerGrid readingList airdryer_v battery_v battery_p batteryState_v dishwasher_v dryer_v fridge_v grid_v house_v lowcarbon_v solar_v solarToBattery_v washer_v
attr powerGrid room Energy1
attr powerGrid setList airdryer_v:textField battery_v:textField battery_p:textField batteryState_v:select,stop,gridLoad,gridUnload,solarLoad,houseUnload dishwasher_v:textField dryer_v:textField fridge_v:textField grid_v:textField house_v:textField lowcarbon_v:textField solar_v:textField washer_v:textField
attr powerGrid stateFormat <!DOCTYPE html>\
<html>\
<head>\
<title>powerGrid</title>\
<style>\
#wrapper {\
    background: black;;\
}\
svg {\
    width: 100%;;\
    height: auto;;\
}\
</style>\
</head>\
<body>\
\
<div id="wrapper">\
<svg viewBox='0 0 650 500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: 90%;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text id="batteryPercent" x="250" y="385" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\
</div>\
</body>\
</html>\


setstate powerGrid <!DOCTYPE html>\
<html>\
<head>\
<title>powerGrid</title>\
<style>\
#wrapper {\
    background: black;;\
}\
svg {\
    width: 100%;;\
    height: auto;;\
}\
</style>\
</head>\
<body>\
\
<div id="wrapper">\
<svg viewBox='0 0 650 500' xmlns='http://www.w3.org/2000/svg' style='background-color: black;; width: 90%;; height: auto;;'>\
 \
 <!-- Titel -->\
  <text x='20' y='30' font-family='Arial' font-size='24' fill='white'>Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id='lowCarbonCircle' cx='100' cy='100' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='100' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='100' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Low-Carbon</text>\
  <text id='lowCarbonPower' x='100' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>0 %</text>\
\
  <!-- Solar (Orange) -->\
  <circle id='solarCircle' cx='250' cy='100' r='45' fill='none' stroke='orange' stroke-width='10' opacity='0.4'/>\
  <circle cx='250' cy='100' r='40' fill='none' stroke='orange' stroke-width='5'/>\
  <text x='250' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Solar</text>\
  <text id='solarPower' x='250' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Netz (Blau) -->\
  <circle id='gridCircle' cx='100' cy='250' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='100' cy='250' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='100' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Grid</text>\
  <text id='gridPower' x='100' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text id="batteryPercent" x="250" y="385" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
  <circle id='solarSegment' cx='400' cy='250' r='40' fill='none' stroke='orange' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='gridSegment' cx='400' cy='250' r='40' fill='none' stroke='blue' stroke-width='5' stroke-dasharray='0 100' />\
  <circle id='batterySegment' cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5' stroke-dasharray='0 100' />\
  <text x='400' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>House</text>\
  <text id='housePower' x='400' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id='airDryerCircle' cx='400' cy='100' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='100' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='400' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Airdryer</text>\
  <text id='airdryerPower' x='400' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <circle id='fridgeCircle' cx='400' cy='400' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='400' cy='400' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='400' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Fridge</text>\
  <text id='fridgePower' x='400' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <circle id='washerCircle' cx='550' cy='100' r='45' fill='none' stroke='yellow' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='100' r='40' fill='none' stroke='yellow' stroke-width='5'/>\
  <text x='550' y='100' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Washer</text>\
  <text id='washerPower' x='550' y='115' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id='dryerCircle' cx='550' cy='250' r='45' fill='none' stroke='green' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='250' r='40' fill='none' stroke='green' stroke-width='5'/>\
  <text x='550' y='250' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dryer</text>\
  <text id='dryerPower' x='550' y='265' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id='dishwasherCircle' cx='550' cy='400' r='45' fill='none' stroke='blue' stroke-width='10' opacity='0.4'/>\
  <circle cx='550' cy='400' r='40' fill='none' stroke='blue' stroke-width='5'/>\
  <text x='550' y='400' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'>Dishwasher</text>\
  <text id='dishwasherPower' x='550' y='415' font-family='Arial' font-size='12' fill='white' text-anchor='middle' alignment-baseline='middle'></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id='batteryToHousePath' d='M 260 354 A 110 100 0 0 1 357 260' stroke='purple' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='purple'>\
    <animateMotion id='batteryToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#batteryToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id='solarToHousePath' d='M 260 145 A 110 100 0 0 0 357 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToHouse' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id='solarToBatteryPath' d='M 250 145 A 0 100 0 0 1 250 354' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToBattery' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id='houseToAirdryerPath' d='M 400 203 A 0 67 0 0 1 400 145' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToAirdryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToAirdryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id='houseToFridgePath' d='M 400 298 A 0 67 0 0 1 400 354' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToFridge' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToFridgePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id='gridToLowCarbonPath' d='M 100 208 A 0 68 0 0 1 100 145' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='gridToLowCarbon' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToLowCarbonPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id='gridToHousePath' d='M 146 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='gridToHouse' dur='3s' repeatCount='indefinite'>\
      <mpath href='#gridToHousePath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id='houseToDryerPath' d='M 446 250 A 0 0 0 0 1 505 250' stroke='green' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='green'>\
    <animateMotion id='houseToDryer' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#houseToDryerPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id='houseToDishwasherPath' d='M 446 260 A 110 110 0 0 1 550 354' stroke='blue' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='blue'>\
    <animateMotion id='houseToDishwasher' dur='3s' repeatCount='indefinite'>\
      <mpath href='#houseToDishwasherPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id='solarToGridPath' d='M 240 145 A 110 100 0 0 1 146 240' stroke='orange' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='orange'>\
    <animateMotion id='solarToGrid' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#solarToGridPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id='gridToBatteryPath' d='M 146 260 A 110 100 0 0 1 240 354' stroke='turquoise' stroke-width='2' fill='transparent'/>\
  <circle id="gridToBatteryStatic" r='5' fill='turquoise' style="display:none;;" />\
  <circle id="gridToBatteryForward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryForwardAnim' dur='3s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
  <circle id="gridToBatteryBackward" r='5' fill='turquoise' style="display:none;;">\
    <animateMotion id='gridToBatteryBackwardAnim' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#gridToBatteryPath'/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id='houseToWasherPath' d='M 550 145 A 110 100 0 0 1 446 240' stroke='yellow' stroke-width='2' fill='transparent'/>\
  <circle r='5' fill='yellow'>\
    <animateMotion id='houseToWasher' dur='3s' repeatCount='indefinite' keyPoints='1;;0' keyTimes='0;;1'>\
      <mpath href='#houseToWasherPath'/>\
    </animateMotion>\
  </circle>\
\
</svg>\
</div>\
</body>\
</html>\

setstate powerGrid 2024-10-31 11:22:56 airdryer_v 210
setstate powerGrid 2024-10-31 11:13:29 batteryState_v houseUnload
setstate powerGrid 2024-10-31 11:21:32 battery_p 33
setstate powerGrid 2024-10-31 11:14:29 battery_v 33
setstate powerGrid 2024-10-31 11:22:59 dishwasher_v 0
setstate powerGrid 2024-10-31 11:24:35 dryer_v 0
setstate powerGrid 2024-10-31 11:24:26 fridge_v 76
setstate powerGrid 2024-10-31 11:24:41 grid_v 489
setstate powerGrid 2024-10-31 11:24:41 house_v 724.1
setstate powerGrid 2024-10-31 11:12:09 lowcarbon_v 9
setstate powerGrid 2024-10-31 11:24:44 solar_v 235.1
setstate powerGrid 2024-10-31 11:24:34 washer_v 0



2. Mein DOIF
defmod Powergrid_DOIF DOIF ## Grid + House\
([MQTT2_Smartmeter_2E1F50:"APOX_Power"])\
        ( set powerGrid grid_v {(ReadingsNum("MQTT2_Smartmeter_2E1F50","APOX_Power",0))} )\
        ( set powerGrid house_v {(ReadingsVal("MQTT2_Smartmeter_2E1F50","APOX_Power",0) + ReadingsVal("MQTT2_OpenDTU_585584","power",0))} ) \
\
## Airdryer\
DOELSEIF  ([Luftentfeuchter:"ENERGY_Power"])\
        ( set powerGrid airdryer_v {(ReadingsNum("Luftentfeuchter","ENERGY_Power",0))} )\
\
## Dishwasher\
DOELSEIF  ([MQTT2_zigbee_Geschirrspueler:"power"])\
        ( set powerGrid dishwasher_v {(ReadingsNum("MQTT2_zigbee_Geschirrspueler","power",0))} )\
\
## Dryer\
DOELSEIF  ([MQTT2_zigbee_Trockner:"power"])\
        ( set powerGrid dryer_v {(ReadingsNum("MQTT2_zigbee_Trockner","power",0))} )\
\
## Fridge\
DOELSEIF  ([MQTT2_zigbee_Kuehlschrank:"^power:.*$"])\
        ( set powerGrid fridge_v {(ReadingsNum("MQTT2_zigbee_Kuehlschrank","power",0))} )\
\
## Solar\
DOELSEIF   ([MQTT2_OpenDTU_585584:"power"] )\
        ( set powerGrid solar_v {(ReadingsNum("MQTT2_OpenDTU_585584","power",0))} )\
\
## Washer\
DOELSEIF  ([MQTT2_zigbee_Waschmaschine:"power"])\
        ( set powerGrid washer_v {(ReadingsNum("MQTT2_zigbee_Waschmaschine","power",0))} )\


setstate Powergrid_DOIF cmd_6
setstate Powergrid_DOIF 2024-10-31 11:28:52 Device MQTT2_OpenDTU_585584
setstate Powergrid_DOIF 2024-10-31 11:28:37 cmd 6
setstate Powergrid_DOIF 2024-10-31 11:28:37 cmd_event MQTT2_OpenDTU_585584
setstate Powergrid_DOIF 2024-10-31 11:28:37 cmd_nr 6
setstate Powergrid_DOIF 2024-10-31 11:27:56 e_Luftentfeuchter_events ENERGY_Voltage: 221,ENERGY_Period: 17,ENERGY_Power: 210,ENERGY_Current: 1.498,ENERGY_Factor: 0.63,ENERGY_Yesterday: 0.604,Time: 2024-10-31T12:27:55,ENERGY_Total: 77.216,ENERGY_TotalStartTime: 2024-08-17T10:11:53,ENERGY_ApparentPower: 331,ENERGY_Today: 0.193,ENERGY_ReactivePower: 256
setstate Powergrid_DOIF 2024-10-31 11:28:52 e_MQTT2_OpenDTU_585584_events 116483796003_0_efficiency: 95.247,ForecastToday: 6592 Wh,ForecastTomorrow: 4486 Wh
setstate Powergrid_DOIF 2024-10-31 11:28:37 e_MQTT2_Smartmeter_2E1F50_events StatusSNS_APOX_E_in: 407.821,StatusSNS_APOX_Power: 568,StatusSNS_Time: 2024-10-31T11:28:36
setstate Powergrid_DOIF 2024-10-31 11:28:19 e_MQTT2_zigbee_Geschirrspueler_events current: 0,linkquality: 216,on,voltage: 229,power_outage_memory: restore,energy: 11.15,last_seen: 2024-10-31T11:28:19+01:00,child_lock: UNLOCK,power: 0,countdown: 0,indicator_mode: off/on
setstate Powergrid_DOIF 2024-10-31 11:27:59 e_MQTT2_zigbee_Kuehlschrank_events last_seen: 2024-10-31T11:27:59+01:00,current: 0.37,ON,voltage: 225,child_lock: UNLOCK,linkquality: 172,power: 76,countdown: 0,indicator_mode: off/on,power_outage_memory: restore,energy: 17.98
setstate Powergrid_DOIF 2024-10-31 11:28:28 e_MQTT2_zigbee_Trockner_events energy: 213.93,power_outage_memory: restore,update_state: available,update_installed_version: 77,voltage: 230,on,linkquality: 132,current: 0.03,update_latest_version: 192,indicator_mode: off/on,countdown: 0,power: 15,child_lock: UNLOCK,last_seen: 2024-10-31T11:28:28+01:00
setstate Powergrid_DOIF 2024-10-31 11:27:23 e_MQTT2_zigbee_Waschmaschine_events indicator_mode: off/on,countdown: 0,last_seen: 2024-10-31T11:27:23+01:00,power: 0,child_lock: UNLOCK,power_outage_memory: restore,energy: 248.71,current: 0,update_latest_version: 192,update_state: available,update_installed_version: 77,on,voltage: 228,linkquality: 124
setstate Powergrid_DOIF 2024-10-29 22:09:44 mode enabled
setstate Powergrid_DOIF 2024-10-31 11:28:37 state cmd_6




Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 31 Oktober 2024, 13:26:30
So langsam ist es perfekt.
Sieht richtig gut aus.
Danke dir.
denkst du noch an
Zitat2. Bei Grid evtl gleich 3 Werte:
   Momentaner Grid Export/import mit + oder -
   Heutiger Export
   Heutiger Import

Hier würde ich gerne zugunsten des aktuellen Preises(z.B. von Tibber) auf den heutigen Export/Import verzichten wollen.

Ansonsten gute Arbeit.

Gruß

Hubert
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 31 Oktober 2024, 19:33:25
Nabend,

ah super. Dann kommen endlich die Werte.
Hatte schon gedacht, ich hab etwas vermurkst.

Bei der Batterie bin ich mir noch unschlüssig.
- so lassen.
- maximal 2 Werte im Ring.
- 3 Werte im Ring, Namen außerhalb. Dann für alle.
- extra Readings unter dem Grid, für alles mögliche.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 08 November 2024, 20:47:32
Nabend,

ich habe einen Kompromiss aus beiden zusammengebaut. Falls es doof aussieht, würde ich die animierten Ringe Haus und Batterie
demnächst versuchen, auch auf animierte Kästen umzubauen. Ganz zufrieden bin ich noch nicht.

Update:
- Grid, Solar, Fridge und Washer auf Kasten mit abgerundeten Ecken umgebaut.
- Grid hat dadurch jetzt 3 Werte (grid_v, grid_in_v, grid_out_v)
- Im JS habe ich die 2 neuen Werte grid_in_v und grid_out_v auf eine Nachkommastelle begrenzt.
- Außerdem sind die angezeigten Bezeichnungen ausnahmsweise kWh. Da mein SmartMeterReader die Werte so ausgibt.
Umrechnen möchte ich nicht, da es Platz spart.

Wer das anpassen möchte im JS, hier sind die Stellen:

        const gridReadingIn = parseFloat(parseFloat(doc.querySelector("div[informid='powerGrid-grid_in_v']").textContent).toFixed(1));
        const gridReadingOut = parseFloat(parseFloat(doc.querySelector("div[informid='powerGrid-grid_out_v']").textContent).toFixed(1));


        document.getElementById('gridPowerIn').textContent = gridReadingIn + " kWh";
        document.getElementById('gridPowerOut').textContent = gridReadingOut + " kWh";




1.dummyNew
defmod powerGrid dummyNew
attr powerGrid readingList airdryer_v battery_v battery_p batteryState_v dishwasher_v dryer_v fridge_v grid_v grid_in_v grid_out_v house_v lowcarbon_v solar_v solarToBattery_v washer_v
attr powerGrid room Energy1
attr powerGrid setList airdryer_v:textField battery_v:textField battery_p:textField batteryState_v:select,stop,gridLoad,gridUnload,solarLoad,houseUnload dishwasher_v:textField dryer_v:textField fridge_v:textField grid_v:textField grid_in_v:textField grid_out_v:textField house_v:textField lowcarbon_v:textField solar_v:textField washer_v:textField
attr powerGrid stateFormat <!DOCTYPE html>\
<html>\
<head>\
<title>powerGrid</title>\
<style>\
#wrapper {\
    background: black;;\
}\
svg {\
    width: 100%;;\
    height: auto;;\
}\
</style>\
</head>\
<body>\
\
<div id="wrapper">\
<svg viewBox="0 0 650 500" xmlns="http://www.w3.org/2000/svg" style="background-color: black;; width: 90%;; height: auto;;">\
 \
 <!-- Titel -->\
  <text x="20" y="30" font-family="Arial" font-size="24" fill="white">Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id="lowCarbonCircle" cx="100" cy="100" r="45" fill="none" stroke="green" stroke-width="10" opacity="0.4"/>\
  <circle cx="100" cy="100" r="40" fill="none" stroke="green" stroke-width="5"/>\
  <text x="100" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Low-Carbon</text>\
  <text id="lowCarbonPower" x="100" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">0 %</text>\
\
  <!-- Solar (Orange) - Glow Kasten -->\
  <rect x="205" y="55" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="orange" stroke-width="10"/>\
  <rect x="210" y="60" rx="20" ry="20" width="80" height="80" fill="none" stroke="orange" stroke-width="5" />\
  <text x="250" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Solar</text>\
  <text id="solarPower" x="250" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Netz (Blau) -->\
  <rect x="55" y="205" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="blue" stroke-width="10"/>\
  <rect x="60" y="210" rx="20" ry="20" width="80" height="80" fill="none" stroke="blue" stroke-width="5" />  \
  <text id="gridPower" x="100" y="235" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text x="100" y="250" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Grid</text>\
  <text id="gridPowerIn" x="100" y="265" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text id="gridPowerOut" x="100" y="280" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text id="batteryPercent" x="250" y="385" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id="batteryCircle" cx="250" cy="400" r="45" fill="none" stroke="turquoise" stroke-width="10" opacity="0.4"/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id="houseCircle" cx="400" cy="250" r="45" fill="none" stroke="purple" stroke-width="10" opacity="0.4"/>\
  <circle id="solarSegment" cx="400" cy="250" r="40" fill="none" stroke="orange" stroke-width="5" stroke-dasharray="0 100" />\
  <circle id="gridSegment" cx="400" cy="250" r="40" fill="none" stroke="blue" stroke-width="5" stroke-dasharray="0 100" />\
  <circle id="batterySegment" cx="400" cy="250" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="0 100" />\
  <text x="400" y="250" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">House</text>\
  <text id="housePower" x="400" y="265" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id="airDryerCircle" cx="400" cy="100" r="45" fill="none" stroke="blue" stroke-width="10" opacity="0.4"/>\
  <circle cx="400" cy="100" r="40" fill="none" stroke="blue" stroke-width="5"/>\
  <text x="400" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Airdryer</text>\
  <text id="airdryerPower" x="400" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <rect x="355" y="355" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="yellow" stroke-width="10"/>\
  <rect x="360" y="360" rx="20" ry="20" width="80" height="80" fill="none" stroke="yellow" stroke-width="5" />\
  <text x="400" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Fridge</text>\
  <text id="fridgePower" x="400" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <rect x="505" y="55" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="yellow" stroke-width="10"/>\
  <rect x="510" y="60" rx="20" ry="20" width="80" height="80" fill="none" stroke="yellow" stroke-width="5" />\
  <text x="550" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Washer</text>\
  <text id="washerPower" x="550" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id="dryerCircle" cx="550" cy="250" r="45" fill="none" stroke="green" stroke-width="10" opacity="0.4"/>\
  <circle cx="550" cy="250" r="40" fill="none" stroke="green" stroke-width="5"/>\
  <text x="550" y="250" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Dryer</text>\
  <text id="dryerPower" x="550" y="265" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id="dishwasherCircle" cx="550" cy="400" r="45" fill="none" stroke="blue" stroke-width="10" opacity="0.4"/>\
  <circle cx="550" cy="400" r="40" fill="none" stroke="blue" stroke-width="5"/>\
  <text x="550" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Dishwasher</text>\
  <text id="dishwasherPower" x="550" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id="batteryToHousePath" d="M 260 354 A 110 100 0 0 1 357 260" stroke="purple" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="purple">\
    <animateMotion id="batteryToHouse" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#batteryToHousePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id="solarToHousePath" d="M 260 145 A 110 100 0 0 0 357 240" stroke="orange" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="orange">\
    <animateMotion id="solarToHouse" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#solarToHousePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id="solarToBatteryPath" d="M 250 145 A 0 100 0 0 1 250 354" stroke="orange" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="orange">\
    <animateMotion id="solarToBattery" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#solarToBatteryPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id="houseToAirdryerPath" d="M 400 203 A 0 67 0 0 1 400 145" stroke="blue" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="blue">\
    <animateMotion id="houseToAirdryer" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToAirdryerPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id="houseToFridgePath" d="M 400 298 A 0 67 0 0 1 400 354" stroke="yellow" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="yellow">\
    <animateMotion id="houseToFridge" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToFridgePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id="gridToLowCarbonPath" d="M 100 208 A 0 68 0 0 1 100 145" stroke="green" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="green">\
    <animateMotion id="gridToLowCarbon" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#gridToLowCarbonPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id="gridToHousePath" d="M 146 250 H 357" stroke="blue" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="blue">\
    <animateMotion id="gridToHouse" dur="3s" repeatCount="indefinite">\
      <mpath href="#gridToHousePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id="houseToDryerPath" d="M 446 250 A 0 0 0 0 1 505 250" stroke="green" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="green">\
    <animateMotion id="houseToDryer" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToDryerPath"/>\
    </animateMotion>\
  </circle>\
\
    <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id="houseToWasherPath" d="M 446 240 A 110 110 0 0 0 550 145" stroke="yellow" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="yellow">\
    <animateMotion id="houseToWasher" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToWasherPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id="houseToDishwasherPath" d="M 446 260 A 110 110 0 0 1 550 354" stroke="blue" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="blue">\
    <animateMotion id="houseToDishwasher" dur="3s" repeatCount="indefinite">\
      <mpath href="#houseToDishwasherPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id="solarToGridPath" d="M 240 145 A 110 100 0 0 1 146 240" stroke="orange" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="orange">\
    <animateMotion id="solarToGrid" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#solarToGridPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id="gridToBatteryPath" d="M 146 260 A 110 100 0 0 1 240 354" stroke="turquoise" stroke-width="2" fill="transparent"/>\
  <circle id="gridToBatteryStatic" r="5" fill="turquoise" style="display:none;;" />\
  <circle id="gridToBatteryForward" r="5" fill="turquoise" style="display:none;;">\
    <animateMotion id="gridToBatteryForwardAnim" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#gridToBatteryPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Batterie zu Netz (Turkis) -->\
  <path id="batteryToGridPath" d="M 240 354 A 110 100 0 0 0 146 260" stroke="turquoise" stroke-width="2" fill="transparent"/>\
  <circle id="batteryToGridForward" r="5" fill="turquoise" style="display:none;;">\
    <animateMotion id="batteryToGridForwardAnim" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#batteryToGridPath"/>\
    </animateMotion>\
  </circle>\
\
</svg>\
</div>\
</body>\
</html>

setstate powerGrid <!DOCTYPE html>\
<html>\
<head>\
<title>powerGrid</title>\
<style>\
#wrapper {\
    background: black;;\
}\
svg {\
    width: 100%;;\
    height: auto;;\
}\
</style>\
</head>\
<body>\
\
<div id="wrapper">\
<svg viewBox="0 0 650 500" xmlns="http://www.w3.org/2000/svg" style="background-color: black;; width: 90%;; height: auto;;">\
 \
 <!-- Titel -->\
  <text x="20" y="30" font-family="Arial" font-size="24" fill="white">Power Flow</text>\
\
  <!-- Kohlenstoffarm (Grün) -->\
  <circle id="lowCarbonCircle" cx="100" cy="100" r="45" fill="none" stroke="green" stroke-width="10" opacity="0.4"/>\
  <circle cx="100" cy="100" r="40" fill="none" stroke="green" stroke-width="5"/>\
  <text x="100" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Low-Carbon</text>\
  <text id="lowCarbonPower" x="100" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">0 %</text>\
\
  <!-- Solar (Orange) - Glow Kasten -->\
  <rect x="205" y="55" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="orange" stroke-width="10"/>\
  <rect x="210" y="60" rx="20" ry="20" width="80" height="80" fill="none" stroke="orange" stroke-width="5" />\
  <text x="250" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Solar</text>\
  <text id="solarPower" x="250" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Netz (Blau) -->\
  <rect x="55" y="205" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="blue" stroke-width="10"/>\
  <rect x="60" y="210" rx="20" ry="20" width="80" height="80" fill="none" stroke="blue" stroke-width="5" />  \
  <text id="gridPower" x="100" y="235" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text x="100" y="250" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Grid</text>\
  <text id="gridPowerIn" x="100" y="265" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text id="gridPowerOut" x="100" y="280" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie Label -->\
  <text x="250" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Battery</text>\
  <text id="batteryPower" x="250" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
  <text id="batteryPercent" x="250" y="385" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Batterie stop (Turkis) -->\
  <circle id="batteryCircle" cx="250" cy="400" r="45" fill="none" stroke="turquoise" stroke-width="10" opacity="0.4"/>\
  <circle id="batteryStatic" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5"/>\
\
  <!-- Batterie dreht links -->\
  <circle id="batteryClockwise" cx="250" cy="400" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Batteriering dreht rechts -->\
  <circle id="batteryCounterClockwise" cx="250" cy="400" r="40" fill="none" stroke="turquoise" stroke-width="5" stroke-dasharray="9 5" stroke-dashoffset="3" style="display:none;;">\
    <animateTransform attributeName="transform" type="rotate" from="0 250 400" to="-360 250 400" dur="5s" repeatCount="indefinite" />\
  </circle>\
\
  <!-- Haus + Ringsegmente -->\
  <circle id="houseCircle" cx="400" cy="250" r="45" fill="none" stroke="purple" stroke-width="10" opacity="0.4"/>\
  <circle id="solarSegment" cx="400" cy="250" r="40" fill="none" stroke="orange" stroke-width="5" stroke-dasharray="0 100" />\
  <circle id="gridSegment" cx="400" cy="250" r="40" fill="none" stroke="blue" stroke-width="5" stroke-dasharray="0 100" />\
  <circle id="batterySegment" cx="400" cy="250" r="40" fill="none" stroke="purple" stroke-width="5" stroke-dasharray="0 100" />\
  <text x="400" y="250" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">House</text>\
  <text id="housePower" x="400" y="265" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Lufttrockner (Blau) -->\
  <circle id="airDryerCircle" cx="400" cy="100" r="45" fill="none" stroke="blue" stroke-width="10" opacity="0.4"/>\
  <circle cx="400" cy="100" r="40" fill="none" stroke="blue" stroke-width="5"/>\
  <text x="400" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Airdryer</text>\
  <text id="airdryerPower" x="400" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Kühlschrank (Gelb) -->\
  <rect x="355" y="355" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="yellow" stroke-width="10"/>\
  <rect x="360" y="360" rx="20" ry="20" width="80" height="80" fill="none" stroke="yellow" stroke-width="5" />\
  <text x="400" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Fridge</text>\
  <text id="fridgePower" x="400" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Waschmaschine (Gelb) -->\
  <rect x="505" y="55" rx="25" ry="25" width="90" height="90" fill="none" opacity="0.3" stroke="yellow" stroke-width="10"/>\
  <rect x="510" y="60" rx="20" ry="20" width="80" height="80" fill="none" stroke="yellow" stroke-width="5" />\
  <text x="550" y="100" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Washer</text>\
  <text id="washerPower" x="550" y="115" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Trockner (Grün) -->\
  <circle id="dryerCircle" cx="550" cy="250" r="45" fill="none" stroke="green" stroke-width="10" opacity="0.4"/>\
  <circle cx="550" cy="250" r="40" fill="none" stroke="green" stroke-width="5"/>\
  <text x="550" y="250" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Dryer</text>\
  <text id="dryerPower" x="550" y="265" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Geschirrspüler (Blau) -->\
  <circle id="dishwasherCircle" cx="550" cy="400" r="45" fill="none" stroke="blue" stroke-width="10" opacity="0.4"/>\
  <circle cx="550" cy="400" r="40" fill="none" stroke="blue" stroke-width="5"/>\
  <text x="550" y="400" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle">Dishwasher</text>\
  <text id="dishwasherPower" x="550" y="415" font-family="Arial" font-size="12" fill="white" text-anchor="middle" alignment-baseline="middle"></text>\
\
  <!-- Verbindungslinien -->\
\
  <!-- Verbindungslinie von Batterie zu Haus (Lila) --> \
  <path id="batteryToHousePath" d="M 260 354 A 110 100 0 0 1 357 260" stroke="purple" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="purple">\
    <animateMotion id="batteryToHouse" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#batteryToHousePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
  <path id="solarToHousePath" d="M 260 145 A 110 100 0 0 0 357 240" stroke="orange" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="orange">\
    <animateMotion id="solarToHouse" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#solarToHousePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
  <path id="solarToBatteryPath" d="M 250 145 A 0 100 0 0 1 250 354" stroke="orange" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="orange">\
    <animateMotion id="solarToBattery" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#solarToBatteryPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Lufttrockner (Blau) -->\
  <path id="houseToAirdryerPath" d="M 400 203 A 0 67 0 0 1 400 145" stroke="blue" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="blue">\
    <animateMotion id="houseToAirdryer" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToAirdryerPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Kühlschrank (Gelb) -->\
  <path id="houseToFridgePath" d="M 400 298 A 0 67 0 0 1 400 354" stroke="yellow" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="yellow">\
    <animateMotion id="houseToFridge" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToFridgePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Kohlenstoffarm (Grün) -->\
  <path id="gridToLowCarbonPath" d="M 100 208 A 0 68 0 0 1 100 145" stroke="green" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="green">\
    <animateMotion id="gridToLowCarbon" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#gridToLowCarbonPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
  <path id="gridToHousePath" d="M 146 250 H 357" stroke="blue" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="blue">\
    <animateMotion id="gridToHouse" dur="3s" repeatCount="indefinite">\
      <mpath href="#gridToHousePath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Trockner (Green) -->\
  <path id="houseToDryerPath" d="M 446 250 A 0 0 0 0 1 505 250" stroke="green" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="green">\
    <animateMotion id="houseToDryer" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToDryerPath"/>\
    </animateMotion>\
  </circle>\
\
    <!-- Verbindungslinie von Haus zu Waschmaschine (Gelb) -->\
  <path id="houseToWasherPath" d="M 446 240 A 110 110 0 0 0 550 145" stroke="yellow" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="yellow">\
    <animateMotion id="houseToWasher" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#houseToWasherPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Haus zu Geschirrspüler (Blue) -->\
  <path id="houseToDishwasherPath" d="M 446 260 A 110 110 0 0 1 550 354" stroke="blue" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="blue">\
    <animateMotion id="houseToDishwasher" dur="3s" repeatCount="indefinite">\
      <mpath href="#houseToDishwasherPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
  <path id="solarToGridPath" d="M 240 145 A 110 100 0 0 1 146 240" stroke="orange" stroke-width="2" fill="transparent"/>\
  <circle r="5" fill="orange">\
    <animateMotion id="solarToGrid" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#solarToGridPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
  <path id="gridToBatteryPath" d="M 146 260 A 110 100 0 0 1 240 354" stroke="turquoise" stroke-width="2" fill="transparent"/>\
  <circle id="gridToBatteryStatic" r="5" fill="turquoise" style="display:none;;" />\
  <circle id="gridToBatteryForward" r="5" fill="turquoise" style="display:none;;">\
    <animateMotion id="gridToBatteryForwardAnim" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#gridToBatteryPath"/>\
    </animateMotion>\
  </circle>\
\
  <!-- Verbindungslinie von Batterie zu Netz (Turkis) -->\
  <path id="batteryToGridPath" d="M 240 354 A 110 100 0 0 0 146 260" stroke="turquoise" stroke-width="2" fill="transparent"/>\
  <circle id="batteryToGridForward" r="5" fill="turquoise" style="display:none;;">\
    <animateMotion id="batteryToGridForwardAnim" dur="3s" repeatCount="indefinite" keyPoints="0;;1" keyTimes="0;;1">\
      <mpath href="#batteryToGridPath"/>\
    </animateMotion>\
  </circle>\
\
</svg>\
</div>\
</body>\
</html>
setstate powerGrid 2024-11-09 19:27:38 airdryer_v 0
setstate powerGrid 2024-11-09 19:28:25 batteryState_v stop
setstate powerGrid 2024-11-01 12:43:15 battery_p 100
setstate powerGrid 2024-11-01 12:43:35 battery_v 0
setstate powerGrid 2024-11-09 19:28:38 dishwasher_v 0
setstate powerGrid 2024-11-09 19:29:17 dryer_v 0
setstate powerGrid 2024-11-09 19:28:12 fridge_v 0
setstate powerGrid 2024-11-09 19:29:14 grid_in_v 485.170
setstate powerGrid 2024-11-09 19:29:14 grid_out_v 81.575
setstate powerGrid 2024-11-09 19:29:14 grid_v 364
setstate powerGrid 2024-11-09 19:29:14 house_v 364
setstate powerGrid 2024-11-03 17:52:47 lowcarbon_v 0
setstate powerGrid 2024-11-09 19:29:15 solar_v 0
setstate powerGrid 2024-11-09 19:29:16 washer_v 0



2. Mein DOIF

defmod Powergrid_DOIF DOIF ## Grid + House\
([MQTT2_Smartmeter_2E1F50:"APOX_Power"])\
        ( set powerGrid grid_v {(ReadingsNum("MQTT2_Smartmeter_2E1F50","APOX_Power",0))} )\
        ( set powerGrid grid_in_v {(ReadingsNum("MQTT2_Smartmeter_2E1F50","APOX_E_in",0))} )\
        ( set powerGrid grid_out_v {(ReadingsNum("MQTT2_Smartmeter_2E1F50","APOX_E_out",0))} )\
        ( set powerGrid house_v {(ReadingsVal("MQTT2_Smartmeter_2E1F50","APOX_Power",0) + ReadingsVal("MQTT2_OpenDTU_585584","power",0))} ) \
\
## Airdryer\
DOELSEIF  ([Luftentfeuchter:"ENERGY_Power"])\
        ( set powerGrid airdryer_v {(ReadingsNum("Luftentfeuchter","ENERGY_Power",0))} )\
\
## Dishwasher\
DOELSEIF  ([MQTT2_zigbee_Geschirrspueler:"power"])\
        ( set powerGrid dishwasher_v {(ReadingsNum("MQTT2_zigbee_Geschirrspueler","power",0))} )\
\
## Dryer\
DOELSEIF  ([MQTT2_zigbee_Trockner:"power"])\
        ( set powerGrid dryer_v {(ReadingsNum("MQTT2_zigbee_Trockner","power",0))} )\
\
## Fridge\
DOELSEIF  ([MQTT2_zigbee_Kuehlschrank:"^power:.*$"])\
        ( set powerGrid fridge_v {(ReadingsNum("MQTT2_zigbee_Kuehlschrank","power",0))} )\
\
## Solar\
DOELSEIF   ([MQTT2_OpenDTU_585584:"power"] )\
        ( set powerGrid solar_v {(ReadingsNum("MQTT2_OpenDTU_585584","power",0))} )\
\
## Washer\
DOELSEIF  ([MQTT2_zigbee_Waschmaschine:"power"])\
        ( set powerGrid washer_v {(ReadingsNum("MQTT2_zigbee_Waschmaschine","power",0))} )\


setstate Powergrid_DOIF cmd_6
setstate Powergrid_DOIF 2024-11-08 20:35:49 Device MQTT2_OpenDTU_585584
setstate Powergrid_DOIF 2024-11-08 20:35:49 cmd 6
setstate Powergrid_DOIF 2024-11-08 20:35:49 cmd_event MQTT2_OpenDTU_585584
setstate Powergrid_DOIF 2024-11-08 20:35:49 cmd_nr 6
setstate Powergrid_DOIF 2024-11-08 20:32:40 e_Luftentfeuchter_events ENERGY_Period: 0,ENERGY_Today: 0.447,ENERGY_TotalStartTime: 2024-08-17T10:11:53,ENERGY_ApparentPower: 0,ENERGY_Yesterday: 0.516,ENERGY_Current: 0.000,ENERGY_Factor: 0.00,Time: 2024-11-08T21:32:40,ENERGY_ReactivePower: 0,ENERGY_Power: 0,ENERGY_Total: 82.747,ENERGY_Voltage: 0
setstate Powergrid_DOIF 2024-11-08 20:35:49 e_MQTT2_OpenDTU_585584_events is_valid: 1,ForecastToday: 864 Wh,ForecastTomorrow: 8497 Wh
setstate Powergrid_DOIF 2024-11-08 20:35:39 e_MQTT2_Smartmeter_2E1F50_events StatusSNS_APOX_Power: 264,StatusSNS_APOX_E_in: 475.202,StatusSNS_Time: 2024-11-08T20:35:39
setstate Powergrid_DOIF 2024-11-08 20:35:47 e_MQTT2_zigbee_Geschirrspueler_events on,last_seen: 2024-11-08T20:35:47+01:00,linkquality: 236,power_outage_memory: restore,energy: 14.1,power: 0,countdown: 0,indicator_mode: off/on,voltage: 226,current: 0,child_lock: UNLOCK
setstate Powergrid_DOIF 2024-11-08 20:33:13 e_MQTT2_zigbee_Kuehlschrank_events energy: 23.54,power: 0,power_outage_memory: restore,linkquality: 188,ON,last_seen: 2024-11-08T20:33:13+01:00,current: 0,child_lock: UNLOCK,voltage: 226,indicator_mode: off/on,countdown: 0
setstate Powergrid_DOIF 2024-11-08 20:35:12 e_MQTT2_zigbee_Trockner_events countdown: 0,child_lock: UNLOCK,voltage: 226,update_state: available,on,energy: 215.15,linkquality: 140,indicator_mode: off/on,current: 0,update_installed_version: 77,last_seen: 2024-11-08T20:35:12+01:00,update_latest_version: 192,power_outage_memory: restore,power: 0
setstate Powergrid_DOIF 2024-11-08 20:35:44 e_MQTT2_zigbee_Waschmaschine_events on,linkquality: 116,energy: 251.09,countdown: 0,voltage: 229,update_state: available,child_lock: UNLOCK,last_seen: 2024-11-08T20:35:44+01:00,update_latest_version: 192,update_installed_version: 77,power_outage_memory: restore,power: 0,indicator_mode: off/on,current: 0
setstate Powergrid_DOIF 2024-11-08 20:12:30 mode enabled
setstate Powergrid_DOIF 2024-11-08 20:35:49 state cmd_6



Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 09 November 2024, 17:56:08
Tag,

ich musste das SVG, bzw die Linie von Haus zu Waschmaschine fixen. Ich hatte die Linie damals falschherum gebaut.
Sprich der Startpunkt war an der Waschmaschine und bewegte sich zum Haus. Als Workaround hatte ich keyPoints="1;0" gesetzt.
Jetzt gerade ist mir aufgefallen, alle meine Browser kommen damit klar. Aber Fully auf meinem Tablet nicht...
Daher, Linie drehen und keyPoints="0;1". 

Das Update ist einen Post höher in der Raw von 1.dummyNew.

edit:
Bei gridUnload ist bei Fully der selbe Effekt. Der Startpunkt ist bei Grid. Bei Batterie laden ist die Animation zur Batterie. Bei entladen ins Netzt aber auch zur Batterie...
Am PC mit Chrome ist es ok.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 09 November 2024, 19:36:29
Und noch ein Update.

Wegen Fully musste ich eine identische Linie von Batterie zu Netz einfügen. Die beiden Linien sind überlagert und haben
unterschiedliche Startpunkte. Einen Fehler im JS, welcher eine Linie nicht abgeschaltet hat, habe ich auch noch entdeckt
und gefixt.

Die Änderungen sind in Post #18 eingeflossen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 10 November 2024, 16:08:19
Nabend,

ich habe jetzt Low-Carbon mit eingebunden.

- Im SVG umbenannt in FossilFree
- Ein HTTPMOD zum auslesen erstellt
- Die Linie zu FossilFree musste ich nochmal drehen. Der animierte Punkt wandert nun von FossilFree zu Grid
- Der animierte Punkt wird jetzt nur vom JS angesteuert, wenn Grid > 0 ist oder die Batterie den Status gridLoad hat.

Im Moment nutze ich nur noch den modifizierten Dummy. Deshalb habe ich alles im ersten Post daraufhin überarbeitet.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 14 November 2024, 18:55:39
Nabend

Update im ersten Post. Geändert dummy + svg_update.js

- Das SVG wieder auf viele Ringe geändert. Außer Grid.
- Neue Farben.
- Verbindungslinie von Netz zu Haus und Solar zu Batterie vermischt. Damit der animierte Punkt von Solar zu Batterie nicht mehr drunter fährt.
- JS angepasst. Jetzt verschwinden die Punkte bei Stop und ruhen nicht mehr.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ch.eick am 16 November 2024, 08:58:40
Hallo zusammen,
tolle Arbeit!

Ich verwende seit geraumer Zeit das doif im Perl Modus, da stecken extrem viele Möglichkeiten in Bezug auf GUI drin und andere Devices wie das Dummy  fallen weg.

Als Beispiel von mir schaut euch mal das WR_1_ctl an. Da habe ich
- Diagramme im uiState
- Pulldown Menüs im uiState
- Statistiken im uiTable
drin.

Wenn man da das Flowchart ins stateFormat unter kriegen könnte wäre alles schön zusammen.

Ein Bild kommt gleich...

VG Christian
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 16 November 2024, 10:29:36
Morgen,

das freut mich. Ich bin auch der Freund von "alles in einem Device". Aber manchmal muss man akzeptieren, das das nicht
immer harmonisch zusammen funktioniert. Deswegen habe ich den dummy im ersten Post modifiziert, damit ein refresh des
STATE unterdrückt wird. Bzw, werden alle Werte im Hintergrund gesetzt, aber die Seitenansicht wird nicht neu geladen.
Ohne das, werden die Animationen unterbrochen und starten abrupt von vorne.

Bei DOIF oder auch dummy ist es bis jetzt nicht möglich, das zu unterbinden. Das SVG ist quasi nur ein stiller Platzhalter, welcher vom JS gefüttert wird.

Falls du es mit deinem DOIF zusammen benutzen willst, würde ich dir attr subType vorschlagen. Nutz du für alle Devices den
selben subType, sieht es so aus, als wenn diese zusammengehören.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ch.eick am 16 November 2024, 11:52:36
Zitat von: schwatter am 16 November 2024, 10:29:36Falls du es mit deinem DOIF zusammen benutzen willst, würde ich dir attr subType vorschlagen. Nutz du für alle Devices den
selben subType, sieht es so aus, als wenn diese zusammengehören.
Das attr subType kenne ich noch nicht, muss ich mich mal einlesen, was das bewirkt.

EDIT: Im DOIF Perl Modus kann ich kein attr subType finden und verstehe auch nicht wofür das sein soll.
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 17 November 2024, 12:13:43
Mahlzeit,

Update im ersten Post. Geändert dummy + svg_update.js

- Nicht existente Readings werden jetzt abgefangen und mit "n/a" gesetzt. Damit ist es leichter, unerwünschte Ringe im SVG zu löschen.
- Batteriering färbt sich je nach Status ein. Zum Beispiel bei solarLoad in gelb.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Wzut am 17 November 2024, 13:06:53
Zitat von: schwatter am 27 Oktober 2024, 12:45:07      readingsSingleUpdate($hash, $v, join(" ",@a), 1);
vs.
      readingsBeginUpdate($hash);
      readingsBulkUpdate($hash, $v, join(" ",@a), 1);
      readingsEndUpdate($hash, 0);  # Verhindert das Aktualisieren des STATE


Dadurch kann ich jetzt das aktualisieren des STATE unterdrücken.
schaut man sich den Quellcode von readingsSingleUpdate und readingsBulkUpdate in fhem.pl an, dann stellt man fest das ein readingsSingleUpdate in Wahrheit auch dort der Dreizeiler aus  readingsBeginUpdate , readingsBulkUpdate und readingsEndUpdate ist. Was du meinst mit "aktualisieren des STATE unterdrücken" ist das verhindern eines Events. Das wird durch den vierten Parameter $dotrigger bei readingsSingleUpdate geregelt.
Der wird eine Zeile später als zweiter Parameter direkt an readingsEndUpdate weitergegeben.
D.h. eigenlich müsste es reichen bei Rudis Original nur $dotrigger (1 -> 0) zu ändern :
readingsSingleUpdate($hash, $v, join(" ",@a), 0);
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 17 November 2024, 14:11:19
Vielen Dank, das funktioniert! Ändere ich.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 17 November 2024, 14:59:46
@ch.eick

Habe gerade erst gesehen, das du per Edit in deinem Post nochmal geantwortet hast.
subType muss in Global gesetzt werden, danach kann ein eigener subType in Devices gesetzt werden.

attr global userattr subType
Vorsicht, falls da schon etwas steht, nur ergänzen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 12 Januar 2025, 09:21:31
Morgen,

Update im ersten Post:

- width und height beziehen sich jetzt nur auf das SVG. Vorher hat es global gegriffen. Einige Skins konnten das nicht verkraften.
- Jetzt mit Mobile Ansicht. Diese greift bis 1200px.
- Bis dahin werden alle Ringe und Linien mit der Klasse class="animated-point" und class="ring" ausgeblendet.
- Im Fuß des SVG ein Skript hinzugefügt, das wenn die Ringe und Linien ausgeblendet werden, auch die Viewbox verkleinert wird.



Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 12 Januar 2025, 11:56:59
Da fällt mir ein, der andies hatte ja auch das eChart gebaut.
Das sieht ganz schick nebeneinander aus. Sowas wie ein Energydashboard.
Die Namen habe ich in den 2 devices per alias entfernt.

attr powerGrid alias <span></span>
Da dann der Link zum Deviceoverview weg ist, muss z.B per list TYPE=dummyNew gesucht werden.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 17 Januar 2025, 20:16:48
Nabend,

Update im ersten Post:

- eigene Namen für die 5 Ringe um das Haus setzbar (set powerGrid cCircle1Name_s Airdryer).
- cCircle1Name_s bis cCircle5Name_s. Beginnend oben und dann im Uhrzeiger.
- cCircle1Power_v bis cCircle5Power_v. Beginnend oben und dann im Uhrzeiger.
- Sind keine Namen gesetzt, wird n/a ausgegeben. Mal sehen, vielleicht blende ich im nächsten Step die Ringe aus.
- Um das Update anzuwenden, müssen die Raw vom Dummy und das DOIF neu gesetzt werden. Sowie svg_update.js erneut nach
codemirror kopieren.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 18 Januar 2025, 13:33:01
Hallo,
ich habe das soweit auch in mein fhem eingebaut, allerdigs muss ich irgndwo einen Fehler gemacht haben,
wenn ich das Device Powergrid_DOIF öffne erhalte ich folgende Fehlermeldung:
fhem?detail=Powergrid_DOIF line 815:
TypeError: svg is null

Hier mein DOIF:
Internals:
   DEF        ## Grid + House
([SolisPVA:"house_load_power"])
        ( set powerGrid grid_v {(ReadingsNum("SolisPVA","house_load_power",0))} )
        ( set powerGrid grid_in_v {(ReadingsNum("SolisPVA","meter_power_in_modified",0))} )
        ( set powerGrid grid_out_v {(ReadingsNum("SolisPVA","meter_power_out_modified",0))} )
        ( set powerGrid house_v {(ReadingsVal("SolisPVA","solar_to_house_power_modified",0))} )
        ( set powerGrid lowcarbon_v {(ReadingsNum("electricitymap","fossilFreePercentage",0))} )

## Computer
DOELSEIF  ([buero_shelly_computer:"power"])
        ( set powerGrid cCircle1Power_v {(ReadingsNum("buero_shelly_computer","power",0))} )

## Dishwasher
DOELSEIF  ([ku_shellypmmini_sm:"power"])
        ( set powerGrid cCircle4Power_v {(ReadingsNum("ku_shellypmmini_sm","power",0))} )

## Boiler
DOELSEIF  ([ku_shellypmmini_boiler:"power"])
        ( set powerGrid cCircle3Power_v {(ReadingsNum("ku_shellypmmini_boiler","power",0))} )

## Warmwasserboiler
DOELSEIF  ([keller_shelly_wwboiler:"^power:.*$"])
        ( set powerGrid cCircle5Power_v {(ReadingsNum("keller_shelly_wwboiler","power",0))} )

## Solar
DOELSEIF   ([aktuellerErtragPVA:"state"] )
        ( set powerGrid solar_v {(ReadingsNum("aktuellerErtragPVA","state",0))} )

## Washer
DOELSEIF  ([hw_shellypmmini_wm:"power"])
        ( set powerGrid cCircle2Power_v {(ReadingsNum("hw_shellypmmini_wm","power",0))} )

   FUUID      678ad3f5-f33f-e471-1cbb-3610b9abe3d3dd10
   MODEL      FHEM
   NAME       Powergrid_DOIF
   NOTIFYDEV  ku_shellypmmini_sm,keller_shelly_wwboiler,global,hw_shellypmmini_wm,buero_shelly_computer,SolisPVA,ku_shellypmmini_boiler,aktuellerErtragPVA
   NR         337
   NTFY_ORDER 50-Powergrid_DOIF
   STATE      cmd_1
   TYPE       DOIF
   VERSION    29460 2024-12-29 20:25:48
   eventCount 4413
   READINGS:
     2025-01-18 13:30:11   Device          aktuellerErtragPVA
     2025-01-18 13:30:11   cmd             1.5
     2025-01-18 13:30:11   cmd_event       SolisPVA
     2025-01-18 13:30:11   cmd_nr          1
     2025-01-18 13:30:11   cmd_seqnr       5
     2025-01-18 13:30:11   e_SolisPVA_events meter_voltage: 2319,dc_voltage_1: 2024,meter_power_in_modified: 212,total_dc_input_power_2: 238,meter_ac_voltage_a: 2319,dc_bus_voltage: 3917,meter_current: 180,system_second: 1,meter_total_apparent_power_2: 849,apparent_power_2: 170,meter_reactive_power_a_2: 105,meter_total_active_power_2: 65278,system_minute: 32,phase_a_voltage: 2324,meter_apparent_power_a_2: 471,system_epoch: 1737203521,meter_active_power_2: 65323,meter_power_modified: 212,meter_active_power_a_2: 65175,active_power_2: 170,house_load_power: 413,total_load_power_modified: 413,grid_frequency: 4997,meter_power_factor: 65239,solar_to_house_power_modified: 238,total_dc_input_power: 238,apparent_power: 170
     2025-01-18 13:30:11   e_aktuellerErtragPVA_events 266.7
     2025-01-18 13:30:10   e_buero_shelly_computer_events power: 52.45
     2025-01-18 13:30:00   e_hw_shellypmmini_wm_events params_pm1_0_ret_aenergy_minute_ts: 1737203400,params_pm1_0_aenergy_minute_ts: 1737203400,params_ts: 1737203400.00
     2025-01-18 13:29:24   e_keller_shelly_wwboiler_events uptime: 13675,voltage: 235.6,current: 0.138,power: 16.7,energy: 672448.38,energy_purchased: 672448.38,16.7
     2025-01-18 13:30:00   e_ku_shellypmmini_boiler_events params_pm1_0_ret_aenergy_minute_ts: 1737203400,params_ts: 1737203400.00,params_pm1_0_aenergy_minute_ts: 1737203400
     2025-01-18 13:30:00   e_ku_shellypmmini_sm_events params_pm1_0_aenergy_minute_ts: 1737203400,params_ts: 1737203400.00,params_pm1_0_ret_aenergy_minute_ts: 1737203400
     2025-01-17 23:06:51   mode            enabled
     2025-01-18 13:30:11   state           cmd_1
   Regex:
     accu:
     bar:
     barAvg:
     collect:
     cond:
       SolisPVA:
         0:
           &STATE     ^SolisPVA$
         1:
         2:
         3:
         4:
         5:
         6:
       aktuellerErtragPVA:
         0:
         1:
         2:
         3:
         4:
         5:
           &STATE     ^aktuellerErtragPVA$
         6:
       buero_shelly_computer:
         0:
         1:
           &STATE     ^buero_shelly_computer$
         2:
         3:
         4:
         5:
         6:
       hw_shellypmmini_wm:
         0:
         1:
         2:
         3:
         4:
         5:
         6:
           &STATE     ^hw_shellypmmini_wm$
       keller_shelly_wwboiler:
         0:
         1:
         2:
         3:
         4:
           &STATE     ^keller_shelly_wwboiler$
         5:
         6:
       ku_shellypmmini_boiler:
         0:
         1:
         2:
         3:
           &STATE     ^ku_shellypmmini_boiler$
         4:
         5:
         6:
       ku_shellypmmini_sm:
         0:
         1:
         2:
           &STATE     ^ku_shellypmmini_sm$
         3:
         4:
         5:
         6:
   attr:
     cmdState:
     wait:
     waitdel:
   condition:
     0          ::EventDoIf('SolisPVA',$hash,'house_load_power',1)
     1          ::EventDoIf('buero_shelly_computer',$hash,'power',1)
     2          ::EventDoIf('ku_shellypmmini_sm',$hash,'power',1)
     3          ::EventDoIf('ku_shellypmmini_boiler',$hash,'power',1)
     4          ::EventDoIf('keller_shelly_wwboiler',$hash,'^power:.*$',1)
     5          ::EventDoIf('aktuellerErtragPVA',$hash,'state',1)
     6          ::EventDoIf('hw_shellypmmini_wm',$hash,'power',1)
   do:
     0:
       0           set powerGrid grid_v {(ReadingsNum("SolisPVA","house_load_power",0))}
       1           set powerGrid grid_in_v {(ReadingsNum("SolisPVA","meter_power_in_modified",0))}
       2           set powerGrid grid_out_v {(ReadingsNum("SolisPVA","meter_power_out_modified",0))}
       3           set powerGrid house_v {(ReadingsVal("SolisPVA","solar_to_house_power_modified",0))}
       4           set powerGrid lowcarbon_v {(ReadingsNum("electricitymap","fossilFreePercentage",0))}
     1:
       0           set powerGrid cCircle1Power_v {(ReadingsNum("buero_shelly_computer","power",0))}
     2:
       0           set powerGrid cCircle4Power_v {(ReadingsNum("ku_shellypmmini_sm","power",0))}
     3:
       0           set powerGrid cCircle3Power_v {(ReadingsNum("ku_shellypmmini_boiler","power",0))}
     4:
       0           set powerGrid cCircle5Power_v {(ReadingsNum("keller_shelly_wwboiler","power",0))}
     5:
       0           set powerGrid solar_v {(ReadingsNum("aktuellerErtragPVA","state",0))}
     6:
       0           set powerGrid cCircle2Power_v {(ReadingsNum("hw_shellypmmini_wm","power",0))}
     7:
   helper:
     NOTIFYDEV  ku_shellypmmini_sm,keller_shelly_wwboiler,global,hw_shellypmmini_wm,buero_shelly_computer,SolisPVA,ku_shellypmmini_boiler,aktuellerErtragPVA
     event      266.7
     globalinit 1
     last_timer 0
     sleeptimer -1
     timerdev   SolisPVA
     timerevent house_load_power: 413
     triggerDev aktuellerErtragPVA
     timerevents:
       meter_voltage: 2319
       dc_voltage_1: 2024
       meter_power_in_modified: 212
       total_dc_input_power_2: 238
       meter_ac_voltage_a: 2319
       dc_bus_voltage: 3917
       meter_current: 180
       system_second: 1
       meter_total_apparent_power_2: 849
       apparent_power_2: 170
       meter_reactive_power_a_2: 105
       meter_total_active_power_2: 65278
       system_minute: 32
       phase_a_voltage: 2324
       meter_apparent_power_a_2: 471
       system_epoch: 1737203521
       meter_active_power_2: 65323
       meter_power_modified: 212
       meter_active_power_a_2: 65175
       active_power_2: 170
       house_load_power: 413
       total_load_power_modified: 413
       grid_frequency: 4997
       meter_power_factor: 65239
       solar_to_house_power_modified: 238
       total_dc_input_power: 238
       apparent_power: 170
     timereventsState:
       meter_voltage: 2319
       dc_voltage_1: 2024
       meter_power_in_modified: 212
       total_dc_input_power_2: 238
       meter_ac_voltage_a: 2319
       dc_bus_voltage: 3917
       meter_current: 180
       system_second: 1
       meter_total_apparent_power_2: 849
       apparent_power_2: 170
       meter_reactive_power_a_2: 105
       meter_total_active_power_2: 65278
       system_minute: 32
       phase_a_voltage: 2324
       meter_apparent_power_a_2: 471
       system_epoch: 1737203521
       meter_active_power_2: 65323
       meter_power_modified: 212
       meter_active_power_a_2: 65175
       active_power_2: 170
       house_load_power: 413
       total_load_power_modified: 413
       grid_frequency: 4997
       meter_power_factor: 65239
       solar_to_house_power_modified: 238
       total_dc_input_power: 238
       apparent_power: 170
     triggerEvents:
       266.7
     triggerEventsState:
       state: 266.7
   internals:
   perlblock:
   readings:
   trigger:
     all         SolisPVA buero_shelly_computer ku_shellypmmini_sm ku_shellypmmini_boiler keller_shelly_wwboiler aktuellerErtragPVA hw_shellypmmini_wm
   uiState:
   uiTable:
Attributes:
   DbLogExclude .*
   room       Energy

Alles andere habe ich unverändert aus dem ersten Post genommen.
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 18 Januar 2025, 21:13:27
Nabend,

falsch gemacht hast du nichts. Das Problem ist, das DOIF an der Stelle und ein paar anderen einen Wert erwartet.
Den Fehler hast du nicht komplett kopiert, denke ich. Diesen bekomme ich.

fhem?detail=Powergrid_DOIF line 1636:
Uncaught TypeError: Cannot read properties of null (reading 'setAttribute')

Das ist der Teil im SVG

function adjustViewBox() {
                    const svg = document.querySelector(&apos;#powerGrid svg&apos;);
                    if (window.innerWidth &lt; 1200) {
                      svg.setAttribute(&apos;viewBox&apos;, &apos;0 0 500 500&apos;);
                    } else {
                      svg.setAttribute(&apos;viewBox&apos;, &apos;0 0 650 500&apos;);
                    }
                  }

Ich werde Damian fragen, ob er das abfangen möchte. Problem, vorher hat noch keiner so eine lange
SVG-Orgie im Stateformat gemacht.

Ansonsten, sollte es trotz Fehler normal funktionieren. Tut es bei dir auch?

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 18 Januar 2025, 22:03:46
Vielen Dank für die schnelle Antwort.
Ich bin mir sicher alles aus der Fehlermeldung kopiert zu haben.
Das SVG zeigt keine Daten an, obwohl die Readings befüllt werden.
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 19 Januar 2025, 08:55:55
Morgen,

ich habe jetzt versucht es nachzustellen.

- dummyNew und svg_update.js gelöscht
- gespeichert + Browserrefresh (STRG + F5)
- Fhem-Neustart
- Die Dateien svg_update.js + powerFlow_dummyNew_raw.txt aus dem ersten Post heruntergeladen
- svg_update.js nach /opt/fhem/www/codemirror kopiert und Rechte/Eigentümer : fhem/Gruppe:dialout
- pro FHEmWEB Device muss das attr JavaScripts mit dem Inhalt gesetzt sein -->codemirror/svg_update.js
- SVG mit dummyNew per raw wieder angelegt über den + Button oben links.
- Speichern nicht vergessen
- Noch ein Fhem-Neustart, damit Fhem weiß, das ein Script in /opt/fhem/www/codemirror liegt.
- Nochmal Browserrefresh (STRG + F5)

Bis jetzt kann ich den Fehler nicht nachstellen. Wichtig ist, das alles da ist wo es hingehört.
Wenn etwas nicht funktioniert, dann einen Fhem-Neustart. Und nachdem Fhem wieder da ist, nochmal STRG + F5
für den Browserrefresh.

Funktioniert es nicht, stimmmt etwas mit dem Script nicht. Es wird nicht gefunden oder geladen. Oder es ist defekt.
Auch darfst du den dummy oder die Readings nicht selber umbenennen. Da alles im Script auf die Namensgebung ausgelegt ist.

Hier ist noch die alte Version, bei der die Namen der 5 Ringe um House nicht per dummy gesetzt werden konnten.
https://github.com/schwatter/PowerFlow
Damit könnte der Fehler eingegrenzt werden. Mein Browser bytheway is Chrome. Sonst habe ich keine Besonderheiten.

Wenn bis heut Abend noch Interesse daran besteht, dann könnte ich per Teamviewer versuchen zu helfen. Bin ca. 18Uhr wieder da.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 19 Januar 2025, 10:11:41
Hallo schwatter,

ich habe die Vorgehensweise auch nochmal nachvollzogen, komme aber auf denselben Fehler.
Ich nutze normalerweise Firefox, bei Edge sieht die Meldung exakt so aus wie in deinem Post #34
fhem?detail=Powergrid_DOIF line 807:
Uncaught TypeError: Cannot read properties of null (reading 'setAttribute')

Da ich nicht weiter komme würde ich das Angebot per Teamviewer gerne annehmen.

Grüße ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 19 Januar 2025, 18:09:01
Hast PM

Gruß
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 19 Januar 2025, 19:25:11
Hallo schwatter,

deine Vermutung das es am csrfToken liegt war richtig. Nachdem ich darauf umgestellt habe funzt alles.

Nochmals vielen Dank und viele Grüße
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 19 Januar 2025, 21:03:09
Nabend,

Update der svg_update.js im ersten Post.

- fetchReadings funktioniert jetzt mit und ohne CSRF-Token
- motionAnim.setAttribute wurde von ('dur', '0s') zu ('begin', 'indefinite') geändert. Da wurde gemeckert


Da DOIF den Fehler setAttribute ausspuckt, gehe ich jetzt von einem Fehler meinerseits aus.
Ich suche weiter. Die Funktion, Werte in den dummy zu schreiben, behindert es nicht. Kann also
vom User erstmal missachtet werden.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 23 Januar 2025, 20:02:33
Nabend,

Update im ersten Post. Dazu bitte svg_update.js und powerFlow_dummyNew_raw.txt laden und Beide erneuern.

- die Customringe können jetzt ausgeblendet werden. Dazu den Namen n/a vergeben.
- Dadurch ergibt sich eine neue Reihenfolge. Über Haus C1, unter Haus C2, oben rechts C3, rechts C4 und unten rechts C5.
- Tooltips wurde deaktiviert. Bedeutet, das wenn die Maus auf dem StateformatSvg verweilt, kein Codegeschnetzeltes erscheint.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 25 Januar 2025, 14:07:46
Tag,

Update im ersten Post. Dazu bitte svg_update.js und powerFlow_dummyNew_raw.txt laden und Beide erneuern.
STRG + F5 nicht vergessen!

- Icons per set setzbar für FossilFree, Solar, House + 5 Customringe

Entweder per Pfad zu den Fhem SVG's

/fhem/www/images/fhemSVG/solar_icon.svg
/fhem/www/images/openautomation/scene_clothes_dryer.svg

oder direkt aus dem Internet. Zum Beispiel von hier: https://pictogrammers.com/library/mdi/
Dazu Icon auswählen. Dann oben rechts mit der Maus auf "Download SVG" aber nicht downloaden.
Rechte Maustaste und Adresse des Links kopieren. Das sieht dann so kryptisch aus

data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%203L2%2012H5V20H19V12H22L12%203M11.5%2018V14H9L12.5%207V11H15L11.5%2018Z%22%20%2F%3E%3C%2Fsvg%3E


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 07 Februar 2025, 19:59:52
Nabend,

Update im ersten Post. Dazu bitte svg_update.js und powerFlow_dummyNew_raw.txt laden und Beide erneuern.
STRG + F5 nicht vergessen!

- Jetzt 9 Customringe.
- Neuer Style für die Linien.
- Diverses Caching im JS hinzugefügt.
- JS-Ausführung nur noch, wenn der passende Title auf der Seite vorhanden ist. Siehe Browserkonsole.
- Der Title Powerflow oben links ist klickbar und führt zum Deviceoverview.
- Deshalb wird jetzt der Devicename mit attr alias "<span></span>" ausgebelndet.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 01 März 2025, 21:15:03
Nabend,

Update im ersten Post. Dazu bitte svg_update.js, powerGrid_style.css und powerFlow_dummyNew_raw.txt laden und erneuern.
STRG + F5 nicht vergessen!
Bei Fully schalte ich immer "Clear Cache After Each Page" an. Dann ein paar mal hin und her. Dann wieder ausschalten.
Dem fehlt ein einfacher Clearcache Button?!

- die Linien sind jetzt auf CSS umgestellt.
- Das neue Stylefile muss nach /opt/fhem/www/svggrid kopiert werden.
- Script nochmal mit Caching überarbeitet.

Ich kämpfe auf meinem FireHD 10 mit Fully Kioskbrowser. Allgemein funktioniert es ganz gut. Jetzt weniger zucken der Linien
als vorher. Problem ist wahrscheinlich die ganze Kombi...
- FireHD10(FiretoolboxMod)
- FullyKioskBrowser (der hat wohl echt ein Performanceproblem)
- Webview veraltet. Den konnte ich auf zumindest 108 updaten. Danach ist Sense.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 03 März 2025, 14:19:41
Kann ich die Größe beinflussen? Ist doch arg klein. Nachder letzten Änderung sehe ich auch die
Auswahlboxen nicht mehr
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 03 März 2025, 17:18:10
Habe bei mir geschaut. Auch mit verschiedenen Skins alles ok.
Ich glaube ich habe vergessen zu erwähnen, das "shutdown restart" erforderlich ist.
Um Fhem das CSS File bekannt zu machen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 03 März 2025, 19:22:59
Komisch, ich bekomme das nicht hin.
Das CSS habe ich bekannt gemacht, shutdown restart und Ctrl-F5.
Es ändert sich nichts.
fhem_Energy2.png
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 03 März 2025, 19:35:14
Getestet habe ich mit Chrome,Firefox und Fully.
Mh, ich lade nachher nochmal die Files neu hoch.
Vielleicht die Ordner nicht beachtet? Der vom CSS-File und vom JavaScript sind unterschiedlich.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 03 März 2025, 22:07:57
Hier nochmal alles. Ich habe im SVG den Pfad für das StyleCSS geändert auf den Pfad
wo auch das Javascript liegt. Dachte da sind nur Javascript drinne. Aber von Haus aus liegen da
auch ein paar CSS-Files. So ist es einfacher zu pflegen.

- Javascript und Style-CSS nun zusammen im Pfad /opt/fhem/www/codemirror
- Ladeanimation geändert. Von drehender Kreis auf pulsierend. Laden von außen nach innnen. Entladen von innen nach außen.

Ob svg_update.js und svg_update.css richtig geladen wurde, kannst du dann per Direktlink kontrollieren:
http://192.168.178.79:8084/fhem/www/codemirror/svg_update.css
http://192.168.178.79:8084/fhem/www/codemirror/svg_update.js

Hoffentlich funktioniert es jetzt. Welchen Browser nutzt du nochmal?

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 09:24:51
Ich bin jetzt verwirrt, svg_update.css ersetzt jetzt powerGrid_style.css?

Als Browser benutze ich Firefox auf dem Laptop und Chrome auf dem Tablet. Verhalten ist identisch.
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 09:53:04
Ich habe jetzt die Datei svg_update.css und svg_update.js in das Verzeichnis codemirror kopiert, und
das CSS in fhem bekannt gemacht.
Danach habe ich fhem neu gestartet und auf der Seite mit dem dummyNew ein Refresh gemacht.
Leider ist es immer noch klein.
ABER: Wenn ich auf den Raum klicke wird das SVG ganz kurz groß und sofort wieder klein.
Vielleicht hilft das

Gruß ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 04 März 2025, 10:19:23
Das hatte ich auch schonmal. Ich tippe auf fehlendes CSS.
Ich habe ein paar Selectoren entfernt. Du könntest versuchen von meinem alten SVG per copy and paste herauszufinden welche(r) es ist.
Der Kram versteckt sich im älteren Raw im Head vom Stateformat.
Ansonsten um 20Uhr hab ich wahrscheinlich Zeit für Teamviewer.

Edit:
Direkt beeinflussen kannst es hiermit. Das ist das Original.
Wenn du anstatt Prozent z.B width: 1700px;

* SVG-Stile überschreiben */
#powerGrid svg {
    background-color: black;
    width: 90% !important;
    height: auto;
}

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 12:22:07
Ja, das funktioniert! Für meine Zwecke habe ich 1300px eingetragen.

Vielen Dank für deine Mühe!

Gruß ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 12:25:30
Jetzt müsste ich nur noch wissen wie ich an die Auswahlbox herankomme,
um weitere Daten anzeigen zu können :-)

Gruß
ergerd

edit: Noch eine Idee: Ich habe über dem Text "Solar" noch ein weiteres Datenfeld eingebaut,
in dem ich die generierte Tagesleistung anzeige. Wäre vielleicht auch für andere interessant.
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 04 März 2025, 12:31:17
Schön das es jetzt funktioniert. Was doof ist, normal sollte  bei width: 90% !important; das !important fhem CSS überschreiben. Warum funktioniert das jetzt nicht mehr ? >:(
Was meinst du mit Auswahlbox? DeviceOverview?

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 19:29:06
Ich bin nicht sicher wie die Auswahlbox hieß, aber man muss doch
irgendwo den Userdefined Ringen einen Text verpassen können

Gruß ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 04 März 2025, 20:19:33
Der Link versteckt sich hinter dem Titel "Power Flow".
Siehe Bilder.

edit:
teste bitte nochmal das CSS-File im Anhang. Ob damit die Breite wieder automatisch gesetzt wird.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 22:15:52
Auf den Link bin ich schon per Zufall gestossen :-)

Das neue CSS funktioniert leider nicht.

Gruß
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 04 März 2025, 23:29:29
Noch eine Frage zu electricitymap: Ich bekomme seit einiger Zeit folgende Meldung:
Please provide a valid authentication header. See https://portal.electricitymaps.com/docs/getting-started#authorization for details
Einen Token habe ich mir besorgt aber ich habe keine Ahnung wie man den einbaut.
Kannst du da weiterhelfen?

Gruß
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 05 März 2025, 18:40:04
Nabend,

ich habe mir gerade einen Token erstellt. Teste mal:

deletereading electricitymap message
deletereading electricitymap error

defmod electricitymap HTTPMOD none 60
attr electricitymap event-on-change-reading .*
attr electricitymap extractAllJSON 1
attr electricitymap get1Header1 accept: */*
attr electricitymap get1Header2 auth-token: XpiDeinGeheimerTokenAut
attr electricitymap get1Name carbon-intensity
attr electricitymap get1Poll 1
attr electricitymap get1URL https://api.electricitymap.org/v3/carbon-intensity/latest?lat=51.817132&lon=9.764435
attr electricitymap get2Header1 accept: */*
attr electricitymap get2Header2 auth-token: XpiDeinGeheimerTokenAut
attr electricitymap get2Name power-breakdown
attr electricitymap get2Poll 1
attr electricitymap get2URL https://api.electricitymap.org/v3/power-breakdown/latest?lat=51.817132&lon=9.764435

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 05 März 2025, 21:21:17
Das funktioniert, vielen Dank!

Gruß ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 15 März 2025, 22:18:36
Nabend,

Update im ersten Post. Bitte erneuert alle 3 (dummy,JS und CSS). Weiß nicht mehr so genau, ob
ich bei allen etwas geändert habe  ;D  my $name = 'Alzheimer';

STRG + F5 für Cache löschen!

- CSS SVG Größe Desktop auf 85vw umgestellt. Daher jetzt mit vielen Skins kompatibel.
- CSS SVG Größe Mibile auf 95vw umgestellt. Daher jetzt mit vielen Skins kompatibel.
- CSS Animation für Hausring erstellt. Bei betreten des Raums sowie Werteänderung.
- Devicename wird per CSS ausgeblendet. Daher entfällt das attr alias <span></span>.

@ergerd
Ich konnte dein Problem nachstellen. Lag daran, das ich bei width: 90% !important; hatte.
Das muss aber width: 85vw !important; bzw Viewport == sichtbare Teil des Browserfensters.
Wahrscheinlich musst du die 85vw minimal anpassen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 18 März 2025, 09:12:35
Hallo,
Leider ist bei mir der Powerflow seit einigen Versionen nicht mehr zu gebrauchen.
Am Anfang ging er noch, aber jetzt sieht er im f18 style so aus:
Bildschirmfoto 2025-03-18 um 09.01.05.png

Im flex style sogar so:
Bildschirmfoto 2025-03-18 um 09.01.24.png

Bei f18 sieht man kurz den ganzen Powerflow, dann sieht es aus wie oben.

Schade, habe aber auch keine Ahnung wie man das ändern kann.

Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 18 März 2025, 09:52:46
Hallo carlos,
ich benutze den Firefox und habe das gleiche Problem.
Workaround für mich:
Ich ändere kurz den Zoom auf 110% und wieder zurück auf 100%
Das geht gut mit gedrückter Ctrl-Taste und dem Mausrad.

Grüße
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 18 März 2025, 12:00:15
Tag,

ja einen guten Kompromiss zwischen Firefox und Chrome zu finden ist wenn man nach Performance sucht nicht so einfach. Auch die Skins haben ihre Eigenarten.
Grundsätzlich möchte ich bei mehr CSS bleiben damit es performanter ist.
Ich sehe auch, seit dem umstellen fingen die Probleme bei euch an.
Gibt bestimmt eine Lösung.

@carlos
Hast du denn schon feste Werte für Größe verwendet? Die helfen eigentlich immer.
Also anstatt width mit % oder vw dann 1200px.
Das erste Bild bei F18, so sieht es bei mir aus wenn ich etwas ändere
aber danach kein STRG + F5 ausführe oder ein File nicht
gefunden wird.

Edit:
Auch hatte ich die Namensgebung der Files umgestellt und den Pfad auf /opt/fhem/www/codemirror geändert für alles.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 18 März 2025, 22:55:03
Nabend,

damit der Powerflow in Flexstyle funktioniert, muss der Skin erstmal angepasst werden.
Damals mochte ich den Skin, habe ihn dann aber gegen f18 getauscht. Die Stylevorgaben waren
mir zu strikt. Die SVG's vom DOIF waren immer zu klein....

So, habe Flexstyle etwas frisiert für Desktop und Mobile. Damit schauen einige Elemente
wieder viel besser aus und nicht mehr so klein.


1. CSS-File aus dem Anhang ersetzen. Speichert das Alte ab!
2. Im Skin --> Sytle settings -->Mehrspalten Layout-->single
3. Auf Desktop STRG + F5 und Handy auf Browsercache löschen.
4. Gegebenfalls in der svg_update.css die Größen anpassen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 19 März 2025, 11:10:46
Ich musste Plotcontrol hinzufügen. Die Buttons für das SVG (Plus,Minus,Zoom) waren viel zu groß.
Bzw die class .SVGlabel svg. Update in dem Post drüber.
Bin bei mir nochmal alle Räume durchgegangen und finde in meiner Umgebung jetzt keine Ausreißer mehr.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 19 März 2025, 17:35:07
Und noch ein Update zu Flexstyle 2 Posts drüber.
.roomoverview svg musste auch noch dazu. Im Deviceoverview zu SolarForecast gingen die SVG's durch die Decke.
edit:
Und nochmal erweitert mit td.containsTable svg.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Icinger am 19 März 2025, 19:15:04
Ein einzelnes Icon habe ich noch im Flex, welches viel zu groß ist.
Schaut aber nur im DOIF so aus, im Device selber ist das Icon "normal" groß.

lg, Stefan
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 19 März 2025, 20:37:33
Ich denke ich war zu weit in den Unterklassen. Ich habe es jetzt auf

.odd svg, .even svg {
    width: 30px;
    height: 30px;
}

geändert.


edit...
moment

edit2:
so nochmal. Hatte wieder zuviel gelöscht...
.odd svg, .even svg, td.wrapped svg, .col2 svg, .col3 svg, .SVGlabel svg, .roomoverview svg, td.containsTable svg {
    width: 30px;
    height: 30px;
}

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 22 März 2025, 10:49:04
Hallo,
Leider funktioniert es bei mir immer noch nicht.
Ich habe svg_update.css und svg_update.js im codemirror verzeichnis auch im WEB device mit flex eingestellt.
Dein flexstyle.css liegt in /opt/fhem/www/pgm2 und ist vom update ausgeschlossen.

Ergebnis ist folgendes:
Gehe ich in den Raum wird das Device kurz richtig angezeigt, dann sieht es so aus:

Bildschirmfoto 2025-03-22 um 10.36.42.png

Das gleiche im F18 style.


Gruß

Hubert

Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 22 März 2025, 10:55:14
Hallo Carlos,
schon den Workaround aus #64 probiert?
Gruß ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: carlos am 22 März 2025, 12:54:02
Ich nutze Chrome und der Workaround hilft bei mir nicht.

Gruß

Hubert
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 22 März 2025, 16:07:50
Gibt bitte die "Raw definition" von deinen FHEMWEB-Devices sowie vom powerGrid-dummy.

Edit:
Hast du vielleicht ein Adblocker der etwas blockiert?

Edit:
Lösche ich im dummy die Zeile zum CSS-File, dann sieht es bei mir auch ganz klein aus.
Ich tippe auf das nicht gefundenes CSS-File.
<head>
    <title>powerGrid</title>
    <link rel="stylesheet" type="text/css" href="/fhem/www/codemirror/svg_update.css">
</head>
Aber deine "Raw definition" würde ich mir gerne anschauen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Torxgewinde am 23 März 2025, 11:09:11
@schwatter: Ich glaube im Kern haben wir ein ähnliches Problem gehabt. Vielleicht ist es technisch auch für dich interessant:

Wenn man sich im DOM einfach DIVs mit passenden informIds anlegt und denen eine JS-Funktion "setValueFn(value) ..." zuweist, dann versorgt FHEM einen mit den jeweiligen Daten. Wenn man seinem eigenem SVG unter dem Knoten mit der "informId" auch solch eine JS-Funktion zuweist, wird das SVG nicht im DOM ersetzt, sondern bei Updates die setValueFn()-Funktion getriggert.

Mein SVG ist viel einfacher als deins hier, aber im Kern kann man sich die Kommunikation da an- bzw. ggf. gerne abgucken: https://forum.fhem.de/index.php?topic=141113.msg1337604#msg1337604
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 23 März 2025, 11:36:36
Sehr interessant, danke. Ich hatte mir schon einige Konzepte angeschaut. Über Websocket,Jsonlist2,telnet inform on
und bin dann bei JS extern gelandet. Da ich mit meinem laienhaften Verständnis keinen Weg gefunden hatte, eine Animation
dauerhaft zu starten, ohne das sie von Fhem unterbrochen wird. Problem war immer das readingsSingleUpdate zum Refresh
des STATE führte und die Animationen neu startete. Durch das abschalten kommen aber auch keine Events mehr, deshalb das externe JS.

Bist du sicher, das das mit deinem gefundenen Weg funktioniert?
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Torxgewinde am 23 März 2025, 12:59:00
Zitat von: schwatter am 23 März 2025, 11:36:36Bist du sicher, das das mit deinem gefundenen Weg funktioniert?

Kurz:
Ich denke schon dass das klappt.

Lang:
Bei dem simplem Bargraphen von mir läuft eine CSS-Animation und im Debugger bekommt man es ja angezeigt, wenn im DOM HTML-Elemente hinzukommen, oder geändert werden. Das blinkt dann einmal kurz auf. Auch passt es gut zu den restlichen Infos die ich her so aus dem Forum und dem Quelltext zusammengesucht habe. Man kommt an die Infos kommt, die zu dem jeweiligem Raum oder sogar dem eigenem Device gehören.

Solange in der JS-Konsole solche Meldungen durchlaufen die deine Werte sind, kann man die mit der Methode (1. div machen, 2. informId setzen, 3. js Funktion dranpacken) anzapfen und dann auch in seinem Javascript nutzen um die Darstellung zu verändern.

Alleine damit, dass das Element mit der passenden informId die JS-Funktion setValueFn() hat, weiß FHEM, dass ein besserer Weg geschaffen wurde, als den ganzen DOM-Knoten zu tauschen. Der relevante Code aus /opt/fhem/www/pgm2/fhemweb.js ist:
// d: array
  // d[0]: informid
  // d[1]: if the informid Widget has setValueFn, arg for this
  // d[2]: else replace the html with this
  function
  setValue(d) // is Callable from eval below
  {
    $("[informId='"+d[0]+"']").each(function(){
      if(this.setValueFn) {     // change the select/etc value
        this.setValueFn(d[1].replace(/\n/g, '\u2424'));

      } else {
        if(d[2].match(/\n/) && !d[2].match(/<.*>/)) // format multiline
          d[2] = '<html><pre>'+d[2]+'</pre></html>';
...
Und speziell davon if(this.setValueFn).

Bei meinem Bargraph läuft die Animation schön ungestört einfach weiter, egal wie oft ich Werte neu setze durch anklicken der WebCmds.

Ich denke für deine Anwendung heißt das erstmal garnichts, aber ich finde die Methode nun ganz praktisch zu kennen und du dann vielleicht auch. Eingangs im allerersten Post Stand ja deine Frage ob man das ggf. auch anders machen kann.
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 23 März 2025, 14:56:26
So, ich habe versucht es zu adaptieren. Funktioniert gut.

1.
defmod ring_grid_test dummy
attr ring_grid_test devStateIcon {\
    # Lese die Werte aus den Readings\
    my $val1 = ReadingsVal($name, 'ring1', 0);;\
    my $val2 = ReadingsVal($name, 'ring2', 0);;\
    my $val3 = ReadingsVal($name, 'ring3', 0);;\
    my $val4 = ReadingsVal($name, 'ring4', 0);;\
\
    # Hole das SVG als Template\
    my $svg = FW_makeImage('ring_grid_test');;\
\
    # Setze den Wert und aktiviere Animationen je nach Wert\
    $svg =~ s/(<tspan class="informId_ringSVG:ring2">)(.*?)(<\/tspan>)/$1$val2$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:ring4">)(.*?)(<\/tspan>)/$1$val4$3/;;\
\
    # Füge Animationen hinzu, wenn die Werte größer als 0 sind\
    $svg =~ s/(<circle[^>]+id="circle1"[^>]+class="motion-disabled")/$1 motion-enabled/ if $val2 > 0;;\
    $svg =~ s/(<circle[^>]+id="circle2"[^>]+class="motion-disabled")/$1 motion-enabled-line4/ if $val4 > 0;;\
\
    return $svg;;\
}\

attr ring_grid_test readingList ring1 ring2 ring3 ring4
attr ring_grid_test room SVGTEST
attr ring_grid_test setList ring1 ring2 ring3 ring4

setstate ring_grid_test 2025-03-23 13:26:50 ring1 Grid
setstate ring_grid_test 2025-03-23 14:46:45 ring2 0
setstate ring_grid_test 2025-03-23 13:26:45 ring3 Solar
setstate ring_grid_test 2025-03-23 14:45:44 ring4 5
setstate ring_grid_test 2025-03-23 12:57:39 state ???



2.
Svg aus dem Anhang nach /opt/fhem/www/images/fhemSVG und "shutdown restart"

3. Da es noch keine Skalierung gibt, muss das Skin F18 oder Flex benutzt werden. Da diese zusätzlichen CSS Code erlauben.
svg.ring_grid_test {
    width: 400px !important;
    height: 400px !important;
}

4. Das Skin muss helle, sein, die animierten Linien sind schwarz.

5. Bezeichner bei Ring 1 und 3 setzen. Werte bei Ring 2 und 4 setzen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Torxgewinde am 23 März 2025, 15:26:57
Mega!!

Ich hätte da noch Ideen:

Die CSS Angaben kann man auch mit einem Regex in das SVG reinmogeln:
defmod ring_grid_test dummy
attr ring_grid_test devStateIcon {\
    # Lese die Werte aus den Readings\
    my $val1 = ReadingsVal($name, 'ring1', 0);;\
    my $val2 = ReadingsVal($name, 'ring2', 0);;\
    my $val3 = ReadingsVal($name, 'ring3', 0);;\
    my $val4 = ReadingsVal($name, 'ring4', 0);;\
\
    # Hole das SVG als Template\
    my $svg = FW_makeImage('ring_grid_test');;\
\
    # Setze den Wert und aktiviere Animationen je nach Wert\
    $svg =~ s/(<tspan class="informId_ringSVG:ring2">)(.*?)(<\/tspan>)/$1$val2$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:ring4">)(.*?)(<\/tspan>)/$1$val4$3/;;\
\
    # Füge Animationen hinzu, wenn die Werte größer als 0 sind\
    $svg =~ s/(<circle[^>]+id="circle1"[^>]+class="motion-disabled")/$1 motion-enabled/ if $val2 > 0;;\
    $svg =~ s/(<circle[^>]+id="circle2"[^>]+class="motion-disabled")/$1 motion-enabled-line4/ if $val4 > 0;;\
\
#mogel noch ein wenig CSS in das SVG mit rein:\
my $extras = 'style="width: 400px !important;;height: 400px !important;;background-color: white !important;;"';;\
$svg =~ s/<svg([^>]*)\s*(style="[^"]*")?/<svg$1$extras/;;\
\
    return $svg;;\
}\

attr ring_grid_test readingList ring1 ring2 ring3 ring4
attr ring_grid_test setList ring1 ring2 ring3 ring4
attr ring_grid_test webCmd ring2 0:ring2 123:ring4 456:ring4 0

Anstatt FHEM neuzustarten, reicht auch bei fhemweb ein rereadicons auszulösen:
set web rereadicons

Sehr cool!
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 23 März 2025, 15:36:15
Top, danke für die Anmerkungen.
Gefällt mir alles sehr gut. Mal sehen wie ich es umsetze. Wird wenn ein ganz schön dickes SVG  ;D

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 29 März 2025, 11:54:00
So, es wird. Etwas zum spielen.

1. Das Svg aus dem Anhang nach /opt/fhem/www/images/fhemSVG kopieren.
Rechte: Eigentümer fhem / Gruppe dialout

2.
set WEB rereadicons
set WEBphone rereadicons
set WEBtablet rereadicons

3. Der dummy
defmod powergrid_test dummy
attr powergrid_test devStateIcon { \
    use URI::Escape;;\
    \
    # Lese die Werte aus den Readings\
    my $lowcarbon_v = ReadingsVal($name, 'lowcarbon_v', 0);;\
    my $grid_v = ReadingsVal($name, 'grid_v', 0);;\
    my $grid_in_v= ReadingsVal($name, 'grid_in_v', 0);;\
    my $grid_out_v= ReadingsVal($name, 'grid_out_v', 0);;\
    my $house_v = ReadingsVal($name, 'house_v', 0);;\
    my $solar_v = ReadingsVal($name, 'solar_v', 0);;\
    my $battery_v = ReadingsVal($name, 'battery_v', 0);;\
    my $battery_p = ReadingsVal($name, 'battery_p', 0);;\
    my $batteryState_v = ReadingsVal($name, 'batteryState_v', 'stop');;\
    my $solar_icon = ReadingsVal($name, 'solar_i', 0);;\
    my $lowcarbon_icon = ReadingsVal($name, 'lowcarbon_i', 0);;\
    my $house_icon = ReadingsVal($name, 'house_i', 0);;\
\
    # Hole das SVG als Template\
    my $svg = FW_makeImage('powergrid');;\
\
    # Setze den Wert und aktiviere Animationen je nach Wert\
    $svg =~ s/(<tspan class="informId_ringSVG:lowcarbon_v">)(.*?)(<\/tspan>)/$1$lowcarbon_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:grid_v">)(.*?)(<\/tspan>)/$1$grid_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:gridPowerIn">)(.*?)(<\/tspan>)/$1$grid_in_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:gridPowerOut">)(.*?)(<\/tspan>)/$1$grid_out_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:house_v">)(.*?)(<\/tspan>)/$1$house_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:solar_v">)(.*?)(<\/tspan>)/$1$solar_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:battery_v">)(.*?)(<\/tspan>)/$1$battery_v$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:battery_p">)(.*?)(<\/tspan>)/$1$battery_p$3/;;\
    $svg =~ s/(<tspan class="informId_ringSVG:batteryState_v">)(.*?)(<\/tspan>)/$1$batteryState_v$3/;;\
\
    # URI-Unescape und Bearbeitung der SVG-Icons\
    my $decoded_solar_svg = uri_unescape($solar_icon);;\
    $decoded_solar_svg =~ s/^data:image\/svg\+xml;;charset=utf-8,//;;\
    $decoded_solar_svg =~ s/<svg([^>]*)/ <svg$1 width="25px" height="25px"/;;\
    $decoded_solar_svg =~ s/<path([^>]*)/ <path fill="yellow"$1/;;\
\
    my $decoded_lowcarbon_svg = uri_unescape($lowcarbon_icon);;\
    $decoded_lowcarbon_svg =~ s/^data:image\/svg\+xml;;charset=utf-8,//;;\
    $decoded_lowcarbon_svg =~ s/<svg([^>]*)/ <svg$1 width="25px" height="25px"/;;\
    $decoded_lowcarbon_svg =~ s/<path([^>]*)/ <path fill="green"$1/;;  # Beispiel mit blau gefüllt\
\
    my $decoded_house_svg = uri_unescape($house_icon);;\
    $decoded_house_svg =~ s/^data:image\/svg\+xml;;charset=utf-8,//;;\
    $decoded_house_svg =~ s/<svg([^>]*)/ <svg$1 width="25px" height="25px"/;;\
    $decoded_house_svg =~ s/<path([^>]*)/ <path fill="yellow"$1/;;  # Beispiel mit grün gefüllt\
\
    # Nun das SVG in das Template einfügen\
    $svg =~ s{<g id="solarCircleIcon"([^>]*)>}{<g id="solarCircleIcon"$1>$decoded_solar_svg };;\
    $svg =~ s{<g id="fossilfreeCircleIcon"([^>]*)>}{<g id="lowcarbonCircleIcon"$1>$decoded_lowcarbon_svg };;\
    $svg =~ s{<g id="houseCircleIcon"([^>]*)>}{<g id="houseCircleIcon"$1>$decoded_house_svg };;\
\
    # Mogel noch ein wenig CSS in das SVG mit rein:\
    my $extras = 'style="width: 95% !important;;height: auto !important;;background-color: black !important;;"';;\
    $svg =~ s/<svg([^>]*)\s*(style="[^"]*")?/<svg$1$extras/;;\
\
    return $svg;;\
}
attr powergrid_test readingList battery_v battery_p batteryState_v cCircle1Icon_i cCircle1Name_s cCircle1Power_v cCircle2Icon_i cCircle2Name_s cCircle2Power_v cCircle3Icon_i cCircle3Name_s cCircle3Power_v cCircle4Icon_i cCircle4Name_s cCircle4Power_v cCircle5Icon_i cCircle5Name_s cCircle5Power_v cCircle6Icon_i cCircle6Name_s cCircle6Power_v cCircle7Icon_i cCircle7Name_s cCircle7Power_v cCircle8Icon_i cCircle8Name_s cCircle8Power_v cCircle9Icon_i cCircle9Name_s cCircle9Power_v dryer_v grid_v grid_in_v grid_out_v house_i house_v lowcarbon_i lowcarbon_v solar_i solar_v
attr powergrid_test room SVGTEST
attr powergrid_test setList battery_v:textField battery_p:textField batteryState_v:select,stop,gridLoad,gridUnload,solarLoad,houseUnload cCircle1Icon_i:textField cCircle1Name_s:textField cCircle1Power_v:textField cCircle2Icon_i:textField cCircle2Name_s:textField cCircle2Power_v:textField cCircle3Icon_i:textField cCircle3Name_s:textField cCircle3Power_v:textField cCircle4Icon_i:textField cCircle4Name_s:textField cCircle4Power_v:textField cCircle5Icon_i:textField cCircle5Name_s:textField cCircle5Power_v:textField cCircle6Icon_i:textField cCircle6Name_s:textField cCircle6Power_v:textField cCircle7Icon_i:textField cCircle7Name_s:textField cCircle7Power_v:textField cCircle8Icon_i:textField cCircle8Name_s:textField cCircle8Power_v:textField cCircle9Icon_i:textField cCircle9Name_s:textField cCircle9Power_v:textField grid_v:textField grid_in_v:textField grid_out_v:textField house_i:textField house_v:textField lowcarbon_i:textField lowcarbon_v:textField solar_i:textField solar_v:textField
attr powergrid_test webCmd batteryState_v stop

setstate powergrid_test 2025-03-29 11:29:09 batteryState_v stop
setstate powergrid_test 2025-03-27 22:09:40 battery_p 100
setstate powergrid_test 2025-03-27 21:53:56 battery_v 223
setstate powergrid_test 2025-03-27 20:32:48 cCircle1Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M22.11%2021.46L2.39%201.73L1.11%203L7.65%209.54C6.74%2011.03%206%2012.65%206%2014.23C6%2017.54%208.69%2020.23%2012%2020.23C13.74%2020.23%2015.3%2019.5%2016.4%2018.29L20.84%2022.73L22.11%2021.46M12%2018.23C9.78%2018.23%208%2016.45%208%2014.23C8%2013.5%208.5%2012.27%209.14%2011.03L15%2016.88C14.26%2017.71%2013.2%2018.23%2012%2018.23M11.14%207.94L9.71%206.5C10.57%205.38%2011.25%204.61%2011.25%204.61L12%203.77L12.75%204.61C12.75%204.61%2014.03%206.06%2015.32%207.94S18%2012.07%2018%2014.23C18%2014.41%2018%2014.59%2017.97%2014.77L15.46%2012.26C15%2011.23%2014.37%2010.07%2013.68%209.07C12.84%207.85%2012.44%207.42%2012%206.9C11.73%207.21%2011.5%207.5%2011.14%207.94Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:44:05 cCircle1Name_s Airdryer
setstate powergrid_test 2025-03-24 17:25:48 cCircle1Power_v 500
setstate powergrid_test 2025-03-27 20:33:06 cCircle2Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M14.83%2C11.17C16.39%2C12.73%2016.39%2C15.27%2014.83%2C16.83C13.27%2C18.39%2010.73%2C18.39%209.17%2C16.83L14.83%2C11.17M6%2C2H18A2%2C2%200%200%2C1%2020%2C4V20A2%2C2%200%200%2C1%2018%2C22H6A2%2C2%200%200%2C1%204%2C20V4A2%2C2%200%200%2C1%206%2C2M7%2C4A1%2C1%200%200%2C0%206%2C5A1%2C1%200%200%2C0%207%2C6A1%2C1%200%200%2C0%208%2C5A1%2C1%200%200%2C0%207%2C4M10%2C4A1%2C1%200%200%2C0%209%2C5A1%2C1%200%200%2C0%2010%2C6A1%2C1%200%200%2C0%2011%2C5A1%2C1%200%200%2C0%2010%2C4M12%2C8A6%2C6%200%200%2C0%206%2C14A6%2C6%200%200%2C0%2012%2C20A6%2C6%200%200%2C0%2018%2C14A6%2C6%200%200%2C0%2012%2C8Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:45:23 cCircle2Name_s Washer
setstate powergrid_test 2025-03-23 20:45:29 cCircle2Power_v 0
setstate powergrid_test 2025-03-27 20:33:22 cCircle3Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M6%2C2H18A2%2C2%200%200%2C1%2020%2C4V20A2%2C2%200%200%2C1%2018%2C22H6A2%2C2%200%200%2C1%204%2C20V4A2%2C2%200%200%2C1%206%2C2M7%2C4A1%2C1%200%200%2C0%206%2C5A1%2C1%200%200%2C0%207%2C6A1%2C1%200%200%2C0%208%2C5A1%2C1%200%200%2C0%207%2C4M10%2C4A1%2C1%200%200%2C0%209%2C5A1%2C1%200%200%2C0%2010%2C6A1%2C1%200%200%2C0%2011%2C5A1%2C1%200%200%2C0%2010%2C4M12%2C8A6%2C6%200%200%2C0%206%2C14A6%2C6%200%200%2C0%2012%2C20A6%2C6%200%200%2C0%2018%2C14A6%2C6%200%200%2C0%2012%2C8M8.11%2C10.5H10C9.76%2C11.88%2010%2C12.67%2010.58%2C13.29C11.68%2C14.36%2012.16%2C15.71%2011.89%2C17.5H10C10.24%2C16.12%2010%2C15.33%209.42%2C14.71C8.32%2C13.64%207.85%2C12.29%208.11%2C10.5M12.11%2C10.5H14C13.76%2C11.88%2014%2C12.67%2014.58%2C13.29C15.68%2C14.36%2016.16%2C15.71%2015.89%2C17.5H14C14.24%2C16.12%2014%2C15.33%2013.42%2C14.71C12.32%2C13.64%2011.85%2C12.29%2012.11%2C10.5Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:43:45 cCircle3Name_s Dryer
setstate powergrid_test 2025-03-23 21:16:00 cCircle3Power_v 300
setstate powergrid_test 2025-03-27 20:33:40 cCircle4Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M18%2C2H6A2%2C2%200%200%2C0%204%2C4V20A2%2C2%200%200%2C0%206%2C22H18A2%2C2%200%200%2C0%2020%2C20V4A2%2C2%200%200%2C0%2018%2C2M10%2C4A1%2C1%200%200%2C1%2011%2C5A1%2C1%200%200%2C1%2010%2C6A1%2C1%200%200%2C1%209%2C5A1%2C1%200%200%2C1%2010%2C4M7%2C4A1%2C1%200%200%2C1%208%2C5A1%2C1%200%200%2C1%207%2C6A1%2C1%200%200%2C1%206%2C5A1%2C1%200%200%2C1%207%2C4M18%2C20H6V8H18V20M14.67%2C15.33C14.69%2C16.03%2014.41%2C16.71%2013.91%2C17.21C12.86%2C18.26%2011.15%2C18.27%2010.09%2C17.21C9.59%2C16.71%209.31%2C16.03%209.33%2C15.33C9.4%2C14.62%209.63%2C13.94%2010%2C13.33C10.37%2C12.5%2010.81%2C11.73%2011.33%2C11L12%2C10C13.79%2C12.59%2014.67%2C14.36%2014.67%2C15.33%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:43:34 cCircle4Name_s Dishwasher
setstate powergrid_test 2025-03-23 21:14:31 cCircle4Power_v 800
setstate powergrid_test 2025-03-27 20:33:56 cCircle5Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%204V19C19%2020.11%2018.11%2021%2017%2021V22H15V21H12.5V2H17C18.11%202%2019%202.9%2019%204M7%202H11.5V21H9V22H7V21C5.9%2021%205%2020.11%205%2019V4C5%202.9%205.9%202%207%202M10%2010H7V14H10V10Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:43:21 cCircle5Name_s Fridge
setstate powergrid_test 2025-03-23 21:14:56 cCircle5Power_v 500
setstate powergrid_test 2025-03-27 20:34:12 cCircle6Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M8%202C6.89%202%206%202.89%206%204V16C6%2017.11%206.89%2018%208%2018H9V20H6V22H9C10.11%2022%2011%2021.11%2011%2020V18H13V20C13%2021.11%2013.89%2022%2015%2022H18V20H15V18H16C17.11%2018%2018%2017.11%2018%2016V4C18%202.89%2017.11%202%2016%202H8M12%204.97A2%202%200%200%201%2014%206.97A2%202%200%200%201%2012%208.97A2%202%200%200%201%2010%206.97A2%202%200%200%201%2012%204.97M10%2014.5H14V16H10V14.5Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:43:11 cCircle6Name_s Boiler
setstate powergrid_test 2025-03-27 20:37:53 cCircle6Power_v 500
setstate powergrid_test 2025-03-27 20:34:28 cCircle7Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19.77%2C7.23L19.78%2C7.22L16.06%2C3.5L15%2C4.56L17.11%2C6.67C16.17%2C7.03%2015.5%2C7.93%2015.5%2C9A2.5%2C2.5%200%200%2C0%2018%2C11.5C18.36%2C11.5%2018.69%2C11.42%2019%2C11.29V18.5A1%2C1%200%200%2C1%2018%2C19.5A1%2C1%200%200%2C1%2017%2C18.5V14A2%2C2%200%200%2C0%2015%2C12H14V5A2%2C2%200%200%2C0%2012%2C3H6A2%2C2%200%200%2C0%204%2C5V21H14V13.5H15.5V18.5A2.5%2C2.5%200%200%2C0%2018%2C21A2.5%2C2.5%200%200%2C0%2020.5%2C18.5V9C20.5%2C8.31%2020.22%2C7.68%2019.77%2C7.23M18%2C10A1%2C1%200%200%2C1%2017%2C9A1%2C1%200%200%2C1%2018%2C8A1%2C1%200%200%2C1%2019%2C9A1%2C1%200%200%2C1%2018%2C10M8%2C18V13.5H6L10%2C6V11H12L8%2C18Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:42:59 cCircle7Name_s EV-Charge
setstate powergrid_test 2025-03-23 21:15:11 cCircle7Power_v 700
setstate powergrid_test 2025-03-27 20:34:43 cCircle8Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M2%204.6V9.4C2%2010.3%202.5%2011%203.2%2011H20.9C21.5%2011%2022.1%2010.3%2022.1%209.4V4.6C22%203.7%2021.5%203%2020.8%203H3.2C2.5%203%202%203.7%202%204.6M10%208V6H9V8H10M5%208H7V6H5V8M20%209H4V5H20V9M2%2014.6V19.4C2%2020.3%202.5%2021%203.2%2021H20.9C21.5%2021%2022.1%2020.3%2022.1%2019.4V14.6C22.1%2013.7%2021.6%2013%2020.9%2013H3.2C2.5%2013%202%2013.7%202%2014.6M10%2018V16H9V18H10M5%2018H7V16H5V18M20%2019H4V15H20V19Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:42:33 cCircle8Name_s Server
setstate powergrid_test 2025-03-23 21:15:27 cCircle8Power_v 800
setstate powergrid_test 2025-03-27 20:34:56 cCircle9Icon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%203H5C3.9%203%203%203.9%203%205V19C3%2020.1%203.9%2021%205%2021H19C20.1%2021%2021%2020.1%2021%2019V5C21%203.9%2020.1%203%2019%203M19%2019H5V5H19V19M12%2018C15.31%2018%2018%2015.31%2018%2012S15.31%206%2012%206%206%208.69%206%2012%208.69%2018%2012%2018M11.25%2015.92C10.7%2015.82%2010.2%2015.6%209.75%2015.3L11.25%2013.8V15.92M12.75%2015.92V13.81L14.25%2015.31C13.8%2015.61%2013.3%2015.82%2012.75%2015.92M15.31%2014.25L13.81%2012.75H15.92C15.82%2013.3%2015.61%2013.8%2015.31%2014.25M15.92%2011.25H13.81L15.31%209.75C15.61%2010.2%2015.82%2010.7%2015.92%2011.25M12.75%208.08C13.3%208.18%2013.8%208.4%2014.25%208.7L12.75%2010.2V8.08M12%2011C12.55%2011%2013%2011.45%2013%2012S12.55%2013%2012%2013%2011%2012.55%2011%2012%2011.45%2011%2012%2011M11.25%208.08V10.19L9.75%208.69C10.2%208.39%2010.7%208.18%2011.25%208.08M8.69%209.75L10.19%2011.25H8.08C8.18%2010.7%208.39%2010.2%208.69%209.75M10.19%2012.75L8.69%2014.25C8.39%2013.81%208.18%2013.3%208.07%2012.75H10.19Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-23 20:42:25 cCircle9Name_s Heat-Pump
setstate powergrid_test 2025-03-23 21:15:39 cCircle9Power_v 900
setstate powergrid_test 2025-03-29 11:38:21 grid_in_v 1547.792
setstate powergrid_test 2025-03-29 11:38:21 grid_out_v 483.436
setstate powergrid_test 2025-03-29 11:38:21 grid_v -450
setstate powergrid_test 2025-03-27 20:37:15 house_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%203L2%2012H5V20H19V12H22L12%203M11.5%2018V14H9L12.5%207V11H15L11.5%2018Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-29 11:38:21 house_v 503.3
setstate powergrid_test 2025-03-27 20:38:50 lowcarbon_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19.19%2018H24L20.14%2012H22L15%202L12.61%205.41L17.92%2013H15.97L19.19%2018M16%2012L9%202L2%2012H3.86L0%2018H7V22H11V18H18L14.14%2012H16M12.16%2010H10.5L14.34%2016H3.67L7.53%2010H5.84L9%205.5L12.16%2010M13%2019V22H17V19H13Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-29 11:38:21 lowcarbon_v 76
setstate powergrid_test 2025-03-29 10:56:26 solar_i data:image/svg+xml;;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M11.45%2C2V5.55L15%2C3.77L11.45%2C2M10.45%2C8L8%2C10.46L11.75%2C11.71L10.45%2C8M2%2C11.45L3.77%2C15L5.55%2C11.45H2M10%2C2H2V10C2.57%2C10.17%203.17%2C10.25%203.77%2C10.25C7.35%2C10.26%2010.26%2C7.35%2010.27%2C3.75C10.26%2C3.16%2010.17%2C2.57%2010%2C2M17%2C22V16H14L19%2C7V13H22L17%2C22Z%22%20%2F%3E%3C%2Fsvg%3E
setstate powergrid_test 2025-03-29 11:38:25 solar_v 941.2
setstate powergrid_test 2025-03-23 12:57:39 state ???
setstate powergrid_test 2025-03-29 08:59:25 test data%3Aimage%2Fsvg%2Bxml%3Bcharset%3Dutf-8%2C%253Csvg%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%2520viewBox%253D%25220%25200%252024%252024%2522%253E%253Cpath%2520d%253D%2522M11.45%252C2V5.55L15%252C3.77L11.45%252C2M10.45%252C8L8%252C10.46L11.75%252C11.71L10.45%252C8M2%252C11.45L3.77%252C15L5.55%252C11.45H2M10%252C2H2V10C2.57%252C10.17%25203.17%252C10.25%25203.77%252C10.25C7.35%252C10.26%252010.26%252C7.35%252010.27%252C3.75C10.26%252C3.16%252010.17%252C2.57%252010%252C2M17%252C22V16H14L19%252C7V13H22L17%252C22Z%2522%2520%252F%253E%253C%252Fsvg%253E



Im Moment hänge ich an der Implementierung der Icons. Quick N dörty habe ich diese erstmal nur auf SVG-Url beschränkt.
Da überlege ich noch ob ich das in fhem mit perl mach oder wieder im SVG per JS. Jetzt gerade kickt Fhem die Icons rein.
Finde ich ganz sympathisch und wenig Code. Wird aber aufwendiger wenn ich von Fhem auch noch die Icons per Path einlesen
möchte. Wenn das steht, dann können die Customringe folgen und dann als letztes die Skalierung für Mobile und Desktop.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: Torxgewinde am 29 März 2025, 13:55:29
Wow, spannend, finde ich gut!

Ich habe noch ein paar Dinge gelernt, die dir hier ggf. auch nützlich sein können. Manchmal scheint document.currentScript einfach null zurückzuliefern, auch wenn es eigentlich nicht "async" geladen wurde. Dafür habe ich mir ein Fallback ausgedacht, dass dem script Tag das wahrscheinlich unser eigenes ist eine UUID verpasst um es wiederzuerkennen. Das ist nur Fallbackcode, per Standard ist weiterhin document.currentScript genutzt:
<script><![CDATA[
    let uuid = crypto.randomUUID();
    let script = document.currentScript;
    if (!script) {
      console.log('using fallback for currentScript');
      let scripts = document.querySelectorAll('svg > script:not([data-uuid])');
      if (scripts.length === 0) {
        console.warn('Could not find any matching scripts.');
      } else {
        script = scripts[scripts.length - 1];
      }
    }
    script?.setAttribute('data-uuid', uuid);
....

Das CDATA ist nützlich wenn der SVG Parser wegen ungültigem XML nörgelt.

Bissel experimentell ist wie ich den Link zum Device ausblende, aber zumindest bei meinem Skin klappt das 1a:
/* entferne in FHEMWEB alle Zellen dieser Zeile die nicht StatusIcon sind */
    let table = script?.closest("table");
    if (table) {
      let maxCols = 0;
      for (let i = 0; i < table.rows.length; i++) {
        maxCols = Math.max(maxCols, table.rows[i].cells.length);
      }
      [...script?.closest('tr')?.querySelectorAll("td:not([informId])")].forEach(td => td.remove());
      script?.closest('td')?.setAttribute('colspan', maxCols);
    }

Wie gesagt, nur als "vielleicht hilfreich" ansehen. Ich freue mich auf dein Powerflow!
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 01 April 2025, 22:15:30
Nabend,

next try. Der Code in Fhem in Perl ist, naja *hust* erstmal einfach runtergerattert.

- Alle Grundfunktionen wiederhergestellt. (Ringe per n/a ausblenden, Mobileansicht,...,)
- Mehr Performance durch die neuen informIds.
- Dadurch endlich Werte in Realtime, bzw Event-basiert.
- Unsichtbare Buttons hinzugefügt. Dort kann ein Link hinterlegt werden. Setzbar mit z.B set powergrid cCircle3Link_s /fhem?detail=Waschmaschine
- House und FossilFree haben noch keinen Button.
- Das setzen der Icons funktioniert fast wie früher. SVG-Url einfach reinkopieren. Fhem interne so setzen -->coronavirus:fhem

todo:
Code in Fhem dummy komprimieren/auslagern und im SVG 4 Größen für die Skalierung einbauen. Damit etwas abgeschnitten wird,
wenn Ringe ausgeblendet werden.

Installieren wie vorher auch:
1. Das Svg aus dem Anhang nach /opt/fhem/www/images/fhemSVG kopieren.
Rechte: Eigentümer fhem / Gruppe dialout

2.
set WEB rereadicons
set WEBphone rereadicons
set WEBtablet rereadicons

3. Die Raw des dummy per + Zeichen oben links, bzw Execute ausführen/anlegen.


Hoffentlich habe ich nichts vergessen?

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 05 April 2025, 15:10:01
Tag,

wieder etwas weiter.

- Verschiedene ViewBoxen hinzugefügt. Dabei werden alle Customringe berücksichtigt.
- Hide wird korrekt für Elemente gesetzt, welche ausgeblendet werden.
- Die animierten Linie nochmal überarbeitet. Da bei verschiedenen Skalierungen die gestoppten Punkte bei ca. x und y 0 auftauchten...
- dies und das

@Torxgewinde
Vielen Dank für deine Tips. Besonders das Beispiel mit setValue(d) hat mir sehr geholfen.
Die Performance auf meinem FireHD ist jetzt wirklich akzeptabel.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 06 April 2025, 09:14:32
Morgen,

kleines Update ein Post drüber. Ausversehen habe ich die Reihenfolge der gekreuzten Linie verhauen...
Vorher: Linie,Punkt,Linie,Punkt. Jetzt: Linie,Linie,Punkt,Punkt. Das muss sein, sonst verschwindet ein Punkt hinter einer Linie.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 06 April 2025, 23:01:30
Hallo schwatter,

ich habe diese neue Version ausprobiert, habe aber die Angaben ab Circle6 geleert, weil ich sie nicht brauche,
daraufhin werden sie ja auch ausgeblendet.

Allerdings wird mein Log mit folgenden Meldungen geflutet:

2025.04.06 21:10:48 1: PERL WARNING: "my" variable $house_icon masks earlier declaration in same scope at (eval 464) line 21.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle6_svg in substitution (s///) at (eval 464) line 134.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle6_svg in substitution (s///) at (eval 464) line 136.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle7_svg in substitution (s///) at (eval 464) line 139.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle7_svg in substitution (s///) at (eval 464) line 140.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle7_svg in substitution (s///) at (eval 464) line 141.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle8_svg in substitution (s///) at (eval 464) line 144.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle8_svg in substitution (s///) at (eval 464) line 145.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle8_svg in substitution (s///) at (eval 464) line 146.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle9_svg in substitution (s///) at (eval 464) line 149.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle9_svg in substitution (s///) at (eval 464) line 150.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle9_svg in substitution (s///) at (eval 464) line 151.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle6_svg in concatenation (.) or string at (eval 464) line 162.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle7_svg in concatenation (.) or string at (eval 464) line 163.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle8_svg in concatenation (.) or string at (eval 464) line 164.
2025.04.06 21:10:48 3: eval: {

2025.04.06 21:10:48 1: PERL WARNING: Use of uninitialized value $decoded_circle9_svg in concatenation (.) or string at (eval 464) line 165.
2025.04.06 21:10:48 3: eval: {

Ab dem eval: wird der SVG-Code ausgegeben.
Offensichtlich wird immer dann solch ein Meldungsblock ausgegeben, wenn Daten an das SVG übergeben werden.
Ich benutze dafür das DOIF aus dem ersten Post.
Woran mag das liegen?

Grüße
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 07 April 2025, 08:09:46
Moin,

danke für den Hinweis. Ich denke ich komme heut Abend zum fixen.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 07 April 2025, 19:14:57
Nabend,

da war eine Variable doppelt und die Icons musste ich abfangen. Irgendwann wird das noch schöner, aber jetzt sollte erstmal Ruhe sein.
Im Anhang nur das devStateIcon. Teste und gibt bitte Rückmeldung.

Danke, Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 07 April 2025, 22:10:25
Hallo schwatter,

das klappt jetzt, vielen Dank!

Grüße
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 07 April 2025, 22:29:18
Super,

hier dann nochmal alles komplett.

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 09 April 2025, 19:21:35
Nabend,

Updates jetzt wieder im ersten Post. Habe die Infos auf das neue SVG + dummy angepasst.

Update:
- Code im dummy komprimiert
- Diesbezüglich 2 <tspan class="informId_ringSVG: im SVG angepasst.

Zum updaten bitte dummy Code und powergrid.svg erneuern.


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 10 April 2025, 09:05:10
Hallo schatter,

vielen Dank. Allerdings werden jetzt die unbenutzten Circles als leere Circles angezeigt.
Kann man das unterdrücken, so wie vorher?

Grüße
ergerd
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 10 April 2025, 09:32:08
Morgen,

ich habe Circle 5 bis 9 mit n/a ausgeblendet und auch die Readings von Icon + Power gelöscht. Bei mir werden alle ausgeblendet, auch die Hidden_Buttons.
Hast du aus dem ersten Post Beide erneuert? Vielleicht nochmal ein STRG + F5.

Im Anhang mit Chrome Desktop + FireFox Desktop


Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: ergerd am 10 April 2025, 11:41:56
Ah, man muss in das Feld Name "n/a" eingegeben, ok, habe ich wohl irgendwo überlesen.

Danke, funktioniert!

Grüße
erger
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 10 April 2025, 16:06:49
Ich habe jetzt nochmal geschaut. Wenn ich z.B "deletereading powergrid cCircle4Name_s" oder "set powergrid cCircle4Name_s n/a" setze, wird bei Beiden der Ring
nach erneutem Laden der Seite ausgeblendet. Bedeutet, wenn jemand das Device neu anlegt, sollten auch keinen toten Ringe erscheinen. Vielleicht dein Browsercache?

Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: wicky am 04 Mai 2025, 13:43:11
Hallo schwatter,

habe Dein powergrid Installiert und soweit funktioniert
Eigentlich alles, ein zwei Probleme habe ich dann doch mit
der Batterieanzeige für was ist batteryLink_s = ???,
battery_v  müsste ich über DOIF die Wattangabe In und Out
wie gerade der Zustand ist übergeben, gilt auch für
batteryState_v = houseUnload, solarLoad, usw.,
battery_p = Prozent Batterie ist für mich klar.
Die Berechnungen stimmen für mich nicht siehe Anhang
Werte rot markiert, werden die in der .svg berechnet oder
sollte man über ein Userreading rechnen und dann der DOIF
die fertigen Werte übergeben.

Gruß Hans
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 04 Mai 2025, 18:44:00
Hallo Hans,

- batteryLink_s = /fhem?detail=NameVonMeinemBatteryDevice. Kann man setzen, muss man nicht. Wenn du dann auf den
Batteryring klickst, landest du in dem Device. Da könnte auch www.google.de stehen.
- zu Werte stimmen nicht. Du hast recht, ist mir noch nicht aufgefallen. Da ich selber noch keinen Akku habe.
Richtig wäre:
  Grid -41 W
+ Solar 1551 W
- Battery 983 W
---------------
= House 527 W.

Im Moment wird im DOIF/notify nur stumpf der Wert Smartmeter + Solarinverter addiert. Bedeutet, die 983 W von deiner Battery
verstecken sich im House 1510 mit W. Müssten da aber abgezogen werden. Also ja, du müsstest deine Berechnung anpassen.

Wie ist das bei deinem Akku? Wenn du lädst, zeigt er positive Werte an (300w) und beim entladen negative Werte (-300w)?

Edit:
Zum testen habe ich mir einen Batterydummy angelegt und berücksichtige ihn so:
( set powergrid house_v {(ReadingsNum("Smartmeter_2E1F50","APOX_Power", 0, 1) + ReadingsNum("OpenDTU","total.Power.v", 0, 1) - ReadingsNum("batteryDummy","power", 0, 1) )} )
Gruß schwatter
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: wicky am 04 Mai 2025, 20:58:10
Hallo schwatter,

ist kein Problem, Berechnungen mach ich erstmal in der DOIF.

ZitatWie ist das bei deinem Akku? Wenn du lädst, zeigt er positive Werte an (300w) und beim entladen negative Werte (-300w)?

Akku wird mit zwei Readings ausgeben data_out und data_in keine negativen
Werte sowie batteryState_v = houseUnload, solarLoad werde
ich dann auch gleich in der DOIF mit lösen.

Schönen Dank erstmal und wenn irgendwelche Fragen noch habe melde ich mich.

Gruß Hans
 
Titel: Aw: PowerFlow [animiertes SVG, dummy, javascript]
Beitrag von: schwatter am 04 Mai 2025, 21:12:13
Ok,

also 2 positive Werte für Battery in und out.
Damit der Hausring prozentual den Anteil der Battery farblich anzeigt,
ist auch ein positiver Wert + houseUnload erforderlich.
Dann passt das.

Gruß schwatter