Ü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]