Ich möchte hier mein neues Modul TOUCHSCREEN vorstellen (im Anhang ein Bild vom Modul im Einsatz).
Motivation
Ich habe schon seit geraumer Zeit einen Raspberry Pi zwecks Überwachung und Steuerung mit meiner Viessmann Heizung verbunden. Was mich an dieser Lösung schon immer gestört hat: ich kann mir den aktuellen Status nur über einen PC bzw. Browser anzeigen lassen, jedoch nicht "vorort" im Heizungskeller. Die Idee war also, den Pi mit einem Touchscreen Display auszustatten, das Anzeige und Bedienung ermöglicht.
Umsetzung
Nach einiger Recherche habe ich mich für den Touchscreen Watterott (http://www.watterott.com/de/RPi-Display) entschieden. Ein Touchscreen am Pi hat leider einen Nachteil: Man kann die Touch-Bedienung nur in Verbindung mit dem X-Server vernünftig nutzen. Zusammen mit dem Browser für die FHEM Oberfläche geht das ziemlich zulasten der Ressourcen, die beim Pi sowieso nicht im Übermaß vorhanden sind. Nun gibt es mit dem FHEM Modul FRAMEBUFFER die Möglichkeit der Darstellung von Inhalten aus FHEM ohne X-Server. Was allerdings noch fehlte war eine Möglichkeit für die Bedienung, um ganz auf den X-Server verzichten zu können.
Für den Zugriff auf den Touchscreen bietet sich das Linux Input Device an. Da es hierzu kein für Touchscreens passendes FHEM Modul gibt, habe ich selbst eines entwickelt. Grundlage war das Modul "inputevent". Allerdings ist davon nicht mehr viel übrig geblieben, da die Eingabeverarbeitung von "inputevent" für Touchscreens nicht geeignet bzw. m.E. fehlerhaft ist (es werden nicht alle Input-Events korrekt verarbeitet).
Ein wichtiges Feature des neuen Moduls ist die Unterstützung von RSS/FRAMEBUFFER Layout-Definitionen. In diesen Layout-Dateien können Eingabebereiche für die Touch-Bedienung definiert werden was die Auswertung von Events sowie die Handhabung der Steuerung deutlich erleichtert. Mehr dazu weiter unten.
Das Modul TOUCHSCREEN (im Anhang) benötigt keine weiteren Perl Pakete (ein User berichtet, dass er das Modul libswitch-perl nachinstallieren musste - das ist aber eigentlich per Default vorhanden). Die Zip-Datei enthält neben dem Modul 89_TOUCHSCREEN.pm eine kurze Doku in HTML (ts_doc.html) sowie eine Layout-Datei als Beispiel (default.layout).
Definition eines Touchscreen Device
Ein Device wie folgt definiert:
define name TOUCHSCREEN device touchx touchy [timeout]
Als device muss das Linux Devicefile des Touchscreens angegeben werden. Meistens ist das /dev/input/touchscreen. Danach folgt mit touchx/touchy die Auflösung des Touchscreens. Das ist nicht zwingend die Auflösung der Anzeige! Die Werte können z.B. mit dem Tool evtest ermittelt werden. Der letzte Parameter timeout ist optional. Er legt eine Zeit in Sekunden fest, nach der das Backlight des Displays abgeschaltet wird.
Nach dieser Definition sollten bei Berührung des Touchscreens schon die ersten Events in FHEM eingehen. Diese sehen z.B. so aus:
2015-01-21 16:32:09 TOUCHSCREEN pitouch SCR_TOUCHED, btn: none, touchx: 1874, touchy: 2714, screenx: 1874, screeny: 2714, pressure: 215
Für eine vernünftige Nutzung braucht es allerdings noch etwas Feintuning, was mit diversen Attributen erledigt wird.
Mit den Attributen screenx und screeny wird die Auflösung des Bildschirms angegeben. In den Events werden dann automatisch Touchscreen-Koordinaten in Bildschirm-Koordinaten umgerechnet. Weiterhin muss man beachten, dass je nach Ausrichtung des Raspberry X- und/oder Y-Koordinaten vertauscht sind. Das kann mit den Attributen swapx und swapy korrigiert werden.
Layout Definitionen
Um sich die Auswertung der Koordinaten aus den Events zu ersparen, kann man Layout-Definitionsdateien (s. FRAMEBUFFER/RSS) um die Definition von Touch-Bereichen (im Prinzip Buttons) erweitern. Die entsprechenden Einträge beginnen alle mit #TS, werden also von FRAMEBUFFER und RSS als Kommentare ignoriert. Folgende Definitionen sind möglich:
#TS name rect x1 y1 x2 y2
#TS name circle x y r
Der erste Befehl definiert einen rechteckigen, der zweite einen runden Button. Nach Aktivierung eines Layout per set Befehl (set name layout File) enthalten die Events den Namen des Buttons (sofern die Berührung des Bildschirms innerhalb eines Buttons lag):
2015-01-21 16:32:16 TOUCHSCREEN pitouch SCR_TOUCHED, btn: BTN_ON, touchx: 2723, touchy: 1943, screenx: 212, screeny: 113, pressure: 182
Auf solche Events kann nun mit NOTIFY reagiert werden. So kann man z.B. Geräte ein- oder ausschalten. Oder man ruft ein neues Layout auf, um so verschiedene Anzeigen zu realisieren.
Weitere Attribute
bloncmd/bloffcmd - Legt die Linux-Befehle zum Ein-/Ausschalten des Backlight fest.
blauto - Wenn 1, wird das Backlight bei jeder Berührung des Displays eingeschaltet. Automatisches Abschalten über Parameter timeout in Gerätedefinition.
deflayout - Legt das Layout fest, das beim Start automatisch geladen wird (funktioniert nicht bei reload!)
rawevent - Wenn 1 werden die Linux Input Rawevents ohne Interpretation/Auswertung durchgereicht (type, code, value).
Beispiel: TOUCHSCREEN und FRAMEBUFFER im gemeinsamen Einsatz:
define pidisp FRAMEBUFFER /dev/fb1
attr pidisp bgcolor C0C0C0
attr pidisp layoutBasedir /opt/fhem/layouts
attr pidisp layoutList default.layout
attr pidisp room Display
attr pidisp size 320x240
attr pidisp startLayoutNo 0
define pitouch TOUCHSCREEN /dev/input/touchscreen 4095 4095 60
attr pitouch blauto 1
attr pitouch deflayout /opt/fhem/layouts/default.layout
attr pitouch room Display
attr pitouch screenx 320
attr pitouch screeny 240
attr pitouch swapy 1
define testdev dummy
define testdevon notify pitouch:.*BTN_ON.* set testdev on
Interessante Entwicklung. Dennoch:
Das Display, ein RPi, ein Gehäuse, ein WLAN-Stick ... das sind geschätzt 70-80 €.
Was ist der Vorteil der Variante gegenüber einem Android-Tablet für weniger als 50 € mit einem deutlich größeren und besser aufgelösten Display? Auch dort hat man Anzeige und Touch-Bedienung in Einem, muss es aber nicht erst großartig einrichten.
(Dies ist kein Angriff, ich möchte es nur einfach gern verstehen und bin bestimmt nicht alleine)
Der Raspi hängt neben meinem Heizkessel im Keller und ist per Optolink Kabel mit der Heizungssteuerung verbunden. Mir geht es um die Möglichkeit, direkt im Heizungskeller auf die Heizungsparameter zugreifen zu können (auch die, die nicht über die Originalsteuerung angezeigt werden). Ohne Display müsste ich immer das iPad mitschleppen.
Ich werde einen weiteren Raspi als "Leaving Home" Anzeige neben der Haustür platzieren. Dieser wird gleichzeitig per Bluetooth und PRESENCE Modul erkennen, wenn mein iPhone (und damit ich) zuhause ist.
Aber Du hast natürlich recht: wenn jemand mit dem Tablet auskommt, braucht er das nicht.
Ja natürlich. FHEM muss auf dem Raspi laufen. Es wird ja auch das Modul FRAMEBUFFER für die Anzeige verwendet (zumindest macht TOUCHSCREEN ohne Anzeige wenig Sinn).
Vielleicht nochmal zum besseren Verständnis meine Installation:
Heizungskeller: Raspi mit Touchdisplay und FHEM (Module FRAMEBUFFER und TOUCHSCREEN), WLAN Stick und direktes USB Kabel zur Viessmann Steuerung.
Flur EG: Raspi (noch ohne Touchscreen) mit FHEM (Masterinstanz), Bluetooth, WLAN.
ich konnte das Modul erst nutzen nachdem ich mit
sudo apt-get install libswitch-perl
switch.pm im system hatte.
Mm, explizit verwendet wird es nicht. Bei mir war das Modul schon per Default installiert, daher habe ich das nicht bemerkt.
Habe dieses Modul entdeckt, nachdem ich mir jetzt mir ein Display an den RPi gesteckt habe, für einfache Temperatur/Feuchtigkeitsanzeige.
Bei mir erscheint beim framebuffer define: Cannot load module FRAMEBUFFER
Was muss ich nachinstallieren?
Gruss
Ralf
Steht eigentlich in der commandref (http://fhem.de/commandref.html#FRAMEBUFFER).
GD muss installiert sein, siehe auch die Voraussetzungen für RSS (http://fhem.de/commandref.html#RSS).
Genaueres sollte sich aber auch aus den Fehlermeldungen im Log entnehmen lassen.
Zitat von: kaihs am 23 Januar 2016, 14:05:59
Steht eigentlich in der commandref (http://fhem.de/commandref.html#FRAMEBUFFER).
GD muss installiert sein, siehe auch die Voraussetzungen für RSS (http://fhem.de/commandref.html#RSS).
Genaueres sollte sich aber auch aus den Fehlermeldungen im Log entnehmen lassen.
Danke, bin mittlerweile auch drauf gekommen.
Jetzt hab ich nur noch ein define display FRAMEBUFFER /dev/fb1: /dev/fb1 isn't readable and writebale.
fb1 existiert (/dev/fb1 crw-rw---T mit root:video und pi ist in der Gruppe video), sollte also Unix Technisch ok sein.
an was kann das noch liegen?
gruss
Ralf
Zitat von: coolcat am 25 Januar 2016, 13:12:00
...
Jetzt hab ich nur noch ein define display FRAMEBUFFER /dev/fb1: /dev/fb1 isn't readable and writebale.
fb1 existiert (/dev/fb1 crw-rw---T mit root:video und pi ist in der Gruppe video), sollte also Unix Technisch ok sein.
...
Hallo Ralf,
mein FHEM ist in diesen Gruppen.
root@raspberrypi:/dev# id fhem
uid=999(fhem) gid=20(dialout) groups=20(dialout),44(video),999(input)
Kannst du den mit z.B. fbvs etwas anzeigen ? Schau mal auf diese Seite http://www.waveshare.com/wiki/3.5inch_RPi_LCD_%28A%29
Vielleicht hilft es ja. Ich habe es glaube damit eingerichtet.
pejonp
Zitat von: coolcat am 25 Januar 2016, 13:12:00
Jetzt hab ich nur noch ein define display FRAMEBUFFER /dev/fb1: /dev/fb1 isn't readable and writebale.
fb1 existiert (/dev/fb1 crw-rw---T mit root:video und pi ist in der Gruppe video), sollte also Unix Technisch ok sein.
an was kann das noch liegen?
Der fhem Prozess wird doch wahrscheinlich nicht unter dem User pi sondern unter fhem laufen, oder?
Dann muss der User fhem noch in die Gruppe video.
Zitat von: kaihs am 25 Januar 2016, 19:49:08
Der fhem Prozess wird doch wahrscheinlich nicht unter dem User pi sondern unter fhem laufen, oder?
Dann muss der User fhem noch in die Gruppe video.
DAAAANKEEE!!!
Es kann so einfach sein, oder: wer lesen kann, ist klar im Vorteil.... natürlich ist fhem der User :(
kaum macht man es richtig, klappt es auch ;)
dann kann ich endlich weitermachen :)
EDIT: ----> /usr/local/bin/fbvs doesn't exist or isn't executable, please install it wo bekomm ich das her?Gruss
Ralf
Steht auch in der commandref, bitte noch mal genau lesen. Da ist ein Link auf github wo du es runterladen kannst.
Zitat von: kaihs am 26 Januar 2016, 20:37:39
Steht auch in der commandref, bitte noch mal genau lesen. Da ist ein Link auf github wo du es runterladen kannst.
war mit den Fingern zu schnell, hatte es kurz nach dem absenden gelesen. ;(
klappt bisher alles alles ganz gut :)
Ei gude,
hatte mal wieder Zeit, mich dran zu setzen und ein zweites Layout zu erstellen, um auch das Prinzip zu verstehen.
Dazu habe ich im ersten Layout rechts unten ein Rechteck definiert, das WEITER liefert und im zweiten Layout eins, das links unten ZURUECK liefert.
pitouch
Internals:
CFGFN /opt/fhem/config/170_touchscreen.cfg
DEF /dev/input/event0 4095 4095 30
DeviceName pitouch
FD 30
NAME pitouch
NR 570
STATE SCR_TOUCHED, btn: none, touchx: 490, touchy: 3662, screenx: 57, screeny: 286, pressure: 223
TYPE TOUCHSCREEN
TouchX 4095
TouchY 4095
blofftime 30
bltimer 0
layout /opt/fhem/layouts/darkroom.layout
Readings:
2016-02-09 09:03:57 button 1
2016-02-09 09:03:57 evtime 1455005037565640
2016-02-09 09:03:57 pressure 223
2016-02-09 09:03:57 screenx 57
2016-02-09 09:03:57 screeny 286
2016-02-09 09:03:57 touchx 490
2016-02-09 09:03:57 touchy 3662
Timer:
Pitouch_backlight:
HASH pitouch
MODIFIER Backlight
NAME pitouch_Backlight
Attributes:
blauto 1
deflayout /opt/fhem/layouts/darkroom.layout
room Touchscreen
screenx 480
screeny 320
verbose 3
pidisp
Internals:
CFGFN /opt/fhem/config/170_touchscreen.cfg
DEF /dev/fb1
NAME pidisp
NR 568
STATE Initialized
TYPE FRAMEBUFFER
layoutBasedir /opt/fhem/layouts
layoutList darkroom.layout pca301.layout
updateInterval 5
Readings:
2016-02-09 09:17:06 absLayoutNo 1
2016-02-09 09:17:06 layoutFilename darkroom.layout
2016-02-09 00:06:25 state Initialized
Fhem:
absLayoutNo 1
counter 121
fb_device /dev/fb1
filename darkroom.layout
layout font /usr/share/fonts/truetype/msttcorefonts/arial.ttf
pt 14
rgb "000000"
#####################################################################################################
##### Headline
date 15 20
text 220 20 "Status"
time 420 20
line 0 20 480 20
##### Buttons
pt 12
# Rot
rgb "FF0000"
rect 10 30 210 80 1
#TS BTNITOFF rect 10 30 210 80
# Grün
rgb "00ff00"
rect 230 30 430 80 1
#TS BTNITON rect 230 30 430 80
rgb "B6D0D9"
rect 300 250 480 320 1
#TS WEITER rect 300 250 480 320
# Schwarz
rgb "000000"
text 230 110 "ITDarkRoom"
pt 20
rgb "0000ff"
text 5 140 { " DarkRoom: ".ReadingsVal("tempDarkRoom","temperature","")."°C - ".ReadingsVal("tempDarkRoom","humidity","")."%"; }
#line 0 125 225 115 1
rgb "0000ff"
text 5 180 { "Wohnzimmer: ".ReadingsVal("tempWohnzimmer","temperature","")."°C - ".ReadingsVal("tempWohnzimmer","humidity","")."%"; }
#line 0 145 225 135 1
rgb "0000ff"
text 5 220 { "Schlafzimmer: ".ReadingsVal("tempSchlafzimmer","temperature","")."°C - ".ReadingsVal("tempSchlafzimmer","humidity","")."%"; }
#line 0 165 225 155 1
rgb "0000ff"
text 5 260 { " Terrasse: ".ReadingsVal("tempTerrasse","temperature","")."°C - ".ReadingsVal("tempTerrasse","humidity","")."%"; }
useTextAlign 1
useTextWrap 1
Attributes:
bgcolor C0C0C0
layoutBasedir /opt/fhem/layouts
layoutList darkroom.layout pca301.layout
room Touchscreen
size 480x320
startLayoutNo 0
update_interval 5
verbose 3
Mein Display ist das http://www.amazon.com/Tontec%C2%AE-Raspberry-Display-Touchscreen-Transparent/dp/B00NANNJLQ (http://www.amazon.com/Tontec%C2%AE-Raspberry-Display-Touchscreen-Transparent/dp/B00NANNJLQ) Tontec Display mit 480x320 Bildpunkten.
rgb "B6D0D9"
rect 300 250 480 320 1
#TS WEITER rect 300 250 480 320
bzw
rgb "B6D0D9"
rect 0 240 100 350 1
#TS ZURUECK rect 0 240 100 350
mit diesem Notify reagier ich darauf, equivalent das für zurück.
Internals:
CFGFN /opt/fhem/config/170_touchscreen.cfg
DEF pitouch:.*WEITER.* set pidisp layoutFilename pca301.layout
NAME n_Weiter
NOTIFYDEV pitouch
NR 580
NTFY_ORDER 50-n_Weiter
REGEXP pitouch:.*WEITER.*
STATE 2016-02-09 08:35:09
TYPE notify
Readings:
2016-02-09 00:06:27 state active
Attributes:
room Touchscreen
Was mir aufgefallen ist, der Touchscreen liefert zwas Ergebnisse, doch wird nicht der Button für Weiter erkannt, bzw. nur sporadisch. Irgendwann wechselt das Layout:
Internals:
CFGFN /opt/fhem/config/170_touchscreen.cfg
DEF pitouch:.*WEITER.* set pidisp layoutFilename pca301.layout
NAME n_Weiter
NOTIFYDEV pitouch
NR 580
NTFY_ORDER 50-n_Weiter
REGEXP pitouch:.*WEITER.*
STATE 2016-02-09 08:35:09
TYPE notify
Readings:
2016-02-09 00:06:27 state active
Attributes:
room Touchscreen
Beispiel:
Ich bin auf dem zweiten Layout und will ZURUECK aufs Erste:
SCR_TOUCHED, btn: none, touchx: 704, touchy: 3369, screenx: 82, screeny: 263, pressure: 222
das liegt doch mitten im definierten Rechteck, oder?
Ausserdem bleiben beim Wechsel alle definierten Rechtecke bestehen, sind im zweiten Layout neue Buttons, werden aber die alten genommen und nur wenn ich auf einen nicht in L1 definierten Bereich komme, könnte es klappen, wenn es erkannt wird, was, wie gesagt, nicht immer klappt :(
Mach ich was falsch?
Gruss
Ralf
ok,
jetzt klappt es, indem ich pidisp (framebuffer) und pitouch (touchdisplay) auf das gleiche Layout setzte.
Reagiert aber trotzdem nicht immer. Naja, wenn man's weiss
Gruss
Ralf
Hallo,
vielen Dank für das tolle Modul. Funktioniert super.
Ich hatte jedoch im Log Fehler:
2017.02.22 22:44:28 1: PERL WARNING: Subroutine myInternalTimer redefined at ./FHEM/89_TOUCHSCREEN.pm line 544, <$fh> line 1311.
2017.02.22 22:44:28 1: PERL WARNING: Subroutine myRemoveInternalTimer redefined at ./FHEM/89_TOUCHSCREEN.pm line 567, <$fh> line 1311.
Diese habe ich beseitigt, indem ich die Subroutinen mit dem Prefix TOUCHSCREEN_ versehen habe, also TOUCHSCREEN_myInternalTimer
134c134
< myInternalTimer ("Backlight", gettimeofday()+$blofftime, "TOUCHSCREEN_BacklightTimeout", $hash, 0);
---
> TOUCHSCREEN_myInternalTimer ("Backlight", gettimeofday()+$blofftime, "TOUCHSCREEN_BacklightTimeout", $hash, 0);
349c349
< myRemoveInternalTimer ("Backlight", $hash);
---
> TOUCHSCREEN_myRemoveInternalTimer ("Backlight", $hash);
354c354
< myInternalTimer ("Backlight", gettimeofday()+$blofftime, "TOUCHSCREEN_BacklightTimeout", $hash, 0);
---
> TOUCHSCREEN_myInternalTimer ("Backlight", gettimeofday()+$blofftime, "TOUCHSCREEN_BacklightTimeout", $hash, 0);
544c544
< sub myInternalTimer($$$$$) {
---
> sub TOUCHSCREEN_myInternalTimer($$$$$) {
567c567
< sub myRemoveInternalTimer($$) {
---
> sub TOUCHSCREEN_myRemoveInternalTimer($$) {
VG
Olaf