//Version 13.6
//nachbearbeitet von ticaki
/*
*/
/* ************************************************************************* */
/* Script zum Übertragen der DWD-Wetterwarnungen über */
/* Telegram, Pushover, Home24-Mediaplayer oder SayIt */
/* mit freundlicher Unterstützung von Paul53 (Tausend Dank nochmals) */
/* Stand: 130022017 PrinzEisenherz1 */
/* */
/* */
/* */
/* ************************************************************************* */
/* ************************************************************************* */
/* NICHT EDITIEREN */
var konstanten = [
{"name":'telegram',"value":1},
{"name":'pushover',"value":2},
{"name":'email',"value":4},
{"name":'sayit',"value":8},
{"name":'home24',"value":16},
{"name":'alexa',"value":32},
{"name":'state',"value":64},
{"name":'iogo',"value":128}
];
const TELEGRAM = konstanten[0].value;
const PUSHOVER = konstanten[1].value;
const EMAIL = konstanten[2].value;
const SAYIT = konstanten[3].value;
const HOMETWO = konstanten[4].value;
const ALEXA = konstanten[5].value;
const STATE = konstanten[6].value;
const IOGO = konstanten[7].value;
var pushdienst=0;
/* ************************************************************************* */
/* Konfiguration ab hier */
/* ************************************************************************* */
/* Konfiguration der zu nutzenden Ausgabe um //pushdienst+= PUSHOVER; zu aktivieren, bitte die // enfernen, also pushdienst+= PUSHOVER; */
//pushdienst+= TELEGRAM; // Auskommentieren zum aktivieren
//pushdienst+= PUSHOVER; // Auskommentieren zum aktivieren
//pushdienst+= EMAIL; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen
//pushdienst+= SAYIT; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen
//pushdienst+= HOMETWO; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen
//pushdienst+= ALEXA; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen
//pushdienst+= STATE; // Auskommentieren zum aktivieren. State befindet sich unter onClickMessageState.message
//pushdienst+= IOGO; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen
/* Einstellungen zur Emailbenachrichtigung*/
var senderEmailID = ""; // mit Sender Emailadresse füllen. email Adapter muß installiert sein
var empfaengerEmailID = "";// mit Empfänger Emailadresse füllen.
/* Konfiguration Sprachausgabe über Home24-Mediaplayer */
var idMediaplayer = "192.168.178.68:50000"; // Eingabe IP-Adresse incl. Port für Home24-Mediaplayer
/* Konfiguration Sprachausgabe über SayIt */
var idSayIt = "sayit.0.tts.text";
var lautstaerke = 60;
//Konfiguration Sprachausgabe über Alexa
var idAlexaSerial =''; // die reine Seriennummer des Echos z.B.: var idAlexaSerial ='G090RV32984110Y';
var alexaVolumen = 40; // Lautstärke 0-100 (denke ich :) )
//Konfiguration von ioGo
var ioGoUser = ''; // Einzelnutzer 'Hans'; Multinutzer ['Hans','Peter']; Nutzer vom Adapter übernehmen '';
//StatePfad um Mitteilungen auszulösen darunter werden jeweils Punkte für jede Ausgabemöglichkeit erstellt.
var onClickMessageState = 'javascript.0.DWD_Script.'; // abschließender Punkt . nicht vergessen
// Filtereinstellungen
const minlevel = 0 // Warnungen gleich oder unterhalb dieses Levels nicht senden;
const maxhoehe = 1410 // Warnung für eine Höhe oberhalb dieses Wertes nicht senden
//Formatierungsstring für Datum/Zeit Alternative "TT.MM.YYYY SS:mm" KEINE Anpassung nötig
const formatierungString = "TT.MM.YYYY SS:mm";
// Sprachausgabe Zeiten
// Für durchgehende Sprachausgabe die Einstellung der Zeiten auf '' setzen. z.B. var startTimeSpeak = '';
var startTimeSpeak = '6:45';// Zeiten mo-fr ab der Sprachausgaben ok sind. Nicht unter 6 Uhr gehen oder den Schedule ändern
var startTimeSpeakWeekend = '9:00';// sa + so Bemerkung siehe oben
var endTimeSpeak = '22:30'; // ab diesem Zeitpunkt gibt es keine Sprachausgabe
// Automatikmodus auschalten
var autoMode = true;
//Auslösen der Pushnachricht über States ignoriert Sprachausgabezeiten
var forcedSpeak = false;
// ignoriere Warnmeldungen von geringerer Schwere, wenn ansonsten vergleichbare Warnmeldungen vorliegen.
var SkipDuplicates = true;
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
/* Konfiguration Ende */
/* ************************************************************************* */
/* Keine Anpassungen ab hier, außer du weißt was du tuest */
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
var idAlexa = 'alexa2.0.Echo-Devices.'+idAlexaSerial+'.Commands.announcement';
var idAlexaVolumen = 'alexa2.0.Echo-Devices.'+idAlexaSerial+'.Commands.speak-volume';
var forceSpeak = false;
/* Arrays festlegen */
const InitArrayLenght = 9;
var newDescriptions = [InitArrayLenght];
var oldDescriptions = [InitArrayLenght];
var newHeadlines = [InitArrayLenght];
var oldHeadlines = [InitArrayLenght];
var newBegins = [InitArrayLenght];
var oldBegins = [InitArrayLenght];
var newEnds = [InitArrayLenght];
var oldEnds = [InitArrayLenght];
var newInstruction = [InitArrayLenght];
var oldData = [InitArrayLenght];
var newData = [InitArrayLenght];
var timer = null;
/* erstmaliges Befüllen der arrays */
for (let a=0;a<InitArrayLenght;a++) {
var id = "dwd.0.warning";
if (a!=0) id+=a.toString();
id+='.object';
var warn = {};
if (existsState(id)) warn = JSON.parse(getState(id).val);
warn = convertJsonDWD(warn);
newDescriptions[a] = warn.description;
oldDescriptions[a] = warn.description;
newHeadlines[a] = warn.headline;
oldHeadlines[a] = warn.headline;
newBegins[a] = warn.start;
oldBegins[a] = warn.start;
newEnds[a] = warn.end;
oldEnds[a] = warn.end;
newData[a] = {"level":warn.level,"type":warn.type};
oldData[a] = {"level":warn.level,"type":warn.type};
}
// State der Pushnachrichten über pushover/telegram spiegelt
const mirrorMessageState = onClickMessageState+'message';
if (!existsState(mirrorMessageState)) {
createState(mirrorMessageState,'', {
read: true,
write: false,
desc: "Beschreibung",
type: "string",
});
}
// State über den man gesonderte Aktionen auslösen kann, gibt die höchste Warnstufe aus.
const AlertState = onClickMessageState+'alertlevel';
if (!existsState(AlertState)) {
createState(AlertState,0, {
read: true,
write: false,
desc: "Beschreibung",
type: "number"
});
} else {
let AlertLevel = -1;
newData.forEach((item, i) => {if (AlertLevel<item.level) AlertLevel = item.level;});
oldData.forEach((item, i) => {if (AlertLevel<item.level) AlertLevel = item.level;});
setState(AlertState,AlertLevel);
}
// Nachrichtenversand per Click States erzeugen und subscript
for (var a=0;a<konstanten.length;a++){
if (!existsState(onClickMessageState+'Commands.'+konstanten[a].name)) {
createState(onClickMessageState+'Commands.'+konstanten[a].name,false, {
read: true,
write: true,
desc: "Beschreibung",
type: "boolean",
def: false
});
}
if (existsState(onClickMessageState+'Commands.'+konstanten[a].name)){
subscribe({id: onClickMessageState+'Commands.'+konstanten[a].name},function(obj){
if (!obj.state.val) return;
setState(obj.id,false,true);
let b = obj.id.split('.');
let d = konstanten.findIndex(function(c){return (c.name===b[b.length-1]);})
if (d == -1) {log('Fehler. State nicht in Konstanten enthalten','error'); return;}
if ((pushdienst & konstanten[d].value) == 0) return;
let oldPushdienst = pushdienst;
pushdienst = konstanten[d].value*1;
let tempHeadlines = oldHeadlines.slice();
let tempDescriptions = oldDescriptions.slice();
let tempBegins = oldBegins.slice();
let tempEnds = oldEnds.slice();
for (let i=0;i<oldDescriptions.length;i++) {
oldHeadlines[i] = '';
oldDescriptions[i] = '';
oldBegins[i] = '';
oldEnds[i] = '';
}
forceSpeak = forcedSpeak;
check();
forceSpeak = false;
pushdienst = oldPushdienst;
// sollte überflüssig sein
//oldHeadlines = tempHeadlines.slice();
//oldDescriptions = tempDescriptions.slice();
//oldBegins = tempBegins.slice();
//oldEnds = tempEnds.slice();
})
}
}
// Zeitsteuerung für SayIt & Alexa
var START = new Date();
var ENDE = new Date();
setWeekend();
function setWeekend()
{
if (forceSpeak) return;
let date = new Date();
let n = date.getDay();
let weekend = 0;
weekend = (n === 0 || n == 6) ? 1 : 0;
let d = new Date();
if(weekend == 1){ // wenn Wochenende, dann setze Start auf 9h, sonst 6:45h
var e = startTimeSpeakWeekend.split(':');
d.setHours(e[0]);
d.setMinutes(e[1]);
d.setSeconds(0);
START = d;
}
else{
var e = startTimeSpeak.split(':');
d.setHours(e[0]);
d.setMinutes(e[1]);
d.setSeconds(0);
START = d;
}
var e = endTimeSpeak.split(':');
ENDE = new Date();
ENDE.setHours(e[0]);
ENDE.setMinutes(e[1]);
ENDE.setSeconds(0);
}
function check() {
if (!forcedSpeak) forceSpeak = (!startTimeSpeakWeekend||!startTimeSpeak||!endTimeSpeak);
setWeekend();
// Werfe doppelte Nachrichten raus
if(SkipDuplicates && newDescriptions.findIndex(function(a){return (!a);})!=-1 ) {
for (let a=0; a<newData.length;a++) {
if (newData[a].type==-1) continue;
for (let b=0; b<newData.length;b++) {
if (newData[b].type==-1) continue;
if (
(
a!=b
&& newData[b].type!=-1 // vergleiche neue Daten mit neuen Daten
&& newData[a].type == newData[b].type
&& newData[a].level <= newData[b].level
&& newBegins[a] >= newBegins[b]
&& newEnds[a] <= newEnds[b]
)||(
oldData[b].type!=-1 // vergleiche neue Daten mit alten Daten
&& newData[a].type == oldData[b].type
&& newData[a].level <= oldData[b].level
&& newEnds[a] < oldEnds[b]
)
) { // lösche Daten da diese eine niedrigeres level haben
newDescriptions[a] = '';
newHeadlines[a] = '';
newBegins[a] = '';
newEnds[a] = '';
newData[a].type = -1;
newData[a].level = -1;
}
}
}
}
let AlertLevel = -1;
newData.forEach((item, i) => {if (AlertLevel<item.level) AlertLevel = item.level;});
oldData.forEach((item, i) => {if (AlertLevel<item.level) AlertLevel = item.level;});
setState(AlertState,AlertLevel);
/* Bereich für 'Alle Wetterwarnungen wurden aufgehoben' */
if(newDescriptions.findIndex(function(a){return (!!a);})==-1 && oldDescriptions.findIndex(function(a){return (!!a);})!=-1) {
MeldungSpracheDWD = 'Achtung' + ' . ' + 'Alle Warnmeldungen des DWD wurden aufgehoben';
/* Bereich für Sprachausgabe über SayIt & Alexa & Home24*/
if ( forceSpeak || compareTime(START, ENDE, 'between')){ // Ansage über Sayit nur im definierten Zeitbereich
if ((pushdienst & SAYIT)!=0) {
setState(idSayIt, lautstaerke + ";" + MeldungSpracheDWD);
}
if ((pushdienst & ALEXA)!=0) {
setState(idAlexaVolumen, alexaVolumen);
setState(idAlexa, MeldungSpracheDWD);
}
if((pushdienst & HOMETWO)!=0 ){
var Url = "http://" + idMediaplayer + "/track=4fachgong.mp3|tts=" + MeldungSpracheDWD;
request(Url);
}
}
let pushmsg = 'Alle Warnmeldungen des DWD wurden aufgehoben';
if ((pushdienst & TELEGRAM)!=0 ) {
sendTo ("telegram.0", pushmsg);
}
if ((pushdienst & PUSHOVER)!=0 ) {
sendTo("pushover.0", pushmsg);
}
if ((pushdienst & IOGO)!=0 ) {
sendioGo('Wetterentwarnung', pushmsg);
}
if ((pushdienst & STATE)!=0 ) {
setState(mirrorMessageState, pushmsg);
}
if ((pushdienst & EMAIL)!=0 && senderEmailID != '' && empfaengerEmailID !='') {
sendEmail('Wetterentwarnung des DWD(iobroker)',pushmsg);
}
/* alle Sicherungen Wetterwarnung löschen */
oldHeadlines = newHeadlines.slice();
oldDescriptions = newDescriptions.slice();
oldBegins = newBegins.slice();
oldEnds = newEnds.slice();
oldData = newData.slice();
return;
}
/* Variablen für Meldungen Text */
var MeldungNew = '';
/* Variablen für Meldungen Sprache */
var MeldungSpracheDWD = '';
var MeldungNewSprache = '';
var MeldungOldSprache = '';
var AllEmailMsg = '';
var AllEmailMsgDelete = '';
var headline;
var description;
var begin;
var end;
var i;
var warn;
/* Bereich für 'Wetterwarnung gültig bis wurde aufgehoben' */
for(i = 0; i < newDescriptions.length; i++) {
headline = oldHeadlines[i];
description = oldDescriptions[i];
begin = oldBegins[i];
end = oldEnds[i];
if(description !== undefined && headline !== undefined && description !== '' && newDescriptions.indexOf(description) == -1 ) {
MeldungOldSprache = headline + ' gültig bis ' + getFormatDateSpeak(end) + ' Uhr wurde aufgehoben' + ' . ';
let pushmsg = "Die Wetterwarnung " +"'"+ headline + " gültig bis " + end + "'" + " des DWD wurde aufgehoben";
if ((pushdienst & TELEGRAM)!=0) {
sendTo ("telegram.0", pushmsg);
}
if ((pushdienst & PUSHOVER)!=0) {
sendTo("pushover.0", pushmsg);
}
if ((pushdienst & IOGO)!=0) {
sendioGo('Wetterentwarnung',pushmsg);
}
if ((pushdienst & STATE)!=0 ) {
setState(mirrorMessageState, pushmsg);
}
if ((pushdienst & EMAIL)!=0 && senderEmailID!= '' && empfaengerEmailID!='') {
AllEmailMsgDelete+=pushmsg+'\n\n';
}
/* Verknüpfen aller aufgehobenen Wetterwarnungen */
if(MeldungOldSprache !== "" && MeldungOldSprache !== undefined){
MeldungSpracheDWD = MeldungSpracheDWD + MeldungOldSprache;
}
}
}
/* Bereich für 'Neue Amtliche Wetterwarnung' */
for(i = 0; i < newDescriptions.length; i++) {
headline = newHeadlines[i];
description = newDescriptions[i];
begin = newBegins[i];
end = newEnds[i];
var instruction = newInstruction[i];
if(description !== undefined && description !== "" && oldDescriptions.indexOf(description) == -1 ) {
MeldungNew = headline + "\ngültig vom " + begin + " Uhr bis " + end + " Uhr\n" + description;
if (!!instruction && typeof instruction === 'string' && instruction.length > 2) MeldungNew+='\nHandlungsanweisungen: '+instruction;
/* Entfernen °C für Sprachausgabe */
var replaceDescription0 = entferneDatenpunkt(description);
MeldungNewSprache = headline + " gültig vom " + getFormatDateSpeak(begin) + " Uhr, bis " + getFormatDateSpeak(end) + " Uhr. " + replaceDescription0 + ' . ';
if (!!instruction && typeof instruction === 'string' && instruction.length > 2) MeldungNewSprache+='Handlungsanweisungen: '+instruction;
if ((pushdienst & TELEGRAM)!=0) {
sendTo ("telegram.0", MeldungNew);
}
if ((pushdienst & PUSHOVER)!=0) {
sendTo("pushover.0", MeldungNew);
}
if ((pushdienst & IOGO)!=0) {
sendioGo('Wetterwarnung',MeldungNew);
}
if ((pushdienst & STATE)!=0 ) {
setState(mirrorMessageState,MeldungNew);
}
if ((pushdienst & EMAIL)!=0 && senderEmailID!= '' && empfaengerEmailID!='') {
AllEmailMsg+=MeldungNew+'\n\n';
}
/* Verknüpfen aller neuen Warnmeldungen */
if(MeldungNewSprache !== "" && MeldungNewSprache !== undefined){
MeldungSpracheDWD = MeldungSpracheDWD + MeldungNewSprache;
}
}
}
/* Verknüpfen aller neuen und abgelaufenen Warnmeldungen */
MeldungSpracheDWD = 'Achtung . ' + MeldungSpracheDWD;
/* Bereich für Sprachausgabe über Home24-Mediaplayer */
if((forceSpeak || compareTime(START, ENDE, 'between') ) && (pushdienst & HOMETWO)!=0 && (MeldungSpracheDWD !== "" )){
var Url2 = "http://" + idMediaplayer + "/track=4fachgong.mp3|tts=" + MeldungSpracheDWD;
log('Url2 :' + Url2);
request(Url2);
}
/* Bereich für Sprachausgabe über SayIt + Alexa */
if (MeldungSpracheDWD !== "" && (forceSpeak || compareTime(START, ENDE, 'between'))){
if ((pushdienst & SAYIT)!=0) setState(idSayIt, lautstaerke + ";" + MeldungSpracheDWD);
if ((pushdienst & ALEXA)!=0) {
setState(idAlexaVolumen, alexaVolumen);
setState(idAlexa, MeldungSpracheDWD);
}
}
AllEmailMsg+=AllEmailMsgDelete;
if ((pushdienst & EMAIL)!=0 && senderEmailID != '' && empfaengerEmailID != '' && AllEmailMsg != '') {
sendEmail("Wetterwarnungen des DWD(iobroker)",AllEmailMsg);
}
/* Neue Werte sichern */
oldHeadlines = newHeadlines.slice();
oldDescriptions = newDescriptions.slice();
oldBegins = newBegins.slice();
oldEnds = newEnds.slice();
oldData = newData.slice();
}
/* Entfernt "°C" aus Sprachmeldung und ersetzt es durch "Grad" */
function entferneDatenpunkt(beschreibung) {
var rueckgabe;
rueckgabe = beschreibung;
try {
rueckgabe = rueckgabe.replace(/\°C/g, "Grad");
rueckgabe = rueckgabe.replace(/\km\/h/g, "Kilometer pro Stunde");
rueckgabe = rueckgabe.replace(/\kn/g, " Knoten");
rueckgabe = rueckgabe.replace(/\bft/g, " Windstärke");
rueckgabe = rueckgabe.replace(/\m\/s/g, " Meter pro Sekunde");
}
catch(e) {}
return rueckgabe;
}
on(/^dwd\.0\..*\.object$/, function(dp) {
let i = getIdIndex(dp.id);
var warn = null;
if (dp.state.val != '') warn = JSON.parse(dp.state.val);
warn = convertJsonDWD(warn);
newDescriptions[i] = warn.description ;
newHeadlines[i] = warn.headline;
newBegins[i] = warn.start;
newEnds[i] = warn.end;
newInstruction[i] = warn.instruction;
newData[i].level = warn.level;
newData[i].type = warn.type;
if(timer) clearTimeout(timer);
if (autoMode) timer = setTimeout(check, 10000);
});
function convertJsonDWD(warn) {
warn = (!warn || warn === ''? {} : warn);
if (warn != {} && (warn.altitudeStart>maxhoehe || warn.level < minlevel)) warn = {};
let a = warn.description === undefined ? '' : warn.description;
let b = warn.headline === undefined ? '' : warn.headline;
let c = warn.start === undefined ? '' : getFormatDate(new Date(warn.start));
let d = warn.end === undefined ? '' : getFormatDate(new Date(warn.end));
let e = warn.instruction === undefined ? '' : warn.instruction;
let f = warn.type === undefined ? -1 : warn.type;
let g = warn.level === undefined ? -1 : warn.level;
return {"description":a,"headline":b,"start":c,"end":d,"instruction":e,"type":f,"level":g};
}
function getIdIndex(a) {
a = a.split('.');
if (a[2].length == 7) return 0
return a[2][7];
}
function getFormatDate(a) {
if (!a || a === '') return '';
return formatDate(a.getTime(), formatierungString);
}
// @PARAM Rückgabe von getFormatDate
function getFormatDateSpeak(a) {
if (!a || a === '') return '';
let b = a.split('.');
let m = '';
switch (b[1]) {
case '01': m='Januar';break;
case '02': m='Februar';break;
case '03': m='März';break;
case '04': m='April';break;
case '05': m='Mai';break;
case '06': m='Juni';break;
case '07': m='Juli';break;
case '08': m='August';break;
case '09': m='September';break;
case '10': m='Oktober';break;
case '11': m='November';break;
case '12': m='Dezember';break;
default: m='';
}
b[1]=m; // setze Monatsname
// entferne Jahr
let c = b[2].split(' ');
c[0]='';
b[2] = c.join(' ');
return b.join(' ');
}
function sendEmail(topic, msg) {
if (senderEmailID=='') {
log('senderEmailID ist nicht definiert!','warn');
return;
}
if (empfaengerEmailID=='') {
log('empfaengerEmailID ist nicht definiert!','warn');
return;
}
sendTo("email", {
from: senderEmailID,
to: empfaengerEmailID,
subject: topic,
text: msg
});
}
function sendioGo(topic, msg) {
if ((pushdienst & IOGO)!=0) {
if (ioGoUser) {
sendTo('iogo.0', "send", {
user: ioGoUser,
text: topic,
title: msg
});
} else {
sendTo('iogo.0', "send", {
text: topic,
title: msg
});
}
}
}