• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

JS Script mehrfach ausführen mit unterschiedlichen "Variablen"

Nvd126

Neues Mitglied
Hallo,

ich möchte für meine Heimautomatisierung gerne auf besondere Art und Weise anzeigen, wann ein Zustand sich das letzte mal geändert hat. Das klappt auch alles soweit. Hab da eine Vorlage gefunden und auf meine Bedürfnisse angepasst.
Javascript:
// Spezifische zu ändernde Variablen.


var name = "time_treppenhaus"
var startStamp = {knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts};


// Keine weiteren Eingaben.
var newDate = new Date();
var newStamp = newDate.getTime();
var timer;
function updateClock() {
    newDate = new Date();
    newStamp = newDate.getTime();
    var diff = Math.round((newStamp-startStamp)/1000);
    var d = Math.floor(diff/(24*60*60));
        diff = diff-(d*24*60*60);
    var h = Math.floor(diff/(60*60));
        diff = diff-(h*60*60);
    var m = Math.floor(diff/(60));
        diff = diff-(m*60);
    var s = diff;
    if (d == 0 && h == 0 && m == 0) { 
        document.getElementById(name).innerHTML ="Vor "+s+" Sekunden.";}
    else if (d == 0 && h == 0) { 
        document.getElementById(name).innerHTML ="Vor "+m+" Minuten und "+s+" Sekunden.";}
    else if (d == 0) { 
        document.getElementById(name).innerHTML ="Vor "+h+" Stunden, "+m+" Minuten.";}
    else if (d != 0) { 
        document.getElementById(name).innerHTML ="Vor "+d+" Tagen, "+h+" Stunden.";}
    }
    setInterval(updateClock, 1000);

Jetzt ist es so, dass die beiden Punkte "var name" und "var startStamp" sich immer ändern, da ich an unterschiedlichen Punkten mir die Zeit anzeigen lassen möchte.
Hier auf der "ersten" Seite wäre dies nur für die Anzeige, wann das letzte mal eine Anwesenheit festgestellt worden ist im Treppenhaus.
HTML:
<td>Letzte Anwesenheit:</td>
    <td><p class="timeklein" id="time_treppenhaus"></p>
</td>

Soweit so gut - bis jetzt funktioniert alles!

Das Problem was ich jetzt habe ist, dass sich wie erwähnt "var name" & "var startStamp" immer ändern müssen, weil....
Code:
kuche_herd
knx.0.Obergeschoss.Status.SA_A_E_Herd_schalten_status.ts

kuche_spuhlmaschine
knx.0.Obergeschoss.Status.WL_C_Spuehlmaschine_schalten_status.ts

kuche_steckdosen
knx.0.Obergeschoss.Status.SA_D_Steckdosen_Kuche_schalten_status.ts

schlafzimmer_steckdosen
knx.0.Obergeschoss.Status.SA_E_Steckdosen_Schlafzimmer_schalten_status.ts

und noch 12 weitere.......
Zur Erläuterung:
"Oben" ist jeweils der Name für die Ausgabe, welchen ich mir vorstelle. [var name]
"Unten" ist immer der Datenpunkt, welcher mir bei einem Aufruf eine Zeit ausgibt. [var startStamp].

Endergebnis der ganzen Aktion ist immer, dass an definierter Stelle beispielsweise steht:
"Steckdose - Vor 1 Stunde und 25 Minuten"


Ich verstehe nicht, wie ich jetzt es hinkriege, dass für die unterschiedlichen Positionen immer eine Berechnung der vergangenen Zeit stattfindet.
Ich habe es auch schon mit Classen probiert... aber hatte kein Erfolg dabei..
Javascript:
<div class="datenpunkt" id="knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status"></div>
<div class="datenpunkt" id="knx.0.Außenbereich.Status.SA_A_Steckdosen_Anbau_schalten_status"></div>
<script>
const collection = document.getElementsByClassName("datenpunkt");
var startStamp = {collection[0].id+".ts"}; // Geschwungene Klammern sind -manchmal- notwendig für den Zugriff auf den Datenpunkt, aber auch schon ohne Probiert. Ohne Erfolg!
var newDate = new Date();

...und so weiter ...
Bei diesem Versuch habe ich tatsächlich auch immer den Namen herausbekommen welchen ich wollte. Schien perfekt! Aber es ist immer irgendwie Text geblieben, also ich habe nie meinen Zeitstempel abrufen können.

Kurzum:
var startStamp = knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts; -> Direkt Eingeben -> FUNKTIONIERTE!
var startStamp = {collection[0].id+".ts"}; -> mit Ergebnis: knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts -> aus ID entnommen -> GEHT NICHT!


Ich hab zwar gesehen, dass es ne Lösung wäre, das Script 16x mit unterschiedlichen var Namen einzufügen... aber das geht doch bestimmt auch anders?

Nebenbei: Das ist alles nur Hobbysache bei mir, deshalb bitte ich um Nachtsicht sollte ich etwas unterirdisch schlecht erklärt haben oder ich die einfachsten Sachen nicht weiß...


Danke schon mal im voraus
 

Sempervivum

Senior HTML'ler
Hallo @Nvd126 und willkommen im Forum!
Was bedeutet denn dieses:
{knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts}
Ich vermute, das ist ein Platzhalter wo der Server dann die betr. Zeit einträgt, so dass im Browser der Timestamp ankommt, etwa so:
var startStamp = 1062076208;
 

Nvd126

Neues Mitglied
Dankeschön für die Antwort und die Begrüßung

Ja, also
Code:
{knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts}
gibt mir bspw. "1660820125000", damit das mit der Zeitrechnung klappt.
Das aufrufen eines Datenwertes ist eine Eigenheit von der Visualisierung eines Systems namens iOBroker.

Wenn das ganze jetzt noch für TS 2-16 klappen würde einfach wäre das super :D
 

Sempervivum

Senior HTML'ler
Was auf jeden Fall funktionieren müsste, ist, die Parameter name und startStamp in einem Array abzulegen, dieses in einer Schleife abzuarbeiten und die Parameter an eine Funktion zu übergeben:
Code:
        // Array mit den Daten anlegen:
        const daten = [
            ['time_treppenhaus', { knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts }],
            ['kuche_herd', startStamp: { knx.0.Obergeschoss.Status.SA_A_E_Herd_schalten_status.ts }],
            ['kuche_spuhlmaschine', { knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts }],
            // usw.
        ];
        // Das Starten des Update legen wir in eine Funktion
        // mit den Parametern name und startStamp:
        function startUpdate(name, startStamp) {
            var newDate = new Date();
            var newStamp = newDate.getTime();
            var timer;
            function updateClock() {
                newDate = new Date();
                newStamp = newDate.getTime();
                var diff = Math.round((newStamp - startStamp) / 1000);
                var d = Math.floor(diff / (24 * 60 * 60));
                diff = diff - (d * 24 * 60 * 60);
                var h = Math.floor(diff / (60 * 60));
                diff = diff - (h * 60 * 60);
                var m = Math.floor(diff / (60));
                diff = diff - (m * 60);
                var s = diff;
                if (d == 0 && h == 0 && m == 0) {
                    document.getElementById(name).innerHTML = "Vor " + s + " Sekunden.";
                }
                else if (d == 0 && h == 0) {
                    document.getElementById(name).innerHTML = "Vor " + m + " Minuten und " + s + " Sekunden.";
                }
                else if (d == 0) {
                    document.getElementById(name).innerHTML = "Vor " + h + " Stunden, " + m + " Minuten.";
                }
                else if (d != 0) {
                    document.getElementById(name).innerHTML = "Vor " + d + " Tagen, " + h + " Stunden.";
                }
            }
            setInterval(updateClock, 1000);
        }
        // Jetzt starten wir für alle Einträge im Array das Update:
        data.forEach(item => {
            // item ist das aktuelle Element im Array.
            startUpdate(
                item[0], // der Name
                item[1]  // die Startzeit "startStamp"
            );
        });
(ungetestet, wenn es nicht funktioniert müssen wir weiter sehen)
 

Sempervivum

Senior HTML'ler
Wenn ich mir das noch Mal durchlese, frage ich mich, ob das schon alles ist: Der startStamp wird ja beim Laden der Seite eingelesen. Wenn sich jedoch ein Zustand ändert, während man die Seite offen hat, wird das nicht erkannt. Wahrscheinlich muss man die Zustände zyklisch aktualisieren durch Ajax und fetch.
 

Nvd126

Neues Mitglied
Also ich habe das grade mal soweit Probiert. Sieht auf jeden Fall schon mal gut aus, auch wenns noch nicht klappt. (Arry wird angelegt, und mit console.log(daten[1][1] kriege ich auch den Zeitstempel angezeigt.)
console.log("Zeile 1 Gesamt: "+daten[1]) ---------> In der Konsole ->> Zeile 1 Gesamt: kuche_herd,1660808028246
console.log("Zeile 1 TS: "+daten[1][1]) ----------->In der Konsole: ->> Zeile 1 TS: 1660808028246

Also die ganzen Daten werden allesamt automatisch schon aktualisiert. Da ist kein weiteres zutun notwendig.

Aktuell kriege ich noch Fehler in der Ausführung der "function startUpdate(name, startStamp)". Was müsste ich denn am besten Angeben, um das nachvollziehbar gestalten zu können?

['time_treppenhaus', { knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts }],
['kuche_herd', startStamp: { knx.0.Obergeschoss.Status.SA_A_E_Herd_schalten_status.ts }],
Muss das startstamp noch in der zweiten Zeile stehen oder ist das ein versehen? Das hatte ich auf Vermutung nämlich entfernt, ändert aber nichts daran, dass es noch nicht ganz klappt.
 

Nvd126

Neues Mitglied
Mein Held! Es geht!!
data.forEach(item => { hatte nur noch ein weiteres N benötigt. :p

DANKESCHÖN!!!!!!!!!
 

Sempervivum

Senior HTML'ler
Ja, da waren noch kleinere Fehler drin, sehr gut, dass Du sie beheben konntest.
Was hältst Du denn von diesem, was ich in #5 geschrieben habe:
Wenn ich mir das noch Mal durchlese, frage ich mich, ob das schon alles ist: Der startStamp wird ja beim Laden der Seite eingelesen. Wenn sich jedoch ein Zustand ändert, während man die Seite offen hat, wird das nicht erkannt.
 

Nvd126

Neues Mitglied
Also wie ich sagte, die Zustände werden allesamt aktualisiert. Ich bin nicht so tief in der Materie. So wie ich das Überblickt habe, gibt es eine index.html, wo massenweise Sachen eingebettet werden (CSS, diverse Scripte). In diese index.html wird auch alles was ich so in HTML schreibe eingefügt. Auch meine Scripte, so wie auch dieses Zeitscript hier.

Eines der Scripte davon soll eine Websocket-Verbindung zu der (auf dem lokalen PC) befindlichen Plattform herstellen und "Zustandsänderungen abonnieren" (das hört sich glaub nicht sehr fachlich an :( ) . Ich hoffe das hört sich einigermaßen schlüssig an.

Fakt ist: Ändert sich irgendwas, was ich in meinem Projekt benutze (nur benutzte Sachen werden aktualisiert, nicht alle möglichen Zustände), dann aktualisiert sich das in maximal 1-2 Sekunden. Klappt auch sehr zuverlässig.



Ein kleineres Problemchen ist mir aber noch aufgefallen. In der Browser-Konsole gibt es etliche (teils tausende) Fehlermeldungen, die da lauten: "Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')". "Durchschnittlich" jedoch gibt es pro Sekunde, so wie halt das Intervall eingestellt ist, exakt eine Meldung.

Beispiel: Ich bin vor 10 Minuten im Treppenhaus entlang gelaufen. Das sagt mir das Script auch - alles gut soweit. Wenn ich jetzt erneut lang gehe, bin ich also vor bspw. einer Sekunde dort lang gelaufen.
Jetzt gibt es das Problem, dass nun jeweils abwechselnd mir angezeigt wird, dass ich vor 10 Minuten im Treppenhaus war und vor einer Sekunde. Der alte, jetzt irrelevante Wert von 10 Minuten wird irgendwie nicht vergessen.
Lade ich die komplette Seite neu, dann wird alles richtig angezeigt (die 10 Minuten von grade existieren dann nicht mehr), nur noch die Angabe, vor wenigen Sekunden bzw. vor einer Sekunde. Hochzählen tuen die Zeiten fehlerfrei.

Neben den Meldungen in der Konsole gibt es ansonsten noch den Eindruck, dass die Ladegeschwindigkeit der Seite etwas länger ist. Gibt es hierfür auch noch eine einfache Lösung?
 

Sempervivum

Senior HTML'ler
Eines der Scripte davon soll eine Websocket-Verbindung zu der (auf dem lokalen PC) befindlichen Plattform herstellen und "Zustandsänderungen abonnieren" (das hört sich glaub nicht sehr fachlich an :( ) . Ich hoffe das hört sich einigermaßen schlüssig an.

Fakt ist: Ändert sich irgendwas, was ich in meinem Projekt benutze (nur benutzte Sachen werden aktualisiert, nicht alle möglichen Zustände), dann aktualisiert sich das in maximal 1-2 Sekunden. Klappt auch sehr zuverlässig.
Das ist sehr gut, wenn das mit Websocket und spontaner Aktualisierung passiert können wir meinen Einwand aus Posting #4 vergessen.
Jetzt gibt es das Problem, dass nun jeweils abwechselnd mir angezeigt wird, dass ich vor 10 Minuten im Treppenhaus war und vor einer Sekunde. Der alte, jetzt irrelevante Wert von 10 Minuten wird irgendwie nicht vergessen.
Das ist dann ein Problem, was man untersuchen und lösen muss. Ich kann an diesem Wochenende nicht viel dazu beitragen, weil ich in eine Nachbarstadt zu einer Veranstaltung fahre. Sicher kann dich jemand anders dabei unterstützen.
 

Nvd126

Neues Mitglied
Jippi, ich konnt's nachvollziehbar erklären. Falls sonst niemand eine Idee dafür hat, kann ich natürlich gerne ein paar Tage warten. Das ist kein Problem. Viel Freude jedenfalls wünsche ich.

Hier nochmal der aktuelle Stand, welchen ich eingefügt habe.

Javascript:
// Array mit den Daten anlegen:
const daten = [
    ['time_treppenhaus', '{knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts}'],
    ['kuche_herd', '{knx.0.Obergeschoss.Status.SA_A_E_Herd_schalten_status.ts}'],
    ['kuche_spuhlmaschine', '{knx.0.Obergeschoss.Status.WL_C_Spuehlmaschine_schalten_status.ts}'],
    ['kuche_steckdosen', '{knx.0.Obergeschoss.Status.SA_D_Steckdosen_Kuche_schalten_status.ts}'],
    ['schlafzimmer_steckdosen', '{knx.0.Obergeschoss.Status.SA_E_Steckdosen_Schlafzimmer_schalten_status.ts}'],
    ['wohnzimmer_tv', '{knx.0.Obergeschoss.Status.WL_A_TV_Ecke_schalten_status.ts}'],
    ['wohnzimmer_steckdosen', '{knx.0.Obergeschoss.Status.SA_F_Steckdosen_Wohnzimmer_schalten_status.ts}'],
    ['flur_kamin', '{knx.0.Obergeschoss.Status.SA_I_Steckdosen_Kamin_schalten_status.ts}'],
    ['flur_steckdosen', '{knx.0.Obergeschoss.Status.SA_G_Steckdosen_Flur_schalten_status.ts}'],
    ['bad_steckdosen', '{knx.0.Obergeschoss.Status.SA_H_Steckdosen_Badezimmer_schalten_status.ts}'],
    ['eg_waschmaschine', '{knx.0.Erdgeschoss.Status.SA_B_WaMa_schalten_status.ts}'],
    ['eg_trockner', '{knx.0.Erdgeschoss.Status.SA_C_Trockner_schalten_status.ts}'],
    ['garten_anbau', '{knx.0.Außenbereich.Status.SA_A_Steckdosen_Anbau_schalten_status.ts}'],
    ['garten_terasse', '{knx.0.Außenbereich.Status.SA_D_Steckdosen_Nachbar_schalten_status.ts}'],
    ['garten_pumpe', '{knx.0.Außenbereich.Status.SA_E_Steckdosen_Pumpe_schalten_status.ts}'],
    ['garten_hochbeet', '{knx.0.Außenbereich.Status.SA_F_Ventil_Hochbeet_schalten_status.ts}'],
    ['garten_erdbeeren', '{knx.0.Außenbereich.Status.SA_G_Ventil_Erdbeeren_schalten_status.ts}']
];
////////////////
function startUpdate(name, startStamp) {
    var newDate = new Date();
    var newStamp = newDate.getTime();
    var timer;
    function updateClock() {
        newDate = new Date();
        newStamp = newDate.getTime();
        var diff = Math.round((newStamp - startStamp) / 1000);
        var d = Math.floor(diff / (24 * 60 * 60));
        diff = diff - (d * 24 * 60 * 60);
        var h = Math.floor(diff / (60 * 60));
        diff = diff - (h * 60 * 60);
        var m = Math.floor(diff / (60));
        diff = diff - (m * 60);
        var s = diff;
        if (d == 0 && h == 0 && m == 0) {
            document.getElementById(name).innerHTML = "Vor " + s + " Sekunden.";
        }
        else if (d == 0 && h == 0) {
            document.getElementById(name).innerHTML = "Vor " + m + " Minuten und " + s + " Sekunden.";
        }
        else if (d == 0) {
            document.getElementById(name).innerHTML = "Vor " + h + " Stunden, " + m + " Minuten.";
        }
        else if (d != 0) {
            document.getElementById(name).innerHTML = "Vor " + d + " Tagen, " + h + " Stunden.";
        }
    }
    setInterval(updateClock, 2500);
}
// Jetzt starten wir für alle Einträge im Array das Update:
daten.forEach(item => {
    // item ist das aktuelle Element im Array.
    startUpdate(
        item[0], // der Name
        item[1]  // die Startzeit "startStamp"
    );
});
 

Sempervivum

Senior HTML'ler
Veranstaltung war super aber die Hinfahrt mit dem 9-Euro-Ticket ein Horror.

Anscheinend hat sich niemand anders dieser Sache angenommen. Leider überblicke ich nicht ganz, wie das mit der spontanen Aktualisierung funktioniert aber wir wollen versuchen, ob wir zum Ziel kommen, ohne in dein Skript einzusteigen.

Ich stelle es mir so vor, dass wir den Timer für das zyklische Aktualisieren löschen, wenn eine neue kommt. Versuche dies:
Code:
        // Array mit den Daten anlegen:
        const daten = [
            ['time_treppenhaus', '{knx.0.Obergeschoss.Status.SA_P_Treppenhaus_Licht_schalten_status.ts}'],
            ['kuche_herd', '{knx.0.Obergeschoss.Status.SA_A_E_Herd_schalten_status.ts}'],
            ['kuche_spuhlmaschine', '{knx.0.Obergeschoss.Status.WL_C_Spuehlmaschine_schalten_status.ts}'],
            ['kuche_steckdosen', '{knx.0.Obergeschoss.Status.SA_D_Steckdosen_Kuche_schalten_status.ts}'],
            ['schlafzimmer_steckdosen', '{knx.0.Obergeschoss.Status.SA_E_Steckdosen_Schlafzimmer_schalten_status.ts}'],
            ['wohnzimmer_tv', '{knx.0.Obergeschoss.Status.WL_A_TV_Ecke_schalten_status.ts}'],
            ['wohnzimmer_steckdosen', '{knx.0.Obergeschoss.Status.SA_F_Steckdosen_Wohnzimmer_schalten_status.ts}'],
            ['flur_kamin', '{knx.0.Obergeschoss.Status.SA_I_Steckdosen_Kamin_schalten_status.ts}'],
            ['flur_steckdosen', '{knx.0.Obergeschoss.Status.SA_G_Steckdosen_Flur_schalten_status.ts}'],
            ['bad_steckdosen', '{knx.0.Obergeschoss.Status.SA_H_Steckdosen_Badezimmer_schalten_status.ts}'],
            ['eg_waschmaschine', '{knx.0.Erdgeschoss.Status.SA_B_WaMa_schalten_status.ts}'],
            ['eg_trockner', '{knx.0.Erdgeschoss.Status.SA_C_Trockner_schalten_status.ts}'],
            ['garten_anbau', '{knx.0.Außenbereich.Status.SA_A_Steckdosen_Anbau_schalten_status.ts}'],
            ['garten_terasse', '{knx.0.Außenbereich.Status.SA_D_Steckdosen_Nachbar_schalten_status.ts}'],
            ['garten_pumpe', '{knx.0.Außenbereich.Status.SA_E_Steckdosen_Pumpe_schalten_status.ts}'],
            ['garten_hochbeet', '{knx.0.Außenbereich.Status.SA_F_Ventil_Hochbeet_schalten_status.ts}'],
            ['garten_erdbeeren', '{knx.0.Außenbereich.Status.SA_G_Ventil_Erdbeeren_schalten_status.ts}']
        ];

        // Die Timer legen wir global an, damit wir sie später auch löschen können:
        let timer = {};
        ////////////////
        function startUpdate(name, startStamp) {
            var newDate = new Date();
            var newStamp = newDate.getTime();
            // var timer;
            function updateClock() {
                newDate = new Date();
                newStamp = newDate.getTime();
                var diff = Math.round((newStamp - startStamp) / 1000);
                var d = Math.floor(diff / (24 * 60 * 60));
                diff = diff - (d * 24 * 60 * 60);
                var h = Math.floor(diff / (60 * 60));
                diff = diff - (h * 60 * 60);
                var m = Math.floor(diff / (60));
                diff = diff - (m * 60);
                var s = diff;
                if (d == 0 && h == 0 && m == 0) {
                    document.getElementById(name).innerHTML = "Vor " + s + " Sekunden.";
                }
                else if (d == 0 && h == 0) {
                    document.getElementById(name).innerHTML = "Vor " + m + " Minuten und " + s + " Sekunden.";
                }
                else if (d == 0) {
                    document.getElementById(name).innerHTML = "Vor " + h + " Stunden, " + m + " Minuten.";
                }
                else if (d != 0) {
                    document.getElementById(name).innerHTML = "Vor " + d + " Tagen, " + h + " Stunden.";
                }
            }
            // Vorigen Timer für diesen Namen löschen:
            if (timer[name]) clearInterval(timer[name]);
            // Neuen Timer starten:
            timer[name] = setInterval(updateClock, 2500);
        }
        // Jetzt starten wir für alle Einträge im Array das Update:
        daten.forEach(item => {
            // item ist das aktuelle Element im Array.
            startUpdate(
                item[0], // der Name
                item[1]  // die Startzeit "startStamp"
            );
        });
 
Werbung:

Neueste Beiträge

Oben