Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. ICal / SayIt - Auslesen der Termine am heutigen Tag

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    ICal / SayIt - Auslesen der Termine am heutigen Tag

    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      tempestas last edited by

      Update 21.3 14:21:

      Nachdem ich jetzt den originären Thread gefunden habe ist mir einiges klarer geworden.

      Kalenderereignisse.heute ist ein Object mit dem Wert "heute" wobei "heute" im iCal Adapter definiert ist als Event?

      Das "Müll" Skript sucht im Gegensatz zum Geburtstagsskript gar nicht dezidiert nach dem Event "Müll" sondern liest einfach alle (!) events aus dem Kalender per "heute" ein?

      Wenn das so ist und ich ohnehin zwei getrennte Kalender benutze müsste ich beide parts quasi mit dem "Müll" Skript einlesen können?

      Das "Datum to string" scheint historisch gewachsen. Das schaue ich mir später mal in Ruhe an.

      Werde es heute abend alles mal testen, bin gespannt.

      –---------- Orginärer Post -----------------

      Hallo zusammen,

      ich habe mich, inspiriert von Pixs / skorpils und PrinzEinherz1's Skripte zum Thema Geburtstage und Müll inspirieren lassen und würde gerne wenn es geht ein Skript erstellen (bei mir wohl eher zusammenklauben), dass mir morgens im Bad via Sonos erst die Geburtstage des heutigen Tages und dann die Termine vorliest.

      Installiert sind zwei Adapter für Ical mit jeweils einem dezidierten Google Kalender, d.h. in einem Pflege ich nur Geburtstage (manuell, nur die Namen der betreffenden) und im anderen teilen meine Frau und ich die Termine, die für beide relevant sind.

      Da sie nicht so sehr häufig auf die Termine in ihrem Handy guckt, wäre es toll, wenn die Termine eben morgens vorgelesen würden.

      Aus den anderen Skripten habe ich verstanden, dass sie zum einen Events durchsuchen (d.h. ich müsste eben Events anlegen, sprich immer "Geburtstag" dazu schreiben oder "Termin"). Das brauche ich aber nicht, da ich diese Trennung ja bereits in den Kalendern vollziehe. Außerdem werden Events nach meinem verständnis der GitHub Erläuterungen zum iCal Adapter nur ausgelesen, wenn sie entweder ganztägig sind, oder eben zum passenden Zeitpunkt, oder?

      Selber schreiben kann ich Skripte nicht, nachvollziehen klappt halbwegs.

      in diesem Skript: http://forum.iobroker.net/viewtopic.php ... 51&p=30846 verstehe ich allerdings z.B. nicht, wie er dezidiert nach den Events sucht. Was müsste ich ändern, damit mir sayit einfach stumpf alles vorliest, was in den beiden Kalendern für den heutigen Tag enthalten ist?

      Gerne lerne ich auch "on the run" sprich sanftes pushen in die Richtung, dann probiere ich mich mal aus. Es muss nicht das gemachte Nest sein, aber dagegen hätte ich auch nichts. 😉

      Danke und Grüße

      tempestas

      1 Reply Last reply Reply Quote 0
      • T
        tempestas last edited by

        Übersichtlicher formatiert (hoffe ich)

        Um auch Eigeninitiative zu zeigen hier mal der Code von Pix/PrinzEisenherz1, den ich als Basis nutzen möchte. Da mein JS Verständnis noch eher rudimentär ist (wenn überhaupt), habe ich als Kommentare eingetragen, was ich denke/verstehe, was dort passiert. Eventuell könnte mir jemand auf dieser Basis dann Hinweise geben, was ich wie ändern muss? Ich lerne gerne 🙂

        Ich habe mich mit diesem tollen Thread http://forum.iobroker.net/viewtopic.php?f=21&t=3926 sowie https://www.w3schools.com und https://www.mediaevent.de/javascript/ beschäftigt, um das Skript so gut ich kann zu verstehen. Allerdings liegen meine letzten Programmierversuche in der Jugend, was so ca 20 Jahre her ist. Seitdem habe ich mich nicht mehr damit beschäftigt.

        // Test mit Variable;
        // Besser ist es, gleich den Bewegungsmelder hier abzufragen.
        var idSayVar = 'javascript.0.Sayit.Trigger';   
        

        // hier würde ich wie vorgeschlagen direkt auf meinen BWM verweisen. in einem einfacheren Skript funktiniert das auch

        // Definition
        var idSayIt =            "sayit.0.tts.text";             
        var lautstaerke = 100  
        
        

        // hier Ansprechen der SayIt Instanz 0, die dann ausgegeben wird (z.B. übeR sonos) -das läuft auch soweit bei mir sowie setzen der Lautstärke als Variable

        // Quellen
        var idWetter =           "hm-rega.0.23460"; 
        

        // entfällt bei mir, nutze ich nicht

        var idTemperatursensor = "hm-rega.0.23642";  
        

        // hier verweise ich auf meinen entsprechenden Homematic Außensensor. Läuft auch

        var idGeburtstage =      "javascript.0.Kalenderereignisse.heute";   
        var idMuell =            "javascript.0.Muellereignisse.heute"; 
        

        /* javascript.0 verweist auf die JS Instanz, hier 0. Kalenderereignisse.heute sowie Muellereignisse.heute sind states, die weiter unten definiert werden. Fragen dazu dann dort. */

        function ermitteleAnsagedatum () {
            //Wochentag ermitteln
            var d = new Date ();                   
            var w = new Array("Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"); 
            var wochentag = w[d.getDay()];  
          //Tagesdatum ermitteln
            var tag = d.getDate();
        
        

        // Variable d wird definiert als ein neu erzeugtes Datum, wobei das "()" bedeuted, dass immer das aktuelle Datum eingelesen wird

        // Wie zuvor, nur wird ein Array erstellt und gefüllt

        // Hier wird der String, Z.B. "Montag" anhand des Tages zugeordnet. D.h. wenn Variable "w" = 1 dann "Montag". Das "d" bei "d.getDay()" wurde zuvor als neues Datum definiert, daher funktioniert das hier so.

        // Dann wird das eigentliche Datum ausgelesen, damit später ausgegeben wird "Montag, der 2te …"

          //Monat ermitteln
            var month = new Array("Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember");
            var monat = month[d.getMonth()];  
            //Jahr ermitteln
            var jahr = d.getFullYear();  
            //Stunde ermitteln
            var stunde = d.getHours();     
            //Minute ermitteln
            var minute = d.getMinutes();  
        
        

        // Wie beim Tagesdatum, aber natrülich ohne die nochmalige Abfrage der "Monatszahl", da man ja nicht "Monat 12 Dezember" sagt.

        // Jahr wird ausgewertet und in die Variable eingefügt

        // Stunde wird ausgewertet und in die Variable eingefügt

        // Minute wird ausgewertet und in die Variable eingefügt

            return { // zurückgeben        
                'Jahr'      : jahr,
                'Monat'     : monat,
                'Tag'       : tag,
                'Wochentag' : wochentag,
                'Stunde'    : stunde,
                'Minute'    : minute
            };
        }
        
        

        // Das hier verstehe ich leider nicht ganz. Ich sehe, dass die in Hochkommata gesetzten Werte später im ansagetext genutzt werden, aber wieso so? Was ganz genau passiert hier? Der Ansagetext bezieht sich jeweils auf die function.WERT [z.B. Jahr]. Warum muss ich die function ansprechen und nicht direkt die Variable ?

        `function ermitteleWetter () { // Wetterbedingungen       [color]
          var wetterdaten = getState(idWetter).val;
            log('Wetter: ' + wetterdaten);
            return(wetterdaten);
        }
        
        function ermitteleAnsageTemperatur () {
            // Die Außentemperatur ist xx. Das Wetter heute ist xx
            // Einfache Temperaturansage mit SayIt.
            // Variante 1 mittels splitten der Temperatur, damit die Ansage nicht
            // "Es sind 18 Punkt 2 Grad " sagt.
        
            var temperatursensor = getState(idTemperatursensor).val;` 
        // Hier hätte ich erwartet, dass es "getState("hm-rpc.0.xxxxxxxxx.1.TEMPERATURE"); lautet bzw das oben bereits so definiert werden würde? Oder wird in diesem Skript ein reiner Temperaturfühler angesprochen und der Verweis auf den Temperaturdatenpunkt ist damit hinfällig? (in meinem Fall könnte ja auch humidity abgefragt werden)
        
        `~~[code]~~   
         var temp_string = temperatursensor.toString(); [/code]`
         //kann " temperatursensor.**~~[b]~~val[/b]**.toString()  " das "val" entfallen, weil ja bereits vorher abgefragt? 
          `~~[code]~~  log('Temp  ' + temp_string);
            var temp_array = [];                        
            temp_array = temp_string.split(".");    
        [/code]`
        // die eckigen Klammern definieren einen array-index (d.h. der array wird durchnummeriert beginnend mit 0)   
        
        // hier wird definiert, dass "temp_array" befüllt wird mit zwei Teilen aus derausgelesenen Temperatur, nämlich vor und nach dem Punkt 
        `~~[code]~~    // Fange leere Nachkommastellen ab. Das passiert, wenn die Temperatur z. B. 18.0 ist.
            // Es wird dann nur "18" gelesen.
            if (!temp_array[1]) {            [        temp_array[1] = "0";
                log("Die Nach-Kommastelle in temp_array[1] war nicht vorhanden und wird nun fest auf 0 gesetzt.");
            }
            return{
                'Ganzzahl'      : temp_array[0 
                'Nachkommazahl' : temp_array[1]
            };
        }
        [/code]`
        color=#BF0000] // Wenn falsy (weil leer), dann setze 0\. Bei Ganzzahlen ist der zweite (d.h. Abfrage 1) index des Arrays leer und wird auf 0 gesetzt, damit der Array befüllt ist ]
        
         // Vorkommastelle wird aus erstem Array Teil bestimmt, Nachkomma aus zweitem
        
        `~~[code]~~function ermitteleGeburtstage () {                                
            var geburtstage = getState(idGeburtstage).val;       
            log(geburtstage);
            return (geburtstage);
        }
         [/code]`
        
        // Ab hier fange ich deutlich an zu straucheln 
        
         /* die Variable "geburtstage" wird befüllt mit dem Wert (val) aus idGeburtstage (eingangs definiert), welche wiederum weiter unten mit createState erschaffen wird? Die function "ermitteleGeburtstage" erhält den Wert aus "geburtstage" und wird dann im Ansagetext angesprochen? Wäre jemand so freundlich, mir den ganz genauen Sinn / Grund für dieses Vorgehen zu erläutern ? */ 
        `~~[code]~~function ermitteleMuell () {
            var muell = getState(idMuell).val;
            log(muell);
            return (muell);
         }
           [/code]`
            // Analog Geburtstage 
        
        `~~[code]~~// ################################### 
        // Trigger für Ansage
        // ###################################
        
        on(idSayVar, function (data) {                 
        
            var ansagetext = "Guten Morgen, heute ist " + ermitteleAnsagedatum().Wochentag + " der " + ermitteleAnsagedatum().Tag + "te " + ermitteleAnsagedatum().Monat + ' ' + ermitteleAnsagedatum().Jahr 
                    + ". Es ist" + ermitteleAnsagedatum().Stunde + "  Uhr und " + ermitteleAnsagedatum().Minute + "  Minuten." 
                    + " Die Aussentemperatur beträgt " + ermitteleAnsageTemperatur().Ganzzahl + "," + ermitteleAnsageTemperatur().Nachkommazahl + " Grad." 
                    + " Wetter Bedingungen," + ermitteleWetter() +" .";
        
        // ####################################################
        // Wenn Geburtstag dann mit ansagen
        // ####################################################
            var geburtstage2 = getState(idGeburtstage).val;
            if (geburtstage2.length > 2) { // wenn der Inhalt des Objektes "idGeburtstage" weniger als 2 Zeichen lang ist (also praktisch leer), dann ...
                ansagetext = ansagetext + "Nicht vergessen, " + ermitteleGeburtstage() +" .";
           }
        
        // ####################################################
        // Wenn Müll dann mit ansagen
        // ####################################################
           var muell2 = getState(idMuell).val;
            if (muell2.length > 2) { // wenn der Inhalt des Objektes "idMuell" weniger als 2 Zeichen lang ist (also praktisch leer), dann ...
                ansagetext = ansagetext + "Achtung, heute ist Abholung " + ermitteleMuell() +" .";
            }         
        
            log('Trigger: ' + data.state.val);                                 
            if (data.state.val === true) {
                setState(idSayIt, lautstaerke + ";" + ansagetext);  // hier also ("40;Guten Morgen ...")
            }
        }); [/code]`
        // Wenn (bei mir) BWM ausgelöst dann wird der Text aus den einzelnen functions bzw deren Datenwerten zusammengesetzt. Nehme gerne nochmal Erläuterungen zu diesem Teil in genauerer Art, da ich nicht ganz sicher bin, den Code wirklich zu verstehen             
        
        // Im letzten Teil (log ..) wird der vollständige Ansagetext samt Zeillautstärke in das Log geschrieben 
        
        `~~[code]~~/* Kalenderevent auswerten ----> nur Geburtstage
        
        sucht im iCal Adapter nach events (heute)
        auf Anfrage von Skorpil im Forum erstellt.
        http://forum.iobroker.de/viewtopic.php?f=21&t=2347&p=20627&sid=524f9dda2f313d3cbb183941df61fc38#p20627
        
        27.02.2016 erstellt von Pix
        02.03.2016 Anpassung und Aufbereitung für Sprachausgabe
        21.07.2016 Umbau auf Müll  Kalender
        */
        
        //Datum als String ermitteln;
        function ermitteleDatum() {
            var d= new Date();
        
            //Tagesdatum ermitteln
                var day = new Array("00","01","02","03","04","05","06","07","06","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31");
                var t = day[d.getDate().toString()];
        
            //Monat ermitteln
                var month = new Array("01","02","03","04","05","06","07","08","09","10","11","12");
                var m = month[d.getMonth().toString()];
        
            //Jahr ermitteln
                var j = d.getFullYear().toString();
        
            var datum= t+"."+m+"."+j+" ";
            //log("datum:   " + datum);
            return (datum);
        }
        createState('Kalenderereignisse.heute', '', {     
            name: 'Events von heute',                        // Wird hier der Name geändert? Falls ja, wieso? Falls nein: was passiert hier genau? Freue mich  
            type: 'string'
        });
        [/code]`
        Fragen:  wieso muss dasTagesdatum als String evaluiert werden?
        
        Könnte mir jemand den „createState“ Teil näher erläutern? Ich verstehe es so:  erzeugen der Variable "Kalenderereignisse" mit Wert "heute", welcher nachfolgend evaluiert wird. Warum muss das hier über createState gemacht werden? 
        
        /* Nachfolgend verlässt es mich völlig. Ich habe verstanden, dass das Skript insgesamt doch nach dem "event" Geburtstag sucht. Wo finde ich das? Bin für eine Erklärung, was in den nachfolgenden Zeilen passiert sehr dankbar *
        `~~[code]~~var idListe =  'Kalenderereignisse.heute';                                 
        
        function pruefeKalender() {
            var inhalt = getState('ical.2.data.table').val;
            var heute = ermitteleDatum();
            try{
                var ereignisse = JSON.stringify(inhalt, null, 2); // Ausgabe als String
                log(ereignisse);
                var ereignisheute = '', // Liste (kommasepariert)
                    ereignisheute_zeilen = ''; // Liste (mit Zeilenumbruch, zB für Anzeige in VIS)
                for(var i = 0; i <inhalt.length; i++)/{/alle/events/durchgehen/if/(/(inhalt[i].date.indexof(heute)/!="-1)" ||/(inhalt[i].date.indexof('heute')/)/strings/datum/oder/relatives/(nicht/nicht)/gefunden/var/ereignis="inhalt[i].event;" komma/im/namen/ersetzen="">0) ? ', ' : '';
                        ereignisheute = ereignisheute + komma + ereignis;
                    } 
                }
                // Aufbereitung für die Ansage (falls vorhanden, wird letztes Komma durch und ersetzt)
                var lastkomma = ereignisheute.lastIndexOf(','); // letztes Komma in der Reihe
                if (lastkomma != -1) {
                   var vorn = ereignisheute.slice(0,lastkomma-1);
                   var hinten = ereignisheute.slice(lastkomma+1, ereignisheute.length);
                   ereignisheute = vorn + ' und' + hinten;
                }
                // Ende Aufbereitung für die Ansage
        
                setState(idListe, ereignisheute);
                log('Geburtstage: ' + ereignisheute);
            } catch (fehler_try) {
                log('Fehler beim Kalenderevent einlesen ' + fehler_try);
            }
        }</inhalt.length;>` 
        /*Müll  Ignoriert bis ich den Geburtstagsteil verstanden habe */  
        `~~[code]~~// neuer Teil für Müllkalender 
        
        createState('Muellereignisse.heute', '', {
            name: 'Müll-Events von heute',
            type: 'string'
        });
        
        var idListe2 = "Muellereignisse.heute";
        
        function pruefeKalender2() {
            var inhalt2 = getState('ical.1.data.table').val;
            var heute2 = ermitteleDatum();
            try{
                var ereignisse2 = JSON.stringify(inhalt2, null, 2); // Ausgabe als String
                log(ereignisse2);
                var ereignisheute2 = '', // Liste (kommasepariert)
                    ereignisheute2_zeilen = ''; // Liste (mit Zeilenumbruch, zB für Anzeige in VIS)
                for(var i = 0; i <inhalt2.length; i++)/{/alle/events/durchgehen/if/(/(inhalt2[i].date.indexof(heute2)/!="-1)" ||/(inhalt2[i].date.indexof('heute')/)/strings/datum/oder/relatives/(nicht/nicht)/gefunden/var/ereignis2="inhalt2[i].event;" komma/im/namen/ersetzen="">0) ? ', ' : '';
                        ereignisheute2 = ereignisheute2 + komma + ereignis2;
                    } 
                }
                // Aufbereitung für die Ansage (falls vorhanden, wird letztes Komma durch und ersetzt)
                var lastkomma = ereignisheute2.lastIndexOf(','); // letztes Komma in der Reihe
                if (lastkomma != -1) {
                   var vorn = ereignisheute2.slice(0,lastkomma-1);
                   var hinten = ereignisheute2.slice(lastkomma+1, ereignisheute2.length);
                   ereignisheute2 = vorn + ' und' + hinten;
                }
                // Ende Aufbereitung für die Ansage
        
                setState(idListe2, ereignisheute2);
                log('Müll: ' + ereignisheute2);
            } catch (fehler_try) {
                log('Fehler beim Müll-Kalenderevent einlesen ' + fehler_try);
            }
        }</inhalt2.length;>` 
        Im letzten Teil wird die iCal Instanz 2 angesprochen und das zu suchende Event "Geburtstag" definiert. Korrekt? 
        `~~[code]~~// bei Aktualisierung des Kalenders                           
        on ({id:'ical.2.events.Geburtstag', change: 'any'}, function(data) {
            pruefeKalender();
        });
        on ({id:/\ical.1.events.$/, change: 'any'}, function(data) { // jedes Objekt im ical.1
            pruefeKalender2();
        });
        
        //bei Skriptstart
        schedule("5 0 * * *", function () {
        log("===>Wird einmal am Tag ausgelöst"); 
        pruefeKalender();
        pruefeKalender2();
        });
        [/code]`[/i][/i][/i][/code][/i][/i][/i][/code][/color]
        
        1 Reply Last reply Reply Quote 0
        • First post
          Last post

        Support us

        ioBroker
        Community Adapters
        Donate

        598
        Online

        31.7k
        Users

        79.8k
        Topics

        1.3m
        Posts

        1
        2
        1238
        Loading More Posts
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes
        Reply
        • Reply as topic
        Log in to reply
        Community
        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
        The ioBroker Community 2014-2023
        logo