Dashboard 2.0 SVG variables wont work

I got a svg with variables and try to feed some variables, but this wont work ...

<svg xmlns="http://www.w3.org/2000/svg" id="powercard" viewBox="0 0 318 318" preserveAspectRatio="xMidYMid meet">
  <style>
    .ring { fill:#fff; fill-opacity:0.1; stroke-width:3; }
    .ring.red { stroke:#c00; }
    .ring.grey { stroke:#ccc; }
    .ring.blue { stroke:#005FFF; }
    .ring.lightblue { stroke:#7FC6FE; fill:#7FC6FE; fill-opacity:0.2; }
    .ring.yellow { stroke:#FFF700; }
    .ring.brown { stroke:#5C4033; }
    .ring.green { stroke:#24FD00; }
    .ring.white { stroke:#ffffff; }

    .label { fill:#fff; font-size:0.9em; text-anchor:middle; }
    .value { fill:#fff; font-size:0.8em; text-anchor:middle; }

    .line { stroke-width:2; fill:none; }
    .line.yellow { stroke:#ff0; }
    .line.blue { stroke:#005FFF; }
    .line.red { stroke:#c00; }
    .line.grey { stroke:#ccc; }
    .line.brown { stroke:#5C4033; }

    .dot { stroke-width:6; stroke-linecap:round; fill:none; }
    .dot.yellow { stroke:#ff0; }
    .dot.blue { stroke:#005FFF; }
    .dot.red { stroke:#c00; }
    .dot.grey { stroke:#ccc; }
    .dot.brown { stroke:#5C4033; }
  </style>

  <!-- Kreise -->
  <circle cx="45" cy="45" r="32" class="ring lightblue"/>
  <circle cx="275" cy="45" r="40" class="ring red"/>
  <circle cx="160" cy="45" r="40" class="ring yellow"/>
  <circle cx="45" cy="165" r="40" class="ring grey"/>
  <circle cx="275" cy="165" r="40" class="ring white"/>
  <circle cx="160" cy="275" r="40" class="ring blue"/>
  <circle cx="275" cy="275" r="40" class="ring brown"/>
  <circle cx="45" cy="275" r="40" class="ring green"/>

  <!-- Werte -->
  <text x="45" y="50" class="value">{{msg.P1}}</text>
  <text x="160" y="28" class="value">{{msg.P2}}W</text>
  <text x="275" y="28" class="value">{{msg.P3}}W</text>
  <text x="45" y="148" class="value">{{msg.P4}}W</text>
  <text x="275" y="148" class="value">{{msg.P6}}W</text>
  <text x="160" y="258" class="value">{{msg.P8}}W</text>
  <text x="275" y="258" class="value">{{msg.P9}}L</text>
  <text x="200" y="220" fill="cornflowerblue" text-anchor="middle">{{msg.P_Bat}}W</text>

  <!-- Labels + Symbole -->
  <text x="160" y="74" class="label">PV</text>
  <text x="160" y="55" class="label">๐ŸŒž</text>

  <text x="275" y="74" class="label">WP</text>
  <text x="275" y="55" class="label">๐Ÿ”ฅ</text>

  <text x="275" y="192" class="label">Haus</text>
  <text x="275" y="175" class="label">๐Ÿ </text>

  <text x="160" y="298" class="label">{{msg.soc}}</text>
  <text x="160" y="280" class="label">๐Ÿ”‹</text>

  <text x="45" y="192" class="label">Netz</text>
  <text x="45" y="175" class="label">โšก</text>

  <text x="275" y="298" class="label">Heizung</text>
  <text x="275" y="280" class="label">๐Ÿ”ฅ</text>

  <!-- Erzeugung & Verbrauch unten links -->
  <text x="45" y="270" class="value"><tspan fill="#24FD00">๐ŸŒž</tspan>{{msg.P_erzeugung}}kWh</text>
  <text x="45" y="290" class="value"><tspan fill="#c00">๐Ÿ”Œ</tspan>{{msg.P_verbrauch}}kWh</text>

  <!-- Linien + Punkte mit dynamischer Geschwindigkeit -->
  <g>
    <path id="lineY3" d="M160,87 C160,166 160,166 160,235" class="line yellow"/>
    <circle r="3" class="dot yellow">
      <animateMotion id="animY3" repeatCount="indefinite">
        <mpath href="#lineY3"/>
      </animateMotion>
    </circle>
  </g>

  <g>
    <path id="lineB" d="M170,235 C170,176 170,176 235,176" class="line blue"/>
    <circle r="3" class="dot blue">
      <animateMotion id="animB" repeatCount="indefinite">
        <mpath href="#lineB"/>
      </animateMotion>
    </circle>
  </g>

  <g>
    <path id="lineR2" d="M200,45 L235,45" class="line red"/>
    <circle r="3" class="dot red">
      <animateMotion id="animR2" repeatCount="indefinite">
        <mpath href="#lineR2"/>
      </animateMotion>
    </circle>
  </g>

  <g>
    <path id="lineG2" d="M87,166 C160,166 160,166 233,166" class="line grey"/>
    <circle r="3" class="dot grey">
      <animateMotion id="animG2" repeatCount="indefinite">
        <mpath href="#lineG2"/>
      </animateMotion>
    </circle>
  </g>

  <g>
    <path id="lineBr" d="M275,235 C275,210 275,210 275,205" class="line brown"/>
    <circle r="3" class="dot brown">
      <animateMotion id="animBr" repeatCount="indefinite">
        <mpath href="#lineBr"/>
      </animateMotion>
    </circle>
  </g>
  <!-- Script zum Setzen der Animation-Dauer -->
  <script>
    document.getElementById('animY3').setAttribute('dur', '{{msg.v_yellow3}}s');
    document.getElementById('animB').setAttribute('dur', '{{msg.v_blue}}s');
    document.getElementById('animR2').setAttribute('dur', '{{msg.v_red2}}s');
    document.getElementById('animG2').setAttribute('dur', '{{msg.v_grey2}}s');
    document.getElementById('animBr').setAttribute('dur', '{{msg.brown}}s');
  </script>
</svg>

I try to feed the duration attributes in script but they wont work and in the svg stay {{msg.v_blue}}

Someone here could explain this ?

Regards,
Daniel

Try wrapping it in a template tag

Also, use optional chaining and fallback values e.g. msg?.v_yellow3 || 'yellow'

The variables are set ... i made a point with {{msg.v_blue}} and the data is shown. Put it in template tag mess the whole grafic ... or witch part i should pack into it ?

Actually I see you have a script element inside of the SVG (yuk) and are accessing document elements.

This script will run once and likely BEFORE msg is sent.

I recommend you use vue watchers and monitor the msg.xxxx value changing and only then update the attribute.

For me it seems so that there was no access to the variables in the template node ...

Likely due to what I said.

or because it (the SVG) is NOT inside a template element

... but where i should place the ... im not sure.
Several other variables are avalible like msg.P3 and so on ...

When you first add a ui-template, it is pre-filled.

The docs also link off to the main dashboard docs where it goes into depth with more examples.

To do more complex things like you are asking, a level of vue knowledge is necessary though much of it is piecing together what you want with what you know

For example, you want things to change when message values arrive. So armed with the knowledge of how vue works, you might chose to watch the msg and update data variables. Alternatively, you might just bind directly to the msg object using the bind syntax - but you have to understand if you only send a msg with yellow, then the other bindings will get undefined values.

But, you give you a head start - here is something possibly close to what you need:
chrome_4FPQ0QsPsQ

<template>
    <svg xmlns="http://www.w3.org/2000/svg" id="powercard" viewBox="0 0 318 318" preserveAspectRatio="xMidYMid meet">
        <!-- Kreise -->
        <circle cx="45" cy="45" r="32" class="ring lightblue" />
        <circle cx="275" cy="45" r="40" class="ring red" />
        <circle cx="160" cy="45" r="40" class="ring yellow" />
        <circle cx="45" cy="165" r="40" class="ring grey" />
        <circle cx="275" cy="165" r="40" class="ring white" />
        <circle cx="160" cy="275" r="40" class="ring blue" />
        <circle cx="275" cy="275" r="40" class="ring brown" />
        <circle cx="45" cy="275" r="40" class="ring green" />

        <!-- Werte -->
        <text x="45" y="50" class="value">{{msg.P1}}</text>
        <text x="160" y="28" class="value">{{msg.P2}}W</text>
        <text x="275" y="28" class="value">{{msg.P3}}W</text>
        <text x="45" y="148" class="value">{{msg.P4}}W</text>
        <text x="275" y="148" class="value">{{msg.P6}}W</text>
        <text x="160" y="258" class="value">{{msg.P8}}W</text>
        <text x="275" y="258" class="value">{{msg.P9}}L</text>
        <text x="200" y="220" fill="cornflowerblue" text-anchor="middle">{{msg.P_Bat}}W</text>

        <!-- Labels + Symbole -->
        <text x="160" y="74" class="label">PV</text>
        <text x="160" y="55" class="label">๐ŸŒž</text>

        <text x="275" y="74" class="label">WP</text>
        <text x="275" y="55" class="label">๐Ÿ”ฅ</text>

        <text x="275" y="192" class="label">Haus</text>
        <text x="275" y="175" class="label">๐Ÿ </text>

        <text x="160" y="298" class="label">{{msg.soc}}</text>
        <text x="160" y="280" class="label">๐Ÿ”‹</text>

        <text x="45" y="192" class="label">Netz</text>
        <text x="45" y="175" class="label">โšก</text>

        <text x="275" y="298" class="label">Heizung</text>
        <text x="275" y="280" class="label">๐Ÿ”ฅ</text>

        <!-- Erzeugung & Verbrauch unten links -->
        <text x="45" y="270" class="value">
            <tspan fill="#24FD00">๐ŸŒž</tspan>{{msg.P_erzeugung}}kWh
        </text>
        <text x="45" y="290" class="value">
            <tspan fill="#c00">๐Ÿ”Œ</tspan>{{msg.P_verbrauch}}kWh
        </text>

        <!-- Linien + Punkte mit dynamischer Geschwindigkeit -->
        <g>
            <path id="lineY3" d="M160,87 C160,166 160,166 160,235" class="line yellow" />
            <circle r="3" class="dot yellow">
                <animateMotion id="animY3" repeatCount="indefinite">
                    <mpath href="#lineY3" />
                </animateMotion>
            </circle>
        </g>

        <g>
            <path id="lineB" d="M170,235 C170,176 170,176 235,176" class="line blue" />
            <circle r="3" class="dot blue">
                <animateMotion id="animB" repeatCount="indefinite">
                    <mpath href="#lineB" />
                </animateMotion>
            </circle>
        </g>

        <g>
            <path id="lineR2" d="M200,45 L235,45" class="line red" />
            <circle r="3" class="dot red">
                <animateMotion id="animR2" repeatCount="indefinite">
                    <mpath href="#lineR2" />
                </animateMotion>
            </circle>
        </g>

        <g>
            <path id="lineG2" d="M87,166 C160,166 160,166 233,166" class="line grey" />
            <circle r="3" class="dot grey">
                <animateMotion id="animG2" repeatCount="indefinite">
                    <mpath href="#lineG2" />
                </animateMotion>
            </circle>
        </g>

        <g>
            <path id="lineBr" d="M275,235 C275,210 275,210 275,205" class="line brown" />
            <circle r="3" class="dot brown">
                <animateMotion id="animBr" repeatCount="indefinite">
                    <mpath href="#lineBr" />
                </animateMotion>
            </circle>
        </g>
    </svg>
</template>

<script>
    export default {
        watch: {
            // watch msg for any changes
            msg: function () {
                const m = this.msg
                console.log('msg changed', m)
                this.updateDuration('animY3', m.v_yellow3)
                this.updateDuration('animB', m.v_blue)
                this.updateDuration('animR2', m.v_red2)
                this.updateDuration('animG2', m.v_grey2)
                this.updateDuration('animBr', m.brown)
            }
        },
        methods: {
            updateDuration(animationId, newValue, unit = 's') {
                if (typeof newValue !== 'number' || newValue < 0) {
                    console.log(`Invalid animation duration for ${animationId}: ${newValue}`)
                    return;
                }
                console.log('Updating animation', animationId, 'to duration', newValue)
                const anim = this.$el.querySelector(`#${animationId}`)
                if (anim) {
                    anim.setAttribute('dur', (newValue ?? 5) + unit)
                }
            }
        }
    }
</script>


<style>
    .ring {
        fill: #fff;
        fill-opacity: 0.1;
        stroke-width: 3;
    }

    .ring.red {
        stroke: #c00;
    }

    .ring.grey {
        stroke: #ccc;
    }

    .ring.blue {
        stroke: #005FFF;
    }

    .ring.lightblue {
        stroke: #7FC6FE;
        fill: #7FC6FE;
        fill-opacity: 0.2;
    }

    .ring.yellow {
        stroke: #FFF700;
    }

    .ring.brown {
        stroke: #5C4033;
    }

    .ring.green {
        stroke: #24FD00;
    }

    .ring.white {
        stroke: #ffffff;
    }

    .label {
        fill: #fff;
        font-size: 0.9em;
        text-anchor: middle;
    }

    .value {
        fill: #fff;
        font-size: 0.8em;
        text-anchor: middle;
    }

    .line {
        stroke-width: 2;
        fill: none;
    }

    .line.yellow {
        stroke: #ff0;
    }

    .line.blue {
        stroke: #005FFF;
    }

    .line.red {
        stroke: #c00;
    }

    .line.grey {
        stroke: #ccc;
    }

    .line.brown {
        stroke: #5C4033;
    }

    .dot {
        stroke-width: 6;
        stroke-linecap: round;
        fill: none;
    }

    .dot.yellow {
        stroke: #ff0;
    }

    .dot.blue {
        stroke: #005FFF;
    }

    .dot.red {
        stroke: #c00;
    }

    .dot.grey {
        stroke: #ccc;
    }

    .dot.brown {
        stroke: #5C4033;
    }
</style>
2 Likes

Jesus this is amazing ... i dont got such skills in scripting.

The only thing is miss is the direction of some lines could change ... This is the input actually:`

{"_msgid":"5b8020f9b3d25bdc","payload":2,"P1":"12.4ยฐC","soc":"34%","soc_icon":"battery_2_bar","P8":"-339","P3":"0","P2":"0","P4":"-28","P6":"367","P9":"0.0","P_erzeugung":"0.0","P_verbrauch":"0.0","P_Bat":"339","w_blue":11,"v_blue":14.74705882352941,"d_blue":"normal","w_grey2":14,"v_grey2":23.862742474916388,"d_grey2":"normal","w_yellow1":10,"w_yellow2":10,"w_yellow3":2,"v_yellow3":0,"w_red2":2,"v_red2":0,"brown":0.6666666666666666}

d_blue for example set the direction ... this can also be changed but no idea how to place it in script :-/
Values are "normal" and "reverse" ...

Regards,
Snot

`