Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Müllkalender

    NEWS

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Müllkalender

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

      @rasiegfr:

      hi adnim,

      werde mich damit mal am wochenede befassen. da brauche ich ruhe und zeit. das meine jetzige lösung eine "krücke" und mich nicht zufrieden stellt habe ich ja geschrieben.

      mich ärgert nur (und das ist nur mein problem) dass ich dein skript nicht verstehe. ich werde mich da mal ranwagen, weil ich möchte eigentlich nicht mit meiner lösung leben, wie du schon geschrieben hast mit der automatisierung ….

      ich danke euch allen für die zeit die ihr euch nehmt !

      lg

      ralph `

      Hallo Ralph,

      schau mal, in diesem Posting habe ich das von adnim gepostet Skript damals erstmalig für den User noxx erstellt:

      viewtopic.php?f=21&t=3351&hilit=guten+m … 120#p79458

      Hier:

      viewtopic.php?f=21&t=3351&p=86026&hilit ... dra#p86026

      da habe ich einem anderen User das Skript erklärt und Schritt für Schritt durchgeführt.

      und zu guter letzt hier:

      viewtopic.php?f=21&t=3351&p=86026&hilit ... dra#p91698

      hat dann user PicNic mein Skript genommen und so erweitert, dass man gleich alle Müllarten auf einmal suchen kann. Das wäre aus meinem ersten Posting oben dann das Beispiel 1.

      Wenn du dir das durchliest, wirst du lesen, was das Skript tut und welche Probleme es geben kann. Es ist inhaltlich nicht schwer zu verstehen. Wenn Fragen sind, können wir die gerne hier klären.

      viel Erfolg

      1 Reply Last reply Reply Quote 0
      • T
        tempestas last edited by

        Hallo Ralph,

        ich habe nochmal in meiner Ablage geschaut und dieses Skript gefunden ,dass ich mal geschrieben hatte. Es ist durchgehend kommentiert, vllt. hilft es dir. Das Skript sucht einfach nach "Morgen" und gibt dann alles aus, was morgen ansteht. D.h. du brauchst keinen Suchbegriff festlegen, im Gegenzug würde aber, wenn du einen gemischten Kalender hast (z.B. auch Geburtstage enthalten) alles was morgen ansteht mitgeteilt.

        ! ````
        ! // Skript schaut täglich um 18h, ob im Müllkalender das Wort "Morgen" vorkommt. Wenn ja, wird ein Telegram geschickt mit der betreffenden Müllsorte
        // muss "ersetze Datum mit Worten" aktiviert haben
        //v1.0 tempestas
        ! // Skripteinstellungen
        ! var debug = false;
        ! // Suchfunktion für Termin-Cutoff

        function nthIndex(str, pat, n){
        var L= str.length, i= -1;
        while(n-- && i++ <l){ i="str.indexOf(pat," i);/if/(i/</0)/break;/}/i_search="i;" müll-funktion/function/muellwarnung()/{/var/inhalt="getState("ical.0.data.html").val.toString();" hier/deine/müll-kalender/instanz/eingeben/if(debug)/log(inhalt);/count="inhalt.split("Morgen").length" -1;/wie/häufig/wird/"morgen"/gefunden?/log("count/ist/"+count);/posstart="inhalt.indexOf(" 'morgen',/0);/sucht/das/erste/mal/log("posstart/"+posstart);/if(posstart/!="-1){" falls/gefunden/wurde/gehts/weiter/stringshort="inhalt.substring(posStart," inhalt.length);/abschneiden/von/allem,/was/links/vom/ersten/treffer/steht/log("gekürzt/:"/+stringshort);/nthindex(stringshort,/'</span="">', count); // hier wird nun geschaut, wo es rechts abgeschnitten werden muss
        log('i_search ist '+i_search );
        stringCut = stringShort.slice(0,i_search); // hier wird alles rechts abgeschnitten und so der finale String extrahiert

        if(debug) log("Fast Final: "+stringCut);
        

        ! // aufbereiten für telegram, entfernen von HTML Tags
        ! stringCut = stringCut.replace('
        ',"\n"); // Zeilenumbruch html durch telegram umbruch ersetzen
        ! // remove all inside SCRIPT and STYLE tags
        stringCut=stringCut.replace(/<script.>[\w\W]{1,}(.?)[\w\W]{1,}</script>/gi, "");
        stringCut=stringCut.replace(/<style.>[\w\W]{1,}(.?)[\w\W]{1,}</style>/gi, "");

            // remove BR tags. Werden durch sinnlose Zeichenkette ersetzt, nach der später gesucht wird
            stringCut=stringCut.replace(/
        

        /gi, "");
        stringCut=stringCut.replace(/<br\s>/gi, "");
        stringCut=stringCut.replace(/<br>/gi, "");

            // remove all else
            stringCut=stringCut.replace(/<(?:.|\s)*?>/g, "");
        
            // get rid of html-encoded characters:
            stringCut=stringCut.replace(/ /gi," ");
            stringCut=stringCut.replace(/&/gi,"&");
            stringCut=stringCut.replace(/"/gi,'"');
            stringCut=stringCut.replace(/</gi,'<');
            stringCut=stringCut.replace(/>/gi,'>');
        

        !
        sendTo('telegram', stringCut);

        }
        }

        ! // Trigger Schedule
        ! schedule('0 18 * * ', function(){ // Täglich um 18h
        ! muellWarnung();
        });
        ! // Bei Start
        ! muellWarnung();</br></br\s></style.
        ></script.*></l){>

        1 Reply Last reply Reply Quote 0
        • rasiegfr
          rasiegfr last edited by

          hallo zusammen,

          ihr seit echt göttlich dass ihr mir helfen wollt. ich werde mich am wochenende wie gesagt mal ransetzen, das geht für mich nicht so zwischendurch. möchte es ja halbwegs verstehen was ich da tue.

          @ tempestas: deinen letztes skript wird für mich nicht in frage kommen. ich habe zwar einen extra kalender dafür, möchte aber unterscheiden können. da ich das ganze im wohnzimmer grafisch darstelle in vis bringt mich dann eine textausgabe leider nicht weiter.

          ich danke euch allen für eure hilfe und melde mich montag wie es ausgegangen ist 🙂

          lg

          ralph
          9191_vis_2018.jpg

          1 Reply Last reply Reply Quote 0
          • haselchen
            haselchen Most Active last edited by

            Wenn ihr euren Kalender auf dem Google Home ansagen lasst, welche Stimme nehmt ihr?

            Die ganzen sayit Stimmen sind so blechern und hören sich derbe nach Computer an.

            Gibt es ne Möglichkeit wie bei Alexa die Original Google Stimme sprechen zu lassen?

            Die Google Home Stimme aus dem sayit Adapter klingt bei weitem nicht wie das Original.

            1 Reply Last reply Reply Quote 0
            • haselchen
              haselchen Most Active last edited by

              Hab es anders gelöst. Mit Blockly und der Hilfe von der soundoftext.com Seite.

              Unter Soundoftext.com kann man beliebige Wörter, Sätze eingeben und in Deutsch ausgeben lassen.

              Das File kann man sofort als mp3 speichern.

              Die Stimme ist jetzt nicht mega menschlich, aber irgendwie klarer und deutlicher als die im Adapter gespeicherten.

              Das mp3 File dann in den sayit.0 Adapter und dann kann man es im Blockly zu allem verwenden.

              1 Reply Last reply Reply Quote 0
              • rasiegfr
                rasiegfr last edited by

                hallo zusammen,

                bin leider am wochenende nicht dazu gekommen eure vorschläge zu testen. der grund: hier läuft gar nichts mehr. habe den java adapter auf 4.x upgedate und seither geht leider nix mehr.

                wollte nur kurz eine info geben damit ihr euch nicht verarscht vorkommt ….

                lg

                ralph

                viewtopic.php?p=199401#p199401

                1 Reply Last reply Reply Quote 0
                • rasiegfr
                  rasiegfr last edited by

                  hi zusammen,

                  mein iobroker läuft wieder 🙂 . gestern gab es ein update für den icalender adapter welches glaube ich für viele eine problemlösung sein wird. wenn ich das richtig verstanden habe werden jetzt die kalender ereignisse nach 0,1,2,3,4 und 5 tagen unterteilt.

                  bin gerade noch am testen aber der gewünschte "müllkalender" dürfte dann so kein problem mehr sein (war es ja sowieso nicht für euch, die sich mit java auskennen).

                  lg

                  ralph

                  NACHTRAG: unter objekte hat man jetzt die anzahl datenpunkte je nach dem wie viele tage der kalender abgeholt wird.
                  9191_kalender_neu.jpg

                  1 Reply Last reply Reply Quote 0
                  • E
                    Elektroman last edited by

                    Hi,

                    für mich war das jetzt der Durchbruch [emoji4]

                    Sofort erst mal Alexa beigebracht mich bei der Heimkehr daran zu erinnern [emoji23]

                    1 Reply Last reply Reply Quote 0
                    • T
                      TonyDom last edited by

                      Welche Version ist das Update? Ich bekam nichts!

                      1 Reply Last reply Reply Quote 0
                      • E
                        Elektroman last edited by

                        1.7

                        1 Reply Last reply Reply Quote 0
                        • T
                          TonyDom last edited by

                          habe eben die 1.7 installiert.

                          Genial, einfach nur genial!

                          1 Reply Last reply Reply Quote 0
                          • Negalein
                            Negalein Global Moderator last edited by

                            @Adnim:

                            habe die felder nochmal rausgesucht und im script extra kommentiert…

                            createState('javascript.0.muell.altpapier', 0); //hier das objekt zum speichern analog dem suchwort eintragen,das gleiche wie beim letzten Eintrag

                            var such1= "altpapier"; // HIER DAS SUCHWORT VERGEBEN, Case Sensitiv

                            setState('javascript.0.muell.altpapier', diff); //Schreibe Ergebnis in am anfang erstelles Objekt

                            var inhalt = getState("ical.0.data.html"/HTML iCal table/); //hier deinen Kalender eintragen `

                            Hallo Adnim!

                            Danke für dein/euer Script.

                            Hab es sofort an mich angepasst, bekomme es leider nicht zum laufen.

                            // TESTSKRIPT FÜR NOXX
                            
                            // Annahme ist, dass jede Müllart mindestens einmal im Monat abgeholt wird. Nicht getestet und eventuell problematisch ist es, wenn Müll seltener abgeholt wird.
                            
                            debug = true;
                            
                            // Anlegen JS State für VIS 
                            
                            createState('javascript.0.muell.papier', 0);   //hier das objekt zum speichern analog dem suchwort eintragen
                            
                            // Suchvariablen
                            
                            var such1= "Papier";   // HIER DAS SUCHWORT VERGEBEN
                            
                            // Kalender auslesen (HTML Format)
                            
                                // **************************************************************************************            
                                // Termine auswerten aus html. Bereinigung der HTML Tags und Konvertierung in Plain Text
                                // **************************************************************************************
                            
                                    var inhalt = getState("ical.1.data.html"/*HTML iCal table*/);           // an deinen eigenen Kalender anpassen
                                    var inhaltString = inhalt.val.toString();
                                    var inhaltStringReplace = inhaltString;
                                    var inhaltStringText;
                                    var i_search;
                            
                                    // remove all inside SCRIPT and STYLE tags
                                    inhaltStringReplace=inhaltStringReplace.replace(/<script.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/script>/gi, "");
                                    inhaltStringReplace=inhaltStringReplace.replace(/<style.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/style>/gi, "");
                            
                                    // remove BR tags
                                    inhaltStringReplace=inhaltStringReplace.replace(/
                            /gi, "");
                                    inhaltStringReplace=inhaltStringReplace.replace(/<br\s\>/gi, "");
                                    inhaltStringReplace=inhaltStringReplace.replace(/<br\>/gi, "");
                            
                                    // remove all else
                                    inhaltStringReplace=inhaltStringReplace.replace(/<(?:.|\s)*?>/g, "");
                            
                                    // get rid of html-encoded characters:
                                    inhaltStringReplace=inhaltStringReplace.replace(/ /gi," ");
                                    inhaltStringReplace=inhaltStringReplace.replace(/&/gi,"&");
                                    inhaltStringReplace=inhaltStringReplace.replace(/"/gi,'"');
                                    inhaltStringReplace=inhaltStringReplace.replace(//gi,'>');    
                            
                                    if(debug) log(inhaltStringReplace);
                            
                            // n-ten Treffer finden
                            
                                    function nthIndex(str, pat, n){
                                    var L= str.length, i= -1;
                                    while(n-- && i++ <l){ i="str.indexOf(pat," i);/if/(i/</0)/break;/}/i_search="i;" funktion/zum/tage/im/monat/zählen/function/daysinmonth(month,/year)/{/return/new/date(year,/month,/0).getdate();/position/bestimmen/var/pos="inhaltStringReplace.indexOf(" such1,/1);/if(debug)/log("pos/ist:/"+pos);/inhaltstringtext="inhaltStringReplace.substring((pos-13),pos-1);" log("datum/"+inhaltstringtext);/nthindex(inhaltstringtext,/".",/t_m="inhaltStringText.slice(0," i_search);/pos1="i_search+1;" log("pos1:/"/+pos1/);/2);/m_m="inhaltStringText.slice(pos1," pos2="i_search+1;" log("pos2:/+pos2/j_m="inhaltStringText.slice(pos2," inhaltstringtext.len/log(t_m/+"/,/+m_m/+j_m);/datum/heute/ermitteln/today="new" date();/log(today);/tag/t="today.getDate();" m="today.getMonth()+1;" jahr/j="today.getFullYear();" "+t+m+j);/berechnung/tagesdifferenzen/diff="0;" dim="DaysInMonth(m," j);/des/aktuellen/monats/log("tage/aktueller/monat:/"+dim);/if(j_m="">j || m_m > m) {            // Prüfung: Jahr_Müll größer als aktuelles Jahr? Relevant bei Jahreswechsel ODEr Monat Müll größer aktueller Monat?
                            
                                        diff = parseInt(dim) - parseInt(t) + parseInt(t_m);
                            
                                    }
                                    else diff = parseInt(t_m) - parseInt(t);
                            
                                      if(debug) log("Tage bis zum nächsten Müll: "+diff);
                            
                             setState('javascript.0.muell.papier', diff);    //Schreibe Ergebnis in am anfang erstelles Objekt</l){></br\></br\s\></style.*></script.*> 
                            

                            Beim start des Scripts bekomm ich immer folgende Fehlermeldung:

                            19:01:39.824	info	javascript.0 Stop script script.js.common.Müllkalender
                            19:01:39.847	info	javascript.0 Start javascript script.js.common.Müllkalender
                            19:01:39.848	error	javascript.0 script.js.common.Müllkalender: The "getState" method cannot be used synchronously, because the adapter setting "Do not subscribe to all states on start" is enabled.
                            19:01:39.848	error	javascript.0 script.js.common.Müllkalender: Please disable that setting or use "getState" with a callback, e.g.: getState("ical.1.data.html", (err, state) => { ... });
                            19:01:39.848	error	javascript.0 script.js.common.Müllkalender: script.js.common.Müllka
                            

                            Ical.1 ist so konfiguriert:
                            9441_instances_-iobroker__5.png 9441_instances_-iobroker__7.png 9441_instances_-iobroker__8.png

                            In Objekte - ical.1.events.1 wird Papier als true angezeigt!
                            9441_objects_-iobroker__7.png

                            In Objekte - javascript.0.muell wird papier (javascript.0.muell.papier) mit Wert 0 angezeigt!
                            9441_objects_-iobroker__8.png

                            Morgen wäre im Kalender der Termin für Papier! Wird mir aber nicht angezeigt!
                            9441_google_kalender_-_januar_2019.png

                            Wäre toll, wenn ich es mit eurer Hilfe schaffen könnte!

                            Danke!!

                            1 Reply Last reply Reply Quote 0
                            • T
                              tempestas last edited by

                              Schau Mal hier

                              Das letzte Skript ist am einfachsten.

                              viewtopic.php?p=207653#p207653

                              1 Reply Last reply Reply Quote 0
                              • Negalein
                                Negalein Global Moderator last edited by

                                @tempestas:

                                Schau Mal hier

                                Das letzte Skript ist am einfachsten. `

                                Danke, damit hats sofort funktioniert!

                                1 Reply Last reply Reply Quote 0
                                • Negalein
                                  Negalein Global Moderator last edited by

                                  @tempestas:

                                  Schau Mal hier

                                  Das letzte Skript ist am einfachsten. `

                                  Eine Frage/Bitte hätt ich noch!

                                  Das Script verursacht ein paar Fehler.

                                  JS ist komplettes Neuland für mich!

                                  Könntest du dir das anschaun?

                                  javascript.0	2019-01-19 17:08:26.907	error	Error in callback: TypeError: Cannot read property 'val' of undefined
                                  javascript.0	2019-01-19 17:08:26.907	error	script.js.common.Muell: Please disable that setting or use "getState" with a callback, e.g.: getState("ical.2.events.0.today.Restabfall", (err, state) => { ... });
                                  javascript.0	2019-01-19 17:08:26.906	error	script.js.common.Muell: The "getState" method cannot be used synchronously, because the adapter setting "Do not subscribe to all states on start" is enabled.
                                  

                                  Danke

                                  1 Reply Last reply Reply Quote 0
                                  • T
                                    tempestas last edited by

                                    das hier

                                    script.js.common.Muell: Please disable that setting or use "getState" with a callback, e.g.: getState("ical.2.events.0.today.Restabfall", (err, state) => { ... });
                                    javascript.0	2019-01-19 17:08:26.906	error	script.js.common.Muell: The "getState" method cannot be used synchronously, because the adapter setting "Do not subscribe to all states on start" is enabled.
                                    

                                    taucht ja auch an anderer Stelle bei dir auf. Da ist was in deinem JS Adapter nicht richtig eingestellt, will mir scheinen.

                                    und zwar das hier:

                                    because the adapter setting "Do not subscribe to all states on start" is enabled

                                    im adapter den Haken entfernen, Adapter neu starten und testen

                                    1 Reply Last reply Reply Quote 0
                                    • Negalein
                                      Negalein Global Moderator last edited by

                                      @tempestas:

                                      im adapter den Haken entfernen, Adapter neu starten und testen `

                                      hab ich getestet!

                                      Adapter wird neu gestartet und geht dann gleich wieder von grün auf rot!

                                      host.ioBroker	2019-01-19 22:05:47.089	info	Restart adapter system.adapter.javascript.0 because enabled
                                      host.ioBroker	2019-01-19 22:05:47.089	error	instance system.adapter.javascript.0 terminated with code 0 (OK)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at emitNone (events.js:91:20)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at IncomingMessage.g (events.js:292:16)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at IncomingMessage. <anonymous>(/opt/iobroker/node_modules/iobroker.javascript/node_modules/request/request.js:1083:12)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at Request.emit (events.js:188:7)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at emitOne (events.js:96:13)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at Request. <anonymous>(/opt/iobroker/node_modules/iobroker.javascript/node_modules/request/request.js:1161:10)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at Request.emit (events.js:191:7)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at emitTwo (events.js:106:13)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at Request.self.callback (/opt/iobroker/node_modules/iobroker.javascript/node_modules/request/request.js:185:22)
                                      host.ioBroker	2019-01-19 22:05:47.088	error	Caught by controller[0]: at Request._callback (script.js.common.Alexa_Logon:259:53)
                                      host.ioBroker	2019-01-19 22:05:47.087	error	Caught by controller[0]: TypeError: Cannot read property '1' of null</anonymous></anonymous>
                                      
                                      1 Reply Last reply Reply Quote 0
                                      • T
                                        tempestas last edited by

                                        Das scheint was mit einem Alexa Skript zu tun zu haben

                                        1 Reply Last reply Reply Quote 0
                                        • Negalein
                                          Negalein Global Moderator last edited by

                                          @tempestas:

                                          Das scheint was mit einem Alexa Skript zu tun zu haben `

                                          Da hab ich dieses:

                                          `// AlexaControl
                                          //
                                          // Version:     v0.1.6
                                          // Author:      Hauke
                                          
                                          // Dank an  ruhr70 dessen Skript als Vorlage diente
                                          //		http://forum.iobroker.net/viewtopic.php?f=37&t=6035
                                          // und Stefan.Franke, dessen Skript den Login per Cookie ermöglicht
                                          //		http://forum.iobroker.net/viewtopic.php?f=37&t=9237&p=98626&hilit=alexaLogOn#p98493
                                          
                                          // Changelog:
                                          
                                          // v.0.1.6 Fehler behoben: Cannot use 'in' operator to search for 'provider' in undefined
                                          // v.0.1.5 Dummy-Objekte, falls Alexa {"message":null} antwortet, weil das Device derzeit nicht aktiv ist
                                          // v.0.1.4 Spielzeit und Titellänge werden nun im 2-Sekunden-Takt berechnet
                                          // v.0.1.3 WiFi ESSID / MAC werden ausgelesen
                                          // v.0.1.2 Playlists
                                          // v.0.1.1 History
                                          // v.0.1.0 erste brauchbare Version
                                          
                                          // ----------------------------------------------------------------------------------------------------
                                          // Settings:
                                          // ----------------------------------------------------------------------------------------------------
                                          
                                          // Loglevel kann folgenden Wert haben: debug, info, warn, error, none
                                          var logLevel = 'info';
                                          
                                          // true: Datenpunkte werden überschrieben (wenn z.B. Bezeichnungen geändert wurden)
                                          var forceCreation	= false;
                                          
                                          // Pfad im Javascript-Adapter unter dem die Geräte angelegt werden sollen bei "Alexa" wird daraus z.B.: javascript.0.Alexa
                                          var pfad = "AlexaControl";
                                          
                                          // Hier die Datenpunkti mit dem Cookie und CSRF aus dem Script von Stefan.Franke
                                          var idCookie 	= "javascript.0.AlexaLogon.cookie";
                                          var idCsrf 		= "javascript.0.AlexaLogon.csrf";
                                          
                                          // Hitradio Ö3 - Default Radiostation für den Radio an Button.
                                          var defaultRadiostation = "s8007"; 
                                          
                                          // Jede Minute History auslesen? Wert im üblichen Unix Crontab-Stil
                                          // Manuell jeder Zeit per Button möglich.
                                          var updateHistoryScheduler = "* * * * *";
                                          
                                          // Wie oft Playlists automatisch auslesen? Wert im üblichen Unix Crontab-Stil
                                          // Manuell jeder Zeit per Button möglich.
                                          var updatePlaylistScheduler = "0 0 * * *";
                                          
                                          // Sollen Geräte gelistet werden, die nicht Kontrolliert werden können? (TV-Stick, etc.)
                                          // Hier wird dann nur die Gruppe "device" erstellt. "player" und "control" werden nicht erstellt.
                                          var listNonCotrollable = false;
                                          
                                          // Liste der bekannten Devicetypen, Geräte mit bekannten DeviceType
                                          // auf das ursprüngliche "anlegen" kann verzichtet werden, da die Capabilities geparst werden. 
                                          // Nur Steuerbare Devices werden mit Steuer-Objekten versehen
                                          var knownDeviceType = {
                                              "A3S5BH2HU6VAYF":   "Echo Dot 2.Gen",
                                              "AB72C64C86AW2":    "Echo",
                                              "A7WXQPH584YP":     "Echo 2.Gen",
                                          	"A10A33FOX2NUBK":   "Echo Spot",
                                          	"A1NL4BVLQ4L3N3":	"Echo Show",
                                              "A15ERDAKK5HQQG":   "Sonos",
                                              "A2E0SNTXJVT7WK":   "Fire TV V1",
                                              "ADVBD696BHNV5":    "Fire TV Stick V1",
                                              "A2LWARUGJLBYEW":   "Fire TV Stick V2",
                                              "A2T0P32DY3F7VB":   "echosim.io",
                                              "AILBSA2LNTOYL":    "reverb App",
                                              "A2M35JJZWCQOMZ":   "Echo Plus"
                                          };
                                          
                                          // ----------------------------------------------------------------------------------------------------
                                          // Skript, ab hier nichts ändern
                                          // ----------------------------------------------------------------------------------------------------
                                          
                                          // Initiale Variablen setzen
                                          // ------------------------------------------------------
                                          
                                          //Script von Stefan.Franke nötig, welches csrf und cookie ausliest
                                          var csrf   = getState(idCsrf).val;
                                          var cookie = getState(idCookie).val;
                                          cookie = cookie.replace(/\\/g, "");
                                          
                                          // Object-Pfad definieren unter dem Devices angelegt werden
                                          var deviceObjectPath		= pfad + ".Devices."; 
                                          
                                          // Node Module https verwenden
                                          var https = require('https');     
                                          
                                          // CUSTOMERID wird später aus der Geräteliste ausgelesen
                                          var mediaOwnerCustomerId;
                                          
                                          // globales Objekt mit allen Devices
                                          var devices = {};
                                          
                                          // LoglevelInt defniniern und dann Wert aus den Settings setzen
                                          var logLevelInt = 5;
                                          setLoglevel(logLevel);
                                          
                                          // Beim Programmende eine Info ausgeben
                                          onStop(function skriptStop () {
                                              logInfo("**** AlexaControl wurde gestoppt ****");
                                          }, 2000 /*ms*/);
                                          
                                          // Das eigentliche Programm läuft ab hier
                                          // ------------------------------------------------------
                                          
                                          logInfo("**** AlexaControl wurde gestartet ****");
                                          
                                          if(forceCreation) {
                                          	logWarn("Forcecreation ist eingeschaltet. Wenn nicht mehr benötigt, bitte im Skript auf false setzen");
                                          }
                                          
                                          // Objekte auslegen und anlegen
                                          initAlexa();
                                          
                                          // updates History
                                          schedule(updateHistoryScheduler, function () {rescanHistory();});
                                          
                                          // updates Playlists
                                          schedule(updatePlaylistScheduler, function () {updatePlaylists();});
                                          
                                          // -------------------------------------------------------------------------------------------------------
                                          //  Objekte Auslesen
                                          // -------------------------------------------------------------------------------------------------------
                                          
                                          /**
                                           * liest per https-GET die aktuellen Playlists von Amazon ein und speichert diese in die "Playlists.X" States
                                           */
                                          function updatePlaylists() {
                                          
                                          	logInfo('[updatePlaylists]');
                                          
                                          	// zur Abfrage wird der erste Echo mit MusicPlayer verwendet
                                          	var echoWithMusicPlayer = getEchoWithMusicPlayerFromDevices();
                                          
                                          	var path = '/api/cloudplayer/playlists?deviceSerialNumber=' + echoWithMusicPlayer.serialNumber + '&deviceType=' + echoWithMusicPlayer.deviceType + '&mediaOwnerCustomerId=' + mediaOwnerCustomerId;
                                          
                                          	httpsReqGet(
                                          		path,
                                          		function (result) {	
                                          			tmpListe = JSON.parse(result).playlists;
                                          			var playlistsJSON = [];
                                          			var playlistsTitles = [];
                                          			var playlistsIDs = [];
                                          			for (playlist in tmpListe) {			
                                          				var obj = {  
                                          					"title": tmpListe[playlist][0].title,
                                          					"playlistId": tmpListe[playlist][0].playlistId
                                          				};			
                                          				playlistsJSON.push(obj);				
                                          				playlistsTitles.push(tmpListe[playlist][0].title);				
                                          				playlistsIDs.push(tmpListe[playlist][0].playlistId);				
                                          			}
                                              		setState(pfad + ".Playlists.JSON", JSON.stringify(playlistsJSON));
                                              		setState(pfad + ".Playlists.Titles", playlistsTitles.join(';'));
                                              		setState(pfad + ".Playlists.IDs", playlistsIDs.join(';'));			
                                          		}
                                          	);
                                          }
                                          
                                          /**
                                           * liest per https-GET die letzten 20 Alexa-History-Einträge von Amazon ein und speichert diese in die "Playlists.X" States
                                           */
                                          function rescanHistory() {
                                          
                                          	logInfo('[rescanHistory]');
                                          
                                          	var path = 'https://alexa.amazon.de/api/activities?startTime=&size=20&offset=1';
                                          
                                              httpsReqGet(
                                              	path,
                                              	function (result) {	
                                          			activities = JSON.parse(result).activities;
                                          			creationTime = getState(pfad + ".History.creationTime").val;
                                          			for(var i = (activities.length - 1); i > 0; i--) {
                                          				if ((activities[i].creationTimestamp > creationTime) || creationTime === null) {
                                          					deviceName = getDeviceNameBySerialNumber(activities[i].sourceDeviceIds[0].serialNumber);
                                          					setState(pfad + ".History.creationTime", activities[i].creationTimestamp);
                                          					setState(pfad + ".History.deviceName", deviceName);
                                          					setState(pfad + ".History.summary", JSON.parse(activities[i].description).summary);
                                          				}
                                          		   }
                                          		}
                                              );
                                          }
                                          
                                          /**
                                           * Updated ein Device per DatenpunktName, sowohl "control", als auch "player" wird
                                           * abgerufen und gespeichert befindet sich currentState im Modus "PLAYING", so wird
                                           * mit einem Timeout diese Funktion für das Device erneut aufgerufen
                                           *
                                           * @param string deviceDpName
                                           */
                                          function updateDevice(deviceDpName){
                                          
                                          	if(typeof(devices[deviceDpName]) != "undefined") {		
                                          		if (deviceIsControllable(devices[deviceDpName].capabilities)) {
                                          			logInfo('[updateDevice] ' + deviceDpName);
                                          
                                          			var controlPath = deviceObjectPath + clearName(deviceDpName) + ".control";
                                          
                                          			// deviceObjectPath + clearName(deviceDpName) + ".control.lastState"
                                          			getDeviceStateBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, function(deviceState){
                                          
                                          				// nur updaten, wenn unterschiedlich
                                          				if (deviceState.volume != getState(controlPath + ".volume").val) {
                                          					setState(controlPath + ".volume", parseInt(deviceState.volume));
                                          				}
                                          
                                          				if(deviceHasMusicPlayer(devices[deviceDpName].capabilities)){	
                                          					if (deviceState.shuffling != getState(controlPath + ".shuffle").val) {
                                          						setState(controlPath + ".shuffle", deviceState.shuffling);
                                          					}				
                                          					if (deviceState.looping != getState(controlPath + ".repeat").val) {
                                          						setState(controlPath + ".repeat", deviceState.looping);
                                          					}
                                          				}
                                          
                                          				getDevicePlayerBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, function(devicePlayer){
                                          
                                          					// player	
                                          					var playerPath = deviceObjectPath + clearName(deviceDpName) + ".player";
                                          					setState(playerPath + ".contentType", getStringOrEmpty(deviceState.contentType));
                                          					setState(playerPath + ".currentState", getStringOrEmpty(deviceState.currentState));
                                          					setState(playerPath + ".imageURL", getStringOrEmpty(deviceState.imageURL));
                                          					setState(playerPath + ".muted", deviceState.muted);
                                          					setState(playerPath + ".providerId", getStringOrEmpty(deviceState.providerId));
                                          					setState(playerPath + ".radioStationId", getStringOrEmpty(deviceState.radioStationId));
                                          					setState(playerPath + ".service", getStringOrEmpty(deviceState.service));
                                          
                                          					var providerName = '';
                                          					if ((devicePlayer !== undefined) && ("provider" in devicePlayer) && (devicePlayer.provider !== null)){
                                          						providerName = getStringOrEmpty(devicePlayer.provider.providerName);
                                          					}
                                          					setState(playerPath + ".providerName", providerName);
                                          
                                          					var title = '';
                                          					var interpreter = '';
                                          					var album = '';
                                          					if ((devicePlayer !== undefined) &&("infoText" in devicePlayer) && (devicePlayer.infoText !== null)){
                                          						title = getStringOrEmpty(devicePlayer.infoText.title);
                                          						interpreter = getStringOrEmpty(devicePlayer.infoText.subText1);
                                          						album = getStringOrEmpty(devicePlayer.infoText.subText2);
                                          					}		
                                          					setState(playerPath + ".title", title);
                                          					setState(playerPath + ".interpreter", interpreter);
                                          					setState(playerPath + ".album", album);
                                          
                                          					var mainArtUrl = '';	
                                          					if ((devicePlayer !== undefined) &&("mainArt" in devicePlayer) && (devicePlayer.mainArt !== null)){
                                          						mainArtUrl = getStringOrEmpty(devicePlayer.mainArt.url);
                                          					}	
                                          					setState(playerPath + ".mainArtUrl", mainArtUrl);	
                                          
                                          					var miniArtUrl = '';
                                          					if ((devicePlayer !== undefined) &&("miniArt" in devicePlayer) && (devicePlayer.miniArt !== null)){
                                          						miniArtUrl = getStringOrEmpty(devicePlayer.miniArt.url);
                                          					}	
                                          					setState(playerPath + ".miniArtUrl", miniArtUrl);	
                                          
                                          					var mediaLength = 0;
                                          					var mediaProgress = 0;
                                          					var mediaProgressPercent = 0;
                                          					if ((devicePlayer !== undefined) &&("progress" in devicePlayer) && (devicePlayer.progress !== null)){
                                          						mediaLength = parseInt(devicePlayer.progress.mediaLength);
                                          						mediaProgress = parseInt(devicePlayer.progress.mediaProgress);
                                          						if (mediaLength > 0) {					
                                          							mediaProgressPercent = Math.round(((mediaProgress * 100) / mediaLength));
                                          						}
                                          					}				
                                          					setState(playerPath + ".mediaLength", mediaLength);
                                          					setState(playerPath + ".mediaLengthStr", sekToHMS(mediaLength));
                                          					setState(playerPath + ".mediaProgress", mediaProgress);	
                                          					setState(playerPath + ".mediaProgressStr", sekToHMS(mediaProgress));
                                          					setState(playerPath + ".mediaProgressPercent", mediaProgressPercent);
                                          
                                          				});
                                          			});
                                          
                                          		} else {
                                          			logInfo('[updateDevice] Device not controllable: ' + deviceDpName);
                                          		}
                                          	}else {
                                          		logInfo('[updateDevice] Device unknown: ' + deviceDpName);
                                          	}
                                          }
                                          
                                          /**
                                           * Inkrementiert "mediaProgress" alle 2 Sekunden um 2\. So wird ein permanentes https-get überflüssig
                                           * ruft sich nach 2 Sekunden erneut selbst auf, wenn "currentState" noch auf "PLAYING" steht.
                                           * ist "mediaProgress" größer als "mediaLength", so ist der Song zu Ende und "updateDevice" wird aufgerufen.
                                           *
                                           * @param string deviceDpName
                                           */
                                          function updateMediaProgress(deviceDpName) {
                                          
                                          	var playerPath = deviceObjectPath + deviceDpName + ".player";
                                          
                                          	var currentState 		= getState(playerPath + ".currentState").val;	
                                          	var mediaProgress 		= getState(playerPath + ".mediaProgress").val;
                                          	var mediaLength 		= getState(playerPath + ".mediaLength").val;
                                          
                                          	if ((currentState == 'PLAYING') ) {	
                                          		mediaProgressNew = mediaProgress + 2;
                                          
                                          		// Am Ende des Titels soll neu geladen werden. Ist es Radio (länge = 0) dann alle 200 sekunden
                                          		if ((mediaProgressNew > mediaLength) && ((mediaLength > 0) || (mediaProgressNew % 200 < 2))){		
                                          			setTimeout( function() { updateDevice(deviceDpName); }, 2000 );
                                          		}
                                          
                                          		// Nun mediaProgress und mediaProgressPercent neu berechnen
                                          		if (mediaLength > 0) {
                                          			mediaProgressPercent = Math.round((((mediaProgressNew) * 100) / mediaLength));
                                          		} else {
                                          			mediaProgressPercent = 0;
                                          		}
                                          		setState(playerPath + ".mediaProgressPercent", mediaProgressPercent);
                                          		setState(playerPath + ".mediaProgress", mediaProgressNew);
                                          		setState(playerPath + ".mediaProgressStr", sekToHMS(mediaProgressNew));
                                          
                                          		setTimeout( function() { updateMediaProgress(deviceDpName); }, 2000 );
                                          
                                          	}
                                          }
                                          
                                          /**
                                           * Ruft den aktuellen State eines Devices per Seriennummer und Type von Amazon ab.
                                           * Gibt die Antwort an "callback(result)" weiter
                                           *
                                           * @param string serialNumber
                                           * @param string deviceType
                                           * @param function callback
                                           */
                                          function getDeviceStateBySerialAndType(serialNumber, deviceType, callback) {
                                          	httpsReqGet(
                                          		'/api/media/state?deviceSerialNumber=' + serialNumber + '&deviceType=' + deviceType,
                                          		function(result) {
                                          			// Es kommt vor, dass Geräte nicht antworten, weil sie nicht aktiv sind. Dann greift hier der Dummy-Wert
                                          			if (result == '{"message":null}') {
                                          				result = JSON.stringify({
                                          					"clientId":null,
                                          					"contentId":null,
                                          					"contentType":null,
                                          					"currentState":"IDLE",
                                          					"imageURL":null,
                                          					"isDisliked":false,
                                          					"isLiked":false,
                                          					"looping":false,
                                          					"mediaOwnerCustomerId":null,
                                          					"muted":false,
                                          					"programId":null,
                                          					"progressSeconds":0,
                                          					"providerId":null,
                                          					"queue":null,
                                          					"queueId":null,
                                          					"queueSize":0,
                                          					"radioStationId":null,
                                          					"radioVariety":0,
                                          					"referenceId":null,
                                          					"service":null,
                                          					"shuffling":false,
                                          					"timeLastShuffled":0,
                                          					"volume":0
                                          				});
                                          			}
                                          			if(callback !== undefined && typeof callback === 'function') callback(JSON.parse(result));
                                          		}
                                          	);
                                          }
                                          
                                          /**
                                           * Ruft den aktuellen State eines Devices per DatenpunktNamen von Amazon ab.
                                           * Gibt die Antwort an "callback(result)" weiter
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function getDeviceState(deviceDpName, callback) {
                                          	getDeviceStateBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, callback);
                                          }
                                          
                                          /**
                                           * Ruft die aktuelle PlayerInfo eines Devices per Seriennummer und Type von Amazon ab.
                                           * Gibt die Antwort an "callback(result)" weiter
                                           *
                                           * @param string serialNumber
                                           * @param string deviceType
                                           * @param function callback
                                           */
                                          function getDevicePlayerBySerialAndType(serialNumber, deviceType, callback) {
                                          	httpsReqGet(
                                          		'/api/np/player?deviceSerialNumber=' + serialNumber + '&deviceType=' + deviceType,
                                          		function(result) {		
                                          			// Es kommt vor, dass Geräte nicht antworten, weil sie nicht aktiv sind. Dann greift hier der Dummy-Wert
                                          			if (result == '{"message":null}') {
                                          				result =  JSON.stringify({
                                          					"playerInfo":{
                                          						"hint":null,
                                          						"infoText":null,
                                          						"isPlayingInLemur":false,
                                          						"lemurVolume":null,
                                          						"lyrics":null,
                                          						"mainArt":null,
                                          						"mediaId":null,
                                          						"miniArt":null,
                                          						"miniInfoText":null,
                                          						"playbackSource":null,
                                          						"playingInLemurId":null,
                                          						"progress":null,
                                          						"provider":null,
                                          						"queueId":null,
                                          						"state":null,
                                          						"template":null,
                                          						"transport":null,
                                          						"volume":null
                                          					}
                                          				});
                                          			}	
                                          
                                          			if(callback !== undefined && typeof callback === 'function') callback(JSON.parse(result).playerInfo);
                                          		}
                                          	);
                                          }
                                          
                                          /**
                                           * Ruft die aktuelle PlayerInfo eines Devices per DatenpunktNamen von Amazon ab.
                                           * Gibt die Antwort an "callback(result)" weiter
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function getDevicePlayer(deviceDpName, callback) {
                                          	getDevicePlayerBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, callback);
                                          }
                                          
                                          /**
                                           * liest per https-GET alle Alexa-fähigen Geräte neu ein und updated bei allen 
                                           * bereits bekannten Geräten die Infos, wie z.B. Onlinestatus, WLAN, etc.
                                           */
                                          function updateAlexa(){
                                          	logInfo('[updateAlexa]');
                                          	httpsReqGet('/api/devices/device', function(result) {
                                          		// Falls Result leer ist, soll nichts weiter gemacht werden 
                                          		if(!result) return logWarn("Es konnten keine Daten ermittelt werden! Cookie richtig?");
                                          		logDebug(result);
                                          
                                          		var alexaDeviceObj      = JSON.parse(result);
                                          
                                          		var numberOfDevices     = alexaDeviceObj.devices.length;
                                          		logInfo("Anzahl vorhandener Geräte mit Alexa Unterstützung: " + numberOfDevices);
                                          
                                          		if (numberOfDevices < 1) {
                                          			return logWarn("Error: Skript konnte keine Geräte abfragen");
                                          		}
                                          
                                          		// Kundenindiviuelle Customer ID aus dem ersten Gerät entnehmen -> in vorbereitete globale Variable schreiben
                                          		mediaOwnerCustomerId = getStringOrEmpty(alexaDeviceObj.devices[0].deviceOwnerCustomerId);
                                          
                                          		// Devices
                                          		for(var i = 0; i < numberOfDevices; i++) {
                                          			// Nur bekannte Geraete updaten
                                          			if(typeof(devices[clearName(alexaDeviceObj.devices[i].accountName)]) != "undefined") {
                                          
                                          				// Pruefen, ob das Geraet noch das selbe ist
                                          				if (devices[clearName(alexaDeviceObj.devices[i].accountName)].serialNumber != alexaDeviceObj.devices[i].serialNumber){
                                          					logError('Das Geraet "' + clearName(alexaDeviceObj.devices[i].accountName) + '" hat nach update eine andere Seriennummer!');
                                          				} else {
                                          
                                          					var devicePath = deviceObjectPath + clearName(alexaDeviceObj.devices[i].accountName) + ".device";
                                          
                                          					httpsReqGet(
                                          						'/api/device-wifi-details?deviceSerialNumber=' + alexaDeviceObj.devices[i].serialNumber + '&deviceType=' + alexaDeviceObj.devices[i].deviceType,
                                          						function(result) {
                                          							setState(devicePath + ".essid",			getStringOrEmpty(JSON.parse(result).essid));
                                          							setState(devicePath + ".macAddress",	getStringOrEmpty(JSON.parse(result).macAddress));
                                          						}
                                          					);
                                          
                                          					setState(devicePath + ".language",			getStringOrEmpty(alexaDeviceObj.devices[i].language));
                                          					setState(devicePath + ".online",			alexaDeviceObj.devices[i].online);
                                          					setState(devicePath + ".parentClusters",	getStringOrEmpty(alexaDeviceObj.devices[i].parentClusters));
                                          					setState(devicePath + ".softwareVersion",	getStringOrEmpty(alexaDeviceObj.devices[i].softwareVersion));
                                          
                                          					// Device updaten
                                          					updateDevice(clearName(alexaDeviceObj.devices[i].accountName));
                                          				}
                                          
                                          			} 
                                          		}
                                          	}); 
                                          }
                                          
                                          // -------------------------------------------------------------------------------------------------------
                                          //  Objekte Anlegen
                                          // -------------------------------------------------------------------------------------------------------
                                          
                                          /**
                                           * liest per https-GET alle Alexa-fähigen Geräte ein und legt die Objekte an
                                           */
                                          function initAlexa() {
                                          	httpsReqGet('/api/devices/device', function(result) {
                                          		// Falls Result leer ist, soll nichts weiter gemacht werden 
                                          		if(!result) return logWarn("Es konnten keine Daten ermittelt werden! Cookie richtig?");
                                          		logDebug(result);
                                          
                                          		var alexaDeviceObj      = JSON.parse(result);
                                          
                                          		var numberOfDevices     = alexaDeviceObj.devices.length;
                                          		logInfo("Anzahl vorhandener Geräte mit Alexa Unterstützung: " + numberOfDevices);
                                          
                                          		if (numberOfDevices < 1) {
                                          			return logWarn("Error: Skript konnte keine Geräte abfragen");
                                          		}
                                          
                                          		// Kundenindiviuelle Customer ID aus dem ersten Gerät entnehmen -> in vorbereitete globale Variable schreiben
                                          		mediaOwnerCustomerId = alexaDeviceObj.devices[0].deviceOwnerCustomerId;
                                          		createDeviceState(pfad + ".mediaOwnerCustomerId",     mediaOwnerCustomerId,  forceCreation,  {name:"Individuelle Kunden ID",   type:"string",  role:"value"});
                                          
                                          		// Devices
                                          		for(var i = 0; i < numberOfDevices; i++) {
                                          			if (listNonCotrollable || deviceIsControllable(alexaDeviceObj.devices[i].capabilities)) {		
                                          				devices[clearName(alexaDeviceObj.devices[i].accountName)] = createDevice(alexaDeviceObj.devices[i], forceCreation);
                                          			}
                                          		}
                                          
                                          		// Update
                                          		createState(
                                          			pfad + ".update",
                                          			false,
                                          			forceCreation,
                                          			{name:"Update Devices",   type:"boolean",  role:"button"}, 
                                          			null,					
                                          			function () {
                                          				setTimeout(
                                          					function() {
                                          						logInfo("CreateON: " + pfad + ".update");
                                          						on({id: "javascript." + instance + "." + pfad + ".update", change: "any"}, 
                                          						function (obj){
                                          							unsetButtonFirst(obj, function (obj) {updateAlexa();});
                                          						})
                                          					}
                                          					,
                                          					3000
                                          				);
                                          			}
                                          		);
                                          
                                          		// Playlists	
                                          		createDeviceState(pfad + ".Playlists.JSON",		null,	forceCreation,  {name:"Playlists als JSON",   					type:"string",  role:"state"});
                                          		createDeviceState(pfad + ".Playlists.Titles",	null,	forceCreation,  {name:"Playlist Titel als Liste fuer Dropdown",	type:"string",  role:"state"});
                                          		createDeviceState(pfad + ".Playlists.IDs",		null,	forceCreation,  {name:"Playlist IDs als Liste fuer Dropdown",	type:"string",  role:"state"});
                                          		createState(
                                          			pfad + ".Playlists.update",
                                          			false,
                                          			forceCreation,
                                          			{name:"Update Playlists",   type:"boolean",  role:"button"}, 
                                          			null,					
                                          			function () {
                                          				setTimeout(
                                          					function() {
                                          						logInfo("CreateON: " + pfad + ".Playlists.update");
                                          						on({id: "javascript." + instance + "." + pfad + ".Playlists.update", change: "any"}, 
                                          						function (obj){
                                          							unsetButtonFirst(obj, function (obj) {updatePlaylists();});
                                          						})
                                          					}
                                          					,
                                          					3000
                                          				);
                                          			}
                                          		);
                                          		// Einmalig die Playlists abfragen
                                          		updatePlaylists();
                                          
                                          		// History
                                          		createState(pfad + ".History.creationTime",	null,	forceCreation,  {name:"Timestamp",		type:"number",  role:"state"});
                                          		createState(pfad + ".History.deviceName",	null,	forceCreation,  {name:"deviceName",		type:"string",  role:"state"});
                                          		createState(pfad + ".History.summary",		null,	forceCreation,  {name:"summary",		type:"string",  role:"state"});
                                          		createState(
                                          			pfad + ".History.update",
                                          			false,
                                          			forceCreation,
                                          			{name:"Update History",   type:"boolean",  role:"button"}, 
                                          			null,					
                                          			function () {
                                          				setTimeout(
                                          					function() {
                                          						logInfo("CreateON: " + pfad + ".History.update");
                                          						on({id: "javascript." + instance + "." + pfad + ".History.update", change: "any"}, 
                                          						function (obj){
                                          							unsetButtonFirst(obj, function (obj) {rescanHistory();});
                                          						})
                                          					}
                                          					,
                                          					3000
                                          				);
                                          			}
                                          		);
                                          		// Erstmalig die History abgragen
                                          		rescanHistory();
                                          	}); 
                                          }
                                          
                                          /**
                                           * Erzeugt alle States zu einem übergebenen Device-Objekt. Anhand der "capabilities" 
                                           * des Devices, werden, ggf. "control" und "player" States erstellt.
                                           *
                                           * @param object amazonDeviceObject
                                           * @param boolean forceCreation
                                           */
                                          function createDevice(amazonDeviceObject, forceCreation) {
                                          	logInfo('createDevice: '+  amazonDeviceObject.accountName);
                                          
                                          	var devicePath = deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".device";
                                          
                                          	// device
                                          	createDeviceState(devicePath + ".accountName",				getStringOrEmpty(amazonDeviceObject.accountName),						forceCreation,   {name:"Name", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".capabilities",				getStringOrEmpty(JSON.stringify(amazonDeviceObject.capabilities)),		forceCreation,   {name:"Fähigkeiten", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".clusterMembers",			getStringOrEmpty(JSON.stringify(amazonDeviceObject.clusterMembers)),	forceCreation,   {name:"GruppenMitglieder", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".deviceAccountId",			getStringOrEmpty(amazonDeviceObject.deviceAccountId),					forceCreation,   {name:"AccountId", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".deviceFamily",				getStringOrEmpty(amazonDeviceObject.deviceFamily),						forceCreation,   {name:"DeviceFamily", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".deviceOwnerCustomerId",	getStringOrEmpty(amazonDeviceObject.deviceOwnerCustomerId),				forceCreation,   {name:"deviceOwnerCustomerId", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".deviceType",				getStringOrEmpty(amazonDeviceObject.deviceType),						forceCreation,   {name:"deviceType", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".deviceTypeString",			getStringOrEmpty(deviceTypeStr(amazonDeviceObject.deviceType)),			forceCreation,   {name:"deviceType als String", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".deviceTypeFriendlyName",	getStringOrEmpty(amazonDeviceObject.deviceTypeFriendlyName),			forceCreation,   {name:"deviceTypeFriendlyName", type:"string", role:"value"});
                                          
                                          	httpsReqGet(
                                          		'/api/device-wifi-details?deviceSerialNumber=' + amazonDeviceObject.serialNumber + '&deviceType=' + amazonDeviceObject.deviceType,
                                          		function(result) {
                                          			createDeviceState(devicePath + ".essid",			getStringOrEmpty(JSON.parse(result).essid),					forceCreation,   {name:"essid", type:"string", role:"value"});
                                          			createDeviceState(devicePath + ".macAddress",		getStringOrEmpty(JSON.parse(result).macAddress),			forceCreation,   {name:"macAddress", type:"string", role:"value"});
                                          		}
                                          	);
                                          
                                          	createDeviceState(devicePath + ".language",					getStringOrEmpty(amazonDeviceObject.language),				forceCreation,   {name:"language", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".online",					amazonDeviceObject.online,									forceCreation,   {name:"online (Klappt nur bei ECHOs)", type:"boolean", role:"value"});
                                          	createDeviceState(devicePath + ".parentClusters",			getStringOrEmpty(amazonDeviceObject.parentClusters),		forceCreation,   {name:"Mitglied in dieser Gruppe", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".serialNumber",				getStringOrEmpty(amazonDeviceObject.serialNumber),			forceCreation,   {name:"serialNumber", type:"string", role:"value"});
                                          	createDeviceState(devicePath + ".softwareVersion",			getStringOrEmpty(amazonDeviceObject.softwareVersion),		forceCreation,   {name:"softwareVersion", type:"string", role:"value"});
                                          
                                          	if (deviceIsControllable(amazonDeviceObject.capabilities)) {
                                          		createDeviceControl(amazonDeviceObject, forceCreation);
                                          	}
                                          
                                          	return { 
                                          		'serialNumber' : amazonDeviceObject.serialNumber,
                                          		'deviceType' : amazonDeviceObject.deviceType,
                                          		'capabilities' : amazonDeviceObject.capabilities
                                          	};
                                          }
                                          
                                          /**
                                           * Erzeugt alle  "control" und "player" States zu einem übergebenen Device-Objekt.
                                           * Für Initial-Werte wird das Device bei Amazon zunächst abgefragt
                                           *
                                           * @param object amazonDeviceObject
                                           * @param boolean forceCreation
                                           */
                                          function createDeviceControl(amazonDeviceObject, forceCreation) {
                                          	logInfo('createDeviceControl: '+  amazonDeviceObject.accountName);
                                          
                                          	var controlPath = deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".control";
                                          
                                          	// control		
                                          	createDeviceState(controlPath + ".LastStatus",				'INIT',					forceCreation,	{name:"Letzter Status", 			type:"string",	role:"value"});
                                          	createDeviceControlState(controlPath + ".updateDevice",		false,					forceCreation,	{name:"Device abfragen",			type:"boolean",	role:"button"});
                                          
                                          	// deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".control.lastState"
                                          	getDeviceStateBySerialAndType(amazonDeviceObject.serialNumber, amazonDeviceObject.deviceType, function(deviceState){
                                          
                                          		createDeviceControlState(controlPath + ".volume",			parseInt(deviceState.volume),	forceCreation,   {name:"Volume in Prozent(0-100)",				type:"number",	role:"level.volume"});
                                          		createDeviceControlState(controlPath + ".pause",			false,							forceCreation,   {name:"Pause",									type:"boolean",	role:"button"});
                                          		createDeviceControlState(controlPath + ".play",				false,							forceCreation,   {name:"Play",									type:"boolean",	role:"button"});
                                          
                                          		if(deviceHasMusicPlayer(amazonDeviceObject.capabilities)){
                                          			createDeviceControlState(controlPath + ".next",			false,							forceCreation,   {name:"Next (nächster Titel)",					type:"boolean",	role:"button"});
                                          			createDeviceControlState(controlPath + ".previous",		false,							forceCreation,   {name:"Previous (vorheriger Titel)",			type:"boolean",	role:"button"});
                                          			createDeviceControlState(controlPath + ".forward",		false,							forceCreation,   {name:"Forward (Hörbuch 30 Sekunden vor)",		type:"boolean",	role:"button"});
                                          			createDeviceControlState(controlPath + ".rewind",		false,							forceCreation,   {name:"Rewind (Hörbuch 30 Sekunden zurück)",	type:"boolean",	role:"button"});
                                          			createDeviceControlState(controlPath + ".previous",		false,							forceCreation,   {name:"Previous (vorheriger Titel)",			type:"boolean",	role:"button"});			
                                          			createDeviceControlState(controlPath + ".shuffle",		deviceState.shuffling,			forceCreation,   {name:"Shuffel an/aus",						type:"boolean",	role:"switch"});
                                          			createDeviceControlState(controlPath + ".repeat",		deviceState.looping,			forceCreation,   {name:"Repeat an/aus)",						type:"boolean",	role:"switch"});
                                          			createDeviceControlState(controlPath + ".playlistId",	false,							forceCreation,   {name:"spiele Playlist",						type:"string",	role:"control.value"});
                                          		}
                                          
                                          		if(deviceHasTuneIn(amazonDeviceObject.capabilities)){
                                          			createDeviceControlState(controlPath + ".radio",	false,					forceCreation,   {name:"Letzte Radiostation an/aus",	type:"boolean",	role:"switch"});
                                          			createDeviceControlState(controlPath + ".tunein",	defaultRadiostation,	forceCreation,   {name:"tunein Radiosenderkennung",		type:"string",	role:"control.value"});
                                          		}
                                          
                                          		getDevicePlayerBySerialAndType(amazonDeviceObject.serialNumber, amazonDeviceObject.deviceType, function(devicePlayer){
                                          
                                          			// player	
                                          			var playerPath = deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".player";
                                          
                                          			createDeviceState(playerPath + ".contentType",			getStringOrEmpty(deviceState.contentType),		forceCreation,   {name:"contentType", type:"string", role:"value"});	// "LIVE_STATION" | "TRACKS" | "CUSTOM_STATION"
                                          			createDeviceControlState(playerPath + ".currentState",	getStringOrEmpty(deviceState.currentState),		forceCreation,   {name:"currentState", type:"string", role:"value"});	// "PAUSED" | "PLAYING"
                                          			createDeviceState(playerPath + ".imageURL",				getStringOrEmpty(deviceState.imageURL),			forceCreation,   {name:"Grosses Bild", type:"string", role:"value"});
                                          			createDeviceState(playerPath + ".muted",				deviceState.muted,								forceCreation,   {name:"muted", type:"boolean", role:"value"});
                                          			createDeviceState(playerPath + ".providerId",			getStringOrEmpty(deviceState.providerId),		forceCreation,   {name:"providerId", type:"string", role:"value"}); // "TUNE_IN" | "CLOUD_PLAYER" | "ROBIN"
                                          			createDeviceState(playerPath + ".radioStationId",		getStringOrEmpty(deviceState.radioStationId),	forceCreation,   {name:"radioStationId", type:"string", role:"value"}); // "s24885" | null
                                          			createDeviceState(playerPath + ".service",				getStringOrEmpty(deviceState.service),			forceCreation,   {name:"service", type:"string", role:"value"}); // "TUNE_IN" | "CLOUD_PLAYER" | "PRIME_STATION"
                                          
                                          			var providerName = null;
                                          			if ((devicePlayer !== undefined) &&("provider" in devicePlayer) && (devicePlayer.provider !== null)){
                                          				providerName = getStringOrEmpty(devicePlayer.provider.providerName);
                                          			}
                                          
                                          			createDeviceState(playerPath + ".providerName",			providerName,							forceCreation,	{name:"active providerName",     type:"string",      role:"value"}); // "Amazon Music" | "TuneIn Live-Radio"
                                          
                                          			var title = '';
                                          			var interpreter = '';
                                          			var album = '';
                                          			if ((devicePlayer !== undefined) &&("infoText" in devicePlayer) && (devicePlayer.infoText !== null)){
                                          				title = getStringOrEmpty(devicePlayer.infoText.title);
                                          				interpreter = getStringOrEmpty(devicePlayer.infoText.subText1);
                                          				album = getStringOrEmpty(devicePlayer.infoText.subText2);
                                          			}
                                          			createDeviceState(playerPath + ".title",				title,									forceCreation,	{name:"active title",    		 type:"string",      role:"value"});
                                          			createDeviceState(playerPath + ".interpreter",			interpreter,							forceCreation,	{name:"active interpreter",    	 type:"string",      role:"value"});
                                          			createDeviceState(playerPath + ".album",				album,									forceCreation,	{name:"active album",    		 type:"string",      role:"value"});
                                          
                                          			var mainArtUrl = '';
                                          			if ((devicePlayer !== undefined) &&("mainArt" in devicePlayer) && (devicePlayer.mainArt !== null)){
                                          				mainArtUrl = getStringOrEmpty(devicePlayer.mainArt.url);
                                          			}			
                                          			createDeviceState(playerPath + ".mainArtUrl",			mainArtUrl,				forceCreation,	{name:"active mainArtUrl",    	 type:"string",      role:"value"});
                                          
                                          			var miniArtUrl = '';
                                          			if ((devicePlayer !== undefined) &&("miniArt" in devicePlayer) && (devicePlayer.miniArt !== null)){
                                          				miniArtUrl = getStringOrEmpty(devicePlayer.miniArt.url);
                                          			}			
                                          			createDeviceState(playerPath + ".miniArtUrl",			miniArtUrl,				forceCreation,	{name:"active miniArtUrl",    	 type:"string",      role:"value"});
                                          
                                          			var mediaLength = 0;
                                          			var mediaProgress = 0;
                                          			var mediaProgressPercent = 0;
                                          			if ((devicePlayer !== undefined) &&("progress" in devicePlayer) && (devicePlayer.progress !== null)) {
                                          				mediaLength = parseInt(devicePlayer.progress.mediaLength);
                                          				mediaProgress = parseInt(devicePlayer.progress.mediaProgress);
                                          				if (mediaLength > 0) {					
                                          					mediaProgressPercent = Math.round(((mediaProgress * 100) / mediaLength));
                                          				}
                                          			}
                                          			createDeviceState(playerPath + ".mediaLength",			mediaLength,				forceCreation,	{name:"active mediaLength",    			type:"number",      role:"value"});
                                          			createDeviceState(playerPath + ".mediaLengthStr",		sekToHMS(mediaLength),		forceCreation,	{name:"active mediaLength als (HH:)MM:SS",    			type:"string",      role:"value"});
                                          			createDeviceState(playerPath + ".mediaProgress",		mediaProgress,				forceCreation,	{name:"active mediaProgress",    		type:"number",      role:"value"});
                                          			createDeviceState(playerPath + ".mediaProgressStr",		sekToHMS(mediaProgress),	forceCreation,	{name:"active mediaProgress als (HH:)MM:SS",    		type:"string",      role:"value"});
                                          			createDeviceState(playerPath + ".mediaProgressPercent",	mediaProgressPercent,		forceCreation,	{name:"active mediaProgressPercent",    type:"number",      role:"value"});
                                          		});
                                          	});
                                          }
                                          
                                          /**
                                           * Erzeugt einen State und macht danach einen Logeintrag
                                           *
                                           * @param string objectdevicePath
                                           * @param mixed initialValue
                                           * @param boolean forceCreation
                                           * @param object common
                                           */
                                          function createDeviceState(objectdevicePath, initialValue, forceCreation, common) {
                                          	createState(objectdevicePath, initialValue, forceCreation, common, null, function(){logInfo('createState: ' + objectdevicePath)});
                                          }
                                          
                                          /**
                                           * Erzeugt einen State und macht danach einen Logeintrag
                                           * Dann wird für den State eine "on()-Funktion" erzeugt, die die gewünschte Funktion ausfürht
                                           *
                                           * @param string objectdevicePath
                                           * @param mixed initialValue
                                           * @param boolean forceCreation
                                           * @param object common
                                           */
                                          function createDeviceControlState(objectdevicePath, initialValue, forceCreation, common) {
                                          	createState(
                                          		objectdevicePath,
                                          		initialValue,
                                          		forceCreation,
                                          		common, 
                                          		null,					
                                          		function () {
                                          			logInfo('createState: ' + objectdevicePath);
                                          			setTimeout(
                                          				function() {
                                          					logInfo("CreateON: " + objectdevicePath);
                                          					on({id: "javascript." + instance + "." + objectdevicePath, change: "any"}, 
                                          					function (obj){
                                          
                                          						var   objArr  = obj.id.match(/(^.+)\.(.+)\.(.+)\.(.+)$/, ""); //Aufteilung in devicePath + deviceDpName + CMD
                                          						var deviceDpName  = objArr[2]; 
                                          						var cmd     = objArr[4]; 
                                          						logDebug("Device: " + deviceDpName+", Kommando: " + cmd);
                                          						parameter = obj.state.val;
                                          
                                          						var reloadCallback = function() {setTimeout(function() {updateDevice(deviceDpName);}, 3000);};
                                          
                                          						switch (cmd) {
                                          							// Buttons, werden immer wieder auf false gesetzt								
                                          							case "updateDevice": 
                                          								unsetButtonFirst(obj, function (obj) {updateDevice(deviceDpName);});
                                          								break;								
                                          							case "pause":
                                          								unsetButtonFirst(obj, function (obj) {setPause(deviceDpName, reloadCallback);});
                                          								break;
                                          							case "play":
                                          								unsetButtonFirst(obj, function (obj) {setPlay(deviceDpName, reloadCallback);});
                                          								break;
                                          							case "next":
                                          								unsetButtonFirst(obj, function (obj) {setNext(deviceDpName, reloadCallback);});
                                          								break;
                                          							case "previous":
                                          								unsetButtonFirst(obj, function (obj) {setPrevious(deviceDpName, reloadCallback);});
                                          								break;
                                          							case "forward":
                                          								unsetButtonFirst(obj, function (obj) {setForward(deviceDpName, reloadCallback);});
                                          								break;
                                          							case "rewind":
                                          								unsetButtonFirst(obj, function (obj) {setRewind(deviceDpName, reloadCallback);});
                                          								break;
                                          
                                          							//Switch
                                          							case "shuffle":
                                          								if(parameter === null){
                                          									logWarn("Alexa Shuffle: kein true/false angegeben. Auf true gesetzt.");
                                          									parameter = true;
                                          								}
                                          								setShuffle(deviceDpName, parameter);
                                          								break;
                                          
                                          							case "repeat":
                                          								if(parameter === null){
                                          									logWarn("Alexa Repeat: kein true/false angegeben. Auf true gesetzt.");
                                          									parameter = true;
                                          								}
                                          								setRepeat(deviceDpName, parameter);
                                          								break;
                                          
                                          							case "radio":
                                          								if(obj.state.val) {
                                          									// Letzte Radiostation einschlaten
                                          									var stationId = getState(deviceObjectPath + deviceDpName + ".control.tunein").val;
                                          									setTuneIn(deviceDpName,stationId, reloadCallback);
                                          								} else {
                                          									// Musik auf Pause.
                                          									setPause(deviceDpName, reloadCallback);
                                          								}
                                          								break;
                                          
                                          							case "volume":
                                          								if(!parameter ||parameter === null){
                                          									logWarn("Alexa Volume: keine Lautstärke angegeben. Parameter fehlt.");
                                          									break;
                                          								}
                                          								parameter = parseInt(parameter);
                                          								if(parameter < 0) {
                                          									parameter = 0;
                                          									logWarn("Alexa Volume: ungültige Lautsträke angegeben (<0). Auf 0 gesetzt.");
                                          								}
                                          								if(parameter > 100) {
                                          									parameter = 100;
                                          									logWarn("Alexa Volume: ungültige Lautsträke angegeben (>100). Auf 100 gesetzt.");
                                          								}
                                          								setVolume(deviceDpName, parameter);
                                          								break;
                                          
                                          							case "playlistId":
                                          								setPlaylistId(deviceDpName, parameter, reloadCallback);
                                          								break;
                                          
                                          							case "tunein":
                                          								setTuneIn(deviceDpName,parameter, reloadCallback);
                                          								break;
                                          
                                          							case "currentState":	
                                          								// den aktuellen "mediaProgress" berechnen, statt ihn immer neu runterzuladen
                                          								if ((obj.oldState.val == 'PAUSED') && (obj.state.val == 'PLAYING')) {
                                          									// Wechsel von Pause zu Playing
                                          									updateMediaProgress(deviceDpName);
                                          								} else if (obj.state.val == 'PLAYING') {
                                          									// war vorher nicht Pause, nun aber Playing, dann überprüfen, ob sich "mediaProgress" 
                                          									// innerhalb einer gewissen Zeit verändert (dann wurde die Funktion bereits ausgeführt)
                                          									var playerPath = deviceObjectPath + deviceDpName + ".player";
                                          									setTimeout( function() {
                                          										var mediaProgress = getState(playerPath + ".mediaProgress").val;
                                          										setTimeout( function() {									
                                          											var mediaProgressNew = getState(playerPath + ".mediaProgress").val;
                                          											// Wurde mediaProgress in der Zeit trotz PLAYING nicht verändert, dann trotzdem ausführen
                                          											if (mediaProgressNew == mediaProgress){
                                          												setState(playerPath + ".mediaProgress", mediaProgressNew + 7);
                                          												updateMediaProgress(deviceDpName);
                                          											}									
                                          										}, 5000 );
                                          									}, 3000 );
                                          								}
                                          								break;
                                          
                                          							default:
                                          								logWarn("Kommando << "+cmd+" >> im Skript nicht behandelt");
                                          								break;
                                          						}
                                          					})								
                                          				}
                                          				,
                                          				3000
                                          			);
                                          		}
                                          	);
                                          }
                                          
                                          // -------------------------------------------------------------------------------------------------------
                                          // 	HTTPS-GET/POST-Funktionen
                                          // -------------------------------------------------------------------------------------------------------
                                          
                                          /**
                                           * Setzt die Options für den https Request
                                           *
                                           * @param string path
                                           * @param string method - Should be GET oder POST
                                           */
                                          function setOptions(path,method) {
                                              var options = {
                                                  "host": 'layla.amazon.de',
                                                  "path": path,
                                                  "method": method,
                                                  "timeout":10000,
                                                  "headers": {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'csrf' : csrf,
                                                      'Cookie' : cookie
                                                  }
                                              };
                                              return options;
                                          }
                                          
                                          /**
                                           * Erzeugt eine GET Anfrage
                                           * @param string path
                                           * @param function callback
                                           */
                                          function httpsReqGet(path,callback) {
                                              logDebug("Abfrage " + path + " an Alexa gesendet");
                                              var options = setOptions(path,"GET");
                                              var req = https.get(options, function getDevices(res) {
                                                  logDebug('STATUS: ' + res.statusCode) + ": " + statusCode(res.statusCode); // Statuscode
                                                  logDebug('HEADERS: ' + JSON.stringify(res.headers)); // Header (Rückmeldung vom Webserver)
                                                  // Buffer the body entirely for processing as a whole.
                                                  var bodyChunks  = [];
                                                  var chunkLine   = 0;
                                          
                                                  res.on('data', function(chunk) {
                                                      chunkLine = chunkLine + 1;
                                                      // Hier können die einzelnen Zeilen verarbeitet werden...
                                                      logDebug("Zeilennummer: " + chunkLine+ " ,Inhalt: " +  chunk);
                                                      bodyChunks.push(chunk);
                                          
                                                  }).on('end', function() {
                                                      logDebug("ARRAY mit den einzelnen Zeilen: " + bodyChunks);
                                                      logDebug("ARRAY Länge: " + bodyChunks.length);
                                                      var body = Buffer.concat(bodyChunks);
                                                      // ...und/oder das Gesamtergebnis (body).
                                                      if(!body) log("keine Daten erhalten","warn");
                                                      logDebug('BODY: ' + body);
                                          
                                                      if(callback !== undefined && typeof callback === 'function') return callback(body);
                                                  });
                                          
                                              });
                                          
                                              req.on('error', function(e) { // Fehler abfangen
                                                  log('ERROR: ' + e.message,"warn");
                                                  log("keinen gültigen Callback gefunden","warn");
                                                  ok = false;
                                              });
                                              req.end();
                                          }
                                          
                                          /**
                                           * Setzt das Device auf die Lautstärke
                                           *
                                           * @param string deviceDpName
                                           * @param integer volumeLevel
                                           * @param function callback
                                           */
                                          function setVolume(deviceDpName, volumeLevel, callback) {httpsPostCmd(deviceDpName, '{"type":"VolumeLevelCommand","volumeLevel":' + volumeLevel + '}' , callback);}
                                          
                                          /**
                                           * Setzt das Device auf PLAY
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function setPlay(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"PlayCommand"}', callback);}
                                          
                                          /**
                                           * Setzt das Device auf PAUSE
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function setPause(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"PauseCommand"}', callback);}
                                          
                                          /**
                                           * Setzt das Device auf NEXT
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function setNext(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"NextCommand"}', callback);}
                                          
                                          /**
                                           * Setzt das Device auf PREVIOUS
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function setPrevious(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"PreviousCommand"}', callback);}
                                          
                                          /**
                                           * Setzt das Device auf FORWARD
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function setForward(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"ForwardCommand"}', callback);}
                                          
                                          /**
                                           * Setzt das Device auf REWIND
                                           *
                                           * @param string deviceDpName
                                           * @param function callback
                                           */
                                          function setRewind(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"RewindCommand"}', callback);}
                                          
                                          /**
                                           * Setzt für das Device SHUFFLE auf den gewünschten zustand
                                           *
                                           * @param string deviceDpName
                                           * @param boolean state
                                           * @param function callback
                                           */
                                          function setShuffle(deviceDpName, state, callback) {httpsPostCmd(deviceDpName, '{"type":"ShuffleCommand","shuffle":' + state + '}', callback);}
                                          
                                          /**
                                           * Setzt für das Device REPEAT auf den gewünschten zustand
                                           *
                                           * @param string deviceDpName
                                           * @param boolean state
                                           * @param function callback
                                           */
                                          function setRepeat(deviceDpName, state, callback) {httpsPostCmd(deviceDpName, '{"type":"RepeatCommand","repeat":' + state + '}', callback);}
                                          
                                          /**
                                           * Schickt ein Kommando an Alexa
                                           *
                                           * @param string deviceDpName
                                           * @param string postData
                                           * @param function callback
                                           */
                                          function httpsPostCmd(deviceDpName, postData, callback) {
                                          
                                          	logInfo("[httpsPostCmd] Device: " + deviceDpName + " - Kommando: " + postData);		
                                          
                                          	var path	= '/api/np/command?' 
                                          		+ 'deviceSerialNumber=' + devices[deviceDpName].serialNumber 
                                          		+ '&deviceType=' + devices[deviceDpName].deviceType ;
                                          
                                          	httpsPost(deviceDpName, path, postData, callback);
                                          }
                                          
                                          /**
                                           * Startet auf dem Device den Radiosender
                                           *
                                           * @param string deviceDpName
                                           * @param string stationId
                                           * @param function callback
                                           */
                                          function setTuneIn(deviceDpName,stationId, callback) {
                                          
                                          	logInfo("[setTuneIn] Device: " + deviceDpName + " - TuneIn-StationId: " + stationId);
                                          
                                          	var path	= '/api/tunein/queue-and-play?' 
                                          		+ 'deviceSerialNumber=' + devices[deviceDpName].serialNumber 
                                          		+ '&deviceType=' + devices[deviceDpName].deviceType 
                                          		+ '&guideId=' + stationId 
                                          		+ '&contentType=station&callSign=&mediaOwnerCustomerId=' + mediaOwnerCustomerId;
                                          
                                          	httpsPost(deviceDpName, path, '', callback);
                                          }
                                          
                                          /**
                                           * Startet auf dem Device die Playlist
                                           *
                                           * @param string deviceDpName
                                           * @param string playlistId
                                           * @param function callback
                                           */
                                          function setPlaylistId(deviceDpName, playlistId, callback) {
                                          
                                          	logInfo("[setPlaylistId] Device: " + deviceDpName + " - PlaylistId: " + playlistId);
                                          
                                          	var path	= '/api/cloudplayer/queue-and-play?' 
                                          		+ 'deviceSerialNumber=' + devices[deviceDpName].serialNumber 
                                          		+ '&deviceType=' + devices[deviceDpName].deviceType 
                                          		+ '&shuffle=false'
                                          		+ '&contentType=station&callSign=&mediaOwnerCustomerId=' + mediaOwnerCustomerId;
                                          
                                          	httpsPost(deviceDpName, path, '{"playlistId":"' + playlistId + '"}', callback);
                                          }
                                          
                                          /**
                                           * Erzeugt eine POST Anfrage und setzt den Status-Code
                                           * der Anfrage in das 'control.LastStatus' Feld
                                           *
                                           * @param string deviceDpName
                                           * @param string path
                                           * @param string postData
                                           * @param function callback
                                           */
                                          function httpsPost(deviceDpName, path, postData, callback) {
                                          
                                          	logDebug("[httpsPost] Device: " + deviceDpName + " Path: " + path + " postData: " + postData);
                                          
                                              var options = setOptions(path,"POST");
                                          
                                          	// request object
                                          	var req = https.request(options, function (res) {
                                          		var result = '';
                                          		res.on('data', function (chunk) {
                                          			result += chunk;
                                          		});
                                          		res.on('end', function () {
                                          			logDebug(result);
                                          
                                          			setState(deviceObjectPath + deviceDpName +".control.LastStatus",res.statusCode.toString()+" " + statusCode(res.statusCode));
                                          			if(res.statusCode != 200) {
                                          				logWarn("Negative Rückmeldung von Alexa: " + res.statusCode + ": " + statusCode(res.statusCode));
                                          				logWarn("Gesendetes Kommando: " + postData);
                                          			} else {
                                          				logDebug('STATUS: ' + res.statusCode + ": " + statusCode(res.statusCode)); // Statuscode
                                          			}
                                          			if(res.statusCode != 200){
                                          				logWarn('HEADERS: ' + JSON.stringify(res.headers)); // Header (Rückmeldung vom Webserver)
                                          			}
                                          
                                                      if(callback !== undefined && typeof callback === 'function') callback(result);
                                          		});
                                          
                                          		res.on('error', function (err) {
                                          			logWarn('ERROR: ' + err.message);
                                          		})
                                          	});
                                          
                                          	// req error
                                          	req.on('error', function (err) {
                                          		logWarn('ERROR: ' + err.message);
                                          	});
                                          
                                          	//send request witht the postData form
                                          	req.write(postData);
                                          	req.end();
                                          }
                                          
                                          // -------------------------------------------------------------------------------------------------------
                                          // 	Hilfs-Funktionen
                                          // -------------------------------------------------------------------------------------------------------
                                          
                                          /**
                                           * Setzt das gewünschte Loglevel
                                           *
                                           * @param string level
                                           */
                                          function setLoglevel(level) {
                                          	switch(level.toLowerCase()) {
                                          		case 'debug':
                                          			logLevelInt = 0;
                                          			break;
                                          		case 'info':
                                          			logLevelInt = 1;
                                          			break;
                                          		case 'warn':
                                          			logLevelInt = 2;
                                          			break;
                                          		case 'error':
                                          			logLevelInt = 3;
                                          			break;
                                          		case 'none':
                                          			logLevelInt = 4;
                                          			break;			
                                          		default:
                                          			logLevelInt = 2;
                                          			break;
                                          	}
                                          }
                                          
                                          /**
                                           * Logt eine DEBUG Message
                                           * (wird als info geloggt, da Debug nicht angezeigt wird)
                                           *
                                           * @param string msg
                                           */
                                          function logDebug(msg) {	
                                          	if (logLevelInt <= 0) {
                                          		log(msg, "info");
                                          	}
                                          }
                                          
                                          /**
                                           * Logt eine INFO Message
                                           *
                                           * @param string msg
                                           */
                                          function logInfo(msg) {
                                          	if (logLevelInt <= 1) {
                                          		log(msg, "info");
                                          	}
                                          }
                                          
                                          /**
                                           * Logt eine WARN Message
                                           *
                                           * @param string msg
                                           */
                                          function logWarn(msg) {
                                          	if (logLevelInt <= 2) {
                                          		log(msg, "warn");
                                          	}
                                          }
                                          
                                          /**
                                           * Logt eine ERROR Message
                                           *
                                           * @param string msg
                                           */
                                          function logError(msg) {
                                          	if (logLevelInt <= 3) {
                                          		log(msg, "error");
                                          	}
                                          }
                                          
                                          /**
                                           * Durchsucht ein Array nach needle und 
                                           * liefert bei Erfolg TRUE
                                           *
                                           * @param string needle
                                           * @param array haystack
                                           * @return boolean
                                           */
                                          function inArray(needle, haystack) {
                                              var length = haystack.length;
                                              for(var i = 0; i < length; i++) {
                                                  if(haystack[i] == needle) return true;
                                              }
                                              return false;
                                          }
                                          
                                          /**
                                           * Gibt zurück, ob die capabilities ein Steuern zulassen
                                           *
                                           * @param array capabilities
                                           * @return boolean
                                           */
                                          function deviceIsControllable(capabilities) {
                                          	return (inArray('AUDIO_PLAYER', capabilities)
                                          		|| inArray('AMAZON_MUSIC', capabilities)
                                          		|| inArray('TUNE_IN', capabilities));
                                          }
                                          
                                          /**
                                           * Gibt zurück, ob die capabilities eine Audiowiedergabe zulassen
                                           *
                                           * @param array capabilities
                                           * @return boolean
                                           */
                                          function deviceHasMusicPlayer(capabilities) {
                                          	return (inArray('AUDIO_PLAYER', capabilities)
                                          		|| inArray('AMAZON_MUSIC', capabilities));
                                          }
                                          
                                          /**
                                           * Gibt zurück, ob die capabilities TuneIn und somit Radio zulassen
                                           *
                                           * @param array capabilities
                                           * @return boolean
                                           */
                                          function deviceHasTuneIn(capabilities) {
                                          	return (inArray('TUNE_IN', capabilities));
                                          }
                                          
                                          /**
                                           * Button wieder auf false zurücksetzen, wenn er true war, danach callback
                                           *
                                           * @param object obj
                                           * @param function callback
                                           */
                                          function unsetButtonFirst(obj, callback) {
                                          	if(getState(obj.id).val) {
                                          		setState(obj.id,false);
                                          		if(callback !== undefined && typeof callback === 'function') callback(obj);
                                          	}
                                          }
                                          
                                          /**
                                           * Liefert str als String zurück, '' anstelle von null, false, ...
                                           *
                                           * @param mixed str
                                           * @return string
                                           */
                                          function getStringOrEmpty(str){
                                          	return (String(str) !== 'undefined') ? String(str) : '';
                                          }
                                          
                                          /**
                                           * Liefert das Device anhand der seriennummer
                                           *
                                           * @param string serialNumber
                                           * @param object
                                           */
                                          function getDeviceNameBySerialNumber(serialNumber) {
                                          
                                          	for (device in devices) {
                                          		if (devices[device].serialNumber == serialNumber) {
                                          			return device;
                                          		}
                                          	}
                                          
                                             return null;
                                          }
                                          
                                          /**
                                           * Liefert das erste Device das einen MusicPlayer hat, 
                                           * oder null, wenn es keines gibt
                                           *
                                           * @return object|null
                                           */
                                          function getEchoWithMusicPlayerFromDevices() {
                                          	for (device in devices) {
                                          		if (deviceHasMusicPlayer(devices[device].capabilities)) {
                                          			return devices[device];
                                          		}
                                          	}
                                          	return null;
                                          }
                                          
                                          /**
                                           * Liefert einen bereinigten Namen um daraus einen State-Pfad zu erzeugen
                                           *
                                           * @param string name
                                           * @return string
                                           */
                                          function clearName(name){
                                              name = umlaut(name);
                                              name = name.replace(/\W/g,"_");
                                              return name;
                                          }
                                          
                                          /**
                                           * Ersetzt Umlaufe/Sonderzeichen
                                           *
                                           * @param string str
                                           * @return string
                                           */
                                          function umlaut(str) {
                                           return str
                                            .replace(/Â|À|Å|Ã/g, "A")
                                            .replace(/â|à|å|ã/g, "a")
                                            .replace(/Ä/g, "AE")
                                            .replace(/ä/g, "ae")
                                            .replace(/Ç/g, "C")
                                            .replace(/ç/g, "c")
                                            .replace(/É|Ê|È|Ë/g, "E")
                                            .replace(/é|ê|è|ë/g, "e")
                                            .replace(/Ó|Ô|Ò|Õ|Ø/g, "O")
                                            .replace(/ó|ô|ò|õ/g, "o")
                                            .replace(/Ö/g, "OE")
                                            .replace(/ö/g, "oe")
                                            .replace(/Š/g, "S")
                                            .replace(/š/g, "s")
                                            .replace(/ß/g, "ss")
                                            .replace(/Ú|Û|Ù/g, "U")
                                            .replace(/ú|û|ù/g, "u")
                                            .replace(/Ü/g, "UE")
                                            .replace(/ü/g, "ue")
                                            .replace(/Ý|Ÿ/g, "Y")
                                            .replace(/ý|ÿ/g, "y")
                                            .replace(/Ž/g, "Z")
                                            .replace(/ž/, "z"); 
                                          }
                                          
                                          /**
                                           * Liefert einen String zum http-Status
                                           *
                                           * @param integer status
                                           * @return string
                                           */
                                          function statusCode(status) {
                                              if(status === 0)  return "** Daten unvollständig **   (*csrf* fehlt/falsch?   *Cookie* falsch?)";
                                              if(status == 200) return "** OK **";
                                              if(status == 302) return "** Found (Moved Temporarily) **   (Cookie abgelaufen?)";
                                              if(status == 401) return "** Unauthorized **   (Cookie nicht richtig gesetzt?)";
                                              if(status == 403) return "** Forbidden **   (Kombination Cookie, deviceType, Seriennummer richtig?)";
                                              if(status == 404) return "** Not Found **   (Kommando im Kontext des Geräts sinnvoll?)";
                                              if(status == 500) return "** Internal Server Error**   (ggf. Kommando im falschen Kontext verwendet?)";
                                              return "Fehler";
                                          }
                                          
                                          /**
                                           * Liefert einen String zum deviceType
                                           *
                                           * @param integer deviceType
                                           * @return string
                                           */
                                          function deviceTypeStr(deviceType){
                                              if(!knownDeviceType[deviceType] || knownDeviceType[deviceType] === undefined) return "Gerät unbekannt";
                                              return knownDeviceType[deviceType];
                                          }
                                          
                                          /**
                                           * Konvertiert eine Sekundenzahl in einen String im Format (HH:)MM:SS
                                           *
                                           * @param integer sek
                                           * @return string
                                           */
                                          function sekToHMS(sek) {
                                          
                                          	 if (sek  === 0) {
                                                  return '0';
                                              }
                                          
                                              var sec_num = parseInt(sek, 10);
                                              var hours   = Math.floor(sec_num / 3600);
                                              var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
                                              var seconds = sec_num - (hours * 3600) - (minutes * 60);
                                          
                                              if (minutes < 10) {minutes = "0"+minutes;}
                                              if (seconds < 10) {seconds = "0"+seconds;}
                                          
                                              if (hours  === 0) {
                                                  return minutes+':'+seconds;
                                              }
                                          
                                              if (hours   < 10) {hours   = "0"+hours;}
                                              return hours+':'+minutes+':'+seconds;
                                          }`
                                          
                                          und dieses:
                                          `~~[code]~~//------------------------------------------------------------------------------
                                          // AlexaLogOn
                                          //------------------------------------------------------------------------------
                                          // Dieses Script ermöglicht es das Cookie für den Amazon-Account mit der Angabe 
                                          // von User und Passwort (und falls konfiguriert, 2FA code) erzeugen zu lassen.
                                          // Das Cookie wird dann in einen Datenpunkt geschrieben, wo es für andere Skripe
                                          // zugriffbar ist.
                                          //
                                          // Skript arbeitet unabhängig vom Cloud Adapter.
                                          //
                                          // Version: v0.7
                                          // Feedback: http://forum.iobroker.net/viewtopic.php?f=37&t=9237
                                          
                                          //------------------------------------------------------------------------------
                                          // Changelog:
                                          // v0.7: Sonderzeichenunterstützung für user/pass
                                          // v0.6: Automatische Anpassung der Instanznummer
                                          // v0.5: Datenpunkt für Cookie Status
                                          // v0.4: Cron schedule
                                          // v0.3: 2 Factor Authentication
                                          // v0.2: CSRF wird berechnet
                                          // v0.1: initialer Release
                                          
                                          //------------------------------------------------------------------------------
                                          // Einrichtung:
                                          // 1\.  User und Passwort (und wenn konfiguriert, 2FA Code) eintragen. 
                                          //
                                          // WARNUNG:  Die Login-Daten sollten nicht in diesem Script gespeichert werden,
                                          //           sondern nur für die einmalige Ausführung eingetragen werden. Sobald 
                                          //           das Cookie in dem Datenpunkt erzeugt ist, sollten die Eingaben in
                                          //           den beiden folgenden Felder wieder gelöscht werden.
                                          //           Erst bei der nächsten Ausführung (z.B. wenn das Cookie 
                                          //           abgelaufen ist) sollten sie wieder neu eintragen werden.
                                          
                                          var username = "xxxx@xxx.at";
                                          var password = "xxxx";
                                          var twofacode = "";
                                          
                                          // 2\.  Datenpunkte konfigurieren (optional)
                                          //
                                          // Wenn gewünscht, Pfad und Name nach eigenen Vorstellungen anpassen
                                          // ("javascript.#instanznummer#." nicht angeben, wird automatisch berechnet).
                                          var idAlexaLogonCookie = 'productive.alexalogon.cookie';
                                          var forecreation = false;
                                          
                                          // Wenn gewünscht, Name und desc für den Datenpunkt anpassen.
                                          createState(idAlexaLogonCookie, instance, forecreation, {
                                               name: 'Alexa LogOn Cookie',
                                               desc: 'Alexa LogOn Cookie',
                                               type: 'string',
                                               unit: '',
                                               role: 'value'
                                          });
                                          
                                          // Wenn gewünscht, Pfad und Name nach eigenen Vorstellungen anpassen.
                                          // ("javascript.#instanznummer#." nicht angeben, wird automatisch berechnet).
                                          var idAlexaLogonCSRF = 'productive.alexalogon.csrf';
                                          
                                          // Wenn gewünscht, Name und desc für den Datenpunkt anpassen.
                                          createState(idAlexaLogonCSRF, instance, forecreation, {
                                               name: 'Alexa LogOn CSRF',
                                               desc: 'Alexa LogOn CSRF',
                                               type: 'string',
                                               unit: '',
                                               role: 'value'
                                          });
                                          
                                          // Wenn gewünscht, Pfad und Name nach eigenen Vorstellungen anpassen.
                                          // ("javascript.#instanznummer#." nicht angeben, wird automatisch berechnet).
                                          var idAlexaLogonCookieValid = 'productive.alexalogon.cookievalid';
                                          
                                          // Wenn gewünscht, Name und desc für den Datenpunkt anpassen.
                                          createState(idAlexaLogonCookieValid, instance, forecreation, {
                                               name: 'Alexa LogOn Cookie Valid',
                                               desc: 'Alexa LogOn Cookie Valid',
                                               type: 'state',
                                               unit: '',
                                               role: 'switch.active'
                                          });
                                          
                                          // Ende der Einrichtung. 
                                          // Nachfolgend der eigentliche Source Code des Scripts.
                                          //------------------------------------------------------------------------------
                                          
                                          //------------------------------------------------------------------------------
                                          // Global Variables
                                          
                                          var request = require('request');
                                          
                                          var logOn = true; 
                                          
                                          var locationURL;
                                          var formParameter;
                                          var postData = "";
                                          var sessionID;
                                          var cookieStr = "";
                                          
                                          var cronStr         = "0 0 * * *";
                                          
                                          //------------------------------------------------------------------------------
                                          // Start der Script-Logik
                                          
                                          // Construct fullnames of data points
                                          idAlexaLogonCookie = 'javascript.' + instance + '.' + idAlexaLogonCookie;
                                          idAlexaLogonCSRF = 'javascript.' + instance + '.' + idAlexaLogonCSRF;
                                          idAlexaLogonCookieValid = 'javascript.' + instance + '.' + idAlexaLogonCookieValid;
                                          
                                          // Cron Schedule
                                          schedule(cronStr, main);
                                          
                                          // Sofortstart
                                          setTimeout(main, 1000);
                                          
                                          function main() {
                                          
                                              if(logOn) log("Start LogOn Process");
                                          
                                              var storedCookie = "" + getState(idAlexaLogonCookie).val;
                                          
                                              if (storedCookie !== null && storedCookie !== "") {
                                                  storedCookie = storedCookie.replace(/\\/g, "");
                                                  checkIfCookieIsStillValid(storedCookie);
                                              } else {
                                                  logIntoAmazonAccount();
                                              }
                                          
                                          }
                                          
                                          function checkIfCookieIsStillValid(cookie) {
                                          
                                              var options = {
                                                  url : "https://layla.amazon.de/api/bootstrap?version=0",
                                                  method : "GET",
                                                  followAllRedirects : true,
                                                  headers : {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'Accept-Language': 'de,en',
                                                      'DNT' : '1',
                                                      'Connection': 'keep-alive',
                                                      'Upgrade-Insecure-Requests' : '1',
                                                      'Referer' : 'https://layla.amazon.de/spa/index.html/',
                                                      'Cookie' : cookie
                                                  }
                                              };
                                          
                                              var req = request.get(options, function(err, res, body){
                                                  var bodyTrim = res.body.trim();
                                                  if(logOn) log("First Char: " + bodyTrim.startsWith("{"));
                                                  if(logOn) log("Auth String Exists: " + bodyTrim.indexOf("authenticated"));
                                                  if(bodyTrim.startsWith("{") === false && bodyTrim.indexOf("authenticated") == -1) {
                                                      setState(idAlexaLogonCookie, "");
                                                      setState(idAlexaLogonCSRF, "");
                                                      setState(idAlexaLogonCookieValid, "false");
                                                      logIntoAmazonAccount();
                                                      return;
                                                  }
                                          
                                                  var bodyObject = JSON.parse(res.body);
                                                  if(bodyObject.authentication.authenticated === true) {
                                                      log("Stored Cookie is still valid. No LogOn Required.");
                                                  }
                                          
                                              });
                                          
                                          }
                                          
                                          function logIntoAmazonAccount() {
                                          
                                              var options = {
                                                  url : "https://layla.amazon.de/",
                                                  method : "GET",
                                                  followRedirect : false,
                                                  headers : {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'Accept-Language': 'de,en',
                                                      'DNT' : '1',
                                                      'Connection': 'keep-alive',
                                                      'Upgrade-Insecure-Requests' : '1'
                                                  }
                                              };
                                          
                                              if(username === "" || password === "") {
                                                  if(logOn) log("User or password variable empty.");
                                                  return;
                                              }
                                          
                                              locationURL = "";
                                              postData = "";
                                              sessionID = "";
                                              cookieStr = "";
                                          
                                              request.get(options, function(err, res, body){
                                                  if(logOn) log("Referer Location: " + JSON.stringify(res.headers.location));
                                                  locationURL = res.headers.location;
                                          
                                                  getRedirectCookieAndLogonParameter();
                                              });
                                          
                                          }
                                          
                                          function getRedirectCookieAndLogonParameter() {
                                          
                                              var options = {
                                                  url : "https://layla.amazon.de/",
                                                  method : "GET",
                                                  followAllRedirects : true,
                                                  headers : {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'Accept-Language': 'de,en',
                                                      'DNT' : '1',
                                                      'Connection': 'keep-alive',
                                                      'Upgrade-Insecure-Requests' : '1'
                                                  }
                                              };
                                          
                                              formParameter = [
                                                  "appActionToken",
                                                  "appAction",
                                                  "showRmrMe",
                                                  "openid.return_to",
                                                  "prevRID",
                                                  "openid.identity",
                                                  "openid.assoc_handle",
                                                  "openid.mode",
                                                  "failedSignInCount",
                                                  "openid.claimed_id",
                                                  "pageId",
                                                  "openid.ns",
                                                  "showPasswordChecked"
                                              ];
                                          
                                              request.get(options, function(err, res, body){
                                                  var setCookies = res.headers['set-cookie'];
                                                  if(logOn) log("Set-Cookies: " + JSON.stringify(setCookies));
                                                  if(logOn) log("Request: " + JSON.stringify(res.request));
                                          
                                                  for(var i = 0; i < setCookies.length; i++) {
                                                      var setCookie = JSON.stringify(setCookies[i]);
                                          
                                                      if(setCookie.indexOf("1970") == -1){
                                                          var setCookieArray = setCookie.match(/"(.*) Domain=|Expires=|Version=/);
                                                          cookieStr = cookieStr + setCookieArray[1] + " ";
                                                      }
                                                  }
                                                  cookieStr = cookieStr.replace(/\\/g, "");
                                                  if(logOn) log("Cookie Part 1: " + cookieStr);
                                          
                                                  for(i = 0; i < formParameter.length; i++) {
                                                      var regex = eval("/type=\"hidden\" name=\"" + formParameter[i] + "\" value=\"(.*)\"/");
                                                      var parameterValueArray = regex.exec(body);
                                                      var parameterValue = parameterValueArray[1];
                                                      parameterValueArray = parameterValue.match(/^(.*?)"/);
                                                      if (parameterValueArray !== null) {
                                                          parameterValue = parameterValueArray[1];
                                                      }
                                                      if(logOn) log("Parameter Value: " + parameterValue);
                                                      postData = postData + formParameter[i] + "=" + parameterValue + "&";
                                                  }
                                                  if(logOn) log("LogOn Parameter: " + postData);
                                          
                                                  postLogonParameters();
                                              });
                                          }
                                          
                                          function postLogonParameters() {
                                          
                                              var options = {
                                                  url : "https://www.amazon.de/ap/signin?" + postData,
                                                  method : "POST",
                                                  followAllRedirects : true,
                                                  headers : {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'Accept-Language': 'de,en',
                                                      'DNT' : '1',
                                                      'Connection': 'keep-alive',
                                                      'Upgrade-Insecure-Requests' : '1',
                                                      'Referer' : locationURL,
                                                      'Cookie' : cookieStr
                                                  }
                                              };
                                          
                                              request.post(options, function(err, res, body){
                                                  var setCookies = res.headers['set-cookie'];
                                                  if(logOn) log("Set-Cookies: " + JSON.stringify(setCookies));
                                          
                                                  var cookieStrTemp = "";
                                                  for(var i = 0; i < setCookies.length; i++) {
                                                      var setCookie = JSON.stringify(setCookies[i]);
                                          
                                                      if(setCookie.indexOf("1970") == -1){
                                                          var setCookieArray = setCookie.match(/"(.*) Domain=|Expires=|Version=/);
                                                          cookieStrTemp = cookieStrTemp + setCookieArray[1] + " ";
                                                          var cookieStrTempArray = cookieStrTemp.match(/ubid-acbde=(.*);/);
                                                          sessionID = cookieStrTempArray[1];
                                                      }
                                                  }
                                                  cookieStrTemp = cookieStrTemp.replace(/\\/g, "");
                                                  cookieStr = cookieStr + cookieStrTemp;
                                                  if(logOn) log("Cookie Part 2: " + cookieStr);
                                          
                                                  postdata = "";
                                                  for(i = 0; i < formParameter.length; i++) {
                                                      var regex = eval("/type=\"hidden\" name=\"" + formParameter[i] + "\" value=\"(.*)\"/");
                                                      var parameterValueArray = regex.exec(body);
                                                      var parameterValue = parameterValueArray[1];
                                                      parameterValueArray = parameterValue.match(/^(.*?)"/);
                                                      if (parameterValueArray !== null) {
                                                          parameterValue = parameterValueArray[1];
                                                      }
                                                      if(logOn) log("Parameter Value: " + parameterValue);
                                                      postData = postData + formParameter[i] + "=" + parameterValue + "&";
                                                  }
                                                  if(logOn) log("LogOn Parameter: " + postData);
                                          
                                                  postUserAndPassword();
                                              });
                                          
                                          }
                                          
                                          function postUserAndPassword() {
                                          
                                              var options = {
                                                  url : "https://www.amazon.de/ap/signin?" 
                                                      + postData 
                                                      + "email=" + encodeURIComponent(username)
                                                      + "&password=" + encodeURIComponent(password) + twofacode,
                                                  method : "POST",
                                                  followRedirect : false,
                                                  headers : {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'Accept-Language': 'de,en',
                                                      'DNT' : '1',
                                                      'Connection': 'keep-alive',
                                                      'Upgrade-Insecure-Requests' : '1',
                                                      'Referer' : 'https://www.amazon.de/ap/signin/' + sessionID,
                                                      'Cookie' : cookieStr
                                                  }
                                              };
                                          
                                              request.post(options, function(err, res, body){
                                                  var setCookies = res.headers['set-cookie'];
                                                  if(logOn) log("Set-Cookies: " + JSON.stringify(setCookies));
                                          
                                                  var cookieStrTemp = "";
                                                  for(var i = 0; i < setCookies.length; i++) {
                                                      var setCookie = JSON.stringify(setCookies[i]);
                                          
                                                      if(setCookie.indexOf("1970") == -1){
                                                          setCookie = setCookie.replace(/Version=1; /g, "");
                                                          var setCookieArray = setCookie.match(/"(.*) Domain=|Expires=|Version=/);
                                                          if(cookieStr.indexOf(setCookieArray[1]) == -1) {
                                                              cookieStrTemp = cookieStrTemp + setCookieArray[1] + " ";
                                                          }
                                                      }
                                                  }
                                                  cookieStrTemp = cookieStrTemp.replace(/\\/g, "");
                                                  cookieStr = cookieStr + cookieStrTemp;
                                                  if(logOn) log("Cookie Part 3: " + cookieStr);
                                          
                                                  signIntoAlexa();
                                              });
                                          
                                          }
                                          
                                          function signIntoAlexa() {
                                          
                                              var options = {
                                                  url : "https://layla.amazon.de/api/bootstrap?version=0",
                                                  method : "GET",
                                                  followAllRedirects : true,
                                                  headers : {
                                                      'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
                                                      'Content-Type': 'text/plain',
                                                      'Accept-Language': 'de,en',
                                                      'DNT' : '1',
                                                      'Connection': 'keep-alive',
                                                      'Upgrade-Insecure-Requests' : '1',
                                                      'Referer' : 'https://layla.amazon.de/spa/index.html/',
                                                      'Cookie' : cookieStr
                                                  }
                                              };
                                          
                                              request.get(options, function(err, res, body){
                                                  var setCookies = res.headers['set-cookie'];
                                                  if(logOn) log("Set-Cookies: " + JSON.stringify(setCookies));
                                          
                                                  var cookieStrTemp = "";
                                                  for(var i = 0; i < setCookies.length; i++) {
                                                      var setCookie = JSON.stringify(setCookies[i]);
                                          
                                                      if(setCookie.indexOf("1970") == -1){
                                                          setCookie = setCookie.replace(/Version=1; /g, "");
                                                          var setCookieArray = setCookie.match(/"(.*) Domain=|Expires=|Version=/);
                                                          if(cookieStr.indexOf(setCookieArray[1]) == -1) {
                                                              cookieStrTemp = cookieStrTemp + setCookieArray[1] + " ";
                                                          }
                                                      }
                                                  }
                                                  cookieStrTemp = cookieStrTemp.replace(/\\/g, "");
                                                  cookieStr = cookieStr + cookieStrTemp;
                                                  if(logOn) log("Cookie Complete: " + cookieStr);
                                          
                                                  if (cookieStr.indexOf("csrf") != -1) {
                                                      log("LogOn successfull!");
                                                  } else {
                                                      log("LogOn Failed.");
                                                      setState(idAlexaLogonCookie, "");
                                                      setState(idAlexaLogonCSRF, "");
                                                      setState(idAlexaLogonCookieValid, "false");
                                                      return;
                                                  }
                                          
                                                  setState(idAlexaLogonCookie, cookieStr);
                                          
                                                  var csrfArray = cookieStr.match(/csrf=(.*?); /);
                                                  setState(idAlexaLogonCSRF, csrfArray[1]);
                                          
                                                  setState(idAlexaLogonCookieValid, 'true');
                                              });
                                          
                                          }`[/i][/i][/i][/i][/i][/i][/i][/i][/code][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]
                                          
                                          1 Reply Last reply Reply Quote 0
                                          • T
                                            tempestas last edited by

                                            ja dann schalte doch mal beide aus, teste ob es dann geht.

                                            dann eins wieder einschalten, testen.

                                            edit: es liegt wenn dann wohl am AlexaLogOn Skript

                                            mehr kann ich dir zu den skripten nicht sagen, die nutze ich nicht

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

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            875
                                            Online

                                            31.7k
                                            Users

                                            79.7k
                                            Topics

                                            1.3m
                                            Posts

                                            10
                                            38
                                            5759
                                            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