Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Visualisierung
    4. Tabellen in HABPanel programmieren, flexibel, mit ng-repeat

    NEWS

    • Wir empfehlen: Node.js 22.x

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker goes Matter ... Matter Adapter in Stable

    Tabellen in HABPanel programmieren, flexibel, mit ng-repeat

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

      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:

      tabelle_klein.jpg

      Und eine „große“, die zusätzlich Mess- und andere Werte auflistet:

      tabelle_gross.jpg

      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:

      tabelle_klein.jpg

      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>&nbsp;&nbsp;&nbsp;Zigbee-Schalter&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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:

      1. 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)
      2. Die eigentlich Programmierung der Tabelle beginnt bei
        < table class="table table-bordered" …> mit der Klasse, der Spaltenzahl und der Überschrift.
        (Zeile 36 - 37)
      3. Mit
        <div ng-app="" beginnt die flexible Tabellenprogrammierung, wobei ng-app leer bleibt.
        (Zeile 38)
      4. 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)
      5. . <tr ng-repeat="x in geraete">
        eröffnet eine Tabellenzeile und ist der wichtigste Teil der flexiblen Tabellenprogrammierung
        (Zeile 47)
      6. bilde für jeden Eintrag „x“ in der Liste „geraete“ eine Tabellenzeile
        aus raum und x.adresse+'battery‘
        (Zeile 43 - 51)
      7. 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)
      8. in ng-class erfolgt die Formatierung kritischer Werte mit Hilfe der obigen Styles
        (Zeile 49)
      9. 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:

      tabelle_gross.jpg

      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>&nbsp;&nbsp;&nbsp;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

      1. Styles
        (Zeile 5 - 34)
      2. <table class …
        (Zeile 36)
      3. <div ng-app="" ng-init="geraete=[
        (Zeile 38)
      4. Listenelemente:
        {art:'Thermometer',raum:'Arbeitszimmer',adresse:'zigbee.0.00158d0008ce4367.'},
        (Zeile 39 - 51)
      5. <tr ng-repeat="x in geraete">
        (Zeile 64)
      6. 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.

      arteck 1 Reply Last reply Reply Quote 0
      • arteck
        arteck Developer Most Active @jahnbes last edited by arteck

        @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.

        jahnbes 1 Reply Last reply Reply Quote 0
        • jahnbes
          jahnbes @arteck last edited by jahnbes

          @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.

          arteck 1 Reply Last reply Reply Quote 0
          • arteck
            arteck Developer Most Active @jahnbes last edited by

            @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 .. 🙂

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

            Support us

            ioBroker
            Community Adapters
            Donate

            798
            Online

            32.0k
            Users

            80.4k
            Topics

            1.3m
            Posts

            2
            4
            343
            Loading More Posts
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes
            Reply
            • Reply as topic
            Log in to reply
            Community
            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
            The ioBroker Community 2014-2023
            logo