FTUI eigene Widgets: Unterschied zwischen den Versionen

Aus FHEMWiki
(Die Seite wurde neu angelegt: „Eigene Widgets für FTUI zu erstellen ist relativ einfach. Dafür muss nur eine widget_mywidget.js im js-Folder neben den anderen Widgets angelegt werden. EIn…“)
 
Keine Bearbeitungszusammenfassung
 
(10 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
Eigene Widgets für FTUI zu erstellen ist relativ einfach. Dafür muss nur eine widget_mywidget.js im js-Folder neben den anderen Widgets angelegt werden.
Eigene Widgets für [[FHEM Tablet UI V2]] zu erstellen ist relativ einfach. Im Folgenden nennen wir dieses neue Widget "mywidget" Dafür muss zunächst eine widget_mywidget.js im js-Folder neben den anderen Widgets angelegt werden.


EIne Minimalvariante eine widget_mywidget.js Datei könnte so aussehen:
Eine Minimalvariante einer widget_mywidget.js-Datei könnte so aussehen:


<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Zeile 24: Zeile 24:
</syntaxhighlight>
</syntaxhighlight>


Am Ende der Datei steht die Definition der Public Parameter. Neben dem Namen müssen mindestens die beiden Funktionen '''init()''' und '''update()''' implementiert sein.
Am Ende der Datei steht die Definition der Public-Parameter. Neben dem Namen müssen mindestens die beiden Funktionen '''init()''' und '''update()''' implementiert sein.


init() wird einmal gleich nach dem Laden des Plugins aufgerufen, update() jedesmal, wenn Änderungen von Readings passieren.  
'''init()''' wird einmal gleich nach dem Laden des Plugins aufgerufen, '''update()''' jedesmal, wenn Änderungen von Readings passieren.  


Dieses FTUI-Plugin kann man jetzt so einbinden
Dieses FTUI-Plugin kann man jetzt so einbinden:


<syntaxhighlight lang="html">
<syntaxhighlight lang="html">
Zeile 35: Zeile 35:




Wenn das Plugin für ein UI-Control sein soll, was mehrfach auf der Seite vorkommt, kann man im init() per each() durch alle Elemente iterieren
Wenn das Plugin für ein UI-Control sein soll, das mehrfach auf der Seite vorkommt, kann man im '''init()''' per '''each()''' durch alle Elemente iterieren:


<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Zeile 47: Zeile 47:




Updates werden aber nur gerufen, wenn man die entsprechenden Readings beim init() abonniert. Das passiert mit '''addReading();''' (Funktion ist enthalten im Base-Widget: Modul_widget)
Wenn ein Plugin Daten abrufen soll, die NICHT in einem Reading von FHEM enthalten sind, empfiehlt es sich, eine Klasse zu definieren:


In diesem Beispiel fügen wir das Reading hinzu, was im data-get angegeben ist. Wir legen gleich noch als Default das Reading 'STATE' fest, für den Fall, dass data-get im HTML Code fehlt. Das passiert mit '''elem.initData();'''
<syntaxhighlight lang="html">
<div class="neueklasse" data-type="blabla" data-device='test-device' data-get='neueklasse'>}
</syntaxhighlight>
 
Im JS kann man dann so diese Elemente auswählen bzw ihnen etwas zuweisen:
<syntaxhighlight lang="javascript">
if (elem.is('.neueklasse')) {
  elem.html(text);
}
</syntaxhighlight>
 
Nicht vergessen: Wenn hier Daten aus Readings abgefragt werden sollen, müssen diese Readings in init() abonniert werden:
<syntaxhighlight lang="javascript">
  elem.initData('reading123', 'testreading');
  me.addReading(elem, 'reading123');
</syntaxhighlight>
 
Und dann in der Update-Routine muss auf diese Readings geprüft werden:
<syntaxhighlight lang="javascript">
me.elements.filterDeviceReading('reading123', dev, par)
  .add(me.elements.filterDeviceReading('testreading', dev, par))
</syntaxhighlight>
Nur dann werden die Elemente bei Updates aus fhem auch aktualisiert.
 
Ausserdem empfiehlt es sich natürlich in fhem bei den betroffenen Devices ein
 
<code>
attr device event-on-change-reading .*
</code>
 
zu machen!
 
Updates werden aber nur gerufen, wenn man die entsprechenden Readings beim '''init()''' abonniert. Das passiert mit '''addReading();''' (Funktion ist enthalten im Base-Widget: Modul_widget)
 
In diesem Beispiel fügen wir das Reading hinzu, das im Attribut '''data-get''' angegeben ist. Wir legen gleich noch als Default das Reading 'STATE' fest, für den Fall, dass data-get im HTML Code fehlt. Das passiert mit '''elem.initData();'''


<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Zeile 65: Zeile 99:
</syntaxhighlight>
</syntaxhighlight>


Dann können wir unter update() auf die Notifizierungen warten.  
Dann können wir unter '''update()''' auf die Notifizierungen warten. Wir filtern mit '''elements.filterDeviceReading()''' die Elemente heraus, die unter '''data-get''' das aktualisierte Reading haben und holen mit '''elem.getReading().val''' den aktuell bekannten Wert aus dem lokalen Cache.  
Wir filter mit '''elements.filterDeviceReading()''' die Elemente heraus, die unter data-get das aktualisierte Reading haben und holen mit  
'''elem.getReading().val''' den aktuell bekannten Wert aus dem lokalen Cache.  


'''elem.getReading().date''' würde den Zeitstempel des Readings liefern.
'''elem.getReading().date''' würde den Zeitstempel des Readings liefern.
Zeile 123: Zeile 155:
</syntaxhighlight>
</syntaxhighlight>


Im HTML würde an das jetzt so nutzen können.
Im HTML würde man das jetzt so nutzen können.


<syntaxhighlight lang="html">
<syntaxhighlight lang="html">
<div data-type="mywidget" data-device='AvReceiver' data-get='volume'></div>
<div data-type="mywidget" data-device='AvReceiver' data-get='volume'></div>
</syntaxhighlight>
</syntaxhighlight>
Wem das noch nicht genug war, der kann sich ein weiterführendes Praxisbeispiel unter [[FTUI eigene Widgets - Beispiel]] ansehen.
[[Kategorie:FHEM Tablet UI V2|Widgets]]

Aktuelle Version vom 3. August 2024, 09:34 Uhr

Eigene Widgets für FHEM Tablet UI V2 zu erstellen ist relativ einfach. Im Folgenden nennen wir dieses neue Widget "mywidget" Dafür muss zunächst eine widget_mywidget.js im js-Folder neben den anderen Widgets angelegt werden.

Eine Minimalvariante einer widget_mywidget.js-Datei könnte so aussehen:

var Modul_mywidget = function () {

    function init() {
        alert('init called');
    }

    function update(device, reading) {
        alert('update called for' + device + ':' + reading );
    }

    var me = $.extend(new Modul_widget(), {
        widgetname: 'mywidget',
        init: init,
        update: update,
    });

    return me;
};

Am Ende der Datei steht die Definition der Public-Parameter. Neben dem Namen müssen mindestens die beiden Funktionen init() und update() implementiert sein.

init() wird einmal gleich nach dem Laden des Plugins aufgerufen, update() jedesmal, wenn Änderungen von Readings passieren.

Dieses FTUI-Plugin kann man jetzt so einbinden:

<div data-type="mywidget"></div>


Wenn das Plugin für ein UI-Control sein soll, das mehrfach auf der Seite vorkommt, kann man im init() per each() durch alle Elemente iterieren:

function init() {
     me.elements = $('[data-type="' + me.widgetname + '"]');
     me.elements.each(function (index) {
         alert('init #' + index + ' called');
    });
}


Wenn ein Plugin Daten abrufen soll, die NICHT in einem Reading von FHEM enthalten sind, empfiehlt es sich, eine Klasse zu definieren:

<div class="neueklasse" data-type="blabla" data-device='test-device' data-get='neueklasse'>}

Im JS kann man dann so diese Elemente auswählen bzw ihnen etwas zuweisen:

if (elem.is('.neueklasse')) {
   elem.html(text);	
}

Nicht vergessen: Wenn hier Daten aus Readings abgefragt werden sollen, müssen diese Readings in init() abonniert werden:

   elem.initData('reading123', 'testreading');
   me.addReading(elem, 'reading123');

Und dann in der Update-Routine muss auf diese Readings geprüft werden:

me.elements.filterDeviceReading('reading123', dev, par)
		  .add(me.elements.filterDeviceReading('testreading', dev, par))

Nur dann werden die Elemente bei Updates aus fhem auch aktualisiert.

Ausserdem empfiehlt es sich natürlich in fhem bei den betroffenen Devices ein

attr device event-on-change-reading .*

zu machen!

Updates werden aber nur gerufen, wenn man die entsprechenden Readings beim init() abonniert. Das passiert mit addReading(); (Funktion ist enthalten im Base-Widget: Modul_widget)

In diesem Beispiel fügen wir das Reading hinzu, das im Attribut data-get angegeben ist. Wir legen gleich noch als Default das Reading 'STATE' fest, für den Fall, dass data-get im HTML Code fehlt. Das passiert mit elem.initData();

function init() {

    me.elements = $('div[data-type="' + me.widgetname + '"]', me.area);
    me.elements.each(function (index) {

        var elem = $(this);  
        elem.initData('get', 'STATE');

        me.addReading(elem, 'get');
    });
}

Dann können wir unter update() auf die Notifizierungen warten. Wir filtern mit elements.filterDeviceReading() die Elemente heraus, die unter data-get das aktualisierte Reading haben und holen mit elem.getReading().val den aktuell bekannten Wert aus dem lokalen Cache.

elem.getReading().date würde den Zeitstempel des Readings liefern.

function update(device, reading) {
     me.elements.filterDeviceReading('get', device, reading)
         .each(function (index) {
             var elem = $(this);
             var value = elem.getReading('get').val;
             if (value) {
                 elem.html(value);
             }
         });
}

Zusammengefasst sieht unser FTUI Plugin jetzt so aus:

var Modul_mywidget = function () {

    function init() {

        me.elements = $('div[data-type="' + me.widgetname + '"]', me.area);
        me.elements.each(function (index) {

            var elem = $(this);  
            elem.initData('get', 'STATE');

            me.addReading(elem, 'get');
        });
    }

    function update(device, reading) {
        me.elements.filterDeviceReading('get', device, reading)
            .each(function (index) {
                var elem = $(this);
                var value = elem.getReading('get').val;
                if (value) {
                    elem.html(value);
                }
            });

    }

    var me = $.extend(new Modul_widget(), {
        widgetname: 'mywidget',
        init: init,
        update: update,
    });

    return me;
};

Im HTML würde man das jetzt so nutzen können.

<div data-type="mywidget" data-device='AvReceiver' data-get='volume'></div>

Wem das noch nicht genug war, der kann sich ein weiterführendes Praxisbeispiel unter FTUI eigene Widgets - Beispiel ansehen.