//Version 1.0.09 // Erläuterung Update: // Suche im Script nach 123456 und kopiere/ersetze ab diesem Punkt. So braucht ihr die Konfiguration nicht zu erneuern. // Link: https://forum.iobroker.net/topic/30616/script-dwd-uwz-nina-warnungen-als-push-sprachnachrichten/ // /* /* ************************************************************************* */ /* Script zum Übertragen der DWD/UWZ-Wetterwarnungen über */ /* Telegram, Pushover, Home24-Mediaplayer, SayIt, Alexa */ /* Datenpunkt, eMail oder ioGo */ /* Pushnachrichten können manuell ausgelöst werden */ /* höchstes Warnlevel pro Warnungstyp is als State vorhanden */ /* mit freundlicher Unterstützung von Paul53 (Tausend Dank nochmals) */ /* Stand: 13022017 PrinzEisenherz1 */ /* Stand: 08032020 ticaki */ /* */ /* */ /* ************************************************************************* */ /* Unterstützt: - Telegram, Pushover, Home24-Mediaplayer, SayIt, Alexa, Datenpunkt, eMail oder ioGo - DWD-Adapter & Unwetterzentrale-Script & NINA-Adapter ab V0.0.22 - Eigener Datenabruf für DWD Kreiswarnungen (wie Adapter), DWD Gemeindeegene, UWZ, Nina (ausgenommen Hochwasser), Zamg - Wetterwarnung - Wetterentwarnung Funktionen: - Filter die Warnungen nach doppelt, Gefahr(level) und Höhe - Umschalten über iobroker zwischen DWD/UWZ/NINA - Automatischer Versand und/oder manueller Nachrichtenversand - Zeitschaltuhr für Sprachausgabe - Datenpunkte mit der Startzeit, Endzeit, Type, Schlagzeile, Beschreibung, Farbe für Level(bgcolor) und höchstem Warnlevel dieses Typs - Unterstützung für 0_userdata - Datenpunkthauptpfade sind konfigurierbar incl. 0_userdata - Konfigurationsprüfung soweit möglich - Automodus und einzelne Pushdienste über iobroker schaltbar, sowohl für Automodus als auch Manuell - Optimierte Sprachausgabe Kleinkram: - Sprachausgabe: Sturmdetails werden ausgefiltert oder korrekt ausgesprochen (konfigurierbar) - Sprachausgabe: Pause zwischen dem Absenden der einzelnen Warnungen an die Wiedergabeeinheit konfigurierbar. - Manuelle Sprachnachrichten können die Zeitschaltuhr missachten. (konfigurierbar) - Multi-User/Device bei fast allen Pushdiensten verfügbar (außer Datenpunkt & pushover) - Alexa und SayIt mit Lautstärkeeinstellung. Alexagruppen unterstützen keine Lautstärke trotzdem konfigurieren. - Zusätzliche Hervorhebung konfigurierbar über attentionWarningLevel (im Betreff/Ansage) - Filter für Nina-sender - Namesbezeichner für Nina verfügbar, diese werden benötigt, falls in der Warnung Ort genannt wird, das auszugeben und damit die Bedeutung der Warnung hervorzuheben. Farben-Bedeutung: 0 - Grün // sollte es nicht geben 1 - Dunkelgrün 2 - Gelb Wetterwarnungen (Stufe 2) 3 - Orange Warnungen vor markantem Wetter (Stufe 3) 4 - Rot Unwetterwarnungen (Stufe 4) // im Grunde höchste Stufe in diesem Skript. 5 - Violett Warnungen vor extremem Unwetter (sollte es nicht geben) Dank an: - crunchip, sigi234, Latzi, CruziX fürs Testen und Ideen - die ursprünglichen Authoren s.o. /* ************************************************************************ /* ************************************************************************ */ /* ************************************************************************ */ /* Datenpfad konfigurieren */ /* ************************************************************************ */ /* */ /* 0_userdata. möglich */ /* */ /* ************************************************************************ */ var mainStatePath = '0_userdata.0.Wetterwarnung.'; /* ************************************************************************ */ /* Datenpfad konfigurieren ENDE */ /* ************************************************************************ */ /* ************************************************************************ */ /* NICHT EDITIEREN */ /* ************************************************************************ */ /* ************************************************************************ */ var konstanten = [ {'name':'telegram','value':1,count:0, delay:200, maxChar: 4000 }, {"name":'pushover',"value":2, count:0, delay:1000, maxChar: 1000}, {"name":'email',"value":4}, {"name":'sayit',"value":8, count:0, delay:0, maxChar: 940}, {"name":'home24',"value":16, count:0, delay:0}, {"name":'alexa',"value":32, count:0, delay:0, maxChar: 940}, {"name":'state',"value":64}, {"name":'iogo',"value":128, maxChar: 940, count: 0, delay: 300}, {"name":'state_html',"value":256} ]; 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; const STATE_HTML = konstanten[8].value; var uPushdienst = 0; const DWD = 1; const UWZ = 2; const NINA = 4; const DWD2 = 8; // only for request const ZAMG = 16; const MODES = [{mode:DWD, text:'DWD'},{mode:UWZ, text:'UWZ'},{mode:NINA, text:'NINA'}, {mode: ZAMG, text:'ZAMG'}]; if(mainStatePath[mainStatePath.length - 1] != '.') mainStatePath += '.'; const aliveState = mainStatePath+'alive'; if (extendedExists(aliveState)) { setState(aliveState, true, true); } /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* Konfiguration ab hier */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* Konfiguration der zu nutzenden Ausgabe um //uPushdienst+= PUSHOVER; zu aktivieren, bitte die // enfernen, also uPushdienst+= PUSHOVER; */ uPushdienst+= TELEGRAM; // Auskommentieren zum aktivieren uPushdienst+= PUSHOVER; // Auskommentieren zum aktivieren //uPushdienst+= EMAIL; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen //uPushdienst+= SAYIT; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen //uPushdienst+= HOMETWO; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen uPushdienst+= ALEXA; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen //uPushdienst+= STATE; // Auskommentieren zum aktivieren. State befindet sich unter mainStatePath.message //uPushdienst+= IOGO; // Auskommentieren zum aktivieren. Einstellungen nicht vergessen //uPushdienst+= STATE_HTML; // Auskommentieren zum aktivieren. State_html befindet sich unter mainStatePath.messageHtml als Tabelle /* ************************************************************************* */ /* Beispiele zur weiteren Konfiguration */ /* ************************************************************************* */ /* /* kein oder einen Eintrag möglich: /* var senderEmailID = ["max@mustermann.de"]; /* /* kein oder mehrfach nach gleichem Muster [1, 2, 3] bzw. ['1', '2', '3'] Einträge /* '' ist das selbe wie "", jedoch nicht mischen. /* /* var empfaengerEmailID = ["max@musterman.de","max2@musterman.de"]; /* var telegramUser = []; // leer /* var telegramUser = ['']; // leer /* var telegramUser = ['Hans']; // User mit Namen Hans /* var telegramUser = ['Hans', 'Gretel']; // User mit Namen Hans und User mit Namen Gretel /* var idSayIt = ["sayit.0.tts.text"]; /* var sayItVolumen = [60]; // Zahl ohne '' /* var idSayIt = ["sayit.0.tts.text","sayit.1.tts.text"]; /* var sayItVolumen = [60, 30]; // mehrfach Zahl ohne '' /* var ioGoUser = ['max@musterman.de']; /* var idAlexaSerial =['G090RV32984110Y', 'G090RZ3345643XR']; /* var alexaVolumen = [40, 30]; // Lautstärke die gleiche Anzahl an Einträgen wie bei idAlexaSerial /* /* ************************************************************************* */ /* weitere Konfiguration */ /* ************************************************************************* */ /* ************************************************************************* */ /* Datenabruf intern */ /* ************************************************************************* */ /* für UWZ Regionnamen eingeben "Warnung der Unwetterzentrale für XXXX" */ /* Durch das auffüllen wird der Datenabruf der UWZ aktiviert*/ /* Textbeispiel anstatt Entenhausen: 'Stadt / Dorfname' 'Berlin' oder 'den Regionsbezeichnung' 'den Schwarzwald' ''*/ /* UWZ - Für Deutschland: UWZDE + PLZ (UWZDE12345) */ /* var regionName = ['UWZDE13245', 'Entenhausen'] */ /* zum Deaktivieren [[]] oder [['','']]*/ var regionName = [['UWZDE16540','Hohen Neuendorf']]; // Standalone Datenquelle // entnehme ZAHL aus CSV /* nur Gemeinde/Landkreis/Großstädte werden verwendet: https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv?__blob=publicationFile&v=3 */ var dwdWarncellId = '812065144'; // Deaktivieren mit '' einzel: '2334535354' mehrere: ['23423424','23423423'] // Koordinaten [{laengen:13.05501,breiten:47.80949},{breiten:46.6247200, laengen:14.3052800},{breiten:48.332741,laengen:14.62274}];. var zamgCoordinates = []; // [] ist deaktiviert var uZAMGMitMeteoinformationen = false; // gibt die Wetterinformationen mit der Beschreibung aus: z.B Eine Kaltfront und ein Italientief sorgen im Warnzeitraum... // für Nina gebt die Koordinaten für euren Ort ein. ninaCoordinates = [{breiten:52.xxxxxxx, laengen:13.xxxxxx, text:'Hohen Neuendorf'}]; // ninaCoordinates = [{breiten:51.2277, laengen:6.7735, text:'dadrüben'}, {breiten:53.0511000, laengen:8.6309100, text:'Delmenhorst'}]; /* ************************************************************************* */ /* Datenabruf über Adapter oder externes Skript */ /* ************************************************************************* */ // für Nina wird die Gemeinde und der Landkreis benötigt. Am besten von hier kopieren: https://warnung.bund.de/assets/json/suche_channel.json // ohne die kryptischen Zeichen. Das ersetzt nicht den NINA-Adapter var uGemeinde = ''; // hier steht zum Beispiel, Hamburg, Unterdorf var uLandkreis = ''; // hier Kreis Bitburg, Landkreis Fürth /* ************************************************************************* */ /* Sonstige */ /* ************************************************************************* */ /* Einstellungen zur Emailbenachrichtigung*/ var senderEmailID = ["xxx@gmail.com"]; // mit Sender Emailadresse füllen. email Adapter muß installiert sein. 1 Eintrag erlaubt [] oder ["email1"] var empfaengerEmailID = ["xxx@gmail.com"]; // mit Empfänger Emailadresse füllen. Mehrere Empfänger möglich. [] oder ["email1"] oder ["email1","email2"] /* Konfiguration Sprachausgabe über Home24 - Mediaplayer */ //var idMediaplayer = ["192.168.178.x:Port"]; var idMediaplayer = [""]; // Eingabe IP-Adresse incl. Port für Home24-Mediaplayer mehrere Möglich - ungetestet /* Konfiguration Telegram */ var telegramUser = ['yyyyy']; // Einzelnutzer ['Hans']; Multinutzer ['Hans, Gretel']; Nutzer vom Adapter übernehmen []; var telegramChatId = ['12345678']; // Mehrfach Einträge möglich ['Gruppe1','Gruppe2'] var uTelegramReplyMarkup = null; // Falls ihr ein Telegrammmenü verwendet, könnt ihr hier einen Weg zurück definieren z.B.: {keyboard: [['Zurück']], resize_keyboard: true}; var uTelegramAllowNotification = true; // Erlaube Telegramnotification (Benachrichtigungston/Hinweise auf dem Empfangsgerät) var uTelegramUseStdUser = false; // Verwende immer auch die im Adapter gespeicherten Benutzer. uTelegramReplyMarkupInline = true // Bei Nachrichten die nicht mit volle Länge angefragt wurde, gibt es eine Schalfläche in der man die Langversion anfordern kann. /* Konfiguration Pushover */ var uPushoverDeviceName = ''; // ein bestimmtes Gerät z.B: ['droid4']; var uPushoverSound = 'pushover'; // Sounds siehe: https://pushover.net/api#sounds //Konfiguration von ioGo var ioGoUser = ['']; // // Einzelnutzer ['Hans']; Multinutzer ['Hans', 'Gretel']; Nutzer vom Adapter übernehmen []; var ioGoExpiry = 0; // Nachricht wird nach Sekunden entfernt. 0: aus /* Konfiguration Sprachausgabe über SayIt */ var idSayIt = ["sayit.0.tts.text"]; // mehrfach Einträge möglich var sayItVolumen = [30]; // gleiche Anzahl wie idSayIt /* Konfiguration Sprachausgabe über Alexa /* mehrere Einträge möglich, bei mir ging nur der Echo, 2 dots 2.Gen reagieren nicht auf announcement. */ var idAlexaSerial = ['G09xxxxxxxxxxxxxxxxxx']; // die reine Seriennummer des Echos z.B.: var idAlexaSerial =['G090RV32984110Y', 'G090RV32984110Y'] var alexaVolumen = [30,0]; // Lautstärke die gleiche Anzahl an Einträgen wie bei idAlexaSerial // Filtereinstellungen über Objekte einstellen var minlevel = 1 // Warnungen unterhalb dieses Levels nicht senden; (DWD und Nina level 1-4 / UWZ 0-5) var attentionWarningLevel = 3 // Warnung gleich oder oberhalb dieses Levels mit zusätzlichen Hinweisen versehen var minhoehe = 0 // Warnung für eine Höhe unterhalb dieses Wertes nicht senden var maxhoehe = 5000 // Warnung für eine Höhe oberhalb dieses Wertes nicht senden // 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 = '21:30'; // ab diesem Zeitpunkt gibt es keine Sprachausgabe // Ein manuellen Auslösen von Sprachnachrichten, löscht alle noch nicht ausgegebenen Sprachnachrichten aus der Liste. var uManuellClickClearSpeakMessageList = true; //Auslösen der Pushnachricht über States ignoriert Sprachausgabezeiten var forcedSpeak = true; // keine Ansage über m/s Knoten und Windstärke. Die Angabe mit Kilometer pro Stunde wird angesagt var windForceDetailsSpeak = false; // Über Objekte einzustellen uLogLevel = 1 // 0:OFF, 1:INFO, 2:ADVANCE, 4:DEBUG /* ************************************************************************* */ /* Nur Anpassen wenn nötig */ /* ************************************************************************* */ //Formatierungsstring für Datum / Zeit Alternative "TT.MM.YYYY SS:mm" KEINE Anpassung nötig const formatierungString = "TT.MM.YY SS:mm"; var scriptOverrides = false; // Die Einstellung im Skript überschreiben bei jedem Start die Einstellungen in den Objekten (punkte unter Basiskonfiguration außer warnzelle. // Die Geschwindigkeit gibt an wie lange das Skript wartet bevor es eine neue Nachricht an die Sprachausgabe sendet. konstanten[3].delay /*SayIt*/ = 86; // Vorlese Geschwindigkeit pro Zeichen in ms konstanten[4].delay /*Home24*/ = 90; // Vorlese Geschwindigkeit pro Zeichen in ms konstanten[5].delay /*Alexa*/ = 88; // Vorlese Geschwindigkeit pro Zeichen in ms // Mit diesen Optionen verringert man die Nachrichtenlänge in dem Beschreibung oder Handlungsanweisungen // nicht der Nachricht hinzugefügt werden. // über Objekte einzustellen var uHtmlMitBeschreibung = true; // gilt für Email var uHtmlMitAnweisungen = true; // uHtmlMitBeschreibung muß evenfalls true sein um Anweisungen zu erhalten var uTextMitBeschreibung = true; // gilt nicht für Email, aber für alle anderen Textnachrichten var uTextMitAnweisungen = true; // uTextMitBeschreibung muß evenfalls true sein um Anweisungen zu erhalten var uSpracheMitBeschreibung = true; // gilt für alle Sprachnachrichten var uSpracheMitAnweisungen = true; // uSpracheMitBeschreibung muß evenfalls true sein um Anweisungen zu erhalten var uSpracheMitOhneAlles = true; // super kurz überschreibt die anderen Einstellungen uTextHtmlMitOhneAlles = false // super kurz für Text und Html // Obergrenze an Zeichen die über Sprachausgabe ausgegeben werden, bei überschreitung wird nur die Schlagzeile ausgegebenen var uMaxCharToSpeak = 0; // 0 = aus - Zahl größer als 0 = maximal Zeichenanzahl (1000 sind rund 86 Sekunden bla bla) // Automodus Filter um Warnungen unterhalb attentionWarningLevel von DWD, UWZ oder NINA zu unterdrücken // Sprachausgabe bei auto und manuell unterdrückt. // Diese Warnungen sind vorhanden, sie werden nur in den benannten Fällen ausgeblendet. // Ist eine feste Vorgabe überschreibt alles andere var uFilterList = 0; // generelles Filter für den AutoModus ( = DWD + UWZ; oder = NINA; oder = 0;), außer Warnungslevel ist gleich/über attentionWarningLevel var uAutoNinaFilterList = ['CAP@hochwasserzentralen.de']; //Nina only. Filter diesen Sender raus s.o. - mehrere ['abc','cde']; var uwzPath= 'javascript.0.UWZ'; var dwdPath= 'dwd.0'; var ninaPath= 'nina.0' var intervalMinutes = 5; // die Daten bei DWD werden alle 10 Minuten aktualisiert. // Instanzen im ioBroker var telegramInstanz= 'telegram.0'; var pushoverInstanz= 'pushover.0'; var ioGoInstanz= 'iogo.0'; var alexaInstanz= 'alexa2.0'; var emailInstanz= 'email.0'; /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* Konfiguration Ende */ /* ************************************************************************* */ /* Keine Anpassungen ab hier, außer du weißt was du tuest */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ //Logausgabe var DEBUGSENDEMAIL = false; var DEBUG_VARS = false; //ab hier bei Update // 123456 var DEBUGINGORESTART = false // die Datenbank wird beim Start nicht befüllt Test von Standalone UWZ/DWD var uTelegramMessageShort = 'Ww?'; var uTelegramMessageLong = 'Wwww'; // Aus diesen Elementen wird die html warnung zusammengesetzt. // Prefix wird als ersten eingefügt, dann mehrfach html_headline und html_message, wenn verfügbar. Zum Schluß kommt html_end // html_headline_color wird verwendet wenn eine Farbe angegeben ist und bildet hier die Hintergrundfarbe. // Jede einzelne Warnung wird mit Headline, Message und Farbe(optional) aufgerufen, wenn headline oder message leer ist, wird // die Zeichenkette nicht hinzugefügt. ###color###, ###message###, ###headline### sind Platzhalter für die jeweilgen Zeichenketten. Farbe ist // ein hexdezimaler Wert als Zeichenkette. var html_prefix = ''; var html_headline_color = ''; var html_headline = ''; var html_message = ''; var html_end = '
' + '###headline###' + '
' + '###headline###' + '
' + '###message###' + '
'; var ninaCoordinates; if (ninaCoordinates === undefined) ninaCoordinates = [] if ( DEBUG_VARS) { ninaCoordinates = [{breiten:51.2277, laengen:6.7735, text:'dadrüben'}, {breiten:53.0511000, laengen:8.6309100, text:'Delmenhorst'}]; zamgCoordinates = [{laengen:13.05501,breiten:47.80949},{breiten:46.6247200, laengen:14.3052800},{breiten:48.332741,laengen:14.62274}]; regionName.push(['UWZAT00810', 'sig']); } // MODE einstellen über Datenpunkte, das hier hat keine auswirkungen // nur für ersten Lauf nötig, ab dann überschreiben States diesen Wert var MODE = 0; // DWD oder UWZ wird von gültigen Einstellungen im Datenpfad überschrieben // Wandel Usereingabe in sauberes True / False um forcedSpeak = !!forcedSpeak; windForceDetailsSpeak = !!windForceDetailsSpeak; //Vorgezogene Tests checkConfigVariable('uZAMGMitMeteoinformationen'); checkConfigVariable('ZAMG'); checkConfigVariable('zamgCoordinates'); checkConfigVariable('DEBUGINGORESTART'); checkConfigVariable('dwdWarncellId'); checkConfigVariable('DWD2'); // Variable nicht konfigurierbar const SPEAK = ALEXA + HOMETWO + SAYIT; const PUSH = TELEGRAM + PUSHOVER + IOGO + STATE; const ALLMSG = EMAIL | STATE_HTML; const ALLMODES = DWD | UWZ | NINA | ZAMG; const CANHTML = EMAIL + STATE_HTML; const CANPLAIN = PUSH + EMAIL; const placeHolder = 'XXXXPLACEHOLDERXXXX'; const configModeState = mainStatePath + 'config.mode'; const mirrorMessageState = mainStatePath + 'message'; const mirrorMessageStateHtml = mainStatePath + 'messageHtml'; const totalWarningCountState = mainStatePath + 'totalWarnings'; const SPACE = ' '; const NEWLINE = '\n'; const axios = require('axios'); var numOfWarnings = 5; var enableInternDWD = false; var enableInternDWD2 = false; const internDWDUrl='https://www.dwd.de/DWD/warnungen/warnapp/json/warnings.json'; const internDWD2Url = 'https://maps.dwd.de/geoserver/dwd/ows?service=WFS&version=1.2.0&CQL_FILTER=WARNCELLID%20IN%20(%27'+ placeHolder +'%27)&request=GetFeature&typeName=dwd%3AWarnungen_Gemeinden&maxFeatures=50&outputFormat=application%2Fjson'; const interngetNameDWD2Url = 'https://maps.dwd.de/geoserver/dwd/ows?service=WFS&version=1.2.0&CQL_FILTER=WARNCELLID%20IN%20(%27'+ placeHolder +'%27)&request=GetFeature&typeName=dwd%3AWarngebiete_Gemeinden&maxFeatures=50&outputFormat=application%2Fjson'; var internalDWDPath = mainStatePath + 'data.dwd.'; var internalWarningEnd = '.warning'; var standaloneInterval = null; const statesIntern = {[DWD]:{}, [UWZ]:{}, [ZAMG]:{}, [NINA]:{}}; statesIntern[DWD].path = internalDWDPath var sendNoMessgesOnInit = false; var enableInternUWZ = false; var internUWZUrl='http://feed.alertspro.meteogroup.com/AlertsPro/AlertsProPollService.php?method=getWarning&language=de&areaID='; var internalUWZPath = mainStatePath + 'data.uwz-id.'; statesIntern[UWZ].path = internalUWZPath var internZamgUrl = "https://warnungen.zamg.at/wsapp/api/getWarningsForCoords?lon=" + placeHolder+"&lat=" + placeHolder+"1&lang=de" var internalZamgPath = mainStatePath + 'data.zamg.'; statesIntern[ZAMG].path = internalZamgPath var internMowasUrl = ["https://warnung.bund.de/bbk.mowas/gefahrendurchsagen.json", 'https://warnung.bund.de/bbk.biwapp/warnmeldungen.json', 'https://warnung.bund.de/bbk.katwarn/warnmeldungen.json']; var internalMowasPath = mainStatePath + 'data.nina.'; statesIntern[NINA].path = internalMowasPath var START = new Date(); var ENDE = new Date(); var idAlexa = alexaInstanz + '.Echo-Devices.' + placeHolder + '.Commands.announcement'; var idAlexaVolumen = alexaInstanz + '.Echo-Devices.' + placeHolder + '.Player.volume'; var idAlexaState = alexaInstanz + '.Echo-Devices.' + placeHolder + '.Player.currentState' var idAlexaPause = alexaInstanz + '.Echo-Devices.' + placeHolder + '.Player.controlPause' var idAlexaPlay = alexaInstanz + '.Echo-Devices.' + placeHolder + '.Player.controlPlay' var idAlexaLastState = [] var autoSendWarnings = true; var forceSpeak = false; var timer = null; var onClickCheckRun = false; var onClickCheckRunCmd = ''; var warnDatabase = { new: [], old: [] }; var subDWDhandler = null; var subUWZhandler = null; var subNINAhandler = null; let nPushdienst = {auto:{}, man:{}} for (let a=0; a 0 ) { enableInternUWZ = true; if (Array.isArray(regionName)){ for(let a = 0; a < regionName.length; a++) warncells[UWZ].push({id:regionName[a][0],text:regionName[a][1], area:''}) } } function checkConfigArray(arr, name, type) { for (let a = 0; a < arr.length; a++) { if (!arr[a]) arr.splice(a--, 1); else { testValueTypeLog(arr[a], 'name', type); } } } checkConfigArray(uAutoNinaFilterList, 'uAutoNinaFilterList', 'string'); checkConfigArray(senderEmailID, 'senderEmailID', 'string'); checkConfigArray(empfaengerEmailID, 'empfaengerEmailID', 'string'); checkConfigArray(idAlexaSerial, 'idAlexaSerial', 'string'); checkConfigArray(idMediaplayer, 'idMediaplayer', 'string'); checkConfigArray(telegramUser, 'telegramUser', 'string'); checkConfigArray(idSayIt, 'idSayIt', 'string'); checkConfigArray(ioGoUser, 'ioGoUser', 'string'); checkConfigArray(telegramChatId, 'telegramChatId', 'string'); for (let a = 0; a < sayItVolumen.length; a++) { if (sayItVolumen[a] === undefined) sayItVolumen[a] = 0; else testValueTypeLog(sayItVolumen[a], 'sayItVolumen', 'number'); } for (let a = 0; a < alexaVolumen.length; a++) { if (alexaVolumen[a] === undefined) alexaVolumen[a] = 0; else testValueTypeLog(alexaVolumen[a], 'alexaVolumen', 'number'); } if ((uPushdienst & ALEXA) != 0) { testValueTypeLog(idAlexaSerial, 'idAlexaSerial', 'array'); if (idAlexaSerial.length == 0) { ticaLog(0,'Keine Alexa / Echoseriennummer eingetragen. Überpüfen!', 'error'); stopScript(scriptName); } for (let a = 0; a < idAlexaSerial.length; a++) { if (!extendedExists(replacePlaceholder(idAlexa, idAlexaSerial[a]))) { ticaLog(0,'Alexa - Serial ' + idAlexaSerial[a] + ' ist fehlerhaft. Überpüfen! Object ID:' + replacePlaceholder(idAlexa, idAlexaSerial[a]), 'error'); stopScript(scriptName); } idAlexaLastState[a] = {} } } if ((uPushdienst & SAYIT) != 0) { testValueTypeLog(idSayIt, 'idSayIt', 'array'); for (let a = 0; a < idSayIt.length; a++) { if ( !extendedExists(idSayIt[a]) ) { ticaLog(0,'SayIt - Konfiguration ist fehlerhaft. Überpüfen!', 'error'); stopScript(scriptName); } } } if ((uPushdienst & EMAIL) != 0) { if (senderEmailID.length > 1) { ticaLog(0,'eMail - Konfiguration ist fehlerhaft. Nur 1 Eintrag in senderEmailID erlaubt!', 'error'); stopScript(scriptName); } } } /*************************************************************************************** * function testValueTypeLog(test, teststring, typ, need = false) * @param {any} test Variable deren Typ / Inhalt getestet werden soll * @param {string} teststring Variable als String, wie er im Script steht * @param {string} typ Soll - Type der Variable alles + 'array' * @param {boolean} need Variable darf nicht null / leer sein /***************************************************************************************/ function testValueTypeLog(test, teststring, typ, need = false) { if (test === undefined) { let errorLog = 'Konfiguration enthält Fehler. Der / Ein Wert von var ' + teststring + ' ist undefiniert oder fehlt!'; ticaLog(0,errorLog, 'error'); stopScript(scriptName); } if (typ == 'array') { if (!test || !Array.isArray(test)) { let errorLog = 'Konfiguration enthält Fehler. Der / Ein Wert von var ' + teststring + ' ist kein Array. Es fehlen wohl die umschließenden []!'; ticaLog(0,errorLog, 'error'); stopScript(scriptName); } } else if (typeof test !== typ) { let errorLog = 'Konfiguration enthält Fehler. Ändere ' + teststring + ' = ['; if (typ == 'string') { errorLog += test + '];//(' + typeof test + ') in ' + teststring + ' = [\'' + test + '\'];//(' + typ + ')'; } else { errorLog += '\'' + test + '\'];//(' + typeof test + ') in ' + teststring + ' = [' + test + '];//(' + typ + ')'; } ticaLog(0,errorLog, 'error'); stopScript(scriptName); } if (need && !test) { ticaLog(0,'Konfiguration enthält Fehler. Der Wert von var ' + teststring + ' wird benötigt, ist jedoch nicht konfiguriert!', 'error'); stopScript(scriptName); } } /* ************************************************************************* * Überprüfe Nutzerkonfiguration ENDE /* ************************************************************************* * Erstellung von Datenpunkten * Trigger aktivieren und Datenpflege für eigene Datenpunkte /* ************************************************************************* */ async function changeMode(modeFromState) { if (MODE != modeFromState || firstRun) { let oldMode = MODE; MODE = modeFromState; ticaLog(2, 'MODE wurde geändert. MODE: ' + MODE + ' firstRun:' + firstRun); if ( MODE == 0 ) ticaLog(0,'Alle Benachrichtigungen ausgeschaltet, bitte unter ioBroker - Objektansicht - '+ mainStatePath + '.config - UWZ und/oder DWD und/oder NINA auf true stellen.', 'warn'); await InitDatabase(sendNoMessgesOnInit); dataSubscribe(); if (!firstRun) { // überspringe das beim Starten des Scripts for (let a = 0; a < konstanten.length; a++) { for (let x = 0; x < MODES.length; x++) { let oid = mainStatePath + 'config.auto.' + MODES[x].text.toLowerCase() + '.' + konstanten[a].name; let update = !!((switchFlags(MODE, oldMode, false) & MODES[x].mode)); if (extendedExists(oid)) { setState(oid, update || !!(getAutoPushFlags(MODE & MODES[x].mode) & konstanten[a].value)); } oid = mainStatePath + 'config.manuell.' + MODES[x].text.toLowerCase() + '.' + konstanten[a].name; if (extendedExists(oid)) { setState(oid, update || !!(getManuellPushFlags(MODE & MODES[x].mode) & konstanten[a].value)); } } } } if (autoSendWarnings && (!sendNoMessgesOnInit)) { checkWarningsMain() } firstRun = false; sendNoMessgesOnInit = false; } setConfigModeStates(modeFromState); } async function init() { // erster fund von create custom onStopped = false ticaLog(0, 'Starte Initialisierung! - Bitte warten. Das dauert beim ersten Start etwas länger. - Das Skript in dieser Phase nicht Neustarten, wenn doch bitte Javascript Instanz ebenfalls neustarten') ticaLog(0, 'Datenpunkte werden überprüft') try { // State der Pushnachrichten über pushover / telegram spiegelt if (!await existsStateAsync(mirrorMessageState)) { createStateAsync(mirrorMessageState, { read: true, write: false, desc: "State der für jede Warnung neu geschrieben wird", type: "string", def:'' }); } if (!await existsStateAsync(mirrorMessageStateHtml)) { await createStateAsync(mirrorMessageStateHtml, { read: true, write: false, desc: "State mit dem selben Inhalt wie die Email", type: "string", def:'' }); } if (!await existsStateAsync(totalWarningCountState)) { await createStateAsync(totalWarningCountState, { read: true, write: false, desc: "Anzahl der aktiven Warnung nach Filter", type: "number", def:0}); } } catch(error) { ticaLog(0,'Fehler in CreateStates #1'); ticaLog(0,error); stopScript(); } // erstelle Datenpunkte für DWD/UWZ standalone for (let c = 0; c < MODES.length; c++) { if (onStopped) return; let warncellid = mainStatePath + 'config.basiskonfiguration.warnzelle.' + MODES[c].text.toLowerCase() ; try { let app = []; switch(MODES[c].mode) { case DWD: { app[0] = '.add#'; break; } case UWZ: { app[0] = '.addName#'; app[1] = '.addId#'; break; } case ZAMG: { app[0] = '.addLat#'; app[1] = '.addLong#'; break; } case NINA: { app[0] = '.addLat#'; app[1] = '.addLong#'; app[2] = '.addName#'; break; } default: continue; } for (let x = 0; x 0) { for (let a = 0; a < warncells[mode].length; a++) { await addWarncell(warncells[mode][a].id, c); } } let st = $('state(state.id='+mainStatePath +'config.basiskonfiguration.warnzelle.' + MODES[c].text.toLowerCase()+'.*)'); for (let a = 0; a < st.length; a++) { let val = getEndfromID(st[a]); if (val == 'add#' || val == 'refresh#' || val == 'addName#' || val == 'addId#' || val == 'addLat#' || val == 'addLong#') continue; let wIndex = warncells[mode].findIndex(w => val == w.id); if (wIndex == -1 && getState(st[a]).val) await addWarncell(val, c); else if (wIndex > -1 && getState(st[a]).val == '') warncells[mode].splice(wIndex, 1); } on(new RegExp(getRegEx(mainStatePath +'config.basiskonfiguration.warnzelle.', '^')+'.*'), function(obj) { let val = getEndfromID(obj.id); if (val == 'add#' || val == 'refresh#' || val == 'addName#' || val == 'addId#' || val == 'addLat#' || val == 'addLong#') return; setState(obj.id, obj.state.val, true); let modetext = getPreEndfromID(obj.id); let c = MODES.findIndex((a) => a.text.toLowerCase() == modetext); let mode = MODES[c].mode; let wIndex = warncells[mode].findIndex(w => val == w.id); if (wIndex == -1 && obj.state.val) addWarncell(val, c); else if (wIndex > -1 && obj.state.val == '') warncells[mode].splice(wIndex, 1); }); } for (let w = 0; w < warncells[DWD].length; w++) { for (let i = 0; i < numOfWarnings; i++) { let p = internalDWDPath + warncells[DWD][w].id + internalWarningEnd + (i == 0 ? '' : i) + '.'; for (let a = 0; a < statesDWDintern.length; a++) { if (onStopped) return; let dp = statesDWDintern[a]; let id = p + dp.id; try { await createStateCustomAsync(id, dp.default,dp.options); } catch (e) { ticaLog(0,'error in .data.dwd create ' + e, 'error'); } } } } for (let w = 0; w < warncells[UWZ].length; w++) { for (let i = 0; i < numOfWarnings; i++) { let p = internalUWZPath + warncells[UWZ][w].id + internalWarningEnd + (i == 0 ? '' : i) + '.'; for (let a = 0; a < statesUWZintern.length; a++) { let dp = statesUWZintern[a]; let id = p + dp.id; try { await createStateCustomAsync(id, dp.default,dp.options); } catch (e) { ticaLog(0,'error in .data.uwz create ' + e, 'error'); } } } } for (let w = 0; w < warncells[NINA].length; w++) { for (let i = 0; i < numOfWarnings; i++) { let p = internalMowasPath + warncells[NINA][w].id + internalWarningEnd + (i == 0 ? '' : i) + '.'; for (let a in statesNINAintern) { if (onStopped) return; let dp = statesNINAintern[a]; let id = p + dp.id; try { await createStateCustomAsync(id, dp.default,dp.options); } catch (e) { ticaLog(0,'error in .data.nina create ' + e, 'error'); } } } } try { // MODE änderung über Datenpunkte string await createStateCustomAsync(configModeState, '', { read: true, write: true, desc: "Modusauswahl DWD, UWZ, Nina oder Zamg", type: "string"}); on({ id: configModeState, change: 'ne', ack: false }, function(obj) { if (obj.state.val && typeof obj.state.val === 'string' && (obj.state.val.toUpperCase().includes('DWD') || obj.state.val.toUpperCase().includes('UWZ') || obj.state.val.toUpperCase().includes('NINA') || obj.state.val.toUpperCase().includes('ZAMG'))) { //setState(configModeState, MODE, true) let mode = 0; if (firstRun) return; for (let a = 0; a < MODES.length; a++) mode |= obj.state.val.toUpperCase().includes(MODES[a].text) ? MODES[a].mode : 0; if (MODE != mode) { ticaLog(4, 'Modus wird geändert von: ' + mode + ' String:' + obj.state.val); changeMode(mode); } else { changeMode(MODE); } } else { changeMode(MODE); } }); // MODE änderung über Datenpunkte Boolean for (let a = 0; a < MODES.length; a++) { let tok = MODES[a].text.toLowerCase(); let id = mainStatePath + 'config.' + tok; if (!await existsStateAsync(id)) { let mi = !!(MODE & MODES[a].mode); await createStateCustomAsync(id, mi, { read: true, write: true, desc: "Aktivere " + tok.toUpperCase() + '.', type: "boolean" }); } on({ id: id, change: 'ne', ack: false }, function(obj) { let arr = obj.id.split('.'); let tok = arr[arr.length - 1].toUpperCase(); let mode = MODES[MODES.findIndex(function(j) { return j.text == tok })].mode; let oldMode = MODE; oldMode = switchFlags(oldMode, mode, obj.state.val); ticaLog(4, 'Modus wird geändert von: ' + MODE); changeMode(oldMode); }); MODE = switchFlags(MODE, MODES[a].mode, getState(id).val); } // Automodus ein und ausschalten let id = mainStatePath + 'config.auto.on'; await createStateCustomAsync(id, true, { read: true, write: true, desc: "Aktivere automatischen Push bei eintreffen der Warnungen.", type: "boolean" }); autoSendWarnings = getState(id).val; await setStateAsync(id, !!(autoSendWarnings), true); for (let a = 0; a < configObj.length; a++) { if (onStopped) return; let p = mainStatePath + 'config.' + configObj[a].id if (!await existsStateAsync(p)) { let n = configObj[a].name !== undefined ? configObj[a].name : configObj[a].id; let def = configObj[a].def; await createStateAsync(p, {read:true, write:true, def: def, type:configObj[a].typ, name:n}); } if (scriptOverrides) { await configObj[a].setObj(); } else { const v = await getStateAsync(p); configObj[a].on({id:p, state:{val:v.val}}); } on(p, configObj[a].on); } // Nachrichtenversand per Click States/ config. und auto . erzeugen und subscript for (let a = 0; a < konstanten.length; a++) { if ((uPushdienst & konstanten[a].value) != 0) { if (!await existsStateAsync(mainStatePath + 'commands.' + konstanten[a].name)) { await createStateAsync(mainStatePath + 'commands.' + konstanten[a].name, { read: true, write: true, desc: "Gebe Warnungen auf dieser Schiene aus", type: "boolean", role: "button", def: false }); } if (!await existsStateAsync(mainStatePath + 'commands.' + konstanten[a].name + '_short')) { await createStateAsync(mainStatePath + 'commands.' + konstanten[a].name + '_short', { read: true, write: true, desc: "Gebe Kurzwarnungen auf dieser Schiene aus", type: "boolean", role: "button", def: false }); } if (!await existsStateAsync(mainStatePath + 'commands.' + konstanten[a].name + '_long')) { await createStateAsync(mainStatePath + 'commands.' + konstanten[a].name + '_long', { read: true, write: true, desc: "Gebe lange Warnungen auf dieser Schiene aus", type: "boolean", role: "button", def: false }); } if (!await existsStateAsync(mainStatePath + 'commands.' + konstanten[a].name + '_veryshort')) { await createStateAsync(mainStatePath + 'commands.' + konstanten[a].name + '_veryshort', { read: true, write: true, desc: "Gebe sehr kurze Warnungen auf dieser Schiene aus", type: "boolean", role: "button", def: false }); } for (let x = 0; x < MODES.length; x++) { let oid = mainStatePath + 'config.auto.' + MODES[x].text.toLowerCase() + '.' + konstanten[a].name; await createStateCustomAsync(oid, true, { read: true, write: true, desc: "Schalte Autopushmöglichkeiten ein / aus", type: "boolean" }); setConfigKonstanten(oid, getState(oid).val, true); oid = mainStatePath + 'config.manuell.' + MODES[x].text.toLowerCase() + '.' + konstanten[a].name; await createStateCustomAsync(oid, true, { read: true, write: true, desc: "Schalte Manuellepushmöglichkeiten ein / aus", type: "boolean" }); setConfigKonstanten(oid, getState(oid).val, false); // letzer fund von Create Custom } } } ticaLog(0, 'Abonniere Konfigurationsdatenpunkte') subscribeStates(); setWeekend(); activateSchedule(); ticaLog(0, 'Setzte Modus, Inialisiere Datenbank, starte Datenabruf(asynchron)') if (firstRun) changeMode(MODE) ticaLog(0, 'Initialisierung abgeschlossen') } catch(error) { ticaLog(0,'Fehler in CreateStates #5'); ticaLog(0,error); stopScript(); } } // setzte alle MODE Datenpunkte function setConfigModeStates(mode) { let m = (mode & DWD ? 'DWD' : '') + (mode & UWZ ? mode & DWD ? '/UWZ' : 'UWZ' : '') + (mode & NINA ? mode & (DWD|UWZ) ? '/NINA' : 'NINA' : '') + (mode & ZAMG ? mode & (DWD|UWZ|NINA) ? '/ZAMG' : 'ZAMG' : '') if (extendedExists(configModeState)) setState(configModeState, m , true); for (let a = 0; a < MODES.length; a++) { let t = MODES[a].text.toLowerCase(); let id = mainStatePath + 'config.' + t; if (extendedExists(id)) setState(id, !!(mode & MODES[a].mode), true); } } function subscribeStates() {// on() für alles unter config.auto subscribe({ id: new RegExp(getRegEx(mainStatePath + 'config.auto', '^') + '.*'), ack: false }, function(obj) { if (obj.state.val == obj.oldState.val) { setState(obj.id, obj.state.val, true); return; } if (obj.id == mainStatePath + 'config.auto.on') { ticaLog(4, 'Auto trigger: ' + obj.id + ' Value:' + obj.state.val); autoSendWarnings = !!obj.state.val; setState(obj.id, autoSendWarnings, true); for (let a = 0; a < konstanten.length; a++) { for (let x = 0; x < MODES.length; x++) { let oid = mainStatePath + 'config.auto.' + MODES[x].text.toLowerCase() + '.' + konstanten[a].name; if (extendedExists(oid)) { setState(oid, obj.state.val); } } } } else { ticaLog(4, 'else auto trigger: ' + obj.id + ' Value:' + obj.state.val); setConfigKonstanten(obj.id, obj.state.val, true); } }); // on() für alles unter config.manuell subscribe({ id: new RegExp(getRegEx(mainStatePath + 'config.manuell', '^') + '.*'), ack: false }, function(obj) { if (obj.state.val == obj.oldState.val) { setState(obj.id, obj.state.val, true); return; } ticaLog(4, 'Manuell trigger: ' + obj.id + ' Value:' + obj.state.val); setConfigKonstanten(obj.id, obj.state.val, false); }); subscribe({ id: new RegExp(getRegEx(mainStatePath + 'commands', '^') + '.*') }, function(obj) { if (!obj.state.val) return; setState(obj.id, false, true); let b = obj.id.split('.'); let msgLength = 0; let d = konstanten.findIndex(function(c) { return (c.name === b[b.length - 1]); }) if (d == -1) { d = konstanten.findIndex(function(c) { return (c.name + '_short' === b[b.length - 1]); }); msgLength = 1; if (d == -1) { d = konstanten.findIndex(function(c) { return (c.name + '_long' === b[b.length - 1]); }); msgLength = 2; if (d == -1) { d = konstanten.findIndex(function(c) { return (c.name + '_veryshort' === b[b.length - 1]); }); msgLength = 3; if (d == -1) { return } } } } let oldA = uTextMitAnweisungen, oldB = uTextMitBeschreibung, oldC = uSpracheMitAnweisungen, oldD = uSpracheMitBeschreibung, oldE = uHtmlMitAnweisungen, oldF = uHtmlMitBeschreibung, oldG = uSpracheMitOhneAlles, oldH = uTextHtmlMitOhneAlles if (msgLength != 0 ) { uTextMitAnweisungen = msgLength == 2; uTextMitBeschreibung = msgLength == 2; uSpracheMitAnweisungen = msgLength == 2; uSpracheMitBeschreibung = msgLength == 2; uHtmlMitAnweisungen = msgLength == 2; uHtmlMitBeschreibung = msgLength == 2; uTextHtmlMitOhneAlles = msgLength == 3; uSpracheMitOhneAlles = msgLength == 3; } warnDatabase.old = []; let oPd = uPushdienst; uPushdienst &= konstanten[d].value; forceSpeak = forcedSpeak; onClickCheckRun = true; onClickCheckRunCmd = obj.id; if ((uPushdienst & SPEAK) != 0 && uManuellClickClearSpeakMessageList) _speakToArray = [{ speakEndtime: new Date() }]; ticaLog(1, 'Sendwarnings manuell uPushdienst: ' +uPushdienst) checkWarningsMain(true); uTextMitAnweisungen = oldA; uTextMitBeschreibung = oldB; uSpracheMitAnweisungen = oldC; uSpracheMitBeschreibung = oldD; uHtmlMitAnweisungen = oldE; uHtmlMitBeschreibung = oldF; uSpracheMitOhneAlles = oldG uTextHtmlMitOhneAlles = oldH onClickCheckRun = false; onClickCheckRunCmd = ''; forceSpeak = false; uPushdienst = oPd; }); } // Hilfsfunktion zu on() function setConfigKonstanten(id, val, auto) { try { let b = id.split('.'); let m1 = b[b.length - 2]; let m = MODES.findIndex(function(c) { return (c.text.toLocaleLowerCase() == m1); }); if (m == -1) return; m = MODES[m].mode; let d = konstanten.findIndex(function(c) { return (c.name === b[b.length - 1]); }); if (d == -1) return; let value = konstanten[d].value let tp = 0; let typ = auto ? 'auto' : 'man'; if (MODE & m) { nPushdienst[typ][m] = switchFlags(nPushdienst[typ][m], value, val); setState(id, val, true); } } catch(e) { ticaLog(0,'Fehler in setConfigKonstanten() ' + e) } } // setzte die Alert States auf die höchste aktuelle Warnstufe async function setAlertState(go = false) { if (setAlertStateTimeout) clearTimeout(setAlertStateTimeout) if ( !go ) { setAlertStateTimeout = setTimeout(function(){setAlertState(true)},15000); return; } if (++setAlertStateCount > 1) { // lasse keine mehrfach Aufrufe zu setAlertStateCount = 2; return; } let mode = [MODES[0], MODES[1], MODES[3]]; let sA = mainStatePath + 'alert.'; let tempExistIds = []; for (let a = 0; a < mode.length; a++) { if (!(MODE & mode[a].mode)) continue; let stateAlertid = sA + mode[a].text.toLowerCase() + '.'; for (let wcIndex = 0; wcIndex < warncells[mode[a].mode].length; wcIndex++) { let area = warncells[mode[a].mode][wcIndex].area; if (area === undefined) continue; let stateAlertIdArea = stateAlertid + area.split(' ').join('_') + '.' for (let b = 0; b < warningTypesString[mode[a].mode].length; b++) { let stateAlertIdFull = stateAlertIdArea + warningTypesString[mode[a].mode][b][0] + '.'; let AlertLevel = -1, AlertIndex = -1; for (let c = 0; c < warnDatabase.new.length; c++) { let entry = warnDatabase.new[c]; if (entry.mode == mode[a].mode && entry.type == b && entry.level > AlertLevel && entry.area == area && !entry.ignored) { AlertLevel = warnDatabase.new[c].level; AlertIndex = c; } } tempExistIds.push(stateAlertIdFull); if (!await existsStateAsync(stateAlertIdFull + stateAlert[0].name) || getState(stateAlertIdFull + stateAlert[0].name).val != AlertLevel || (AlertIndex > -1 && (!await existsStateAsync(stateAlertIdFull + stateAlert[9].name) || getState(stateAlertIdFull + stateAlert[9].name).val != warnDatabase.new[AlertIndex].hash))) { let cwarn = false; if (AlertIndex > -1) { let start = warnDatabase.new[AlertIndex].start ? new Date(warnDatabase.new[AlertIndex].start) : new Date(new Date().setHours(new Date().getHours() - 2)); let end = warnDatabase.new[AlertIndex].end ? new Date(warnDatabase.new[AlertIndex].end) : new Date(new Date().setHours(new Date().getHours() + 2)); cwarn = end.getTime() - start.getTime() > 0 ? timeIsBetween(new Date(), start, end) : false; if (!cwarn && warnDatabase.new[AlertIndex].alerttimeout === undefined) { if (!warnDatabase.new[AlertIndex].alertendtimeout) { if (end && end.getTime() - (new Date().getTime()) > 0) { warnDatabase.new[AlertIndex].alertendtimeout = setTimeout(setAlertState, end.getTime() - (new Date().getTime())+100); } if (start && start.getTime() - (new Date().getTime()) > 0) { warnDatabase.new[AlertIndex].alertstarttimeout = setTimeout(setAlertState, start.getTime() - (new Date().getTime())+100) } } } } let ci = 0 try { let data = [] data[0] = AlertLevel; data[1] = b; data[2] = (AlertIndex > -1 ? new Date(warnDatabase.new[AlertIndex].start).getTime() : 0) data[3] = (AlertIndex > -1 ? new Date(warnDatabase.new[AlertIndex].end).getTime() : 0) data[4] = (AlertIndex > -1 ? cwarn : false); data[5] = (AlertIndex > -1 ? warnDatabase.new[AlertIndex].headline : '') data[6] = (AlertIndex > -1 ? warnDatabase.new[AlertIndex].description : '') data[7] = (AlertIndex > -1 ? warnDatabase.new[AlertIndex].color : '') data[8] = (AlertIndex > -1 ? warnDatabase.new[AlertIndex].picture : '') data[9] = (AlertIndex > -1 ? warnDatabase.new[AlertIndex].hash : 0) data[10] = (AlertIndex > -1 ? (warnDatabase.new[AlertIndex].ec_ii_type !== undefined ? warnDatabase.new[AlertIndex].ec_ii_type : -1) : -1) for (let index=0; index < data.length; index++) { if (onStopped) return; if (await extendedExistsAsync(stateAlertIdFull + stateAlert[index].name)) await setStateAsync(stateAlertIdFull + stateAlert[index].name, data[index], true) else { try { await createStateCustomAsync(stateAlertIdFull + stateAlert[index].name, data[index], stateAlert[index].type); } catch(error) { ticaLog(0,'Fehler in setAlertState #2 id:' + stateAlertIdFull + stateAlert[index].name); ticaLog(0,error); stopScript(); return; } } } } catch(error) { ticaLog(0,'Fehler in setAlertState #3 id:' + stateAlertIdFull + stateAlert[ci].name + ' Index:' + ci, 'error'); ticaLog(0,error); stopScript(); return; } } } } } let tempDelIds = $('state(state.id='+sA+'*)') for (let i=0;i { if (tempDelIds[i].includes(a)) return true; }) try { if (t == -1 && await existsStateAsync(tempDelIds[i])) await deleteStateAsync(tempDelIds[i]); } catch (e) { ticaLog(0, 'Fehler setAlertState(): id' + tempDelIds[i], 'error') } } ticaLog(4, 'Alert States wurden gesetzt'); if (setAlertStateCount > 1) { // rufe sich selbst auf, wenn während der Verarbeitung ein weiterer Aufruf stattfand setAlertStateCount = 0 setAlertState(); } else setAlertStateCount = 0 } function timeIsBetween(fTime,start,ende) {//Dateobjekt,hh:mm,hh:mm let eTime = new Date(), sTime = new Date(); if (typeof start == 'object') { sTime = new Date(start); } else { start = start.split(':'); sTime.setHours(parseInt(start[0]), parseInt(start[1]), 0); } if (typeof ende === 'object') { eTime = new Date(ende); } else { ende = ende.split(':'); eTime.setHours(parseInt(ende[0]), parseInt(ende[1]), 0); } if (sTime.getTime()>eTime.getTime()) { if (fTime.getTime() < eTime.getTime()) sTime.setDate(eTime.getDate()-1); if (fTime.getTime() > sTime.getTime()) eTime.setDate(sTime.getDate()+1); } if ( compareTime(sTime, eTime, 'between', fTime) ) return true; return false; } /* ************************************************************************* * Erstellung von Datenpunkten ENDE * Trigger aktivieren und Datenpflege für eigene Datenpunkte ENDE /* ************************************************************************* */ /* ************************************************************************* * Hilfsfunktion für Flags Bearbeitung Pushdienste & MODE /* ************************************************************************* */ function getPushModeFlag(mode, noflags) { if (noflags === undefined || !noflags) { if (onClickCheckRun) return getManuellPushFlags(mode); else return getAutoPushFlags(mode); } else { if (onClickCheckRun) return getManuellPushMode(mode); else return getAutoPushMode(mode); } } function getAutoPushMode(mode) { if (onClickCheckRun) return getManuellPushMode(mode, 'man'); else return getManuellPushMode(mode, 'auto'); } function getManuellPushMode(mode, typ) { if (!onClickCheckRun) typ = 'auto'; if (typ === undefined) typ = 'man'; if (mode !== undefined) { let result; for (let a=0; a= w.start && w2.end <= w.end && !w2.favorit) { let test = w.messageHash == w2.messageHash ? 1 : ((w.areaGroup == w2.areaGroup && w.areaID != w2.areaID) ? 2 : 0) ticaLog(4, w.areaGroup +' == ' + w2.areaGroup + ' && ' + w.areaID + ' != ' + w2.areaID + ' = test:' + test) if (test != 0) { w.useAreaGroup = true; ticaLog(2, 'Nr 2: '+ (test == 1 ? 'gleicher Hash' : 'Favorit') + ' - Behalte Warnung mit Headline: ' + w.headline + ' Level: ' + w.level + ' Ort: ' + w.areaID+ ' Ignoriere: ' + w2.headline +' Level:' + w2.level + ' Ort: ' + w2.areaID ); w2.ignored = true; } } if ( w2.start < w.start || w2.end > w.end || w.areaID != w2.areaID || w2.favorit && w.favorit ) continue if (w.level > w2.level) { ticaLog(1, 'Nr 3 Behalte Warnung wegen Überschneidung und höherem Level mit Headline: ' + w.headline + ' Level:' + w.level + ' Ignoriere: ' + w2.headline +' Level:' + w2.level ); w2.ignored = true; } else if (w.altitudeEnd !== undefined && w2.altitudeEnd !== undefined && w.altitudeEnd > w2.altitudeEnd && w.level == w2.level) { if (w.altitudeStart !== undefined && w2.altitudeStart !== undefined && w.altitudeStart > w2.altitudeStart ) w.altitudeStart = w2.altitudeStart; w.repeatCounter = w2.rerepeatCounter ticaLog(1, 'Nr 4 (Level gleich - Höhen unterschiedlich) Behalte Warnung mit Headline:' + w.headline + ' Ignoriere:' + w2.headline); w2.ignored = true; } } } // Entferne Einträge die verlängert wurden in OldDB if (!onClickCheckRun) { for (let a = 0; a < warnDatabase.new.length; a++) { let w = warnDatabase.new[a]; if (w.mode === NINA) continue if (getIndexOfHash(warnDatabase.old, w.hash) != -1) continue; // nur neue Einträge betrachten for (let b = 0; b < warnDatabase.old.length; b++) { let w2 = warnDatabase.old[b]; if ( w.mode !== w2.mode || w.ignored || w2.ignored || w.type !== w2.type || w2.end > w.end || w.level >= attentionWarningLevel || w2.level >= attentionWarningLevel || w.hash == w2.hash || w.areaID != w2.areaID || Math.abs(w2.end - w.end) > 43200000 // Verlängern ignorieren wenn 12 Stunden zwischen den Warnungen liegen. ) continue; if (w2.end >= w.start) { if (w.repeatCounter > 30) { ticaLog(1, 'Nr 5 reset repeatCounter... push message with headline: ' + w.headline); w.repeatCounter = 0; } if (w2.level == w.level) { w.repeatCounter += w2.repeatCounter + 1; let i = getIndexOfHash(warnDatabase.new, w2.hash); if (w.start > w2.start) w.start = w2.start warnDatabase.old.splice(b--, 1); ticaLog(1, 'Nr 5 Entferne Warnung zwecks Verlängerung mit Headline:' + w2.headline); if (i != -1) { warnDatabase.new.splice(a--, 1); if (i <= a) --a; break; } } } } } } for (let a = 0; a < warnDatabase.new.length; a++) { let w = warnDatabase.new[a]; if (isWarnIgnored(w) || w.ignored) { ignoreWarningCount++ } } for (let a = 0; a < warnDatabase.old.length; a++) { let w = warnDatabase.old[a]; if (isWarnIgnored(w) || w.ignored) { ignoreWarningCountOld++ } } warnDatabase.new.sort(function(a, b) { return a.level == b.level ? a.start - b.start : b.level - a.level; }) let collectMode = 0; let emailHtmlWarn = ''; let emailHtmlClear = ''; let emailSend = onClickCheckRun; collectMode = 0; let debugdata = ''; /* Bereich für 'Wetterwarnung gültig bis wurde aufgehoben' */ ticaLog(4, 'Nr 6 Build messages'); for (let i = 0; i < warnDatabase.old.length; i++) { let entry = warnDatabase.old[i]; let headline = entry.headline; let hash = entry.hash; let area = entry.useAreaGroup !== undefined ? entry.areaGroup : entry.areaID; let mode = entry.mode; let picture = entry.picture ? entry.picture + SPACE : ''; if (isWarnIgnored(entry) || entry.ignored) continue; if (DEBUGSENDEMAIL) debugdata += i + SPACE + mode + SPACE + hash + SPACE + getIndexOfHash(warnDatabase.new, hash) + SPACE + (getPushModeFlag(mode) & PUSH).toString(2) + ' ignoreWarningCount)) { ticaLog(4, 'Old Msg with headline:' + headline + ' onClickCheckRun:' + onClickCheckRun +' hash:' +hash); let prefix = '' let end = entry.end ? getFormatDate(entry.end) : null; collectMode |= mode; // Text Entwarnungen if (mode === NINA) { prefix = 'Die Warnung'; } else { prefix = 'Die Wetterwarnung'; } let pushMsg = picture + prefix + getArtikelMode(mode) + "'" + headline + SPACE + area + (end ? " gültig bis " + end + "Uhr'" : '') + " wurde aufgehoben."; // EMAIL if (getPushModeFlag(mode) & EMAIL) { emailHtmlClear += pushMsg + '
'; emailSend = true; } // PUSH // Insgesamt x... anhängen pushMsg += getStringWarnCount(null, warnDatabase.new.length); if ( uTextHtmlMitOhneAlles && mode != NINA ) pushMsg = getShortVersion(entry, true); sendMessage(getPushModeFlag(mode) & PUSH, picture + (mode == NINA ? 'Entwarnung' : 'Wetterentwarnung') + SPACE + (i + 1), pushMsg); ticaLog(4, 'text old:' + pushMsg); // SPEAK pushMsg = headline + (!uSpracheMitOhneAlles ? getArtikelMode(mode, true) + area + (end ? ' gültig bis ' + getFormatDateSpeak(end) + ' Uhr' : ''): '') + ' wurde aufgehoben' + ' . '; if ( uSpracheMitOhneAlles && mode != NINA ) pushMsg = getShortVersion(entry, true) + ', '; if (forceSpeak || compareTime(START, ENDE, 'between')) { sendMessage(getPushModeFlag(mode) & SPEAK, '', pushMsg, entry); } ticaLog(4, 'Sprache old:' + pushMsg); } } if (DEBUGSENDEMAIL) DebugMail = buildHtmlEmail(DebugMail, 'Index Mode Hash Index-New Flags', debugdata, null); let gefahr = false; let count = 0; /* Bereich für 'Neue Amtliche Wetterwarnung' */ for (let i = 0; i < warnDatabase.new.length; i++) { let entry = warnDatabase.new[i]; if ( hashForced !== undefined && entry.hash != hashForced.hash) continue if (entry.repeatCounter > 1 && !onClickCheckRun) continue; let headline = entry.headline; let description = entry.description; let level = entry.level; let instruction = entry.instruction; let hash = entry.hash; let area = entry.useAreaGroup === true ? entry.areaGroup : entry.areaID; let color = entry.color; let mode = entry.mode; let meteo = entry.meteo || ''; let picture = entry.picture ? entry.picture + SPACE : ''; if (DEBUGSENDEMAIL) debugdata += i + SPACE + mode + SPACE + hash + SPACE + getIndexOfHash(warnDatabase.old, hash) + SPACE + (getPushModeFlag(mode)).toString(2) + SPACE + isWarnIgnored(entry) + '= attentionWarningLevel; let isLong = (uHtmlMitBeschreibung && uHtmlMitAnweisungen && (!(mode & ZAMG ) || uZAMGMitMeteoinformationen)) && !uTextHtmlMitOhneAlles; let begin = entry.start ? getFormatDate(entry.start) : '', end = entry.end ? getFormatDate(entry.end) : ''; let sTime = SPACE, bt = (begin || end); if (begin || end) sTime = "gültig "; if (begin) sTime += "vom " + begin + " Uhr"; if ((begin && end)) sTime += SPACE; if (end) sTime += "bis " + end + " Uhr"; // html if ((getPushModeFlag(mode) & CANHTML) != 0) { let html = '' let he = '', de = ''; let prefix = isNewMessage && !onClickCheckRun ? 'Neu: ' : ''; if (uTextHtmlMitOhneAlles) { he = prefix + getShortVersion(entry); } else { if (entry.html !== undefined) { let html = entry.html; if (html.headline) he = prefix + html.headline; else he = prefix + headline; if (uHtmlMitBeschreibung) { if (html.description) de = html.description; else if (entry.htmldesc) de = entry.htmldesc; else de = description; if (meteo && uZAMGMitMeteoinformationen) de += meteo ? '

Wetterinformation:
' + meteo.replace("/n", '
') : ''; if (uHtmlMitAnweisungen) { if (html.instruction && html.instruction.length > 2) de += '

Handlungsanweisungen:
' + html.instruction; else if (instruction && instruction.length > 2) de += '

Handlungsanweisungen:
' + instruction; } if (entry.html.web) de += '

' + entry.html.web; } } else { he = prefix + headline; if (uHtmlMitBeschreibung) { de = description; if (meteo && uZAMGMitMeteoinformationen) de += meteo ? '

Wetterinformation:
' + meteo.replace("/n", '
') : ''; if (uHtmlMitAnweisungen && instruction && instruction.length > 2) { de += '

Handlungsanweisungen:
' + instruction; } } } html = (bt ? sTime + '
' : '') + de; html = html.length > 0 ? html[0].toUpperCase() + html.substring(1) : html; he += getArtikelMode(mode) + area + ':'; } if (entry.repeatCounter == 1 && !onClickCheckRun) he += ' wurde verlängert.'; emailHtmlWarn = buildHtmlEmail(emailHtmlWarn, picture + he, html, color, false); if (entry.repeatCounter == 1 && !onClickCheckRun) html = he; else html = he + html; if (warnDatabase.new.length > 1) html += getStringWarnCount(count, warnDatabase.new.length); let b = getPushModeFlag(mode) & CANHTML & ~EMAIL & ~STATE_HTML; if (isNewMessage && getPushModeFlag(mode) & EMAIL){ emailSend = true; } sendMessage(b, picture + getTopic(mode, level, false, entry.urgency), html, entry, {isLong:isLong, isAnswer: hashForced && hashForced.isAnswer}); todoBitmask &= ~b & ~EMAIL & ~STATE_HTML; } if (!isNewMessage) continue; // Plain text if ((getPushModeFlag(mode) & CANPLAIN & todoBitmask) != 0) { let pushMsg = ''; if (uTextHtmlMitOhneAlles) { pushMsg = getShortVersion(entry); if (todoBitmask & (EMAIL | STATE_HTML)) emailHtmlWarn = buildHtmlEmail(emailHtmlWarn, pushMsg, '', color, false); } else { pushMsg = headline + getArtikelMode(mode) + area; if (entry.repeatCounter == 1 && !onClickCheckRun) { pushMsg += ' wurde verlängert.'; } else { pushMsg += (bt ? NEWLINE + sTime : ''); if (uTextMitBeschreibung) { pushMsg += NEWLINE + NEWLINE + description; if (meteo && uZAMGMitMeteoinformationen) pushMsg += meteo ? NEWLINE + NEWLINE + 'Wetterinformation: ' + meteo : ''; if (uTextMitAnweisungen && !!instruction && typeof instruction === 'string' && instruction.length > 2) { pushMsg += NEWLINE + 'Handlungsanweisungen:' + NEWLINE + instruction; } } } // Anzahl Meldungen erst am Ende zu email hinzufügen if (todoBitmask & (EMAIL | STATE_HTML)) emailHtmlWarn = buildHtmlEmail(emailHtmlWarn, headline + getArtikelMode(mode) + area + ':', pushMsg, color, false); /* ab Level 4 zusätzlicher Hinweis */ if (warnDatabase.new.length > 1) pushMsg += getStringWarnCount(count, warnDatabase.new.length); } let b = getPushModeFlag(mode) & CANPLAIN & todoBitmask & PUSH; sendMessage(b, picture + getTopic(mode, level, false, entry.urgency) + SPACE + count, picture + pushMsg, entry, {isLong:isLong, isAnswer: hashForced && hashForced.isAnswer}) ticaLog(4, 'text new:' + pushMsg); todoBitmask &= ~b; } // Sprache if ((getPushModeFlag(mode) & SPEAK) != 0) { let speakMsg = ''; if ( !uSpracheMitOhneAlles || mode == NINA ) { sTime = SPACE; speakMsg = getTopic(mode, level, true, entry.urgency) + headline + getArtikelMode(mode, true) + area; if (entry.repeatCounter == 1 && !onClickCheckRun) { speakMsg += ' wurde verlängert.'; } else { if (begin || end) sTime += "gültig "; if (begin) sTime += "vom " + getFormatDateSpeak(begin) + " Uhr"; if ((begin && end)) sTime += " "; if (end) sTime += "bis " + getFormatDateSpeak(end) + " Uhr"; speakMsg += SPACE + sTime + '.' + SPACE; if (meteo && uZAMGMitMeteoinformationen) description += meteo ? SPACE + SPACE + 'Wetterinformation: ' + meteo : ''; if (uSpracheMitAnweisungen && !!instruction && typeof instruction === 'string' && instruction.length > 2) { description += SPACE + SPACE + 'Handlungsanweisungen:' + NEWLINE + instruction; } description = replaceTokenForSpeak(description); if (uMaxCharToSpeak === 0 || (speakMsg + description).length <= uMaxCharToSpeak) { if (uSpracheMitBeschreibung) speakMsg += description; } else speakMsg += ' Weiterführende Informationen sind vorhanden.'; } } else { speakMsg = getShortVersion(entry) + ', '; } if (!entry.ignored && !isWarnIgnored(entry) && (forceSpeak || compareTime(START, ENDE, 'between')) && (getPushModeFlag(mode) & SPEAK) != 0) { sendMessage(getPushModeFlag(mode) & SPEAK, '', speakMsg, entry); } ticaLog(4, 'Sprache new:' + speakMsg + ' isWarnIgnored():' + isWarnIgnored(entry)) + 'entry.ignored: ' +entry.ignored; } } } if (DEBUGSENDEMAIL) DebugMail = buildHtmlEmail(DebugMail, 'Index Mode Hash Index-old Flags ignored', debugdata, null); if ((getPushModeFlag(collectMode) & ALLMSG) != 0 && (emailHtmlWarn + emailHtmlClear) && emailSend) { emailHtmlWarn = buildHtmlEmail(emailHtmlWarn, (emailHtmlClear ? 'Aufgehobene Warnungen' : null), emailHtmlClear, 'silver', false); emailHtmlWarn = buildHtmlEmail(emailHtmlWarn, null, getStringWarnCount(null, warnDatabase.new.length), null, true); sendMessage(getPushModeFlag(collectMode) & ALLMSG, (gefahr ? "Wichtige Warnungen" : "Warnungen") + getArtikelMode(collectMode) + "(iobroker)", emailHtmlWarn); } /* Bereich für 'Alle Wetterwarnungen wurden aufgehoben' */ if (!emailHtmlWarn && warnDatabase.new.length == ignoreWarningCount && (warnDatabase.old.length > ignoreWarningCountOld || onClickCheckRun)) { //let notAllDone = onClickCheckRun for (let a = 0; a < warnDatabase.old.length; a++) { collectMode |= warnDatabase.old[a].mode; //if (getIndexOfHash(warnDatabase.new, warnDatabase.old[a].hash, true)) notAllDone = true; } let pushMsg = 'Alle Warnmeldungen' + getArtikelMode(collectMode) + 'wurden aufgehoben.' + getStringIgnoreCount(ignoreWarningCount); // Einen Mode ermitteln der aktiv ist und der das Versenden erlauben würde. if (!getPushModeFlag(collectMode)) collectMode = getPushModeFlag(switchFlags(ALLMODES, collectMode, false) & MODE, true); if (!getPushModeFlag(collectMode)) ticaLog(0,'Keine erlaubten Versandmöglichkeiten im ' + (onClickCheckRun ? 'manuellen Modus über ID: ' + onClickCheckRunCmd : 'Automatikmodus') + ' gefunden!', 'warn'); /* Bereich für Sprachausgabe über SayIt & Alexa & Home24*/ if (forceSpeak || compareTime(START, ENDE, 'between')) { // Ansage über Sayit nur im definierten Zeitbereich sendMessage(getPushModeFlag(collectMode) & SPEAK, '', pushMsg); } ticaLog(4, 'all all:' + pushMsg + ' PUSH' + (getPushModeFlag(collectMode) & PUSH).toString(3) + ' ALLMSG:' + (getPushModeFlag(collectMode) & ALLMSG).toString(3)); let topic = ((collectMode & NINA || !collectMode) ? 'Entwarnungen' : 'Wetterentwarnung'); sendMessage(getPushModeFlag(collectMode) & PUSH, topic, pushMsg, ); sendMessage(getPushModeFlag(collectMode) & ALLMSG, topic + getArtikelMode(collectMode) + '(iobroker)', buildHtmlEmail('', pushMsg, null, 'silver', true)); } if (DEBUGSENDEMAIL) { let a; DebugMail = buildHtmlEmail(DebugMail, 'uPushdienst', 'Binär:' + uPushdienst.toString(2) + ' Decimal:' + uPushdienst.toString(), null); for (a = 0; a < warnDatabase.new.length; a++) DebugMail = buildHtmlEmail(DebugMail, 'warnDatabase.new' + a, JSON.stringify(warnDatabase.new[a])); for (a = 0; a < warnDatabase.old.length; a++) DebugMail = buildHtmlEmail(DebugMail, 'warnDatabase.old' + a, JSON.stringify(warnDatabase.old[a])); DebugMail = buildHtmlEmail(DebugMail, 'warnDatabase.new.length', warnDatabase.new.length.toString(), null); DebugMail = buildHtmlEmail(DebugMail, 'warnDatabase.old.length', warnDatabase.old.length.toString(), null, true); if (DEBUGSENDEMAIL) sendMessage(uPushdienst & EMAIL, 'Debug checkWarningsMain() ' + scriptName, DebugMail); //ticaLog(0,DebugMail); } /* Neue Werte sichern */ ticaLog(4, 'done'); setState(totalWarningCountState, warnDatabase.new.length - ignoreWarningCount, true); warnDatabase.old = cloneObj(warnDatabase.new); function getTopic(mode, level, s, urg) { if (s == undefined) s = false; let topic = mode === NINA ? 'Warnung' : 'Wetterwarnung'; if (urg !== undefined && urg == 1) topic = mode === NINA ? 'Vorwarnung' : 'Wettervorwarnung' let result = ''; result = (level >= attentionWarningLevel) ? 'Wichtige '+topic : s ? '' : topic; return result; } function getShortVersion(entry, removed) { // kurzform let speakMsg ='' if (removed) speakMsg = entry.typename + 'warnung aufgehoben' else { speakMsg = getTopic(entry.mode, entry.level, false, entry.urgency) speakMsg +=' vor ' + entry.typename; } speakMsg +=', ' + (entry.useAreaGroup ? entry.areaID : entry.areaGroup) if (removed) speakMsg +='(' else speakMsg +=', Stufe '; let color = ''; switch (entry.level) { case 0: case 1: color = 'grün'; break; case 2: color = 'gelb'; break; case 3: color = 'orange'; break; case 4: color = 'rot'; speakMsg = 'Achtung! Achtung! Lebensgefahr! ' + speakMsg break; case 5: default: color = 'violet'; } speakMsg += color; if (removed) return speakMsg + ')'; let e = new Date(entry.start); let d = e.getDate() - new Date().getDate(); let s = e.getHours(); let pre = ''; if (s < 5 || s >= 22) pre = 'nacht '; else if (s < 10) pre = 'früh '; else if (s < 12) pre = 'vormittag '; else if (s < 14) pre = 'mittag '; else if (s < 18) pre = 'nachmittag '; else if (s < 22) pre = 'abend '; let day = '' switch (d) { case -2: day = ', seit vorgestern '; break; case -1: day = ', seit gestern '; break; case 0: day = ', ab heute '; break; case 1: day = ', ab morgen '; break; case 2: day = ', ab übermorgen '; break; case 3: case 4: case 5: day = ', in ' + d + ' Tagen '; pre = ''; break; default: day = getFormatDateSpeak(getFormatDate(entry.start)) + " Uhr "; pre = ''; } speakMsg += '' + day + pre return speakMsg; } } /* ************************************************************************* * Hauptfunktion zur Auswahl der Warnungen zum Versenden und Aufbereiten der * Nachrichten ENDE /* ************************************************************************* */ /* ************************************************************************* * Senden der Nachricht über die verschiedenen Möglichkeiten /* ************************************************************************* */ //Versende die Warnungen über die Schienen function sendMessage(pushdienst, topic, msg, entry = null, msgFull = null) { if ((pushdienst & TELEGRAM) != 0) { ticaLog(4, 'send Msg with Telegram'); let edit = false; let nMsg = {text:''}; if (entry) { if (msgFull && !msgFull.isLong && uTelegramReplyMarkupInline){ nMsg.reply_markup = { inline_keyboard: [[{ text: 'mehr', callback_data: '#$WarnscriptLong%&' + String(entry.hash)}]] }; } else if (msgFull && msgFull.isLong && uTelegramReplyMarkupInline){ nMsg.reply_markup = { inline_keyboard: [[{ text: 'weniger', callback_data: '#$WarnscriptShort%&' + String(entry.hash)}]] }; } if (entry.web && entry.webname) { if (nMsg.reply_markup !== undefined) nMsg.reply_markup.inline_keyboard.push = [{ text: entry.webname, url: entry.web }] else nMsg.reply_markup = { inline_keyboard: [[{ text: entry.webname, url: entry.web }]] }; } } if (uTelegramReplyMarkupInline && msgFull && msgFull.isAnswer) { let options = {} edit = true let tempMsg = getState(telegramInstanz + '.communicate.request').val nMsg.user = tempMsg.substring(1, tempMsg.indexOf(']')); options.chat_id = getState(telegramInstanz + ".communicate.requestChatId").val options.message_id = getState(telegramInstanz + ".communicate.requestMessageId").val if (nMsg.reply_markup !== undefined) options.reply_markup = nMsg.reply_markup nMsg.editMessageText = {options} log('editMessageText: Text:' + msg + ' hash:' + (entry ? entry.hash : 'null') ) } if (!uTelegramReplyMarkupInline) { if (nMsg.reply_markup === undefined) nMsg.reply_markup = {}; nMsg.reply_markup.keyboard = uTelegramReplyMarkup.keyboard; } if (!uTelegramAllowNotification) nMsg.disable_notification = true; if (!(telegramUser.length > 0 || telegramChatId.length > 0) || uTelegramUseStdUser || edit) { _sendSplitMessage(TELEGRAM, msg.slice(), nMsg, function(msg, opt) { opt.text = msg; _sendTo(TELEGRAM, telegramInstanz, opt); }); } if (telegramUser.length > 0 && !edit) { let nMsg2 = cloneObj(nMsg); nMsg2.user = telegramUser.join(','); _sendSplitMessage(TELEGRAM, msg.slice(), nMsg2, function(msg, opt) { opt.text = msg; _sendTo(TELEGRAM, telegramInstanz, opt); }); } if (telegramChatId.length > 0 && !edit) { let c = 0; telegramChatId.forEach(function(chatid) { let nMsg2 = cloneObj(nMsg); nMsg2.chatId = chatid; _sendSplitMessage(TELEGRAM, msg.slice(), nMsg2, function(msg, opt) { opt.text = msg; _sendTo(TELEGRAM, telegramInstanz, opt); }); }); } } if ((pushdienst & PUSHOVER) != 0) { ticaLog(4, 'send Msg with Pushover'); let newMsg = { html: 1 }; let usesound = ((deviceList[PUSHOVER].count == undefined || deviceList[PUSHOVER].count == 0) || !(!entry || entry.level < attentionWarningLevel)); newMsg.message = msg; newMsg.title = topic; if (entry) { if (entry.web && entry.web.length < 512) { newMsg.url = entry.web; newMsg.url_title = entry.webname; } newMsg.message = msg.replace(entry.headline, '' + entry.headline + ''); if (entry.level >= attentionWarningLevel) newMsg.priority = 1; } if (!usesound) newMsg.sound = 'none'; else if (uPushoverSound) newMsg.sound = uPushoverSound; if (uPushoverDeviceName) newMsg.device = uPushoverDeviceName; _sendSplitMessage(PUSHOVER, newMsg.message.slice(), newMsg, function(msg, opt, c) { opt.message = msg; if (c > 1) { opt.title += ' Teil ' + c; opt.sound = 'none'; } _sendTo(PUSHOVER, pushoverInstanz, opt); }); } if ((pushdienst & IOGO) != 0) { ticaLog(4, 'send Msg with Iogo'); let j = {}; j.text = msg; j.title = topic; if (ioGoExpiry > 0 ) j.expiry = ioGoExpiry; if (ioGoUser.length > 0) { j.user = ioGoUser[0]; for (let a = 1; a < ioGoUser.length; a++) { j.user += ',' + ioGoUser[a]; } } _sendSplitMessage(IOGO, j.text.slice(), j, function(msg, opt, c) { opt.text = msg; _sendTo(IOGO, ioGoInstanz, opt); }); } if ((pushdienst & STATE) != 0) { setState(mirrorMessageState, msg, true); } if ((pushdienst & STATE_HTML) != 0) { setState(mirrorMessageStateHtml, msg, true); } if ((pushdienst & SPEAK) != 0) { ticaLog(4, 'send Msg with Speak'); _speakTo(pushdienst & SPEAK, msg); } if ((pushdienst & EMAIL) != 0) { ticaLog(4, 'send Msg with Email'); let j = {}; j.html = msg; j.subject = topic; if (senderEmailID[0]) j.from = senderEmailID[0]; if (empfaengerEmailID.length > 0) { for (let a = 0; a < empfaengerEmailID.length; a++) { j.to = empfaengerEmailID[a]; _sendTo(EMAIL, emailInstanz, j); } } else { _sendTo(EMAIL, emailInstanz, j); } } function _sendTo(dienst, a, b) { ticaLog(4, 'send Msg _sendTo dienst:' + dienst); if (deviceList[dienst].count == undefined) { sendTo(a, b); ticaLog(2,'Dienst: ' + a + ' Nachricht: ' + b) } else { setTimeout(function(dienst, a, b) { sendTo(a, b); ticaLog(2,'Dienst: ' + a + ' Nachricht: ' + b) deviceList[dienst].count--; }, (deviceList[dienst].count++ * deviceList[dienst].delay + 20), dienst, a, b); } } // nur einmal pro Mitteilung aufrufen // Element 0 im Array muß immer vorhanden sein. function _speakTo(dienst, msg) { if (_speakToInterval) clearInterval(_speakToInterval); _speakToArray = _addItem(_speakToArray, msg, dienst); _speakToArray = _speakToArray.sort(function(a, b) { return a.startTimeSpeak - b.startTimeSpeak; }); _speakToInterval = setInterval(function() { if (_speakToArray.length > 1) { let entry = _speakToArray[1]; if (entry.startTimeSpeak <= new Date()) { if (entry.part > 1) entry.msg = 'Teil ' + entry.part + ': ' + entry.msg; let nTime = new Date(new Date().getTime() + (deviceList[entry.dienst].delay * (entry.msg + _getMsgCountString(_speakToArray, entry.dienst)).length)+1900); let value = nTime.getTime() - new Date(entry.endTimeSpeak).getTime(); for (let a = 1; a < _speakToArray.length; a++) { if (entry.dienst == _speakToArray[a].dienst) { _speakToArray[a].endTimeSpeak = new Date(_speakToArray[a].endTimeSpeak.getTime() + value); if (a != 1 || value < 0) _speakToArray[a].startTimeSpeak = new Date(_speakToArray[a].startTimeSpeak.getTime() + value); } } if (entry.dienst == HOMETWO) { for (let a = 0; a < idMediaplayer.length; a++) { let Url2 = "http://" + idMediaplayer[a] + "/track = 4fachgong.mp3|tts=" + entry.msg + _getMsgCountString(_speakToArray, entry.dienst); ticaLog(4, 'Url2 :' + Url2); axios.get(Url2) } } else if (entry.dienst == SAYIT) { for (let a = 0; a < idSayIt.length; a++) { setState(idSayIt[a], sayItVolumen[a] + ";" + entry.msg + _getMsgCountString(_speakToArray, entry.dienst)); ticaLog(2,'Dienst: ' + idSayIt[a] + ' Nachricht: ' + sayItVolumen[a] + ";" + entry.msg + _getMsgCountString(_speakToArray, entry.dienst)) } } else if (entry.dienst == ALEXA) { for (let a = 0; a < idAlexaSerial.length; a++) { // Wenn auf Gruppe, keine Lautstärkenregelung möglich if (extendedExists(replacePlaceholder(idAlexaState, idAlexaSerial[a])) && getState(replacePlaceholder(idAlexaState, idAlexaSerial[a])).val) { idAlexaLastState[a].play = true setState(replacePlaceholder(idAlexaPause, idAlexaSerial[a]), true) } if (alexaVolumen[a] && extendedExists(replacePlaceholder(idAlexaVolumen, idAlexaSerial[a]))) { if (idAlexaLastState[a].volumen === undefined) idAlexaLastState[a].volumen = getState(replacePlaceholder(idAlexaVolumen, idAlexaSerial[a])).val if (idAlexaLastState[a].volumen != alexaVolumen[a]) setState(replacePlaceholder(idAlexaVolumen, idAlexaSerial[a]), alexaVolumen[a]); } if (idAlexaLastState[a].timeout) clearTimeout(idAlexaLastState[a].timeout) idAlexaLastState[a].timeout = setTimeout(function(a){ if (idAlexaLastState[a].play) setState(replacePlaceholder(idAlexaPlay, idAlexaSerial[a]), true) if (alexaVolumen[a] && idAlexaLastState[a].volumen !== undefined && idAlexaLastState[a].volumen != alexaVolumen[a]) setState(replacePlaceholder(idAlexaVolumen, idAlexaSerial[a]), idAlexaLastState[a].volumen); idAlexaLastState[a] = {}; }, nTime.getTime() - new Date().getTime() + 500, a) if (alexaVolumen[a]) setState(replacePlaceholder(idAlexa, idAlexaSerial[a]), entry.msg + _getMsgCountString(_speakToArray, entry.dienst)); ticaLog(2,'Dienst: ' + replacePlaceholder(idAlexa, idAlexaSerial[a]) + ' Nachricht: ' + entry.msg + _getMsgCountString(_speakToArray, entry.dienst)) } } ticaLog(4, 'Länge der auszugebenen Sprachnachricht: ' + (entry.endTimeSpeak.getTime() - entry.startTimeSpeak)); _speakToArray.shift(); _speakToArray = _speakToArray.sort(function(a, b) { return a.startTimeSpeak - b.startTimeSpeak; }); } } else clearInterval(_speakToInterval); }, 1000); return; // Hilfunktionen // gibt den letzten Satz zur Sprachausgabe zurück. function _getMsgCountString(arr, dienst) { let msgAppend = ''; let len = arr.slice(1).filter(function(a, b) { return (!!(a.dienst & dienst)) && a.part === 1; }).length - 1; if (len > 0) { if (len == 1) { msgAppend = ' Eine weitere neue Warnung.'; } else { msgAppend = ' Es gibt ' + (len) + ' weitere neue Warnungen.'; } } else { if (warnDatabase.new.length == 0) { if (!onClickCheckRun) msgAppend = ' keine weitere Warnung.'; } else { if (warnDatabase.new.length == 1) msgAppend = ' Insgesamt eine aktive Warnung.'; else msgAppend = ' Insgesamt ' + warnDatabase.new.length + ' aktive Warnungen.'; } } return msgAppend; } // fügt eine Sprachausgabe dem Array hinzu function _addItem(arr, a, dienst) { if ((dienst & HOMETWO) != 0) { let m = deviceList[HOMETWO].delay * a.length + 2000; arr = __addItem(arr, a, HOMETWO, m, 1) } if ((dienst & SAYIT) != 0) { arr = _sendSplitMessage(SAYIT, a.slice(), arr, _splitedSpeakMessage); } if ((dienst & ALEXA) != 0) { arr = _sendSplitMessage(ALEXA, a.slice(), arr, _splitedSpeakMessage); } return arr; // Hilfsunktion function __addItem(arr, a, dienst, m, count) { let t = null; for (let a = arr.length - 1; a >= 0; a--) { if (dienst == arr[a].dienst) { t = arr[a].endTimeSpeak; break; } } t = t || new Date(); let nt = new Date(t); nt.setMilliseconds(t.getMilliseconds() + m); arr.push({ msg: a, dienst: dienst, endTimeSpeak: nt, startTimeSpeak: t, part: count }); return arr; } function _splitedSpeakMessage(dienst, str, c, opt) { let m = deviceList[dienst].delay * str.length + 2000; return __addItem(opt, str, dienst, m, c); } } } function _sendSplitMessage(dienst, str, opt, callback) { let text = '\n* Warnung wurde aufgeteilt *'; let index = deviceList[dienst].maxChar !== undefined ? deviceList[dienst].maxChar - text.length : 0; let e = 0; let c = 1; do { let msg = str; e = 0; if (index != 0 && index < msg.length) { e = _getLastIndexToSplit(msg, index); msg = str.substring(0, e) + text; } if (dienst & SPEAK) { opt = callback(dienst, msg, c++, opt); } else { callback(msg, cloneObj(opt), c++); } if (e != 0) str = str.substring(e).trimLeft(); } while (e != 0) return opt; } function _getLastIndexToSplit(str, index) { let f = str.substring(0, index).match(/..\n|..
|[a-zA-Z][a-z][\.\!\?\:](?= [A-Z])|[a-zA-Z][a-z]\.(?=[A-Z][a-zA-Z]{3})/gi); let e = index; if (f && f.length > 0) e = str.lastIndexOf(f[f.length - 1], index) + f[f.length - 1].length; return e; } } /* ************************************************************************* * Senden der Nachricht über die verschiedenen Möglichkeiten * ENDE /* ************************************************************************* */ /* ************************************************************************* * Datenquelle Trigger /* ************************************************************************* */ // setzt on() für DWD oder UWZ function dataSubscribe() { if (subDWDhandler) unsubscribe(subDWDhandler); if (MODE & DWD && !(enableInternDWD || enableInternDWD2)) { ticaLog(1, 'Nutze Datenabruf für DWD über States in ' + dwdPath); let r = getRegEx(dwdPath, '^'); r += '.*\.object$'; ticaLog(4, 'subscribe path:' + r); subDWDhandler = subscribe({ id: new RegExp(r), change: 'ne' }, onChangeDWD); } if (subUWZhandler) unsubscribe(subUWZhandler); if (MODE & UWZ && !enableInternUWZ) { ticaLog(1, 'Nutze Datenabruf für UWZ über States in ' + uwzPath); let r = getRegEx(uwzPath, '^'); r += '.*\.object$'; ticaLog(4, 'subscribe path:' + r); subUWZhandler = subscribe({ id: new RegExp(r), change: 'ne' }, onChangeUWZ); } if (subNINAhandler) unsubscribe(subNINAhandler); if (MODE & NINA && warncells[NINA].length == 0) { ticaLog(1, 'Nutze Datenabruf für NINA über States in ' + ninaPath); let r = getRegEx(ninaPath, '^'); r += '.*.rawJson$'; ticaLog(4, 'subscribe path:' + r); subNINAhandler = subscribe({ id: new RegExp(r), change: 'ne' }, onChangeNina); } } function onChangeDWD(dp) { if (onChangeTimeoutObj[dp.id]) clearTimeout(onChangeTimeoutObj[dp.id]); onChangeTimeoutObj[dp.id] = setTimeout( function(dp) { onChangeTimeoutObj[dp.id] = null; ticaLog(4, 'onchange DWD id:' + dp.id); onChange(dp, DWD); },500, dp); } function onChangeUWZ(dp) { if (onChangeTimeoutObj[dp.id]) clearTimeout(onChangeTimeoutObj[dp.id]); onChangeTimeoutObj[dp.id] = setTimeout( function(dp) { onChangeTimeoutObj[dp.id] = null; ticaLog(4, 'onchange UWZ id:' + dp.id); onChange(dp, UWZ); },500, dp); } function onChangeNina(dp) { if (onChangeTimeoutObj[dp.id]) clearTimeout(onChangeTimeoutObj[dp.id]); onChangeTimeoutObj[dp.id] = setTimeout( function(dp) { onChangeTimeoutObj[dp.id] = null; ticaLog(4, 'onchange NINA ' + dp.id); onChange(dp, NINA); },500, dp); } // funktion die von on() aufgerufen wird function onChange(dp, mode) { if (addDatabaseData(dp.id, dp.state.val, mode, false)) { ticaLog(4, 'Datenbank wurde geändert - checkWarningsMain():' + autoSendWarnings + ' id:' + dp.id + ' Mode:' + mode); checkWarningsMain() } } /* ************************************************************************* * Datenquelle Trigger ENDE /* ************************************************************************* */ /* ************************************************************************* * Datenbank /* ************************************************************************* */ // Erstes befüllen der Database async function InitDatabase(first) { ticaLog(1, 'InitDatabase() - first run: ' + first); if (firstRun) { setState(totalWarningCountState, 0, true); warnDatabase = { new: [], old: [] }; if ((enableInternDWD)) ticaLog(1,'Standalone DWD Datenabruf aktiviert'); if ((enableInternDWD2)) ticaLog(1,'Standalone DWD2 Datenabruf aktiviert'); if ((enableInternUWZ)) ticaLog(1,'Standalone UWZ Datenabruf aktiviert'); if (warncells[ZAMG].length > 0) ticaLog(1,'Standalone ZAMG Datenabruf aktiviert'); if (warncells[NINA].length > 0) ticaLog(1,'Standalone NINA Datenabruf aktiviert'); if (!((uLogLevel & 4) && DEBUGINGORESTART)) await getDataFromServer(first); if (standaloneInterval) clearSchedule(standaloneInterval); let sec = 18 + Math.round(Math.random()*30); standaloneInterval = schedule(sec + ' */'+intervalMinutes+' * * * *', getDataFromServer); } if (MODE & DWD && !(enableInternDWD || enableInternDWD2)) { _helper($("state[state.id=" + dwdPath + ".*.object]"), DWD, first); } if (MODE & UWZ && !enableInternUWZ) { _helper($("state[state.id=" + uwzPath + ".*.object]"), UWZ, first); } if (MODE & NINA && warncells[NINA].length == 0) { _helper($("state[state.id=" + ninaPath + ".*.rawJson]"), NINA, first); } warnDatabase.new = warnDatabase.new.filter(function(j) { return (j.mode & MODE); }); if (!firstRun) { warnDatabase.new = _filter(warnDatabase.new); warnDatabase.old = _filter(warnDatabase.old); } return; function _helper(arr, mode, first) { for (let a = 0; a < arr.length; a++) { let id = arr[a]; addDatabaseData(id, getState(id).val, mode, first); } } function _filter(database) { if (database && database.length > 0) { database = database.filter(function(j, i){ let b = (-1 == database.findIndex(function(j2, i2){ return i > i2 && j.mode == j2.mode && j.hash == j2.hash; })); if (!b) ticaLog(4, 'filtere: '+JSON.stringify(j)); return b;} ) } return database; } } // Daten vom Server abfragen async function getDataFromServer(first) { if (onStopped) { if (standaloneInterval) clearSchedule(standaloneInterval); return; } if (blockGetDataFromServer > 6) blockGetDataFromServer = 0; if (blockGetDataFromServer++ > 0) return; if (first === undefined) first = false; if (enableInternDWD2 && warncells[DWD].length == 0) { enableInternDWD2 = false; enableInternDWD = false; ticaLog(0,'DWD deaktivieren, keine Warncell vorhanden'); } else if (!enableInternDWD2 && warncells[DWD].length > 0) { enableInternDWD2 = true; enableInternDWD = true; ticaLog(0,'DWD aktivieren, Warncell vorhanden'); } for (let a = 0; a < warncells[DWD].length; a++) { if (warncells[DWD][a][DWD2] === undefined) await _getDataFromServer([internDWDUrl], DWD, first, warncells[DWD][a].id, a); if (warncells[DWD][a][DWD] === undefined) await _getDataFromServer([replacePlaceholder(internDWD2Url, warncells[DWD][a].id)], DWD2, first, warncells[DWD][a].id, a); } if (enableInternUWZ && warncells[UWZ].length == 0) { enableInternUWZ = false; ticaLog(0,'UWZ deaktivieren, keine Warncell vorhanden'); } else if (!enableInternUWZ && warncells[UWZ].length > 0) { enableInternUWZ = true; ticaLog(0,'UWZ aktivieren, Warncell vorhanden'); } for (let a = 0; a < warncells[UWZ].length; a++) { if (enableInternUWZ) await _getDataFromServer([internUWZUrl + warncells[UWZ][a].id], UWZ, first, warncells[UWZ][a].id, a); } for (let a = 0; a < warncells[ZAMG].length; a++) { let url = replacePlaceholder(internZamgUrl,warncells[ZAMG][a].laengen,warncells[ZAMG][a].breiten); await _getDataFromServer([url], ZAMG, first, warncells[ZAMG][a].text, a); } if (warncells[NINA].length) { //internMowasUrl, warncells[NINA][a].laengen,warncells[NINA][a].breiten); await _getDataFromServer(internMowasUrl, NINA, first, '', 0); } await writeRawWarningCount() blockGetDataFromServer = 0; async function _getDataFromServer(url, m, first, area, wcIndex) { ticaLog(2, 'Rufe Daten vom Server ab -' + (m & DWD ? ' DWD' : (UWZ & m ? ' UWZ' : (DWD2 & m ? ' DWD2' : (ZAMG & m ? ' ZAMG' : ' NINA')))) + ' Area: ' + area); let results = []; for (let a=0; a { ticaLog(4, "Status: " + results.status); ticaLog(4, "Url: " + url); if (!results) ticaLog(0,'!results'); if (results === undefined) ticaLog(0,'results === undefined') if (results.status == 200) { return results.data } else { ticaLog(1,'getDataFromServer() 1. Status: ' + results.status); } return null; }) .catch(error => { if (error == undefined) { ticaLog(1, 'getDataFromServer() 2. Fehler im Datenabruf ohne Errorlog') } else if (error.response == undefined) { ticaLog(1, 'getDataFromServer() 3. ' + error + ' Maybe internet is down!', 'warn'); } else if (error.response.status == 404) { ticaLog(1, 'getDataFromServer() 4. ' + error.message + ' ' + error.response.data.msg); } else { ticaLog(1, 'getDataFromServer() 5. ') ticaLog(1, error.response.data); ticaLog(1, error.response.status); ticaLog(1, error.response.headers); } return null; }) if (onStopped) return; if((DWD|DWD2) & m) ticaLog(4, "AREA: " + area); if(UWZ & m) ticaLog(4, "AREA: " + getAreaFromURI(url[a])); if((DWD|DWD2|ZAMG) & m) await processData(area, result, m, first, wcIndex); else if(UWZ & m) await processData(getAreaFromURI(url[a]), result, m, first, wcIndex); else if(NINA & m) { results = results.concat(result); } else { ticaLog(0,'getDataFromServer wrong Mode', 'error'); stopScript(); } } if (onStopped) return; if(NINA & m) { await processData(area, results, m, first, wcIndex); } } async function processData(area, thedata, m, first, wcIndex) { let newOBJ = []; if (thedata) { if ((DWD & m)) { if (!enableInternDWD) return; let jsonString = String(thedata); let newString = jsonString.replace('warnWetter.loadWarnings(', ''); newString = newString.replace(/\);$/sg, ''); // damit findet es diesen String nur am Ende let tOBJ = JSON.parse(newString); if (tOBJ.warnings.hasOwnProperty(area)) { warncells[DWD][wcIndex][DWD] = true; newOBJ = tOBJ.warnings[area]; } else newOBJ = []; } else if (UWZ & m) { newOBJ = thedata.results; if (newOBJ.length) newOBJ.sort((a, b) => b.severity - a.severity); } else if (ZAMG & m) { if (thedata.properties !== undefined) { newOBJ = thedata.properties.warnings; let areaname = thedata.properties.location.properties.name; let ind = warncells[ZAMG].findIndex((a) => a.text == areaname); if (ind === -1) { ticaLog(0,'ZAMG Area: '+ area +' nicht gefunden ') return } area = warncells[ZAMG][ind].id; for (let a= 0; a { let result = b.properties.warnstufeid - a.properties.warnstufeid; if (result) return result; result = a.properties.rawinfo.start - b.properties.rawinfo.start; if (result) return result; result = a.properties.warnid - b.properties.warnid; return result; }); } } else if (DWD2 & m) { if (!enableInternDWD2) return; let tempOBJ = Object(thedata); for(let data in tempOBJ.features) { if (tempOBJ.features[data].properties.WARNCELLID == area) { warncells[DWD][wcIndex][DWD2] = true; newOBJ.push(tempOBJ.features[data].properties); } } if (newOBJ.length) { newOBJ.sort(function(a,b) { let result = getCapLevel(b.SEVERITY) - getCapLevel(a.SEVERITY); if (result) return result; if (b.ONSET === undefined) result = -1; if (a.ONSET === undefined) result += 1; if (result) return result; result = getDateObject(a.ONSET).getTime() - getDateObject(b.ONSET).getTime(); if (result) return result; return JSON.stringify(a).hashCode() - JSON.stringify(b).hashCode(); }); } } else if (NINA & m ) { for (let ni in ninaIdentifier) { if (ninaIdentifier[ni].id < 0) delete ninaIdentifier[ni]; else if (ninaIdentifier[ni].id > 0) ninaIdentifier[ni].id = -1; } newOBJ[0]={}; let tempOBJ = Object(thedata); for (let a=0; a< tempOBJ.length; a++) { let obj = tempOBJ[a]; if (!obj || obj.info === undefined) continue; for (let b=0; b { setTimeout(() => { //log('Polygon auswertung Nina' + ++xyz) resolve(pointInPolygon (polygon, point)); }, 10); }); } function pointInPolygon (polygon, point) { //A point is in a polygon if a line from the point to infinity crosses the polygon an odd number of times let odd = false; polygon[polygon.length - 1] = polygon[polygon.length - 1].split(','); let x = polygon[polygon.length - 1][0]; polygon[polygon.length - 1][0] = Number(polygon[polygon.length - 1][1]) polygon[polygon.length - 1][1] = Number(x) //For each edge (In this case for each point of the polygon and the previous one) for (let i = 0, j = polygon.length - 1; i < polygon.length; i++) { if (!Array.isArray(polygon[i])) { polygon[i] = polygon[i].split(','); let x = polygon[i][0]; polygon[i][0] = Number(polygon[i][1]) polygon[i][1] = Number(x) } //If a line from the point into infinity crosses this edge if (((polygon[i][1] > point[1]) !== (polygon[j][1] > point[1])) // One point needs to be above, one below our y coordinate // ...and the edge doesn't cross our Y corrdinate before our x coordinate (but between our x coordinate and infinity) && (point[0] < ((polygon[j][0] - polygon[i][0]) * (point[1] - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) + polygon[i][0]))) { // Invert odd odd = !odd; } j = i; } //If the number of crossings was odd, the point is in the polygon return odd; }; async function writeResultEntry(warnObj, _i, m, first, area, wcIndex) { let baseChannelId = '' if (DWD & m || DWD2 & m) baseChannelId = internalDWDPath + area + internalWarningEnd; else if (UWZ & m) baseChannelId = internalUWZPath + area + internalWarningEnd; else if (ZAMG & m) baseChannelId = internalZamgPath + area + internalWarningEnd; else if (NINA & m ) baseChannelId = internalMowasPath + area + internalWarningEnd; baseChannelId += (_i == 0 ? '' : _i) + '.'; const oldObject = await getStateAsync(baseChannelId + "object"); if (!firstRun && oldObject && JSON.stringify(warnObj) == JSON.stringify(oldObject.val)) { ticaLog(4, 'Datensatz ' + (_i+1) + ' ist schon vorhanden'); return; } let tempObj = {}; if (m & NINA) { if(addDatabaseData(baseChannelId + statesNINAintern.object.id , {info:[warnObj]}, NINA, first)) { ticaLog(1, 'NINA Warnung gefunden oder entfernt.' + 'RID: ' + randomID); checkWarningsMain() } tempObj[statesNINAintern.onset.id] = warnObj.onset !== undefined ? getDateObject(warnObj.onset).getTime() : Number(""); tempObj[statesNINAintern.description.id] = warnObj.description || ''; tempObj[statesNINAintern.expires.id] = warnObj.expires !== undefined ? getDateObject(warnObj.expires).getTime() : Number(""); tempObj[statesNINAintern.headline.id] = warnObj.headline || ''; tempObj[statesNINAintern.level.id] = warnObj.serverity === undefined || warnObj.serverity === '' ? -1 : getCapLevel(warnObj.serverity); tempObj[statesNINAintern.serverity.id] = warnObj.serverity === undefined ? '' : warnObj.serverity; tempObj[statesNINAintern.type.id] = -1; tempObj[statesNINAintern.object.id] = warnObj; tempObj[statesNINAintern.urgency.id] = warnObj.urgency || ''; tempObj[statesNINAintern.certainty.id] = warnObj.certainty || ''; tempObj[statesNINAintern.event.id] = warnObj.event|| ''; tempObj[statesNINAintern.eventCode.id] = warnObj.eventCode === undefined ? [] : warnObj.eventCode; tempObj[statesNINAintern.web.id] = warnObj.web || ''; tempObj[statesNINAintern.contact.id] = warnObj.RESPONSETYPE === undefined ? '' : warnObj.RESPONSETYPE; tempObj[statesNINAintern.parameter.id] = JSON.stringify(warnObj.parameter) || JSON.stringify([]); tempObj[statesNINAintern.areaDesc.id] = warnObj.area && warnObj.area.areaDesc ? warnObj.area.areaDesc : ''; tempObj[statesNINAintern.sent.id] = warnObj.sent !== undefined ? getDateObject(warnObj.sent).getTime() : Number(""); tempObj[statesNINAintern.category.id] = warnObj.category !== undefined ? warnObj.category : []; for (let a in statesNINAintern) { let dp = statesNINAintern[a]; if (extendedExists(baseChannelId + dp.id)) setState(baseChannelId + dp.id, tempObj[dp.id], true); } } if (MODE & DWD && DWD2 & m) { if(addDatabaseData(baseChannelId + statesDWDintern[6].id , warnObj, DWD2, first)) { ticaLog(1, 'DWD2 Warnung gefunden oder entfernt.' + 'RID: ' + randomID); checkWarningsMain() } const maps = ['gewitter', 'sturm', 'regen', 'schnee', 'nebel', 'frost', 'glatteis', 'tauwetter', 'hitze', 'uv']; tempObj[statesDWDintern[0].id] = warnObj.ONSET !== undefined ? getDateObject(warnObj.ONSET).getTime() : Number(""); tempObj[statesDWDintern[1].id] = warnObj.DESCRIPTION || ''; tempObj[statesDWDintern[2].id] = warnObj.EXPIRES !== undefined ? getDateObject(warnObj.EXPIRES).getTime() : Number(""); tempObj[statesDWDintern[3].id] = warnObj.HEADLINE || ''; tempObj[statesDWDintern[4].id] = warnObj.SEVERITY === undefined || warnObj.SEVERITY === '' ? -1 : getCapLevel(warnObj.SEVERITY); tempObj[statesDWDintern[5].id] = ''; tempObj[statesDWDintern[6].id] = warnObj; tempObj[statesDWDintern[7].id] = tempObj[statesDWDintern[4].id] > 0 ? tempObj[statesDWDintern[4].id] : 0; tempObj[statesDWDintern[8].id] = warnObj.EC_GROUP || ''; tempObj[statesDWDintern[9].id] = -1; if (warnObj.EC_II !== undefined) { if (warningTypesString[DWD2][String(warnObj.EC_II)] !== undefined) { tempObj[statesDWDintern[9].id] = warningTypesString[DWD2][String(warnObj.EC_II)]; } } tempObj[statesDWDintern[10].id] = warnObj.EC_II === undefined || warnObj.EC_II === null ? -1 : parseInt(warnObj.EC_II, 10); tempObj[statesDWDintern[11].id] = warnObj.URGENCY === undefined ? '' : warnObj.URGENCY; tempObj[statesDWDintern[12].id] = warnObj.RESPONSETYPE === undefined ? '' : warnObj.RESPONSETYPE; tempObj[statesDWDintern[13].id] = warnObj.CERTAINTY === undefined ? '' : warnObj.CERTAINTY; tempObj[statesDWDintern[14].id] = warnObj.ALTITUDE === undefined ? 0 : Math.round(warnObj.ALTITUDE * 0.3048); tempObj[statesDWDintern[15].id] = warnObj.CEILING === undefined ? 3000 : Math.round(warnObj.CEILING * 0.3048); tempObj[statesDWDintern[20].id] = warnObj.INSTRUCTION === undefined || warnObj.INSTRUCTION === null ? '' : warnObj.INSTRUCTION tempObj[statesDWDintern[16].id] = tempObj.level !== -1 ? getLevelColor(tempObj.level) : ''; tempObj[statesDWDintern[17].id] = tempObj.headline ? _createHTMLtext(tempObj, tempObj.headline, '') : ''; tempObj[statesDWDintern[18].id] = tempObj.headline ? _createHTMLtext(tempObj, tempObj.headline, [tempObj.description]) : ''; tempObj[statesDWDintern[19].id] = tempObj.headline ? _createHTMLtext(tempObj, tempObj.headline, [tempObj.description, tempObj.instruction]) : ''; let a try { for (a = 0; a < statesDWDintern.length; a++) { let dp = statesDWDintern[a]; if (extendedExists(baseChannelId + dp.id)) await setStateAsync(baseChannelId + dp.id, tempObj[dp.id], true); } } catch (e) { ticaLog(0, 'Fehler in SetState() #1 ' + e +' index' + a) ticaLog(0, 'Fehler in SetState() #1 Obj:' + tempObj) } } if (MODE & DWD & m) { if(addDatabaseData(baseChannelId + statesDWDintern[6].id, warnObj, DWD, first)) { ticaLog(1, 'DWD Warnung gefunden oder entfernt.' + 'RID: ' + randomID); checkWarningsMain() } const maps = ['gewitter', 'sturm', 'regen', 'schnee', 'nebel', 'frost', 'glatteis', 'tauwetter', 'hitze', 'uv']; tempObj[statesDWDintern[0].id] = warnObj.start || Number(""); tempObj[statesDWDintern[1].id] = warnObj.description || ''; tempObj[statesDWDintern[2].id] = warnObj.end || Number(""); tempObj[statesDWDintern[3].id] = warnObj.headline || ''; tempObj[statesDWDintern[4].id] = warnObj.level === undefined || warnObj.level === null ? -1 : parseInt(warnObj.level, 10)-1; tempObj[statesDWDintern[6].id] = warnObj; tempObj[statesDWDintern[7].id] = warnObj.level > 1 ? warnObj.level - 1 : 0; tempObj[statesDWDintern[8].id] = warnObj.event || ''; tempObj[statesDWDintern[9].id] = warnObj.type === undefined || warnObj.type === null ? -1 : parseInt(warnObj.type, 10); tempObj[statesDWDintern[10].id] = warnObj.EC_II === undefined || warnObj.EC_II === null ? -1 : parseInt(warnObj.EC_II, 10); tempObj[statesDWDintern[5].id] = ''; tempObj[statesDWDintern[11].id] = warnObj.URGENCY === undefined ? '' : warnObj.URGENCY; tempObj[statesDWDintern[12].id] = warnObj.RESPONSETYPE === undefined ? '' : warnObj.RESPONSETYPE; tempObj[statesDWDintern[13].id] = warnObj.CERTAINTY === undefined ? '' : warnObj.CERTAINTY; tempObj[statesDWDintern[14].id] = warnObj.altitudeStart === undefined || warnObj.altitudeStart == null ? 0 : warnObj.altitudeStart; tempObj[statesDWDintern[15].id] = warnObj.altitudeEnd === undefined || warnObj.altitudeEnd == null? 3000 : warnObj.altitudeEnd; tempObj[statesDWDintern[20].id] = warnObj.instruction === undefined || warnObj.instruction == null? '' : warnObj.instruction; tempObj[statesDWDintern[16].id] = tempObj.level !== -1 ? getLevelColor(tempObj.level) : ''; tempObj[statesDWDintern[17].id] = tempObj.headline ? _createHTMLtext(tempObj, tempObj.headline, '') : ''; tempObj[statesDWDintern[18].id] = tempObj.headline ? _createHTMLtext(tempObj, tempObj.headline, [tempObj.description]) : ''; tempObj[statesDWDintern[19].id] = tempObj.headline ? _createHTMLtext(tempObj, tempObj.headline, [tempObj.description, tempObj.instruction]) : ''; for (let a = 0; a < statesDWDintern.length; a++) { let dp = statesDWDintern[a]; if (extendedExists(baseChannelId + dp.id)) setState(baseChannelId + dp.id, tempObj[dp.id], true); } } if (MODE & ZAMG & m) { if (addDatabaseData(baseChannelId + statesZAMGintern[6].id, warnObj, m, first)){ ticaLog(1, 'ZAMG Warnung gefunden oder entfernt.' + 'RID: ' + randomID); checkWarningsMain() } tempObj[statesZAMGintern[6].id] = warnObj; tempObj[statesZAMGintern[10].id] = warnObj.area === undefined ? '' : warnObj.area ; let plainWarnObj = Object.entries(warnObj); if (plainWarnObj.length > 0) { tempObj[statesZAMGintern[7].id] = warnObj.properties.warntypid; tempObj[statesZAMGintern[9].id] = warningTypesString[ZAMG][warnObj.properties.warntypid][0]; tempObj[statesZAMGintern[0].id] = Number(warnObj.properties.rawinfo.start)*1000; tempObj[statesZAMGintern[1].id] = Number(warnObj.properties.rawinfo.end)*1000; } else { tempObj[statesZAMGintern[7].id] = -1 tempObj[statesZAMGintern[9].id] = 'n/a'; tempObj[statesZAMGintern[0].id] = Number(''); tempObj[statesZAMGintern[1].id] = Number(''); } for (let a = 0; a < statesZAMGintern.length; a++) { let data = statesZAMGintern[a]; if (statesZAMGintern[a].json !== undefined) { let def = null; if (data.options.type == 'string') def = ''; else if (data.options.type == 'object') def = {}; else if (data.options.type == 'number') def = Number(''); else def = null; try { tempObj[data.id] = warnObj.properties !== undefined && warnObj.properties[data.json] !== undefined && warnObj.properties[data.json] ? warnObj.properties[data.json] : def; } catch(e) { ticaLog(0,warnObj,'error'); } } } if (tempObj.level) tempObj.level += 1 tempObj[statesZAMGintern[13].id] = getLevelColor(tempObj.level, ZAMG); tempObj[statesZAMGintern[14].id] = tempObj.type === -1 ? '' : 'Warnung vor ' + warningTypesString[ZAMG][tempObj.type][0]; tempObj[statesZAMGintern[11].id] = plainWarnObj.length == 0 ? '' : _createHTMLtext(tempObj,tempObj.headline,null); let text = [tempObj.auswirkungen !== '' ? '
' + (tempObj.text + '
' + tempObj.auswirkungen).replace(/\\n\*/g, '*').replace(/\*/g, '
*').replace(/\\n/g, '
') : '']; tempObj[statesZAMGintern[12].id] = plainWarnObj.length == 0 ? '' : _createHTMLtext(tempObj, tempObj.headline, text); text.push (tempObj.empfehlungen !== '' ? '
' + tempObj.empfehlungen.replace(/\\n\*/g, '*').replace(/\*/g, '
*').replace(/\\n/g, '
') : '') text.push (tempObj.meteotext !== '' ?'
' + tempObj.meteotext.replace(/\\n\*/g, '*').replace(/\*/g, '
*').replace(/\\n/g, '
'):''); tempObj[statesZAMGintern[15].id] = plainWarnObj.length == 0 ? '' : _createHTMLtext(tempObj, tempObj.headline, text); for (let a = 0; a < statesZAMGintern.length; a++) { let dp = statesZAMGintern[a]; if (extendedExists(baseChannelId + dp.id)) setState(baseChannelId + dp.id, tempObj[dp.id], true); } } if (MODE & UWZ & m) { if (addDatabaseData(baseChannelId + statesUWZintern[6].id, warnObj, m, first)){ ticaLog(1, 'UWZ Warnung gefunden oder entfernt.' + 'RID: ' + randomID); checkWarningsMain() } tempObj[statesUWZintern[6].id] = warnObj; tempObj[statesUWZintern[0].id] = warnObj.dtgStart !== undefined ? warnObj.dtgStart * 1000 : Number(''); tempObj[statesUWZintern[1].id] = warnObj.dtgEnd !== undefined ? warnObj.dtgEnd * 1000 : Number(''); tempObj[statesUWZintern[7].id] = warnObj.severity || 0; tempObj[statesUWZintern[10].id] = warnObj.type || 0; if (warnObj.payload !== undefined) { tempObj[statesUWZintern[2].id] = warnObj.payload.translationsLongText.DE; tempObj[statesUWZintern[3].id] = warnObj.payload.translationsShortText.DE; tempObj[statesUWZintern[4].id] = _getUWZLevel(warnObj.payload.levelName); tempObj.urgency = _getUWZUrgency(warnObj.payload.levelName); tempObj[statesUWZintern[5].id] = getLevelColor(warnObj.severity, UWZ); let headline = ''; if (tempObj.urgency !== undefined && tempObj.urgency == 1) headline += "Vorwarnung vor "; else headline += "Warnung vor "; headline += warningTypesString[UWZ][tempObj.type]; tempObj[statesUWZintern[11].id] = headline; tempObj[statesUWZintern[8].id] = _createHTMLtext(tempObj, headline, [warnObj.payload.translationsShortText.DE]); tempObj[statesUWZintern[9].id] = _createHTMLtext(tempObj, headline, [warnObj.payload.translationsLongText.DE]); tempObj[statesUWZintern[12].id] = _createHTMLtext(tempObj, headline, [warnObj.payload.translationsLongText.DE]); } else { tempObj[statesUWZintern[2].id] = ''; tempObj[statesUWZintern[3].id] = ''; tempObj[statesUWZintern[4].id] = 0; tempObj.uwzUrgency = 0; tempObj[statesUWZintern[5].id] = ''; tempObj[statesUWZintern[8].id] = ''; tempObj[statesUWZintern[9].id] = ''; tempObj[statesUWZintern[11].id] = ''; tempObj[statesUWZintern[12].id] = ''; } for (let a = 0; a < statesUWZintern.length; a++) { let dp = statesUWZintern[a]; if (extendedExists(baseChannelId + dp.id)) setState(baseChannelId + dp.id, tempObj[dp.id], true); } function _getUWZLevel(warnName) { let result = -1; // -1 is an error! let alert = warnName.split("_"); let colors = ["green", "darkgreen", "yellow", "orange", "red", "violet"]; if (alert[0] == "notice") { result = 1; } else if (alert[1] == "forewarn") { result = 2; } else { result = colors.indexOf(alert[2]); } return result; } function _getUWZUrgency(warnName) { let result = 0; let alert = warnName.split("_"); if (alert[1] == "forewarn") { result = 1; } else { result = 2; // immediate; } return result; } } function _createHTMLtext(w, headline, text) { let html = '
'; html += '

'; html += headline; html += "

"; html += "

Zeitraum von " + formatDate(new Date(w.begin), "WW, DD. OO YYYY hh:mm") + " Uhr bis " + formatDate(new Date(w.end), "WW, DD. OO YYYY hh:mm") + " Uhr

"; if (text !== undefined && Array.isArray(text)) { for (let a = 0; a'; } } } html += "
"; return html; } } function getAreaFromURI(uri) { let searchstr = "&areaID="; let n = uri.search(searchstr); let result = uri.slice(n + searchstr.length, uri.length); return result; } } async function writeRawWarningCount () { let warnObjs = $('state(state.id=' + mainStatePath + 'data.*.object)'); if (warnObjs.length>0) { let countObj = {}; let mpath = mainStatePath + 'data'; for (let a = 0; a < warnObjs.length;a++){ let id = warnObjs[a]; let has = false; const theData = await getStateAsync(id); if (theData && theData.val) { has = Object.entries(theData.val).length > 0; } let x = 0; id = id.substr(0,id.lastIndexOf('.')); while (mpath !== id && x++ <4) { id = id.substr(0,id.lastIndexOf('.')); countObj[id] = (countObj[id] === undefined ? 0 : countObj[id]) + (has ? 1 : 0); } } for (let id in countObj) { if (onStopped) return; try { let nid = id + '.rawTotalWarnings' if (!extendedExists(nid)) { await createStateAsync(nid,{ read:true, write:false, type:'number', name:'Gesamtwarnungsanzahl der Unterebenen'}); } setState(nid, countObj[id], true); } catch(e) { ticaLog(0,'Fehler in getDataFromServer()', 'error'); } } } } async function addWarncell(obj, i){ let wc = ''; let id = ''; let restart = false; let wcname = '' if ((typeof(obj) === 'object')) { if (obj.state.ack) return; let e = obj.id.split('.'); i = MODES.findIndex((a) => a.text.toLowerCase() == e[e.length-2]) wc = obj.state.val id = obj.id; restart = true; } else { wc = obj; } let warncellid = mainStatePath + 'config.basiskonfiguration.warnzelle.'; let index=-1; let folder = '' let breiten = 0, laengen = 0; switch (MODES[i].mode) { case DWD: wcname = await testValueDWD2(wc); if (!wcname) { if(id) setState(id,'Fehler', true); return; } warncellid += MODES[i].text.toLowerCase() +'.'+ wc; folder = internalDWDPath; if ((index=warncells[DWD].findIndex(w => wc == w.id)) == -1 ) { warncells[DWD].push({id:wc, text:wcname, area:''}); index = warncells[DWD].length-1; } else warncells[DWD][index].text = wcname; break; case UWZ: if (id) { let t = id.split('.'); if (getEndfromID(id) == 'addId#') { t[t.length-1] = 'addName#'; wcname = getState(t.join('.')).val; if (!wcname || wcname == 'Fehler') { return; } setState(id,'',true); setState(t.join('.'),'',true); } else if (getEndfromID(id) == 'addName#') { t[t.length-1] = 'addId#'; wcname = wc; wc = null; wc = getState(t.join('.')).val; if (!wc) { return; } setState(id,'',true); setState(t.join('.'),'',true); } } index=warncells[UWZ].findIndex(w => wc == w.id); if (index == -1) { warncells[UWZ].push({id:wc, text:wcname, area:''}); index = warncells[UWZ].length-1 } wcname = warncells[UWZ][index].text; warncellid += MODES[i].text.toLowerCase() +'.'+ wc; if (!wcname) { if (await existsStateAsync(warncellid)) { wcname = getObject(warncellid).common.name; } } if (!wcname) { ticaLog(0,'Fehler 2#'); return; } folder = internalUWZPath; break; case ZAMG: if (id) { let t = id.split('.'); t[t.length-1] ='addLat#'; const lat = await getStateAsync(t.join('.')); t[t.length-1] = 'addLong#'; const long = await getStateAsync(t.join('.')); if (!lat.val || !long.val || lat.val == 'Fehler' || long.val == 'Fehler') { return; } breiten = lat.val; laengen = long.val; wc = breiten + '/' + laengen; wc = wc.replace(/\./g,'#'); } else { let ar = wc.replace(/\#/g,'.').split('/'); breiten = Number(ar[0]); laengen = Number(ar[1]); } wcname = await getZamgName(breiten, laengen); if (!wcname || wcname == 'Fehler') { if (id) { let t = id.split('.'); t[t.length-1] ='addLat#'; setState(t.join('.'),'Fehler', true); t[t.length-1] = 'addLong#'; setState(t.join('.'),'Fehler', true); } return; } else { if (id) { let t = id.split('.'); t[t.length-1] ='addLat#'; setState(t.join('.'),'', true); t[t.length-1] = 'addLong#'; setState(t.join('.'),'', true); } } index=warncells[ZAMG].findIndex(w => wc == w.id); if (index == -1) { warncells[ZAMG].push({breiten:breiten, laengen:laengen, text:wcname, id:wc, area:''}); index = warncells[ZAMG].length-1 } warncellid += MODES[i].text.toLowerCase() +'.'+ wc; if (!wcname) { if (await existsStateAsync(warncellid)) { wcname = getObject(warncellid).common.name; } } if (!wcname) { ticaLog(0,'Fehler 3#'); return; } warncells[ZAMG][index].text = wcname; folder = internalZamgPath; for (let i = 0; i < numOfWarnings; i++) { let p = folder + wc + internalWarningEnd + (i == 0 ? '' : i) + '.'; for (let a = 0; a < statesZAMGintern.length; a++) { if (onStopped) return; let dp = statesZAMGintern[a]; let id = p + dp.id; if (!await existsStateAsync(id)) { await createStateAsync(id, dp.options,); } } } break; case NINA: if (id) { let t = id.split('.'); t[t.length-1] ='addLat#'; const lat = await getStateAsync(t.join('.')); t[t.length-1] = 'addLong#'; const long = await getStateAsync(t.join('.')); t[t.length-1] = 'addName#'; let wn = await getStateAsync(t.join('.')); if (!lat.val || !long.val || lat.val == 'Fehler' || long.val == 'Fehler' || !wn.val || wn.val == 'Fehler' ) { return; } breiten = lat.val; laengen = long.val; wcname = wn.val; wc = breiten + '/' + laengen; wc = wc.replace(/\./g,'#'); } else { let ar = wc.replace(/\#/g,'.').split('/'); breiten = Number(ar[0]); laengen = Number(ar[1]); } index=warncells[NINA].findIndex(w => wc == w.id); if (index == -1) { warncells[NINA].push({id:wc, breiten:breiten, laengen:laengen, text:wcname, area:''}); index = warncells[NINA].length-1 } wcname = warncells[NINA][index].text; warncellid += MODES[i].text.toLowerCase() +'.'+ wc; if (!wcname) { if (await existsStateAsync(warncellid)) { wcname = getObject(warncellid).common.name; } } if (!wcname || wcname == 'Fehler') { if (id) { let t = id.split('.'); t[t.length-1] ='addLat#'; setState(t.join('.'),'Fehler', true); t[t.length-1] = 'addLong#'; setState(t.join('.'),'Fehler', true); t[t.length-1] = 'addName#'; setState(t.join('.'),'Fehler', true); } return; } else { if (id) { let t = id.split('.'); t[t.length-1] ='addLat#'; setState(t.join('.'),'', true); t[t.length-1] = 'addLong#'; setState(t.join('.'),'', true); t[t.length-1] = 'addName#'; setState(t.join('.'),'', true); } } warncells[NINA][index].text = wcname; folder = internalMowasPath; break; default: ticaLog(0,'Unbekannter Mode in addWarncell', 'error'); return; } if (index != -1) warncells[MODES[i].mode][index].area = warncells[MODES[i].mode][index].text if (!await existsStateAsync(warncellid)) { await createStateCustomAsync(warncellid, wcname, {name: wcname,type: "string",def:wcname, read: true,write: true},); } else { if (getObject(warncellid).common.type !== 'string') { await extendObjectAsync(warncellid, { common:{ type: 'string', def:wcname } }) await setStateAsync(warncellid, wcname, true); } else { warncells[MODES[i].mode][index].area = getState(warncellid).val; if (warncells[MODES[i].mode][index].text === undefined) warncells[MODES[i].mode][index].text = warncells[MODES[i].mode][index].area if (warncells[MODES[i].mode][index].text.includes(warncells[MODES[i].mode][index].area) || warncells[MODES[i].mode][index].area.includes('#') ) { for (let a = 0; a < warncells[MODES[i].mode].length; a++) warncells[MODES[i].mode][a].favorit = false; warncells[MODES[i].mode][index].favorit = true; warncells[MODES[i].mode][index].area = warncells[MODES[i].mode][index].area.replace('#','') warncells[MODES[i].mode][index].text = warncells[MODES[i].mode][index].text.replace('#','') } let sfavorit = false; for (let a = 0; a < warncells[MODES[i].mode].length; a++) if (warncells[MODES[i].mode][a].favorit) sfavorit = true; if (!sfavorit) warncells[MODES[i].mode][0].favorit = true; } } // setzte den Namen für Datenpunkte unter data if (!(await existsObjectAsync(folder + wc)) || getObject(folder + wc).common.name != wcname) { await extendObjectAsync (folder + wc, { type: 'channel', common: { name: wcname } }); } }; async function getZamgName(lat, long) { ticaLog(2, 'Rufe Zamg Area daten vom Server a'); if (onStopped) return false; const data = await axios.get(replacePlaceholder(internZamgUrl,long,lat)) .then(results => { ticaLog(4, "Status: " + results.status); if (!results) ticaLog(0,'!results'); if (results === undefined) ticaLog(0,'results === undefined') if (results.status == 200) { return results.data } else { ticaLog(1,'testValueDWD2() 1. Status: ' + results.status); return undefined; } }) .catch(error => { if (error == undefined) { ticaLog(1, 'getZamgName() 2. Fehler im Datenabruf ohne Errorlog') } else if (error.response == undefined) { ticaLog(1, 'getZamgName() 3. ' + error + ' Maybe internet is down!', 'warn'); } else if (error.response.status == 404) { ticaLog(1, 'getZamgName() 4. ' + error.message); } else { ticaLog(1, 'getZamgName() 5. ' + error.response.data); ticaLog(1, error.response.status); ticaLog(1, error.response.headers); } return undefined; }) if (data === undefined) return false; if (data.properties === undefined) return false; return data.properties.location.properties.name; } async function testValueDWD2 (value) { const result = await _testValueDWD2(value); templist[DWD].list = undefined; return result } async function _testValueDWD2 (value) { ticaLog(2, 'Rufe DWD Warnzellenbezeichnung vom Server ab'); if (onStopped) return false; if (value === undefined) value = warncells[DWD]; else value = [{id:value, single: true}]; for (let a = 0; a < value.length;a++) { const result = await axios.get(replacePlaceholder(interngetNameDWD2Url,value[a].id )) .then(results => { ticaLog(4, "Status: " + results.status); if (!results) ticaLog(0,'!results'); if (results === undefined) ticaLog(0,'results === undefined') if (results.status == 200) { return results.data } else { ticaLog(1,'testValueDWD2() 1. Status: ' + results.status); return undefined; } }) .catch(error => { if (error == undefined) { ticaLog(1, 'testValueDWD2() 2. Fehler im Datenabruf ohne Errorlog') } else if (error.response == undefined) { ticaLog(1, 'testValueDWD2() 3. ' + error + ' Maybe internet is down!', 'warn'); } else if (error.response.status == 404) { ticaLog(1, 'testValueDWD2() 4. ' + error.message); } else { ticaLog(1, 'testValueDWD2() 5. ' + error.response.data); ticaLog(1, error.response.status); ticaLog(1, error.response.headers); } return undefined; }) if ((result && result.features && result.features.length && result.features[0] && result.features[0].properties && result.features[0].properties.KURZNAME)) { let city = result.features[0].properties.KURZNAME if (value[a].single === undefined) { warncells[DWD][a].text = city ticaLog(1, 'DWD Warncell-Id: ' + warncells[DWD][a].id + ' gefunden: '+ warncells[DWD][a].text ); } else return city; } else { if (templist[DWD].list === undefined) { templist[DWD].list = await axios.get('https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv?__blob=publicationFile&v=3') .then(results => { ticaLog(4, "Status: " + results.status); if (!results) ticaLog(0,'!results'); if (results === undefined) ticaLog(0,'results === undefined') if (results.status == 200) { return results.data } else { ticaLog(1,'testValueDWD2() 1. Status: ' + results.status); return undefined; } }) .catch(error => { if (error == undefined) { ticaLog(1, 'testValueDWD2() 6. Fehler im Datenabruf ohne Errorlog') } else if (error.response == undefined) { ticaLog(1, 'testValueDWD2() 7. ' + error + ' Maybe internet is down!', 'warn'); } else if (error.response.status == 404) { ticaLog(1, 'testValueDWD2() 8. ' + error.message); } else { ticaLog(1, 'testValueDWD2() 9. ' + error.response.data); ticaLog(1, error.response.status); ticaLog(1, error.response.headers); } return undefined; }) } if (templist[DWD].list === undefined) return false; let i = -1; let data = templist[DWD].list if ((i = data.indexOf(value[a].id)) != -1) { let b = data.indexOf(';',i); let e = data.indexOf(';',++b); let city = data.substr(b, e - b) if (value[a].single === undefined) { warncells[DWD][a].text = city ticaLog(1, 'DWD Warncell-Id: ' + warncells[DWD][a].id + ' gefunden: '+ warncells[DWD][a].text ); } else return city; } else if (value[a].single !== undefined) { ticaLog(0,'Warnzelle '+ value[a].id +' für DWD nicht gefunden.','warn'); return false; } } } } // für Objekt zur Database hinzu function addDatabaseData(id, value, mode, old) { let warn = null; let change = false; // value muß ein Object sein, value: String/Object, abfrage auf Null/undefiniert ist nur zur Sicherheit. if (!value || value === undefined ) value = {}; // Kompatibilität zur Stableversion if (typeof value === 'string' ) value = JSON.parse(value); ticaLog(4, "1. addDatabaseData() ID + JSON:" + id + ' - ' + JSON.stringify(value)); if (mode & (UWZ |DWD | DWD2 | ZAMG)) { change = removeDatabaseDataID(id); if (Object.entries(value).length > 0 ) { warn = getDatabaseData(value, mode); if (warn) { let m = mode == DWD2 ? DWD : mode; warn.areaGroup = value.warncellObj === undefined ? '' : 'für die Region ' + value.warncellObj.area; warn.area = value.warncellObj === undefined ? '' : value.warncellObj.area; warn.areaID = "für " + getRegionName(id, m) warn.favorit = value.warncellObj === undefined || value.warncellObj.favorit === undefined ? false : value.warncellObj.favorit warn.wcID = value.warncellObj === undefined || value.warncellObj.id === undefined ? '' : value.warncellObj.id warn.hash = JSON.stringify(warn).hashCode(); warn.id = id; warnDatabase.new.push(warn); if (old) warnDatabase.old.push(warn); change = warnDatabase.old.findIndex(function(j){return j.hash == warn.hash}) == -1; if (!change) { if (old) ticaLog(1, "Init! id: " + id + " headline: " + warn.headline); else ticaLog(2, "No change! id: " + id + " headline: " + warn.headline); } else ticaLog(1,"Add UWZ/DWD/ZAMG warning to database. id: " + id + " headline: " + warn.headline); } } else if (change) ticaLog(1,"Remove Warning UWZ/DWD with id: " + id); } else if (mode == NINA) { // Nina benutzt keine eindeutigen Ids für Warnungen, so dass das löschen woanders erfolgen muß. if (value.info === undefined || !Array.isArray(value.info)) return false; let tempArr = []; let grouphash = 0; // sammele die neuen Daten for (let a = 0; a < value.info.length; a++) { warn = getDatabaseData(value.info[a], mode); // Warnungen nur aufnehmen wenn sie nicht beendet sind. Null berücksichtigt. if (warn && (!warn.end || new Date(warn.end) > new Date())) { warn.identifier = value.identifier === undefined ? "" : value.identifier; warn.sender = value.sender === undefined ? "" : value.sender; warn.areaID = "für " + getRegionName(id, NINA) warn.hash = JSON.stringify(warn).hashCode(); warn['areaGroup'] = '' warn['favorit'] = false warn['wcID'] = '' // setzte start auf das Sendungsdatum, aber nicht im Hash berücksichtigen, ist keine neue Nachricht nur weil sich das datum ändert. warn.start = warn.start || value.sent === undefined ? warn.start : getDateObject(value.sent).getTime(); warn.id = id; // davon ausgehend das die Nachrichten immer gleich sortiert sind und der NINA-Adapter das nicht umsortiert sollte der Hash der ersten Nachrichten // immer der selbe sein. Benutze diesen um die Gruppe an Nachrichten zu identifizieren. if (!grouphash) grouphash = warn.hash; warn.grouphash = grouphash; tempArr.push(warn); ticaLog(4, "Added to tempdatabase"); } } // Vergleiche vorhandene und neue Daten wenn hash = hash aktualisiere ID, wenn nicht und ID = ID setzte ID auf null if (tempArr.length > 0) { for (let a = 0; a < tempArr.length; a++) { for (let b = 0; b < warnDatabase.new.length; b++) { if (warnDatabase.new[b].mode !== NINA) continue if (tempArr[a].hash == warnDatabase.new[b].hash) { if (warnDatabase.new[b].id != tempArr[a].id) { ticaLog(2,"Update database Nina warning old id<>new id. headline: " +warn.headline ); } warnDatabase.new[b].id = tempArr[a].id; tempArr.splice(a--, 1); break; } else if ( tempArr[a].id == warnDatabase.new[b].id && tempArr[a].grouphash != warnDatabase.new[b].grouphash ) { if (tempArr[a].messageHash == warnDatabase.new[b].messageHash) { ticaLog(2,"Update database same warning, same id, different dates: " +warn.headline ); let i = getIndexOfHash(warnDatabase.old, warnDatabase.new[b].hash); if (i != -1) warnDatabase.old[i] = tempArr[a]; warnDatabase.new[b] = tempArr[a]; tempArr.splice(a--, 1); break; } else { ticaLog(1, "warnDatabase.new set id to null - duplicate id and wrong grouphash: " + warnDatabase.new[b].headline ); warnDatabase.new[b].id = null; } } } } } if (tempArr.length > 0) { for (let a = 0; a < tempArr.length; a++) { warn = tempArr[a]; warnDatabase.new.push(warn); if (old) warnDatabase.old.push(warn); ticaLog(1, "Add Nina warning to database. headline: " + warn.headline ); } change = true; } } change = old !== undefined && old ? false : change; setState(totalWarningCountState, warnDatabase.new.length, true); setAlertState() return change; // vergleich regionName und die Obj.id und gib den benutzerfreundlichen Namen zurück. function getRegionName(id, mode) { if (!Array.isArray(warncells[mode]) || warncells[mode].length == 0) return ""; for (let a = 0; a < warncells[mode].length; a++) { if (id.includes(warncells[mode][a].id)) { return warncells[mode][a].text; } } return ""; } } function isWarnIgnored(warn) { if (warn.level < attentionWarningLevel) { if ((uFilterList & warn.mode) != 0) return true; if ((warn.mode & NINA) != 0) { if (uAutoNinaFilterList.indexOf(warn.sender) != -1) { ticaLog(4, 'Filter: \'' + warn.sender + '\' ist in uAutoNinaFilterList - level: ' + warn.level); return true; } } } return false; } function getIndexOfHash(db, hash, notIgnored) { return db.findIndex(function(j) { return j.hash === hash && (notIgnored === undefined || !j.ignored) ; }); } // Wandelt den Datensatz in ein internes Format um function getDatabaseData(warn, mode){ if (!warn || warn === undefined || typeof warn !== 'object' || Object.entries(warn).length == 0 || warn === {} || warn =='{}') { return null; } let result={}; if (mode === DWD) { if ( warn.altitudeStart > maxhoehe || (warn.altitudeEnd && warn.altitudeEnd < minhoehe) || warn.level < minlevel ) {ticaLog(2, 'Übergebenene Warnung DWD verworfen');return null;} result['mode'] = DWD; result['headline'] = warn.headline === undefined ? '' : warn.headline; result['start'] = warn.start === undefined ? null : warn.start || null; result['end'] = warn.end === undefined ? null : warn.end || null; result['type'] = warn.type === undefined ? -1 : warn.type; result['level'] = warn.level === undefined ? 0 : warn.level-1; result['areaID'] = warn.regionName === undefined ? '' : warn.regionName; result['altitudeStart'] = warn.altitudeStart === undefined ? 0 : warn.altitudeStart; result['altitudeEnd'] = warn.altitudeEnd === undefined ? 3000 : warn.altitudeEnd; result.messageHash = JSON.stringify(result).hashCode(); result['description'] = warn.description === undefined ? '' : warn.description; result['instruction'] = warn.instruction === undefined ? '' : warn.instruction; result['web'] = ''; result['webname'] = ''; result['picture'] = result.type === -1 ? '' : warningTypesString[DWD][result.type][1]; result['typename'] = result.type === -1 ? '' : warningTypesString[DWD][result.type][0]; } else if (mode === ZAMG) { if ( warn.properties === undefined || warn.properties.rawinfo.wlevel < minlevel ) {ticaLog(1, 'Übergebenene Warnung ZAMG verworfen, level niedriger als minlevel');return null;} result['type'] = warn.properties.warntypid === undefined ? -1 : warn.properties.warntypid; result['mode'] = ZAMG; result['description'] = !warn.properties.text ? '' : warn.properties.text + ' '; result['description'] += !warn.properties.auswirkungen ? '' : warn.properties.auswirkungen; result['meteo'] = !warn.properties.meteotext ? '' : warn.properties.meteotext; result['headline'] = result.type === -1 ? '' : 'Warnung vor ' + warningTypesString[ZAMG][result.type][0]; result['start'] = warn.properties.rawinfo.start === undefined ? null : warn.properties.rawinfo.start*1000 || null; result['end'] = warn.properties.rawinfo.end === undefined ? null : warn.properties.rawinfo.end*1000 || null; result['instruction'] = !warn.properties.empfehlungen ? '' : warn.properties.empfehlungen; result['level'] = warn.properties.rawinfo.wlevel === undefined ? 0 : warn.properties.rawinfo.wlevel + 1; result['areaID'] = warn.area === undefined ? '' : warn.area; result['html'] = {}; result['html']['web'] = ''; result['html']['instruction'] = result.instruction.replace(/\\n\*/g, '*').replace(/\*/g, '
*').replace(/\\n/g, '
'); result['html']['headline'] = result.headline.replace(/\\n\*/g, '*').replace(/\*/g, '
*').replace(/\\n/g, '
'); result['html']['description'] = result.description.replace(/\\n\*/g, '*').replace(/\*/g, '
*').replace(/\\n/g, '
'); result['altitudeStart'] = 0; result['altitudeEnd'] = 3000; result['web'] = ''; result['webname'] = ''; result['picture'] = result.type === -1 ? '' : warningTypesString[ZAMG][result.type][1]; result['urgency'] = 2; if (warningTypesString[ZAMG][result.type][0] == 'unbekannt') { ticaLog(0,'Bitte folgende Zeile im Forum posten. Danke', warn); ticaLog(0,'Unbekannter Typ: ' + result.type + ' Schlagzeile: ' + result.headline, warn); } result['typename'] = result.type === -1 ? '' : warningTypesString[result.mode][result.type][0]; } else if (mode === DWD2) { if ( warn.RESPONSETYPE != 'Prepare' || warn.STATUS == 'Test' || getCapLevel(warn.SEVERITY) < minlevel || (warn.ALTITUDE && warn.ALTITUDE * 0.3048 > maxhoehe) || (warn.CEILING && warn.CEILING * 0.3048 < minhoehe) ) { let why = warn.RESPONSETYPE != 'Prepare' ? 'Responsetype nicht Prepare - ':''; why = warn.STATUS == 'Test' ? 'Testwarnung - ':''; why += (warn.ALTITUDE && warn.ALTITUDE * 0.3048 > maxhoehe) ? 'Höhenlage der Warnung ist zu hoch - ':''; why += (getCapLevel(warn.SEVERITY) < minlevel) ? 'Level zu niedrig - ':''; why += (warn.CEILING && warn.CEILING * 0.3048 < minhoehe) ? 'Höhenlage der Warnung ist zu niedrig - ':''; ticaLog(2, why + 'Übergebenene Warnung UWZ verworfen'); return null; } result['mode'] = DWD; result['start'] = warn.ONSET === undefined ? null : getDateObject(warn.ONSET).getTime() || null; result['end'] = warn.EXPIRES === undefined ? null : getDateObject(warn.EXPIRES).getTime() || null; result['ec_ii_type'] = warn.EC_II === undefined ? -1 : Number(warn.EC_II); result['picture'] = ''; if (result.ec_ii_type != -1) { if (warningTypesString[DWD2][result.ec_ii_type] === undefined) { ticaLog(0,'Bitte das Json im Forum posten: EC: ' + warningTypesString[DWD2][result.ec_ii_type] ,'warn') ticaLog(0, warn, 'warn'); } else { result.type = warningTypesString[DWD2][String(result.ec_ii_type)]; result['picture'] = result.type === -1 ? '' : warningTypesString[DWD][result.type][1]; } } result['level'] = warn.SEVERITY === undefined ? 0 : getCapLevel(warn.SEVERITY); result['areaID'] = warn.AREADESC === undefined ? '' : warn.AREADESC; result['altitudeStart'] = warn.ALTITUDE === undefined ? 0 : warn.ALTITUDE * 0.3048; result['altitudeEnd'] = warn.CEILING === undefined ? 0 : warn.CEILING * 0.3048; result['web'] = ''; result['webname'] = ''; //result['picture'] = result.type === -1 ? '' : warningTypesString[DWD][result.type][1]; result.messageHash = JSON.stringify(result).hashCode(); result['typename'] = result.type === -1 ? '' : warningTypesString[result.mode][result.type][0]; result['description'] = warn.DESCRIPTION === undefined ? '' : warn.DESCRIPTION; result['headline'] = warn.HEADLINE === undefined ? '' : warn.HEADLINE; result['instruction'] = warn.INSTRUCTION === undefined ? '' : warn.INSTRUCTION; result['urgency'] = warn.URGENCY === undefined || warn.URGENCY == 'Immediate' ? 2 : 1; } else if (mode === UWZ) { if ( warn.payload === undefined || warn.payload.altMin > maxhoehe || (warn.payload.altMax && warn.payload.altMax < minhoehe) ) { let why = warn.payload === undefined ? 'Datensatz unvollständig - ':''; why += warn.payload.altMin > maxhoehe ? 'Höhenlage der Warnung ist zu hoch - ':''; why += (warn.payload.altMax && warn.payload.altMax < minhoehe) ? 'Höhenlage der Warnung ist zu niedrig - ':''; ticaLog(2,why + 'Übergebenene Warnung UWZ verworfen'); return null; } result['mode'] = UWZ; result['start'] = warn.dtgStart === undefined ? null : warn.dtgStart * 1000 || null; result['end'] = warn.dtgEnd === undefined ? null : warn.dtgEnd * 1000 || null; result['type'] = warn.type === undefined ? -1 : warn.type; result['level'] = warn.payload.levelName === undefined ? 0 : getUWZLevel(warn.payload.levelName); result['headline'] = warn.type === undefined ? '' : 'Warnung vor '+warningTypesString[UWZ][result.type][0]; result['areaID'] = warn.areaID === undefined ? '' : warn.areaID; result['web'] = ''; result.messageHash = JSON.stringify(result).hashCode(); result['description'] = warn.payload.translationsLongText.DE === undefined ? '' : warn.payload.translationsLongText.DE; result['instruction'] = warn.instruction === undefined ? '' : warn.instruction; result['webname'] = ''; result['picture'] = result.type === -1 ? '' : warningTypesString[UWZ][result.type][1]; result['typename'] = result.type === -1 ? '' : warningTypesString[result.mode][result.type][0]; result['urgency'] = 2; if ( result.level < minlevel ) {ticaLog(2, 'Level zu niedrig - Übergebenene Warnung UWZ verworfen');return null;} } else if (mode === NINA) { // level 2, 3, 4 let web=''; web = warn.web === undefined || !warn.web || !isValidUrl(warn.web)? '' : '
'+warn.web+'
'; result['mode'] = NINA; //result['identifier'] = warn.identifier === undefined ? '' : warn.identifier; //result['sender'] = warn.sender === undefined ? '' : warn.sender; result['web'] = warn.web === undefined || !warn.web || !isValidUrl(warn.web) ? '' : warn.web.replace(/(\.+\<\/a\>)/ig,''); result['webname'] = warn.web === undefined || !warn.web || !isValidUrl(warn.web) ? '' : warn.web.replace(/(\)|(\<\/a\>)/ig,''); result['description'] = warn.description === undefined ? '' : removeHtml(warn.description); result['instruction'] = warn.instruction === undefined ? '' : removeHtml(warn.instruction); result['headline'] = warn.headline === undefined ? '' : removeHtml(warn.headline); result['typename'] = warn.event === undefined ? '' : removeHtml(warn.event); result['type'] = result.typename.hashCode(); result['severity'] = warn.severity === undefined ? '' : warn.severity; //result['certainty'] = warn.certainty === undefined ? '' : warn.certainty; result['areaID'] = warn.area === undefined ? '' : getNinaArea(warn.area); result['level'] = warn.severity === undefined ? 0 : getCapLevel(warn.severity, result.typename); result.messageHash = JSON.stringify(result).hashCode(); result['start'] = warn.onset === undefined ? null : getDateObject(warn.onset).getTime() || null; result['end'] = warn.expires === undefined ? null : getDateObject(warn.expires).getTime() || null; //result['urgency'] = warn.urgency === undefined ? '' : warn.urgency; result['html'] = {}; result['html']['web'] = warn.web === undefined || !warn.web || !isValidUrl(warn.web) ? '' : warn.web; result['html']['instruction'] = warn.instruction === undefined ? '' : warn.instruction; result['html']['headline'] = warn.headline === undefined ? '' : warn.headline; result['html']['description'] = warn.description === undefined ? '' : warn.description; result['picture'] = ''; result['urgency'] = 2; if ( result.level < minlevel ) { ticaLog(2, 'Übergebenene Warnung NINA verworfen. Level' + result.level + ' kleiner als minlevel ' + minlevel);return null;} } result['color'] = getLevelColor(result.level, mode); result['id'] =''; result['pending'] = 0; result['hash'] = 0; result['repeatCounter'] = 0; result.ignored = false; ticaLog(4, '2. getDatabaseData(warn, mode) result: ' + JSON.stringify(result)); return result; function getNinaArea(value) { let result = 'für ihre Region' if (!value && !Array.isArray(value)) return result; // gibt nur 1 nix zum Suchen. if (value.length == 0) return 'für ' + value[0].areaDesc; let region = ''; let lvl = 5; let len = 1000; for (let a = 0; a < value.length; a++) { if (value[a].areaDesc !== undefined) { let area = value[a].areaDesc; if (area.includes(uGemeinde) && area.length - uGemeinde.length < len) { region = area; len = area.length - uGemeinde.length; lvl = 1; } else if (lvl > 2 && area.includes(uLandkreis)) { lvl = 2; region = area; } } if (value[a].geocode !== undefined) { let newval = value[a].geocode; for (let b = 0; b < newval.length; b++) { if (newval[b].valueName === undefined) continue; let area = newval[b].valueName; if (area.includes(uGemeinde) && area.length - uGemeinde.length < len) { region = area; len = area.length - uGemeinde.length; lvl = 1; } else if (lvl > 2 && area.includes(uLandkreis)) { lvl = 2; region = area; } } } } if (region) region = 'für ' + region; return region || result; } function getUWZLevel(warnName) { let result = -1; // -1 is an error! let alert = warnName.split("_"); let colors = { color: ["green", "darkgreen", "yellow", "orange", "red", "violet"], level: [0, 0, 1, 2, 3, 4] // um 1 level reduziert, sond nicht mit DWD vergleichbar nach Erfahrungen }; if (alert[0] == "notice") { result = 1; } else if (alert[1] == "forewarn") { result = 1; } else { result = colors.level[colors.color.indexOf(alert[2])]; } return result; } } // Gibt Farben für die level zurück function getLevelColor(level, typ) { let color = []; if (typ === undefined) typ = UWZ; switch (typ) { case NINA: case UWZ: case DWD: case DWD2: color = [ '#00ff00', // 0 - Grün '#00ff00', // 1 - Dunkelgrün '#fffc04', // 2 - Gelb Wetterwarnungen (Stufe 2) //vorher:#ffff00 '#ffb400', // 3 - Orange Warnungen vor markantem Wetter (Stufe 3) '#ff0000', // 4 - Rot Unwetterwarnungen (Stufe 4) // im grunde höchste Stufe in diesem Skript. '#ff00ff', // 5 - Violett Warnungen vor extremem Unwetter (nur DWD/ Weltuntergang nach aktueller Erfahrung) ]; if (level >= 0 && level <= 4) return color[level]; if (level > 4) return '#ff00ff' break; case ZAMG: color = [ '#00ff00', '#01DF3A', '#fffc04', '#ffc400', '#ff0404' ] if (level >= 0 && level <= 4) return color[level]; if (level > 4) return '#ff00ff' break; } return '#00ff00'; } // gibt Nina level zurück function getCapLevel(str, type) { let ninaLevel = [ 'Minor', 'Moderate', 'Severe', 'Extreme' ] let offset = 1; // Hochwassser ist immer Severe das ist im Vergleich denke ich zu hoch. //if (type == 'Hochwasserinformation') offset = 0; return ninaLevel.indexOf(str) + offset; } function removeHtml(a) { let b = a.replace(//ig, NEWLINE); return b.replace(/( |<([^>]+)>)/ig, ''); } // Überprüfe wegen Nina - Adapter häufig die DB ob obj.ids gelöscht wurden. // Dachte ich zuerst, die Server sind aber sehr unzuverlässig und Meldungen werden laufend nicht ausgeliefert. // Folglich werden Entwarnung raus geschickt. Jetzt warten wir 10 * 10 = 100 Minuten entwarnen erst dann. // Abgelaufene Meldungen werden aufgeräumt. function activateSchedule() { if (removeSchedule) clearSchedule(removeSchedule); removeSchedule = schedule('30 */10 * * * *', function() { if (onStopped) { if (removeSchedule) clearSchedule(removeSchedule); return; } let c = false; for (let a = 0; a < warnDatabase.new.length; a++) { let w = warnDatabase.new[a]; if (!extendedExists(w.id)) { if (warnDatabase.new[a].pending++ >= 10) { // 9 Durchläufe ticaLog(1, 'Remove old warning with id: ' + warnDatabase.new[a].id + ' and headline: ' + warnDatabase.new[a].headline); warnDatabase.new.splice(a--, 1); c = true; } } else { w.pending = 0; } if (w.end && new Date(w.end + intervalMinutes * 65000) < new Date()) { ticaLog(1, 'Remove expired warning with id: ' + warnDatabase.new[a].id + ', headline: ' + warnDatabase.new[a].headline + ' expire:' + new Date(w.end)); warnDatabase.new.splice(a--, 1); c = true; } } if (c && autoSendWarnings) { checkWarningsMain(false) } }); } // entferne Eintrag aus der Database function removeDatabaseDataID(id) { if (!id || (typeof id !== 'string')) return false; if (warnDatabase.new && warnDatabase.new.length > 0) { let i = warnDatabase.new.findIndex(function(j){return j.id == id}); if (i!=-1) { warnDatabase.new.splice(i, 1); return true; } } return false; } /* ************************************************************************* * Datenbank ENDE /* ************************************************************************* */ /* ************************************************************************* * Aufbereitung von Texten für die verschiedenen Pushmöglichkeiten /* ************************************************************************* */ function getArtikelMode(mode, speak = false) { let r = SPACE; if (mode & DWD) r += ((uLogLevel&4) ? 'des DWD('+scriptName+') ' : 'des DWD '); if (mode & ZAMG) r += ((uLogLevel&4) ? 'des ZAMG('+scriptName+') ' : 'des ZAMG '); if (mode & UWZ) { if (r.length > 1) r += 'und '; if (speak) r += ((uLogLevel&4) ? 'der Unwetterzentrale('+scriptName+') ' : 'der Unwetterzentrale '); else r += ((uLogLevel&4) ? 'der UWZ('+scriptName+') ' : 'der UWZ '); } if (mode & NINA) { if (r.length > 1) r += 'und '; r += ((uLogLevel&4) ? 'von Nina('+scriptName+') ' : 'von Nina '); } return r; } // Gibt einen fertigen Zähler string zurück. 1 / 3 wenn es Sinn macht und manuelle Auslösung function getStringWarnCount(i, c) { return SPACE + 'Insgesamt ' + ((i && onClickCheckRun && c > 1) ? (i.toString() + '/') : '') + ((c == 1) ? 'eine gültige Warnung.' : (c.toString() + ' gültige Warnungen.')); } // gibt einen fertigen String für ignorierte Warnungen zurück function getStringIgnoreCount(c) { if (c == 0) return ''; let r = SPACE; if (c == 1) r += 'Es wird eine Warnung ignoriert.'; else r += 'Es werden ' + c.toString() + ' Warnungen ignoriert.'; return r; } // ersetzt Placeholder function replacePlaceholder(str, insertText, insertText2) { let result = str; if (insertText2 !== undefined) result = result.replace(placeHolder+'1', insertText2) result = result.replace(placeHolder, insertText); return result; } // baut eine html table für Email function buildHtmlEmail(mailMsg, headline, msg, color, last = false) { if (!mailMsg) mailMsg = html_prefix; if (headline) { if (color) { mailMsg += html_headline_color.replace('###color###', color).replace('###headline###', headline); } else mailMsg += html_headline.replace('###headline###', headline); } if (msg) mailMsg += html_message.replace('###message###', msg); if (last) mailMsg += html_end; return mailMsg; } /* Entfernt "°C" und anders aus Sprachmeldung und ersetzt es durch "Grad" */ /* noch nicht für UWZ angepasst */ function replaceTokenForSpeak(beschreibung) { let rueckgabe = beschreibung; try { rueckgabe = rueckgabe.replace(/\°C/g, "Grad"); rueckgabe = rueckgabe.replace(/km\/h/g, "Kilometer pro Stunde"); rueckgabe = rueckgabe.replace(/l\/m\²/g, "Liter pro Quadratmeter"); rueckgabe = rueckgabe.replace(/\d{1,2}\.\d{1,2}\.\d{4}../gi, function(x) { return getFormatDateSpeak(x); }) rueckgabe = rueckgabe.replace(/\d{1,2}\.\d{1,2}\.../gi, function(x) { return getFormatDateSpeak(x); }) if (!windForceDetailsSpeak) { rueckgabe = rueckgabe.replace(/\([0-9]+.m\/s..[0-9]+kn..Bft.[0-9]+../g, ""); } else { rueckgabe = rueckgabe.replace(/kn/g, " Knoten"); rueckgabe = rueckgabe.replace(/Bft/g, " Windstärke"); rueckgabe = rueckgabe.replace(/m\/s/g, " Meter pro Sekunde"); } } catch (e) { ticaLog(0,'replaceTokenForSpeak' + e, 'warn'); } return rueckgabe; } // Formatiere Date zu string function getFormatDate(a) { if (!a || (!(typeof a === 'number')) && !(typeof a === 'object')) return ''; return formatDate(new Date(a).getTime(), formatierungString); } // hilffunktion für Zeitausgabe über Sprache // @PARAM Rückgabe von getFormatDate function getFormatDateSpeak(a) { if (!a || typeof a !== 'string') 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=''; } // if (Number(b[0]) < 10) b[0]=b[0].slice(1, 1); // Das geht echt einfacher *g* b[0] = Number(b[0]).toString(); b[1] = m; // setze Monatsname // entferne Jahr let c = b[2].split(SPACE); c[0] = ''; b[2] = c.join(SPACE); return b.join(SPACE); } /* ************************************************************************* * Aufbereitung von Texten für die verschiedenen Pushmöglichkeiten ENDE /* ************************************************************************* */ /* ************************************************************************* * Anfrage über Telegramm mit Ww? und WetterWarnungen? /* ************************************************************************* */ if ((uPushdienst & TELEGRAM) != 0) { on({ id: telegramInstanz + '.communicate.request', change: "any"}, function(obj) { let msg = obj.state.val; let user = msg.substring(1, msg.indexOf(']')); ticaLog(4, 'Telegramnachricht erhalten. Nutzer: ' + user + ' Nachricht: ' + msg); msg = msg.substring(msg.indexOf(']') + 1, msg.length); if ((uLogLevel&4) && msg.includes('Wwdmail')) { let olddebug = DEBUGSENDEMAIL; DEBUGSENDEMAIL = true; setState(mainStatePath + 'commands.' + konstanten[2].name, true, function() { setTimeout(function() { DEBUGSENDEMAIL = olddebug; }, 200); }); } else if (msg.includes('Wwdon') || msg == 'DWDUZWNINA#!§$debugan') { uLogLevel = switchFlags(uLogLevel, 4, true) ticaLog(0,'Debugmodus an'); } else if (msg.includes('Wwdoff') || msg == 'DWDUZWNINA#!§$debugaus') { uLogLevel = switchFlags(uLogLevel, 4, false) ticaLog(0,'Debugmodus aus'); } else if (msg.includes('#$WarnscriptLong%&') || msg.includes('#$WarnscriptShort%&')) { let long = !!(msg.includes('#$WarnscriptLong%&')) let token = long ? '#$WarnscriptLong%&' : '#$WarnscriptShort%&' msg = msg.substring(msg.indexOf(token)+ (token).length, msg.length); ticaLog(2, 'Telegramm-Detailanfrage erkannt, wird bearbeitet.') if ( !msg.isNaN && warnDatabase.new.findIndex((a) => a.hash == msg) != -1) { if ( uTelegramReplyMarkupInline ) { sendTo(telegramInstanz, { user: user, answerCallbackQuery: { text: "gefunden", showAlert: false } }); } warnDatabase.old = []; let oPd = uPushdienst; uPushdienst &= TELEGRAM; forceSpeak = forcedSpeak; onClickCheckRun = true; onClickCheckRunCmd = long ? 'Detailnachricht über Telegram' : 'Kurznachricht über Telegramm' let oldA = uTextMitAnweisungen, oldB = uTextMitBeschreibung, oldC = uTextHtmlMitOhneAlles; uTextMitAnweisungen = long; uTextMitBeschreibung = long; uTextHtmlMitOhneAlles = !long; checkWarningsMain(true, {hash:msg, isAnswer:true}); uTextMitAnweisungen = oldA; uTextMitBeschreibung = oldB; uTextHtmlMitOhneAlles = oldC; onClickCheckRun = false; onClickCheckRunCmd = ''; forceSpeak = false; uPushdienst = oPd; } else { if ( uTelegramReplyMarkupInline ) { sendTo(telegramInstanz, { user: user, answerCallbackQuery: { text: "Warnung wurde aufgehoben", showAlert: true } }); } } } else if (msg === uTelegramMessageLong || msg === 'DWDUZWNINA#!§$LONG' || msg === uTelegramMessageShort || msg.includes('Wetterwarnungen?') || msg == 'DWDUZWNINA#!§$TT') { warnDatabase.old = []; let oPd = uPushdienst; uPushdienst &= TELEGRAM; forceSpeak = forcedSpeak; onClickCheckRun = true; onClickCheckRunCmd = 'Textnachricht über Telegram' let oldA = uTextMitAnweisungen, oldB = uTextMitBeschreibung; let long = true; if ( msg === uTelegramMessageShort || msg.includes('Wetterwarnungen?') || msg == 'DWDUZWNINA#!§$TT') long = false; uTextMitAnweisungen = long; uTextMitBeschreibung = long; checkWarningsMain(true); uTextMitAnweisungen = oldA; uTextMitBeschreibung = oldB; onClickCheckRun = false; onClickCheckRunCmd = ''; forceSpeak = false; uPushdienst = oPd; } }); } /* ************************************************************************* * Anfrage über Telegramm mit Ww? und WetterWarnungen? * ENDE /* ************************************************************************* */ /* ************************************************************************* * Restartfunktion /* ************************************************************************* */ onStop(function (callback) { onStopped = true; ticaLog(1, 'Skripts gestoppt: ID:' + randomID); if (standaloneInterval) clearInterval(standaloneInterval); if (removeSchedule) clearSchedule(removeSchedule); setTimeout(callback, 2000); }) /* ************************************************************************* * Restartfunktion * ENDE /* ************************************************************************* */ /* ************************************************************************* * Erstellung von States incl. 0_userdata & Zugehöriges /* ************************************************************************* */ // gibt die ersten beiden Teile von ID zurück // erweiterte existsState() funktion function extendedExists(id) { return (id) && ($(id).length > 0) && (existsState(id)); } async function extendedExistsAsync(id) { return (id) && ($(id).length > 0) && (existsStateAsync(id)); } /* ************************************************************************* * Erstellung von States incl. 0_userdata & Zugehöriges * ENDE /* ************************************************************************* */ /* ************************************************************************* * Hilffunktion sonstiges /* ************************************************************************* */ // Klone das Objekt function cloneObj(j) { if (Array.isArray(j)) { let arr = [j.length]; for (let a=0;a.+\<\/a\>)/ig,'')); } async function createStateCustomAsync(id, def, options) { if (options === undefined ) { if (typeof(def) === 'object') { options = def; def = undefined; } } switch (options.type) { case 'number': options.def = def === undefined || typeof def !== 'number' ? 0 : def; break; case 'string': options.def = def === undefined || typeof def !== 'string' ? '' : def; break; case 'boolean': options.def = def === undefined || typeof def !== 'boolean' ? false : !!(def); break; default: def = def === undefined ? null : def; break; } if (options.def !== undefined) def = undefined if (!await existsStateAsync(id)) { await createStateAsync(id, options); if (def !== undefined) await setStateAsync(id, def, true); } } /* ************************************************************************* * Hilffunktion sonstiges * ENDE /* ************************************************************************* */ setTimeout(init, 15000); ticaLog(0,'Warte 15 Sekunden das bei einem eventuellen Restart alles beendet wurde!')