lcd4linux -h
lcd4linux -l
lcd4linux [[:-c|key=val]] [[:-F]] [[:-f|config-file]] [[:-i[i]]] [[:-o|output]] [[:-q]] [[:-v]]
Der 'interaktive Modus' kann mit Strg-D beendet werden.
—-
Wenn lcd4linux im Vordergrund läuft, schreibt es abhängig vom Level nach stdout oder stderr. Der Text-Treiber hat ein eigenes Diagnose-Fenster. Wenn es im Hintergrund gestartet wird (Standardverhalten), benutzt lcd4linux den Syslog-Dienst zum Loggen. Facility ist USER, Levels sind ERR, INFO und DEBUG.
Wenn Probleme mit lcd4linux auftreten, kann das Programm mit lcd4linux -Fvv gestartet werden und der Output zur Diagnose eingeschickt werden.
Folgende Displays werden unterstützt:
Dank des modularen Treiber-Konzepts von LCD4Linux sollte es sehr einfach sein, weitere Displays zu unterstützen. Wenn Du ein nicht unterstütztes Display besitzt, ein bisschen von C-Programmierung verstehst, über etwas freie Zeit verfügst und Deinen Namen hier lesen möchtest, schicke uns einfach ein Email.
Genauere Informationen zu den unterstützten Displays und deren Konfiguration sind auf der Displays-Seite zu finden.
Die Konfigurationsdatei (standardmäßig /etc/lcd4linux.conf) enthält die Konfiguration und das Layout von LCD4Linux.\
Ab Version 0.10 hat sich das Format der Datei sehr verändert und ist damit wesentlich flexibler geworden.
Text nach einem Hash-Zeichen ('#') wird ignoriert. Soll das Zeichen '#' in einem Wert verwendet werden (z.B. für X11-Farben), muss es durch einen vorangestellten Backslash maskiert werden. Leere Zeilen und Zeilen, die nur Whitespaces enthalten (das sind Leerzeichen oder Tabulatoren), werden ebenfalls ignoriert.
Die Datei besteht aus Abschnitten, Unterabschnitten und Parametern. Groß- und Kleinschreibung spielt bei Abschnitten und Parameter keine Rolle. Ein Parameter darf keine Whitespaces enthalten.
Ein Parameter sieht folgendermaßen aus:
name wert
WARNUNG: Jeder Wert aus der Konfigurationsdatei wird als Ausdruck behandelt und daher ausgewertet ("evaluiert"). Das bedeutet, dass ein Wert normalerweise in einfache Hochkomma eingeschlossen werden muss, damit er zu einer Zeichenkette (String) aufgelöst wird!
Einige Beispiele:
name1 wert1 name2 'wert 2' name3 '2+3' name4 2+3 name5 '42' name6 42
name1 wird aus dem Ausdruck 'wert1' ausgewertet, welcher 0 (oder einen leeren String) zurückgibt - üblicherweise ist das nicht erwünscht (außer wenn wert1 der Name einer Variable ist)\
name2 gibt den String 'wert2' zurück, was normalerweise erwünscht ist\
name3 gibt den String '2+3' zurück\
name4 wertet den Ausdruck '2+3' aus und gibt 5 zurück\
name5 gibt 42 zurück (oder den String '42' im String-Kontext)\
name6 ergibt genau das selbe Ergebnis wie name5, gibt also 42 zurück\
Ein Abschnitt (eine Sektion) sieht folgendermaßen aus:
sektion_a { name1 wert1 } sektion_b name_b { name2 wert2 } sektion_c name_c { name3 value3 sektion_d { name4 wert4 } }
Ein Abschnitt kann, muss aber keinen Namen haben! \
Abschnitte können in 'kompakter' Form geschrieben werden, daher ist der folgende Eintrag vollkommen gleichbedeutend mit dem obigen Beispiel:
sektion_a.name1 wert1 sektion_b:name_b.name2 wert2 sektion_c:name_c.name3 wert3 sektion_c:name_c.sektion_d.name4 wert4
Abschnitte und Abschnittsnamen werden durch einen Doppelpunkt (':') verbunden.\
Abschnitte, Unterabschnitte und Werte werden durch einen Punkt ('.') verbunden.
Hier ist ein anschauliches Beispiel - die folgenden zwei Einträge der Verkabelungs-Konfiguration sind gleichbedeutend:
Wire.EX 'STROBE' Wire.IOC1 'SELECT' Wire.IOC2 'AUTOFD' Wire.GPO 'INIT'
Wire { EX 'STROBE' IOC1 'SELECT' IOC2 'AUTOFD' GPO 'INIT' }
Abschnitts-Auswahl
Zu beachten ist, dass es einen Unterschied zwischen 'name wert { }' und 'name wert' gibt: Ersteres definiert einen Abschnitt, zweiteres einen Parameter, aber beide haben den selben Namen! Verwendet wird dies, um einen bestimmten Abschnitt “auszuwählen”.
Zur Veranschaulichung:
Display My_20x4 { ... } Display My_16x2 { ... } Display My_16x4
Hier werden zuerst zwei Abschnitte mit unterschiedlichen Namen definiert, und anschließend wird einer der Abschnitte ausgewählt.
Spezielle Abschnitte
Einige Abschnitte haben eine bestimmte Bedeutung:
Display: Displayspezifische Konfiguration, abhängig vom Display und vom verwendeten Treiber\
Plugin: Konfiguration für bestimmte Plugins (selten genutzt)\
Widget: Definition von Widgets\
Layout: Definiert, wie und wo Widgets am Display angezeigt werden\
Variables: Definition von Variablen\
Minimalistische Beispiel-Konfiguration:
Display CT20x4 { Driver 'Beckmann+Egle' Model 'CT20x4' Port '/dev/tts/0' Icons 1 } Widget CPU { class 'Text' expression uname('machine') prefix 'CPU ' width 9 align 'L' update tick } Layout Default { Row1 { Col1 'CPU' } } Variables { tick 500 } Display 'CT20x4' Layout 'Default'
Es gibt mindestens einen 'Display'-Abschnitt, dieser beschreibt und konfiguriert das Display.\
Es gibt einige 'Widget'-Abschnitte, diese definieren, was und wie es angezeigt wird.\
Widgets werden im 'Layout'-Abschnitt des Displays platziert.\
Sicherheit
Aus Sicherheitsgründen (die Konfiguration kann Benutzernamen/Passwörter für Mail-Zugänge enthalten) muss die Konfigurationsdatei folgende Voraussetzungen erfüllen:
Wenn lcd4linux als root gestartet wird, müssen die Rechte auf /etc/lcd4linux.conf folgendermaßen gesetzt sein:
chmod 600 chown root.root
Der Evaluator ist das wohl aufregendste und wichtigste Feature in LCD4Linux. Kurz gesagt ist es ein Subsystem, welches Ausdrücke auswertet und deren Ergebnis zurückliefert. Fast alles in LCD4Linux passiert den Evaluator, also können Ausdrücke auch für nahezu alles verwendet werden!
Ein Ausdruck ist lediglich eine einfache Zeichenkette (string). Das Ergebnis eines Ausdruckes ist ebenfalls eine Zeichenkette. Intern verwendet der Evaluator für jeden Wert eine Zwei-Weg-Darstellung: abgespeichert wird als Zeichenkette und als Gleitkomma-Zahl (für mathematische Berechnungen). Eine Umwandlung zwischen diesen zwei Darstellungen erfolgt transparent: wenn eine Operation ein numerisches Argument erwartet (z.B. eine Addition), aber das Argument eine Zeichenkette ist, wird es in eine Gleitkomma-Zahl konvertiert (und umgekehrt).
Der Evaluator hat eine sehr lockere Fehlerbehandlung: wenn Fehler auftreten, gibt er eine Nachricht aus, aber er arbeitet weiter, gewöhnlich mit dem Ergebnis NULL (das ist entweder eine leere Zeichenkette oder 0). Der Evaluator kennt Operatoren und Funktionen. Operatoren sind im Evaluator hartkodiert, während Funktionen zur Laufzeit hinzugefügt werden können. Das wird mit Hilfe von Plugins realisiert: sie fügen eine oder mehrere Funktionen zum Evaluator hinzu.
Der Evaluator kann im interaktiven Modus von LCD4Linux leicht getestet werden: Wenn man lcd4linux -i aufruft, erhält man ein Prompt, an dem man einen Ausdruck eingeben kann (z.B. '2+3') und das Ergebnis anschließend angezeigt wird (z.B. '5'). Das ist sehr praktisch, um Plugins zu testen!
Operatoren
Token | Beschreibung | Beispiel | Ergebnis | ||
; | Ausdrucks-Liste | 2+3;2*3 | 6 | ||
= | Variablen-Zuweisungen | a=2+3 | 5 | ||
? : | bedingtes a?b:c | a > 1024 ? 'kB' : 'MB' | 'kB' | ||
logisches ODER | 1 | 0 | 1 | ||
& | logisches UND | 1 & 0 | 0 | ||
< | ist kleiner als | 2 < 3 | 1 | ||
> | ist größer als | 2 > 3 | 0 | ||
+ | Addition | 2 + 3 | 5 | ||
- | Subtraktion oder Vorzeichen | 2 - 3 | -1 | ||
. | Zeichenketten-Verknüpfung | 'Hi' . ' ' . 'there' | 'Hi there' | ||
* | Multiplikation | 2 * 3 | 6 | ||
/ | Division | 6 / 2 | 3 | ||
% | Modulo | 5 % 2 | 1 | ||
!|Exponent|2!3 | 8 | ||||
! | logisches NEIN | !0 | 1 | ||
( ) | öffnende/schließende Klammer | 2 * (3 + 4) | 14 | ||
, | Komma (Argument-Trenner) | func (2, 3) | |||
== | ist gleich | 2 == 3 | 0 | ||
!= | ist nicht gleich | 2 != 3 | 1 | ||
⇐ | ist kleiner oder gleich | 2 ⇐ 3 | 1 | ||
>= | ist größer oder gleich | 2 >= 3 | 0 |
Funktionen
Der Evaluator besitzt keine eingebauten Funktionen, diese können aber von Plugins zur Verfügung gestellt werden. Ein Plugin kann eine explizite Funktion sein, Display-Treiber können aber ebenfalls Funktionen hinzufügen (alle spezifischen Display-Features werden als Plugins implementiert, z.B. Kontrast, Hintergrundbeleuchtung, GPO's, Temperatur-Sensoren, Lüfter-Drehzahl lesen und setzen, usw.). Eine genaue Beschreibung dazu gibt es in der Dokumentation des betreffenden Display-Treiber.
Funktionen können eine fixe oder eine variable Anzahl von Parametern haben, das hängt von der Implementierung ab und wird detailliert in der entsprechenden Dokumentation beschrieben.
Funktionen liefern gewöhnlich etwas zurück, aber das kann auch Nebeneffekte haben: eine Funktion kann etwas setzen, überwachen, oder eine Aktion auslösen (z.B. wenn das Display eine software-kontrollierte Hintergrundbeleuchtung besitzt, wird das als Funktion implementiert, normalerweise mit variablen Parametern: 'LCD::backlight()' liefert den aktuellen Level der Hintergrundbeleuchtung zurück, während 'LCD::backlight(n)' die Hintergrundbeleuchtung auf 'n' setzt).
LCD4Linux 0.10 benutzt eine vollkommen neue Layout-Engine, welche die alte, token-basierende Engine ersetzt. Das gesamte Layout besteht aus unterschiedlichen 'Widgets', welche im 'Layout'-Abschnitt abgelegt werden.
Hinweis: es existiert keine Aktion für ein globales 'Display-Update' oder 'Display-Leeren'. Jedes Widget hat seinen eigenen Update-Intervall, und nur dieses eine Widget wird in diesem Intervall neugezeichnet. Die Update-Intervalle müssen nicht gleich sein, obwohl es besser aussieht wenn die selben Intervalle verwendet werden. Es ist ein gute Idee, für diese Intervalle Variablen zu verwenden.
LCD4Linux benutzt extensiv Double-Buffering. Jedes Widget wird zuerst in einen Layout-Framebuffer geladen, dieser Layout-Buffer wird mit einem Display-Framebuffer verglichen, und nur Unterschiede werden an das Display übertragen. Auch wenn ein Widget sehr oft aktualisiert wird - solange der Wert sich nicht ändert, wird auch nichts an das Display geschickt (das spart einiges an Bandbreite und CPU-Zeit).
Der 'Display-Framebuffer' ist üblicherweise gleich groß wie das Display (das ist sinnvoll, oder nicht? , wohingegen die Größe des Layout-Framebuffers automatisch mit dem Layout wächst und deshalb größer als das Display sein kann (Beispiel: bei einem 20×4-Display mit einem 'Row5' und 'Row6' im Layout hat der Display-Framebuffer 4 Zeilen, während der Layout-Framebuffer 6 Zeilen hat). Wenn ein Display-Update anliegt, verhält sich der Display-Framebuffer wie ein 'Fenster' über dem Layout-Framebuffer. Zur Zeit ist dieses Fenster in der oberen linken Ecke fixiert, aber in Zukunft wird es beweglich sein, um so etwas wie 'virtuelle Zeilen' in LCD4Linux-0.9 zu erhalten.
Jedes Widget hat einen 'Namen' (das ist der Abschnittsname) und eine bestimmte Klasse, welche den 'Typ' des Widgets beschreibt (z.B. Text, Balken, Zeichen). Eine detaillierte Beschreibung jeder verfügbaren Widget-Klasse ist in der entsprechenden Widget-Dokumentation nachzulesen.
Hier ist ein Beispiel-Widget:
Widget RAM { class 'Text' expression meminfo('MemTotal')/1024 postfix ' MB RAM' width 11 precision 0 align 'R' update 1000 }
Dadurch wird ein Widget mit dem Namen 'RAM' definiert:
Das Text-Widget ist das am meisten genutzte Widget. Es wird verwendet, um (statischen oder dynamischen) Text oder Zahlen anzuzeigen.
Ein komplettes Text-Widget sieht folgendermaßen aus:
Widget 'name' { class 'Text' expression <expr1> prefix <expr2> postfix <expr3> width <number> align <char> speed <number> update <number> }
Parameter:
expression: dieser Ausdruck wird ausgewertet und das Ergebnis wird angezeigt\
prefix, postfix: das Ergebnis diese Ausdruckes wird vor/nach dem eigentlichen Wert angezeigt\
width: Länge des gesamten Widgets (inklusive Prefix und Postfix!)\
precision: (Maximum) Anzahl der Kommastellen\
align: entweder 'L' (links, das ist der Standard), 'C' (zentriert), 'R' (rechts), 'M' (marquee, Laufschrift), 'A' (Laufschrift wenn Text länger als Widget) oder 'P' (Pingpong, scrollt den text von links nacht rechts) \
speed: Laufschrift-Scroll-Intervall (msec), Standard ist 500msec\
update: Aktualisierungs-Intervall (msec), Standard: 1000 msec (1 sec), 0 bedeutet nie (für statischen Text)\
'align A' erst ab Version 0.10.2 verfügbar\
'align P' erst ab Version 0.10.2+ verfügbar (svn rev850) \
Man mag sich fragen, warum 'prefix' und 'postfix' ebenfalls Ausdrücke sind und nicht nur statische Zeichenketten? Die Antwort ist einfach: das lässt größere Flexibilität zu! Man denke an ein Widget 'load_avg', welches die durchschnittliche Systemlast anzeigen soll, aber ein Rufzeichen anhängt, wenn die CPU-Last größer als 2 ist:
Widget loadavg { class 'Text' expression loadavg(1) prefix 'Load' postfix loadavg(1) > 2.0 ? '!' : ' ' width 10 precision 1 align 'R' update 200 }
Ausrichtung
Wenn der 'Align'-Parameter angegeben wird, wird nur der aktuelle Wert ausgerichtet. Das Prefix ist immer linksbündig und das Postfix immer rechtsbündig! Verwendet man eine Laufschrift (align 'M'), so werden Prefix, der aktuelle Wert und das Postfix einfach verkettet, und die resultierende Zeichenkette wird zirkular angezeigt, das heißt alle 'speed' msec ein Zeichen vorrückend.
Präzision
Wenn der 'precision'-Parameter weggelassen wird, behandelt LCD4Linux das Ergebnis des Ausdrucks als Zeichenkette und zeigt sie auch so an.
Wenn eine Präzision angegeben wird, wird der Wert in eine Gleitkommazahl umgewandelt und mit der angegebenen Anzahl von Kommastellen ausgegeben. Wenn die Zahl nicht in den verfügbaren Platz passt (welcher mit 'width' - length(prefix) - length(postfix) angegeben wird), werden Kommastellen von rechts abgeschnitten, bis genug Platz vorhanden ist. Wenn die letzte Kommastelle abgetrennt wurde, wird auch der Dezimalpunkt weggelassen. Wenn der Wert nun immer noch nicht passt, wird er durch '*' (Asterisk) ersetzt.
Es besteht also ein großer Unterschied zwischen 'precision 0' und überhaupt keiner Präzision!
Das Balken-Widget wird verwendet, um alle Arten von Balken anzuzeigen.
LCD4Linux versucht, Balken so gut wie möglich zu behandeln. Es unterstützt vertikale, horizontale und gesplittete Balken (zwei unabhängige Balken in einer Zeile), alle Balkentypen können gleichzeitig verwendet werden.
Balken sind recht schwierig zu behandeln: die meisten Displays haben nur eine begrenzte Anzahl von benutzerdefinierten Zeichen zur Verfügung (normalerweise 8), was für eine exakte Anzeige all dieser Balken bei weitem zu wenig ist. Wenn noch dazu Icons benutzt werden, reduziert sich die Anzahl der nutzbaren Zeichen weiter. Daher verwendet LCD4Linux eine Art von “Fehler-Streuung”, indem es Zeichen durch ähnliche Zeichen ersetzt.
Hier muss ein weitere Punkt berücksichtigt werden: wenn ein gerade angezeigtes Zeichen neu definiert wird, entsteht ein hässliches Flackern am Display. Daher wird ein gerade angezeigtes Zeichen nicht umdefiniert, nicht einmal wenn es nach dem nächsten Update nicht mehr genutzt wird. Nur wenn die Fehler-Streuung fehlschlägt, werden solche Zeichen in einem zweiten Durchlauf neu definiert. Das Ergebnis sieht recht gut aus!
Wenn Ihr mir nicht glaubt, dass dieses Zeug etwas eigenartig ist, seht Euch doch den Code des Balken-Handlings in drv_generic_text.c an. Falls jemand diesen Code versteht, gewinnt er eine Kiste Bier
Ein Balken-Widget sieht wie folgt aus:
Widget <name> { class 'Bar' expression <expr> expression2 <expr> length <number> min <number> max <number> direction <char> update <number> }
Parameter:
expression: das Ergebnis wird für die Länge des oberen Halbbalkens verwendet\
expression2: das Ergebnis wird für die Länge des unteren Halbbalkens verwendet\
length: die Größe des gesamten Balken-Widgets\
min: scale: Wert mit dem der Balken startet\
max: scale: Wert mit dem der Balken endet\
direction: 'E' (east: von links nach rechts, das ist der Standard), 'W' (west: von rechts nach links), 'N'(north: von unten nach oben) oder 'S' (south: von oben nach unten)\
update: Update-Intervall (msec), Standard: 1000 msec (1 sec)\
Beispiel:
Widget BusyBar { class 'Bar' expression proc_stat::cpu('busy', 500) expression2 proc_stat::cpu('system', 500) length 10 direction 'E' update 100 }
Wenn 'expression2' weggelassen wird, erhält man einen einzelnen Balken, der nur durch 'expression' kontrolliert wird. Wird 'expression2' angegeben (und das Display unterstützt auch geteilte Balken), erhält man gesplittete Balken, die obere Hälfte überwacht durch 'expression' und die untere Hälfte durch 'expression2'.
Skalierung
Gewöhnlich skalieren Balken automatisch. Das heißt sie starten bei einem Wert von 0 (Null), merken sich den Maximalwert und skalieren automatisch bis zum Maximum.\
Manchmal ist aber ein anderes Verhalten erwünscht (z.B. bei Temperaturen). In diesem Fall muss nur der Minimal- und der Maximalwert mit den Parametern 'min' bzw. 'max' angegeben werden.
LCD4Linux-0.9 hat logarithmische Balken unterstützt. Natürlich kann das auch LCD4Linux-0.10, aber es gibt dabei nichts spezielles zu berücksichtigen: einfach eine mathematische Funktion im Ausdruck angeben…
Das Icon-Widget wird verwendet, um benutzerdefinierte Zeichen (wir nennen sie 'Icons') anzuzeigen.\
Icons können nur verwendet werden, wenn das Display benutzerdefinierte Zeichen unterstützt (die meisten Displays tun das), das Display ein grafisches ist (z.B. T6963), und einige Zeichen für Icons reserviert wurden (Details können in der Dokumentation des Display-Treibers nachgeschlagen werden).
Wenn aus irgendeinem Grund das Icon nicht angezeigt werden kann, wird an dessen Stelle ein Asterisk ('*') angezeigt.
Die Definition eines Icon-Widgets ist sehr einfach:
Widget <name> { class 'icon' speed <number> visible <expr> bitmap { row1 <string> row2 <string> ... row8 <string> } }
Parameter:
speed: Animations-Intervall (msec)\
visible: Ausdruck, der die Sichtbarkeit überwacht (für Blink-Effekte)\
bitmap.row*: Zeichenkette, die das Bitmap definiert\
Beispiel: statisches Icon
Widget Lightning { class 'icon' bitmap { row1 '...***' row2 '..***.' row3 '.***..' row4 '.****.' row5 '..**..' row6 '.**...' row7 '**....' row8 '*.....' } }
Beispiel: animiertes Icon
Widget Heartbeat { class 'Icon' speed 800 Bitmap { Row1 '.....|.....' Row2 '.*.*.|.*.*.' Row3 '*****|*.*.*' Row4 '*****|*...*' Row5 '.***.|.*.*.' Row6 '.***.|.*.*.' Row7 '..*..|..*..' Row8 '.....|.....' } }
Dazu dürfte keine weitere Erklärung notwendig sein…
Sichtbarkeit
Es kann ein Ausdruck für 'visible' angegeben werden, welcher bei jedem Icon-Update ausgewertet wird (alle 'speed' msec). Wenn der Ausdruck zu 0 (Null) aufgelöst wird, ist das Icon unsichtbar und wird durch ein Leerzeichen ersetzt. Wenn das Ergebnis nicht Null ergibt, wird das Icon angezeigt. Das ist nützlich für Blink-Effekte oder Aktivitäts-Anzeigen.
Wenn mehrere Widgets definiert sind, muss man LCD4Linux mitteilen, wo es all die hübschen Widgets anzeigen soll. Das geschieht im 'Layout'-Abschnitt.
Das ist einfach, sehen wir uns ein Beispiel an:
Layout L20x2 { Row1 { Col1 'Busy' Col11 'BusyBar' } Row2 { Col1 'Load' Col11 'LoadBar' } }
Wir definieren ein Layout mit dem Namen 'L20x2', wir haben zwei Zeilen (Row1, Row2) und wir platzieren vier Widgets in bestimmten Spalten. Das ist alles!
Zu beachten ist, dass es beliebig viele Layout-Abschnitte geben kann, aber einer davon muss mit dem 'Layout'-Parameter ausgewählt werden. Vielleicht wird es in Zukunft in LCD4Linux eine Möglichkeit geben, automatisch zwischen Layouts umzuschalten (aufgrund eines Tastendrucks, eines Timer-Ereignisses, etc.).
Der Evaluator kann durch zusätzliche 'Funktionen' erweitert werden, diese Erweiterungen nennt man 'Plugins'. Jedes Plugin stellt zumindest eine Funktion zur Verfügung. Wenn es zusätzliche, vom Display-Treiber bereitgestellte Funktionen gibt, findet man diese Information in der jeweiligen Treiber-Dokumentation.
Wenn ein Plugin nur eine Funktion bereitstellt, wird die Funktion wie das Plugin selbst benannt. Wenn es mehrere Funktionen zur Verfügung stellt, besitzt jede Funktion ein Prefix 'plugin_name::'. Das ist notwendig, um in Zukunft automatisches Laden verwenden zu können (im Moment sind alle Plugins statisch zum Executable gelinkt. Irgendwann in der Zukunft wird ein dynamisches Laden auf Anforderung von Plugins unterstützt werden).
Verfügbare Plugins (genauere Informationen auf der Plugin-Seite):
Für Beispiele zu allen Optionen und deren Verwendung bitte die Beispielkonfiguration heranziehen.