[Workshop] 02_RSS.pm für Anfänger - Schritt für Schritt erklärt

Begonnen von betateilchen, 15 April 2014, 19:55:27

Vorheriges Thema - Nächstes Thema

betateilchen

Schritt 7 - Anwendung des bisher gelernten

Wir haben uns jetzt die wichtigsten Grundlagen erarbeitet, um daraus schon etwas sinnvolles zu bauen.
Nun bauen wir uns daraus uns erstes "echtes" Layout, mit dem wir im Laufe dieses Workshops weiterarbeiten werden.

Bitte folgendes Layout anlegen:


# Schriftart festlegen
font /usr/share/fonts/truetype/msttcorefonts/arial.ttf

# Farbe weiss
rgb "FFFFFF"

# drei waagerechte Linien
line 0  40 800  40
# 0.4 * 600 = 240
line 0 0.4 800 0.4
line 0 440 800 440

# wir bauen uns eine Kopfzeile
# Schriftgroesse festlegen
pt 20
date  10 30
time  650 30
rgb "00FF00"
text 300  30 "myrss Workshop"

# ein skaliertes Bild einbinden
img 764 1 .29 png url "http://fhem.de/www/images/default/fhemicon.png"

# einige vorlaeufige Beschriftungen
pt 12
rgb "FFFFFF"
text  10  80 "Darstellungsbereich 1"
text  10 280 "Darstellungsbereich 2"
text  10 480 "Hier bauen wir uns einen SVG Plot ein"


In diesem Layout sind alle bisher besprochenen Elemente enthalten - ich hoffe, ich habe keines vergessen :)

Das Ergebnis sollte so aussehen:

(http://up.picr.de/17988154om.jpg)

Das macht doch schonmal was her, oder?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Für den weiteren Fortgang des Workshops brauchen wir ein paar Datenquellen und einen SVG Plot. Ich schlage vor, wir nutzen dafür openweathermap als Quelle für Wetterdaten, damit kann man am einfachsten arbeiten und alle haben die gleichen Bedingungen.

1. Definition eines owo device


define owo openweathermap
attr owo owoInterval 600
set owo stationByName Hamburg


(wer möchte, kann natürlich auch seinen Heimatort oder die nächstgelegene größere Stadt eintragen)

2. Definition eines zugehörigen Logfiles

define owolog FileLog ./log/owo.log owo.*(c_temperature|c_humidity|c_pressure).*

3. Anlegen eines gplot-Files mit Namen SVG_owolog_1.gplot im Verzeichnis www/gplot


set terminal png transparent size <SIZE> crop
set output '<OUT>.png'
set xdata time
set timefmt "%Y-%m-%d_%H:%M:%S"
set xlabel " "
set title '<L1>'
set ytics
set y2tics
set grid ytics
set ylabel "Temperatur"
set y2label "Luftfeuchte"
set yrange [10:30]
set y2range [0:100]

#FileLog 4:owo.c_temperature\x3a::
#FileLog 4:owo.c_humidity\x3a::
#FileLog 4:owo.c_pressure\x3a:950:$fld[3]-950

plot "<IN>" using 1:2 axes x1y1 title 'Temperatur' ls l0 lw 1 with lines,\
     "<IN>" using 1:2 axes x1y2 title 'Feuchte' ls l2 lw 1 with lines,\
     "<IN>" using 1:2 axes x1y2 title 'Luftdruck' ls l1 lw 1 with lines


4. Definition des SVG plots


define SVG_owo SVG owolog:SVG_owolog_1:CURRENT
attr SVG_owo label "min:$data{min1}°C   max:$data{max1}°C   akt:$data{currval1}°C"


Wenn alles richtig gemacht wurde und die ersten Daten im Logfile stehen (Achtung: es wird nur alle 10 Minuten geloggt!) sollte so etwas erscheinen:

(http://up.picr.de/17988574un.jpg)


  • Diesen Plot werden wir in den RSS einbinden.
  • Die Readings aus dem owo Device werden wir für die Weiterentwicklung des RSS verwenden.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 8 - wir binden den SVG Plot in unseren RSS ein

Zuerst erinnern wir uns an diese Aussage:

Zitaturl = gibt an, dass die Grafikdatei von einer URL gelesen wird. Alternativ gibt es noch "file" und "data"

"file" sollte sich eigentlich selbst erklären, da wird einfach eine Grafikdatei aus dem Dateisystem gelesen und verwendet, darauf werde ich nicht weiter eingehen.

Aber nun kommen wir zu "data". Wir können auch einfach die DATEN verwenden, die eine Grafik beschreiben, vereinfacht gesagt, wäre das der Inhalt, der in eine Grafikdatei geschrieben würde, wenn man sie abspeichern wollte. Den Umweg über die Grafikdatei sparen wir uns aber.

Das Modul 98_SVG stellt uns dafür eine schöne Funktion namens "plotAsPng()" bereit, die einen SVG plot als Datenstrom im png-Format bereitstellt, und genau diese Funktion nutzen wir im RSS. Die Standardplots aus SVG sind im Format 800x160 und passen damit vom Format exakt zu unserem RSS.

Wir ändern am Ende der Layoutdatei folgendes:

1. Auskommentieren (oder Löschen) der Zeile für den Ausgabebereich
2. Einbinden des SVG plots anhand seines in fhem definierten Namen


#text  10 480 "Hier bauen wir uns einen SVG Plot ein"
img  0 441 1 png data { plotAsPng("SVG_owo") }


Das war schon alles, was wir tun müssen, um das hier zu erhalten:

(http://up.picr.de/17988799mq.jpg)

Einfacher gehts wohl kaum noch, glaube ich.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#18
Schritt 9 - wir zeichnen Rechtecke

Seit heute (danke Boris!) gibt es in RSS neu die Möglichkeit, Rechtecke mit und ohne Füllung zu zeichnen.

Wir fügen am Ende der Layoutdatei folgende drei Zeilen ein:


rgb "FF0000"
rect 400 120 480 160
rect 400 320 480 360 1


und betrachten das Ergebnis:

(http://up.picr.de/17989138uo.jpg)

Erklärung: nach der nächsten Maus  :)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#19
Erklärung - was ist im letzten Schritt passiert?

Die Syntax für das Zeichnen von Rechtecken


rect 400 120 480 160
rect 400 320 480 360 1


ist ähnlich wie die Syntax für das Zeichnen von Linien.

rect <x1> <y1> <x2> <y2> [<filled>]

x1/y1 = bezeichnet dabei die linke obere Ecke
x2/y2 = bezeichnet die untere rechte Ecke
filled  = (optional) gibt an, ob das Rechteck nur gezeichnet oder auch mit Farbe gefüllt werden soll

Damit sollten sich die beiden Befehlszeilen eigentlich selbst erklären.

Wozu man die Rechtecke nutzen kann, erkläre ich Euch nach der nächsten Maus  8)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schöner machen - wir kombinieren den Plot im RSS mit einem Rechteck

Mal ehrlich, so richtig "schön" sieht das hier ja noch nicht aus:

(http://up.picr.de/17990117wq.jpg)

Irgendwie hängen die Achsenbeschriftungen auf dem schwarzen Hintergrund "in der Luft".
So würde das doch viel angenehmer aussehen:

(http://up.picr.de/17990121nv.jpg)

Kein Problem, wir können ja nun Rechtecke zeichnen und die sogar füllen. Wir legen also einfach ein passend großes Rechteck mit der gewünschten Hintergrundfarbe unter den Plot.


#text  10 480 "Hier bauen wir uns einen SVG Plot ein"
rgb "585858"
rect 0 441 800 600 1
img  0 441 1 png data { plotAsPng("SVG_owo") }


Wichtig: auf die Reihenfolge achten.

Wer nicht glaubt, dass das wichtig sei, kann ja spasseshalber die Reihenfolge mal umdrehen und erst den Plot und dann das Rechteck einbauen  8) Ich sagte ja eingangs schon, dass die Layout von oben nach unten abgearbeitet wird. Man muss sich das an dem aktuellen Beispiel wie ein Wurstbrot vorstellen:


  • der schwarze Hintergrund ist die Brotscheibe
  • das graue Rechteck ist die Butter auf der Brotscheibe
  • der SVG Plot ist der Wurstbelag auf der Butter auf der Brotscheibe
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Bitte kommentiert jetzt die drei Zeilen für die roten Rechtecke wieder aus (oder löscht sie einfach)


#rgb "FF0000"
#rect 400 120 480 160
#rect 400 320 480 360 1


Seit heute gibt es noch eine weitere Neuerung im RSS-Modul

Seit heute kann man mit einem Attribut die Hintergrundfarbe eines RSS definieren, anstatt immer nur mit dem schwarzen Standardhintergrund arbeiten zu müssen.

Beispiel:

attr myrss bgcolor 0000FF

Diese Änderung wird sofort wirksam, das "set myrss rereadcfg" ist nicht notwendig, da die Änderung ja nicht im Layout erfolgt.

(http://up.picr.de/17990239iq.jpg)

Die "Unschärfen" im Bild kommen von der Unzulänglichkeit des jpg Formates. Das wurde ja im Diskussionsthread schon besprochen und ich habe heute auch schon einen Patch vorgeschlagen, mit dem man wahlweise auch PNG als Ausgabeformat definieren kann.

Das würde dann so aussehen:

(http://up.picr.de/17990240mp.png)

Die Unschärfen sind komplett verschwunden. Sofern die Änderung im Laufe des Workshops noch in das Modul eingebaut wird, werde ich darauf natürlich noch einmal eingehen.

Ich bevorzuge als bgcolor übrigens den Farbcode 1C1C1C - das ist nicht ganz so hart wie das totale schwarz.

attr myrss bgcolor 1C1C1C

Für den weiteren Verlauf des Workshops gehe ich von einem schwarzen (zumindest einem sehr dunklen) Hintergrund aus.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 10 - wir benutzen Werte aus fhem-Readings im RSS

Bitte ändert in der Layout-Datei den Teil mit der Kopfzeile so ab:


# wir bauen uns eine Kopfzeile
# Schriftgroesse festlegen
pt 20
date  10 30
time  650 30
#rgb "00FF00"
#text 300  30 "myrss Workshop"

rgb "FF0000"
text 200 30 { ReadingsVal('owo','c_temperature','')."°C"}

rgb "2E64FE"
text .5  30 { ReadingsVal('owo','c_humidity','')."%"}

rgb "00FF00"
text 500 30 { ReadingsVal('owo','c_pressure','')." hPa"}


und bewundert die schöne neue Kopfzeile:

(http://up.picr.de/17990309bk.jpg)

Ich denke, dazu muss man nicht viel erklären. Das ist die grundsätzliche Vorgehensweise, wenn man Werte aus irgendwelchen fhem-Devices im RSS darstellen möchte: man liest sie einfach aus und übergibt sie an "text" Der Teil zwischen den geschweiften Klammern ist reine perl Syntax, wie man sie auch aus notify, at und der 99_myUtils kennt.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 11a - Ausrichtung von Texten

Bitte ergänzt in Eurer Layoutdatei am Ende folgende Zeilen:


# weitere  Linien im Darstellungsbereich 1
rgb "7F7F7F"
line 400  40 400 240
line 600  40 600 240
line 400 140 800 140

# Demo Textausrichtung vertikal
rgb "FFFFFF"
tvalign "top"
text 410 140 "TO"

tvalign "center"
text 440 140 "CE gjp"

tvalign "base"
text 490 140 "BA gjp"

tvalign "bottom"
text 540 140 "BO gjp"

tvalign "base" # Rücksetzen auf default

# Demo Textausrichtung horizontal
thalign "left"
text 600 170 "LEFT"

thalign "center"
text 600 200 "CENTER"

thalign "right"
text 600 230 "RIGHT"

thalign "left" # Rücksetzen auf default


Das Ergebnis sollte so aussehen:

(http://up.picr.de/17991364oh.jpg)

Auf diese Weise kann man anhand von gedachten Hilfslinien Texte sowohl waagerecht als auch senkrecht ausrichten.
Das Beispiel sollte eigentlich selbst erklärend sein.

thalign => aufgedröselt:
t = text
h = horizontal
align= ausrichten

tvalign => aufgedröselt:
t = text
v = vertikal
align= ausrichten

Natürlich gibt es diese Möglichkeit auch für eingefügte Bilder - nach der nächsten Maus.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 11b - Ausrichtung von Bildern

Was für Texte geht, geht natürlich auch für Bilder.

Bitte ergänzt Eure Layout-Datei am Ende um folgende Zeilen:


# nochmal zwei Hilfslinien
rgb "7F7F7F"
line 300  40 300 240
line   0 140 250 140

# Demo Bildausrichtung vertikal
ivalign "top"
img  10 140 1 png url "http://up.picr.de/17991350as.png"

ivalign "center"
img  75 140 1 png url "http://up.picr.de/17991350as.png"

ivalign "bottom"
img 140 140 1 png url "http://up.picr.de/17991350as.png"

ivalign "top" # Rücksetzen auf default

# Demo Bildausrichtung horizontal
ihalign "left"
img 300  50 1 png url "http://up.picr.de/17991350as.png"

ihalign "center"
img 300 115 1 png url "http://up.picr.de/17991350as.png"

ihalign "right"
img 300 180 1 png url "http://up.picr.de/17991350as.png"

ihalign "left" # Rücksetzen auf default


Das Ergebnis sollte so aussehen:

(http://up.picr.de/17991713uj.png)

ihalign => aufgedröselt:
i = image
h = horizontal
align= ausrichten

ivalign => aufgedröselt:
i = text
v = vertikal
align= ausrichten




Für die Ausrichtung von Text und Bilder gilt gleichermassen: Natürlich kann man horizontale und vertikale Ausrichtung auch kombinieren!

Wer also das Popcorn genau in den Mittelpunkt des RSS setzen will, ohne die Pixel für die Positionierung ausrechnen zu müssen, kann das so machen:


ihalign "center"
ivalign "center"
img .5 .5 1 png url "http://up.picr.de/17991350as.png"


Dafür mache ich jetzt keinen Screenshot, das könnt Ihr mal selbst testen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#25
Bei mir sieht das Ergebnis unserer Arbeit aktuell übrigens so aus:

(http://up.picr.de/17991915rf.jpg)

Wenn ich mir die Sache so recht überlege, sind wir schon sehr weit in unserem Workshop, es fehlen nur noch zwei oder drei wichtige Themen. Und wenn wir diese durchgearbeitet haben, werde ich eine Auflistung machen, was ich Euch NICHT gesagt habe  8)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 12 - bedingtes Einbinden von Informationen

Bitte legt Euch einen Dummy namens "regenDummy" an und gebt ihm den Wert "rain"


define regenDummy dummy
set regenDummy rain


Wir wollen im RSS die Meldung "Es regnet!" ausgeben, aber nur wenn der regenDummy auch den Wert "rain" hat.

Dafür gibt es grundsätzlich zwei Wege.

Lösungsweg 1:

Fügt bitte am Ende der Layoutdatei folgende Zeilen ein:


# Deno für bedingtes Einbinden von Informationen
# Variante 1
rgb "2E64FE"
text 210 280  { "Es regnet!" if(ReadingsVal('regenDummy','state','') eq 'rain') }



und schaut Euch das Ergebnis an:

(http://up.picr.de/17992345kv.png)

Zum Vergleich macht Ihr dann bitte ein "set regenDummy norain" und ladet Euer Lesezeichen für das RSS-Bild (nicht das Layout!) neu.
Die Meldung sollte dann nicht mehr erscheinen.

Die zweite Variante, so etwas zu machen, erkläre ich Euch - nach der nächsten Maus.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Fortsetzung: bedingtes Einbinden von Informationen

Bitte die eben eingefügten zwei Zeilen wieder auskommentieren, wir kommen jetzt zu Variante 2:


# Deno für bedingtes Einbinden von Informationen
# Variante 1
#rgb "2E64FE"
#text 210 280  { "Es regnet!" if(ReadingsVal('regenDummy','state','') eq 'rain') }

# Variante 2
condition {(ReadingsVal('regenDummy','state','') eq 'rain')}
rgb "2E64FE"
text 210 280 "Es regnet!"
condition 1


Das Verhalten sollte identisch zu Variante 1 sein.

Wo ist der Unterschied? Was sind die Vorteile?


  • In der ersten Variante haben wir die Bedingung direkt in das text-Statement eingebaut. Davor wurde aber auf jeden Fall noch die Farbe umschaltet

In der zweiten Variante haben wir einen anderen Ablauf:


  • Alle Befehle, die in der Layout-Definition nach der ersten condition-Zeile stehen, werden nur dann ausgeführt, wenn die in der condition angegebene Bedingung erfüllt ist.

Es wird also auch die bis dahin mit rgb gesetzte Farbe nicht verändert, wenn die Bedingung nicht erfüllt ist.

Ist die Bedingung nicht erfüllt, werden alle folgenden Zeilen übersprungen, bis entweder wieder eine condition Zeile kommt, die erfüllt wird, oder bis das Ende der Layoutdefinition erreicht ist.

Deshalb ist es wichtig, an einen Block, der nur bedingt ausgeführt werden soll, wieder eine Bedingung anzuschließen, mit der die Bedingung wieder aufgehoben wird. Im Beispiel macht das die Zeile "condition 1"

Ein konkretes Anwendungsbeispiel aus meiner Produktivumgebung kommt noch, dazu muss ich erst nochwas basteln, wir kommen nochmal auf das Thema hier zurück, keine Sorge :)



-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 14 - noch eine Methode zur Positionsangabe im RSS
oder: "Wer kennt noch Turtle Graphics"?  8)

Bitte ergänzt Euer Layout am Dateiende *):


# Kapitel 14 - Readingliste anzeigen
# zuerst nochmal eine Linie zeichnen
rgb "7F7F7F"
line 400 240 400 440

# Wertebezeichnungen linksbündig ausgeben
rgb "FFFFFF"
pt 12
thalign "left"
text 410 270 "Temperatur"
text 410 300 "Luftfeuchte"
text 410 330 "Luftdruck"

# Messwerte rechtsbündig ausgeben
thalign "right"
text 550 270 {ReadingsVal('owo','c_temperature','?')}
text 550 300 {ReadingsVal('owo','c_humidity','?')}
text 550 330 {ReadingsVal('owo','c_pressure','?')}

# Einheiten linksbündig an die Messwerte anhängen
thalign "left"
text 552 270 "°C"
text 552 300 "%"
text 552 330 " hPa"


Was da passiert, sollte inzwischen jeder problemlos verstehen können, der den Workshop konzentriert mitgearbeitet hat.
Das Ergebnis sollte so aussehen:

(http://up.picr.de/17993729yt.png)

Das mit den Positionsangaben kann man aber auch noch anders machen. Wie? Das erkläre ich Euch nach der nächsten Maus.

*) für stgeran: das bedeutet nach der letzten aktuell vorhandenen Zeile in der Layoutdatei
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Schritt 14 - Teil 2, die Alternative

Stellt Euch vor, Euer RSS wäre so groß, dass Ihr eine Schildkröte darauf laufen lassen könnt *)

Ihr setzt die Schildkröte auf die Position "x=100 y=100" und sagt Ihr "gehe 100 Schritte in Richtung x" Wo befindet sie sich dann?
Richtig: an der Position x=200 y=100
Jetzt schickt Ihr die Schildkröte weiter: "gehe 50 Schritte in Richtung y". Dann befindet sie sich an der Position x=200 y=150.
Und nun schickt Ihr die Schildkröte nochmal los: "gehe 50 Schritte in Richtung x vorwärts und 30 Schritte in Richtung y rückwärts".
Dann steht die Schildkröte bei x=250 y=120.

Soweit verstanden? Gut.

Und genau das kann der RSS auch.

Wir hatten bisher absolute Positionsangaben, z.B. x=200 y=300
Dann haben wir relative Positionen kennengelernt, z.B. x=0.25 y=0.5

Jetzt kommt die dritte Variante - die Schildkröte.
Dazu gibt es für das RSS Layout die Befehle "moveto <x> <y>" und "moveby <deltaX> <deltaY>"

Nehmen wir unsere Schildkröte von oben und übersetzen ihre Bewegungen in Befehle für unser RSS Layout

setzt die Schildkröte auf die Position "x=100 y=100"
moveto 100 100

gehe 100 Schritte in Richtung x
moveby 100 0

gehe 50 Schritte in Richtung y
moveby 0 50

gehe 50 Schritte in Richtung x vorwärts und 30 Schritte in Richtung y rückwärts
moveby 50 -30

Grundregel:
Bei jeder Positionänderung innerhalb eines RSS Layouts wird die x und y Positon in zwei internen Variablen gespeichert.
Auf diese Variablen "x" und "y" kann innerhalb des Layouts zugegriffen werden, um Positionsangaben zu erzeugen.

Beispiel:
text x y "blubber"

Im nächsten Beitrag geht es um eine Anwendung in unserem Layout. Ich habe jetzt erstmal Hunger, Abendessenzeit.



*) weiterführende Informationen zur Schildkröte
http://de.wikipedia.org/wiki/Turtle-Grafik
http://de.wikipedia.org/wiki/KTurtle
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!