DDF-Handbuch / Teil B – GUI-DDF (SVG)

Walkthrough: DEMO_DDF.csv

DEMO_DDF.csv ist das Referenzbeispiel für GUI-DDF. Eine MODBUS-RTU-Wetterstation (SenTec SEM9000) liefert die Daten, ein responsives Wetter-Widget stellt sie dar. Es zeigt alle GUI-Techniken gemeinsam: mehrere SVG-Vorlagen, Platzhalter, CSS-Klassen, Verläufe, Rotation, berechnete Koordinaten, Mehrsprachigkeit, Layout je Kachelgröße und Mausereignisse.

1. Geräteteil

Den Geräteteil (*GENERAL, *READ, *GROUP, *ITEM) beschreibt MODBUS RTU. Für das Widget ist wichtig: Die Items haben IDs 0…15 und tragen Messwerte wie Temperatur, Wind und UV.

2. *OBJECT-Zeilen

*OBJECT;GROUP;ID;ALIAS;TYPE;ENUM;ENUMTEXT;ENUMVAL;MIN;MAX;IOTYPE;DIGITS;DEFAULT;ITEMID;UNIT;ALARM;ALARMVAL;ALARMTIME;OUTTYPE;CMDITEMID;COMMAND;COMMANDENUM;COMMANDVAL;VIEWTYPE;LOG;SVG;SVGANIMATE;SVGEVENT
;0;0;Widget;4;;;;0;100;;;;;;;;;;;;;;0;1;"<SVG-Vorlagen>";"<SVGANIMATE>";"<SVGEVENT>"
;0;1;Winddirection;4;;;;0;360;;;;0;°;;;;;;;;;0;1
;0;2;Wind;4;;;;0;90;;2;;1;m/s;;;;;;;;;0;1
;0;3;Temperature;4;;;;-60;60;;1;;2;°C;;;;;;;;;0;1
…
;0;16;PM10 concentration;4;;;;0;2000;;1;;14;µg/m3;;;;;;;;;0;1

Objekt 0 der Gruppe 0 trägt SVG und Formeln und ersetzt damit die Standarddarstellung der Gruppe. Die Objekte 1–16 bilden die Werteliste (ITEMID → Item-ID, DIGITS, UNIT, LOG=1).

3. SVG-Vorlagen

Das SVG-Feld enthält sieben Vorlagen:

alias viewBox Inhalt
Qual 200×100 Luftqualität: AQI-Badge, Farbskala, Marker, PM1/PM2.5/PM10
UV 200×100 UV-Index mit 12-Segment-Skala und Abdunkelung
Solar 200×100 Solarstrahlung mit Skala, UV-Strahlung und Tagessumme
General 400×100 große Übersicht: Himmel mit Verlauf, Sonne, Temperatur, 6 Messwerte
Wind 100×100 Kompass mit gedrehtem Pfeil
GeneralCompact 200×100 kompakte Übersicht
GeneralMini 250×200 Kachel für 504/508

Techniken in den Vorlagen

CSS-Klassen (ohne ;, eine Eigenschaft je Zeile):

<style>
 .tile {
 fill: #0c1a32
 stroke: #1c2f4e
 stroke-width: 0.5
 }
 .text-primary {
 fill: #ffffff
 font-weight: 600
 }
</style>
<rect class='tile' x='0' y='0' width='200' height='100' rx='5' ry='5'/>

Platzhalter im Text:

<text class='text-label' x='26' y='15' font-size='7'>$(TITLE)</text>
<text x='192' y='13' fill='#d8f7c8' text-anchor='end' font-size='9' font-weight='600'>$(AQI)</text>

Berechnete Koordinate (Marker auf der AQI-Skala):

<rect x='8+($(AQIPOS)/30*184)' y='38' width='4' height='11' rx='2' ry='2' fill='#ffffff'/>

Platzhalter als Maß (Abdunkelung rechts vom aktuellen Wert):

<rect x='$(UVPOS)' y='52.5' width='$(UVW)' height='8' fill='#0c1a32' fill-opacity='0.72'/>

Rotation (Windpfeil um den Kompassmittelpunkt 34/57):

<path class='arrow' transform='rotate($(DIR) 34 57)' d='M 34 36 L 38 46 L 34 43.5 L 30 46 Z'/>

Verläufe:

<linearGradient id='genSky' x1='0' y1='0' x2='0' y2='1'>
  <stop offset='0' stop-color='#1f4f9a'/>
  <stop offset='1' stop-color='#6f9fd6'/>
</linearGradient>
<path d='M 6.56 0 L 393.44 0 A 6.56 6.56 0 0 1 400 6.56 L 400 62 L 0 62 L 0 6.56 A 6.56 6.56 0 0 1 6.56 0 Z' fill='url(#genSky)'/>

4. SVGANIMATE – die Zeichenformel

4.1 Sprache und Testdaten

language := $.CTRLROOTVAR.WEBVISER_DISPLAY[0].iLANGUAGE+1;
IF $.CTRLVAR.isys == 14 THEN
    valoutside:=22.1;
    …
ELSE
    valoutside:=32.1;
    …
ENDIF;

Die Sprache kommt aus der Display-Konfiguration. $.CTRLVAR.isys ist die Systemnummer des Elements, an dem das Widget hängt. Im Demo sind die Werte Testkonstanten. In einem produktiven Widget stehen hier $.CTRLVAR.…- bzw. $.VARLOCAL.…-Zugriffe.

4.2 Texte nur bei Sprachwechsel setzen

IF language != languageOld THEN
SWITCH language
CASE 1:
    tUV:='UV-Index';
    …
CASE 2:
    tUV:='Indice UV';
    …
DEFAULT:
    tUV:='UV Index';
    …
ENDSWITCH;
ENDIF;
languageOld:=language;

Variablen wie languageOld bleiben zwischen den Zeichenvorgängen erhalten. Dadurch wird die Textzuweisung nur einmal je Sprachwechsel ausgeführt.

4.3 Werte aufbereiten

strTemp:=PRINT(FLOAT,'%.1f',valoutside);
uvpos:=8+valUV*184/12;
IF uvpos>192 THEN
    uvpos:=192;
ENDIF;
uvw:=192-uvpos;
strUVPOS:=PRINT(FLOAT,'%.1f',uvpos);

Platzhalter sind Strings. Zahlen werden mit PRINT formatiert. Positionen werden in den Koordinaten der Vorlage gerechnet (die Skala reicht von x = 8 bis 192).

Klassifizierungen werden mit IF … ELSE IF … ENDIF;-Ketten gebildet (AQI-Stufen, UV-Stufen, Windrichtung in 8 Sektoren).

4.4 Layout je Kachelgröße

xy:=$.GUI.W/$.GUI.H;
SWITCH $.GUI.WIDGETTYPE
CASE 504:
 GUI.setWindow(0,0,245,195,1.0);
 GUI.paintSVG('GeneralMini',0,0,245,195,0,'TEMP',strTemp,'MAX',strTempMax,'MIN',strTempMin,'CONDITION',genCond,…);
CASE 508:
 GUI.setWindow(0,0,245,395,1.0);
 GUI.paintSVG('GeneralMini',0,0,245,195,0,…);
 GUI.paintSVG('Qual',0,200,245,195,0,'PM1',strPM1,'PM25',strPM25,'PM10',strPM10,…);
CASE 1004:
 GUI.setWindow(0,0,495,195,1.0);
 GUI.paintSVG('General',0,0,495,195,0,…);
CASE 1008:
 GUI.setWindow(0,0,495,395,1.0);
 GUI.paintSVG('General',0,0,495,195,0,…);
 GUI.paintSVG('Qual',0,200,245,195,0,…);
 GUI.paintSVG('UV',250,200,245,195,0,…);
DEFAULT:
 IF xy <1.3 THEN
  GUI.setWindow(0,0,410,370,1.0);
  GUI.paintSVG('General',5,0,405,120,0,…);
  GUI.paintSVG('Qual',5,125,200,120,0,…);
  GUI.paintSVG('UV',210,125,200,120,0,…);
  GUI.paintSVG('Solar',5,250,200,120,0,…);
  GUI.paintSVG('Wind',210,250,120,120,0,…);
 ELSE IF xy <2.4 THEN
  …
 ELSE
  …
 ENDIF;
ENDSWITCH;
flowchart TD
    W{$.GUI.WIDGETTYPE} -->|504| A[GeneralMini]
    W -->|508| B[GeneralMini + Qual]
    W -->|1004| C[General]
    W -->|1008| D[General + Qual + UV]
    W -->|sonst| E{Seitenverhältnis}
    E -->|< 1.3| F[General, Qual, UV, Solar, Wind]
    E -->|< 2.4| G[General, Qual, UV]
    E -->|sonst| H[General, Qual, UV, Solar, Wind – breit]

5. SVGEVENT – Interaktion

IF ($.MOUSE.X >( $.GUI.W/2)) && ($.MOUSE.Y >( $.GUI.H/2))THEN
    $.MOUSE.HANDLED:=1;
    test:=$.VARLOCAL.temperature;   /* historisch; seit 09.11.2026 entfernt → $.VAL.temperature */
    test2:=$.VARGLOBAL.systems.network.language;   /* historisch; entfernt → $.VAL / $.CTRLROOTVAR */
ELSE
    $.MOUSE.HANDLED:=0;
ENDIF;

Klicks ins rechte untere Viertel verarbeitet das Widget selbst (HANDLED=1). Alle anderen Klicks gehen an die Standardbehandlung. Nebenbei zeigt das Beispiel den Lesezugriff auf lokale und globale Aliase.

6. Lehren aus dem Demo

Regel Grund
Vorlagen statisch halten, nur Platzhalter variieren d und points werden nicht ersetzt
Zahlen vor der Übergabe mit PRINT formatieren Platzhalter sind Text
Positionen im Vorlagen-Koordinatensystem rechnen paintSVG skaliert die Vorlage
Texte nur bei Sprachwechsel setzen spart Rechenzeit bei jedem Repaint
Layout per WIDGETTYPE und Seitenverhältnis responsive Darstellung
HANDLED immer explizit setzen definiertes Klickverhalten