[gelöst] Javascript bei Raumübersicht ausführen [SVG updaten, Werte aus D.....]

Begonnen von schwatter, 19 Oktober 2024, 16:00:11

Vorheriges Thema - Nächstes Thema

schwatter

Hallo zusammen,

ich bin normalerweise mehr der Endanwender bei Fhem. Ich war auf der Suche nach dynamischen Updaten von Werten für SVG ohne Animationen zu unterbrechen.

Ich bin jetzt soweit, das zumindest im Device das SVG geupdatet wird. Sobald ich aber in der Raumübersicht bin, kommen keine Werte.
Ich hoffe mir kann jemand auf die Sprünge helfen.

Folgende Devices und Javascript habe ich zum nachstellen.

1. myDummy [Hauptdevice zum anzeigen der Werte und Animationen]
defmod myDummy dummy
attr myDummy room Energy
attr myDummy stateFormat <!DOCTYPE html>\
<html lang="en">\
<head>\
    <meta charset="UTF-8">\
    <meta name="viewport" content="width=device-width, initial-scale=1.0">\
    <title>Power Flow SVG</title>\
    <style>\
        body {\
            background-color: black;;\
            display: flex;;\
            justify-content: center;;\
            align-items: center;;\
            height: 100vh;;\
            margin: 0;;\
        }\
    </style>\
</head>\
<body>\
    <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>\
\
        <!-- 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 (Turkis) -->\
        <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
        <circle cx='250' cy='400' r='40' fill='none' stroke='turquoise' stroke-width='5'/>\
        <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>\
\
        <!-- Haus (Lila) -->\
        <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
        <circle cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5'/>\
        <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>\
\
        <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
        <path id='solarToBattery' d='M 250 140 A 0 100 0 0 1 250 360' stroke='orange' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='orange' style="display: none;;">\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#solarToBattery'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
        <path id='gridToHouse' d='M 140 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='blue'>\
            <animateMotion dur='50s' repeatCount='indefinite'>\
                <mpath href='#gridToHouse'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
        <path id='solarToHouse' d='M 260 140 A 110 100 0 0 0 358 240' stroke='orange' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='orange'>\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#solarToHouse'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
        <path id='solarToGrid' d='M 240 140 A 110 100 0 0 1 142 240' stroke='orange' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='orange' style="display: none;;">\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#solarToGrid'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
        <path id='gridToBattery' d='M 142 260 A 110 100 0 0 1 240 360' stroke='turquoise' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='turquoise' style="display: none;;">\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#gridToBattery'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Batterie zu Haus (Lila) -->\
        <path id='batteryToHouse' d='M 260 359 A 110 100 0 0 1 360 260' stroke='purple' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='purple'>\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#batteryToHouse'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Include the JS update script -->\
        <script xlink:href='/fhem/www/pgm2/svg_update.js'></script>\
    </svg>\
</body>\
</html>\
\


setstate myDummy <!DOCTYPE html>\
<html lang="en">\
<head>\
    <meta charset="UTF-8">\
    <meta name="viewport" content="width=device-width, initial-scale=1.0">\
    <title>Power Flow SVG</title>\
    <style>\
        body {\
            background-color: black;;\
            display: flex;;\
            justify-content: center;;\
            align-items: center;;\
            height: 100vh;;\
            margin: 0;;\
        }\
    </style>\
</head>\
<body>\
    <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>\
\
        <!-- 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 (Turkis) -->\
        <circle id='batteryCircle' cx='250' cy='400' r='45' fill='none' stroke='turquoise' stroke-width='10' opacity='0.4'/>\
        <circle cx='250' cy='400' r='40' fill='none' stroke='turquoise' stroke-width='5'/>\
        <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>\
\
        <!-- Haus (Lila) -->\
        <circle id='houseCircle' cx='400' cy='250' r='45' fill='none' stroke='purple' stroke-width='10' opacity='0.4'/>\
        <circle cx='400' cy='250' r='40' fill='none' stroke='purple' stroke-width='5'/>\
        <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>\
\
        <!-- Verbindungslinie von Solar zu Batterie (Orange) -->\
        <path id='solarToBattery' d='M 250 140 A 0 100 0 0 1 250 360' stroke='orange' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='orange' style="display: none;;">\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#solarToBattery'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Netz zu Haus (Blau) -->\
        <path id='gridToHouse' d='M 140 250 H 357' stroke='blue' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='blue'>\
            <animateMotion dur='50s' repeatCount='indefinite'>\
                <mpath href='#gridToHouse'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Solar zu Haus (Orange) -->\
        <path id='solarToHouse' d='M 260 140 A 110 100 0 0 0 358 240' stroke='orange' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='orange'>\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#solarToHouse'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Solar zu Netz (Orange) -->\
        <path id='solarToGrid' d='M 240 140 A 110 100 0 0 1 142 240' stroke='orange' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='orange' style="display: none;;">\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#solarToGrid'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Netz zu Batterie (Turkis) -->\
        <path id='gridToBattery' d='M 142 260 A 110 100 0 0 1 240 360' stroke='turquoise' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='turquoise' style="display: none;;">\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#gridToBattery'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Verbindungslinie von Batterie zu Haus (Lila) -->\
        <path id='batteryToHouse' d='M 260 359 A 110 100 0 0 1 360 260' stroke='purple' stroke-width='2' fill='transparent'/>\
        <circle r='5' fill='purple'>\
            <animateMotion dur='2s' repeatCount='indefinite' keyPoints='0;;1' keyTimes='0;;1'>\
                <mpath href='#batteryToHouse'/>\
            </animateMotion>\
        </circle>\
\
        <!-- Include the JS update script -->\
        <script xlink:href='/fhem/www/pgm2/svg_update.js'></script>\
    </svg>\
</body>\
</html>\
\

setstate myDummy 2024-10-19 11:03:37 battery 53
setstate myDummy 2024-10-19 15:10:32 grid 386
setstate myDummy 2024-10-19 10:36:27 house 500
setstate myDummy 2024-10-19 09:37:38 solar 667


2. myDummy1 [Dieser speichert einfach nur die Werte. Wird mit Javascript ausgelesen]
Die Werte entweder per setreading oder mit einem notify ändern.
defmod myDummy1 dummy
attr myDummy1 readingList battery grid house solar
attr myDummy1 room Energy
attr myDummy1 setList battery:textField grid:textField  house:textField  solar:textField

setstate myDummy1 2024-10-19 16:26:49 battery 100
setstate myDummy1 2024-10-19 16:28:32 grid 210
setstate myDummy1 2024-10-19 16:28:11 house 500
setstate myDummy1 2024-10-19 16:28:17 solar 400

3. Das Javasript -> svg_update.js[Das liest die Werte aus myDummy1]
Das Script gehört nach /opt/fhem/www/pgm2. user=fhem,group=dialout
// Funktion, um CSRF-Token aus dem Body-Element zu extrahieren
function getCsrfToken() {
    const csrfTokenElement = document.querySelector("body");
    if (csrfTokenElement) {
        return csrfTokenElement.getAttribute("fwcsrf");
    } else {
        console.error("CSRF token element not found.");
        return null;
    }
}

// Funktion zum Abrufen der Readings von der FHEM-Seite
function fetchReadings() {
    const csrfToken = getCsrfToken();
    if (!csrfToken) return;

    const fetchUrl = `/fhem?detail=myDummy1&fwcsrf=${csrfToken}`;
   
    fetch(fetchUrl)
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.text();
    })
    .then(data => {
        // Extrahiere die Werte aus der Antwort
        const parser = new DOMParser();
        const doc = parser.parseFromString(data, 'text/html');
       
        const solarReading = doc.querySelector("div[informid='myDummy1-solar']").textContent;
        const gridReading = doc.querySelector("div[informid='myDummy1-grid']").textContent;
        const batteryReading = doc.querySelector("div[informid='myDummy1-battery']").textContent;
        const houseReading = doc.querySelector("div[informid='myDummy1-house']").textContent;

        // Aktualisiere die entsprechenden SVG-Elemente
        document.getElementById('solarPower').textContent = solarReading + " W";
        document.getElementById('gridPower').textContent = gridReading + " W";
        document.getElementById('batteryPower').textContent = batteryReading + " %";
        document.getElementById('housePower').textContent = houseReading + " W";
    })
    .catch(error => {
        console.error('Error fetching data:', error);
    });
}

// Funktion zum Initialisieren und zyklischen Aktualisieren
document.addEventListener('DOMContentLoaded', function() {
    fetchReadings();
    setInterval(fetchReadings, 5000); // Aktualisiere alle 5 Sekunden
});

Edit:
Ich habe  myDummy1 nochmal um setList und readingsList erweitert. So können die Werte direkt im dummy gesetzt werden.


Gruß schwatter

schwatter

Wenn ich mir den Seitenquelltext vom Device und dazu das Device bei Raumübersicht anschaue, gelten jeweils unterschiedliche Regeln  :(

Gruß schwatter

schwatter

Oh man, ich bin so doof  ;D Da in dem Raum noch ein anderes Device, bzw ein DOIF mit den selben SVG ist, habe ich die gleichen Namen für getElementById.
Da wurd, das DOIF quasi 2mal massiert. Mein Dummy aber nicht mehr  ::) 
Alles nochmal durchtüddeln. Wenn es passt, setze ich später das Thema auf gelöst.

Gruß schwatter

frank

schau in die js konsole.
soweit ich weiss, werden in der raumübersicht nur die state events der devices gemeldet.
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

rudolfkoenig

Zitatsoweit ich weiss, werden in der raumübersicht nur die state events der devices gemeldet.

Da ist nicht der Fall.
Wie man in der JS-Console sieht, werden alle Events gemeldet, die Instanzen betreffen, die auf dieser Seite dargestellt werden.
Inwieweit diese Events fuer die Darstellung ausgewertet werden, ist eine andere Sache.

schwatter

Nabend,

es war tatsächlich so, wie ich es vermutet hatte. Die gleichen ID's bei getElementById waren das Problem.

Gruß schwatter