Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. liv-in-sky

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Profile
    • Following 0
    • Followers 39
    • Topics 248
    • Posts 15718
    • Best 1815
    • Groups 4

    liv-in-sky

    @liv-in-sky

    2172
    Reputation
    2311
    Profile views
    15718
    Posts
    39
    Followers
    0
    Following
    Joined Last Online
    Location 85406

    liv-in-sky Follow
    Forum Testing Pro Starter Most Active

    Best posts made by liv-in-sky

    • Script fürTabelle der Batterie Zustände

      hier ein beispiel für die Anzeige der Sensoren-Batterie-Zustände über ein html-Widget (oder iQontrol) - angelehnt an die scripte für html tabellen: https://forum.iobroker.net/topic/28021/html-table-für-vis-oder-iqontrol-js-und-blockly

      1578859811737-batterien_final.png

      die MaterialDesign Widgets sind auch mit eingebunden https://forum.iobroker.net/post/389578

      export der widgets

      [{"tpl":"tplVis-materialdesign-Icon-List","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","wrapItems":true,"listItemDataMethod":"jsonStringObject","countListItems":"1","vibrateOnMobilDevices":"50","listLayout":"card","itemLayout":"horizontal","listType0":"text","showValueLabel0":"true","listType1":"text","showValueLabel1":"true","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"maxItemsperRow":"4","json_string_oid":"controll-own.0.TABELLEN.AkkuMaterialWidget","labelFontSize":"22","subLabelFontSize":"14","labelFontFamily":"RobotoCondensed-Regular","horizontalIconContainerWidth":"70","buttonHeight":"70","iconHeight":"35","iconItemMinWidth":"300"},"style":{"left":"117px","top":"67px","width":"60.89%","height":"87.71%","overflow-y":"auto"},"widgetSet":"materialdesign"}]
      

      [{"tpl":"tplVis-materialdesign-Table","data":{"oid":"controll-own.0.TABELLEN.AkkuMaterialWidgetTable","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","countCols":"4","tableLayout":"standard","showHeader":"true","headerTextSize":"headline6","showColumn0":"true","colType0":"text","textAlign0":"left","showColumn1":"true","colType1":"text","textAlign1":"center","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"showColumn2":"true","colType2":"text","textAlign2":"center","showColumn3":"true","colType3":"image","textAlign3":"center","dataJson":"","colTextSize0":"headline4","label1":"Wert","label0":"Name","label2":"Status","sortKey0":"","fontFamily0":"RobotoCondensed-Regular","padding_left0":"10","colTextColor0":"","colorBackground":"#ffffff","colorHeaderRowBackground":"#424242","colorHeaderRowText":"#b6b9b7","borderColor":"#000000","fontFamily1":"RobotoCondensed-Regular","colTextColor1":"#beb7b7","rowHeight":"19","label3":"Hersteller","imageSize3":"20","padding_right3":"-5","sortKey2":"","showColumn4":false,"colType4":"text","textAlign4":"center","sortKey1":"helpSort"},"style":{"left":"1110px","top":"61px","z-index":"0","width":"587px","height":"926px","overflow-y":"auto"},"widgetSet":"materialdesign"}]
      


      Image 11.png Image 1.png


      Image 2.png
      material design widgetImage 2.png Image 3.png

      die javascript adapter version sollte 4.3.x sein !!!

      anzulegen und in das script einzutragen sind folgende datenpunkte

      • ein datenpunkt für die vis-anzeige unter dpVIS - ganz oben - im script - anschliessend kann man die tabelle so einstellen, dass sie in eure vis paßt (übr ein standard-html-widget mit binding auf diesen selbst-angelegten-datenpunkt)- ein html datei kann auf wunsch geschrieben werden - damit kann auch in iQontrol ein popup "gefüttert" werden und als anzeige dienen. auch die werte für warnung oder alarm sind einzutragen
      • ein datenpunkt für die anzahl der devices mit alarm (im script beschrieben)
      • ein datenpunkt für eine liste mit den devices mit einem alarm (im script beschrieben)

      wie legt man einen datenpunkt an: https://forum.iobroker.net/post/400338

      Script zum download bzw. mit Chrome!!! kopieren


      https://github.com/liv-in-sky/battery-iobroker-vis-table

      • bisher integriert
      hersteller
      iogok.png iogo adapter
      tadok.jpg tado
      homeek.jpg homee
      netatmok.jpg netatmo
      zwavek.jpg zwave
      fritzk.png fritzDect theermostate
      xiaomki.png xiaomi, mihome
      homematick.jpg homematic, homematic-Ip
      huek.jpg hue, hue-ext
      zwavek.jpg zwave
      tradfrik.png tradfri
      fullyk.png fully browser adapter
      zigbeek.jpg zigbee
      deconzk.png deconz
      sonoffk.png sonoff zb bridge
      busware-cul.png cul adapter
      rademacher.png rademacher homepilot
      shellyk.jpg shelly
      boschk.png bosch
      hamk.png ham (homebridge)
      nuki-extended
      posted in JavaScript
      liv-in-sky
      liv-in-sky
    • Petition Photovoltaik

      für alle Pholtaik User ( @Homoran : falls es nicht gewünscht ist, sowas zu posten - bitte löschen)

      evtl wollt ihr das unterschreiben : https://weact.campact.de/petitions/finger-weg-von-der-photovoltaik

      es geht um:

      Zusammenfassung der Petition „Finger weg von der Photovoltaik!“

      Die Petition richtet sich gegen Pläne der Bundesnetzagentur, künftig auch private Betreiber von Solaranlagen mit Netzentgelten für eingespeisten Strom zu belasten. Hintergrund ist ein Diskussionspapier („AgNes“) vom 12. Mai 2025, das sechs verschiedene Modelle für solche Gebühren vorschlägt. Ziel ist es, den Ausbau des Stromnetzes bis 2045 mitzufinanzieren. Kritisiert wird, dass die betroffenen Bürger*innen kaum in die Entscheidungsfindung einbezogen werden, während Verbände und Konzerne Stellung nehmen können.

      Hauptkritikpunkte der Petition:

      Die geplanten Netzentgelte könnten private Solaranlagen wirtschaftlich unattraktiv machen, besonders für kleine Anlagen und Haushalte mit geringem Verbrauch.

      Netzdienliches Verhalten wie Stromspeicherung und flexible Einspeisung wird nicht gefördert, sondern teilweise sogar bestraft.

      Es drohen erhebliche Einnahmeverluste (bis zu 33 % bei Volleinspeisern, über 13 % bei Anlagen mit Speicher), sodass Anlagen abgeschaltet oder für klimaschädliche Zwecke genutzt werden könnten.

      Die Energiewende wird damit ausgebremst, obwohl jede Kilowattstunde erneuerbarer Strom gebraucht wird.

      Forderungen der Petition:

      Netzdienliches Verhalten (z.B. Speicher, Lastglättung, Flexibilität) aktiv fördern.

      Die Modelle Arbeitspreis, Leistungspreis und Grundpreis ausschließen.

      Ein faires, planbares und netzdienliches Modell einführen.

      Den Ausbau von Smart Metern vereinfachen und günstiger machen.

      Kleine Anlagen durch eine Bagatellgrenze schützen.

      Fazit:
      Die Petition fordert, dass die Energiewende nicht durch neue Kosten für private Solaranlagenbetreiber gebremst wird und ruft zu einer fairen, bürgerfreundlichen Lösung auf, die den Ausbau erneuerbarer Energien fördert statt behindert.

      video dazu: https://www.youtube.com/watch?v=84kwjZYU6pQ

      posted in Off Topic
      liv-in-sky
      liv-in-sky
    • HTML-Table für VIS oder Iqontrol (js und blockly)

      mit diesem script kann man HTML Tabellen erzeugen - diese können dann in der VIS oder Iqontrol eingebunden werden - via iframe
      es gibt jeweils ein script für 2,3,4 oder 5 spalten (anzuzeigende werte) - iqontrol braucht ein extra file, um eine tabelle anzeigen zu können - für die vis reicht ein datenpunkt mit einer html-tabelle darin - beides kann das script erzeugen

      • kann auch in blockly übernommen werden - siehe beschreibung unten

      • die eigentliche aufgabe ist es, eine eigene schleife in das script einzutragen, welche die gewünschten werte liefert

      • das beispiel im script erzeugt eine datei htmlexample.html und legt es im iobroker-file-system unter /opt/iobroker/iobroker-data/files/vis.0 ab - als beispiel werden die adapter-zustände angezeigt - somit ist jedes der scripte schon lauffähig

      • es ist ein schedule am ende des scripts - alle 20 sekunden eingestellt - bitte ändern und an eigene bedürfnisse angleichen

      • das file ist im netzwerk erreichbar unter: http://192.168.178.59:8082/vis.0/htmlexample.html - der port und die ip adresse muss natürlich auf das eigene netzwerk angeglichen werden - port ist in dem instanz-setting der web-instanz zu entnehmen

      • für iQontrol kann man ein popup verwenden (eingetragen im feld :HTML - der port und die ip adresse angleichen)
        <iframe width="100% "height="100% "frameborder="0" src="/vis.0/htmlexample.html"></iframe>

      • es kann auch ein datenpunkt für die anzeige in der vis erzeugt werden - in einem eigenen datenpunkt wird dann die tabelle geschrieben - mit binding in das basic-html-widget eintragen

      • die tabelle kann verschiedenartig formatiert werden (auch im 1-, 2-, 3- oder 4-tabellen-nebeneinander-format (damit es kürzer, aber dafür breiter wird) - damit jede tabelle unterscheidbar ist, können die spaltenüberschriften und die felderschrift für jede 2.te tabelle geändert werden

      bisher realisiert:

      forum link MaterialDesign Widget
      tabelle für batterie anzeige für sensoren (z.b. xiaomi): https://forum.iobroker.net/topic/28789/script-fürtabelle-der-batterie-zustände ja
      tabelle für web-speedy adapter: https://forum.iobroker.net/topic/30226/html-tabelle-für-webspeedy-adapter-vis-iqontrol
      tabelle sonoff geräte: https://forum.iobroker.net/topic/28953/sonoff-geräte-als-html-tabelle-vis-iqontrol
      fussball tabelle https://forum.iobroker.net/topic/29526/fussballmeisterschat-html-tabelle
      energieverbrauch anzeige https://forum.iobroker.net/topic/29189/energieanzeige-kwh-über-html-tabelle-vis ja
      IP geräte im netzwerk https://forum.iobroker.net/topic/30057/ip-devices-im-netzwerk-html-tabelle-vis-iqontrol ja
      alexa listen als tabelle https://forum.iobroker.net/topic/28254/script-alexa-listen-pflegen-und-anzeigen
      liste backitup adapter https://forum.iobroker.net/topic/30705/html-tabelle-für-backitup
      alexa smart device https://forum.iobroker.net/topic/30833/html-table-für-alexa-smart-devices
      ping adapter https://forum.iobroker.net/post/396547
      time-switch adapter https://forum.iobroker.net/topic/33088/html-tabelle-für-time-switch-adapter
      unifi clients vom neuen adapter https://forum.iobroker.net/topic/34491/htmltabelle-unificlients-newadapter
      trashschedule anfallende tonnen https://forum.iobroker.net/topic/35399/html-tabelle-für-trashschedule-adapter ja
      Lebensmittel Warnungs Script https://forum.iobroker.net/topic/35474/html-tabelle-lebensmittel-warnung
      Calender Adapter https://forum.iobroker.net/topic/35791/html-tabelle-calendar-adapter
      Linux-Control https://forum.iobroker.net/topic/35880/html-tabelle-linux-control-adapter
      email postfach https://forum.iobroker.net/topic/36558/html-tabelle-für-email-postfach
      Tasmota Timer Tabelle mit Setzen eines Timers https://forum.iobroker.net/topic/36613/html-tabelle-für-tasmota-timer-setzen
      TankerKölnig adapter https://forum.iobroker.net/topic/37609/html-tabelle-für-tankerkönig
      iCal Adapter https://forum.iobroker.net/topic/40691/html-tabelle-für-ical-adapter-mehrere-instanzen

      Image 9.png Image 8.png


      Image 10.png Image 4.pngImage 9.png
      3 verschiedene werte und 4 tabellen nebeneinander!Image 12.png
      4 verschiedene werte und 4 tabellen nebeneinander! Image 13.png
      5 verschiedene werte und 4 tabellen nebeneinanderImage 14.png
      3 verschiedene werte und 3 tabellen nebeneinander!Image 15.png
      und für alle einhorn-fans - alle farben des regenbogenImage 17.png

      was kann man alles einstellen:

      • tabelle zentrieren
      • schriftart, schriftgröße
      • größe der zellen beispiele: https://forum.iobroker.net/post/348791
      • tabelle aufteilen - nebeneinander - 1,2,3 oder4
      • farben: hintergrund allgemein, hintergrund tabelle (verlauf), felderfarbe, ...
      • gitterlinien - alle, nur spalten, nur zeilen, keine
      • eine gesamtüberschrift
      • tabellenwert-überschrift
      • schedule - wie oft wird geprüft
      • ob man eine datei möchte - z.b. für iqontrol
      • überschriften der spalten in der tabelle ein- und abschalten
      • für jede spalte eigene zell-ausrichtung (center,left,right)


      Image 5.png Image 4.png Image 7.png Image 6.png

      im script wird erklärt, was einzustellen ist - es muss der haupteil - je nach gewünschten daten - angelichen werden - evtl muss auch ein schedule erzeugt werden- damit die daten dynamisch geschrieben werden

      Script für verschiedene spaltenanzahl (anzahl werte, die anzuzeigen sind)

         //@liv-in-sky 2020  4.2.-18:42
      
      
      //HIER WIRD PFAD UND FILENAME DEFINIERT
      const path = "/htmlexamplesetting.html";                   //FIlenamen definieren
      const home ='vis.0'                                 //wo soll das file im iobroker-file-system liegen ? (oder z.b auch iqontrol.meta)
      let   braucheEinFile=false;                          // bei true wird ein file geschrieben
      let   braucheEinVISWidget=true;                     // bei true wird ein html-tabelle in einen dp geschrieben - siehe nächste zeile
      let dpVIS="controll-own.0.AAATEST.TestHTML"         //WICHTIG wenn braucheEinVISWidget auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget
      let mySchedule=" */20 * * * * * ";                       //jede minute  
      //---------------------------------------
      
      //HIER DIE SPALTEN ANZAHL DEFINIEREN - jede Spalte einen Wert - in diesem Beispiel sind es 2
      var htmlFeld1='Instanz';       var Feld1lAlign="left";                     // überschrift Tabellen Spalte1 und  Ausrichtung left,right or center
      var htmlFeld2='Alive';         var Feld2lAlign="right";                      // überschrift Tabellen Spalte2 und  Ausrichtung left,right or center
      
      //-----------------------------------
      
      
      
      //hier werden die styles für die tabelle definiert
      //ÜBERSCHRIFT ÜBER TABELLE
      let   htmlUberschrift=false;                           // mit Überschrift über der tabelle
      let   htmlSignature=false;                              // anstatt der Überscghrift eine signature: - kleiner - anliegend
      const htmlFeldUeber='Batterie Zustand Sensoren';              // Überschrift und Signature
      const htmlFarbUber="white";                         // Farbe der Überschrift
      const htmlSchriftWeite="normal";                       // bold, normal - Fettschrift für Überschrift
      const htmlÜberFontGroesse="18px";                       // schriftgröße überschrift
      //MEHRERE TABELLEN NEBENEINANDER
      let   mehrfachTabelle=3;                              // bis zu 4 Tabellen werden nebeneinander geschrieben-  verkürzt das Ganze, dafür etwas breiter - MÖGLICH 1,2,3,oder 4 !!!
      const trennungsLinie="2";                             //extra trennungslinie bei mehrfachtabellen - evtl auf 0 stellen, wnn htmlRahmenLinien auf none sind
      const farbetrennungsLinie="white";
      const htmlFarbZweiteTabelle="white";                // Farbe der Überschrift bei jeder 2.ten Tabelle
      const htmlFarbTableColorUber="#BDBDBD";               // Überschrift in der tabelle - der einzelnen Spalten
      //ÜBERSCHRIFT SPALTEN
      const UeberSchriftHöhe="35";                          //Überschrift bekommt mehr Raum - darunter und darüber - Zellenhöhe
      const LinieUnterUeberschrift="3";                   // Linie nur unter Spaltenüberschrift - 
      const farbeLinieUnterUeberschrift="white";
      const groesseUeberschrift=16;
      const UeberschriftStyle="normal"                     // möglich "bold"
      //GANZE TABELLE
      let abstandZelle="1";
      let farbeUngeradeZeilen="#000000";                     //Farbe für ungerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let farbeGeradeZeilen="#151515";                        //Farbe für gerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let weite="auto";                                     //Weite der Tabelle
      let zentriert=true;                                   //ganze tabelle zentriert
      const backgroundAll="#000000";                        //Hintergrund für die ganze Seite - für direkten aufruf oder iqontrol sichtber - keine auswirkung auf vis-widget
      const htmlSchriftart="Helvetica";
      const htmlSchriftgroesse="14px";
      //FELDER UND RAHMEN
      let   UeberschriftSpalten=true;                // ein- oder ausblenden der spatlen-überschriften
      const htmlFarbFelderschrift="#BDBDBD";                  // SchriftFarbe der Felder
      const htmlFarbFelderschrift2="#D8D8D8";                 // SchriftFarbe der Felder für jede 2te Tabelle
      const htmlFarbTableColorGradient1="#424242";          //  Gradient - Hintergrund der Tabelle - Verlauffarbe
      const htmlFarbTableColorGradient2="#424242";          //  Gradient - Hintergrund der Tabelle - ist dieser Wert gleich Gradient1 gibt es keinen verlauf
      const htmlFarbTableBorderColor="grey";             // Farbe des Rahmen - is tdieser gleich den gradienten, sind die rahmen unsichtbar
      let htmlRahmenLinien="none";                            // Format für Rahmen: MÖGLICH: "none" oder "all" oder "cols" oder "rows"
      const htmlSpalte1Weite="auto";                   //  Weite der ersten beiden  Spalten oder z.b. 115px
      
      // HIER NICHTS  ÄNDERN
      
      let borderHelpBottum;
      let borderHelpRight;
      let htmlcenterHelp;
      let htmlcenterHelp2;
      
      if(htmlRahmenLinien=="rows") {borderHelpBottum=1;borderHelpRight=0;}
      if(htmlRahmenLinien=="cols") {borderHelpBottum=0;borderHelpRight=1;}
      if(htmlRahmenLinien=="none") {borderHelpBottum=0;borderHelpRight=0;}
      if(htmlRahmenLinien=="all")  {borderHelpBottum=1;borderHelpRight=1;}
      zentriert ? htmlcenterHelp="auto" : htmlcenterHelp="left";
      zentriert ? htmlcenterHelp2="center" : htmlcenterHelp2="left";
      
      
      const htmlZentriert='<center>'
      const htmlStart=    "<!DOCTYPE html><html lang=\"de\"><head><title>Vorlage</title><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"+
                       "<style> * {  margin: 0;} body {background-color: "+backgroundAll+"; margin: 0 auto;  }"+
                       " p {padding-top: 10px; padding-bottom: 10px; text-align: "+htmlcenterHelp2+"}"+
                      // " div { margin: 0 auto;  margin-left: auto; margin-right: auto;}"+
                       " td { padding:"+abstandZelle+"px; border:0px solid "+htmlFarbTableBorderColor+";  border-right:"+borderHelpRight+"px solid "+htmlFarbTableBorderColor+";border-bottom:"+borderHelpBottum+"px solid "+htmlFarbTableBorderColor+";}"+ 
                       " table { width: "+weite+";  margin: 0 "+htmlcenterHelp+"; border:1px solid "+htmlFarbTableBorderColor+"; border-spacing=\""+abstandZelle+"0px\" ; }"+   // margin macht center
                       "td:nth-child(1) {width: "+htmlSpalte1Weite+"}"+"td:nth-child(2) {width:"+htmlSpalte1Weite+"}"+
                       " </style></head><body> <div>";
      //const htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-weight: bold\">"+htmlFeldUeber+"</p>";                    
      const htmlTabStyle= "<table bordercolor=\""+htmlFarbTableBorderColor+"\" border=\"2px\" cellspacing=\""+abstandZelle+"\" cellpadding=\""+abstandZelle+"\" width=\""+weite+"\" rules=\""+htmlRahmenLinien+"\" style=\"color:"+htmlFarbFelderschrift+";  font-size:"+htmlSchriftgroesse+
                          "; font-family:"+htmlSchriftart+";background-image: linear-gradient(42deg,"+htmlFarbTableColorGradient2+","+htmlFarbTableColorGradient1+");\">";
      const htmlTabUeber1="<tr height=\""+UeberSchriftHöhe+"\" style=\"color:"+htmlFarbTableColorUber+"; font-size: "+groesseUeberschrift+"px; font-weight: "+UeberschriftStyle+" ;  border-bottom: "+LinieUnterUeberschrift+"px solid "+farbeLinieUnterUeberschrift+" \">";
      const htmlTabUeber3="</tr>";
      
      
      
      ////NICHTS ÄNDERN  - abhängig von den oben definierten _Spalten - in diesem Beispiel sind es 2
      
      var htmlTabUeber2="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+htmlFeld2+"&ensp;</td>";
      var htmlTabUeber2_1="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld2+
                         "&ensp;</td>";
      //------------------------------------------------------
      
      
      var htmlOut="";
      var mix;
      var counter;
      var val1;  var val0;
      var htmlTabUeber="";
      
      function writeHTML(){
      
      
      
      htmlOut="";
      
      counter=-1;
      htmlTabUeber="";
      switch (mehrfachTabelle) { 
         case 1: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber3;  break;
         case 2: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
         case 3: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber3; break;
         case 4: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
      };    
      if (!UeberschriftSpalten) {htmlTabUeber=""}
      
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      //---------hier kommt eure schleife rein counter++, tabelleBind() und tabelleFinish() müssen so integriert bleiben !!!------------------------------
      //---------alle valx werte müssen von euch bestimmt werden - val0,val1 !!!---------------------------------------------------------------------
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      
      $('system.adapter.*.alive').each(function(id, i) {           // hier eigene schleife definieren
              var ida = id.split('.');
              if( !(id.includes("vis") || id.includes("devices") ||  id.includes("fullcalendar"))){
                counter++;                                       // SEHR WICHTIG - MUSS IN JEDER SCHLEIFE INTEGRIERT SEIN
                val0=ida[2]+"."+ida[3];
                var val1help=getState(id.replace("alive","uptime")).val;
                val1=Math.floor( ((val1help)/60/60/24) )+"d "+ Math.floor(((val1help)/60/60) % 24) +"h "+ Math.floor( ((val1help)/60) % 60 )+" m" ;
      
             
          
           tabelleBind(); //HIER NICHTS ÄNDERN : HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT  - diese function muss als letztes in der eigenen schleife aufgerufen werden
          
         }}); //Schleifen Ende - je nach schleifenart muss hier etwas geändert werden !!!!!!!!!
      
      //------------------------------------------------------------
      //------------------------------------------------------------
      //------------------------------------------------------------   
      
            tabelleFinish(); // AB HIER NICHTS ÄNDERN - tabelle fertigstellen
           
      } // function ende
      
      //MAIN:
       
      schedule(mySchedule,  function () {
       writeHTML();
       if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
      }); 
      writeHTML();
      
      function tabelleBind(){
             switch (mehrfachTabelle) {  
               case 1:  if(counter%2==0)         {   htmlOut=htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td></tr>"; break;  } else
                                                 {   htmlOut=htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td></tr>"; break;  }
      //-------------------------------------
               case 2:  if(counter%4==0){
                        if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\" ><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                          ";\"align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+
                                           htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td></tr>";} break;
               }else{
                        if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+
                                          "px solid "+farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td  align="+Feld1lAlign+" style=\" color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+
                                        " style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td></tr>";} break;}
      //-------------------------------------               
               case 3: if(counter%2==0)   {
               
                       if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+
                                          farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+
                                                               " style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td>";} 
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td></tr>";}
                                                } break; }else{
                       if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+
                                          farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+
                                                               " style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td>";} 
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td></tr>";}
                                                } break;  }                       
      //------------------------------------- 
               case 4: //counter=counter+8 
               if(counter%8==0)   {
               
                        if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+
                                          farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>"; } 
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+
                                                                  " style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td>";} 
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+
                                                                                                 Feld2lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"; color:"+htmlFarbFelderschrift2+
                                                                                                 "\">&ensp;"+val1+"&ensp;</td></tr>";} 
                                                                        else    {htmlOut = htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "
                                                                                 +farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>";}}
                                                } break;}else{
                        if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+
                                          farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>"; } 
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+
                                                                  " style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td>";} 
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="
                                                                                                 +Feld2lAlign+" style=\" color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td></tr>";} 
                                                                        else    {htmlOut = htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+
                                                                                 farbetrennungsLinie+";\" align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td>";}}
                                                }  break;   }                     
      
           } //switch ende
      
      }
      
      function tabelleFinish() {
      
             switch (mehrfachTabelle) {  
               case 1:    break;
               case 2:    if(counter%2==0)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td></tr>'); 
                               
                          break;
               case 3:    if(counter%3==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                          if(counter%3==1)  htmlOut = htmlOut.replace(/<\/td>$/,  '</td><td>&ensp;</td><td>&ensp;</td></tr>');       
                          if(counter%3==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                           
                          break;
               case 4:    if(counter%4==3)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                          if(counter%4==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td></tr>");
                          if(counter%4==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");    
                          if(counter%4==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");   
                            
                          break; }
                var htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: "+htmlÜberFontGroesse+"; font-weight:"+htmlSchriftWeite+ "\">"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</p>"; 
             var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 70%; text-align: right;\" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>"
              
              if (!htmlSignature) htmlUnter="";
                //Ausgabe über VIS html widget - tabelle in datenpunkt schreiben - html tabelle ohne html header und body
                 var htmlOutVIS="";
               //  htmlUberschrift ? htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>" : htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>";
                  if (htmlUberschrift) 
                      { zentriert ? htmlOutVIS=htmlZentriert+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter : htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter ;
      
                    } else {
                     zentriert ?  htmlOutVIS=htmlZentriert+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter :  htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter;
      
                       }
      
        // log("bin raus aus tabelleBind");
                 if (braucheEinVISWidget) setState(dpVIS, htmlOutVIS );
      
       var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 80%;  text-align: center; \" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>"
       var htmlEnd="</table>"+htmlUnter+"</div></body>";
       if (!htmlSignature) htmlUnter="";
      
       //mit oder ohne überschrift - zentriert oder links
      htmlUberschrift ? htmlOut=htmlStart+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd : htmlOut=htmlStart+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd;
       //log(htmlOut);
      
      
      }
      
      
      
      


         //@liv-in-sky 2020  4.2.-18:42
      
      
      //HIER WIRD PFAD UND FILENAME DEFINIERT
      const path = "/htmlexample.html";                   //FIlenamen definieren
      const home ='vis.0'                                 //wo soll das file im iobroker-file-system liegen ? (oder z.b auch iqontrol.meta)
      let   braucheEinFile=true;                          // bei true wird ein file geschrieben
      let   braucheEinVISWidget=true;                     // bei true wird ein html-tabelle in einen dp geschrieben - siehe nächste zeile
      let dpVIS="controll-own.0.AAATEST.TestHTML"         //WICHTIG wenn braucheEinVISWidget auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget
      let mySchedule=" */20 * * * * * ";                       //jede minute  
      //---------------------------------------
      
      //HIER DIE SPALTEN ANZAHL DEFINIEREN - jede Spalte einen Wert - in diesem Beispiel sind es 3
      var htmlFeld1='Instanz';      var Feld1lAlign="left";                     // überschrift Tabellen Spalte1 und  Ausrichtung left,right or center
      var htmlFeld2='Alive';        var Feld2lAlign="center";                      // überschrift Tabellen Spalte2 und  Ausrichtung left,right or center
      var htmlFeld3='Status';         var Feld3lAlign="right";                    // überschrift Tabellen Spalte3 und  Ausrichtung left,right or center
      //-----------------------------------
      
      
      //hier werden die styles für die tabelle definiert
      //ÜBERSCHRIFT ÜBER TABELLE
      let   htmlUberschrift=false;                           // mit Überschrift über der tabelle
      let   htmlSignature=false;                              // anstatt der Überscghrift eine signature: - kleiner - anliegend
      const htmlFeldUeber='Batterie Zustand Sensoren';              // Überschrift und Signature
      const htmlFarbUber="white";                         // Farbe der Überschrift
      const htmlSchriftWeite="normal";                       // bold, normal - Fettschrift für Überschrift
      const htmlÜberFontGroesse="18px";                       // schriftgröße überschrift
      //MEHRERE TABELLEN NEBENEINANDER
      let   mehrfachTabelle=3;                              // bis zu 4 Tabellen werden nebeneinander geschrieben-  verkürzt das Ganze, dafür etwas breiter - MÖGLICH 1,2,3,oder 4 !!!
      const trennungsLinie="2";                             //extra trennungslinie bei mehrfachtabellen - evtl auf 0 stellen, wnn htmlRahmenLinien auf none sind
      const farbetrennungsLinie="white";
      const htmlFarbZweiteTabelle="white";                // Farbe der Überschrift bei jeder 2.ten Tabelle
      const htmlFarbTableColorUber="#BDBDBD";               // Überschrift in der tabelle - der einzelnen Spalten
      //ÜBERSCHRIFT SPALTEN
      const UeberSchriftHöhe="35";                          //Überschrift bekommt mehr Raum - darunter und darüber - Zellenhöhe
      const LinieUnterUeberschrift="3";                   // Linie nur unter Spaltenüberschrift - 
      const farbeLinieUnterUeberschrift="white";
      const groesseUeberschrift=16;
      const UeberschriftStyle="normal"                     // möglich "bold"
      //GANZE TABELLE
      let abstandZelle="1";
      let farbeUngeradeZeilen="#000000";                     //Farbe für ungerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let farbeGeradeZeilen="#151515";                        //Farbe für gerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let weite="auto";                                     //Weite der Tabelle
      let zentriert=true;                                   //ganze tabelle zentriert
      const backgroundAll="#000000";                        //Hintergrund für die ganze Seite - für direkten aufruf oder iqontrol sichtber - keine auswirkung auf vis-widget
      const htmlSchriftart="Helvetica";
      const htmlSchriftgroesse="14px";
      //FELDER UND RAHMEN
      let   UeberschriftSpalten=true;                // ein- oder ausblenden der spatlen-überschriften
      const htmlFarbFelderschrift="#BDBDBD";                  // SchriftFarbe der Felder
      const htmlFarbFelderschrift2="#D8D8D8";                 // SchriftFarbe der Felder für jede 2te Tabelle
      const htmlFarbTableColorGradient1="#424242";          //  Gradient - Hintergrund der Tabelle - Verlauffarbe
      const htmlFarbTableColorGradient2="#424242";          //  Gradient - Hintergrund der Tabelle - ist dieser Wert gleich Gradient1 gibt es keinen verlauf
      const htmlFarbTableBorderColor="grey";             // Farbe des Rahmen - is tdieser gleich den gradienten, sind die rahmen unsichtbar
      let htmlRahmenLinien="none";                            // Format für Rahmen: MÖGLICH: "none" oder "all" oder "cols" oder "rows"
      const htmlSpalte1Weite="auto";                   //  Weite der ersten beiden  Spalten oder z.b. 115px
      
      // HIER NICHTS  ÄNDERN
      
      let borderHelpBottum;
      let borderHelpRight;
      let htmlcenterHelp;
      let htmlcenterHelp2;
      
      if(htmlRahmenLinien=="rows") {borderHelpBottum=1;borderHelpRight=0;}
      if(htmlRahmenLinien=="cols") {borderHelpBottum=0;borderHelpRight=1;}
      if(htmlRahmenLinien=="none") {borderHelpBottum=0;borderHelpRight=0;}
      if(htmlRahmenLinien=="all")  {borderHelpBottum=1;borderHelpRight=1;}
      zentriert ? htmlcenterHelp="auto" : htmlcenterHelp="left";
      zentriert ? htmlcenterHelp2="center" : htmlcenterHelp2="left";
      
      
      const htmlZentriert='<center>'
      const htmlStart=    "<!DOCTYPE html><html lang=\"de\"><head><title>Vorlage</title><meta http-equiv=\"content-type\" content=\"text/html;  http-equiv=\"refresh\" content=\"30\"; charset=utf-8\">"+
                         "<style> * {  margin: 0;} body {background-color: "+backgroundAll+"; margin: 0 auto;  }"+
                         " p {padding-top: 10px; padding-bottom: 10px; text-align: "+htmlcenterHelp2+"}"+
                        // " div { margin: 0 auto;  margin-left: auto; margin-right: auto;}"+
                         " td { padding:"+abstandZelle+"px; border:0px solid "+htmlFarbTableBorderColor+";  border-right:"+borderHelpRight+"px solid "+htmlFarbTableBorderColor+";border-bottom:"+borderHelpBottum+"px solid "+htmlFarbTableBorderColor+";}"+ 
                         " table { width: "+weite+";  margin: 0 "+htmlcenterHelp+"; border:1px solid "+htmlFarbTableBorderColor+"; border-spacing=\""+abstandZelle+"0px\" ; }"+   // margin macht center
                         "td:nth-child(1) {width: "+htmlSpalte1Weite+"}"+"td:nth-child(2) {width:"+htmlSpalte1Weite+"}"+
                         " </style></head><body> <div>";
      //const htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-weight: bold\">"+htmlFeldUeber+"</p>";                    
      const htmlTabStyle= "<table bordercolor=\""+htmlFarbTableBorderColor+"\" border=\"2px\" cellspacing=\""+abstandZelle+"\" cellpadding=\""+abstandZelle+"\" width=\""+weite+"\" rules=\""+htmlRahmenLinien+"\" style=\"color:"+htmlFarbFelderschrift+";  font-size:"+htmlSchriftgroesse+
                            "; font-family:"+htmlSchriftart+";background-image: linear-gradient(42deg,"+htmlFarbTableColorGradient2+","+htmlFarbTableColorGradient1+");\">";
      const htmlTabUeber1="<tr height=\""+UeberSchriftHöhe+"\" style=\"color:"+htmlFarbTableColorUber+"; font-size: "+groesseUeberschrift+"px; font-weight: "+UeberschriftStyle+" ;  border-bottom: "+LinieUnterUeberschrift+"px solid "+farbeLinieUnterUeberschrift+" \">";
      const htmlTabUeber3="</tr>";
      /*
      table td:first-child {}  //1
      table td:nth-child(2) {} //2
      table td:nth-child(3) {} //3
      table td:last-child {}   //4
      */
      
      //NICHTS ÄNDERN - abhängig von den oben definierten _Spalten - in diesem Beispiel sind es 3
      
         	var htmlTabUeber2="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+htmlFeld2+"&ensp;</td><td  align="+Feld3lAlign+">&ensp;"+htmlFeld3+"&ensp;</td>";
      var htmlTabUeber2_1="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+"  align="+Feld2lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld2+
                         "&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld3+"&ensp;</td>";
      //------------------------------------------------------
      
      
      var htmlTabUeber="";
      var htmlOut="";
      var mix;
      var counter;
      //HIER SIND DIE  WERTE, DIE IN DER SCHLEIFE GEFILTERET WER%DEN - Jede spalte einen wert - jeder valx muss in dieser schleife gesetzt werden !!
      var val1; var val0; var val2;
      
      function writeHTML(){
      
      
      htmlOut="";
      
      counter=-1;
      htmlTabUeber="";
      switch (mehrfachTabelle) { 
         case 1: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber3;  break;
         case 2: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
         case 3: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber3; break;
         case 4: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
      };   
      if (!UeberschriftSpalten) {htmlTabUeber=""}
      
      
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      //---------hier kommt eure schleife rein counter++, tabelleBind() und tabelleFinish() müssen so integriert bleiben !!!------------------------------
      //---------alle valx werte müssen von euch bestimmt werden - val0,val1,val2 !!!---------------------------------------------------------------------
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      
      $('system.adapter.*.alive').each(function(id, i) {           // hier eigene schleife definieren und den wert counter++ nicht vergessen  !!!
              var ida = id.split('.');
              if( !(id.includes("vis") || id.includes("device")  ||  id.includes("alexa2") ||  id.includes("phantom"))){
                counter++;                                       // SEHR WICHTIG - MUSS IN JEDER SCHLEIFE INTEGRIERT SEIN
                val0=ida[2]+"."+ida[3];
                var val1help=getState(id.replace("alive","uptime")).val;
                val1=Math.floor( ((val1help)/60/60/24) )+"d "+ Math.floor(((val1help)/60/60) % 24) +"h "+ Math.floor( ((val1help)/60) % 60 )+" m" ;
      
                if (getState(id).val==null) {val2="never used"}; //log(id)}; 
           
                if (getState(id).val==false) {val2="❌"} else{val2="✅"}         
                
           
         
           tabelleBind(); //HIER NICHTS ÄNDERN : HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT  - diese function muss als letztes in der eigenen schleife aufgerufen werden
          
         }}); //Schleifen Ende - je nach schleifenart muss hier etwas geändert werden !!!!!!!!!
      
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      //--------------------------------------------------Ende der schleife------------------------------------------------------------------------------
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      
            tabelleFinish(); // AB HIER NICHTS ÄNDERN - tabelle fertigstellen
           
      } // function ende
      
      //MAIN:
       
      schedule(mySchedule,  function () { 
       writeHTML();
       if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
      }); 
      writeHTML();                                   //     <tdalign
      
       function tabelleBind(){
         //  counter=counter+mehrfachTabelle;
             switch (mehrfachTabelle) { 
      
               case 1: if(counter%2==0)         {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>"; break;}else    
                                                {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>"; break;}
               case 2: if(counter%4==0){
                          if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} break;
                            }else{
                                      if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} break;}
                                          
               case 3:if(counter%2==0)   {
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //Teil1 c=0
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              "; color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //Teil 2 c=1
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>";} //Teil 3 c=3
                                                } break;}else{
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} 
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>";}
                                                } break;}                                          
      
      
               case 4:  // counter=counter+8;
                         if(counter%8==0)   {
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+ farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } // teil1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} //teil 4
                                                                        else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"  align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}else{
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //teil 1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} // teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} // teil 4
                                                                        else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}                                    
              } //switch ende
      
      }
      
      function tabelleFinish() {
      
      switch (mehrfachTabelle) {  
             case 1:    break;
      
             case 2:    
                        if(counter%2==0)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>');
                      
                        break;
      
             case 3:   if(counter%3==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%3==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");        
                       if(counter%3==0)      htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                     
                        break;
             case 4:   if(counter%4==3)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%4==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                       if(counter%4==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");    
                       if(counter%4==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");      
                       break; }
           
               var htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: "+htmlÜberFontGroesse+"; font-weight:"+htmlSchriftWeite+ "\">"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</p>"; 
             var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 70%; text-align: right;\" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>";
              
              if (!htmlSignature) htmlUnter="";
                //Ausgabe über VIS html widget - tabelle in datenpunkt schreiben - html tabelle ohne html header und body
                 var htmlOutVIS="";
               //  htmlUberschrift ? htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>" : htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>";
                  if (htmlUberschrift) 
                      { zentriert ? htmlOutVIS=htmlZentriert+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter : htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter ;
      
                    } else {
                     zentriert ?  htmlOutVIS=htmlZentriert+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter :  htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter;
      
                       }
                       
      
        // log("bin raus aus tabelleBind");
                 if (braucheEinVISWidget) setState(dpVIS, htmlOutVIS );
      
       var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 80%;  text-align: center; \" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>"
      
       if (!htmlSignature) htmlUnter="";
        var htmlEnd="</table>"+htmlUnter+"</div></body>";
       //mit oder ohne überschrift - zentriert oder links
      htmlUberschrift ? htmlOut=htmlStart+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd : htmlOut=htmlStart+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd;
       //log(htmlOut);
      
      
      }
      
      
      
      
      


          //@liv-in-sky 2020  4.2.-18:42
      
      
      //HIER WIRD PFAD UND FILENAME DEFINIERT
      const path = "/htmlexample.html";                   //FIlenamen definieren
      const home ='vis.0'                                 //wo soll das file im iobroker-file-system liegen ? (oder z.b auch iqontrol.meta)
      let   braucheEinFile=false;                          // bei true wird ein file geschrieben
      let   braucheEinVISWidget=true;                     // bei true wird ein html-tabelle in einen dp geschrieben - siehe nächste zeile
      let dpVIS="controll-own.0.AAATEST.TestHTML"         //WICHTIG wenn "braucheEinVISWidget" auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget
      let mySchedule=" */20 * * * * * ";                       //jede minute  
      
      //---------------------------------------
      
      //HIER DIE SPALTEN ANZAHL DEFINIEREN - jede Spalte einen Wert - in diesem Beispiel sind es 4
      var htmlFeld1='Instanz';       var Feld1lAlign="left";                     // überschrift Tabellen Spalte1 und  Ausrichtung left,right or center
      var htmlFeld2='Alive';        var Feld2lAlign="right";                      // überschrift Tabellen Spalte2 und  Ausrichtung left,right or center
      var htmlFeld3='MemHeap';         var Feld3lAlign="right";                    // überschrift Tabellen Spalte3 und  Ausrichtung left,right or center
      var htmlFeld4='Status';        var Feld4lAlign="left";                    // überschrift Tabellen Spalte4 und  Ausrichtung left,right or center
      //-----------------------------------
      
      
      
      //ÜBERSCHRIFT ÜBER TABELLE
      let   htmlUberschrift=false;                           // mit Überschrift über der tabelle
      let   htmlSignature=false;                              // anstatt der Überscghrift eine signature: - kleiner - anliegend
      const htmlFeldUeber='Batterie Zustand Sensoren';              // Überschrift und Signature
      const htmlFarbUber="white";                         // Farbe der Überschrift
      const htmlSchriftWeite="normal";                       // bold, normal - Fettschrift für Überschrift
      const htmlÜberFontGroesse="18px";                       // schriftgröße überschrift
      //MEHRERE TABELLEN NEBENEINANDER
      let   mehrfachTabelle=1;                              // bis zu 4 Tabellen werden nebeneinander geschrieben-  verkürzt das Ganze, dafür etwas breiter - MÖGLICH 1,2,3,oder 4 !!!
      const trennungsLinie="2";                             //extra trennungslinie bei mehrfachtabellen - evtl auf 0 stellen, wnn htmlRahmenLinien auf none sind
      const farbetrennungsLinie="white";
      const htmlFarbZweiteTabelle="white";                // Farbe der Überschrift bei jeder 2.ten Tabelle
      const htmlFarbTableColorUber="#BDBDBD";               // Überschrift in der tabelle - der einzelnen Spalten
      //ÜBERSCHRIFT SPALTEN
      const UeberSchriftHöhe="35";                          //Überschrift bekommt mehr Raum - darunter und darüber - Zellenhöhe
      const LinieUnterUeberschrift="3";                   // Linie nur unter Spaltenüberschrift - 
      const farbeLinieUnterUeberschrift="white";
      const groesseUeberschrift=16;
      const UeberschriftStyle="normal"                     // möglich "bold"
      //GANZE TABELLE
      let abstandZelle="1";
      let farbeUngeradeZeilen="#000000";                     //Farbe für ungerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let farbeGeradeZeilen="#151515";                        //Farbe für gerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let weite="auto";                                     //Weite der Tabelle
      let zentriert=true;                                   //ganze tabelle zentriert
      const backgroundAll="#000000";                        //Hintergrund für die ganze Seite - für direkten aufruf oder iqontrol sichtber - keine auswirkung auf vis-widget
      const htmlSchriftart="Helvetica";
      const htmlSchriftgroesse="14px";
      //FELDER UND RAHMEN
      let   UeberschriftSpalten=true;                // ein- oder ausblenden der spatlen-überschriften
      const htmlFarbFelderschrift="#BDBDBD";                  // SchriftFarbe der Felder
      const htmlFarbFelderschrift2="#D8D8D8";                 // SchriftFarbe der Felder für jede 2te Tabelle
      const htmlFarbTableColorGradient1="#424242";          //  Gradient - Hintergrund der Tabelle - Verlauffarbe
      const htmlFarbTableColorGradient2="#424242";          //  Gradient - Hintergrund der Tabelle - ist dieser Wert gleich Gradient1 gibt es keinen verlauf
      const htmlFarbTableBorderColor="grey";             // Farbe des Rahmen - is tdieser gleich den gradienten, sind die rahmen unsichtbar
      let htmlRahmenLinien="none";                            // Format für Rahmen: MÖGLICH: "none" oder "all" oder "cols" oder "rows"
      const htmlSpalte1Weite="auto";                   //  Weite der ersten beiden  Spalten oder z.b. 115px
      
      // HIER NICHTS  ÄNDERN
      
      let borderHelpBottum;
      let borderHelpRight;
      let htmlcenterHelp;
      let htmlcenterHelp2;
      
      if(htmlRahmenLinien=="rows") {borderHelpBottum=1;borderHelpRight=0;}
      if(htmlRahmenLinien=="cols") {borderHelpBottum=0;borderHelpRight=1;}
      if(htmlRahmenLinien=="none") {borderHelpBottum=0;borderHelpRight=0;}
      if(htmlRahmenLinien=="all")  {borderHelpBottum=1;borderHelpRight=1;}
      zentriert ? htmlcenterHelp="auto" : htmlcenterHelp="left";
      zentriert ? htmlcenterHelp2="center" : htmlcenterHelp2="left";
      
      
      const htmlZentriert='<center>'
      const htmlStart=    "<!DOCTYPE html><html lang=\"de\"><head><title>Vorlage</title><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"+
                       "<style> * {  margin: 0;} body {background-color: "+backgroundAll+"; margin: 0 auto;  }"+
                       " p {padding-top: 10px; padding-bottom: 10px; text-align: "+htmlcenterHelp2+"}"+
                      // " div { margin: 0 auto;  margin-left: auto; margin-right: auto;}"+
                       " td { padding:"+abstandZelle+"px; border:0px solid "+htmlFarbTableBorderColor+";  border-right:"+borderHelpRight+"px solid "+htmlFarbTableBorderColor+";border-bottom:"+borderHelpBottum+"px solid "+htmlFarbTableBorderColor+";}"+ 
                       " table { width: "+weite+";  margin: 0 "+htmlcenterHelp+"; border:1px solid "+htmlFarbTableBorderColor+"; border-spacing=\""+abstandZelle+"0px\" ; }"+   // margin macht center
                       "td:nth-child(1) {width: "+htmlSpalte1Weite+"}"+"td:nth-child(2) {width:"+htmlSpalte1Weite+"}"+
                       " </style></head><body> <div>";
      //const htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-weight: bold\">"+htmlFeldUeber+"</p>";                    
      const htmlTabStyle= "<table bordercolor=\""+htmlFarbTableBorderColor+"\" border=\"2px\" cellspacing=\""+abstandZelle+"\" cellpadding=\""+abstandZelle+"\" width=\""+weite+"\" rules=\""+htmlRahmenLinien+"\" style=\"color:"+htmlFarbFelderschrift+";  font-size:"+htmlSchriftgroesse+
                          "; font-family:"+htmlSchriftart+";background-image: linear-gradient(42deg,"+htmlFarbTableColorGradient2+","+htmlFarbTableColorGradient1+");\">";
      const htmlTabUeber1="<tr height=\""+UeberSchriftHöhe+"\" style=\"color:"+htmlFarbTableColorUber+"; font-size: "+groesseUeberschrift+"px; font-weight: "+UeberschriftStyle+" ;  border-bottom: "+LinieUnterUeberschrift+"px solid "+farbeLinieUnterUeberschrift+" \">";
      const htmlTabUeber3="</tr>";
      
      
      
      
      //NICHTS ÄNDERN - abhängig von den oben definierten _Spalten - in diesem Beispiel sind es 4
      
      var htmlTabUeber2="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+htmlFeld2+"&ensp;</td><td  align="+Feld3lAlign+">&ensp;"+htmlFeld3+"&ensp;</td><td align="+Feld4lAlign+">&ensp;"+htmlFeld4+"&ensp;</td>";
      var htmlTabUeber2_1="<td width="+htmlSpalte1Weite+" align=="+Feld1lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+"  align="+Feld2lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld2+
                         "&ensp;</td><td  align=="+Feld3lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld3+"&ensp;</td><td  align="+Feld4lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld4+
                         "&ensp;</td>";
      //------------------------------------------------------
      
      
      var htmlOut="";
      var mix;
      var counter;
      var val1; var val2; var val0; var val3;
      var htmlTabUeber="";
      
      function writeHTML(){
      
      
      htmlOut="";
      
      
      
      counter=-1;
      htmlTabUeber="";
      switch (mehrfachTabelle) { 
         case 1: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber3;  break;
         case 2: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
         case 3: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2+htmlTabUeber2+htmlTabUeber3; break;
         case 4: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
      }; 
      if (!UeberschriftSpalten) {htmlTabUeber=""} 
      
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      //---------hier kommt eure schleife rein counter++, tabelleBind() und tabelleFinish() müssen so integriert bleiben !!!------------------------------
      //---------alle valx werte müssen von euch bestimmt werden - val0,val1,val2,val3 !!!---------------------------------------------------------------------
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      
      $('system.adapter.*.alive').each(function(id, i) {           // hier eigene schleife definieren
              var ida = id.split('.');
              if( !(id.includes("vis") || id.includes("devices") ||  id.includes("sss"))){
                counter++;                                       // SEHR WICHTIG - MUSS IN JEDER SCHLEIFE INTEGRIERT SEIN
                val0=ida[2]+"."+ida[3];
                let val1help=getState(id.replace("alive","uptime")).val;
                val2=getState(id.replace("alive","memHeapUsed")).val;
                val1=Math.floor( ((val1help)/60/60/24) )+"d "+ Math.floor(((val1help)/60/60) % 24) +"h "+ Math.floor( ((val1help)/60) % 60 )+" m" ;
      
                if (getState(id).val==null) {val3="never used"}; //log(id)}; 
           
                if (getState(id).val==false) {val3="❌"} else{val3="✅"}         
      
      
         
           tabelleBind(); //HIER NICHTS ÄNDERN : HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT  - diese function muss als letztes in der eigenen schleife aufgerufen werden
          
         }}); //Schleifen Ende - je nach schleifenart muss hier etwas geändert werden !!!!!!!!!
      
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      //--------------------------------------------------Ende der schleife------------------------------------------------------------------------------
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      
            tabelleFinish(); // AB HIER NICHTS ÄNDERN - tabelle fertigstellen
           
      } // function ende
      
      //MAIN:
      
       
      schedule(mySchedule,  function () {
       writeHTML();
       if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
      }); 
      writeHTML();
      
      
      function tabelleBind(){
           //HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT - hat man oben 4 Felder definiert, braucht man hier 4 Werte 
         
             switch (mehrfachTabelle) {  
              case 1:  if(counter%2==0){  htmlOut=htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td></tr>"; break;} else
                                       {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td></tr>"; break;}
              case 2: if(counter%4==0){ 
                       if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                          ";\"align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td>"; } 
                                    else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td></tr>";} break;
                          }else{
                       if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                          ";\" align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td>"; } 
                                    else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td></tr>";} break;}                  
              case 3:  if(counter%2==0)   {
                        if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align=left>&ensp;"+val3+"&ensp;</td>"; } 
                                    else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td>";} 
                                                     else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td></tr>";}
                                               } break;}else{
                        if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align=left>&ensp;"+val3+"&ensp;</td>"; } 
                                    else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td>";} 
                                                     else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td></tr>";}
                                               } break;}
      
              case 4:  if(counter%8==0)   {
                       if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+ ";\" align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td>"; } 
                                        else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"; color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td>";} 
                                                     else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\"&ensp;>"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+ "color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td></tr>";} 
                                                                       else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td>";}}
                                               } break;}else{
                       if(counter%4==0)   {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+ ";\" align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td>"; } 
                                        else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+ ";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td>";} 
                                                     else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\"&ensp;>"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td><td  align="+Feld4lAlign+"  color:"+htmlFarbFelderschrift2+"\">&ensp;"+val3+"&ensp;</td></tr>";} 
                                                                       else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"align="+Feld4lAlign+">&ensp;"+val3+"&ensp;</td>";}}
                                               } break;     }                   
      
           } //switch ende
      
      }
      
      
      function tabelleFinish() {
      
           // tabelle fertigstellen
      
      
             switch (mehrfachTabelle) {  
             case 1:    break;
      
             case 2:    
                        if(counter%2==0)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>');   
                      
                        break;
      
             case 3:   if(counter%3==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%3==2)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>');      
                       if(counter%3==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                     
                        break;
             case 4:   if(counter%4==3) { log(htmlOut); htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>"); log(htmlOut)}
                       if(counter%4==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                       if(counter%4==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");    
                       if(counter%4==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");      
                       break; } 
      
      
               var htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: "+htmlÜberFontGroesse+"; font-weight:"+htmlSchriftWeite+ "\">"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</p>"; 
             var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 70%; text-align: right;\" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>";
              
              if (!htmlSignature) htmlUnter="";
                //Ausgabe über VIS html widget - tabelle in datenpunkt schreiben - html tabelle ohne html header und body
                 var htmlOutVIS="";
               //  htmlUberschrift ? htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>" : htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>";
                  if (htmlUberschrift) 
                      { zentriert ? htmlOutVIS=htmlZentriert+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter : htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter ;
      
                    } else {
                     zentriert ?  htmlOutVIS=htmlZentriert+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter :  htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter;
      
                       }
      
        // log("bin raus aus tabelleBind");
                 if (braucheEinVISWidget) setState(dpVIS, htmlOutVIS );
      
       var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 80%;  text-align: center; \" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>"
       var htmlEnd="</table>"+htmlUnter+"</div></body>";
       if (!htmlSignature) htmlUnter="";
      
       //mit oder ohne überschrift - zentriert oder links
      htmlUberschrift ? htmlOut=htmlStart+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd : htmlOut=htmlStart+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd;
       //log(htmlOut);
      
      
      }
      
      
      
      
      
      
      
      
      

      https://forum.iobroker.net/post/371271
      

      https://forum.iobroker.net/post/371274
      


      ähnlicher beitrag nur mit blockly: https://forum.iobroker.net/topic/27517/tabelle-erzeugen-für-iqontrol-anzeige-blockly

      diese scripts in blockly einbinden:

      • in diesem beispiel werden die sonoff.0.POWER datenpunkte abgefragt - macht jetzt das blockly
      • dieses übergibt ein array an eine funktion - dieses array enthält die daten für die tabellenerstellung
      • die javascript-funktion im blockly ist eines der -tabellen-javascripte - je nachdem wieviel werte man anzeigen möchte - im beispiel hier sind es 2 werte
      • das javascript muss noch angepaßt werden
        -im inneren des javascripts muss die schleife die daten aus dem im blockly erzeugten und übergebenden array (liste) aufbereiten
      • das schedule wird ins blockly übernommen - daher das schedule im javascript auskommentieren

      Image 14.png

      • das blockly

      Image 10.png

      <xml xmlns="http://www.w3.org/1999/xhtml">
       <variables>
         <variable type="" id="y~gfT%L{V|O04MgdUo57">myList</variable>
         <variable type="" id="}K$K4dup~Vnv!`[}vnQy">Liste</variable>
         <variable type="" id="Z=?7wCQ1-49/,bxoE1#|">counter</variable>
         <variable type="" id="UrdtKDQ=Ky.^B@eAuwIJ">i</variable>
       </variables>
       <block type="schedule" id="Cqz)^1L5B-*_#wudd;?i" x="-387" y="-662">
         <field name="SCHEDULE">*/20 * * * * *</field>
         <statement name="STATEMENT">
           <block type="variables_set" id="sWqJxa.MyY?*y-S}mHPz">
             <field name="VAR" id="}K$K4dup~Vnv!`[}vnQy" variabletype="">Liste</field>
             <value name="VALUE">
               <block type="lists_create_with" id="s1KG8o;:gtQ6DjJt@w9I">
                 <mutation items="0"></mutation>
               </block>
             </value>
             <next>
               <block type="variables_set" id="R6exgi+-F7xoKVW/[NE.">
                 <field name="VAR" id="Z=?7wCQ1-49/,bxoE1#|" variabletype="">counter</field>
                 <value name="VALUE">
                   <block type="math_number" id="AHHG~c/mltPLQ?]Ik;5M">
                     <field name="NUM">-1</field>
                   </block>
                 </value>
                 <next>
                   <block type="controls_forEach" id="~PaFX`X@5n{TM9K^{Jw6">
                     <field name="VAR" id="UrdtKDQ=Ky.^B@eAuwIJ" variabletype="">i</field>
                     <value name="LIST">
                       <block type="selector" id="xQ^Q5{h5V@5PLI+YO@i.">
                         <field name="TEXT">sonoff.0.Sonoff*.POWER</field>
                       </block>
                     </value>
                     <statement name="DO">
                       <block type="lists_setIndex" id="-zUiNM(}BsoQ].Hu.|mx">
                         <mutation at="true"></mutation>
                         <field name="MODE">INSERT</field>
                         <field name="WHERE">FROM_START</field>
                         <value name="LIST">
                           <block type="variables_get" id="Q0Hct8=ken4m!!W]js)U">
                             <field name="VAR" id="}K$K4dup~Vnv!`[}vnQy" variabletype="">Liste</field>
                           </block>
                         </value>
                         <value name="AT">
                           <block type="variables_get" id="m`1tO?)De5*L9}MI~ux0">
                             <field name="VAR" id="UrdtKDQ=Ky.^B@eAuwIJ" variabletype="">i</field>
                           </block>
                         </value>
                         <value name="TO">
                           <block type="lists_create_with" id="6a@[p]s)BEL%k0#L3dY#">
                             <mutation items="2"></mutation>
                             <value name="ADD0">
                               <block type="variables_get" id="(sTiUEK5)L[Ct%sg[AR+">
                                 <field name="VAR" id="UrdtKDQ=Ky.^B@eAuwIJ" variabletype="">i</field>
                               </block>
                             </value>
                             <value name="ADD1">
                               <block type="get_value_var" id="$([Ki:j)vn|kP]]Ce;Xv">
                                 <field name="ATTR">val</field>
                                 <value name="OID">
                                   <shadow type="text" id="4xj+$Gix.+AO32.dH[cI">
                                     <field name="TEXT"></field>
                                   </shadow>
                                   <block type="variables_get" id="e0LEE%1wtlN{@`z.=hw]">
                                     <field name="VAR" id="UrdtKDQ=Ky.^B@eAuwIJ" variabletype="">i</field>
                                   </block>
                                 </value>
                               </block>
                             </value>
                           </block>
                         </value>
                       </block>
                     </statement>
                     <next>
                       <block type="procedures_callcustomnoreturn" id="1tTT@y+3fd)eq*EKO%`c">
                         <mutation name="tabelleMit3Werten">
                           <arg name="myList"></arg>
                         </mutation>
                         <value name="ARG0">
                           <block type="variables_get" id="T3wm-=*hL+H$*f^H0[J9">
                             <field name="VAR" id="}K$K4dup~Vnv!`[}vnQy" variabletype="">Liste</field>
                           </block>
                         </value>
                       </block>
                     </next>
                   </block>
                 </next>
               </block>
             </next>
           </block>
         </statement>
       </block>
       <block type="procedures_defcustomnoreturn" id="d+PXd6N1nBTxz}gaM@Co" x="-12" y="-438">
         <mutation statements="false">
           <arg name="myList" varid="y~gfT%L{V|O04MgdUo57"></arg>
         </mutation>
         <field name="NAME">tabelleMit3Werten</field>
         <field name="SCRIPT">IA0KDQoNCiAvL0hJRVIgV0lSRCBQRkFEIFVORCBGSUxFTkFNRSBERUZJTklFUlQNCiBjb25zdCBwYXRoID0gIi9odG1sZXhhbXBsZS5odG1sIjsgICAgICAgICAgICAgICAgICAgLy9GSWxlbmFtZW4gZGVmaW5pZXJlbg0KIGNvbnN0IGhvbWUgPSd2aXMuMCcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL3dvIHNvbGwgZGFzIGZpbGUgaW0gaW9icm9rZXItZmlsZS1zeXN0ZW0gbGllZ2VuID8gKG9kZXIgei5iIGF1Y2ggaXFvbnRyb2wubWV0YSkNCiBsZXQgICBicmF1Y2hlRWluRmlsZT10cnVlOyAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmVpIHRydWUgd2lyZCBlaW4gZmlsZSBnZXNjaHJpZWJlbg0KIGxldCAgIGJyYXVjaGVFaW5WSVNXaWRnZXQ9dHJ1ZTsgICAgICAgICAgICAgICAgICAgICAvLyBiZWkgdHJ1ZSB3aXJkIGVpbiBodG1sLXRhYmVsbGUgaW4gZWluZW4gZHAgZ2VzY2hyaWViZW4gLSBzaWVoZSBuw6RjaHN0ZSB6ZWlsZQ0KIGxldCBkcFZJUz0iY29udHJvbGwtb3duLjAuQUFBVEVTVC5UZXN0SFRNTCIgICAgICAgICAvL1dJQ0hUSUcgd2VubiBicmF1Y2hlRWluVklTV2lkZ2V0IGF1ZiB0cnVlIGdlc2V0enQgISEgIGRwIHp1c8OkdHpsaWNoIGbDvHIgVklTLUhUTUwtQmFzaWMtV2lkZ2V0DQogLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KLy9ISUVSIERJRSBTUEFMVEVOIEFOWkFITCBERUZJTklFUkVOIC0gamVkZSBTcGFsdGUgZWluZW4gV2VydCAtIGluIGRpZXNlbSBCZWlzcGllbCBzaW5kIGVzIDINCnZhciBodG1sRmVsZDE9J0luc3RhbnonOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDDvGJlcnNjaHJpZnQgVGFiZWxsZW4gU3BhbHRlMQ0KdmFyIGh0bWxGZWxkMj0nQWxpdmUnOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIMO8YmVyc2NocmlmdCBUYWJlbGxlbiBTcGFsdGUyDQoNCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQoNCi8vaGllciB3ZXJkZW4gZGllIHN0eWxlcyBmw7xyIGRpZSB0YWJlbGxlIGRlZmluaWVydA0KLy/DnEJFUlNDSFJJRlQgw5xCRVIgVEFCRUxMRQ0KbGV0ICAgaHRtbFViZXJzY2hyaWZ0PXRydWU7ICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWl0IMOcYmVyc2NocmlmdCDDvGJlciBkZXIgdGFiZWxsZQ0KY29uc3QgaHRtbEZlbGRVZWJlcj0nTUVJTkUgw5xCRVJTQ0hSSUZUJzsgICAgICAgICAgICAgIC8vIMOcYmVyc2NocmlmdA0KY29uc3QgaHRtbEZhcmJVYmVyPSIjMkM3RkI2IjsgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmFyYmUgZGVyIMOcYmVyc2NocmlmdA0KLy9NRUhSRVJFIFRBQkVMTEVOIE5FQkVORUlOQU5ERVINCmxldCAgIG1laHJmYWNoVGFiZWxsZT00OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJpcyB6dSA0IFRhYmVsbGVuIHdlcmRlbiBuZWJlbmVpbmFuZGVyIGdlc2NocmllYmVuLSAgdmVya8O8cnp0IGRhcyBHYW56ZSwgZGFmw7xyIGV0d2FzIGJyZWl0ZXIgLSBNw5ZHTElDSCAxLDIsMyxvZGVyIDQgISEhDQpjb25zdCBodG1sRmFyYlp3ZWl0ZVRhYmVsbGU9IiM0MkE2RUEiOyAgICAgICAgICAgICAgICAvLyBGYXJiZSBkZXIgw5xiZXJzY2hyaWZ0IGJlaSBqZWRlciAyLnRlbiBUYWJlbGxlDQpjb25zdCBodG1sRmFyYlRhYmxlQ29sb3JVYmVyPSIjMkM3RkI2IjsgICAgICAgICAgICAgICAvLyDDnGJlcnNjaHJpZnQgaW4gZGVyIHRhYmVsbGUgLSBkZXIgZWluemVsbmVuIFNwYWx0ZW4NCi8vR0FOWkUgVEFCRUxMRQ0KY29uc3QgaHRtbFNjaHJpZnRhcnQ9IkhlbHZldGljYSI7DQpjb25zdCBodG1sU2NocmlmdGdyb2Vzc2U9IjEzcHgiOw0KLy9GRUxERVIgVU5EIFJBSE1FTg0KY29uc3QgaHRtbEZhcmJGZWxkZXJzY2hyaWZ0PSIjREFERkRBIjsgICAgICAgICAgICAgICAgICAvLyBTY2hyaWZ0RmFyYmUgZGVyIEZlbGRlcg0KY29uc3QgaHRtbEZhcmJGZWxkZXJzY2hyaWZ0Mj0iI0UzRkJFMiI7ICAgICAgICAgICAgICAgICAvLyBTY2hyaWZ0RmFyYmUgZGVyIEZlbGRlciBmw7xyIGplZGUgMnRlIFRhYmVsbGUNCmNvbnN0IGh0bWxGYXJiVGFibGVDb2xvckdyYWRpZW50MT0iIzNGNDAzRiI7ICAgICAgICAgIC8vICBHcmFkaWVudCAtIEhpbnRlcmdydW5kIGRlciBUYWJlbGxlIC0gVmVybGF1ZmZhcmJlDQpjb25zdCBodG1sRmFyYlRhYmxlQ29sb3JHcmFkaWVudDI9IiMzRjQwM0YiOyAgICAgICAgICAvLyAgR3JhZGllbnQgLSBIaW50ZXJncnVuZCBkZXIgVGFiZWxsZSAtIGlzdCBkaWVzZXIgV2VydCBnbGVpY2ggR3JhZGllbnQxIGdpYnQgZXMga2VpbmVuIHZlcmxhdWYNCmNvbnN0IGh0bWxGYXJiVGFibGVCb3JkZXJDb2xvcj0iIzJDN0ZCNiI7ICAgICAgICAgICAgIC8vIEZhcmJlIGRlcyBSYWhtZW4gLSBpcyB0ZGllc2VyIGdsZWljaCBkZW4gZ3JhZGllbnRlbiwgc2luZCBkaWUgcmFobWVuIHVuc2ljaHRiYXINCmNvbnN0IGh0bWxSYWhtZW5MaW5pZW49MTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9ybWF0IGbDvHIgUmFobWVuKEdpdHRlcilsaW5pZW4gMT1hbGxlIC0gMj1udXIgdmVydGlrYWwgLSAzPSBudXIgaG9yaXpvbnRhbCAtIDQ9a2VpbmUNCg0KLy8gSElFUiBOSUNIVFMgIMOETkRFUk4NCmNvbnN0IGh0bWxFbmQ9ICAgICAgJzwvdGFibGU+PC9ib2R5Pic7DQpjb25zdCBodG1sU3RhcnQ9ICAgICc8IURPQ1RZUEUgaHRtbD48aHRtbCBsYW5nPSJkZSI+PGhlYWQ+PHRpdGxlPlZvcmxhZ2U8L3RpdGxlPjxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij48L2hlYWQ+PGJvZHk+JzsNCmNvbnN0IGh0bWxVZWJlcj0gICAgIjxwIHN0eWxlPVwiY29sb3I6IitodG1sRmFyYlViZXIrIjsgZm9udC1mYW1pbHk6IitodG1sU2NocmlmdGFydCsiOyBmb250LXdlaWdodDogYm9sZFwiPiIraHRtbEZlbGRVZWJlcisiPC9wPiI7DQpjb25zdCBodG1sVGFiU3R5bGVDb2w9ICI8dGFibGUgYm9yZGVyY29sb3I9XCIiK2h0bWxGYXJiVGFibGVCb3JkZXJDb2xvcisiXCIgYm9yZGVyPVwiM1wiIGNlbGxzcGFjaW5nPVwiM1wiIGNlbGxwYWRkaW5nPVwiM1wiICBydWxlcz1cImNvbHNcIiBzdHlsZT1cImNvbG9yOiIraHRtbEZhcmJGZWxkZXJzY2hyaWZ0KyI7ICBmb250LXNpemU6IitodG1sU2NocmlmdGdyb2Vzc2UrDQogICAgICAgICAgICAgICAgICAgICAgICI7IGZvbnQtZmFtaWx5OiIraHRtbFNjaHJpZnRhcnQrIjtiYWNrZ3JvdW5kLWltYWdlOiBsaW5lYXItZ3JhZGllbnQoNDJkZWcsIitodG1sRmFyYlRhYmxlQ29sb3JHcmFkaWVudDIrIiwiK2h0bWxGYXJiVGFibGVDb2xvckdyYWRpZW50MSsiKTtcIj4iOw0KY29uc3QgaHRtbFRhYlN0eWxlUm93PSAiPHRhYmxlIGJvcmRlcmNvbG9yPVwiIitodG1sRmFyYlRhYmxlQm9yZGVyQ29sb3IrIlwiIGJvcmRlcj1cIjNcIiBjZWxsc3BhY2luZz1cIjNcIiBjZWxscGFkZGluZz1cIjNcIiAgcnVsZXM9XCJyb3dzXCIgc3R5bGU9XCJjb2xvcjoiK2h0bWxGYXJiRmVsZGVyc2NocmlmdCsiOyAgZm9udC1zaXplOiIraHRtbFNjaHJpZnRncm9lc3NlKw0KICAgICAgICAgICAgICAgICAgICAgICAiOyBmb250LWZhbWlseToiK2h0bWxTY2hyaWZ0YXJ0KyI7YmFja2dyb3VuZC1pbWFnZTogbGluZWFyLWdyYWRpZW50KDQyZGVnLCIraHRtbEZhcmJUYWJsZUNvbG9yR3JhZGllbnQyKyIsIitodG1sRmFyYlRhYmxlQ29sb3JHcmFkaWVudDErIik7XCI+IjsNCmNvbnN0IGh0bWxUYWJTdHlsZUFsbD0gIjx0YWJsZSBib3JkZXJjb2xvcj1cIiIraHRtbEZhcmJUYWJsZUJvcmRlckNvbG9yKyJcIiBib3JkZXI9XCIzXCIgY2VsbHNwYWNpbmc9XCIzXCIgY2VsbHBhZGRpbmc9XCIzXCIgIHJ1bGVzPVwiYWxsXCIgc3R5bGU9XCJjb2xvcjoiK2h0bWxGYXJiRmVsZGVyc2NocmlmdCsiOyAgZm9udC1zaXplOiIraHRtbFNjaHJpZnRncm9lc3NlKw0KICAgICAgICAgICAgICAgICAgICAgICAiOyBmb250LWZhbWlseToiK2h0bWxTY2hyaWZ0YXJ0KyI7YmFja2dyb3VuZC1pbWFnZTogbGluZWFyLWdyYWRpZW50KDQyZGVnLCIraHRtbEZhcmJUYWJsZUNvbG9yR3JhZGllbnQyKyIsIitodG1sRmFyYlRhYmxlQ29sb3JHcmFkaWVudDErIik7XCI+IjsgICANCmNvbnN0IGh0bWxUYWJTdHlsZU5vbmU9ICI8dGFibGUgYm9yZGVyY29sb3I9XCIiK2h0bWxGYXJiVGFibGVCb3JkZXJDb2xvcisiXCIgYm9yZGVyPVwiM1wiIGNlbGxzcGFjaW5nPVwiM1wiIGNlbGxwYWRkaW5nPVwiM1wiICBydWxlcz1cIm5vbmVcIiBzdHlsZT1cImNvbG9yOiIraHRtbEZhcmJGZWxkZXJzY2hyaWZ0KyI7ICBmb250LXNpemU6IitodG1sU2NocmlmdGdyb2Vzc2UrDQogICAgICAgICAgICAgICAgICAgICAgICI7IGZvbnQtZmFtaWx5OiIraHRtbFNjaHJpZnRhcnQrIjtiYWNrZ3JvdW5kLWltYWdlOiBsaW5lYXItZ3JhZGllbnQoNDJkZWcsIitodG1sRmFyYlRhYmxlQ29sb3JHcmFkaWVudDIrIiwiK2h0bWxGYXJiVGFibGVDb2xvckdyYWRpZW50MSsiKTtcIj4iOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KY29uc3QgaHRtbFRhYlVlYmVyMT0iPHRyIHN0eWxlPVwiY29sb3I6IitodG1sRmFyYlRhYmxlQ29sb3JVYmVyKyI7IGZvbnQtd2VpZ2h0OiBib2xkXCI+IjsNCmNvbnN0IGh0bWxUYWJVZWJlcjM9IjwvdHI+IjsNCg0KDQoNCi8vLy9OSUNIVFMgw4ROREVSTiAgLSBhYmjDpG5naWcgdm9uIGRlbiBvYmVuIGRlZmluaWVydGVuIF9TcGFsdGVuIC0gaW4gZGllc2VtIEJlaXNwaWVsIHNpbmQgZXMgMg0KDQp2YXIgaHRtbFRhYlVlYmVyMj0iPHRkICBhbGlnbj1jZW50ZXI+JmVuc3A7IitodG1sRmVsZDErIiZlbnNwOzwvdGQ+PHRkIGFsaWduPWNlbnRlcj4mZW5zcDsiK2h0bWxGZWxkMisiJmVuc3A7PC90ZD4iOw0KdmFyIGh0bWxUYWJVZWJlcjJfMT0iPHRkICBhbGlnbj1jZW50ZXIgc3R5bGU9XCJjb2xvcjoiK2h0bWxGYXJiWndlaXRlVGFiZWxsZSsiXCI+JmVuc3A7IitodG1sRmVsZDErIiZlbnNwOzwvdGQ+PHRkICBhbGlnbj1jZW50ZXIgc3R5bGU9XCJjb2xvcjoiK2h0bWxGYXJiWndlaXRlVGFiZWxsZSsiXCI+JmVuc3A7IitodG1sRmVsZDIrDQogICAgICAgICAgICAgICAgICAgICImZW5zcDs8L3RkPiI7DQovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIA0KDQp2YXIgaHRtbE91dD0iIjsNCg0KDQoNCmZ1bmN0aW9uIHdyaXRlSFRNTCgpew0KDQogICAgICB2YXIgaHRtbFRhYlN0eWxlOw0KICAgIHN3aXRjaCAoK2h0bWxSYWhtZW5MaW5pZW4pIHsgDQogICAgY2FzZSAxOiBodG1sVGFiU3R5bGU9aHRtbFRhYlN0eWxlQWxsOyBicmVhazsNCiAgICBjYXNlIDI6IGh0bWxUYWJTdHlsZT1odG1sVGFiU3R5bGVDb2w7IGJyZWFrOw0KICAgIGNhc2UgMzogaHRtbFRhYlN0eWxlPWh0bWxUYWJTdHlsZVJvdzsgYnJlYWs7DQogICAgY2FzZSA0OiBodG1sVGFiU3R5bGU9aHRtbFRhYlN0eWxlTm9uZTsgYnJlYWs7DQogICAgDQp9OyAgDQoNCmh0bWxPdXQ9IiI7DQoNCnZhciBjb3VudGVyPS0xOw0KdmFyIGh0bWxUYWJVZWJlcj0iIjsNCnN3aXRjaCAobWVocmZhY2hUYWJlbGxlKSB7IA0KICAgIGNhc2UgMTogaHRtbFRhYlVlYmVyPWh0bWxUYWJVZWJlcjEraHRtbFRhYlVlYmVyMitodG1sVGFiVWViZXIzOyAgYnJlYWs7DQogICAgY2FzZSAyOiBodG1sVGFiVWViZXI9aHRtbFRhYlVlYmVyMStodG1sVGFiVWViZXIyK2h0bWxUYWJVZWJlcjJfMStodG1sVGFiVWViZXIzOyBicmVhazsNCiAgICBjYXNlIDM6IGh0bWxUYWJVZWJlcj1odG1sVGFiVWViZXIxK2h0bWxUYWJVZWJlcjIraHRtbFRhYlVlYmVyMl8xK2h0bWxUYWJVZWJlcjIraHRtbFRhYlVlYmVyMzsgYnJlYWs7DQogICAgY2FzZSA0OiBodG1sVGFiVWViZXI9aHRtbFRhYlVlYmVyMStodG1sVGFiVWViZXIyK2h0bWxUYWJVZWJlcjJfMStodG1sVGFiVWViZXIyK2h0bWxUYWJVZWJlcjJfMStodG1sVGFiVWViZXIzOyBicmVhazsNCn07ICAgIA0KDQogLy9ISUVSIFNJTkQgRElFIMKnIFdFUlRFLCBESUUgSU4gREVSIFNDSExFSUZFIEdFRklMVEVSRVQgV0VSJURFTiAtIEplZGUgc3BhbHRlIGVpbmVuIHdlcnQNCiB2YXIgdmFsMTsgIHZhciB2YWwwOw0KIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQogDQogDQogLy9TQ0hMRUlGRSBGw5xSIERJRSBXRVJURQ0KICBmb3IgKHZhciB4PTA7eDxteUxpc3QubGVuZ3RoO3grKyl7DQogICAgICBjb3VudGVyKys7DQogICAgICBpZihteUxpc3RbeF1bMV0hPW51bGwpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbDAgID0gbXlMaXN0W3hdWzBdOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbDEgID0gbXlMaXN0W3hdWzFdDQogICAgIA0KICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbDE9PWZhbHNlKSB7dmFsMT0i4p2MIn0gZWxzZXt2YWwxPSLinIUifSAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSAgDQogICAgIA0KICAgICANCg0KDQoNCg0KICAgICAgICANCiANCiAgICAgIC8vSElFUiBXRVJERU4gRElFIERBVEVOIERFUiBTQ0hMRUlGRSBaVVNBTU1FTkdFU0VUWlQgLSBoYXQgbWFuIG9iZW4gMiBGZWxkZXIgZGVmaW5pZXJ0LCBicmF1Y2h0IG1hbiBoaWVyIDIgV2VydGUNCiAgICANCiAgICAgICAgc3dpdGNoIChtZWhyZmFjaFRhYmVsbGUpIHsgIA0KICAgICAgICAgIGNhc2UgMTogICAgICAgICAgICAgICAgICAgIGh0bWxPdXQ9aHRtbE91dCsiPHRyPjx0ZD4mZW5zcDsiK3ZhbDArIiZlbnNwOzwvdGQ+PHRkIGFsaWduPWNlbnRlcj4mZW5zcDsiK3ZhbDErIiZlbnNwOzwvdGQ+PC90cj4iOyBicmVhazsNCiAgICAgICAgICBjYXNlIDI6ICBpZihjb3VudGVyJTI9PTApICB7aHRtbE91dCA9IGh0bWxPdXQrIjx0cj48dGQ+JmVuc3A7Iit2YWwwKyImZW5zcDs8L3RkPjx0ZCBhbGlnbj1jZW50ZXI+JmVuc3A7Iit2YWwxKyImZW5zcDs8L3RkPiI7IH0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge2h0bWxPdXQgPSBodG1sT3V0KyI8dGQgc3R5bGU9XCJjb2xvcjoiK2h0bWxGYXJiRmVsZGVyc2NocmlmdDIrIlwiPiZlbnNwOyIrdmFsMCsiJmVuc3A7PC90ZD48dGQgIGFsaWduPWNlbnRlciBzdHlsZT1cImNvbG9yOiIraHRtbEZhcmJGZWxkZXJzY2hyaWZ0MisiXCI+JmVuc3A7Iit2YWwxKyImZW5zcDs8L3RkPjwvdHI+Ijt9IGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgIGNhc2UgMzogaWYoY291bnRlciUzPT0wICkgIHtodG1sT3V0ID0gaHRtbE91dCsiPHRyPjx0ZD4mZW5zcDsiK3ZhbDArIiZlbnNwOzwvdGQ+PHRkIGFsaWduPWNlbnRlcj4mZW5zcDsiK3ZhbDErIiZlbnNwOzwvdGQ+IjsgfSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7IGlmKGNvdW50ZXIlMz09MSApICB7IGh0bWxPdXQgPSBodG1sT3V0KyI8dGQgc3R5bGU9XCJjb2xvcjoiK2h0bWxGYXJiRmVsZGVyc2NocmlmdDIrIlwiPiZlbnNwOyIrdmFsMCsiJmVuc3A7PC90ZD48dGQgIGFsaWduPWNlbnRlciBzdHlsZT1cImNvbG9yOiIraHRtbEZhcmJGZWxkZXJzY2hyaWZ0MisiXCI+JmVuc3A7Iit2YWwxKyImZW5zcDs8L3RkPiI7fSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlICAgIHtodG1sT3V0ID0gaHRtbE91dCsiPHRkPiZlbnNwOyIrdmFsMCsiJmVuc3A7PC90ZD48dGQgYWxpZ249Y2VudGVyPiZlbnNwOyIrdmFsMSsiJmVuc3A7PC90ZD48L3RyPiI7fQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gYnJlYWs7DQoNCg0KICAgICAgICAgIGNhc2UgNDogaWYoY291bnRlciU0PT0wKSAge2h0bWxPdXQgPSBodG1sT3V0KyI8dHI+PHRkPiZlbnNwOyIrdmFsMCsiJmVuc3A7PC90ZD48dGQgYWxpZ249Y2VudGVyPiZlbnNwOyIrdmFsMSsiJmVuc3A7PC90ZD4iOyB9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7aWYoY291bnRlciUyPT0xICkgIHsgaHRtbE91dCA9IGh0bWxPdXQrIjx0ZCBzdHlsZT1cImNvbG9yOiIraHRtbEZhcmJGZWxkZXJzY2hyaWZ0MisiXCI+JmVuc3A7Iit2YWwwKyImZW5zcDs8L3RkPjx0ZCAgYWxpZ249Y2VudGVyIHN0eWxlPVwiY29sb3I6IitodG1sRmFyYkZlbGRlcnNjaHJpZnQyKyJcIj4mZW5zcDsiK3ZhbDErIiZlbnNwOzwvdGQ+Ijt9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgICAge2lmKGNvdW50ZXIlMj09MSAmJiBjb3VudGVyJTQ9PTMpICB7IGh0bWxPdXQ9IGh0bWxPdXQrIjx0ZCBzdHlsZT1cImNvbG9yOiIraHRtbEZhcmJGZWxkZXJzY2hyaWZ0MisiXCI+JmVuc3A7Iit2YWwwKyImZW5zcDs8L3RkPjx0ZCAgYWxpZ249Y2VudGVyIHN0eWxlPVwiY29sb3I6IitodG1sRmFyYkZlbGRlcnNjaHJpZnQyKyJcIj4mZW5zcDsiK3ZhbDErIiZlbnNwOzwvdGQ+PC90cj4iO30gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSAgICB7aHRtbE91dCA9IGh0bWxPdXQgPSBodG1sT3V0KyI8dGQ+JmVuc3A7Iit2YWwwKyImZW5zcDs8L3RkPjx0ZD4mZW5zcDsiK3ZhbDErIiZlbnNwOzwvdGQ+Ijt9fQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gYnJlYWs7DQoNCiAgICAgIH0gLy9zd2l0Y2ggZW5kZQ0KDQogICAgIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQogICAgfTsgLy9TY2hsZWlmZW4gZW5kZQ0KICAgICAgDQogICAgICAgICAgIC8vQXVzZ2FiZSDDvGJlciBWSVMgaHRtbCB3aWRnZXQgLSB0YWJlbGxlIGluIGRhdGVucHVua3Qgc2NocmVpYmVuIC0gaHRtbCB0YWJlbGxlIG9obmUgaHRtbCBoZWFkZXIgdW5kIGJvZHkNCiAgICAgICAgICAgIHZhciBodG1sT3V0VklTPSIiOw0KICAgICAgICAgICAgaHRtbFViZXJzY2hyaWZ0ID8gaHRtbE91dFZJUz1odG1sVWViZXIraHRtbFRhYlN0eWxlK2h0bWxUYWJVZWJlcitodG1sT3V0KyI8L3RhYmxlPiIgOiBodG1sT3V0VklTPWh0bWxUYWJTdHlsZStodG1sVGFiVWViZXIraHRtbE91dCsiPC90YWJsZT4iOw0KICAgICAgICAgICAgLy9sb2coaHRtbE91dFZJUyk7DQogICAgICAgICAgICBpZiAoYnJhdWNoZUVpblZJU1dpZGdldCkgc2V0U3RhdGUoZHBWSVMsIGh0bWxPdXRWSVMgKTsNCiANCiAgLy9taXQgb2RlciBvaG5lIMO8YmVyc2NocmlmdA0KICBodG1sVWJlcnNjaHJpZnQgPyBodG1sT3V0PWh0bWxTdGFydCtodG1sVWViZXIraHRtbFRhYlN0eWxlK2h0bWxUYWJVZWJlcitodG1sT3V0K2h0bWxFbmQgOiBodG1sT3V0PWh0bWxTdGFydCtodG1sVGFiU3R5bGUraHRtbFRhYlVlYmVyK2h0bWxPdXQraHRtbEVuZDsNCiAgLy9sb2coaHRtbE91dCk7DQp9IC8vIGZ1bmN0aW9uIGVuZGUNCiANCiAvL2hpZXIgd2lyZCBzY2hsZWlmZSBnZXN0YXJ0ZXQgdW5kIGRhcyBmaWxlIGdlc2NocmllYmVuDQogIA0KIC8vc2NoZWR1bGUoIiovMjAgKiAqICogKiAqIiwgIGZ1bmN0aW9uICgpIHsgIA0KICB3cml0ZUhUTUwoKTsNCiAgaWYgKGJyYXVjaGVFaW5GaWxlKSB7d3JpdGVGaWxlKGhvbWUsIHBhdGggLGh0bWxPdXQsIGZ1bmN0aW9uIChlcnJvcikgeyAvKiBsb2coJ2ZpbGUgd3JpdHRlbicpOyovICB9KTt9DQogLy99KTsgDQogDQoNCg0KDQo=</field>
         <comment pinned="false" h="80" w="160">Beschreibe diese Funktion …</comment>
       </block>
      </xml>
      

      was muss in der javascript-funtion noch getan werden?

      • roter pfeil: der counter ist wichtig und muss in der schleife sein ! zuständig für die anzahl der tabellen nebeneinander
      • grüner pfeil: das schedule auskommentieren
        oranger pfeil: liest die daten aus dem array, welches übergeben worden ist und setzt die val0 und val1 , welche dann angezeigt werden

      Image 13.png

      das ganze sieht dann genauso aus wie ohne blockly: die tabellen sind verschieden zu formatieren

      Image 16.png Image 15.png

      hier gibt es eine bessere version der einkaufs- und todo-liste: https://forum.iobroker.net/post/347479

      alexa todo-liste anzeigen lassen

      Image 3.png
      alexa einkaufsliste
      alexa todo-liste https://forum.iobroker.net/topic/28254/script-alexa-listen-pflegen-und-anzeigen

      man kann sich dadurch schöne html-emails zusenden mit den infos, die in der tabelle sind

      z.b die todoliste als html-email

      Image 13.png Image 12.png

      posted in JavaScript
      liv-in-sky
      liv-in-sky
    • Script: Alexa Listen pflegen und Anzeigen

      dies ist ein script zur anzeige der alexa (echo) einkaufs- und todo-liste in der vis und iqontrol. es können einträge angelegt und gelöscht werden - die tabellen kann verschiedene einstellungen haben (schriftfarbe, hinterrundfarbe, überschrift, nebeneinander-tabellen-anzeige, ...)

      vielen dank an @apollon77 für die integration in den alexa2 adapter

      dieses script entsand aus einem tabellenerzeugungs-script, welches hier als grundlage dient: https://forum.iobroker.net/topic/28021/html-table-für-vis-oder-iqontrol-js-und-blockly

      test5.1.gif


      Image 2.png Image 1.png

      • es muss auch das schedule eingestellt werden - wann werden die daten gelesen - standard jede minute
      • anschliessend werden die tabellen-einstellungen definiert
      • zum löschen wurde das standard list widget und zum anlegen das standard input widget gewählt - diese müssen mit den datenpunkten von euch "gefüttert" werden
      • die tabelle wird über ein standard html widget über binding eingebunden

      [{"tpl":"tplJquiInput","data":{"oid":"controll-own.0.AAATEST.Neues_ObjektTestHTMLAnlegen","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","label":"Input","digits":"0","size":"10","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"asString":true},"style":{"left":"262px","top":"18px","z-index":"200","width":"273px","height":"24px"},"widgetSet":"jqui"},{"tpl":"tplJquiSelectList","data":{"oid":"controll-own.0.AAATEST.TestHTMLAuswahlDelete","g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"{controll-own.0.AAATEST.TestHTMLAuswahlDeleteAuswahl}","texts":"{controll-own.0.AAATEST.TestHTMLAuswahlDeleteWert}","height":"234","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"open":false,"no_style":false},"style":{"left":"300px","top":"50px","width":"253px","height":"20px","text-align":"center","z-index":"200","font-size":"12px","color":"#5ff1ee"},"widgetSet":"jqui"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"{controll-own.0.AAATEST.TestHTML}"},"style":{"left":"18px","top":"34px","color":"","font-family":"SEGMENT","font-size":"large","width":"624px","height":"539px"},"widgetSet":"basic"}]
      

      was kann man alles einstellen:

      • tabelle zentrieren
      • schriftart, schriftgröße
      • größe der zellen beispiele: https://forum.iobroker.net/post/348791
      • tabelle aufteilen - nebeneinander - 1,2,3 oder4
      • farben: hintergrund allgemein, hintergrund tabelle (verlauf), felderfarbe, ...
      • gitterlinien - alle, nur spalten, nur zeilen, keine
      • eine gesamtüberschrift
      • tabellenwert-überschrift
      • schedule - wie oft wird geprüft
      • ob man eine datei möchte - z.b. für iqontrol
      • überschriften der spalten in der tabelle ein- und abschalten

       //@liv-in-sky 2022  14.2.-16:09
       
       const dpPrefix = "javascript."+ instance +".";
      createState("Alexa_Listen.ALEXALists.Einkauf.Anlegen"             , "",{ name: 'Anlegen_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.Einkauf.ALEXAEinkauf"           , { name: 'ALEXAEinkauf_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.Einkauf.AuswahlDeleteWerte"   , { name: 'AuswahlDeleteWert_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.Einkauf.AuswahlDeleteTexte"  , { name: 'AuswahlDeleteTexte_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.Einkauf.Anzahl"  , { name: 'Einkauf_Anzahl_VIS',  type: 'number', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.Einkauf.DeleteALL"  , { name: 'Einkauf_DeleteALL',  type: 'boolean', role: 'switch', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.Einkauf.Refresh"  , { name: 'Refresh',  type: 'boolean', role: 'switch', read:  true,  write: true,});
      //createState("Alexa_Listen.ALEXALists.Einkauf.AuswahlDelete"       , { name: 'AuswahlDelete_VIS',  type: 'number', read:  true,  write: true,});
      
      createState("Alexa_Listen.ALEXALists.Einkauf.AuswahlDelete", {
      name: 'AuswahlDelete',
       role: "state",
       type: "number",
       states: "0:choose ...;1:eeee;2:test1;3:test;",
       min: 0,
       max: 50,
       def: 0,
       read: true,
       write: true});
      
      
      
      
      //HIER WIRD PFAD UND FILENAME DEFINIERT
      const path = "/htmltelegram.html";                   //FIlenamen definieren
      const home ='vis.0'                                 //wo soll das file im iobroker-file-system liegen ? (oder z.b auch iqontrol.meta)
      let   braucheEinFile=false;                          // bei true wird ein file geschrieben - für iqontrol
      let   braucheEinVISWidget=true;                     // bei true wird ein html-tabelle in einen dp geschrieben 
      let   braucheTelegram=true;
      let dpVIS=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.ALEXAEinkauf";                      // dp  für VIS-HTML-Basic-Widget // Datentyp: String
      let dPDELETE=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.AuswahlDelete";                  // Datentyp: Werteliste
      let dPDELETEWert=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.AuswahlDeleteWerte";         // Datentyp: String
      let dPDELETEAuswahl=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.AuswahlDeleteTexte";      // Datentyp: String
      let dpANLEGEN=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.Anlegen";                       // Datentyp: String
      let dpAnzahl=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.Anzahl";                         // Datentyp: Number
      let dpDelAll=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.DeleteALL";                      // Datentyp: Boolean
      let dpRefresh=dpPrefix+"Alexa_Listen.ALEXALists.Einkauf.Refresh";                      // Datentyp: Boolean
      let mySchedule=" */30 * * * * * ";                       
      let sortList=1;                                                                         // SORTIERUNG 1=nach datum; 2 nach Einkauf's
      let mitErstelldatum=false;
      var symbolLink="⚪";                                                                    //  👎  💀 ❌  ⚪  ⚫ ⭕  🔴 🔵
      let farbeSchalterON="blue";
      //---------------------------------------
      
      //HIER DIE SPALTEN ANZAHL DEFINIEREN - jede Spalte einen Wert - in diesem Beispiel sind es 3
      var htmlFeld1='Einkauf';       var Feld1lAlign="left";                     // überschrift Tabellen Spalte1 und  Ausrichtung left or center
      var htmlFeld2='Del';        var Feld2lAlign="center";                      // überschrift Tabellen Spalte2 und  Ausrichtung left,right or center
      var htmlFeld3='Erstellt vor';         var Feld3lAlign="center";                    // überschrift Tabellen Spalte3 und  Ausrichtung left,right or center
      //-----------------------------------
      
      
      //hier werden die styles für die tabelle definiert
      //ÜBERSCHRIFT ÜBER TABELLE
      let   htmlUberschrift=false;                           // mit Überschrift über der tabelle
      let   htmlSignature=false;                              // anstatt der Überscghrift eine signature: - kleiner - anliegend
      const htmlFeldUeber='ALEXA Einkaufsliste';              // Überschrift und Signature
      const htmlFarbUber="white";                         // Farbe der Überschrift
      const htmlSchriftWeite="normal";                       // bold, normal - Fettschrift für Überschrift
      const htmlÜberFontGroesse="18px";                       // schriftgröße überschrift
      //MEHRERE TABELLEN NEBENEINANDER
      let   mehrfachTabelle=1;                              // bis zu 4 Tabellen werden nebeneinander geschrieben-  verkürzt das Ganze, dafür etwas breiter - MÖGLICH 1,2,3,oder 4 !!!
      const trennungsLinie="2";                             //extra trennungslinie bei mehrfachtabellen - evtl auf 0 stellen, wnn htmlRahmenLinien auf none sind
      const farbetrennungsLinie="white";
      const htmlFarbZweiteTabelle="white";                // Farbe der Überschrift bei jeder 2.ten Tabelle
      const htmlFarbTableColorUber="#BDBDBD";               // Überschrift in der tabelle - der einzelnen Spalten
      //ÜBERSCHRIFT SPALTEN
      const UeberSchriftHöhe="35";                          //Überschrift bekommt mehr Raum - darunter und darüber - Zellenhöhe
      const LinieUnterUeberschrift="3";                   // Linie nur unter Spaltenüberschrift - 
      const farbeLinieUnterUeberschrift="white";
      const groesseUeberschrift=16;
      const UeberschriftStyle="normal"                     // möglich "bold"
      //GANZE TABELLE
      let abstandZelle="3";
      let farbeUngeradeZeilen="#000000";                     //Farbe für ungerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let farbeGeradeZeilen="#2E2E2E";                        //Farbe für gerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let weite="auto";                                     //Weite der Tabelle
      let zentriert=true;                                   //ganze tabelle zentriert
      const backgroundAll="#000000";                        //Hintergrund für die ganze Seite - für direkten aufruf oder iqontrol sichtber - keine auswirkung auf vis-widget
      const htmlSchriftart="Helvetica";
      const htmlSchriftgroesse="14px";
      //FELDER UND RAHMEN
      let   UeberschriftSpalten=true;                // ein- oder ausblenden der spatlen-überschriften
      const htmlFarbFelderschrift="lightblue";                  // SchriftFarbe der Felder
      const htmlFarbFelderschrift2="#D8D8D8";                 // SchriftFarbe der Felder für jede 2te Tabelle
      const htmlFarbTableColorGradient1="#424242";          //  Gradient - Hintergrund der Tabelle - Verlauffarbe
      const htmlFarbTableColorGradient2="#424242";          //  Gradient - Hintergrund der Tabelle - ist dieser Wert gleich Gradient1 gibt es keinen verlauf
      const htmlFarbTableBorderColor="grey";             // Farbe des Rahmen - is tdieser gleich den gradienten, sind die rahmen unsichtbar
      let htmlRahmenLinien="none";                            // Format für Rahmen: MÖGLICH: "none" oder "all" oder "cols" oder "rows"
      const htmlSpalte1Weite="auto";                   //  Weite der ersten beiden  Spalten oder z.b. 115px
      
      // HIER NICHTS  ÄNDERN
      
      let borderHelpBottum;
      let borderHelpRight;
      let htmlcenterHelp;
      let htmlcenterHelp2;
      
      if(htmlRahmenLinien=="rows") {borderHelpBottum=1;borderHelpRight=0;}
      if(htmlRahmenLinien=="cols") {borderHelpBottum=0;borderHelpRight=1;}
      if(htmlRahmenLinien=="none") {borderHelpBottum=0;borderHelpRight=0;}
      if(htmlRahmenLinien=="all")  {borderHelpBottum=1;borderHelpRight=1;}
      zentriert ? htmlcenterHelp="auto" : htmlcenterHelp="left";
      zentriert ? htmlcenterHelp2="center" : htmlcenterHelp2="left";
      
      
      const htmlZentriert='<center>'
      const htmlStart=    "<!DOCTYPE html><html lang=\"de\"><head><title>Vorlage</title><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"+
                         "<style> * {  margin: 0;} body {background-color: "+backgroundAll+"; margin: 0 auto;  }"+
                         " p {padding-top: 10px; padding-bottom: 10px; text-align: "+htmlcenterHelp2+"}"+
                        // " div { margin: 0 auto;  margin-left: auto; margin-right: auto;}"+
                         " td { padding:"+abstandZelle+"px; border:0px solid "+htmlFarbTableBorderColor+";  border-right:"+borderHelpRight+"px solid "+htmlFarbTableBorderColor+";border-bottom:"+borderHelpBottum+"px solid "+htmlFarbTableBorderColor+";}"+ 
                         " table { width: "+weite+";  margin: 0 "+htmlcenterHelp+"; border:1px solid "+htmlFarbTableBorderColor+"; border-spacing=\""+abstandZelle+"0px\" ; }"+   // margin macht center
                         "td:nth-child(1) {width: "+htmlSpalte1Weite+"}"+"td:nth-child(2) {width:"+htmlSpalte1Weite+"}"+
                         " </style></head><body> <div>";
      //const htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-weight: bold\">"+htmlFeldUeber+"</p>";                    
      const htmlTabStyle= "<table bordercolor=\""+htmlFarbTableBorderColor+"\" border=\"2px\" cellspacing=\""+abstandZelle+"\" cellpadding=\""+abstandZelle+"\" width=\""+weite+"\" rules=\""+htmlRahmenLinien+"\" style=\"color:"+htmlFarbFelderschrift+";  font-size:"+htmlSchriftgroesse+
                            "; font-family:"+htmlSchriftart+";background-image: linear-gradient(42deg,"+htmlFarbTableColorGradient2+","+htmlFarbTableColorGradient1+");\">";
      const htmlTabUeber1="<tr height=\""+UeberSchriftHöhe+"\" style=\"color:"+htmlFarbTableColorUber+"; font-size: "+groesseUeberschrift+"px; font-weight: "+UeberschriftStyle+" ;  border-bottom: "+LinieUnterUeberschrift+"px solid "+farbeLinieUnterUeberschrift+" \">";
      const htmlTabUeber3="</tr>";
      /*
      table td:first-child {}  //1
      table td:nth-child(2) {} //2
      table td:nth-child(3) {} //3
      table td:last-child {}   //4
      */
      
      const buttonScript =  '<script> function setOnDblClickCustomShop( myvalue ) {	var Self = this; var objID = myvalue;	vis.setValue(myvalue,true);  var2 = \"' + dpPrefix + 'Alexa_Listen.ALEXALists.Einkauf.Refresh\"; vis.setValue(var2,true);  console.log("www")  } </script>'
      
      // const buttonScript =  '<script> function setOnDblClickCustom( myvalue ) {	var Self = this; var objID = myvalue;	Self.servConn.getStates(objID, (error, states) => {  console.log(states);  Self.servConn.setState(objID, true);  }); var2 = \"javascript.0.Alexa_Listen.ALEXALists.Einkauf.Refresh\"; Self.servConn.setState(var2, true); console.log("www")} </script>'
      
      //NICHTS ÄNDERN - abhängig von den oben definierten _Spalten - in diesem Beispiel sind es 3
      
         	var htmlTabUeber2="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+htmlFeld2+"&ensp;</td><td  align="+Feld3lAlign+">&ensp;"+htmlFeld3+"&ensp;</td>";
      var htmlTabUeber2_1="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+"  align="+Feld2lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld2+
                         "&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld3+"&ensp;</td>";
      //------------------------------------------------------
      
      
      var htmlTabUeber="";
      var htmlOut="";
      var mix;
      var counter;
      var warte;
      var myIDArr=[];
      let myDeleterArr;
      var myRememberList="";
      var myTelegram=false;
      var telegramString="telegram.0";
      //HIER SIND DIE  WERTE, DIE IN DER SCHLEIFE GEFILTERET WER%DEN - Jede spalte einen wert - jeder valx muss in dieser schleife gesetzt werden !!
      var val1; var val2; var val0; var val3; var valSort; 
      
      function writeHTML(){
      
      
      htmlOut="";
      
      counter=-1;
      htmlTabUeber="";
      switch (mehrfachTabelle) { 
         case 1: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber3;  break;
         case 2: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
         case 3: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber3; break;
         case 4: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
      };   
      if (!UeberschriftSpalten) {htmlTabUeber=""}
      
      var valID; var myListWerte=""; var myListAuswahl="";
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      //---------hier kommt eure schleife rein counter++, tabelleBind() und tabelleFinish() müssen so integriert bleiben !!!------------------------------
      //---------alle valx werte müssen von euch bestimmt werden - val0,val1,val2 !!!---------------------------------------------------------------------
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      var myArr=[]; var myList=""; var myListArr=[]; myIDArr=[]; myDeleterArr=[];
      
       let myhelerArr=getState("alexa2.0.Lists.SHOPPING_LIST.json").val;
       myDeleterArr.push("alexa2.0.Lists.SHOPPING_LIST.json")
      
      myListArr.push('0'+":"+'choose ...'+";");
                  myListWerte=myListWerte+"choose ..."+";";
                 myListAuswahl=myListAuswahl+(0+";");
                 myIDArr.push("dummy");
      $('alexa2.0.Lists.SHOPPING_LIST.items.*.value').each(function(id, i) {           // hier eigene schleife definierenalexa2.0.Lists.SHOPPING_LIST.items.0f43141e-029c-4860-bcd0-828702b0dc86.value
              
              let ida=id.split('.')
             // log(myhelerArr)
             // log(myhelerArr.includes(ida[5]))
               if(myhelerArr.includes(ida[5])) {
               
                if(!getState(id.replace("value","completed")).val) {
                 val0=getState(id).val;
                 val1=getState(id.replace("value","completed")).val; 
                 val2=valSort=getState(id.replace("value","updatedDateTime")).val; 
                 valID=getState(id.replace("value","id")).val; 
                 myIDArr.push(valID);
                 var yy= (Math.round((new Date()).getTime() / 1000))-Math.round(val2/1000);
                 val2=formatDate(getDateObject(val2), "TT.MM(SS:mm)")
                 val3=(Math.floor( ((yy)/60/60/24) )+"d "+ Math.floor(((yy)/60/60) % 24) +"h "+ Math.floor( ((yy)/60) % 60 )+"m")
              //   if (val1==false) {val1="❌"} else{val1="✅"}
                  let valButton=id.replace("value","#delete")
                  myDeleterArr.push(id.replace("value","#delete"))
                 //log(valButton)
                 val1="<button style\=\"border:none\; background-color\:transparent\; color\:white\; font\-size\:1em\; text\-align:left\" value=\"toggle\" onclick=\"setOnDblClickCustomShop\(\'"+valButton+"\')\">"+symbolLink + "</button> <font color=\""+farbeSchalterON+"\">";
                 myArr.push([val0,val1,val2,val3,valSort]);
                 val0=val0.replace(/,/g,'-');  
                 myListArr.push((i+1)+":"+val0+";");
                 myListWerte=myListWerte+val0+";";
                 myListAuswahl=myListAuswahl+(i+1)+";";
                }} else{ //log('alexa2.0.Lists.SHOPPING_LIST.items.'+ida[5]);
                         deleteObject('alexa2.0.Lists.SHOPPING_LIST.items.'+ida[5], true);
                }
      });
           //  log(myIDArr.toString())
      
              //log (myListArr.toString());
             for (var x=0;x<myListArr.length;x++){
               myList=myList.concat(myListArr[x]);
              // log(myListArr[x]);
               //log(myList);
      
             }
            // log("-----------myList : "+myList)
             if(myList!=myRememberList){
                 myTelegram=true; //log("ist true")
                 setStateDelayed(dPDELETEWert, myListAuswahl,500);        
                 setStateDelayed(dPDELETEAuswahl,  myListWerte,500);
               var timeout = setTimeout(function () {
                 // var obj = getObject(dPDELETE);
                  // log("11---"+myList);
                 // obj.common.states=myList;
                  myRememberList=myList;
                  //log("22---"+myList);
                 extendObject(dPDELETE, {common: {states: myList}});   
               }, 400);
             }
       //SORT
      
         if (sortList==1) {
                       myArr.sort(function (alpha, beta) {
                    if (alpha[4] > beta[4])
                       return -1;
                    if (beta[4] > alpha[4])
                       return 1;
                    return 0;
                   });
                          } else
             {          myArr.sort(function (alpha, beta) {
                    if (alpha[0].toUpperCase() > beta[0].toUpperCase())
                       return 1;
                    if (beta[0].toUpperCase() > alpha[0].toUpperCase())
                       return -1;
                    return 0;
                   });
      
                          }
      
                          telegramString="";
        for (var x=0 ; x<myArr.length ; x++) {
            counter++;
           //HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT - hat man oben 2 Felder definiert, braucht man hier 2 Werte
             val0=myArr[x][0];
             val1=myArr[x][1];
             var val2help=myArr[x][2]
             var val3help=myArr[x][3];
             if (mitErstelldatum) {val2=val3help+" am "+val2help;} else {val2=val3help}
            
               
             if (backgroundAll) {
                telegramString=telegramString+ myArr[x][0] + " - "+myArr[x][2] + '\n';   // "-"+ myArr[x][1]  +
               
             }  
              tabelleBind(); 
        }
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      //--------------------------------------------------Ende der schleife------------------------------------------------------------------------------
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      
            tabelleFinish(); // AB HIER NICHTS ÄNDERN - tabelle fertigstellen
           
      } // function ende
      
      //MAIN:
       
      schedule(mySchedule,  function () { 
        var timeout = setTimeout(function () {
        if(!getState(dpDelAll).val) writeHTML();
          if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
          }, 500);
      
      }); 
       var timeout = setTimeout(function () {
      writeHTML(); 
       }, 2000);                                  //     <tdalign
      
       function tabelleBind(){
         //  counter=counter+mehrfachTabelle;
             switch (mehrfachTabelle) { 
      
               case 1: if(counter%2==0)         {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>"; break;}else    
                                                {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>"; break;}
               case 2: if(counter%4==0){
                          if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} break;
                            }else{
                                      if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} break;}
                                          
               case 3:if(counter%2==0)   {
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //Teil1 c=0
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              "; \"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //Teil 2 c=1
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>";} //Teil 3 c=3
                                                } break;}else{
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} 
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>";}
                                                } break;}                                          
      
      
               case 4:  // counter=counter+8;
                         if(counter%8==0)   {
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+ farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } // teil1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} //teil 4
                                                                        else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"  align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}else{
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //teil 1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} // teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} // teil 4
                                                                        else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}                                    
              } //switch ende
      
      }
      
      function tabelleFinish() {
      
      switch (mehrfachTabelle) {  
             case 1:    break;
      
             case 2:    
                        if(counter%2==0)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>');
                      
                        break;
      
             case 3:   if(counter%3==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%3==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");        
                       if(counter%3==0)      htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                     
                        break;
             case 4:   if(counter%4==3)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%4==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                       if(counter%4==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");    
                       if(counter%4==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");      
                       break; }
           
               var htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: "+htmlÜberFontGroesse+"; font-weight:"+htmlSchriftWeite+ "\">"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</p>"; 
             var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 70%; text-align: right;\" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>";
              
              if (!htmlSignature) htmlUnter="";
                //Ausgabe über VIS html widget - tabelle in datenpunkt schreiben - html tabelle ohne html header und body
                 var htmlOutVIS="";
               //  htmlUberschrift ? htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>" : htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>";
                  if (htmlUberschrift) 
                      { zentriert ? htmlOutVIS=htmlZentriert+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript : htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript ;
      
                    } else {
                     zentriert ?  htmlOutVIS=htmlZentriert+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript :  htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript;
      
                       }
                       
      
        // log("bin raus aus tabelleBind");
                 if (braucheEinVISWidget) setState(dpVIS, htmlOutVIS );
      
       var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 80%;  text-align: center; \" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>"
      
       if (!htmlSignature) htmlUnter="";
        var htmlEnd="</table>"+htmlUnter+"</div></body>";
       //mit oder ohne überschrift - zentriert oder links
      htmlUberschrift ? htmlOut=htmlStart+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd : htmlOut=htmlStart+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd;
       //log(htmlOut);
       setState(dpANLEGEN,"");
       setState(dpAnzahl,(counter+1));
       setState(dPDELETE,0);
      
       
       if(myTelegram && braucheTelegram){ 
           //log("sende");
           myTelegram=false;
           
          sendTo('telegram.0', {
              
         text: (telegramString),
         type: 'text'
         });
      
      telegramString="";
      
      }
      } // function ende
      
      setTimeout(function () {
      on({id: dPDELETE, ack: false, change: "ne"}, function (obj) { 
        
         let a=getState(dPDELETE).val;
         if (a!=0){
         let toDelete=myIDArr[getState(dPDELETE).val];
         var stateHelp="alexa2.0.Lists.SHOPPING_LIST.items."+toDelete+".#delete"
         setState(stateHelp,true);
         var timeout = setTimeout(function () {
         writeHTML(); }, 4000);
       
      
         }
        // log("1+bin im on !!!+++!"+a+stateHelp)
         });
      
         on({id: dpANLEGEN, ack: false, change: "ne"}, function (obj) { 
            // log(getState(dpANLEGEN).val+"----aa");
             if(getState(dpANLEGEN).val!="") {
          setState("alexa2.0.Lists.SHOPPING_LIST.#New",getState(dpANLEGEN).val)
             var timeout = setTimeout(function () {
         writeHTML(); }, 2000);
             } 
             
         });
      
             on({id: dpRefresh, ack: false, change: "any"}, function (obj) { 
             //log(getState(dpANLEGEN).val+"----refresh");
             var timeout2 = setTimeout(function () {
         writeHTML(); }, 4000);
            // }
         
         });  
      
            on({id: myDeleterArr, ack: false, change: "any"}, function (obj) { 
             //log(getState(dpANLEGEN).val+"----refresh");
             var timeout2 = setTimeout(function () {
         writeHTML(); }, 4000);
        
            // }
         
         });
      
         
           on({id: dpDelAll, ack: false,val: true}, function (obj) { 
       let i;
       for (i=0;i<myIDArr.length;i++) {//log("hier : "+myIDArr[i]);
         if (myIDArr[i]!="dummy") {
         let toDelete=myIDArr[i];
            setTimeout( function timer(){
            var stateHelp="alexa2.0.Lists.SHOPPING_LIST.items."+toDelete+".#delete"
         log("Statehelp: "+stateHelp)
         setState(stateHelp,true);
         }, i*2500 );
      
        
         }
         }
         log(i.toString())
         var timeout = setTimeout(function () {
              setState(dpDelAll,false);
              writeHTML(); }, (1+myIDArr.length)*1500);
        
        // log(stateHelp)
      
       });
      
      }, 5000);
      
      
      
      
      




       //@liv-in-sky 2022  14.2.-16:09
      
       const dpPrefix = "javascript."+ instance +".";
      createState("Alexa_Listen.ALEXALists.ToDo.Anlegen"             , "",{ name: 'Anlegen_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.ToDo.ALEXAToDo"           , { name: 'ALEXAToDo_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.ToDo.AuswahlDeleteWerte"   , { name: 'AuswahlDeleteWert_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.ToDo.AuswahlDeleteTexte"  , { name: 'AuswahlDeleteTexte_VIS',  type: 'string', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.ToDo.Anzahl"  , { name: 'ToDo_Anzahl_VIS',  type: 'number', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.ToDo.DeleteALL"  , { name: 'ToDo_DeleteALL',  type: 'boolean', role: 'switch', read:  true,  write: true,});
      createState("Alexa_Listen.ALEXALists.ToDo.Refresh"  , { name: 'Refresh',  type: 'boolean', role: 'switch', read:  true,  write: true,});
      //createState("Alexa_Listen.ALEXALists.ToDo.AuswahlDelete"       , { name: 'AuswahlDelete_VIS',  type: 'number', read:  true,  write: true,});
      
      createState("Alexa_Listen.ALEXALists.ToDo.AuswahlDelete", {
      name: 'AuswahlDelete',
       role: "state",
       type: "number",
       states: "0:choose ...;1:eeee;2:test1;3:test;",
       min: 0,
       max: 50,
       def: 0,
       read: true,
       write: true});
      
      
      
      
      //HIER WIRD PFAD UND FILENAME DEFINIERT
      const path = "/htmltelegram.html";                   //FIlenamen definieren
      const home ='vis.0'                                 //wo soll das file im iobroker-file-system liegen ? (oder z.b auch iqontrol.meta)
      let   braucheEinFile=false;                          // bei true wird ein file geschrieben - für iqontrol
      let   braucheEinVISWidget=true;                     // bei true wird ein html-tabelle in einen dp geschrieben 
      let   braucheTelegram=false;
      let dpVIS=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.ALEXAToDo";                      // dp  für VIS-HTML-Basic-Widget // Datentyp: String
      let dPDELETE=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.AuswahlDelete";                  // Datentyp: Werteliste
      let dPDELETEWert=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.AuswahlDeleteWerte";         // Datentyp: String
      let dPDELETEAuswahl=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.AuswahlDeleteTexte";      // Datentyp: String
      let dpANLEGEN=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.Anlegen";                       // Datentyp: String
      let dpAnzahl=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.Anzahl";                         // Datentyp: Number
      let dpDelAll=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.DeleteALL";                      // Datentyp: Boolean
      let dpRefresh=dpPrefix+"Alexa_Listen.ALEXALists.ToDo.Refresh";                      // Datentyp: Boolean
      let mySchedule=" * * * * * ";                       
      let sortList=1;                                                                         // SORTIERUNG 1=nach datum; 2 nach ToDo's
      let mitErstelldatum=false;
      var symbolLink="⚪";                                                                    //  👎  💀 ❌  ⚪  ⚫ ⭕  🔴 🔵
      let farbeSchalterON="blue";
      //---------------------------------------
      
      //HIER DIE SPALTEN ANZAHL DEFINIEREN - jede Spalte einen Wert - in diesem Beispiel sind es 3
      var htmlFeld1='ToDo';       var Feld1lAlign="left";                     // überschrift Tabellen Spalte1 und  Ausrichtung left or center
      var htmlFeld2='Del';        var Feld2lAlign="center";                      // überschrift Tabellen Spalte2 und  Ausrichtung left,right or center
      var htmlFeld3='Erstellt vor';         var Feld3lAlign="center";                    // überschrift Tabellen Spalte3 und  Ausrichtung left,right or center
      //-----------------------------------
      
      
      //hier werden die styles für die tabelle definiert
      //ÜBERSCHRIFT ÜBER TABELLE
      let   htmlUberschrift=false;                           // mit Überschrift über der tabelle
      let   htmlSignature=false;                              // anstatt der Überscghrift eine signature: - kleiner - anliegend
      const htmlFeldUeber='ALEXA ToDosliste';              // Überschrift und Signature
      const htmlFarbUber="white";                         // Farbe der Überschrift
      const htmlSchriftWeite="normal";                       // bold, normal - Fettschrift für Überschrift
      const htmlÜberFontGroesse="18px";                       // schriftgröße überschrift
      //MEHRERE TABELLEN NEBENEINANDER
      let   mehrfachTabelle=1;                              // bis zu 4 Tabellen werden nebeneinander geschrieben-  verkürzt das Ganze, dafür etwas breiter - MÖGLICH 1,2,3,oder 4 !!!
      const trennungsLinie="2";                             //extra trennungslinie bei mehrfachtabellen - evtl auf 0 stellen, wnn htmlRahmenLinien auf none sind
      const farbetrennungsLinie="white";
      const htmlFarbZweiteTabelle="white";                // Farbe der Überschrift bei jeder 2.ten Tabelle
      const htmlFarbTableColorUber="#BDBDBD";               // Überschrift in der tabelle - der einzelnen Spalten
      //ÜBERSCHRIFT SPALTEN
      const UeberSchriftHöhe="35";                          //Überschrift bekommt mehr Raum - darunter und darüber - Zellenhöhe
      const LinieUnterUeberschrift="3";                   // Linie nur unter Spaltenüberschrift - 
      const farbeLinieUnterUeberschrift="white";
      const groesseUeberschrift=16;
      const UeberschriftStyle="normal"                     // möglich "bold"
      //GANZE TABELLE
      let abstandZelle="3";
      let farbeUngeradeZeilen="#000000";                     //Farbe für ungerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let farbeGeradeZeilen="#2E2E2E";                        //Farbe für gerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let weite="auto";                                     //Weite der Tabelle
      let zentriert=true;                                   //ganze tabelle zentriert
      const backgroundAll="#000000";                        //Hintergrund für die ganze Seite - für direkten aufruf oder iqontrol sichtber - keine auswirkung auf vis-widget
      const htmlSchriftart="Helvetica";
      const htmlSchriftgroesse="14px";
      //FELDER UND RAHMEN
      let   UeberschriftSpalten=true;                // ein- oder ausblenden der spatlen-überschriften
      const htmlFarbFelderschrift="lightblue";                  // SchriftFarbe der Felder
      const htmlFarbFelderschrift2="#D8D8D8";                 // SchriftFarbe der Felder für jede 2te Tabelle
      const htmlFarbTableColorGradient1="#424242";          //  Gradient - Hintergrund der Tabelle - Verlauffarbe
      const htmlFarbTableColorGradient2="#424242";          //  Gradient - Hintergrund der Tabelle - ist dieser Wert gleich Gradient1 gibt es keinen verlauf
      const htmlFarbTableBorderColor="grey";             // Farbe des Rahmen - is tdieser gleich den gradienten, sind die rahmen unsichtbar
      let htmlRahmenLinien="none";                            // Format für Rahmen: MÖGLICH: "none" oder "all" oder "cols" oder "rows"
      const htmlSpalte1Weite="auto";                   //  Weite der ersten beiden  Spalten oder z.b. 115px
      
      // HIER NICHTS  ÄNDERN
      
      let borderHelpBottum;
      let borderHelpRight;
      let htmlcenterHelp;
      let htmlcenterHelp2;
      
      if(htmlRahmenLinien=="rows") {borderHelpBottum=1;borderHelpRight=0;}
      if(htmlRahmenLinien=="cols") {borderHelpBottum=0;borderHelpRight=1;}
      if(htmlRahmenLinien=="none") {borderHelpBottum=0;borderHelpRight=0;}
      if(htmlRahmenLinien=="all")  {borderHelpBottum=1;borderHelpRight=1;}
      zentriert ? htmlcenterHelp="auto" : htmlcenterHelp="left";
      zentriert ? htmlcenterHelp2="center" : htmlcenterHelp2="left";
      
      
      const htmlZentriert='<center>'
      const htmlStart=    "<!DOCTYPE html><html lang=\"de\"><head><title>Vorlage</title><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"+
                         "<style> * {  margin: 0;} body {background-color: "+backgroundAll+"; margin: 0 auto;  }"+
                         " p {padding-top: 10px; padding-bottom: 10px; text-align: "+htmlcenterHelp2+"}"+
                        // " div { margin: 0 auto;  margin-left: auto; margin-right: auto;}"+
                         " td { padding:"+abstandZelle+"px; border:0px solid "+htmlFarbTableBorderColor+";  border-right:"+borderHelpRight+"px solid "+htmlFarbTableBorderColor+";border-bottom:"+borderHelpBottum+"px solid "+htmlFarbTableBorderColor+";}"+ 
                         " table { width: "+weite+";  margin: 0 "+htmlcenterHelp+"; border:1px solid "+htmlFarbTableBorderColor+"; border-spacing=\""+abstandZelle+"0px\" ; }"+   // margin macht center
                         "td:nth-child(1) {width: "+htmlSpalte1Weite+"}"+"td:nth-child(2) {width:"+htmlSpalte1Weite+"}"+
                         " </style></head><body> <div>";
      //const htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-weight: bold\">"+htmlFeldUeber+"</p>";                    
      const htmlTabStyle= "<table bordercolor=\""+htmlFarbTableBorderColor+"\" border=\"2px\" cellspacing=\""+abstandZelle+"\" cellpadding=\""+abstandZelle+"\" width=\""+weite+"\" rules=\""+htmlRahmenLinien+"\" style=\"color:"+htmlFarbFelderschrift+";  font-size:"+htmlSchriftgroesse+
                            "; font-family:"+htmlSchriftart+";background-image: linear-gradient(42deg,"+htmlFarbTableColorGradient2+","+htmlFarbTableColorGradient1+");\">";
      const htmlTabUeber1="<tr height=\""+UeberSchriftHöhe+"\" style=\"color:"+htmlFarbTableColorUber+"; font-size: "+groesseUeberschrift+"px; font-weight: "+UeberschriftStyle+" ;  border-bottom: "+LinieUnterUeberschrift+"px solid "+farbeLinieUnterUeberschrift+" \">";
      const htmlTabUeber3="</tr>";
      /*
      table td:first-child {}  //1
      table td:nth-child(2) {} //2
      table td:nth-child(3) {} //3
      table td:last-child {}   //4
      */
      
      const buttonScript =  '<script> function setOnDblClickCustomToDo( myvalue ) {	var Self = this; var objID = myvalue;	vis.setValue(myvalue,true);  var2 = \"' + dpPrefix + 'Alexa_Listen.ALEXALists.ToDo.Refresh\"; vis.setValue(var2,true);  console.log("www")  } </script>'
      
      // const buttonScript =  '<script> function setOnDblClickCustom( myvalue ) {	var Self = this; var objID = myvalue;	Self.servConn.getStates(objID, (error, states) => {  console.log(states);  Self.servConn.setState(objID, true);  }); var2 = \"javascript.0.Alexa_Listen.ALEXALists.ToDo.Refresh\"; Self.servConn.setState(var2, true); console.log("www")} </script>'
      
      //NICHTS ÄNDERN - abhängig von den oben definierten _Spalten - in diesem Beispiel sind es 3
      
         	var htmlTabUeber2="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+htmlFeld2+"&ensp;</td><td  align="+Feld3lAlign+">&ensp;"+htmlFeld3+"&ensp;</td>";
      var htmlTabUeber2_1="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+"  align="+Feld2lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld2+
                         "&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld3+"&ensp;</td>";
      //------------------------------------------------------
      
      
      var htmlTabUeber="";
      var htmlOut="";
      var mix;
      var counter;
      var warte;
      var myIDArr=[];
      let myDeleterArr;
      var myRememberList="";
      var myTelegram=false;
      var telegramString="";
      //HIER SIND DIE  WERTE, DIE IN DER SCHLEIFE GEFILTERET WER%DEN - Jede spalte einen wert - jeder valx muss in dieser schleife gesetzt werden !!
      var val1; var val2; var val0; var val3; var valSort; 
      
      function writeHTML(){
      
      
      htmlOut="";
      
      counter=-1;
      htmlTabUeber="";
      switch (mehrfachTabelle) { 
         case 1: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber3;  break;
         case 2: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
         case 3: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber3; break;
         case 4: htmlTabUeber=htmlTabUeber1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
      };   
      if (!UeberschriftSpalten) {htmlTabUeber=""}
      
      var valID; var myListWerte=""; var myListAuswahl="";
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      //---------hier kommt eure schleife rein counter++, tabelleBind() und tabelleFinish() müssen so integriert bleiben !!!------------------------------
      //---------alle valx werte müssen von euch bestimmt werden - val0,val1,val2 !!!---------------------------------------------------------------------
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      var myArr=[]; var myList=""; var myListArr=[]; myIDArr=[]; myDeleterArr=[];
      
      let myhelerArr=getState("alexa2.0.Lists.TO_DO.json").val;
        myDeleterArr.push("alexa2.0.Lists.TO_DO.json")
      myListArr.push('0'+":"+'choose ...'+";");
                  myListWerte=myListWerte+"choose ..."+";";
                 myListAuswahl=myListAuswahl+(0+";");
                 myIDArr.push("dummy");
      
      
      $('alexa2.0.Lists.TO_DO.items.*.value').each(function(id, i) {           // hier eigene schleife definierenalexa2.0.Lists.SHOPPING_LIST.items.0f43141e-029c-4860-bcd0-828702b0dc86.value
      
             let ida=id.split('.')
             // log(myhelerArr)
             // log(myhelerArr.includes(ida[5]))
               if(myhelerArr.includes(ida[5])) {
               
                if(!getState(id.replace("value","completed")).val) {    
                 val0=getState(id).val;
                 val1=getState(id.replace("value","completed")).val; 
                 val2=valSort=getState(id.replace("value","updatedDateTime")).val; 
                 valID=getState(id.replace("value","id")).val; 
                 myIDArr.push(valID);
                 var yy= (Math.round((new Date()).getTime() / 1000))-Math.round(val2/1000);
                 val2=formatDate(getDateObject(val2), "TT.MM(SS:mm)")
                 val3=(Math.floor( ((yy)/60/60/24) )+"d "+ Math.floor(((yy)/60/60) % 24) +"h "+ Math.floor( ((yy)/60) % 60 )+"m")
              //   if (val1==false) {val1="?"} else{val1="?"}
                  let valButton=id.replace("value","#delete")
                 //log(valButton)
                 val1="<button style\=\"border:none\; background-color\:transparent\; color\:white\; font\-size\:1em\; text\-align:left\" value=\"toggle\" onclick=\"setOnDblClickCustomToDo\(\'"+valButton+"\')\">"+symbolLink + "</button> <font color=\""+farbeSchalterON+"\">";
                 myArr.push([val0,val1,val2,val3,valSort]);
                 val0=val0.replace(/,/g,'-');  
                 myListArr.push((i+1)+":"+val0+";");
                 myListWerte=myListWerte+val0+";";
                 myListAuswahl=myListAuswahl+(i+1)+";";
             }} else{ //log('alexa2.0.Lists.SHOPPING_LIST.items.'+ida[5]);
                         deleteObject('alexa2.0.Lists.TO_DO.items.'+ida[5], true);
                }
      });
             //log(myIDArr.toString())
      
              //log (myListArr.toString());
             for (var x=0;x<myListArr.length;x++){
               myList=myList.concat(myListArr[x]);
              // log(myListArr[x]);
               //log(myList);
      
             }
            // log("-----------myList : "+myList)
             if(myList!=myRememberList){
                 myTelegram=true; //log("ist true")
                 setStateDelayed(dPDELETEWert, myListAuswahl,500);        
                 setStateDelayed(dPDELETEAuswahl,  myListWerte,500);
               var timeout = setTimeout(function () {
               //  var obj = getObject(dPDELETE);
                  // log("11---"+myList);
                 // obj.common.states=myList;
                  myRememberList=myList;
                  //log("22---"+myList);
                extendObject(dPDELETE, {common: {states: myList}});  
               }, 400);
             }
       //SORT
      
         if (sortList==1) {
                       myArr.sort(function (alpha, beta) {
                    if (alpha[4] > beta[4])
                       return -1;
                    if (beta[4] > alpha[4])
                       return 1;
                    return 0;
                   });
                          } else
             {          myArr.sort(function (alpha, beta) {
                    if (alpha[0].toUpperCase() > beta[0].toUpperCase())
                       return 1;
                    if (beta[0].toUpperCase() > alpha[0].toUpperCase())
                       return -1;
                    return 0;
                   });
      
                          }
      
                          telegramString="";
        for (var x=0 ; x<myArr.length ; x++) {
            counter++;
           //HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT - hat man oben 2 Felder definiert, braucht man hier 2 Werte
             val0=myArr[x][0];
             val1=myArr[x][1];
             var val2help=myArr[x][2]
             var val3help=myArr[x][3];
             if (mitErstelldatum) {val2=val3help+" am "+val2help;} else {val2=val3help}
            
               
             if (backgroundAll) {
                telegramString=telegramString+ myArr[x][0] + " - "+myArr[x][2] + '\n';   // "-"+ myArr[x][1]  +
               
             }  
              tabelleBind(); 
        }
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      //--------------------------------------------------Ende der schleife------------------------------------------------------------------------------
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      
            tabelleFinish(); // AB HIER NICHTS ÄNDERN - tabelle fertigstellen
           
      } // function ende
      
      //MAIN:
       
      schedule(mySchedule,  function () { 
        var timeout = setTimeout(function () {
        if(!getState(dpDelAll).val) writeHTML();
          if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
          }, 500);
      
      }); 
       var timeout = setTimeout(function () {
      writeHTML(); 
       }, 2000);                                  //     <tdalign
      
       function tabelleBind(){
         //  counter=counter+mehrfachTabelle;
             switch (mehrfachTabelle) { 
      
               case 1: if(counter%2==0)         {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>"; break;}else    
                                                {  htmlOut=htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>"; break;}
               case 2: if(counter%4==0){
                          if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} break;
                            }else{
                                      if(counter%2==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} break;}
                                          
               case 3:if(counter%2==0)   {
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //Teil1 c=0
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              "; \"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //Teil 2 c=1
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>";} //Teil 3 c=3
                                                } break;}else{
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} 
                                                      else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td></tr>";}
                                                } break;}                                          
      
      
               case 4:  // counter=counter+8;
                         if(counter%8==0)   {
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+ farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } // teil1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} //teil 4
                                                                        else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"  align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}else{
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //teil 1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} // teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} // teil 4
                                                                        else    {htmlOut  = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}                                    
              } //switch ende
      
      }
      
      function tabelleFinish() {
      
      switch (mehrfachTabelle) {  
             case 1:    break;
      
             case 2:    
                        if(counter%2==0)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>');
                      
                        break;
      
             case 3:   if(counter%3==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%3==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");        
                       if(counter%3==0)      htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                     
                        break;
             case 4:   if(counter%4==3)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%4==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                       if(counter%4==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");    
                       if(counter%4==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");      
                       break; }
           
               var htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: "+htmlÜberFontGroesse+"; font-weight:"+htmlSchriftWeite+ "\">"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</p>"; 
             var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 70%; text-align: right;\" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>";
              
              if (!htmlSignature) htmlUnter="";
                //Ausgabe über VIS html widget - tabelle in datenpunkt schreiben - html tabelle ohne html header und body
                 var htmlOutVIS="";
               //  htmlUberschrift ? htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>" : htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>";
                  if (htmlUberschrift) 
                      { zentriert ? htmlOutVIS=htmlZentriert+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript : htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript ;
      
                    } else {
                     zentriert ?  htmlOutVIS=htmlZentriert+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript :  htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+ buttonScript;
      
                       }
                       
      
        // log("bin raus aus tabelleBind");
                 if (braucheEinVISWidget) setState(dpVIS, htmlOutVIS );
      
       var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 80%;  text-align: center; \" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((parseFloat((new Date().getTime())))), "SS:mm:ss");+"</div>"
      
       if (!htmlSignature) htmlUnter="";
        var htmlEnd="</table>"+htmlUnter+"</div></body>";
       //mit oder ohne überschrift - zentriert oder links
      htmlUberschrift ? htmlOut=htmlStart+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd : htmlOut=htmlStart+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd;
       //log(htmlOut);
       setState(dpANLEGEN,"");
       setState(dpAnzahl,(counter+1));
       setState(dPDELETE,0);
      
       
       if(myTelegram && braucheTelegram){ 
           //log("sende");
           myTelegram=false;
           
          sendTo('telegram.0', {
              
         text: (telegramString),
         type: 'text'
         });
      
      telegramString="";
      
      }
      } // function ende
      
      
      setTimeout(function () {
          
      on({id: dPDELETE, ack: false, change: "ne"}, function (obj) { 
      
         let a=getState(dPDELETE).val;
         if (a!=0){
         let toDelete=myIDArr[getState(dPDELETE).val];
         var stateHelp="alexa2.0.Lists.TO_DO.items."+toDelete+".#delete"
         setState(stateHelp,true);
         var timeout = setTimeout(function () {
         writeHTML(); }, 4000);
         }
        // log("1+bin im on !!!+++!"+a+stateHelp)
         });
      
         on({id: dpANLEGEN, ack: false, change: "ne"}, function (obj) { 
             //log(getState(dpANLEGEN).val+"----aa");
             if(getState(dpANLEGEN).val!="") {
          setState("alexa2.0.Lists.TO_DO.#New",getState(dpANLEGEN).val)
             var timeout = setTimeout(function () {
         writeHTML(); }, 2000);
             } 
             
         });
      
             on({id: dpRefresh, ack: false, change: "any"}, function (obj) { 
             //log(getState(dpANLEGEN).val+"----refresh");
             var timeout2 = setTimeout(function () {
         writeHTML(); }, 4000);
            // }
         
         });
      
       on({id: myDeleterArr, ack: false, change: "any"}, function (obj) { 
             //log(getState(dpANLEGEN).val+"----refresh");
             var timeout2 = setTimeout(function () {
         writeHTML(); }, 4000);
        
            // }
         
         });
      
         
           on({id: dpDelAll, ack: false,val: true}, function (obj) { 
             let i;
       for (i=0;i<myIDArr.length;i++) {//log("hier : "+myIDArr[i]);
         if (myIDArr[i]!="dummy") {
         let toDelete=myIDArr[i];
                setTimeout( function timer(){
         var stateHelp="alexa2.0.Lists.TO_DO.items."+toDelete+".#delete"
        // log("Statehelp: "+stateHelp)
         setState(stateHelp,true);
           }, i*1500);
         }
         }
         var timeout = setTimeout(function () {
              setState(dpDelAll,false);
              writeHTML(); }, (1+myIDArr.length)*1500);
        
        // log(stateHelp)
      
       });
      
      }, 5000);
      
      
      
      
      
      




      https://forum.iobroker.net/post/469286

      smart57.gif

      posted in JavaScript
      liv-in-sky
      liv-in-sky
    • Unifi WLAN Script 2 mit Anwesenheitskontrolle

      hier ein script für das ansteuern des unifi-controllers - der unifi adapter hat einen sehr großen datenfluß und sehr viele datenpunkte - das script arbeitet selbständig und benötigt den adapter nicht. (danke an @thewhobox und @dslraser)

      es gibt eine version des scriptes, welche nur die uaps von vorher definierten clients ausliest und als datenpunkte speichert - es werden keine tabellen oder sonstiges angelegt: https://forum.iobroker.net/post/405654

      was kann es:

      feature variable-info
      WLAN ein und ausschalten (z.b. Gäste-WLAN) geht immer
      AP Led's schalten geht immer- nur site-wide - nicht einzeln!e ap's
      Speedtest Daten nur mit security gateway hardware
      Internet Verbindung www online ? - nur mit security gateway hardware
      rudimentärer datenverbrauch nur mit unifi security hardware - sammelt täglichen und monatlichen datenverbrauch
      Alarme gehen immer - werden alle 3 script-zyklen upgedatet
      anwesenheitskontrolle mit datenpunkte für die clients anwesenheit=true
      voucherauflistung in tabellenform über ein html-widget für vis vouchers=true
      voucherauflistung in tabellenform für iqontrol vouchers,iqontrol=true
      vouchers erstellen es gibt im script setting eine variable zum erstellen von standard vouchers (iqontrol, vis) oder man kann neue anlegen (nur vis)
      vouchers löschen es gibt 2 datenpunkte für seleqtList-Widget, dadurch einfache vis anbindung (iqontrol, vis)
      clientauflistung in tabellenform über ein html-widget für vis anwesenheit=true
      clientauflistung in tabellenform für iqontrol anwesenheit,iqontrol=true es gibt verschiedene tabellen dafür: alle clients (mit disconnected), nur disconnected, nur clients am lan, nur clients am WLAN
      wahlweise hostname oder aliasname anzeige der angemeldeten clients alias=true
      health des WLANs geht immer - wird nur alle 3 abfragezyklen abgefragt - kommen daher erst verspätet beim ersten aktivieren des scripts
      minimale Info's zu AP's variable apInfo = true - welcher Controller ist zuständig, ist der AP adoptet (einbezogen), Ip des AP's, Satisfaction, Modelbezeichnung, abruf der daten nur alle 3 zyklen - kommen daher erst verspätet beim ersten aktivieren des scripts
      apInfo anzeige für vis in html tabellenform und für iqontrol (über popup)
      mehrer installierte netzwerke z.b gästenetzwerk geht immer
      AccessPoint und Switches es können WLAN und LAN Geräte angezeigt werden
      Farben definieren, Schriftart Farben für Vis oder IQontrol können eingestellt werden
      script zyklus das script schreibt nicht alle daten bei jedem zyklus - die health, ap daten werden nur alle 3 zyklen geschrieben - es gibt einen datenpunkt dafür, dieser datenpunkt ist für die vis gedacht - so kann man sich anzeigen, wann der zyklus durch ist - zählt von 1 bis 3
      scriptpause das script macht eine pause beim umschalten eines netzwerkes - die ap's werden umgeschaltet - es gibt einen datenpunkt, der diese pause anzeigt - z.b in meiner vis: ich ändere bei dieser pause die schriftfarbe für die cleints und die rahmen blinke rot - siehe bild am ende
      rudimentärer filter für client anzeige es gibt einen filter für die clientanzeige - es werden nur clientsangezeigt, welche den inhalt vom datenpunkt "Client_WhiteList" beinhalten
      SSID unsichtbar schalten einfache integration - die werte können vom zustand in der unifi datenbank abweichen - wird nicht abgefragt

      was ist wichtig :

      einstellungen im oberen teil des scripts info
      npm zusatzmodule es müssen 3 npm zusatzmodule in der javascript instanz eingetragen - und dadurch installiert - werden: fs, request, request-promise-native
      login daten und port für controller und der site-name const unifi_username, unifi_passwort und unifi_controller WICHTIG: der sitename muss aus der URL im browser, bei aufruf der controller-web-seite, entnommen werden !!!https://forum.iobroker.net/post/323789
      konstante wlan-name(n) mit wlan-id const wifis - wie man die ID des netzwerkes rausfindet steht hier: https://forum.iobroker.net/post/295086
      konstante ap-alias const apName - der Aliasnamen für die AP's und Switches- hat nichts mit den Aliasnamen im Controller zu tun - wird nur für das script gebraucht - können frei gewählt werden
      blacklist für clients const blackList
      clients via AP's kontrolle const checkConnType - darin werden clientnamen angegeben, bei denen man den aktuellen AccessPoint braucht - es werden dafür eigene Datenpunkte angelegt
      länge der pause beim umschalten eines netzwerkes clientPauseConst - ist für die länge der scriptpause verantwortlich - wird benötigt, da beim ein oder ausschalten eines netzwerkes (auch nur das gästenetzwerk) alle ap's einen neustart machen ( proviosioniert) und dadurch die anwesenheitskontrolle beeinflußt werden könnte. z.b brauchen tasmota-geflashte clients lange, bis sie wieder online sind - die anwesenheitskontrolle könnte auch zur überwachung solcher geräte genutzt werden
      abfrageinterval: "abfragezyklus" und "abfrageoffset" abfragezyklus definiert, in welchen interval die abfragen stattfinden sollen (20sek ist eingestellt) - damit erreicht man eine sehr schnelle aktualisierung beim anmelden eines clients im WLAN - beim abmelden des clients muss der abfrageoffset mit berücksichtigt werden (15 sek ist eingestellt) - wählt man den abfrageoffset zu klein, kann es sein, dass bei einem wechsel eines clients (handy) zu einem anderen accesspoint (ap) eine auslogmeldung kommt - bei meinem system bekomme ich nach ungefähr 30 sek einen anmeldevorgang gemeldet und nach ca 45-50 sek einen abmeldevorgang
      gewünschte features auf true setzen iqontrol, anwesenheit,vouchers,apInfo - was nicht benötigt wird, bitte nicht aktivieren -> resourcen sparen - der iqontroladapter muss installiert sein, wenn man iqontrol im script auf true setzt
      aliasnamen für clients aliasname - möchte man lieber, die im unifi-controller definierten aliasnamen für die clients nutzen, muß in jedem client im controller ein alias definiert sein damit alle clients im script sichtbar werden - oder es werden nur aliase für bestimmte geräte angegeben - dann ist der rest nicht sichtbar - wichtig weil: was nicht sichtbar ist, kann nicht zur anwesenheitskontrolle genutzt werden und : der standard - aliasname=false - nimmt den aliasnamen, wenn einer existiert, ansonsten den hostnamen
      ip clients liste nach IP adresse sortiert anzeigen sortedByIP für die clientliste in iqontrol und vis
      disconnected clients als erstes anzeigen disConClientsFirst für die clintliste in iqontrol und vis
      farben für iqontrol und vis
      datenpunkte im admin es wird ein ordner in der javascript instanz erzeugt - unter umständen wird ein zweiter ordner angelegt, zum sichern "dauerhafter daten". WLANUnifi kann gelöscht werden (z.b. bei einem update des scripts; WLANUnifiHelp sollte nicht gelöscht werden, darin sind Daten gespeichert, die wieder gebraucht werden (z.b datenverbrauch messung)

      iqontrol
      kann über ein popup eingebunden werden. im feld html eintragen: mögliche files, die zur verfügung stehen:

      für clients:

      <iframe width="100% "height="100% "frameborder="0" src="/iqontrol.meta/htmlclients.html"></iframe
      

      für vouchers:

      <iframe width="100% "height="100% "frameborder="0" src="/iqontrol.meta/htmlvoucher.html"></iframe
      

      für health und /oder apInfo

      <iframe width="100% "height="100% "frameborder="0" src="/iqontrol.meta/htmlinfo.html"></iframe
      

      zusätzlich : nur LAN geräte : htmllan.html ; nur WLAN geräte: htmlwlan.html ; nur disconnected geräte: htmldisc.html ;

      voucher erstellung:

      • unter dem datenpunkt Wifi_Vouchers-CODES.A_New_Voucher kann ein voucher angelegt werden - die anzahl, dauer und multiuse müssen eingegeben werden - alle anderen sind optional
        oder es gibt datenpunkte zum erstellen einer valueliste, um vorgefertigte (standard) vouchers anzulegen (selectValuelist-widget)
      werte zusatz
      die dauer in minuten z.b. 120
      die anzahl der vouchers wie viele davon sollen angelegt werden
      multiuse 0=immer wieder ;1 ist nur einmal und jede andere zahl für n-mal also 5 für 5 mal
      upload und download speed begrenzung in kbyte - eingabe ohne einheiten
      mb_begrenzung volumen begrenzung in MByte - eingabe ohne einheiten

      Voucher löschen
      direkt über Datenpunkte:

      • zuerst ID des vouchers eintragen :"WLANUnifi.Wifi_Vouchers-CODES.A_Delete_Voucher.Voucher_ID"
        -anschliessend "WLANUnifi.Wifi_Vouchers-CODES.A_Delete_Voucher.Delete" auf true setzen

      oder über VIS:
      dazu gibt es zwei datenpunkte
      -WLANUnifi.Wifi_Vouchers_CodeList - "texte" mit binding in selectValueList widget eintragen
      -WLANUnifi.Wifi_Vouchers_List - "werte" mit binding in selectValueList widget eintragen

      beim update auf eine neue scriptversion:

      • script stoppen
      • script kopieren und einfügen (meist reicht es, nur unter der eigenene konfiguration zu kopieren und einzufügen - damit man nicht jedesmal die konfiguration (login, wlan) neu machen muss
      • alle datenpunkte löschen (wichtig_)
      • script starten

      aktuelle version:

      14.09.19
      16.09.19
      17.09.19 - voucher löschen mit iqontrol
      18.09.19 - WLAN problem - mehr zeit bevor false bei clients
      22.09.19 - einfacheres löschen und erzeugen von vouchers in der vis, unbenennung einiger datenpunktnamen (datenpunkte löschen vor scriptstart)
      23.09.19 - AP Led's site-wide ein- und ausschalten
      27.09.19 - AP LAodAVG für 1,5 und 15 Minuten
      3.10.19 - Alarm, Clients-ohne-Namen, LAN clients >> switch und usg integration
      8.10.19- js-controllerv2 update, Eingabe mit Punkt im Alias, Leerzeichen ersetzen, Scriptlogik verbessert, zusätz. setting ohne Clients, fehlende IP abfangen, eigenes Widget "letzter wechsel im netzwerk für VIS, ...
      9.10.19 fehler behebung bei missingName datenpunkt, scriptpause bei wifiumschaltung geändert
      10.10.19 neue sotierung clients, speedtest-vorbereitung
      11.10.19 neue sotierung clients, speedtest und internet-verbindung
      22.10.19 kleine fehler bei LAN geräten bereinigt, Fehler mit "IP fehlt bereinigt, einzelne iqontrol und vis tables für anzeige von LAN,WLAN clients
      30.10.19 besseres log bei fehleranalyse "sprunghafte" clients (syslog); neue datenpunkte für verbrauchte datenmenge ins internet (nur mit usg)
      9.11.2019 verbesserung - clients ohne namen, neues setting - clients anzeige: Ip zuerst
      06.12.19 verbesserung fehlersuche und fehler mit security gateway und clientanzeige
      08.12.19 fehler bei anzeige von überwachten cients bereinigen
      14.12.19 unifi bug ausgleichen - SSID unsuchtbarschalten
      18.12.19 bug beim starten ohne datenpunkte behoben
      30.12.19 bug ohne anwesenheit begradigt

      unifi-main-script-30-12-19.txt

      Problembehandlung bei anwesenheitskontrolle mit zu schnellen bzw. falschen wertänderungen der clients: https://forum.iobroker.net/post/301328

      beispiel für vis im nächsten bild:es wurden die 3 tabellen aus den datenpunkten , die voucherlöschung (code auswählbar durch SelectValueList-widget siehe https://forum.iobroker.net/post/300367 ) und vouchererzeugung (auswählbar durch SelectValueList-widget)eingerichtet

      gelber pfeil - gerät nicht angemeldet
      oranger pfeil: gerät nicht angemeldet und nicht in controller gelistet - aber ist in script registriert und damit false
      weißer pfeil: valuelist für erzeugung von vouchers
      grüner pfeil: valuelist löschen existierender vouchers
      roter pfeil: alarme
      mehr infos über die anzeige in der vis: https://forum.iobroker.net/post/305865
      Image 7.png

      mittlerweile gibt es 3 zusätzliche html-tables für die vis und iqontrol: einzelne anzeigen für LAN oder WLAN geräte und einen table für die disconnected clients (nicht mehr im controller sichtbar aber als datenpunkt vorahnden)

      Image 3.png
      Image 1.png

      zyklus anzeige :

      zyklus.gif

      scriptpause beim umschalten der wifis: zb.wlan - in dieser pause werden keine client abfragen gemacht - da die ap's neustarten und sich alle clients neu anmelden werden
      scriptpause.gif

      posted in JavaScript
      liv-in-sky
      liv-in-sky
    • IP Devices im Netzwerk - HTML Tabelle vis, Iqontrol

      und noch eine tabelle - es werden alle geräte des netzwerkes gesucht und angezeigt - script wurde zusammen mit @homoran entwickelt - nur für einen netzwerkbereich nutzbar

      NEUE VERSION auf GITHUB: https://github.com/liv-in-sky/nmap-ip-iobroker-script

      • netzwerk wird mit externen befehl gescannt - dazu muss das tool nmap installiert werden - in linux,windows

      • das tool nmap wird unter linux auf der console mit "apt-get install nmap" installiert - für windows das tool downloaden und im standardverzeichnis installieren https://nmap.org/download.html

      • in linux muss in der iobroker datei /etc/sudoers.d/iobroker ein eintrag geschrieben werden https://forum.iobroker.net/post/375519 - der befhel nmap muss mit root ausgeführt werden !!!

      • im setting der javascript instanz das exec. anklicken https://forum.iobroker.net/post/409294

      • in windows habe ich dem user, der iobroker installiert hat, volle rechte auf das standardverzeichnis der nmap installation gegeben wichtig: es muss der befehl "nmap --iflist" ausgeführt werden - dmit bekommt man die aktuelle ethernetschnittstelle heraus ( "up") - diese wird unter const onlyWinEthernetIF eingetragen

      • damit man eine anzeige bekommt, muss ein datenpunkt (zeichenkette, string) angelgt werden, der anschliessend auch im script eingetragen werden muss (dpVis) - im settingbereich des scriptes
        die anderen settings müssen im script auch angeglichen werden z.b. dns server, domainname und der ipbereich

      • die aliasnamen in myDeviceNames: android, amazon-geräte werden bei fritzbox-dnsserver-nutzung mit dem eigennamen des gerätes angezeigt - ist ein fritzbox problem seit fritzos 7

      • es ist möglich eine datei zu erzeugen um die tabelle in iqontrol zu nutzen oder in der vis mit einem iframe einzubinden - standardmäßig nutzt man das standard-html-widget in der vis mit einem binding auf dpVis https://forum.iobroker.net/post/375754

      • symbole, farben tabellensettings sind alle individuell einstellbar!

      • docker bzw. synology-user: https://forum.iobroker.net/post/376631 ihr müßt im ersten exec befehl das "sudo -u root nmap " mit nur "nmap" ersetzen - siehe auch https://forum.iobroker.net/post/376920

      • die javascript adapter version sollte 4.3.x sein oder höher !!!

      AApossis (18).gif


      1581282746893-nmap_finetuning.png

      Anleitung für mehrere links pro server ist hier: https://forum.iobroker.net/post/597255

      in den ersten 20 zeilen sind die wichtigen settings - bitte alle durchgehen !!!

      //@liv-in-sky Januar 2021 13.3-19:00
      
      
      //HIER WIRD PFAD UND FILENAME DEFINIERT
      // @ts-ignore
      const path = "/htmlip.html";                   //FIlenamen definieren
      const home ='vis.0'                                 //wo soll das file im iobroker-file-system liegen ? (oder z.b auch iqontrol.meta)
      let   braucheHostDaten=false;
      let   braucheEinFile=false;                          // bei true wird ein file geschrieben
      let   braucheEinVISWidget=true;                     // bei true wird ein html-tabelle in einen dp geschrieben - siehe nächste zeile
      let   braucheMaterialDesignWidget=false;             // bei true wird ein html-tabelle in einen dp geschrieben - MUSS ANGELEGT WERDEN !!!
      let   braucheMaterialDesignWidgetList=false;        // bei true wird ein html-tabelle in einen dp geschrieben - MUSS ANGELEGT WERDEN !!!
      let dpHost="0_userdata.0.Tabellen.IPDevices_HostDaten"         //WICHTIG wenn braucheHostDaten auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget // string
      let dpSort="0_userdata.0.Tabellen.IPDevicesSort";           //WICHTIG - Sortierung
      let dpVIS="0_userdata.0.Tabellen.IPDevices"         //WICHTIG wenn braucheMaterialDesignWidgetList auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget // string
      let dpMaterialTabelWidget="0_userdata.0.Tabellen.IPDevices_MD_Table"         //WICHTIG wenn braucheMaterialDesignWidget auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget // string
      let dpMaterialListWidget="0_userdata.0.Tabellen.IPDevices_MD_List"         //WICHTIG wenn braucheEinVISWidget auf true gesetzt !!  dp zusätzlich für VIS-HTML-Basic-Widget // string
      let pfadBilderMaterialWidget="/vis.0/armin/img/"                       // PFAD zu den bildern, die in die vis geladen wurden/
      let mySchedule=" */15 * * * * ";                       //jede minute  -  nicht unter eine minute gehen -besser 3 oder 5 minuten nutzen !!!
      const domainName="fritz.box";                  // domainname in der fritzbox definiert
      const ipbereich="192.168.178.0/24";           //  gilt nicht für windows
      const dnsServer="192.168.178.1"               // gilt nicht für windows
      let mysortiereClient=1;                     //1 nach client 2 nach ip 
      const waitTime=500;                        // falls längere zeit keine daten kommen - diesen wert erhöhn um 5000 (ms)
      const lastZellColorSetting="lightgreen"      // farbe der zusammenfassung in der letzten zelle der tabelle 
      const oerationSystemchange=false;              // false ist linux, true ist windows
      const onlyWinEthernetIF="eth0"                // nur windows über befehl "nmap --iflist" herausfinden
      const farbeNichtErreichbar="#819FF7" //"#FFBF00";         // farbe für devices, die gerade nicht online sind
      const styleNichtErreichbar="i";             // möglich i=schräg, b ist fett und span ist normal - nur eines  davon !!!
      const kuerzungNamen=23;                      // länge der namen kürzen
      const materialD_IP_erreichbar="#D8D8D8";        // material design farbe der ip adresse bei erreichbaren klient
      const materialD_IP_nichtErreichbar="#F7819F";    // material design farbe der ip adresse bei nicht erreichbaren klient
      const htmlGragient=[150,30,70];                          // einstellung des gradienten
      
      //hier eintragen für die übersetzung der standardnamen - aliase - rechte seite wird statt linker  angezeigt - die beispiele kann man raus löschen
      // BITTE AUF DIE KOMMAs ACHTEN
      const myDeviceNames={ "192.168.178.24"  :"HF Küche Licht",     // ein leeres array wird so erzeugt: const myDeviceNames=[];
                           "192.168.178.118" :"Echo Beige",
                           "192.168.178.100" :"Echo Plus",
                           "192.168.178.50"  :"Echo Dot Zimmer",
                           "192.168.178.68"  :"HF Desk Haupt"
      
      }
      
      const myDeviceNamesNew= [{"ip" : "192.168.178.10", "name" : "Proxmox", "link" : "https://192.168.178.10:8006/", "kat":"server", "linkFirstName":"WEB"},
                              {"ip" : "192.168.178.157", "name" : "sqltulla", "link" : "http://192.168.178.157:8181/settings", "kat":"server", "linkFirstName":"TAUTULLA" },
                              {"ip" : "192.168.178.145", "name" : "pi-hole", "link" : "http://192.168.178.145/admin", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.59", "name" : "iobroker", "link" : "http://192.168.178.59:8081/#tab-objects", "kat":"server","linkFirstName":"OBJ", "morelinks":[{"TAB":"http://192.168.178.59:8081/#tab-logs"},{"INS":"http://192.168.178.59:8081/#tab-instances"}] },
                              {"ip" : "192.168.178.199", "name" : "NAS-FILE-Server", "link" : "", "kat":"server" },
                              {"ip" : "192.168.178.72", "name" : "AXHD60", "link" : "http://192.168.178.72", "kat":"server" },
                              {"ip" : "192.168.178.173", "name" : "ESP-KAMERA1", "link" : "http://192.168.178.173", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.117", "name" : "ESP-SWITCH-CAM1", "link" : "http://192.168.178.117", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.174", "name" : "ESP-KAMERA2", "link" : "http://192.168.178.174", "kat":"server", "linkFirstName":"WEB" },
                               {"ip" : "192.168.178.172", "name" : "ESP-SWITCH-CAM2", "link" : "http://192.168.178.172", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.175", "name" : "ESP-KAMERA3", "link" : "http://192.168.178.175", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.171", "name" : "ESP-SWITCH-CAM3", "link" : "http://192.168.178.171", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.191", "name" : "ESP-KAMERA4", "link" : "http://192.168.178.191", "kat":"server", "linkFirstName":"WEB" },
                               {"ip" : "192.168.178.135", "name" : "ESP-SWITCH-CAM4", "link" : "http://192.168.178.135", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.192", "name" : "ESP-KAMERA5", "link" : "http://192.168.178.192", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.83", "name" : "ESP-SWITCH-CAM5", "link" : "http://192.168.178.83", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.73", "name" : "MediaPadT5", "link" : "", "kat":"tablet" },
                              {"ip" : "192.168.178.148", "name" : "Echo Dot 3", "link" : "", "kat":"echo_dot3" },
                              {"ip" : "192.168.178.29", "name" : "TrekStor13", "link" : "", "kat":"tablet" },
                              {"ip" : "192.168.178.151", "name" : "FireTab7", "link" : "", "kat":"tablet" },
                              {"ip" : "192.168.178.201", "name" : "VPN Netzwerk", "link" : "", "kat":"vpn" },
                              {"ip" : "192.168.178.56", "name" : "FireHDStick", "link" : "", "kat":"firetvstick" },
                              {"ip" : "192.168.178.41", "name" : "FireTVStick", "link" : "", "kat":"firetvstick" },
                              {"ip" : "192.168.178.37", "name" : "FireTVStick1", "link" : "", "kat":"firetvstick" },
                              {"ip" : "192.168.178.33", "name" : "SonoffS26Alexa", "link" : "", "kat":"sonoff26" },
                              {"ip" : "192.168.178.124", "name" : "Galaxy-S9", "link" : "", "kat":"handygal" },
                              {"ip" : "192.168.178.28", "name" : "Google-Home-Mini", "link" : "", "kat":"googlemini" },
                              {"ip" : "192.168.178.81", "name" : "GalaxyTabA16", "link" : "", "kat":"tablet" },
                              {"ip" : "192.168.178.21", "name" : "GoSund 2 Matrix", "link" : "", "kat":"gosund111" },
                              {"ip" : "192.168.178.155", "name" : "GoSund 3 Freezer", "link" : "", "kat":"gosund111" },
                              {"ip" : "192.168.178.126", "name" : "Matrix Büro", "link" : "", "kat":"matrix" },
                              {"ip" : "192.168.178.168", "name" : "Matrix Küche", "link" : "", "kat":"matrix" },
                              {"ip" : "192.168.178.147", "name" : "MatrixTV", "link" : "", "kat":"matrix" },
                              {"ip" : "192.168.178.80", "name" : "MatrixCPU", "link" : "", "kat":"matrix" },
                              {"ip" : "192.168.178.150", "name" : "Gosund 1", "link" : "", "kat":"gosund111" },
                              {"ip" : "192.168.178.77", "name" : "SteckdoseAlexa", "link" : "", "kat":"fragezeichen" },
                              {"ip" : "192.168.178.235", "name" : "MotionEye", "link" : "http://192.168.178.235:8765/", "kat":"server", "linkFirstName":"EYE"  },
                              {"ip" : "192.168.178.142", "name" : "AdGuard", "link" : "http://192.168.178.142/", "kat":"server" },
                              {"ip" : "192.168.178.1", "name" : "DragonRoot", "link" : "http://192.168.178.1", "kat":"fritzbox", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.129", "name" : "WLEDRund", "link" : "http://192.168.178.129/", "kat":"server", "linkFirstName":"WEB"},
                              {"ip" : "192.168.178.132", "name" : "WLEDLang", "link" : "http://192.168.178.132/", "kat":"server", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.88", "name" : "DragonRoot-Dect", "link" : "http://192.168.178.88", "kat":"fritzbox" },
                              {"ip" : "192.168.178.74", "name" : "LGwebOSTV", "link" : "", "kat":"LG_TV_2" },
                              {"ip" : "192.168.178.139", "name" : "MCU Thermometer", "link" : "http://192.168.178.139", "kat":"sonoff" },
                               {"ip" : "192.168.178.140", "name" : "EASY1", "link" : "http://192.168.178.140", "kat":"sonoff", "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.163", "name" : "EASY2", "link" : "http://192.168.178.163", "kat":"sonoff" , "linkFirstName":"WEB"},
                              {"ip" : "192.168.178.141", "name" : "BridgeSensateTemp", "link" : "", "kat":"" },
                              {"ip" : "192.168.178.101", "name" : "DashPlayboy", "link" : "", "kat":"" },
                              {"ip" : "192.168.178.86", "name" : "DashSakrotan", "link" : "", "kat":"" },
                              {"ip" : "192.168.178.95", "name" : "Sonoff2-Distance", "link" : "http://192.168.178.95", "kat":"sonoff" }, 
                              {"ip" : "192.168.178.14", "name" : "Plex", "link" : "http://192.168.178.14:32400/web/index.html", "kat":"server" , "linkFirstName":"WEB" },
                              {"ip" : "192.168.178.156", "name" : "EchoShow5", "link" : "", "kat":"Echo-Show-5" }
                              ]
      
      var symbolOK="✔️";     // auch möglich: ="✅"   🟩   ✔️  🌎
      var symbolKO="🔵" //"🔔";     //z.b. auch "<font color=\"red\"><b>X</b>" für ein rotes kreuz  oder : ="❌"  ⚪   🟢 ⚫ ⭕  🔴 🔵  🚫 ⏱ 💀 👍 👎 📑 💲 👀 😡 🟥 ⬜ 🧊 💬 🗑️ 🔔
      var symbolWARN="ℹ️";    // ="⚠️" oder info: "ℹ️"
      var symbolKO_MD="🟥"    //symbol für "nicht erreichbar" im MaterialDesign Widget
      var symbolLink="🌎";
      var externalOhneInfo=false;  //noch nicht integriert
      //---------------------------------------
      
      //HIER DIE SPALTEN ANZAHL DEFINIEREN - jede Spalte einen Wert - in diesem Beispiel sind es 3
      var htmlFeld1='Name';      var Feld1lAlign="left";                     // überschrift Tabellen Spalte1 und  Ausrichtung left,right or center
      var htmlFeld2='IP';        var Feld2lAlign="left";                      // überschrift Tabellen Spalte2 und  Ausrichtung left,right or center
      var htmlFeld3='Status';         var Feld3lAlign="center";                    // überschrift Tabellen Spalte3 und  Ausrichtung left,right or center
      //-----------------------------------
      
      
      //ÜBERSCHRIFT ÜBER TABELLE
      let   htmlUberschrift=true;                           // mit Überschrift über der tabelle
      let   htmlSignature=false;                              // anstatt der Überscghrift eine signature: - kleiner - anliegend
      const htmlFeldUeber='IP Devices List';              // Überschrift und Signature
      const htmlFarbUber="white";                         // Farbe der Überschrift
      const htmlSchriftWeite="normal";                       // bold, normal - Fettschrift für Überschrift
      const htmlÜberFontGroesse="18px";                       // schriftgröße überschrift
      //MEHRERE TABELLEN NEBENEINANDER
      let   mehrfachTabelle=3;                              // bis zu 4 Tabellen werden nebeneinander geschrieben-  verkürzt das Ganze, dafür etwas breiter - MÖGLICH 1,2,3,oder 4 !!!
      const trennungsLinie="2";                             //extra trennungslinie bei mehrfachtabellen - evtl auf 0 stellen, wnn htmlRahmenLinien auf none sind
      const farbetrennungsLinie="white";
      const htmlFarbZweiteTabelle="white";                // Farbe der Überschrift bei jeder 2.ten Tabelle
      const htmlFarbTableColorUber="#BDBDBD";               // Überschrift in der tabelle - der einzelnen Spalten
      //ÜBERSCHRIFT SPALTEN
      const UeberSchriftHoehe="35";                          //Überschrift bekommt mehr Raum - darunter und darüber - Zellenhöhe
      const LinieUnterUeberschrift="2";                   // Linie nur unter Spaltenüberschrift - 
      const farbeLinieUnterUeberschrift="lightblue";
      const groesseUeberschrift=16;
      const UeberschriftStyle="normal"                     // möglich "bold"
      //GANZE TABELLE
      let abstandZelle="2";
      let farbeUngeradeZeilen="#000000";                     //Farbe für ungerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let farbeGeradeZeilen="#151515";                        //Farbe für gerade Zeilenanzahl - Hintergrund der Spaltenüberschrift bleibt bei htmlFarbTableColorGradient1/2
      let weite="1200";                                     //Weite der Tabelle
      let zentriert=true;                                   //ganze tabelle zentriert
      const backgroundAll="#000000";                        //Hintergrund für die ganze Seite - für direkten aufruf oder iqontrol sichtber - keine auswirkung auf vis-widget
      const htmlSchriftart="Ubuntu-Regular"   ///"Helvetica";
      const htmlSchriftgroesse="14px";
      //FELDER UND RAHMEN
      let   UeberschriftSpalten=true;                // ein- oder ausblenden der spatlen-überschriften
      const htmlFarbFelderschrift="#D8D8D8";                  // SchriftFarbe der Felder  #D8D8D8
      const htmlFarbFelderschrift2="#D8D8D8";                 // SchriftFarbe der Felder für jede 2te Tabelle
      const htmlFarbTableColorGradient1="#424242";          //  Gradient - Hintergrund der Tabelle - Verlauffarbe
      const htmlFarbTableColorGradient2="#424242";          //  Gradient - Hintergrund der Tabelle - ist dieser Wert gleich Gradient1 gibt es keinen verlauf
      const htmlFarbTableBorderColor="grey";             // Farbe des Rahmen - is tdieser gleich den gradienten, sind die rahmen unsichtbar
      let htmlRahmenLinien="none";                            // Format für Rahmen: MÖGLICH: "none" oder "all" oder "cols" oder "rows"
      const htmlSpalte1Weite="cols";                   //  Weite der ersten beiden  Spalten oder z.b. 115px
      
      // HIER NICHTS  ÄNDERN ---------------------SETTING ENDE ----------------------------------------
      // HIER NICHTS  ÄNDERN ---------------------SETTING ENDE ----------------------------------------
      // HIER NICHTS  ÄNDERN ---------------------SETTING ENDE ----------------------------------------
      
      
      
      const dpPrefix = "javascript."+ instance +".";
      let borderHelpBottum;
      let borderHelpRight;
      let htmlcenterHelp;
      let htmlcenterHelp2;
      
      if(htmlRahmenLinien=="rows") {borderHelpBottum=1;borderHelpRight=0;}
      if(htmlRahmenLinien=="cols") {borderHelpBottum=0;borderHelpRight=1;}
      if(htmlRahmenLinien=="none") {borderHelpBottum=0;borderHelpRight=0;}
      if(htmlRahmenLinien=="all")  {borderHelpBottum=1;borderHelpRight=1;}
      zentriert ? htmlcenterHelp="auto" : htmlcenterHelp="left";
      zentriert ? htmlcenterHelp2="center" : htmlcenterHelp2="left";
      
      let searchMe="<div><input class=\"myinputclassnmap\" type=\"search\" id=\"searchnmap\" placeholder=\"Filter by Item\"></div>";
      const htmlZentriert="<style>  .myinputclassnmap {border: 1px solid; border-color: "+htmlFarbTableColorGradient2+"; margin-bottom: 20px; color: "+htmlFarbTableColorUber+"; height: 30px;background-image: linear-gradient("+htmlGragient[0]+"deg,"+htmlFarbTableColorGradient2+" "+htmlGragient[1]+"%,"+htmlFarbTableColorGradient1+" "+htmlGragient[2]+"%); font-family:"+htmlSchriftart+"\ }"+
                          "</style><center>"
      const htmlStart=    "<!DOCTYPE html><html lang=\"de\"><head><title>Vorlage</title><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"+
                         "<style> * {  margin: 0;} body {background-color: "+backgroundAll+"; margin: 0 auto;  }"+
                         " p {padding-top: 10px; padding-bottom: 10px; text-align: "+htmlcenterHelp2+"}"+
                        // " div { margin: 0 auto;  margin-left: auto; margin-right: auto;}"+
                         " td { padding:"+abstandZelle+"px; border:0px solid "+htmlFarbTableBorderColor+";  border-right:"+borderHelpRight+"px solid "+htmlFarbTableBorderColor+";border-bottom:"+borderHelpBottum+"px solid "+htmlFarbTableBorderColor+";}"+ 
                         " table { width: "+weite+";  margin: 0 "+htmlcenterHelp+"; border:0px solid "+htmlFarbTableBorderColor+"; border-spacing=\""+abstandZelle+"0px\" ; }"+   // margin macht center
                         "td:nth-child(1) {width: "+htmlSpalte1Weite+"}"+"td:nth-child(2) {width:"+htmlSpalte1Weite+"}"+
                         " </style></head><body>"; // <div>";
      //const htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-weight: bold\">"+htmlFeldUeber+"</p>";                    
      const htmlTabStyle= "<table bordercolor=\""+htmlFarbTableBorderColor+"\" border=\"1px\" cellspacing=\""+abstandZelle+"\" cellpadding=\""+abstandZelle+"\" width=\""+weite+"\" rules=\""+htmlRahmenLinien+"\" style=\"color:"+htmlFarbFelderschrift+";  font-size:"+htmlSchriftgroesse+
                            "; font-family:"+htmlSchriftart+";background-image: linear-gradient(42deg,"+htmlFarbTableColorGradient2+","+htmlFarbTableColorGradient1+")\">";
      const htmlTabUeber1="<tr height=\""+UeberSchriftHoehe+"\" style=\"color:"+htmlFarbTableColorUber+"; font-size: "+groesseUeberschrift+"px; font-weight: "+UeberschriftStyle+" ;  border-bottom: "+LinieUnterUeberschrift+"px solid "+farbeLinieUnterUeberschrift+" \">";
      const htmlTabUeber3="</tr>";
      
      //NICHTS ÄNDERN - abhängig von den oben definierten _Spalten - in diesem Beispiel sind es 3
      
      var htmlTabUeber2=  "<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+htmlFeld2+"&ensp;</td><td  align="+Feld3lAlign+">&ensp;"+htmlFeld3+"&ensp;</td>";
      var htmlTabUeber2_1="<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld1+"&ensp;</td><td width="+htmlSpalte1Weite+"  align="+Feld2lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld2+
                         "&ensp;</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbZweiteTabelle+"\">&ensp;"+htmlFeld3+"&ensp;</td>";
      
      const buttonScript =  '<script> function setOnOtherValue22(myval) {	var Self = this;	vis.setValue(\"0_userdata.0.Tabellen.IPDevicesSort\",myval); console.log("nmap: "+myval) }'
                           +'$( "button.myButt" ).click(function() {  $(".myButt" ).slideUp(); setTimeout(function() { $( ".mySpan" ).text(\"wait ...\")}, 1000);  });'    //$this.prop("border", "10px");
                           + `var allRows = $("[class*='nmapspecial']");  $("input#searchnmap").on("keydown keyup", function() {  allRows.hide();  $("tr:contains('" + $(this).val() + "')").show();});`
                           +'</script>' 
      //------------------------------------------------------
      var rootcount=true;
      var myObjOld=[];
      var myJsonWidget=[]; 
      var myJsonWidget2=[];
      var htmlTabUeber="";
      var htmlOut="";
      var mix;
      var valButton=1;
      var myObj;
      var counter;
      //HIER SIND DIE  WERTE, DIE IN DER SCHLEIFE GEFILTERET WER%DEN - Jede spalte einen wert - jeder valx muss in dieser schleife gesetzt werden !!
      var val1; var val0; var val2;
      var json1; var json2; var json3; var json4; var json5; var json6;
      let myObjExtra=[];
      let laeuftSchon=false;
      var hostDaten="";
      
      async function  writeHTML(){
         laeuftSchon=true;
         mysortiereClient=getState(dpSort).val;
      let htmlTabUeber2_2= "<td width="+htmlSpalte1Weite+" align="+Feld1lAlign+">&ensp;"+"<span class=\"mySpan\"></span>"+"<button class=\"myButt\" style\=\" border-radius: 4px; border:1px solid; background-color\: "+"transparent"+"\; color: "+htmlFarbTableColorUber+"; font\-size\:1em\; text\-align:left\" value=\"toggle\" onclick=\"setOnOtherValue22\(\'"+"1"+"\')\">"+htmlFeld1+"</button>"+"&ensp;</td>"+
                          "<td width="+htmlSpalte1Weite+" align="+Feld2lAlign+">&ensp;"+"<span class=\"mySpan\"></span>"+"<button class=\"myButt\" style\=\" border-radius: 4px; border:1px solid; background-color\: "+"transparent"+"\; color: "+htmlFarbTableColorUber+"; font\-size\:1em\; text\-align:left\" value=\"toggle\" onclick=\"setOnOtherValue22\(\'"+"2"+"\')\">"+htmlFeld2+"</button>"+"&ensp;</td>"+
                          "<td  align="+Feld3lAlign+">&ensp;"+"<span class=\"mySpan\"></span>"+"<button class=\"myButt\" style\=\" border-radius: 4px; border:1px solid; background-color\: "+"transparent"+"\; color: "+htmlFarbTableColorUber+"; font\-size\:1em\; text\-align:left\" value=\"toggle\" onclick=\"setOnOtherValue22\(\'"+"1"+"\')\">"+htmlFeld3+"</button>"+"&ensp;</td>";
      
      htmlOut="";
      
      counter=-1;
      htmlTabUeber="";
      switch (mehrfachTabelle) { 
         case 1: htmlTabUeber=htmlTabUeber1+htmlTabUeber2_2+htmlTabUeber3;  break;
         case 2: htmlTabUeber=htmlTabUeber1+htmlTabUeber2_2+htmlTabUeber2_1+htmlTabUeber3; break;
         case 3: htmlTabUeber=htmlTabUeber1+htmlTabUeber2_2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber3; break;
         case 4: htmlTabUeber=htmlTabUeber1+htmlTabUeber2_2+htmlTabUeber2_1+htmlTabUeber2+htmlTabUeber2_1+htmlTabUeber3; break;
      };   
      if (!UeberschriftSpalten) {htmlTabUeber=""}
      
      
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      //---------hier kommt eure schleife rein counter++, tabelleBind() und tabelleFinish() müssen so integriert bleiben !!!------------------------------
      //---------alle valx werte müssen von euch bestimmt werden - val0,val1,val2 !!!---------------------------------------------------------------------
      //--------------------------------------------------------------------------------------------------------------------------------------------------
      hostDaten="";
      var myData="xxxxx"; 
      let myArr=[];
      myObjExtra=[];
      
      async function holeData() {
           return new Promise((resolve) => {
      if(oerationSystemchange == false){
      exec("sudo -u root nmap -sPR --dns-servers "+dnsServer+" "+ipbereich  , async function (error, result, stderr) {
         myData=result
       //  setState("0_userdata.0.Tabellen.IPDeviceERROR", result)
         // console.log(result);
          resolve()
      });} else {
      
      exec((['"C:\\\\Program Files (x86)\\\\Nmap\\\\nmap" ','-sPR  -e ',onlyWinEthernetIF,' --dns-servers ',dnsServer,' ',ipbereich].join('')), function (error, result, stderr) {
         myData=result
          resolve()
      });}
      });
      }
      
      await holeData().then( async function () {  //})
      //let timeout = setTimeout(function () {
      // myData=getState("0_userdata.0.Tabellen.DeviceIPFake").val       //   FÜR TEST
      ////////////////////////////////log(myData)
      
       if (!myData.includes("xxxx")) {
      
      
      
      var myTimeScanArr=myData.match(/(scanned in) (\d+\.\d+ seconds)/g); //log(myTimeScan)
      
      // myArr=myData.match(/for\s+([A-Za-z0-9-_]+).f[^(]+\((\d+.\d+.\d+.\d+)\)|(fritz.\w+)\s+\((\d+.\d+.\d+.\d+)\)|(\d+.\d+.\d+.\d+)$/g)
      
      myArr=myData.match(/for\s+([A-Za-z0-9-_]+).f[^(]+\((\d+\.\d+\.\d+\.\d+)\)|(fritz\.\w+)\s+\((\d+\.\d+\.\d+\.\d+)\)|(\d+\.\d+\.\d+\.\d+)$/gm)
       //log(myArr.toString())
      //myArr.push("10.0.1.200")
      //myArr.push("for iobroker (10.0.1.200)")
      //myArr.push("10.0.1.201")
      //myArr.push("fritz.repeater (10.0.1.200)")
      /////////////////////////////////////log(myArr.toString())
      if(myArr!=null) {
      let var1; let var2; let var3; let varOhneName=[];
       myObj=[]
      for(var i=0;i<myArr.length;i++) {
          var1="na"; var2="na";
          var1=myArr[i].replace(/(for .+) \(\d+\.\d+\.\d+\.\d+\)/,"$1") 
          var1=var1.replace(/(.+)\(.+\)/," $1")
          var2=myArr[i].replace(/for .+ \((\d+\.\d+\.\d+\.\d+)\)/,"$1");//log(var2)
          var2=var2.replace(/.+\((.+)\)/,"$1")
          
          varOhneName=myArr[i].match(/^(\d+\.\d+\.\d+\.\d+)$/) 
          if (varOhneName!=null) {var1=varOhneName[0];var2=varOhneName[0]}
          var3="true";
         /* var2=var2.replace(/[(,)]/g,"")
          for (var index in myDeviceNames) {                   //ersetze mit aliasnamen
                                    //log(index)
                                     if ((var2.trim()).match(index)) {var1="for "+myDeviceNames[index];
                                    // log(val0+" - "+index)
                                       }
      
          }  */
      
      
        let help=[var1.trim(),var2.trim(),var3]
        if (!(var1=="na" || var2=="na")) myObj.push(help)
        if (true) {/* myObjOld= getState("0_userdata.0.Tabellen.IPDeviceERROR").val */ 
                        myObjOld.push(help);    
                        }
      }
      //log("vor await")
      await needDP(myObjOld)
      
                       await Sleep(1500); 
                       myObjOld=await getData(dpPrefix+"Tabellen.IPDevices.Device_Collection")
                      // log("nach await")
        if (false) {/* myObjOld= getState("0_userdata.0.Tabellen.IPDeviceERROR").val */ 
                       // myObjOld.push(help);
                      //  createState(dpPrefix+"Tabellen.IPDevices.Device_Collection", myObjOld,  { name: 'Device_Collection', desc: 'Device_Collection', type: 'array',read: true, write: true });
                       await needDP(myObjOld).then(myObjOld=await getData(dpPrefix+"Tabellen.IPDevices.Device_Collection"))
                       await Sleep(3000); log("")
                      //  myObjOld=await getData(dpPrefix+"Tabellen.IPDevices.Device_Collection") //getState(dpPrefix+"Tabellen.IPDevices.Device_Collection").val; 
                       // log(myObjOld.toString())
                        }
                        else{
                        myObjOld=getState(dpPrefix+"Tabellen.IPDevices.Device_Collection").val;    
                        // log("-----"+myObjOld.toString()) ; 
                        }
      
      //log("++++++++++++++++++ "+myObj.toString())
      
      //setState("0_userdata.0.Tabellen.IPDeviceERROR", myObj.toString())
         
         let varhelp1; let varhelp2; let varhelp3="true";    //neue erkannt geräte zu datenbank hinzufügen
        for (var i=0;i<myObj.length;i++){ 
             //  log("kommen vom myObject: "+myObjOld[i][1]+" mit: "+myObjOld[i][0])
                 if (!myObjOld.toString().includes(myObj[i][1]))  {  varhelp1=myObj[i][0].trim() ; varhelp2=myObj[i][1]; varhelp3="true"; 
                                                          let help=[varhelp1,varhelp2,varhelp3]; /*log("+++++++!!!+++++++++help "+help.toString())*/
                                                         if (!(varhelp1.indexOf("scanned")>-1)) myObjOld.push(help)               
                                           }                       }
      
        for (var i=0;i<myObjOld.length;i++){                // ist gerät noch da ???
           //  if (i>0 && i<10)  log("-----"+myObjOld[i][0]+" alles: ") ;     if (i>0 && i<2) log(myObj.toString())
                 if (!myObj.toString().includes(myObjOld[i][1]))  {  varhelp1=myObjOld[i][0].trim() ; varhelp2=myObjOld[i][1]; varhelp3="false"; 
                                                          let help=[varhelp1,varhelp2,varhelp3]; /*if (i>=0 && i<80)  log("+++++++???+++++++++help "+help.toString())*/
                                                          myObj.push(help)               
                                           }                      }
       
         // log("------------------------------------------------"+myObjOld[1].toString())
      //log(mysortiereClient.toString())
          if (braucheMaterialDesignWidget || braucheMaterialDesignWidgetList) mysortiereClient=1
      
       /*    if (mysortiereClient==1){ 
      
              myObj.sort(function (alpha, beta) {
                  if (alpha[0].toUpperCase().trim() > beta[0].toUpperCase().trim())
                     return 1;
                  if (beta[0].toUpperCase().trim() > alpha[0].toUpperCase().trim())
                     return -1;
                  return 0;
                 });} else {  */
      if (mysortiereClient==2){ 
                 myObj.sort(function (alpha, beta) {
                  //   if (parseFloat(beta[1].replace(/.+\.(.+)$/,"$1")) > parseFloat(alpha[1].replace(/.+\.(.+)$/,"$1")))
                   if ((parseFloat(beta[1].replace(/.+\.(.+)$/,"$1")))+(parseFloat(beta[1].replace(/.+\.(.+)\..+$/,"$1"))*1000) > (parseFloat(alpha[1].replace(/.+\.(.+)$/,"$1")))+(parseFloat(alpha[1].replace(/.+\.(.+)\..+$/,"$1"))*1000))
                         return -1;
                     if ((parseFloat(alpha[1].replace(/.+\.(.+)$/,"$1")))+(parseFloat(alpha[1].replace(/.+\.(.+)\..+$/,"$1"))*1000) > (parseFloat(beta[1].replace(/.+\.(.+)$/,"$1")))+(parseFloat(beta[1].replace(/.+\.(.+)\..+$/,"$1"))*1000))
                         return 1;
                  return 0;
                 });  
                 }
          var1="scanned in" //nur scanned seconds
         var3="true"
         var2=myTimeScanArr[0].replace(/.+ (\d+\.\d+.+$)/,"$1");//log(var2)
         let help=[var1,var2,var3]
      
        if (mysortiereClient==1) help=["xxxx"+var1,var2,var3]
        myObj.push(help)
      /*if (!rootcount)*/  setState(dpPrefix+"Tabellen.IPDevices.Device_Collection", myObjOld)
      ///////////////////////////log("myObject ------- "+myObj.length.toString()+"---- ")
       // setState("0_userdata.0.Tabellen.IPDeviceERROR", myObj.toString())   // zur fehlersuche
              for(var i=0;i<myObj.length;i++) {            // hier eigene schleife definieren und den wert counter++ nicht vergessen  !!!
      
                counter++;                                       // SEHR WICHTIG - MUSS IN JEDER SCHLEIFE INTEGRIERT SEIN
              //  log(myObj[i][0].toString())
                val0=myObj[i][0].replace("for","").trim()
                val0=val0.replace("."+domainName,"")
                val0=val0.replace(/[(,)]/g,"")
                val1=myObj[i][1]
                val1=val1.replace(/[(,)]/g,"")
      
            //  log(val0+" --- "myDeviceNamesNew[].ip)
      
      for (var index in myDeviceNames) {                   //ersetze mit aliasnamen
                                    //log(index)
                                     if ((val1.trim()).match(index.trim()) && val1.trim().length == index.trim().length) {val0=myDeviceNames[index];
                                                                                                                          
                                     //log(val0+" - "+index)
                                       } } 
      let helperIP=""
      let helperlink=""
      for (var index in myDeviceNamesNew) {                   //ersetze mit aliasnamen
                                    //log(index)
                                     if ((val1.trim()).match(myDeviceNamesNew[index].ip) && val1.trim().length == (myDeviceNamesNew[index].ip).length) {
                                         
                                                                                                                       val0=myDeviceNamesNew[index].name; 
      
                                                                                                                     //   if (val0.length>=(kuerzungNamen)+2)  val0=val0.substring(0,kuerzungNamen)+" ...";
                                                                                                                       // helperIP=val0 ;  //log(val0)
                                                                                                                        if (myDeviceNamesNew[index].link!="") {helperlink=myDeviceNamesNew[index].link; 
                                                                            myDeviceNamesNew[index].hasOwnProperty("linkFirstName") ? helperIP=helperIP+` <a href="${helperlink}" target="_blank"><button style="font-size: 75%; background: ${farbeNichtErreichbar}; color:${htmlFarbFelderschrift}">${myDeviceNamesNew[index].linkFirstName}</button></a>` 
                                                                                                                                    : helperIP =helperIP+` <a style="text-decoration:none;" href="${helperlink}" target="_blank"> ${symbolLink}</a>` 
                                                                              
                                                                            if(myDeviceNamesNew[index].hasOwnProperty("morelinks")) {//log(JSON.stringify(myDeviceNamesNew[index].morelinks))
                                                                          
                                                                            for(let o=0;o<myDeviceNamesNew[index].morelinks.length;o++) {
                                                                                                                                         let test=JSON.parse(JSON.stringify(myDeviceNamesNew[index].morelinks))
                                                                                                                                         let key1=Object.keys(test[o])[0]
                                                                                                                                         //log(    Object.keys(test[o])[0]    );
                                                                                                                                       //  log(   test[o][key1]  );
                                                                                                                                         helperIP=helperIP+ ` <a href="${test[o][key1]}" target="_blank"><button style="font-size: 75%; background: ${farbeNichtErreichbar}; color:${htmlFarbFelderschrift}">${Object.keys(test[o])[0]}</button> </a>`         //`<button onclick="window.location.href =${test[o][key1]};">${Object.keys(test[o])[0]}</button>`                        //` ${Object.keys(test[o])[0]}<a style="text-decoration:none;" href="${test[o][key1]}" target="_blank"> ${symbolLink}</a>`
                                                                                                                                            }  
                                                                            }
                                                                          //  val0=helperIP;    
                                                                           }
                                                                      
                                     //log(val0+" - "+index)
                                       } }                                   
      
                  if (val0.length>=(kuerzungNamen)+2)  val0=val0.substring(0,kuerzungNamen)+" ..." 
                       val0=val0+helperIP;          
      
                  
                
                var val2help=myObj[i][2]
            if (mysortiereClient==2){ 
      
             if(val0=="scanned in") {val2=symbolWARN;val0="<font color=\""+lastZellColorSetting+"\"><i>"+" Anzahl "+counter+"</i>"; 
             let valer=val1.replace(/.* (um.*)/,"$1");
                                    val1=val1.replace(/(.*) um.*/,"$1");
                                    
                                    val1="<font color=\""+lastZellColorSetting+"\"><i>"+val1+"</i>"}
            
      
                if (val2help=="false") {val2=symbolKO;
      
                                        val0=("<font color=\""+farbeNichtErreichbar+"\"><"+styleNichtErreichbar+">")+val0+ "<\/"+styleNichtErreichbar+">";
                                        val1=("<font color=\""+farbeNichtErreichbar+"\"><"+styleNichtErreichbar+">")+val1+ "<\/"+styleNichtErreichbar+">";}  else{val2=symbolOK}        
      
                
      
           
       
      
      
           tabelleBind(); }//HIER NICHTS ÄNDERN : HIER WERDEN DIE DATEN DER SCHLEIFE ZUSAMMENGESETZT  - diese function muss als letztes in der eigenen schleife aufgerufen werden
           else {let help=[val0.trim(),val1,val2help];myObjExtra.push(help);}
         //}
      }; //Schleifen Ende - je nach schleifenart muss hier etwas geändert werden !!!!!!!!!
          var valLink=""; var valKat="";  
          if (mysortiereClient==1){ 
             counter=-1;
              myObjExtra.sort(function (alpha, beta) {
                  if ((alpha[0].toUpperCase()).trim() > (beta[0].toUpperCase()).trim())
                     return 1;
                  if ((beta[0].toUpperCase()).trim() > (alpha[0].toUpperCase()).trim())
                     return -1;
                  return 0;
                 });} 
                 var valLink=""; var valKat="";     
              
               for(var i=0;i<myObjExtra.length;i++) {
      
                     json4="standard"
                     json6="";
                      let val0helping="";
                     counter++
                     val0=myObjExtra[i][0]//.replace(/(^.*?) <a.*/,"$1")
                     json1=myObjExtra[i][0] ;// if(i>20 && i<30) log(val0)
                     json2=val1=myObjExtra[i][1] ;
                      val2help=myObjExtra[i][2] ;
                          for (var index in myDeviceNamesNew) { 
                              //   log("bin hier bei "+myDeviceNamesNew[index].ip+" mit ...")
                                if ((myObjExtra[i][1].match(myDeviceNamesNew[index].ip)) && myObjExtra[i][1].length == myDeviceNamesNew[index].ip.length) {
                                   //  log("bin hier bei "+myDeviceNamesNew[index].name+" mit "+  myObjExtra[i][0]+" und kat: " + myDeviceNamesNew[index].kat)
                               
                                   /*  if (myDeviceNamesNew[index].link!="") {json6=myDeviceNamesNew[index].link; 
                                                                            myDeviceNamesNew[index].hasOwnProperty("linkFirstName") ? json6=` <a href="${json6}" target="_blank"><button style="font-size: 75%; background: ${farbeNichtErreichbar}; color:${htmlFarbFelderschrift}">${myDeviceNamesNew[index].linkFirstName}</button></a>` 
                                                                                                                                    : json6 =` <a style="text-decoration:none;" href="${json6}" target="_blank"> ${symbolLink}</a>` 
                                                                              
                                                                            if(myDeviceNamesNew[index].hasOwnProperty("morelinks")) {//log(JSON.stringify(myDeviceNamesNew[index].morelinks))
                                                                          
                                                                            for(let o=0;o<myDeviceNamesNew[index].morelinks.length;o++) {
                                                                                                                                         let test=JSON.parse(JSON.stringify(myDeviceNamesNew[index].morelinks))
                                                                                                                                         let key1=Object.keys(test[o])[0]
                                                                                                                                         //log(    Object.keys(test[o])[0]    );
                                                                                                                                       //  log(   test[o][key1]  );
                                                                                                                                         json6=json6+ ` <a href="${test[o][key1]}" target="_blank"><button style="font-size: 75%; background: ${farbeNichtErreichbar}; color:${htmlFarbFelderschrift}">${Object.keys(test[o])[0]}</button> </a>`         //`<button onclick="window.location.href =${test[o][key1]};">${Object.keys(test[o])[0]}</button>`                        //` ${Object.keys(test[o])[0]}<a style="text-decoration:none;" href="${test[o][key1]}" target="_blank"> ${symbolLink}</a>`
                                                                                                                                            }  
                                                                            }
                                                                            val0helping=json6;    
                                                                           }*/
                                     if (myDeviceNamesNew[index].kat!="")  json4=myDeviceNamesNew[index].kat;}  }
                                 if (val2help=="false") {json3=val2=symbolKO; json5="red";
                                        val0=("<font color=\""+farbeNichtErreichbar+"\"><"+styleNichtErreichbar+">")+val0+ "<\/"+styleNichtErreichbar+">";
                                        val1=("<font color=\""+farbeNichtErreichbar+"\"><"+styleNichtErreichbar+">")+val1+ "<\/"+styleNichtErreichbar+">";}  else{json3=val2=symbolOK;   json5="green";} 
                     if(val0=="xxxxscanned in") {json3=val2=symbolWARN;   json5="blue"; json1="Anzahl: "+counter; json4="info";
                                                  val0="<font color=\""+lastZellColorSetting+"\"><i>"+" Anzahl "+counter; 
                                                  val1="<font color=\""+lastZellColorSetting+"\"><i>"+val1+"</i>" //" um "+formatDate(getDateObject((new Date().getTime())), "SS:mm:ss")+
                                                  json2=myObjExtra[i][1]+", "+formatDate(getDateObject(((new Date().getTime()))), "SS:mm:ss")}
      
                                                 if (val2help) val0=val0+val0helping ; // link
                       tabelleBind();
                    
                     if (braucheMaterialDesignWidget || braucheMaterialDesignWidgetList) {
                        if (val2help=="false") {json3=val2=symbolKO_MD; }
                       makeJsonWidget(json1,json2,json3,json4,json5,json6);}
                 }
                
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      //--------------------------------------------------Ende der schleife------------------------------------------------------------------------------
      //-------------------------------------------------------------------------------------------------------------------------------------------------
      
            // AB HIER NICHTS ÄNDERN - tabelle fertigstellen
            let timeout = setTimeout(function () {
                                                   tabelleFinish();
                                                   if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
                                                   if (braucheHostDaten) {for(var i=0;i<myObjExtra.length;i++) {  if (myObjExtra[i][0]!="xxxxscanned"){
                                                                                                                  hostDaten=hostDaten+myObjExtra[i][1]+"\t"+myObjExtra[i][0]+"\n" }}}
                                                    setState(dpHost,hostDaten); //log(hostDaten)
                                                 }, 2000); 
         
             }  else {log("no Array","warn")} //Ende Array falsch
             } else {log("no Data","warn")} // ende daten falsch
           //  rootcount=false;
      //}, waitTime);
       laeuftSchon=false;
       })
      //laeuftSchon=false;
      } // function ende
      
      //MAIN:
       
      schedule(mySchedule,  function () { 
       if ( !laeuftSchon) writeHTML();
      // if (braucheEinFile) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
      }); 
      if ( !laeuftSchon) writeHTML();                                   
      
       function tabelleBind(){
         //  counter=counter+mehrfachTabelle;
             switch (mehrfachTabelle) { 
      
               case 1: if(counter%2==0)         {  htmlOut=htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">"+val0+"</td><td align="+Feld2lAlign+">"+val1+"</td><td align="+Feld3lAlign+">"+val2+"</td></tr>"; break;}else    
                                                {  htmlOut=htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">"+val0+"</td><td align="+Feld2lAlign+">"+val1+"</td><td align="+Feld3lAlign+">"+val2+"</td></tr>"; break;}
               case 2: if(counter%4==0){
                          if(counter%2==0)  {htmlOut = htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">"+val0+"</td><td align="+Feld2lAlign+">"+val1+"</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align="+Feld3lAlign+">"+val2+"</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">"+val0+"</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">"+val1+"</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">"+val2+"</td></tr>";} break;
                            }else{
                                      if(counter%2==0)  {htmlOut = htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">"+val0+"</td><td align="+Feld2lAlign+">"+val1+"</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align="+Feld3lAlign+">"+val2+"</td>"; } 
                                     else {htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">"+val0+"</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">"+val1+"</td><td  align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">"+val2+"</td></tr>";} break;}
                                          
               case 3:if(counter%2==0)   {
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeGeradeZeilen+"\"><td align=\""+Feld1lAlign+"\">"+val0+"</td><td align=\""+Feld2lAlign+"\">"+val1+"</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align=\""+Feld3lAlign+"\">"+val2+"</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align=\""+Feld1lAlign+"\" style=\"color:"+htmlFarbFelderschrift2+"\">"+val0+"</td><td  align=\""+Feld2lAlign+"\" style=\"color:"+htmlFarbFelderschrift2+"\">"+val1+"</td><td  align=\""+Feld3lAlign+"\" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"; color:"+htmlFarbFelderschrift2+"\">"+val2+"</td>";} 
                                                      else    {htmlOut = htmlOut+"<td align=\""+Feld1lAlign+"\">"+val0+"</td><td align=\""+Feld2lAlign+"\">"+val1+"</td><td align=\""+Feld3lAlign+"\">"+val2+"</td></tr>";}
                                                } break;}else{
                          if(counter%3==0 )  {htmlOut = htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeUngeradeZeilen+"\"><td align=\""+Feld1lAlign+"\">"+val0+"</td><td align=\""+Feld2lAlign+"\">"+val1+"</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+
                                                              ";\" align=\""+Feld3lAlign+"\">"+val2+"</td>"; } 
                                     else { if(counter%3==1 )  { htmlOut = htmlOut+"<td align=\""+Feld1lAlign+"\" style=\"color:"+htmlFarbFelderschrift2+"\">"+val0+"</td><td  align=\""+Feld2lAlign+"\" style=\"color:"+htmlFarbFelderschrift2+"\">"+val1+"</td><td  align=\""+Feld3lAlign+"\" style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"; color:"+htmlFarbFelderschrift2+"\">"+val2+"</td>";} 
                                                      else     {htmlOut = htmlOut+"<td align=\""+Feld1lAlign+"\">"+val0+"</td><td align=\""+Feld2lAlign+"\">"+val1+"</td><td align=\""+Feld3lAlign+"\">"+val2+"</td></tr>";}
                                                } break;}                                
      
      
               case 4:  // counter=counter+8;
                         if(counter%8==0)   {
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeGeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+ farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } // teil1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} //teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} //teil 4
                                                                        else    {htmlOut =htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"  align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}else{
                         if(counter%4==0)  {htmlOut = htmlOut+"<tr class=\"nmapspecial\" bgcolor=\""+farbeUngeradeZeilen+"\"><td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\" align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>"; } //teil 1
                                         else {if(counter%4==1 )  { htmlOut = htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td  align="+Feld3lAlign+" style=\"border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td>";} // teil 2
                                                      else    {if(counter%4==3)  { htmlOut= htmlOut+"<td align="+Feld1lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val0+"&ensp;</td><td  align="+Feld2lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val1+"&ensp;</td><td align="+Feld3lAlign+" style=\"color:"+htmlFarbFelderschrift2+"\">&ensp;"+val2+"&ensp;</td></tr>";} // teil 4
                                                                        else    {htmlOut = htmlOut+"<td align="+Feld1lAlign+">&ensp;"+val0+"&ensp;</td><td align="+Feld2lAlign+">&ensp;"+val1+"&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+";\"align="+Feld3lAlign+">&ensp;"+val2+"&ensp;</td>";}} //teil 3
                                                } break;}                                    
              } //switch ende
      
      }
      
      function tabelleFinish() {
      
      switch (mehrfachTabelle) {  
             case 1:    break;
      
             case 2:    
                        if(counter%2==0)  htmlOut = htmlOut.replace(/<\/td>$/, '</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>');
                      
                        break;
      
             case 3:   if(counter%3==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%3==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");        
                       if(counter%3==0)      htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td  style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                     
                        break;
             case 4:   if(counter%4==3)  htmlOut = htmlOut.replace(/<\/td>$/, "</td></tr>");
                       if(counter%4==2)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");
                       if(counter%4==1)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");    
                       if(counter%4==0)  htmlOut = htmlOut.replace(/<\/td>$/, "</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td style=\" border-right: "+trennungsLinie+"px solid "+farbetrennungsLinie+"\">&ensp;</td><td>&ensp;</td><td>&ensp;</td><td>&ensp;</td></tr>");      
                       break; }
           
               var htmlUeber=    "<p style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: "+htmlÜberFontGroesse+"; font-weight:"+htmlSchriftWeite+ "\">"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((new Date().getTime())), "SS:mm:ss")+"</p>"; 
             var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 70%; text-align: right;\" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject((new Date().getTime())), "SS:mm:ss")+"</div>";
              htmlUeber=htmlUeber+searchMe
              if (!htmlSignature) htmlUnter="";
      
            //  log(" ist htmlUnter - signature "+htmlUnter)
                //Ausgabe über VIS html widget - tabelle in datenpunkt schreiben - html tabelle ohne html header und body
                 var htmlOutVIS="";
               //  htmlUberschrift ? htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>" : htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>";
                  if (htmlUberschrift) 
                      { zentriert ? htmlOutVIS=htmlZentriert+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+"</center>"+ buttonScript : htmlOutVIS=htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+"</center>"+ buttonScript ;
      
                    } else {
                     zentriert ?  htmlOutVIS=htmlZentriert+htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+"</center>"+ buttonScript :  htmlOutVIS=htmlTabStyle+htmlTabUeber+htmlOut+"</table>"+htmlUnter+"</center>"+ buttonScript;
      
                       }
                       
      
        // log("bin raus aus tabelleBind");
                 if (braucheEinVISWidget) setState(dpVIS, htmlOutVIS );
                 
      
       var htmlUnter= "<div  style=\"color:"+htmlFarbUber+"; font-family:"+htmlSchriftart+"; font-size: 80%;  text-align: center; \" >"+htmlFeldUeber+"&ensp;&ensp;Last Update: "+formatDate(getDateObject(((new Date().getTime()))), "SS:mm:ss");+"</div>"
       if (!htmlSignature) htmlUnter="";
       var htmlEnd="</table>"+htmlUnter+"</div></body>";
      
      
       //mit oder ohne überschrift - zentriert oder links
      htmlUberschrift ? htmlOut=htmlStart+htmlUeber+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd : htmlOut=htmlStart+htmlTabStyle+htmlTabUeber+htmlOut+htmlEnd;
       //log(htmlOut);
      if (braucheMaterialDesignWidgetList) {
           
             setState(dpMaterialListWidget,JSON.stringify(myJsonWidget2)); 
             myJsonWidget2=[];
      }
      if (braucheMaterialDesignWidget) {
        
        setState(dpMaterialTabelWidget,JSON.stringify(myJsonWidget)); 
           myJsonWidget=[];
      }
      
      }
      
       function makeJsonWidget(vax1,vax2,vax3,vax4,vax5,vax6) {
      //log(vax3+vax6+htmlFeld1)
      vax4=pfadBilderMaterialWidget+vax4+".png" ;
         if ( braucheMaterialDesignWidgetList) {
         myJsonWidget.push({
             Device : vax4,
             IP : vax1,
             Status : vax2,
             Kategorie : vax3+" "+vax6
         }
      
         );}
      
      //	log(myJsonWidget)
      if (braucheMaterialDesignWidget) {
          let colorIP= materialD_IP_erreichbar   //"lightgreen";
        //  log(vax3)
          if (vax3==symbolKO_MD) colorIP=materialD_IP_nichtErreichbar     //"lightcoral";
        //  vax4=pfadBilderMaterialWidget+vax4+".png" ; 
      let mysubText = `<div style="display: flex; flex-direction: row; line-height: 1.3; padding-left: 1px; padding-right: 8px; align-items: center;">
                                    <div style="flex: 1;font-size: 16px; color: ${colorIP};">${vax2}</div>
                                    <div style="color: grey; font-size: 12px; font-family: RobotoCondensed-LightItalic; text-align: right;">${vax3}${vax6}</div>
                                </div>`
           let ip=vax2                     
        
           myJsonWidget2.push({
                     text: vax1,
                     subText: mysubText,
                     statusBarColor: vax5,
                     image: vax4,
                     imageColor: "",
                     listType: "text",
                     showValueLabel: true,
                     ip: ip, //vax2,
                     status: vax3,
                     link:vax6
                     
                 });
      }
       }
      
       
      
         on({id: "0_userdata.0.Tabellen.IPDevicesSort", ack: false, change: "any"}, function (obj) { 
           //  log(obj.id);log(String(mehrfachTabelle))
           mysortiereClient=obj.state.val
         log(mysortiereClient.toString())
         
         //  log(String(mehrfachTabelle))
        setTimeout(function () { // log('file written')
           if ( !laeuftSchon)  writeHTML();
             if (braucheEinFile && !laeuftSchon) {writeFile(home, path ,htmlOut, function (error) { /* log('file written');*/  });}
      }, 350);
          
      
           
         })
      
      
          function extraTablefinish() {   
      } //extraTablefinish
      
      async function needDP(myData){
          if (!(await existsStateAsync("Tabellen.IPDevices.Device_Collection"))) {
             await createStateAsync("Tabellen.IPDevices.Device_Collection", myData,{type: "array", name: "Device_Collection", desc: 'Device_Collection', role: "value", read: true, write: true, } ); }
         //await Sleep(3000); 
      }
      
      async function getData(myData){
          
         return getState(myData).val; 
      }
      //createState(dpPrefix+"Tabellen.IPDevices.Device_Collection", myObjOld,  { name: 'Device_Collection', desc: 'Device_Collection', type: 'array',read: true, write: true });
      
      function Sleep(milliseconds) {
      return new Promise(resolve => setTimeout(resolve, milliseconds));
      }
      
      
      
      
      
      
      

      posted in JavaScript
      liv-in-sky
      liv-in-sky
    • [Vorlage]-Zeit herunterzählen bis GoogleTermin Eintritt

      diese beiden scripte ermöglichen es einen bestimmten Termin (z.B Geburtstag, Müllabfuhr, Geburt ,,,) des GoogleKalenders herunterzählen zu lassen

      es gibt eine neue version - läuft mit countdown-adapter und einem blockly
      https://forum.iobroker.net/post/672238

      noch ...
      Image 9.png bis zum geburtstag

      was wird benötigt:

      • ical-adapter - liest google kalender aus
      • ein blockly script -> daten aus ical.data lesen, datum vorbereiten und triggern des zweiten scripts
      • ein js-script -> berechnen der werte (tage, stunden minuten bis zum ereignis

      Schematic:
      Schema-goole-anbindung.png

      der ical adapter:

      • neue ical instanz anlegen
      • Haupeistellungen: Datumsangaben mit führender "0" anhaken und 30 (oder was gewünscht wird) tage als Tagesvorschau
      • Ereignisse: den suchbegriff eingeben: z.b. Papiertonne - "anzeigen" anhaken
      • Kalender: google-kalender definieren

      damit ist der trigger für das blockly-script definiert worden - ist der event (tag 30) true - wird das blockly aktiv !

      das blockly script:

      Blockly-Google-script.txt
      Version 1.2

      • es reagiert auf den tag 30 - papiertonne true - liest den ical-adapter-wert html aus und manipuliert den string so, dass die uhrzeit und das datum gefunden werden - anschliessend wird ein Schedule auf gesetzt, wann das zweite script getriggert wird (um ein überschreiben vor ablauf des letzten termins zu unterbinden)
      • anschliessend (durch schedule) schreibt es das datum (Termin Datum) und einen selbsgewählten begriff (Termin Name) in die datenpunkte für das js-script, welches dadurch getriggert wird
        die datenpunkte im blocklyscript müssen auf eure datenpunkte (des icaladapters) angeglichen werden !!!!

      bis jetzt haben wir ein ical adapter, der uns an einem bestimmten tag einen event auf true setzt - ein blockly script, welches an diesem bestimmten punkt aufwacht und das datum und die uhrzeit aus dem ical ausliest.

      jetzt fehlt nur noch die berechnung, damit wir etwas in der vis anzeigen können 🙂

      das js-script:

      Counter-Abwaerts.txt

      es installiert datenpunkte unter javascript.0.Countdown. schreibt man ein bestimmtes datums format in den datenpubkt (javascript.0.Countdown.Termin.Datum) läuft das script los, bis die zeit abgelaufen ist. das script kann auch ohne google kalender genutzt werden und z.b. in der vis direkt eingegeben werden (siehe bild 1) (https://forum.iobroker.net/topic/20267/gelöst-einfacher-countdown-in-vis-von-festem-datum-gesucht?page=1). Im Datenpunkt javascript.0.Countdown.Termin.Name wird der Termin Name eingetragen (Kommt nicht von Google sondern vom Blockly script)

      die datumsformate sind folgende:

      • 9.4.2019 10:00
      • 9.4.2019 (bezug 00:00 uhr)
      • 9 May 2019 10:00 - (Monat 3 Buchstaben engl. Abkürzung)
      • 9 May 2019 - (Monat 3 Buchstaben engl. Abkürzung)

      es muss besonders auf auf das zusammenspiel der sich wiederholende termine geachtet werden. will man alle 4 wochen einen termin abfragen, anzeigen und runterzählen lassen, muss der ical adapter mindestens 28 tage abholen. im blockly script muss dann auch der 28. tag als trigger für das blockly script gewählt werden - durch das integrierte schedule wird der zählvorgang auch erst nach ablauf des letzten termins mit dem zählen beginnen

      ein weiteres beispiel speziell für dieses script:

      Image 11.png

      posted in Skripten / Logik
      liv-in-sky
      liv-in-sky
    • DIY Alexa Skill - praktisch und einfach erstellt

      kam von hier: https://forum.iobroker.net/topic/48251/gelöst-alexa-fragen-lassen-ohne-sprachaktivierung
      danke an @tklein

      wollte hier nochmals auf das erstellen und den mehrwert eines eigenen alexa skills hinweisen - über voiceflow.com erstellt, kostenlos (für 2 skills) und so simple wie node-red

      • der skill wird über einen alexa2-adapter textcommand gestartet (öffne regler), alexa meldet sich und wartet auf eingabe (diese eingabe braucht kein "weckwort") , anschliessend wird das gesagte über iot-adapter an iobroker gesendet - dort wartet ein script zur auswertung
      • es benötigt mind. 2 worte - eine kategorie und befehl
      • das alexa auf input wartet kann über text umgesetzt werden (alexa sagt: "was willst du",..) oder ich habe mich über eine eigenes mp3 mit signalton entschieden

      beispiele

      • man kommt heim, alexa wartet auf input, z.b "radio ein", heizung boost, ...
      • tv wird eingeschaltet, alexa wartet auf: programm zdf
      • man betritt das büro am morgen das erste mal: computer ein,
      • .... unendliche möglichkeiten

      der skill sieht so aus - ist noch nicht perfekt - im moment muss ich noch 2 wörter (eines davon ist "nichts" oder "keine") sagen, um keinen befehl auszuführen: "will nichts", "keine befehle" - oder "stop"

      Image 2.png

      auf dem iobroker wertet ein script die eingabe über alexa aus und schaltet(triggert) den gewünschten vorgang ein

      verbesserungen:

      • reaktion des skills ohne eine eingabe
      • mehrere befehle (das wort "und" rausfiltern)
      • abfrage von iobroker variablen (ist abhängig vom externen zugang zu iobroker) z.b https://forum.iobroker.net/topic/48306/datenaustausch-mit-extern-durch-php-sql-api
      posted in ioBroker Allgemein
      liv-in-sky
      liv-in-sky
    • [Vorage]-Blockly-Alexa Timer sichtbar machen (vis)

      das script macht es möglich 2 gestellte alexa timer sichtbar zu machen - das script wird parallel zum alexa timer gestartet - der datenunkt summary des alexa2 adapters wird ausgewertet.

      voraussetzung ist eine neue version des alexa2 adapters, da in älteren versionen das summary anders reagiert.

      es werden nur 2 aktive timer angezeigt. es werden die minuten als datenpunkte ausgegeben . unter einer minute werden die sekunden in 5er schritten ausgegeben. die datenpunkte werden unter: javascript.0.ALEXATimer. angelegt. das script ist nicht bidirectional -> timer, die in der alexa app gelöscht werden, haben keinen einfluss auf das script (läuft einfach weiter!!!)
      es können nur folgende zeiten angegebene werden

      • minuten von 1 bis 999 - dies wird im script verwandelt
      • stunden von 1 bis 24
      • stunden können nichtmit minuten zusammen eingegeben werden

      wie müssen die timer befehle angegeben werden'?
      am besten gibt man die timer mit namen an (der name sollte ein wort sein):

      • "alexa timer 3 minuten"
      • "alexa timer 9 minuten spaghetti"
      • "alexa timer 3 stunden ankunft"
        mittlerweile funktioniert auch:
      • "alexa <stelle, erstelle, mache ...> timer <mit, auf, für> 10 minuten <name des timers>

      löschen laufender timer:

      • "alexa lösche timer spaghetti"
      • "alexa lösche timer"
      • "alexa lösche timer xxx" -> wenn xxx kein existierender timer name ist, werden die scripttimer ohne namen gelöscht

      reset des scriptes:

      • "alexa lösche alle timer" -> löscht alle alexa timer und führt zu rest des scriptes
      • es gibt einen datenpunkt (javascript.0.ALEXATimer.TimerResetVIS) mit dem kann man von der VIS ausalle timer löschen (nicht die alexatimer selbst!)

      sonstiges:

      • der Datenpunkt javascript.0.ALEXATimer.TimerTausch : bei false werden auf mehr timer wie 2 nicht reagiert - der ersten beiden bleiben sichtbar - bei true werden die älteren timer überschrieben - der dritte alexatimer wird zum scripttimer1, der vierte alexatimer wird zum zweiten scripttimer.

      IMPORT: version 0.92 ,1.1, 2.0, 2.1, 3.0, 3.1, 3.2, 3.5
      alexa-timer-script-zahlenbis999+stunden.txt
      tester und ideengeber sind willkommen

      vorgehen bei script update:

      • stoppt das existierende script - (schneller: löschen existierendes script)
      • geht in datenobjekte und löscht den ganzen ALEXATimer ordner unter javascript.0 (rechts ist ein mülleimer zum löschen der objekte)
      • importiert neues script
      • script wieder enabeln

      widget beispiel:
      timer-widget.gif

      timer-widget-3stellig.txt
      Image 2.png timer-widget-3stellig-eckig.txt

      posted in Blockly
      liv-in-sky
      liv-in-sky
    • Sonoff Geräte als HTML Tabelle - Vis

      --------------------------------------------------------------------------------------------------------------------

      NEUE VERSION DES SCRIPT's HIER: https://forum.iobroker.net/post/601855
      --------------------------------------------------------------------------------------------------------------------


      hier eine tabelle mit sonoff devices in html zur anzeige in iqontrol, vis oder als webseite - die tabelle kaann verschieden formatiert werden - farben, linien, abstande, schriftart, ...
      grundlage für die einstellung der tabellenparameter ist hier : https://forum.iobroker.net/topic/28021/html-table-für-vis-oder-iqontrol-js-und-blockly/96

      wichtig - ihr müßt euch einen eigenen datenpunkt als zeichenkette anlegen und diesen dann im script (ganz oben "dpVIS") eingeben
      darunter werden dann die einzelnen devices freigeschalten - steht eine deviceart auf true und ist im system nicht enthalten, passiert nix außer das die überschrift in der tabelle erscheint und keine geräte da sind
      zusätzlich wird ein datenpunkt für die anzahl benötigt - auch den selbst anlegen und im script (dpAnzahl) einfügen

      wie legt man einen datenpunkt an: https://forum.iobroker.net/post/400338

      das widget ist ein standard html widget und der von euch angelegte datenpunkt wird als binding angegeben -also einfach den datenpunkt unter HTML reinschreiben und in klammern setzen {}

      ein erstes beispiel - es fehlen noch einige sonoffarten - da könnte ich hilfe brauchen, da ich nicht alle arten habe - also falls es da wünsche gibt - einfach melden

      Image 3.png

      wenn die geräte nicht erreichbar sind:

      Image 2.png

      aus platz-gründen in einer datei - beim kopieren einen editor verwenden (wegen emojis) - nicht direkt aus browser kopieren sondern datei downloaden und mit editor öffnen und dann in iobroker einfügen !!!
      sonoff-8spalten-tabelle-15.1.21.txt

      script mit 6 spalten - es fehlen die switch: dieses script mit 6 spalten wird nicht weitergepflegt - daher alte version

      sonoff-6spalten-tabelle.txt

      Image 7.png

      bisher integriert

      • pow
      • generic
      • basic
      • th10
      • schalter2ch
      • schalter3ch
      • dual
      • schalter1ch
      • channel4
      • rfbridge
      • ZbBridge
      • stdoseS2X
      • teckin
      • sv
      • blitzwolf_shp
      • sonoffDev
      • gosundSP1x
      • shelly
      • mini
      • delock
      posted in JavaScript
      liv-in-sky
      liv-in-sky

    Latest posts made by liv-in-sky

    • RE: Test Adapter Growatt v3.3.1

      @io2345 habe mir extra einen apsystem Wechselrichter gekauft, der kann mit httpget lokal abgefragt werden
      Damit geht dann auch eine 0-einspeisung

      Der Akku wird dann auf 800 gestellt und gut is

      posted in Tester
      liv-in-sky
      liv-in-sky
    • RE: Suche Tester für komerz. Visu und Scriptbaukasten

      wo soll hier ein shitstorm sein ? ein paar anständig vorgetragene meinungen sollen schon ein shitstorm sein ?

      posted in Marktplatz
      liv-in-sky
      liv-in-sky
    • RE: Erfahrungen mit Regensensor von AliExpress - Zigbee

      @crunchip ja - ich auch ungefähr - bisher kein akku oder anderes problem

      den unteren finde ich schöner- habe ihn aber erst seit gestern im einsatz - hat regen erkannt - wie lange akku hält weiß ich nicht

      posted in ioBroker Allgemein
      liv-in-sky
      liv-in-sky
    • Erfahrungen mit Regensensor von AliExpress - Zigbee

      falls jmd sowas sucht und zigbee2mqtt nutzt

      https://de.aliexpress.com/item/1005007455034223.html (mit Solarladung)

      Image 061.png

      und auch

      https://de.aliexpress.com/item/1005009184828073.html (mit Akku)

      Image 062.png

      posted in ioBroker Allgemein
      liv-in-sky
      liv-in-sky
    • RE: ical Abonierter Kalender?

      @beowolf danke - wußte nicht, dass sich das updatet

      posted in ioBroker Allgemein
      liv-in-sky
      liv-in-sky
    • RE: ical Abonierter Kalender?

      @beowolf sagte in ical Abonierter Kalender?:

      MOQO App

      mal ne allgemeine frage - sind diese daten, die im gCalender angezeigt werden, dynamisch ? so ein carsharing kalender wird doch siche rimmer wieder geändert - werden die änderungen dann in googleC. angezeigt ?

      posted in ioBroker Allgemein
      liv-in-sky
      liv-in-sky
    • RE: Frage zu URL() im Javascript adapter

      füge das oben ein :

      const { URL } = require('url'); 
      
      posted in JavaScript
      liv-in-sky
      liv-in-sky
    • RE: Erfahrungen mit Zigbee BWM/Präsenzmelder von AliExpress

      @crunchip danke dir - bin eigentlich ganz zufrieden - nur einer hatte bisher ein batterie problem

      manchmal kommt es vor, dass bei zigbee2mqtt nichts mehr ankommt - dann muss ich das gerät leider wieder einbinden - war aber in letzter zeit nicht mehr der fall - kann auch ein server thema sein

      ich brauche ja eine sehr schnelle wieder-erkennung und nutze daher auch den radar bereich - kann di egeräte eigentlich schon empfehlen - habe schon viele sache getestet - diese hier sind am besten bis jetzt

      posted in Off Topic
      liv-in-sky
      liv-in-sky
    • RE: Petition Photovoltaik

      zwei stunden sonne und der akku ist voll - durch die nulleinspeisung wird alles was über den momentanen verbrauch liegt, auch für den akku genutzt - damit ist sichergestellt,falls es nicht so viel sonne gibt, dass der akku bis morgens des nächsten tages ausreicht.

      der mai war nur am ende etwas wolkig - daherhat es gut geklappt

      posted in Off Topic
      liv-in-sky
      liv-in-sky
    • RE: Petition Photovoltaik

      @martinp siehe chat

      posted in Off Topic
      liv-in-sky
      liv-in-sky
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo