NEWS
ICal / SayIt - Auslesen der Termine am heutigen Tag
-
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
-
Ü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]