NEWS
Tabellen in HABPanel programmieren, flexibel, mit ng-repeat
-
Tabellen-Programmierung, flexibel unter HABPanel mit ng-repeat
Ziel war eine Tabelle in einer HABPanel-Visualisierung zur einheitlichen Darstellung von Werten von ZigBee-Geräten. Wobei besonderer Wert darauf gelegt wurde, durch eine flexible Programmierung der Tabelle es möglich zu machen, mit wenig Aufwand neue ZigBee-Geräte in die Tabelle aufzunehmen.
Es werden zwei Tabellen vorgestellt, eine „kleine“, die den Batteriezustand von beliebig vielen Geräten zeigt:
Und eine „große“, die zusätzlich Mess- und andere Werte auflistet:
In beiden Tabellen werden kritische Zustände einiger Werte durch einen farbigen Hintergrund hervorgehoben.
Die vollständigen Codes beider Tabellen sind angefügt.
Programmierung der kleinen Tabelle
Die flexible Programmierung der Tabellen erfolgt unter Verwendung der Direktive ng-repeat.
ng-repeat ist eine Direktive in AngularJS. So ziemlich jede Anwendung, die mit Collections operiert, benötigt den Einsatz dieser Direktive, um die Sammlungen von Daten in einer View bequem ausgeben zu können. Hier werden sie benutzt, um Tabellen in HABPanel dynamisch gestalten zu können, das heißt, eine Zeile der Tabelle wird als Schablone programmiert, dann eine Liste der darzustellenden Elemente (z.B. ZigBee-Geräte) erstellt und mit Hilfe von ng-repeat diese Liste abgearbeitet und die Tabelle mit allen Zeilen (ZigBee-Geräten) erzeugt. Neben der einfacheren Programmierung der Tabelle (es muss nur eine Zeile programmiert werden) hat das auch deutliche Vorteile, wenn Elemente (Zeilen - ZigBee-Geräten) zur Tabelle hinzukommen oder entfallen. im Code muss dann nur die Liste der Geräte geändert werden,
Hier die kleine Tabelle, die der Code generiert:
Und hier der Code dazu:
<!-- 20. Februar 2024 D:\develop\Visuali - sierung\HABpanel\Zigbee\zigbee_batteriezustand_3.html --> <style> caption { color: white; font-size: x-large; } th { text-align: center; color: black; background-color: #67eea8b7; font-size: large; font-weight: normal; } .alarm { color: black; background-color: rgb(253, 116, 116); } .attention { color: black; background-color: rgb(252, 234, 115); } td { text-align: center; color: white; font-size: large; } </style> <table class="table table-bordered" columns="2"> <caption> Zigbee-Schalter Batteriezustand</caption> <div ng-app="" ng-init="geraete=[ {raum:'Heizung-Eco (Flur)',adresse:'zigbee.0.0c4314fffe1e2d25.'}, {raum:'Multi-Licht (Flur)',adresse:'zigbee.0.b4e3f9fffed1bd72.'}, {raum:'Klingelkontakt (Flur)',adresse:'alias.0.Flur.Tuerklingel.'} ]"> <tr> <th>Raum</th> <th>Prozent</th> </tr> <tr ng-repeat="x in geraete"> <td>{{x.raum}}</td> <td ng-init="percentV=itemValue(x.adresse+'battery')" ng-class="{'alarm': percentV <= 45, 'attention': percentV > 45 && percentV <= 70}"> {{'%.0f' | sprintf:percentV}} %</td> </tr> </div> </table>
Erläuterung:
- Zunächst werden unter <style> einige Styles vereinbart, besondere Beachtung verdienen hier die eigenen Styles „attention“ und „alarm“. Sie dienen später der Markierung kritischer Werte.
(Zeile 5 - 34) - Die eigentlich Programmierung der Tabelle beginnt bei
< table class="table table-bordered" …> mit der Klasse, der Spaltenzahl und der Überschrift.
(Zeile 36 - 37) - Mit
<div ng-app="" beginnt die flexible Tabellenprogrammierung, wobei ng-app leer bleibt.
(Zeile 38) - ng-init="geraete=[
eröffnet die Liste (Name: „geraete“) der anzuzeigenden ZigBee-Geräte, wobei jede folgende Zeile ein Gerät mit seinen unikalen Werten enthält in der Form
raum:‘Raumname‘, adresse:‘erster Teil der ZigBee-Adresse.‘
hier
{raum:'Heizung-Eco (Flur)',adresse:'zigbee.0.0c4314fffe1e2d25.'},
Wichtig ist der abschließende Punkt in adresse, damit aus diesem Teil der Adresse des ZigBee-Gerätes und dem weiter unten folgenden Wertenamen eine komplette, richtige ZigBee-Adresse gebildet werden kann.
(Zeile 38 - 42) - . <tr ng-repeat="x in geraete">
eröffnet eine Tabellenzeile und ist der wichtigste Teil der flexiblen Tabellenprogrammierung
(Zeile 47) - bilde für jeden Eintrag „x“ in der Liste „geraete“ eine Tabellenzeile
aus raum und x.adresse+'battery‘
(Zeile 43 - 51) - x.adresse+'battery‘ wird hier mit Hilfe von ng-init „percentV“ zugewiesen, um einen mehrfachen Aufruf des Wertes zu vermeiden und im Code Platz zu sparen
(Zeile 49) - in ng-class erfolgt die Formatierung kritischer Werte mit Hilfe der obigen Styles
(Zeile 49) - Abschließend wird mit
{{'%.0f' | sprintf:percentV}} %</td>'
der ZigBee-Wert des Batteriezustandes selbst dargestellt.
(Zeile 50)
Kommt jetzt eines oder mehrere weitere ZigBee-Geräte hinzu, ist es lediglich notwendig, die Liste „geraete“ um diese Geräte zu erweitern. An der Programmierung der Tabelle braucht nichts mehr geändert zu werden.
Programmierung der großen Tabelle
Hier noch einmal die große Tabelle:
Und hier ihr Code:
<!-- 22. Februar 2024 D:\Projekte\Visualisierung\HABpanel\Zigbee\zigbee_geraete_tabelle.html --> <style> th { text-align: center; color: black; background-color: #67eea8b7; font-size: large; font-weight: normal; } td { text-align: center; color: white; font-size: large; } caption { color: white; font-size: x-large; } .alarm { color: black; background-color: rgb(253, 116, 116); } .attention { color: black; background-color: rgb(252, 234, 115); } </style> <table class="table table-bordered" columns="9"> <caption> Zigbee - Geräte</caption> <div ng-app="" ng-init="geraete=[ {art:'Thermometer',raum:'Arbeitszimmer',adresse:'zigbee.0.00158d0008ce4367.'}, {art:'Thermometer',raum:'Schlafzimmer',adresse:'zigbee.0.00158d0008c11f15.'}, {art:'Thermometer',raum:'Wohnzimmer',adresse:'zigbee.0.00158d0008385f00.'}, {art:'Thermometer',raum:'Flur',adresse:'zigbee.0.00158d0008c12e72.'}, {art:'Thermometer',raum:'Küche',adresse:'zigbee.0.00158d0007f7a4b5.'}, {art:'Thermometer',raum:'Bad',adresse:'zigbee.0.a4c138a06538b164.'}, {art:'Thermometer',raum:'Keller',adresse:'zigbee.0.a4c13863047b5222.'}, {art:'Thermometer',raum:'Waschküche',adresse:'zigbee.0.a4c138374fc3121f.'}, {art:'Schalter Heizung-Eco',raum:'Flur',adresse:'zigbee.0.0c4314fffe1e2d25.'}, {art:'Schalter Multi-Licht',raum:'Flur',adresse:'zigbee.0.b4e3f9fffed1bd72.'}, {art:'Klingelkontakt',raum:'Flur',adresse:'alias.0.Flur.Tuerklingel.'}, {art:'Repeater',raum:'Küche',adresse:'zigbee.0.e0798dfffee7ddd4.'}, {art:'Repeater',raum:'Keller',adresse:'zigbee.0.70ac08fffe68a9b2.'} ]"> <tr> <th>Art</th> <th>Raum</th> <th>Verfügbarkeit</th> <th>Verbindung</th> <th>Temperatur</th> <th>Luftfeuchtigkeit</th> <th>Luftdruck</th> <th>Batterie</th> <th>Spannung</th> </tr> <tr ng-repeat="x in geraete"> <td>{{x.art}}</td> <td>{{x.raum}}</td> <td ng-init="availableV=itemValue(x.adresse+'available')" ng-class="{'alarm': availableV == 'false'}"> {{availableV}}</td> <td ng-init="qualityV=itemValue(x.adresse+'link_quality')" ng-class="{'alarm': qualityV <= 20, 'attention': qualityV > 20 && qualityV < 100}"> {{'%.0f' | sprintf:qualityV}} %</td> <td ng-if="itemValue(x.adresse+'temperature')">{{'%.2f' | sprintf:itemValue(x.adresse+'temperature')}} °C</td> <td ng-if="!itemValue(x.adresse+'temperature')"> </td> <td ng-if="itemValue(x.adresse+'humidity')">{{'%.2f' | sprintf:itemValue(x.adresse+'humidity')}} %</td> <td ng-if="!itemValue(x.adresse+'humidity')"> </td> <td ng-if="itemValue(x.adresse+'pressure')">{{'%.2f' | sprintf:itemValue(x.adresse+'pressure')}} mb</td> <td ng-if="!itemValue(x.adresse+'pressure')"> </td> <td ng-if="itemValue(x.adresse+'battery') && x.raum != 'Keller' && x.raum != 'Waschküche'" ng-init="percentV=itemValue(x.adresse+'battery')" ng-class="{'alarm': percentV <= 45, 'attention': percentV > 45 && percentV <= 70}"> {{'%.0f' | sprintf:percentV}} %</td> <td ng-if="!itemValue(x.adresse+'battery') || x.raum == 'Keller' || x.raum == 'Waschküche'"> </td> <td ng-if="itemValue(x.adresse+'voltage') && x.raum != 'Keller' && x.raum != 'Waschküche'">{{'%.2f' | sprintf:itemValue(x.adresse+'voltage')}} V</td> <td ng-if="!itemValue(x.adresse+'voltage') || x.raum == 'Keller' || x.raum == 'Waschküche'"> </td> </tr> </div> </table>
Erläuterung:
Die Programmierung der großen Tabelle, die wesentlich mehr Zeilen und Spalten hat, erfolgt in der gleichen Art und Weise, auch hier gibt es
- Styles
(Zeile 5 - 34) - <table class …
(Zeile 36) - <div ng-app="" ng-init="geraete=[
(Zeile 38) - Listenelemente:
{art:'Thermometer',raum:'Arbeitszimmer',adresse:'zigbee.0.00158d0008ce4367.'},
(Zeile 39 - 51) - <tr ng-repeat="x in geraete">
(Zeile 64) - eine programmierte Tabellenzeile (hier die ersten drei Spalten)
<td>{{x.art}}</td>
<td>{{x.raum}}</td>
<td ng-init="availableV=itemValue(x.adresse+'available')" ng-class="{'alarm': availableV == 'false'}">{{availableV}}</td>
(Zeile 64 - 82)
Nur ist hier Auflistung der Gerätewerte komplizierter, da nicht alle Geräte alle Werte zur Verfügung stellen, aber trotzdem alles in EINER Tabelle untergebracht werden sollte. Z.B. zeigt ein Schalter üblicherweise keine Temperatur an. Deshalb können nicht jedes Mal alle Zellen einer Zeile mit Werten und ihrer Formatierung angezeigt werden, sondern müssen leer vorhanden sein. Wenn diese Zellen nicht leer sind, sondern z.B. mit „NULL“ o.ä. gefüllt werden, würde das die Lesbarkeit der Tabelle erheblich einschränken.
Die Programmierung einer Tabellenzeile in Abhängigkeit von den darzustellenden Geräten ist sicher noch unkomplizierter möglich, z.B. in dem in der Liste "geraete" eine ID vergeben wird, die die Art der darzustellenden Zeile (welche Werte sind auszulassen) angibt. So würde die doch speziellen Entscheidungen in der Programmierung der Tabellenzeile (Zeile 77 - 78) vermieden werden können. - Zunächst werden unter <style> einige Styles vereinbart, besondere Beachtung verdienen hier die eigenen Styles „attention“ und „alarm“. Sie dienen später der Markierung kritischer Werte.
-
@jahnbes schön schön aber so flexibel ist es nicht ..
da du immer die Geräte per Hand in die Tabellen einpflegen musst. will ich die Tabelle jetzt nutzuen muss ich ca 200 Geräte auflisten..eleganter währe es wenn du diese dir aus den enum rausholen würdest.
-
@arteck
Hallo arteck,
das ist eine interessante Idee. Allerdings war und ist die Intention meines Beitrages darzulegen, wie eine Tabelle in HABPanel flexibel zu programmieren ist. Was mit Hilfe von ng-repeat gelingt.
Deine Anregung, diese Daten für diese Tabelle automatisch zu gewinnen, wäre ein zweiter, wichtiger Schritt und ist bemerkenswert. Du solltest hier einen nachvollziehbaren Beitrag dazu schreiben. Das würde sicher vielen helfen.
Viele Grüße, jahnbes. -
@jahnbes sagte in Tabellen in HABPanel programmieren, flexibel, mit ng-repeat:
Du solltest hier einen nachvollziehbaren Beitrag dazu schreiben
mein Tip solle nur dazu dienen dich in richtung mehr Felxibilität zu schubsen ..