Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Skript AlleStörungen

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    Skript AlleStörungen

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

      Hallo. Heute stelle ich euch einmal mein Skript "Alle Störungen" vor. Dieses Skript liest Daten einer Website (in diesem Falle allestörungen.de [at] [ch]) aus. Es ermittelt wie auch andere Skripts (z.B. Wetter, Luftdaten, Pollen, Biowetter, usw.) Daten und schreibt diese zur Weiterverarbeitung in einzelne Datenpunkte.

      Habe zwar nicht daran gedacht gleich ein Skript zu erstellen, aber man hatte bei Problemen doch dann schon mal auf der genannten Seite nachgesehen.

      Da wir ja viele Daten sammeln, speichern und visualisieren - ist dies vielleicht ein weiteres Skript für Nutzer vom ioBroker.

      //Version 1.0.1 - 20.09.2024
      //Ersteller Ro75.
      
      //Voraussetzungen (Version 1.0.0 getestet mit)
      //NodeJS: 20.x
      //Javascript-Adapter: 8.7.6
      //Admin-Adapter: 7.0.23
      //JS-Controller: 6.0.11
      
      
      
      const sMainPath = '0_userdata.0.allestoerungen.'; //Zentraler Datenpunkt zur Datenablage
      const sMainURL  = 'https://xn--allestrungen-9ib.de/stoerung/'; //Website die ausgelesen wird
      
      //Konfiguration der auszulesenden Dienste - kann frei zusammengestellt werden (Suche auf https://xn--allestrungen-9ib.de/ verwenden)
      //Dienste werden durch ein "," (KOMMA) getrennt
      //Innterhalb eines Dienstes gibt es zwie Werte, gertrennt durch ":" (Doppelpunkt)
      //Die linke Seite repräsentiert die Bezeichnung, die rechte Seite den Unterpfad in der Website
      const aDienste  = 'Amazon Alexa:amazon-alexa,Amazon:amazon,Amazon Music:amazon-music,Amazon Prime Video:amazon-prime-instant-video,Amazon Web Services:aws-amazon-web-services,Blau:blau-de,Cloudflare:cloudflare,DHL:dhl,Disney+:disney-plus,EA:ea,Facebook:facebook,Facebook Messenger:facebook-messenger,Gmail:gmail,GMX:gmx,Google:google,Google Calendar:google-calendar,Hue:hue,Instagram:instagram,Microsoft 365:microsoft-365,Netatmo:netatmo,Netflix:netflix,Paramount+:paramountplus,Paypal:paypal,Playstation Network:playstation-network,Snapchat:snapchat,SKY:sky,Telekom:deutsche-telekom,TikTok:tiktok,TuneIn:tunein,Visa:visa,Volksbanken Raiffeisenbanken:volksbanken-und-raiffeisenbanken,Whatsapp:whatsapp,X (Twitter):Twitter,Xbox Live:xbox-live,YouTube:youtube';
      
      //Anlage der Datenpunkte, basierend auf const aDienste
      function Initalisierung(){
          let dienste = aDienste.split(',');
          for (let i = 0; i <= dienste.length-1; i++) {
              let dienste_data = dienste[i].split(':');
              //Hauptordner
              createState(sMainPath+dienste_data[0], '', {name: dienste_data[0],type: 'string', read: true, write: true});
              //Name vom Dienst
              createState(sMainPath+dienste_data[0]+'.name', dienste_data[0], {name: 'Dienst', type: 'string', read: true, write: true, desc: 'Dienst'});
              //Logo vom Dienst
              createState(sMainPath+dienste_data[0]+'.image_url', '', {name: 'Logo',type: 'string', read: true, write: true, desc: 'Logo'});
              //Störung laut Website (Datum + Uhrzeit)
              createState(sMainPath+dienste_data[0]+'.disruption', '', {name: 'Störung',type: 'string', read: true, write: true, desc: 'Störung'});
              // Störung % Satz 1
              createState(sMainPath+dienste_data[0]+'.disruption_1', 0, {name: 'Störung 1',type: 'number', read: true, write: true, desc: 'Störung Satz 1', unit: '%'});
              createState(sMainPath+dienste_data[0]+'.disruption_desc_1', '', {name: 'Beschreibung Störung 1',type: 'string', read: true, write: true, desc: 'Beschreibung Störung Satz 1'});
              // Störung % Satz 2
              createState(sMainPath+dienste_data[0]+'.disruption_2', 0, {name: 'Störung 2',type: 'number', read: true, write: true, desc: 'Störung Satz 2', unit: '%'});
              createState(sMainPath+dienste_data[0]+'.disruption_desc_2', '', {name: 'Beschreibung Störung 2',type: 'string', read: true, write: true, desc: 'Beschreibung Störung Satz 1'});
              // Störung % Satz 3
              createState(sMainPath+dienste_data[0]+'.disruption_3', 0, {name: 'Störung 3',type: 'number', read: true, write: true, desc: 'Störung Satz 3', unit: '%'});
              createState(sMainPath+dienste_data[0]+'.disruption_desc_3', '', {name: 'Beschreibung Störung 3',type: 'string', read: true, write: true, desc: 'Beschreibung Störung Satz 1'});
              // Daten-Array der letztes 24 Stunden bezogen auf Werte
              createState(sMainPath+dienste_data[0]+'.data_plain', '', {name: 'Werte',type: 'string', read: true, write: true, desc: 'Werte'});
              // Daten-Array der letztes 24 Stunden bezogen auf Zeit
              createState(sMainPath+dienste_data[0]+'.data_time_plain', '', {name: 'Zeit',type: 'string', read: true, write: true, desc: 'Zeit'});
              // Daten-Array der letztes 24 Stunden als JSON - kann direkt weiter verarbeitet werden (auch Grafana)
              createState(sMainPath+dienste_data[0]+'.data_json', '', {name: 'JSON',type: 'string', def: '[]', read: true, write: true, desc: 'JSON Widget/Simple-API/Grafana'});
              // Min Meldungen der letzten 24 Stunden
              createState(sMainPath+dienste_data[0]+'.min', 0, {name: 'Min',type: 'number', read: true, write: true, desc: 'kleinster Wert'});
              // Max Meldungen der letzten 24 Stunden
              createState(sMainPath+dienste_data[0]+'.max', 0, {name: 'Max',type: 'number', read: true, write: true, desc: 'größter Wert'});
              // Meldungen letzter Stand
              createState(sMainPath+dienste_data[0]+'.last', 0, {name: 'Last',type: 'number', read: true, write: true, desc: 'letzter Wert'});
              // Schwellenpunkt für eigenen Alarm - standardmäßig sind je Dienst 300 eingetragen, kann individuell im DP angepasst werden
              createState(sMainPath+dienste_data[0]+'.alarm_threshold', 300, {name: 'Threshold',type: 'number', read: true, write: true, desc: 'Schwelle Alarm'});
              // Alarm, resultierend aus 'alarm_threshold' und 'last'
              createState(sMainPath+dienste_data[0]+'.alarm', false, {name: 'Alarm',type: 'boolean', read: true, write: true, desc: 'Alarm'});
              // stand der Daten
              createState(sMainPath+dienste_data[0]+'.lasttimestand', '', {name: 'letzter Stand',type: 'string', read: true, write: true, desc: 'letzter Stand'});
      
              //Hinweis: mit den Werten 'data_*', min, max, last, alarm ist eine umfangreiche Visualisierung möglich
          }
          //JSON
          createState(sMainPath+'data_json', '', {name: 'JSON',type: 'string', def: '[]', read: true, write: true, desc: 'JSON Widget'});
      
          //erster Datenabruf
          Dienste_Main();
      }
      //START
      Initalisierung();
      
      //automatisierte Datenabfrage: standard sind 30 Minuten - kann geändert werden (aber nicht zu oft - keine Erfahrung mit blocken)
      schedule('*/30 * * * *', Dienste_Main);
      
      //Hauptfunktion
      async function Dienste_Main(){
          let dienste = aDienste.split(',');
          for (let i = 0; i <= dienste.length-1; i++) {
              let dienste_data = dienste[i].split(':');
              let dienst_url = dienste_data[1];
      
              try {
                  let response = await httpGetAsync(sMainURL+dienst_url+'/', {timeout: 10000});
                  if (response.statusCode == 200) {
                      //Logo vom Dienst
                      await Dienst_Image(response.data,sMainPath+dienste_data[0]);
                      //Wann war letzte Störung, laut Website
                      await Dienst_letzte_stoerung(response.data,sMainPath+dienste_data[0]);
                      //Abruf der Hauptdaten ()
                      await Dienst_Data(response.data,sMainPath+dienste_data[0]);
                      //Indikator in % für Probleme mit Festnetz Internet
                      await IndicatorChart(1,response.data,sMainPath+dienste_data[0]);
                      //Indikator in % für Probleme mit Mobiles Internet
                      await IndicatorChart(2,response.data,sMainPath+dienste_data[0]);
                      //Indikator in % für Probleme mit Total Blackout
                      await IndicatorChart(3,response.data,sMainPath+dienste_data[0]);
                      setState(sMainPath+dienste_data[0]+'.lasttimestand',new Date().toDateString() + ' '+ new Date().toTimeString(),true);
                  }
                  response = null;
              } catch (error) {
                  console.error('AlleStörungen:', error);
              }
          }
          setTimeout(function(){
              CreateJSON();
          },1000);
      }
      
      async function Dienst_Data(sData,sMainDP){
          let Position = sData.indexOf("data: [");
          if (Position > 0) {
              var info = sData.substr(Position+7, 10000);
              var pos = info.indexOf("],");
              var str = info.substr(0, pos).trim();
              var daten = await Dienst_Data_Details(str);
              var Splitdaten = daten.split('||');
              setState(sMainDP+'.data_json',Splitdaten[0],true);
              setState(sMainDP+'.data_plain',Splitdaten[1],true);
              setState(sMainDP+'.data_time_plain',Splitdaten[2],true);
              setState(sMainDP+'.min',parseInt(Splitdaten[3]),true);
              setState(sMainDP+'.max',parseInt(Splitdaten[4]),true);
              setState(sMainDP+'.last',parseInt(Splitdaten[5]),true);
      
              var bAlert = false;
              if (parseInt(Splitdaten[5]) >= getState(sMainDP+'.alarm_threshold').val) {
                  bAlert = true;
              }
              setState(sMainDP+'.alarm',bAlert,true);
      
              info = null;
          } 
      }
      async function Dienst_Data_Details(sData){
          let JSON_List   = [];
          var Plain_List  = '';
          var Time_List   = '';
          var lMin        = 100000000;
          var lMax        = 0;
          var lLast       = 0;
      
          let sDataDetail = sData.split('},');
          for (let i = 0; i <= sDataDetail.length-2; i++) {
              let dData = sDataDetail[i].replace('{ x: ','').replace(' y: ','').replace('+00:00','.000Z').replace(/[&\/\\'"*?<>{}]/g,'').replace('\n','').trim();
              dData = dData.split(',');
      
              JSON_List.push({"time": dData[0], "value": dData[1]});
      
              if (Plain_List == '') {
                  Plain_List = dData[1];
              } else {
                  Plain_List = Plain_List+','+dData[1];
              }
              if (lMax < parseFloat(dData[1])) {
                  lMax = parseFloat(dData[1]);
              }
              if (lMin > parseFloat(dData[1])) {
                  lMin = parseFloat(dData[1]);
              }
      
              if (Time_List == '') {
                  Time_List = dData[0];
              } else {
                  Time_List = Time_List+','+dData[0];
              }
      
              lLast = dData[1];
          }
          return JSON.stringify(JSON_List)+'||'+Plain_List+'||'+Time_List+'||'+lMin+'||'+lMax+'||'+lLast;
      }
      
      async function Dienst_Image(sData,sMainDP){
          let Position = sData.indexOf("'og:image' content='");
          if (Position > 0) {
              var info = sData.substr(Position+20, 200);
              var pos = info.indexOf("'>");
              var str = info.substr(0, pos);
              setState(sMainDP+'.image_url',str,true);
              info = null;
          } 
      }
      
      async function Dienst_letzte_stoerung(sData,sMainDP){
          let Position = sData.indexOf("<p class='text-danger'>");
          if (Position > 0) {
              var info = sData.substr(Position+23, 200);
              var pos=info.indexOf("</p>");
              var str = info.substr(0, pos).replace('Letzte Störung: ','');
              setState(sMainDP+'.disruption',str.trim(),true);
              info = null;
          } else {
              setState(sMainDP+'.disruption','',true);
          } 
      }
      
      async function IndicatorChart(lItem,sData,sMainDP){
          var lValue = 0;
          var Position = sData.indexOf("<div class='col-4'>");
          var info = sData.substr(Position+19, 30000);
          var Position2 = info.indexOf("indicator_"+lItem);
          if (Position2 > 0) {
              var info2 = info.substr(Position2+11, 5000);
              var Position3 = info2.indexOf("tage'>");
              if (Position3 > 0) {
                  var info3 = info2.substr(Position3+6, 50);
                  var pos=info3.indexOf("</div>");
                  var str = info3.substr(0, pos);
                  lValue = parseInt(str);
              }
          }
          setState(sMainDP+'.disruption_'+lItem,lValue,true);
      
          //Beschreibung
          var sInfo = '';
          if (Position2 > 0) {
              var info2 = info.substr(Position2+11, 5000);
              var Position3 = info2.indexOf("_name'>");
              if (Position3 > 0) {
                  var info3 = info2.substr(Position3+7, 200);
                  var pos=info3.indexOf("</div>");
                  var str = info3.substr(0, pos);
                  sInfo = str.trim();
              }
          }
          setState(sMainDP+'.disruption_desc_'+lItem,sInfo,true);
      }
      
      function CreateJSON() {
          let JSON_List   = [];
          let dienste = aDienste.split(',');
          for (let i = 0; i <= dienste.length-1; i++) {
              var rDienst = sMainPath+dienste[i].split(':')[0];
              var dis1 = getState(rDienst+'.disruption_desc_1').val;
              if (dis1 != '') {
                  dis1 = dis1 + ': '+getState(rDienst+'.disruption_1').val+'%';
              }
              var dis2 = getState(rDienst+'.disruption_desc_2').val;
              if (dis2 != '') {
                  dis2 = dis2 + ': '+getState(rDienst+'.disruption_2').val+'%';
              }
              var dis3 = getState(rDienst+'.disruption_desc_3').val;
              if (dis3 != '') {
                  dis3 = dis3 + ': '+getState(rDienst+'.disruption_3').val+'%';
              }
              var alarm = '';
              if (getState(rDienst+'.alarm').val == false) {
                  alarm = 'nein';
              } else {
                  alarm = 'ja';
              }
              JSON_List.push({"dienst": dienste[i].split(':')[0], "logo": getState(rDienst+'.image_url').val, "min": getState(rDienst+'.min').val, "max": getState(rDienst+'.max').val, "last": getState(rDienst+'.last').val, "stoerung1": dis1, "stoerung2": dis2, "stoerung3": dis3, "alarm": alarm});
          }
          setState(sMainPath+'data_json', JSON.stringify(JSON_List), true);
          JSON_List = [];
      }
      

      Im Grunde sollte alles selbsterklärend sein. Die hinzugefügten Kommentare geben Info und Einstellmöglichkeiten. Für Anregungen bin ich offen, auch wenn es ggfs. nicht gleich umgesetzt werden kann (die gute Zeit).

      5ce0143a-0086-42bc-a8d5-1ef9618cb8b6-image.png Visualisierung als Liste

      b7dba355-071c-46b7-8d67-ef95ab55ca1c-image.png Visualisierung mit Grafana (via Simple-API)

      Ich wünsche euch viel Spaß.

      Ro75.

      NACHTRAG 20.09.2024:

      Das Skript kann auch für Österreich und Schweiz Anwendung finden. Dazu muss die Konstante "sMainURL" angepasst werden.

      Österreich: const sMainURL  = 'https://xn--allestrungen-9ib.at/stoerung/';
      Schweiz: const sMainURL  = 'https://xn--allestrungen-9ib.ch/stoerung/';
      

      ACHTUNG:
      Die Auflistung der Dienste in der Konstante "aDienste" muss aber für das jeweilige Land individuell angepasst werden, da es in jedem Land spezifische Dienste gibt, die in anderen Ländern nicht bekannt sind. Wird also ein Dienst in Österreich verwendet, welcher nur in Deutschland verfügbar ist (z.B. All-Inkl), wird es zu Fehlermeldungen bei der Auswerung kommen.

      Version 1.01 - 20.09.2024

      1. Zentrale JSON hinzugefügt
      2. Fehlerbehandlung
      sigi234 K D4vE 3 Replies Last reply Reply Quote 2
      • sigi234
        sigi234 Forum Testing Most Active @Ro75 last edited by sigi234

        @ro75 sagte in Skript AlleStörungen:

        const sMainURL = 'https://allestörungen.de/stoerung/'; //Website die ausgelesen wird

        allestrungen

        Stimmt die Url?

        Geht das auch für Österreich?

        Ro75 1 Reply Last reply Reply Quote 0
        • Ro75
          Ro75 @sigi234 last edited by Ro75

          @sigi234 die von mir angegebene URL ist korrekt, wegen dem Umlaut. Sollte aber auch allestoerungen.de gehen.

          Gibt es für Österreich eine separate Adresse? Hab ich jetzt noch nicht geschaut. Aber ändere es mal statt .de in .at ab

          Edit: eventuell musst du aber die Liste der Dienste anpassen, da es einige in Österreich nicht gibt.

          Ro75

          sigi234 1 Reply Last reply Reply Quote 0
          • K
            Kuddel @Ro75 last edited by

            @ro75 die Idee selber finde ich spannend.

            Ohne das Skript jetzt am PC angeschaut zu haben (etwas nervig auf dem Handy), würde ich es gut finden, wenn man seine PLZ sowie die genutzten Dienste angeben könnte.

            Vllt. findet sich ja jemand, der das Skript später zu einem Adapter macht

            Ro75 1 Reply Last reply Reply Quote 0
            • sigi234
              sigi234 Forum Testing Most Active @Ro75 last edited by

              @ro75 sagte in Skript AlleStörungen:

              @sigi234 die von mir angegebene URL ist korrekt, wegen dem Umlaut. Sollte aber auch allestoerungen.de gehen.

              Gibt es für Österreich eine separate Adresse? Hab ich jetzt noch nicht geschaut. Aber ändere es mal statt .de in .at ab

              Edit: eventuell musst du aber die Liste der Dienste anpassen, da es einige in Österreich nicht gibt.

              Ro75

              Funktioniert mit at wunderbar, Danke 👍

              1 Reply Last reply Reply Quote 1
              • Ro75
                Ro75 @Kuddel last edited by

                @kuddel schaue es dir an. Die Dienste kannst du selbst bestimmen.

                Ro75

                sigi234 1 Reply Last reply Reply Quote 0
                • D4vE
                  D4vE @Ro75 last edited by D4vE

                  @ro75 sehr starke Arbeit!

                  könnte man da noch Telegram mit rein hauen? das bei einer neuen Störung eine Nachricht bekommt? wer Hammer!

                  Danke für deine Arbeit!

                  1 Reply Last reply Reply Quote 0
                  • sigi234
                    sigi234 Forum Testing Most Active @Ro75 last edited by

                    @ro75

                    Zu Vis2 muss ich mir noch so meine Gedanken machen, aber es wird

                    Screenshot (965).png

                    1 Reply Last reply Reply Quote 3
                    • Ro75
                      Ro75 last edited by

                      Einganspost um den NACHTRAG 20.09.2024: erweitert.

                      Ro75.

                      1 Reply Last reply Reply Quote 2
                      • Ro75
                        Ro75 last edited by

                        Eingangspost um Visualisierungsbeispiele erweitert.

                        Ro75.

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post

                        Support us

                        ioBroker
                        Community Adapters
                        Donate

                        843
                        Online

                        31.7k
                        Users

                        79.9k
                        Topics

                        1.3m
                        Posts

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