Ankündigung

Einklappen
Keine Ankündigung bisher.

Neues Widget: Klingel-getriggertes Kamera Popup

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Neues Widget: Klingel-getriggertes Kamera Popup

    Hallo,

    ich habe soeben ein neues Widget erstellt, dass mir ein Popup mit dem aktuellen Kamerabild auf jede Seite bringt, sobald es geklingelt hat.
    Das ganze kommt ohne grosse Logik aus sh.py aus und ist z.Zt noch work-in-progress, da ich nicht so der Programmierer bin...

    Insbesondere das ganze CSS, JS und soweiter ist noch ziemlich "ugly" und ich werde das ein bisschen systematisieren, so dass das für alle einsetzbar ist.

    Aus dem Popup kann ich den Kameraview aufrufen (mit "Live-stream" oder eben einfach nur schliessen. Der Trigger kommt von meiner Klingel, die beim "Ding" den Wert auf True setzt (und somit das Popup getriggert wird) und beim "Dong" auf False. Somit ist bei einem erneuten Seitenaufruf das Popup nicht mehr zu sehen.

    Bildschirmfoto 2015-11-29 um 14.35.11.png

    Das einzige Problem: Meine Visu läuft auf einem iPad und ich habe schon Insomnia installiert (soll angeblich helfen, dass Wifi nicht abzuschalten bei Screen aus), aber leider ist die Websocket Verbindung immer weg, wenn der Screen in den Stromsparmodus geht. Und ein Page refresh dauert halt so seine Zeit... Hat da noch jemand Ideen?

    Gruss-
    christian
    Angehängte Dateien
    ++ KNX und ETS schnell, einfach und verständlich ++
    Der ultimative ETS Schnellkurs
    www.ets-schnellkurs.de


    #2
    Hi Christian,

    bei iTunes gibt es den Schalter, dieses Gerät über WLAN zu synchronisieren. (iPad an den Rechner anschließen!)

    Dieses wurde als Tipp gehandelt, wenn man die Anwesenheit mit einem Ping abfragen wollte, da dann das Gerät per WLAN erreichbar war, auch wenn der Bildschirm dunkel war.

    Ich habe es aber nie selbst ausprobiert.

    Gruss Andreas

    Kommentar


      #3
      Hallo Christian,
      ich wäre stark an deinem "ugly"- js,css usw. interessiert. Könntest du entscheidene Teile hier posten....sozusagen als Verständnis/-Ideengeber?

      Viele Grüße
      Thomas

      Kommentar


        #4
        Zitat von tomluebke Beitrag anzeigen
        ich wäre stark an deinem "ugly"- js,css usw. interessiert. Könntest du entscheidene Teile hier posten....sozusagen als Verständnis/-Ideengeber?
        Ich habe das Widget in die menu.html eingebunden, so dass es auf jeder Seite (unsichtbar) auftaucht.
        1)
        Code:
        {% import "widgets/widget_notification_camera.html" as camera_popup %}
            ...
            {{ camera_popup.camera_popup('camera_popup', 'Haustuer.klingel', 'http://xx.xx.xx.xx/Streaming/channels/2/picture?auth=xxxxxxxx') }}
        2) das widget:
        Code:
        /** 
        * Widget for displaying camera picture / stream in case of an event
        *
        * @id unique id for this widget
        * GAD a gad/item
        */
        
        {% macro camera_popup(id, gad, image_url) %}
        
        {% set uid = uid(page, id) %}
        
        
          <script language="javascript" type="text/javascript">
          $(document).ready(function(){
        
            $("#{{ uid }}").toggle(false);
            $("#notification_camera_popup_button").click(function(){
                 $("#{{ uid }}").toggle(false);
             });
        
          });
          </script>
        
        <div class="block full-width"
             id="{{ uid }}" 
             data-widget="notification.camera"
             data-item="{{ gad }}" 
             data-image ="{{ image_url }}"
             style="z-index:0; position: absolute; top: 50%; left: 50%; margin-right: -50%; transform: translate(-50%, 0%);"
        >
            <div class="ui-bar-c ui-li-divider ui-corner-top">Klingel</div>
            <div class="ui-fixed ui-body-a ui-corner-bottom" style="min-height: 50px">
                <img id="notification_camera_popup_picture_url" src="{{ image_url }}" width="80%" height="99%">
                <div id="notification_camera_popup_button" style="width:100px; display: block;">
                    <table><tr><td align="left"><button type="button">Schliessen</button></td><td align=right><button type="button" onclick="window.location='?page=kamera';">Kameraansicht</button></td></tr></table>
                </div>
            </div>
        </div>
        
        {% endmacro %}
        TODO:
        a) Das Kamerabild wird momentan mit jedem Smartvisu aufruf geladen (wenn auch unsichtbar). Sicherlich nicht gut, wenn über VPN verbunden. Eine Art Lazy loading würde wohl Sinn machen.
        b) Ausserdem gibt es noch ein Problem mit der Positionierung des Popups: Das "left: 50%; " funktioniert im Chrome, auf dem iPhone nicht.
        c) Link zum Kamera-View konfigurierbar machen

        3) Item:
        Code:
        [Haustuer]
            [[klingel]]
                type = bool
                visu_acl = r
                knx_dpt = 1
                knx_listen = 5/2/0
        4) Das ganze kann dann mit
        Code:
        sh.Haustuer.klingel(True);
        aktiviert werden.

        Aber wie oben geschrieben, dass macht die Klingel beim "Ding" automatisch...
        Zu Testzwecken könnte
        Code:
         $("#{{ uid }}").toggle(false);
        einfach durch
        Code:
         $("#{{ uid }}").toggle();
        ersetzt werden und man kann es über die shell auch wieder inaktivieren, aber dann würde das "Dong" dieses auch tun.

        Bei Verbesserungsvorschlägen nehme ich das gerne auf.
        ++ KNX und ETS schnell, einfach und verständlich ++
        Der ultimative ETS Schnellkurs
        www.ets-schnellkurs.de

        Kommentar


          #5
          Hi, nettes widget - leider funktioniert es bei mir nicht (es erscheint kein Popup) probiert in Firefox, Chrome, Edge...
          Ich habe es auch mit:
          PHP-Code:
            $("#{{ uid }}").toggle(); 
          probiert. Habe es in menu.html eingefügt, der Code ist auch im Quelltext vorhanden, alleine es gibt kein Pop-up

          Kommentar


            #6
            Moin Christian,
            ich brauche zwar keine Webcam, aber die Funktion auf eine GA zu hören und eine Extraseite aufzumachen finde ich sehr praktisch.
            Irgendwann werde ich das mal nutzen um beim verlassen des Hauses noch schnell eine Übersicht mit offenen Fenstern und so anzuzeigen. Vor allem aber um den Bildschirmschoner, denn ich innerhalb der SmartVISU nutze (Qlock2) abzuschalten, wenn man davor steht.
            Gruß, Sebastian
            Baustelle 2.0 (Detailprogrammierung und Restarbeiten)
            Ruhri? -> Komm zum Stammtisch

            Kommentar


              #7
              Zitat von Marcov Beitrag anzeigen
              Hi, nettes widget - leider funktioniert es bei mir nicht (es erscheint kein Popup) probiert in Firefox, Chrome, Edge...
              Ich habe es auch mit:
              PHP-Code:
               $("#{{ uid }}").toggle(); 
              probiert. Habe es in menu.html eingefügt, der Code ist auch im Quelltext vorhanden, alleine es gibt kein Pop-up
              Tja, was soll ich sagen. Tut mir leid! Aber bei so viel Info kann ich natürlich nicht weiterhelfen. Sorry!

              Spass beiseite: Gibt es JS Fehler in der Console?
              ++ KNX und ETS schnell, einfach und verständlich ++
              Der ultimative ETS Schnellkurs
              www.ets-schnellkurs.de

              Kommentar


                #8
                Hallo,

                ich habe heute auch versucht das Popup zu verwenden. Dazu habe ich eine Widget im Order: /var/www/smartvisu/widgets erstellt.
                Dieses habe ich dann wie hier beschrieben: widget_notification_camera.html genannt.

                Eingefügt habe ich dann folgendes:

                HTML-Code:
                /**
                * Widget for displaying camera picture / stream in case of an event
                *
                * @id unique id for this widget
                * GAD a gad/item
                */
                
                {% macro camera_popup(id, gad, image_url) %}
                
                {% set uid = uid(page, id) %}
                
                
                  &lt;script language="javascript" type="text/javascript"&gt;
                  $(document).ready(function(){
                
                    $("#{{ uid }}").toggle(false);
                    $("#notification_camera_popup_button").click(function(){
                         $("#{{ uid }}").toggle(false);
                     });
                
                  });
                  &lt;/script&gt;
                
                &lt;div class="block full-width"
                     id="{{ uid }}"
                     data-widget="notification.camera"
                     data-item="{{ gad }}"
                     data-image ="{{ image_url }}"
                     style="z-index:0; position: absolute; top: 50%; left: 50%; margin-right: -50%; transform: translate(-50%, 0%);"
                &gt;
                    &lt;div class="ui-bar-c ui-li-divider ui-corner-top"&gt;Klingel&lt;/div&gt;
                    &lt;div class="ui-fixed ui-body-a ui-corner-bottom" style="min-height: 50px"&gt;
                        &lt;img id="notification_camera_popup_picture_url" src="{{ image_url }}" width="80%" height="99%"&gt;
                        &lt;div id="notification_camera_popup_button" style="width:100px; display: block;"&gt;
                            &lt;table&gt;&lt;tr&gt;&lt;td align="left"&gt;&lt;button type="button"&gt;Schliessen&lt;/button&gt;&lt;/td&gt;&lt;td align=right&gt;&lt;button type="button" onclick="window.location='?page=cam1';"&gt;Kameraansicht&lt;/button&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                
                {% endmacro %}
                Danach habe ich wie beschrieben ein Item erstellt wie hier vorgeschlagen:

                Code:
                [Haustuer]
                    [[klingel]]
                        type = bool
                        enforce_updates = yes
                        visu_acl = rw
                        knx_dpt = 1
                        knx_listen = 5/5/0
                Als nächstes habe ich das Widget ins Menü eingebunden: /var/www/smartvisu/pages/base/menu.html

                HTML-Code:
                /**
                * -----------------------------------------------------------------------------
                * @package     smartVISU
                * @author      Martin Gleiß
                * @copyright   2012
                * @license     GPL [http://www.gnu.de]
                * -----------------------------------------------------------------------------
                */
                
                
                {% import "widget_notification_camera.html" as camera_popup %}
                
                {{ camera_popup.camera_popup('camera_popup', 'Haustuer.klingel', 'http://test:test@192.168.xxx.xxx/Streaming/channels/102/preview?snapShotImageType=JPEG') }}
                
                <div id="menu" class="menu">
                    
                    <a id="menu-rooms" class="icon1" href="index.php">
                        <img class="icon" src="{{ icon0 }}control_building_empty.svg" /></a>
                
                    <a id="menu-category" class="icon1" href="index.php?page=category">
                        <img class="icon" src="{{ icon0 }}time_manual_mode.svg" /></a>
                
                    <a id="menu-apps" class="icon1" data-ajax="false" href="index.php?page=apps">
                        <img class="icon" src="{{ icon0 }}it_net.svg" /></a>
                
                    <a id="menu-system" class="icon1" data-ajax="false" href="index.php?page=config">
                        <img class="icon" src="{{ icon0 }}edit_settings.svg" /></a>
                
                </div>
                Danach habe ich einen Neustart gemacht.

                Wenn ich es nun über den Cli mit sh.Haustuer.klingel(True) öffnen möchte passiert bei mir auch nichts. (Auch über den BUS funktioniert es leider nicht.)

                Wie kann ich testen, was ich falsch gemacht habe ? Ab und zu kommt es vor, dass wenn ich von einem Raum zurück zum Index wechsel, dass dann das Pupup abgezeigt wird.

                Gruß Manuel

                Kommentar


                  #9
                  Habe das ein bisschen verfeinert, so dass das Kamerabild nur geladen wird, wenn es tatsächlich geklingelt hat und nicht bei jedem Page refresh.
                  1) menu.html
                  Code:
                  {{ camera_popup.camera_popup('camera_popup', 'Haustuer.klingel.delayed', 'http://192.168.2.5/Streaming/channels/2/picture?auth=123456789) }}
                  hierbei nicht vergessen, dass das widget mit
                  Code:
                  {% import "widgets/widget_notification_badge.html" as notification %}
                  eingebunden werden muss.

                  2) widget_notification_camera.html
                  Code:
                  /** 
                  * Widget for displaying camera picture / stream in case of an event
                  *
                  * @id unique id for this widget
                  * GAD a gad/item
                  */
                  
                  {% macro camera_popup(id, gad, image_url) %}
                  
                  {% set uid = uid(page, id) %}
                  
                    <script language="javascript" type="text/javascript">
                    $(document).ready(function(){
                      $("#{{ uid }}").toggle(false);
                      $("#notification_camera_popup_button").click(function(){
                           $("#{{ uid }}").toggle(false);
                       });
                    });
                    </script>
                  
                  <div class="block full-width"
                       id="{{ uid }}" 
                       data-widget="notification.camera"
                       data-item="{{ gad }}" 
                       data-image ="{{ image_url }}"
                       style="z-index:0; position: absolute; top: 50%; margin-right: -50%; transform: translate(-50%, 0%);"
                  >
                      <div class="ui-bar-c ui-li-divider ui-corner-top">Klingel</div>
                      <div class="ui-fixed ui-body-a ui-corner-bottom" style="min-height: 50px">
                          <img id="notification_camera_popup_picture_url" src="" width="80%" height="99%">
                          <div id="notification_camera_popup_button" style="width:100px; display: block;">
                              <table><tr><td align="left"><button type="button">Schliessen</button></td><td align=right><button type="button" onclick="window.location='?page=kamera';">Kameraansicht</button></td></tr></table>
                          </div>
                      </div>
                  </div>
                  
                  {% endmacro %}
                  Hier gibt es leider noch das kleine Darstellungsproblem bei unterschiedlichen Browsern (iPad und Chrome auf Mac). Obiges Bsp ist für iPad optimiert.

                  3) visu.js
                  Code:
                  // ----- notification.camera -------------------------------------------------------
                  $(document).delegate('div[data-widget="notification.camera"]', {
                      'update': function (event, response) {
                          console.log("[notification.camera] update"); 
                          if (response == 1) {
                              $('#notification_camera_popup_picture_url').attr("src", $(this).attr('data-image') + Date.now());
                              $('#' + this.id).toggle(true);
                          } else {
                              // just for testing purposes
                              // to be deactivated lateron
                              // $('#' + this.id).toggle(false);
                          }
                      }
                  });
                  Ich habe das JS wohl in der ersten Beschreibung vergessen. Sorry, probiert es bitte nochmal und gebt Bescheid ob es nun tut.

                  Die Item Beschreibung ist oben.
                  ++ KNX und ETS schnell, einfach und verständlich ++
                  Der ultimative ETS Schnellkurs
                  www.ets-schnellkurs.de

                  Kommentar


                    #10
                    Hallo Christian,

                    ich bin gerade dabei es zu testen.
                    Wenn ich das widget mit
                    Code:
                     {% import "widgets/widget_notification_badge.html" as notification %}
                    einbinden will, dann bekomme ich die Meldung dass das Widget nicht gefunden wird. Wenn ich es dann so einbinde:
                    Code:
                      
                     {% import "widget_notification_badge.html" as notification %}
                    bekomme ich diese Meldung nicht mehr. Leider funktioniert das Popup auch nicht. Ich habe es im Ordner /var/www/smartvisu/widgets Was könnte ich noch testen?

                    in der visu.js habe ich das so eingefügt:

                    Code:
                    // ----------------------------------------------------------------------------
                    //
                    // Neugestaltetes UZSU Widget zur Bedienung UZSU Plugin
                    //
                    // Release v3.01
                    //
                    // Darstellung der UZSU Einträge und Darstellung Widget in Form eine Liste mit den Einträgen
                    // Umsetzung
                    // (c) Michael Würtenberger 2014,2015
                    //
                    //  APL 2.0 Lizenz
                    //
                    // Basis der Idee des dynamischen Popups übernommen von John Chacko
                    //         jQuery Mobile runtime popup
                    //         16. November 2012 · 0 Comments    
                    //         http://johnchacko.net/?p=44
                    //
                    // ----------------------------------------------------------------------------
                    // Basis der Architektur: document.update und document.click baut die handler in die Seite für das Popup ein.
                    // document.update kopiert bei einem update die Daten aus dem Backend (per Websocket) in das DOM Element ("uzsu") ein
                    // document.click übernimmt die Daten aus dem DOM Element in Variable des JS Bereichs und baut über runtimepopup
                    // dynamisch header, body und footer des popup zusammen und hängt sie an die aktuelle seite an (append, pagecreate)
                    // danach werden die Daten aus den Variablen in die Elemente der Seite kopiert. Die Elemente der Seite bilden immer
                    // den aktuellen Stand ab und werden von dort in die Variablen zurückgespeichert, wenn notwendig (save, sort).
                    // In der Struktur können Zeilen angehängt (add) oder gelöscht werden (del). Dies geschieht immer parallel in den Variablen
                    // und den Elementen der Seite. Die Expertenzeilen werden immer sofort mit angelegt, sind aber zu Beginn nicht sichtbar.
                    // Beim verlassen des Popups werden die dynamisch angelegten DOM Elemente wieder gelöscht (remove).
                    //
                    // ----------------------------------------------------------------------------
                    // set browser and platform identification variables
                    // ----------------------------------------------------------------------------
                    var browserIdentificationVariable = document.documentElement;
                        browserIdentificationVariable.setAttribute('data-useragent',navigator.userAgent);
                        browserIdentificationVariable.setAttribute('data-platform', navigator.platform);
                        browserIdentificationVariable.className += ((!!('ontouchstart' in window) || !!('onmsgesturechange' in window)) ? ' touch' : '');
                    //----------------------------------------------------------------------------
                    // Funktionen für das Handling des dicts aus dem und in das Backend
                    //----------------------------------------------------------------------------
                    function uzsuCollapseTimestring(response, designType){
                        for (var numberOfEntry = 0; numberOfEntry < response.list.length; numberOfEntry++) {
                            // und den string setzen, bei designtype = 1 bleibt er bestehen, wird nicht geändert
                            if(designType === '0'){
                                // zeitstring wieder zusammenbauen, falls Event <> 'time', damit wir den richtigen Zusammenbau im zeitstring haben
                                var timeString = '';
                                if(response.list[numberOfEntry].event === 'time'){
                                    // wenn der eintrag time ist, dann kommt die zeit rein
                                    response.list[numberOfEntry].time = response.list[numberOfEntry].timeCron;
                                }
                                else{
                                    // ansonsten wird er aus der bestandteilen zusammengebaut
                                    if(response.list[numberOfEntry].timeMin.length > 0){
                                        timeString = timeString + response.list[numberOfEntry].timeMin + '<';
                                    }
                                    timeString += response.list[numberOfEntry].event;
                                    if(response.list[numberOfEntry].timeOffset > 0){
                                        timeString = timeString + '+' + response.list[numberOfEntry].timeOffset + 'm';
                                    }
                                    else if(response.list[numberOfEntry].timeOffset < 0){
                                        timeString = timeString + response.list[numberOfEntry].timeOffset + 'm';
                                    }
                                    if(response.list[numberOfEntry].timeMax.length > 0){
                                        timeString = timeString + '<' + response.list[numberOfEntry].timeMax;
                                    }
                                    response.list[numberOfEntry].time = timeString;
                                }
                            }
                        }
                    }
                    
                    function uzsuExpandTimestring(response){
                        // ist aus cron von schedule.py aus sh.py übernommen und nach js portiert
                        var timeCron = '';
                        var timeMin = '';
                        var timeMax = '';
                        var timeOffset = '';
                        var event = '';
                        var tabsTime = '';
                        for (var numberOfEntry = 0; numberOfEntry < response.list.length; numberOfEntry++) {
                            timeCron = '';
                            tabsTime = response.list[numberOfEntry].time.split('<');
                            if(tabsTime.length == 1){
                                timeMin = '';
                                timeMax = '';
                                if (tabsTime[0].trim().indexOf('sunrise')===0){
                                    event = 'sunrise';
                                }
                                else if (tabsTime[0].trim().indexOf('sunset')===0){
                                    event = 'sunset';
                                }
                                else{
                                    event = 'time';
                                    timeCron = tabsTime[0].trim();
                                }
                            }
                            else if(tabsTime.length == 2){
                                if(tabsTime[0].indexOf('sunrise')===0){
                                    timeMin = '';
                                    event = 'sunrise';
                                    timeMax = tabsTime[1].trim();
                                }
                                else if(tabsTime[0].indexOf('sunset')===0){
                                    timeMin = '';
                                    event = 'sunset';
                                    timeMax = tabsTime[1].trim();
                                }
                                else{
                                    timeMin = tabsTime[0].trim();
                                    timeMax = '';
                                    event = tabsTime[1].trim();
                                    if(event.indexOf('sunrise')===0) event = 'sunrise'; else event = 'sunset';
                                }
                            }
                            else if(tabsTime.length == 3){
                                timeMin = tabsTime[0].trim();
                                timeMax = tabsTime[2].trim();
                                event = tabsTime[1].trim();
                                if(event.indexOf('sunrise')===0) event = 'sunrise'; else event = 'sunset';
                            }
                            else{
                                // Formatfehler ! ich nehme dann Defaulteinstellung an
                                timeMin = '';
                                event = 'time';
                                timeMax = '';
                            }
                            // nun noch der Offset herausnehmen
                            var tabsOffset = response.list[numberOfEntry].time.split('+');
                            if(tabsOffset.length == 2){
                                // dann steht ein plus drin
                                tabsOffset = tabsOffset[1].split('m');
                                timeOffset = '+' + tabsOffset[0].trim();
                            }
                            tabsOffset = response.list[numberOfEntry].time.split('-');
                            if(tabsOffset.length == 2){
                                // dann steht ein minus drin
                                tabsOffset = tabsOffset[1].split('m');
                                timeOffset = '-' + tabsOffset[0].trim();
                            }
                            // zuweisung der neuen Werte im dict
                            response.list[numberOfEntry].timeMin = timeMin;
                            response.list[numberOfEntry].timeMax = timeMax;
                            response.list[numberOfEntry].timeCron = timeCron;
                            response.list[numberOfEntry].timeOffset = timeOffset;
                            response.list[numberOfEntry].event = event;
                            if(event != 'time') response.list[numberOfEntry].timeCron = event;
                        }
                    }
                    //----------------------------------------------------------------------------
                    // Funktionen für den Seitenaufbau
                    //----------------------------------------------------------------------------
                    function uzsuBuildTableHeader(headline, designType, valueType, valueParameterList) {
                        // Kopf und überschrift des Popups
                        var template = "";
                        // hier kommt der Popup Container mit der Beschreibung ein Eigenschaften
                        template += "<div data-role='popup' data-overlay-theme='b' data-theme='a' class='messagePopup' id='uzsuPopupContent' data-dismissible = 'false'>";
                        // Schliessen Button rechts oben
                        template += "<div data-rel='back' data-role='button' data-icon='delete' data-iconpos='notext' class='ui-btn-right' id='uzsuClose'></div>";
                        // jetzt der Inhalt geklammert mit span
                        template += " <span> <div style='text-align:center'><h1>" + headline + "</h1></div>";
                        // und dann der Aufbau mit einer Tabelle. Hier muss im 2. Schritt die Formatierung über span laufen um eine Anpassung auf die aktuellen Notation hinzubekommen. Table ist leider nicht zukunftsweisend
                        template += "<table id='uzsuTable' style = 'border: 1px solid;padding-right: 3px;padding-left: 3px'> ";
                        // generell gibt es dann dispatcher für die einzelnen Formate. Ich fasse sie zusammen, wo immer es geht. Hier kann man auch die Formate für sich selbst erweitern und anpassen.
                        if(designType === '0'){
                            // Format 0 ist der Default, macht Wochentage, eine konfigurierbare Eingabe des Wertes und die Aktivierungen
                            template += "<tr><td>Value</td><td>Time</td><td>Weekdays</td><td>Active</td><td>Expert</td><td>Remove</td></tr>";
                        }
                        else{
                            // Format 1 ist der Profimodus, hier kann man in einem Textstring de facto alles auswerten
                            template += "<tr><td>Value</td><td>Time (flex)<br>RRULE</td><td>Active</td><td>Remove</td></tr>";
                        }
                        return template;
                    }
                    
                    function uzsuBuildTableRow(numberOfRow, designType, valueType, valueParameterList) {
                        // Tabelleneinträge
                        var template = "";
                        // Liste für die Wochentage, damit ich später per Index darauf zugreifen kann
                        var weekDays = [ 'MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU' ];
                        template += "<tr id='uzsuNumberOfRow" + numberOfRow + "'>";
                        // Jetzt beginnen die Spalten in der Reihenfolge value, time / rrule, active, delete button mit flipswitch (bessere Erkennbarkeit), die Texte können über das Widget gesetzt werden
                        if (valueType == 'bool') {
                            template += "<td><select name='UZSU' id='uzsuValue" + numberOfRow + "' data-role='slider' data-value = '1' data-mini='true'> <option value='0'>" + valueParameterList[1] + "</option> <option value='1'> "    + valueParameterList[0] + " </option></select></td>";
                        }
                        else if (valueType == 'num') {
                            template += "<td><input type='number' " + valueParameterList[0] + " data-clear-btn='false' class='uzsuValueInput' pattern='[0-9]*' style = 'width:50px' id='uzsuValue" + numberOfRow + "'</td>";
                        }
                        else if (valueType == 'text') {
                            template += "<td><input type='text' data-clear-btn='false' class='uzsuTextInput' style = 'width:60px' id='uzsuValue" + numberOfRow + "'</td>";
                        }
                        else if (valueType == 'list') {
                            // das Listenformat mit select ist sehr trickreich.
                            template += "<td><form><div data-role='fieldcontain' class='uzsuListInput' style = 'width:120px; height:auto !important'>";
                            template += "<select name='uzsuValue'" + numberOfRow + "' id='uzsuValue" + numberOfRow + "' data-mini='true'>";
                            for (var numberOfListEntry = 0; numberOfListEntry < valueParameterList.length; numberOfListEntry++) {
                                // Unterscheidung Anzeige und Werte
                                if (valueParameterList[0].split(':')[1] === undefined) {
                                    template += "<option value='" + valueParameterList[numberOfListEntry].split(':')[0]    + "'>"+ valueParameterList[numberOfListEntry].split(':')[0]    + "</option>";
                                }
                                else {
                                    template += "<option value='" + valueParameterList[numberOfListEntry].split(':')[1]    + "'>"+ valueParameterList[numberOfListEntry].split(':')[0]    + "</option>";
                                }
                            }
                            template += "</select></div></form></td>";
                        }
                        // time
                        if(designType === '0'){
                            template += "<td><input type='time' data-clear-btn='false' style='width:50px' class='uzsuTimeInput' id='uzsuTimeCron" + numberOfRow + "'>";
                            // rrule wurde auf die Tage verteilt
                            template += "<td><form><fieldset data-role='controlgroup' data-type='horizontal' data-mini='true'>";
                            for (var numberOfDay = 0; numberOfDay < 7; numberOfDay++) {
                                template += "<input type='checkbox' id='checkbox" + numberOfDay    + "-" + numberOfRow + "'> <label for='checkbox"    + numberOfDay + "-" + numberOfRow + "'>" + weekDays[numberOfDay] + "</label>";
                            }
                            template += "</fieldset></form></td>";
                        }
                        else{
                            // time
                            template += "<td><input type='text' data-clear-btn='true' style = 'width:350px' id='uzsuTime" + numberOfRow + "'>";
                            // rrule hier wird nur der Textstring übernommen. Prüfungen erfolgen keine !
                            template += "<input type='text' data-clear-btn='true' style = 'width:350px' id='uzsuRrule"    + numberOfRow + "'></td>";
                        }
                        // Aktive Schalter, die einzelne Zeilen der Schaltuhr aktivieren.
                        template += "<td><form><fieldset data-role='controlgroup' data-type='horizontal' data-mini='true'> " + "<input type='checkbox' id='uzsuActive"    + numberOfRow + "'> <label for='uzsuActive" + numberOfRow + "'>Act</label>" + "</fieldset></form></td>";
                        if(designType === '0'){
                            // Expert Button nur bei type = 0
                            template += "<td> <button id='uzsuExpert" + numberOfRow + "' data-mini='true' data-icon='arrow-d' data-iconpos='notext'></button></td>";
                        }
                        // del Button zum Löschen eines Zeileneintrags
                        template += "<td> <button id='uzsuDelTableRow" + numberOfRow + "' data-mini='true'>Del</button></td>";
                        // Tabelle Reihen abschliessen
                        template += "</tr>";
                        // und jetzt noch die unsichbare Expertenzeile
                        template += "<tr id='uzsuExpertLine" + numberOfRow + "' style='display:none;'><td colspan='6'><table>";
                        // Tabellenüberschriften
                        template += "<tr><td>earliest</td><td></td><td>Event</td><td>+/- min</td><td></td><td>latest</td></tr>";
                        // Tabellenfelder
                        template += "<tr><td><input type='time' data-clear-btn='false' style='width:60px' class='uzsuTimeMaxMinInput' id='uzsuTimeMin" + numberOfRow + "'</td>";
                        template += "<td> <h1 style='margin:0'> < </h1> </td>";
                        template += "<td><form><div data-role='fieldcontain' class='uzsuEvent' style = 'height:auto !important'>";
                        template += "<select name='uzsuEvent" + numberOfRow + "' id='uzsuEvent" + numberOfRow + "' data-mini='true'>";
                        template += "<option value='time'>Time</option><option value='sunrise'>Sunrise</option><option value='sunset'>Sunset</option></div></form></td>";
                        template += "<td><input type='number' data-clear-btn='false' style='width:60px' class='uzsuTimeOffsetInput' id='uzsuTimeOffset" + numberOfRow + "'</td>";
                        template += "<td> <h1 style='margin:0'> < </h1> </td>";
                        template += "<td><input type='time' data-clear-btn='false' style='width:60px' class='uzsuTimeMaxMinInput' id='uzsuTimeMax" + numberOfRow + "'</td></tr>";
                        // Abschluss des Tabelleeintrags der Expertenzeile
                        template += "</table></td></tr>";
                        return template;
                    }
                    
                    function uzsuBuildTableFooter(designType) {
                        // Anteil der Button zur steuerung des Popups
                        var template = "";
                        // Tabelle der Zeileneinträge abschliessen
                        template += "</table>";
                        // hier der Aktivierungsbutton für die gesamte uzsu
                        template += "<table style = 'border: 0'> <tr> <td> <form> <fieldset data-mini='true'> " + "<input type='checkbox' id='uzsuGeneralActive'> <label for='uzsuGeneralActive'>UZSU Activate</label>"    + "</fieldset></form> </td>";
                        // jetzt kommen noch die Buttons in der Basisleiste mit rein
                        template += "<td> <div data-role='controlgroup' data-type='horizontal' data-inline='true' data-mini='true'>";
                        template += "<div data-role = 'button' id = 'uzsuAddTableRow'> Add Entry </div>";
                        template += "<div data-role = 'button' id = 'uzsuSaveQuit'> Save&Quit</div>";
                        if (designType == '0') {
                            template += "<div data-role = 'button' id = 'uzsuSortTime'> Sort Times </div>";
                        }
                        template += "<div data-role = 'button' id = 'uzsuCancel'> Cancel </div> </td>";
                        template += "<td style = 'text-align: right'><h6> v3.01 </h6></td></div></tr></table>";
                        // Abschlus des gesamten span container
                        template += "</span>";
                        // und der Abschluss des popup divs
                        template += "</div>";
                        return template;
                    }
                    //----------------------------------------------------------------------------
                    // Funktionen für das dynamische Handling der Seiteninhalte des Popups
                    //----------------------------------------------------------------------------
                    function uzsuSetTextInputState(numberOfRow){
                        // status der eingaben setzen, das brauchen wir an mehreren stellen
                        if ($('#uzsuEvent' + numberOfRow).val() === 'time'){
                            $('#uzsuTimeMin' + numberOfRow).textinput('disable');
                            $('#uzsuTimeOffset' + numberOfRow).textinput('disable');
                            $('#uzsuTimeMax' + numberOfRow).textinput('disable');
                            // und den Zeit auf 00:00 stellen wenn von sunrise auf time umgeschaltet wird
                            if($('#uzsuTimeCron' + numberOfRow).length !== 0){
                                $('#uzsuTimeCron' + numberOfRow).textinput('enable');
                                if($('#uzsuTimeCron' + numberOfRow).val().indexOf('sun')===0)
                                    $('#uzsuTimeCron' + numberOfRow).val('00:00');
                            }
                        }
                        else{
                            $('#uzsuTimeMin' + numberOfRow).textinput('enable');
                            $('#uzsuTimeOffset' + numberOfRow).textinput('enable');
                            $('#uzsuTimeMax' + numberOfRow).textinput('enable');
                            // und den Text event auf sunrise bzw. sunset setzen, damit man ihn erkennt !
                            if($('#uzsuTimeCron' + numberOfRow).length !== 0){
                                $('#uzsuTimeCron' + numberOfRow).textinput('disable');
                                $('#uzsuTimeCron' + numberOfRow).val($('#uzsuEvent' + numberOfRow).val());
                            }
                        }
                    }
                    
                    function uzsuFillTable(response, designType, valueType, valueParameterList) {
                        // Tabelle füllen. Es werden die Daten aus der Variablen response gelesen und in den Status Darstellung der Widgetblöcke zugewiesen. Der aktuelle Status in dann in der Darstellung enthalten !
                        var numberOfEntries = response.list.length;
                        var weekDays = [ 'MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU' ];
                        // jetzt wird die Tabelle befüllt allgemeiner Status, bitte nicht mit attr, sondern mit prop, siehe    // https://github.com/jquery/jquery-mobile/issues/5587
                        $('#uzsuGeneralActive').prop('checked', response.active).checkboxradio("refresh");
                        // dann die Werte der Tabelle
                        for (var numberOfRow = 0; numberOfRow < numberOfEntries; numberOfRow++) {
                            // beim Schreiben der Daten Unterscheidung, da sonst das Element falsch genutzt wird mit Flipswitch für die bool Variante
                            if (valueType == 'bool') {
                                $('#uzsuValue' + numberOfRow).val(response.list[numberOfRow].value).slider("refresh");
                            }
                            // mit int Value für die num Variante
                            else if ((valueType == 'num') || (valueType == 'text')) {
                                $('#uzsuValue' + numberOfRow).val(response.list[numberOfRow].value);
                            }
                            else if (valueType == 'list') {
                                // hier ist es etwas schwieriger, denn ich muß den Wert mit der Liste vergleichen und dann setzen
                                for (var numberOfListEntry = 0; numberOfListEntry < valueParameterList.length; numberOfListEntry++) {
                                    // wenn ich den Eintrag gefunden haben, dann setze ich den Eintrag auf die richtige Stelle ansonsten wird einfach der erste Eintrag genomme.
                                    // zusätzlich noch die Unterscheidung, ob ich in der Listen Anzeige und Wertezuweisung trenne
                                    if (valueParameterList[0].split(':')[1] === undefined) {
                                        if (response.list[numberOfRow].value == valueParameterList[numberOfListEntry].split(':')[0]) {
                                            $('#uzsuValue' + numberOfRow).val(valueParameterList[numberOfListEntry].split(':')[0]).attr('selected',true).siblings('option').removeAttr('selected');
                                            $('#uzsuValue' + numberOfRow).selectmenu('refresh', true);
                                        }
                                    }
                                    else {
                                        if (response.list[numberOfRow].value == valueParameterList[numberOfListEntry].split(':')[1]) {
                                            $('#uzsuValue' + numberOfRow).val(valueParameterList[numberOfListEntry].split(':')[1]).attr('selected',true).siblings('option').removeAttr('selected');
                                            $('#uzsuValue' + numberOfRow).selectmenu('refresh', true);
                                        }
                                    }
                                }
                            }
                            // Values in der Zeile setzen
                            $('#uzsuActive' + numberOfRow).prop('checked',response.list[numberOfRow].active).checkboxradio("refresh");
                            $('#uzsuTime' + numberOfRow).val(response.list[numberOfRow].time);
                            $('#uzsuTimeMin'+numberOfRow).val(response.list[numberOfRow].timeMin);
                            $('#uzsuTimeOffset'+numberOfRow).val(parseInt(response.list[numberOfRow].timeOffset));
                            $('#uzsuTimeMax'+numberOfRow).val(response.list[numberOfRow].timeMax);
                            $('#uzsuTimeCron'+numberOfRow).val(response.list[numberOfRow].timeCron);
                            // und die pull down Menüs richtig, damit die Einträge wieder stimmen
                            $('#uzsuEvent'+numberOfRow).val(response.list[numberOfRow].event).attr('selected',true).siblings('option').removeAttr('selected');
                            // und der Refresh, damit es angezeigt wird
                            $('#uzsuEvent'+numberOfRow).selectmenu('refresh', true);
                            // Fallunterscheidung für den Expertenmodus
                            uzsuSetTextInputState(numberOfRow);
                            if(designType === '0'){
                                // in der Tabelle die Werte der rrule, dabei gehe ich von dem Standardformat FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU aus und setze für jeden Eintrag den Button.
                                var rrule = response.list[numberOfRow].rrule;
                                if (typeof rrule == "undefined") {
                                    rrule = '';
                                }
                                var ind = rrule.indexOf('BYDAY');
                                // wenn der Standard drin ist
                                if (ind > 0) {
                                    var days = rrule.substring(ind);
                                    // Setzen der Werte
                                    for (var numberOfDay = 0; numberOfDay < 7; numberOfDay++) {
                                        $('#checkbox' + numberOfDay + '-' + numberOfRow).prop('checked', days.indexOf(weekDays[numberOfDay]) > 0).checkboxradio("refresh");
                                    }
                                }
                            }
                            else{
                                // wenn Experte, dann einfach nur den String
                                $('#uzsuRrule' + numberOfRow).val(response.list[numberOfRow].rrule);
                            }
                        }
                    }
                    
                    function uzsuSaveTable(item, response, designType, valueType, valueParameterList,
                            saveSmarthome) {
                        // Tabelle auslesen und speichern
                        var numberOfEntries = response.list.length;
                        var weekDays = [ 'MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU' ];
                        // hier werden die Daten aus der Tabelle wieder in die items im Backend zurückgespielt bitte darauf achten, dass das zurückspielen exakt dem der Anzeige enspricht. Gesamthafte Aktivierung
                        response.active = $('#uzsuGeneralActive').is(':checked');
                        // Einzeleinträge
                        for (var numberOfRow = 0; numberOfRow < numberOfEntries; numberOfRow++) {
                            response.list[numberOfRow].value = $('#uzsuValue' + numberOfRow).val();
                            response.list[numberOfRow].active = $('#uzsuActive' + numberOfRow).is(':checked');
                            response.list[numberOfRow].time = $('#uzsuTime'+numberOfRow).val();
                            response.list[numberOfRow].timeMin = $('#uzsuTimeMin'+numberOfRow).val();
                            response.list[numberOfRow].timeOffset = $('#uzsuTimeOffset'+numberOfRow).val();
                            response.list[numberOfRow].timeMax = $('#uzsuTimeMax'+numberOfRow).val();
                            response.list[numberOfRow].timeCron = $('#uzsuTimeCron'+numberOfRow).val();
                            response.list[numberOfRow].event = $('#uzsuEvent'+numberOfRow).val();
                            if(designType === '0'){
                                // in der Tabelle die Werte der rrule, dabei gehe ich von dem Standardformat FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU aus und setze für jeden Eintrag den Button. Setzen der Werte.
                                var first = true;
                                var rrule = '';
                                for (var numberOfDay = 0; numberOfDay < 7; numberOfDay++) {
                                    if ($('#checkbox' + numberOfDay + '-' + numberOfRow).is(':checked')) {
                                        if (first) {
                                            first = false;
                                            rrule = 'FREQ=WEEKLY;BYDAY=' + weekDays[numberOfDay];
                                        }
                                        else {
                                            rrule += ',' + weekDays[numberOfDay];
                                        }
                                    }
                                }
                                response.list[numberOfRow].rrule = rrule;
                            }
                            else{
                                // hier wird der String direkt übergeben
                                response.list[numberOfRow].rrule = $('#uzsuRrule' + numberOfRow).val();
                            }
                        }
                        // über json Interface / Treiber herausschreiben
                        if (saveSmarthome) {
                            uzsuCollapseTimestring(response, designType);
                            io.write(item, {active : response.active,list : response.list});
                        }
                    }
                    //----------------------------------------------------------------------------
                    // Funktionen für das Erweitern und Löschen der Tabelleneinträge
                    //----------------------------------------------------------------------------
                    function uzsuAddTableRow(response, designType, valueType, valueParameterList) {
                        // Tabellenzeile einfügen
                        var numberOfNewRow = response.list.length;
                        var template = '';
                        // alten Zustand mal in die Liste rein. da der aktuelle Zustand ja nur im Widget selbst enthalten ist, wird er vor dem Umbau wieder in die Variable response zurückgespeichert.
                        uzsuSaveTable(1, response, designType, valueType, valueParameterList, false);
                        // ich hänge immer an die letzte Zeile dran ! erst einmal das Array erweitern
                        response.list.push({active:false,rrule:'',time:'00:00',value:0,event:'time',timeMin:'',timeMax:'',timeCron:'00:00',timeOffset:''});
                        // dann eine neue HTML Zeile genenrieren
                        template = uzsuBuildTableRow(numberOfNewRow, designType, valueType,    valueParameterList);
                        // Zeile in die Tabelle einbauen
                        $('#uzsuTable').append(template);
                        // hier wichtig: damit die Optimierung jquerymobile auf Tabelle wirkt
                        $.mobile.activePage.trigger('pagecreate');
                        // den delete Handler für die neue Zeile einhängen
                        $.mobile.activePage.find('#uzsuDelTableRow' + numberOfNewRow).bind('tap',function(e) {
                            uzsuDelTableRow(response, designType, valueType,valueParameterList, e);
                        });
                        // den helper Handler für die neue Zeile einhängen
                        $.mobile.activePage.find('#uzsuExpert' + numberOfNewRow).bind('tap', function(e) {
                            uzsuShowExpertLine(e);
                        });    
                        // und Daten ausfüllen. hier werden die Zeile wieder mit dem Status beschrieben. Status ist dann wieder im Widget
                        uzsuFillTable(response, designType, valueType, valueParameterList);
                    }
                    
                    function uzsuDelTableRow(response, designType, valueType, valueParameterList, e) {
                        // Tabellenzeile löschen
                        var numberOfEntries = response.list.length;
                        // wenn überhaupt Einträge vorhanden sind sollte nicht passieren, weil eigentlich auch kein Button dann da ist, aber...
                        if (numberOfEntries > 0) {
                            // Index heraussuchen, in welcher Zeile gelöscht wurde
                            var numberOfRowToDelete = parseInt(e.currentTarget.id.substr(15));
                            // zwischenspeichern vor dem löschen
                            uzsuSaveTable(1, response, designType, valueType, valueParameterList, false);
                            // erst mal das Array entsprechen kürzen
                            response.list.splice(numberOfRowToDelete, 1);
                            // jetzt die Tabelle kürzen im Popup
                            $('#uzsuNumberOfRow' + (numberOfEntries - 1)).remove();
                            // und Daten wieder ausfüllen
                            uzsuFillTable(response, designType, valueType, valueParameterList);
                        }
                    }
                    
                    function uzsuShowExpertLine(e) {
                        // Tabellezeile ermitteln, wo augerufen wurde. es ist die 10. Stelle des aufrufenden Objektes
                        var numberOfRow = parseInt(e.currentTarget.id.substr(10));
                        /// Zeile anzeigen
                        $('#uzsuExpertLine' + numberOfRow).css('display','');
                        // jetzt noch den Button in der Zeile drüber auf arrow up ändern
                        $('#uzsuExpert' + numberOfRow).buttonMarkup({ icon: 'arrow-u' });
                        // und den Callback ändern
                        $.mobile.activePage.find('#uzsuExpert' + numberOfRow).unbind('tap');
                        $.mobile.activePage.find('#uzsuExpert' + numberOfRow).bind('tap', function(e) {
                            // propagation stoppen, sonst wird die Zeile gleich wieder aufgemacht
                            e.stopImmediatePropagation();
                            uzsuHideExpertLine(e);
                        });
                        // Handler, um je nach Event die inputs zu Aktivieren / Deaktiovieren
                        // reagiert auf die Änderung des Pulldown Menüs
                        $.mobile.activePage.find('#uzsuEvent' + numberOfRow).on('change', function (){
                            uzsuSetTextInputState(numberOfRow);
                        });
                    }
                    
                    function uzsuHideExpertLine(e) {
                        // Tabellezeile ermitteln, wo augerufen wurde. es ist die 10. Stelle des aufrufenden Objektes
                        var numberOfRow = parseInt(e.currentTarget.id.substr(10));
                        // tabellenzeile löschen
                        if ($('#uzsuExpertLine'+numberOfRow)) {
                            // jetzt die Tabelle kürzen im Popup
                            $('#uzsuExpertLine'+numberOfRow).css('display','none');
                            // jetzt noch den Button in der Zeile drüber ändern auf arrow down
                            $('#uzsuExpert'+ numberOfRow).buttonMarkup({ icon: 'arrow-d' });
                            // und den Callback ändern
                            $.mobile.activePage.find('#uzsuExpert'+ numberOfRow).unbind('tap');
                            $.mobile.activePage.find('#uzsuExpert'+ numberOfRow).bind('tap', function(e) {
                                // Propagation stoppen, sonst wird die Zeile gleich wieder aufgemacht
                                e.stopImmediatePropagation();
                                uzsuShowExpertLine(e);
                            });
                        }
                    }
                    //----------------------------------------------------------------------------
                    // Funktionen für das Sortrieren der Tabelleneinträge
                    //----------------------------------------------------------------------------
                    function uzsuSortFunction(a, b) {
                        // sort Funktion, wirklich vereinfacht für den speziellen Fall
                        // ergänzt um das sunrise und sunset Thema
                        var A = a.timeCron.replace(':', '');
                        var B = b.timeCron.replace(':', '');
                        // Reihenfolge ist erst die Zeiten, dann sunrise, dann sunset
                        if(A == 'sunrise') A = '2400';
                        if(A == 'sunset') A = '2400';
                        if(B == 'sunrise') B = '2401';
                        if(B == 'sunset') B = '2401';
                        return (A - B);
                    }
                    
                    function uzsuSortTime(response, designType, valueType, valueParameterList, e) {
                        // erst aus dem Widget zurücklesen, sonst kann nicht im Array sortiert werden (alte daten)
                        uzsuSaveTable(1, response, designType, valueType, valueParameterList, false);
                        // sortieren der Listeneinträge nach zeit
                        response.list.sort(uzsuSortFunction);
                        // dann die Einträge wieder schreiben
                        uzsuFillTable(response, designType, valueType, valueParameterList);
                    }
                    //----------------------------------------------------------------------------
                    // Funktionen für den Aufbau des Popups und das Einrichten der Callbacks
                    //----------------------------------------------------------------------------
                    function uzsuRuntimePopup(response, headline, designType, valueType, valueParameterList, item) {
                        // Steuerung des Popups erst einmal wird der Leeranteil angelegt
                        // erst den Header, dann die Zeilen, dann den Footer
                        var template = uzsuBuildTableHeader(headline, designType, valueType, valueParameterList);
                        for (var numberOfRow = 0; numberOfRow < response.list.length; numberOfRow++) {
                            template += uzsuBuildTableRow(numberOfRow, designType, valueType, valueParameterList);
                        }
                        template += uzsuBuildTableFooter(designType);
                        // dann hängen wir das an die aktuelle Seite
                        $.mobile.activePage.append(template).trigger('pagecreate');
                        // dann speichern wir uns für cancel die ursprünglichen im DOM gespeicherten Werte in eine Variable ab
                        var responseCancel = jQuery.extend(true, {}, response);
                        // dann die Werte eintragen.
                        uzsuFillTable(response, designType, valueType, valueParameterList);
                        // Popup schliessen mit close rechts oben in der Box
                        $.mobile.activePage.find('#uzsuClose').bind('tap', function(e) {
                            // wenn keine Änderungen gemacht werden sollen (cancel), dann auch im cache die alten Werte
                            $.mobile.activePage.find('#uzsuPopupContent').popup('close');
                        });
                        // Popup schliessen mit Cancel in der Leiste
                        $.mobile.activePage.find('#uzsuCancel').bind('tap', function(e) {
                            // wenn keine Änderungen gemacht werden sollen (cancel), dann auch im cache die alten Werte
                            $.mobile.activePage.find('#uzsuPopupContent').popup('close');
                        });
                        // speichern mit SaveQuit
                        $.mobile.activePage.find('#uzsuSaveQuit').bind('tap', function(e) {
                            // jetzt wird die Kopie auf das Original kopiert und geschlossen
                            uzsuSaveTable(item, response, designType, valueType, valueParameterList, true);
                            $.mobile.activePage.find('#uzsuPopupContent').popup('close');
                        });
                        // Eintrag hinzufügen mit add
                        $.mobile.activePage.find('#uzsuAddTableRow').bind('tap', function(e) {
                            uzsuAddTableRow(response, designType, valueType, valueParameterList);
                        });
                        // Eintrag sortieren nach Zeit
                        $.mobile.activePage.find('#uzsuSortTime').bind('tap', function(e) {
                            uzsuSortTime(response, designType, valueType, valueParameterList);
                        });
                        // Löschen mit del als Callback eintragen
                        for (numberOfRow = 0; numberOfRow < response.list.length; numberOfRow++) {
                            $.mobile.activePage.find('#uzsuDelTableRow' + numberOfRow).bind('tap',function(e) {
                                uzsuDelTableRow(response, designType, valueType, valueParameterList, e);
                            });
                            // call Expert Mode
                            $.mobile.activePage.find('#uzsuExpert'+ numberOfRow).bind('tap', function(e) {
                                uzsuShowExpertLine(e);
                            });
                        }
                        // hier wir die aktuelle Seite danach durchsucht, wo das Popup ist und im folgenden das Popup initialisiert, geöffnet und die schliessen
                        // Funktion daran gebunden. Diese entfernt wieder das Popup aus dem DOM Baum nach dem Schliessen mit remove
                        $.mobile.activePage.find('#uzsuPopupContent').popup('open').bind({
                            popupafterclose: function () {
                                $(this).remove();
                            }
                        });
                    }
                    //----------------------------------------------------------------------------
                    //Funktionen für das Verankern des Popup auf den Webseiten
                    //----------------------------------------------------------------------------
                    function uzsuDomUpdate(event, response) {
                        // Initialisierung zunächst wird festgestellt, ob Item mit Eigenschaft vorhanden. Wenn nicht: active = false
                        // ansonsten ist der Status von active gleich dem gesetzten Status
                        var active = response.length > 0 ? response[0].active : false;
                        // Das Icon wird aktiviert, falls Status auf aktiv, ansonsten deaktiviert angezeigt
                        $('#' + this.id + ' img').attr('src',(active ? $(this).attr('data-pic-on') : $(this).attr('data-pic-off')));
                        // wenn keine Daten vorhanden, dann ist kein item mit den eigenschaften hinterlegt und es wird nichts gemacht
                        if (response.length === 0){
                            alert('DOM Daten für UZSU nicht vorhanden! Item falsch konfiguriert oder nicht vorhanden ! (update-event)');
                            return;
                        }
                        // Wenn ein Update erfolgt, dann werden die Daten erneut in die Variable uzsu geladen damit sind die UZSU objekte auch in der click Funktion verfügbar
                        if (response[0].list instanceof Array) {
                            $(this).data('uzsu', response[0]);
                        }
                        else {$(this).data('uzsu', {active : true,list : []    });
                        }
                    }
                    
                    function uzsuDomClick(event) {
                        // hier werden die Parameter aus den Attributen herausgenommen und beim Öffnen mit .open(....) an das Popup Objekt übergeben
                        // und zwar mit deep copy, damit ich bei cancel die ursprünglichen werte nicht überschrieben habe
                        var response = jQuery.extend(true, {}, $(this).data('uzsu'));
                        // erst gehen wir davon aus, dass die Prüfungen positiv und ein Popup angezeigt wird
                        var popupOk = true;
                        // Fehlerbehandlung für ein nicht vorhandenes DOM Objekt. Das response Objekt ist erst da, wenn es mit update angelegt wurde. Da diese
                        // Schritte asynchron erfolgen, kann es sein, dass das Icon bereits da ist, clickbar, aber nocht keine Daten angekommen. Dann darf ich nicht
                        // auf diese Daten zugreifen wollen !
                        if(response.list === undefined){
                            alert('DOM Daten für UZSU nicht vorhanden! Item falsch konfiguriert oder nicht vorhanden ! (click-event)');
                            popupOk = false;
                        }
                        else
                        {
                            // jetzt erweitern wir die dicts pro Eintrag, um dem dort einhaltenen Timestring die enthaltenen Einzelteile zu bekommen
                            uzsuExpandTimestring(response);
                        }
                         // Auswertung der Übergabeparameter
                        var headline = $(this).attr('data-headline');
                        var designType = $(this).attr('data-designType');
                        var valueType = $(this).attr('data-valueType');
                        // hier wird die komplette Liste übergeben. widget.explode kehrt das implode aus der Webseite wieder um
                        var valueParameterList = widget.explode($(this).attr('data-valueParameterList'));
                        // default Werte setzen fuer valueParameterList
                        if(valueParameterList.length === 0){
                            if(valueType === 'bool') valueParameterList = ['On','Off'];
                            else if (valueType === 'num') valueParameterList = [''];
                            else if (valueType === 'text') valueParameterList = [''];
                            else if (valueType === 'list') valueParameterList = [''];
                        }
                        // data-item ist der sh.py item, in dem alle Attribute lagern, die für die Steuerung notwendig ist ist ja vom typ dict. das item, was tatsächlich per
                        // Schaltuhr verwendet wird ist nur als attribut (child) enthalten und wird ausschliesslich vom Plugin verwendet. wird für das rückschreiben der Daten an smarthome.py benötigt
                        var item = $(this).attr('data-item');
                        // jetzt kommt noch die Liste von Prüfungen, damit hinterher keine Fehler passieren, zunächst fehlerhafter designType (unbekannt)
                        if ((designType !== '0') && (designType !== '1')) {
                            alert('Fehlerhafter Parameter: "' + designType + '" im Feld designType bei Item ' + item);
                            popupOk = false;
                        }
                        // fehlerhafter valueType (unbekannt)
                        if ((valueType !== 'bool') && (valueType !== 'num')    && (valueType !== 'text') && (valueType !== 'list')) {
                            alert('Fehlerhafter Parameter: "' + valueType + '" im Feld valueType bei Item ' + item);
                            popupOk = false;
                        }
                        // bei designType '0' wird rrule nach Wochentagen umgewandelt und ein festes Format vogegegeben hier sollte nichts versehentlich überschrieben werden
                        if (designType == '0') {
                            var numberOfEntries = response.list.length;
                            for (var numberOfRow = 0; numberOfRow < numberOfEntries; numberOfRow++) {
                                // test, ob die RRULE fehlerhaft ist
                                if ((response.list[numberOfRow].rrule.indexOf('FREQ=WEEKLY;BYDAY=') !== 0) && (response.list[numberOfRow].rrule.length > 0)) {
                                    if (!confirm('Fehler: Parameter designType ist "0", aber gespeicherte RRULE String in UZSU "' + response.list[numberOfRow].rrule + '" entspricht nicht default Format FREQ=WEEKLY;BYDAY=MO... bei Item ' + item    + '. Soll dieser Eintrag überschrieben werden ?')) {
                                        // direkter Abbruch bei der Entscheidung !
                                        numberOfRow = numberOfEntries;
                                        popupOk = false;
                                    }
                                }
                            }
                        }
                        // wenn bei designType = 'list' ein Split angegeben wird, dann muss er immer angegeben sein
                        if ((valueType == 'list') && (valueParameterList[0].split(':')[1] !== undefined)) {
                            for (var numberOfTextEntries = 0; numberOfTextEntries < valueParameterList.length; numberOfTextEntries++) {
                                if (valueParameterList[numberOfTextEntries].split(':')[1] === undefined) {
                                    alert('Fehlerhafte Einträge im Parameter valueParameterList !');
                                    popupOk = false;
                                }
                            }
                        }
                        if (popupOk) {
                            // Öffnen des Popups bei clicken des icons und Ausführung der Eingabefunktion
                            uzsuRuntimePopup(response, headline, designType, valueType, valueParameterList, item);
                        }
                    }
                    // Verankerung als Callback in den DOM Elementen
                    $(document).on('update','[data-widget="uzsu.uzsu_icon"]', uzsuDomUpdate);
                    $(document).on('click','[data-widget="uzsu.uzsu_icon"]', uzsuDomClick);
                    
                    
                    
                    // ----- notification.camera -------------------------------------------------------
                    $(document).delegate('div[data-widget="notification.camera"]', {
                        'update': function (event, response) {
                            console.log("[notification.camera] update");
                            if (response == 1) {
                                $('#notification_camera_popup_picture_url').attr("src", $(this).attr('data-image') + Date.now());
                                $('#' + this.id).toggle(true);
                            } else {
                                // just for testing purposes
                                // to be deactivated lateron
                                // $('#' + this.id).toggle(false);
                            }
                        }
                    });
                    Gruß Manuel

                    Zuletzt geändert von manu241; 05.02.2016, 21:39.

                    Kommentar


                      #11
                      Zitat von manu241 Beitrag anzeigen
                      Hallo Christian,

                      ich bin gerade dabei es zu testen.
                      Wenn ich das widget mit
                      Code:
                      {% import "widgets/widget_notification_badge.html" as notification %}
                      einbinden will, dann bekomme ich die Meldung dass das Widget nicht gefunden wird. Wenn ich es dann so einbinde:
                      Code:
                      {% import "widget_notification_badge.html" as notification %}
                      bekomme ich diese Meldung nicht mehr.

                      Leider funktioniert das Popup auch nicht. Ich habe es im Ordner /var/www/smartvisu/widgets Was könnte ich noch testen?
                      in der visu.js habe ich das so eingefügt:...
                      Es sollte klar sein, dass die Verzeichnisstruktur angepasst werden muss. Aber dann passt es ja jetzt.
                      Weiterhin ist es sehr schwierig, etwas remotely zu debuggen, wenn man nur den Source Code zur Verfügung gestellt bekommt, den man ja selber geschrieben hat und der bei einem selbst funktioniert.
                      Bitte schau in Dein sh.py log ob da Fehlermeldungen sind.
                      Ausserdem auch in der JS-Console vom Browser (unter Chrome: Anzeigen-Entwickler-Javascript-Konsole) nachsehen und dann etwaiges posten.
                      ++ KNX und ETS schnell, einfach und verständlich ++
                      Der ultimative ETS Schnellkurs
                      www.ets-schnellkurs.de

                      Kommentar


                        #12
                        Ich greife das hier noch einmal auf.....

                        Die Anleitung hinkt an der ein oder anderen Stelle. Funktioniert nach Anpassung aber trotzdem:

                        In der menu.html:
                        Code:
                        {% import "widget_notification_camera.html" as campopup %}
                        {{ campopup.camera_popup('camera_popup', 'EG.Raum1.Tuer', 'http://192.168.178.xx/snap.jpg?JpegCam=1') }}
                        Das Widget (widget_notification_camera.html):
                        Code:
                        /**
                        * Widget for displaying camera picture / stream in case of an event
                        *
                        * @id unique id for this widget
                        * GAD a gad/item
                        */
                        
                        {% macro camera_popup(id, gad, image_url) %}
                        
                        {% set uid = uid(page, id) %}
                        
                          <script language="javascript" type="text/javascript">
                          $(document).ready(function(){
                            $("#{{ uid }}").toggle(false);
                            $("#notification_camera_popup_button").click(function(){
                                 $("#{{ uid }}").toggle(false);
                             });
                          });
                          </script>
                        
                        <div class="block full-width"
                             id="{{ uid }}"
                             data-widget="notification.camera"
                             data-item="{{ gad }}"
                             data-image ="{{ image_url }}"
                             style="z-index:0; position: absolute; top: 50%; margin-right: 50%; transform: translate(50%, 0%);"
                        >
                            <div class="ui-bar-c ui-li-divider ui-corner-top">Klingel</div>
                            <div class="ui-fixed ui-body-a ui-corner-bottom" style="min-height: 50px">
                                <img id="notification_camera_popup_picture_url" src="" width="80%" height="99%">
                                <div id="notification_camera_popup_button" style="width:100px; display: block;">
                                    <table><tr><td align="left"><button type="button">Schliessen</button></td><td align=right><button type="button" onclick="window.location='?page=Kameras';">Kameraansicht</button></td></tr></table>
                                </div>
                            </div>
                        </div>
                        
                        {% endmacro %}
                        visu.js:
                        Code:
                        // ----- notification.camera -------------------------------------------------------
                        $(document).delegate('div[data-widget="notification.camera"]', {
                            'update': function (event, response) {
                                console.log("[notification.camera] update");
                                if (response == 1) {
                                    $('#notification_camera_popup_picture_url').attr("src", $(this).attr('data-image') + Date.now());
                                    $('#' + this.id).toggle(true);
                                } else {
                                    // just for testing purposes
                                    // to be deactivated lateron
                                    // $('#' + this.id).toggle(false);
                                }
                            }
                        });
                        Grüße, Marc

                        Kommentar


                          #13
                          Hi Marc.
                          Öffnet sich bei dir das PopUp in SV 2.8? In der Console sehe ich zwar, dass das "[notification.camera] update" ausgeführt wird, aber beim Wechsel des GAD von false auf true passiert nichts.
                          Danke für deine Hilfe.

                          Kommentar


                            #14
                            Hallo, ja bei mir läuft das gut.
                            gucke mal ob du das Popup verschieben kannst.
                            Eventuell liegt das Fenster außerhalb des sichtbaren Bereichs.
                            Im Widget:
                            Code:
                             style="z-index:0; position: absolute; top: 50%; margin-right: 50%; transform: translate(50%, 0%);"
                            Ich habe das Widget dann auch in der Menu.html eingebunden. Sonst liegt das Popup hinter den anderen Seiten. Da sollte man es aber zumindestens noch sehen. Nur die Icons sind dann überlagert.
                            Zuletzt geändert von schuma; 22.12.2016, 12:01.

                            Kommentar


                              #15
                              Das Popup funktioniert bei mir in SV 2.8 auf dem Ipad und auch im Firefox

                              Ich habe jedoch ein Problem mit der Anzeige des Bildes.
                              Code:
                              {{ campopup.camera_popup('camera_popup', 'haustuer.klingel', 'http://xxxx:xxxxx@10.1.1.1/Streaming/channels/1/picture') }}
                              Im Browser und Multimedia Widget funktioniert der Link.

                              Im Popup Windows wird jedoch z.B.als Link
                              Code:
                              http://10.1.1.1/Streaming/channels/1/picture47835792
                              übergeben und kein Bild angezeigt

                              Ich habe mal testweise in dem widget_notification_camera.html

                              Code:
                                {{ multimedia.image('image2', 'http://xxxx:xxxxx@10.1.1.1/Streaming/channels/1/picture', 'fill','2s') }}
                              eingefügt. Dann sehe ich das Bild.

                              jemand eine Idee?
                              Gruß von der Weser
                              Michael

                              Meine Installation: VM Debian Stretch SH NG 1.6, SmartVISU 2.9, KNX, DMX, 1-wire, Cisco ASA 5512X IPS, VMware vSphere 6.7

                              Kommentar

                              Lädt...
                              X