Heinrich_Schwietering
Wikiteam
Anmeldungsdatum: 12. November 2005
Beiträge: 11324
Wohnort: Bremen
|
Hi! An meinem "neuen" Scanner CanoScan LIDE 60 gibt es Bedientasten. Mit scanbuttond lassen die sich auch verwenden. Jetzt würde ich gerne mehrere Funktionen auf eine Taste legen, je nachdem wie oft sie gedrückt wird (also z.B. Farb-, Gray-, SW-Kopie auf eine Taste). Dafür müsste ich zählen, wie oft in einem Zeitraum (sagen wir 5 Sekunden) die entsprechende Taste gedrückt wird, und diesen Wert dann dem Scan-Skript übergeben, damit dann die jeweils gewünschte Aktion durchgeführt wird. Wie könnte ich das bewerkstelligen? so long hank
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Ich denke da braucht man zwei Skripte: Eines, das beim Drücken des Buttons durch scanbuttond aufgerufen wird und eine Art Daemon, der nach dem ersten Druck mindestens 5 Sekunden weiterlebt: Das Skript, das du durch scanbuttond aufrufst, könnte z.B. so aussehen:
| #!/bin/bash
PID_FILE=/tmp/scanbutton.pid
if [ -e $PID_FILE ]; then
kill -SIGUSR1 $(<"$PID_FILE")
else
rm -f /tmp/scanbutton.log
nohup /usr/local/bin/scanbutton_counter >> /tmp/scanbutton.log 2<&1 < /dev/null &
fi
|
Und das Gegenstück in /usr/local/bin/scanbutton_counter dazu könnte so aussehen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | #!/bin/bash
TIMEOUT=5 # count button presses after n seconds and take appropriate actions
PID_FILE=/tmp/scanbutton.pid
echo $$ > $PID_FILE # create a file with our pid
declare -a BTN_PRESSED
BTN_PRESSED+=($(date +%s))
trap "BTN_PRESSED+=($(date +%s));" SIGUSR1
function check_runtime {
if [[ ${BTN_PRESSED[0]} -lt $(date +%s -d "$TIMEOUT seconds ago") ]]; then
return 1 # the oldest timestamp is older than $TIMEOUT
else
return 0
fi
}
trap 'rm -f "$PID_FILE"; exit 0' SIGTERM SIGINT
while check_runtime; do
sleep 0.2 # if the button presses have a shorter delta t, then reduce this value
done
echo "Button has been pressed at ${BTN_PRESSED[@]}"
case ${#BTN_PRESSED[@]} in
1) echo "action #1"
;;
2) echo "action #2"
;;
3) echo "action #3"
;;
4) echo "action #4"
;;
*) echo "too many button presses"
esac
rm -f "$PID_FILE" # cleanup
|
Wobei du in dem case-Statement die Aktionen je nach Anzahl der Tastendrücke definieren kannst. Das Skript funktioniert so:
Falls das zweite Skript noch nicht läuft, wird es gestartet. Falls es läuft, wird SIGUSR1 gesendet, woraufhin es den Timestamp in den Array schreibt. Sobald das erste Array-Element älter als die aktuelle Zeit minus dem TIMEOUT ist, zählt es die Array-Elemente, führt das case-Statement aus und beendet sich. Die Ausgabe der Skripte erfolgt in der Datei /tmp/scanbutton.log.
|
Heinrich_Schwietering
Wikiteam
(Themenstarter)
Anmeldungsdatum: 12. November 2005
Beiträge: 11324
Wohnort: Bremen
|
Hi! Danke, das sieht schon sehr gut aus! 👍 scanbuttond wird über zwei Dateien gesteuert, in /etc/scanbuttond/, und zwar initscanner.sh und buttonpressed.sh, wobei letztere verwendet wird, um andere Skripte aufzurufen. Mit buttonpressed.sh würde ich also dein erstes Skript aufrufen, was dann dein zweites aufruft? Ich teste das mal an... so long hank
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Heinrich Schwietering schrieb: Hi! Danke, das sieht schon sehr gut aus! 👍 scanbuttond wird über zwei Dateien gesteuert, in /etc/scanbuttond/, und zwar initscanner.sh und buttonpressed.sh, wobei letztere verwendet wird, um andere Skripte aufzurufen. Mit buttonpressed.sh würde ich also dein erstes Skript aufrufen, was dann dein zweites aufruft?
Das ginge, aber eigentlich kannst du das erste Skript auch direkt in buttonpressed.sh unterbringen ☺
|
Heinrich_Schwietering
Wikiteam
(Themenstarter)
Anmeldungsdatum: 12. November 2005
Beiträge: 11324
Wohnort: Bremen
|
Hi! Ja, das habe ich gerade probiert. Leider bekomme ich Fehlermeldungen: /etc/scanbuttond/buttonpressed.sh: 15: kill: Illegal option -S
bezieht sich auf
kill -SIGUSR1 $(<"$PID_FILE") Unterschiede zwischen bash und sh? so long hank
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Heinrich Schwietering schrieb: Hi! Ja, das habe ich gerade probiert. Leider bekomme ich Fehlermeldungen: /etc/scanbuttond/buttonpressed.sh: 15: kill: Illegal option -S
bezieht sich auf
kill -SIGUSR1 $(<"$PID_FILE") Unterschiede zwischen bash und sh?
sh zeigt bei Ubuntu standardmäßig auf die dash - aber berücksichtigt scanbuttond den Shebang der Datei nicht, wenn es die ausführt? Wie sieht das Skript jetzt bei dir aus?
|
Heinrich_Schwietering
Wikiteam
(Themenstarter)
Anmeldungsdatum: 12. November 2005
Beiträge: 11324
Wohnort: Bremen
|
Hi! Wenn ich beide Skripte auf bash umstelle, geht es ☺. Im Log kann ich erkennen, dass der Befehl für "action 2" etc ausgeführt wird 👍 Super, dann bastele ich jetzt mal weiter, sollte ja für die anderen Tasten genauso funktionieren! So sieht die buttonpressed.sh jetzt aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | #!/bin/bash
TMPDIR="$HOME/Dokumente/Scans" #hier wird ein Verzeichnis für die Datei festgelegt; durch die Verwendung der Umgebungsvariable $HOME wird jedesmal der Desktop des aktuellen Benutzers verwendet
TMPFILE="$TMPDIR/scan`date +%Y%m%d`-`date +%H%M%S`" #wir generieren uns hier den Dateinamen für das spätere Ergebnis; der Name besteht aus dem Präfix scan und wird jedesmal um Datum und Uhrzeit ergänzt
#Dateinamenerweiterungen werden später hinzugefügt
LOCKFILE="/tmp/copy.lock" #Variable für das Lockfile, das kennzeichnet, ob der Scanner schon in Benutzung ist; wird hier nicht verwendet
case $1 in
1) echo "Button 1 pressed" #wird Button 1 gedrückt so wird eine Meldung ausgegeben (nur sichtbar, wenn scanbuttond im Vordergrund läuft - zum Debuggen)
$HOME/.scanscripts/copy.sh $TMPFILE $DEVICE #und das Skript scan.sh im versteckten Ordner .scanscripts im Homeverzeichnis gestartet; zusätzlich werden noch Name und Ort des Tempfiles,
;; #sowie die Adresse des Scanners übergeben, sinnvoll bei mehr als einem Scanner
2) echo "Button 2 pressed" #wird Button 2 gedrückt, so wird eine Meldung ausgegeben (siehe oben)
PID_FILE=/tmp/scanbutton.pid
if [ -e $PID_FILE ]; then
kill -SIGUSR1 $(<"$PID_FILE")
else
rm -f /tmp/scanbutton.log
nohup /home/heinrich/.scanscripts/scanbutton_counter.sh >> /tmp/scanbutton.log 2<&1 < /dev/null &
fi
;;
3) echo "Button 3 pressed - pdf" #wird Button 3 gedrückt, so wird eine Meldung ausgegeben (siehe oben)
$HOME/.scanscripts/pdf.sh $TMPFILE $DEVICE
;;
4) echo "Button 4 pressed" #wird Button 3 gedrückt, so wird eine Meldung ausgegeben (siehe oben)
$HOME/.scanscripts/mail.sh $TMPFILE $DEVICE #und das Skript mail.sh im versteckten Ordner .scanscripts im Homeverzeichnis gestartet; zu übergebenen Attributen siehe oben
;;
esac
|
so long hank EDIT fast OK... jetzt meldet das TErminal rm: das Entfernen von »/tmp/scanbutton.log“ ist nicht möglich: Vorgang nicht zulässig Rechteproblem?... EDIT2 und dann doch wieder
/etc/scanbuttond/buttonpressed.sh: Zeile 15: kill: (5143) - Vorgang nicht zulässig
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Heinrich Schwietering schrieb: EDIT fast OK... jetzt meldet das TErminal rm: das Entfernen von »/tmp/scanbutton.log“ ist nicht möglich: Vorgang nicht zulässig Rechteproblem?...
Wem gehört die Datei denn aktuell? Wenn ich das Wiki richtig verstanden habe, läuft scanbuttond normalerweise unter dem Benutzer saned - der darf die Datei natürlich nur löschen, wenn er die Rechte dazu hat.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Leider erkennt scanbuttond die Tasten von meinem Canon 8800F nicht, sonst könnte ich das selbst ausprobieren. Edit: kann es sein, dass du das Skript mit unterschiedlichen Benutzern ausführst?
|
Heinrich_Schwietering
Wikiteam
(Themenstarter)
Anmeldungsdatum: 12. November 2005
Beiträge: 11324
Wohnort: Bremen
|
Hi! seahawk1986 schrieb:
Edit: kann es sein, dass du das Skript mit unterschiedlichen Benutzern ausführst?
Nein, eigentlich nicht. Aber ich teste noch mal mit diesem Hinweis aus dem Wiki "muss in der Datei /etc/default/scanbuttond der Eintrag RUN_AS_USER=saned zu RUN_AS_USER=root geändert werden." Ich hatte es allerdinhs so versatanden, dass es sich dabei um ein workaround für diese spezielle scanbutttond-Version scanbuttond_0.2.3.cvs20090713-1 handelt, bei mir ist aber scanbuttond_0.2.3.cvs20090713-16 im Einsatz... so long hank
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Ich hatte das so verstanden, dass das ein Workaround ist, wenn man in Probleme mit den Berechtigungen beim Zugriff auf die Hardware läuft - aber mir hat das vor allem verraten, dass scanbuttond als System-Dienst standardmäßig nicht unter dem Benutzer root läuft. Wenn man z.B. die Funktion der buttonpressed.sh als normaler Nutzer mit scanbuttond -f getestet hat und danach den Dienst startet, dann haben /tmp/scanbutton.pid und /tmp/scanbutton.log natürlich noch den normalen User als Besitzer und der User saned hat nicht die Rechte die Dateien zu löschen oder zu beschreiben - in dem Fall müsste man die einmalig von Hand löschen.
|
Heinrich_Schwietering
Wikiteam
(Themenstarter)
Anmeldungsdatum: 12. November 2005
Beiträge: 11324
Wohnort: Bremen
|
Hi! Noch bin ich dabei, immer nur mit scanbuttond -f im Terminal zu hantieren, nicht als Hintergrunddienst... Jetzt erscheint wieder /etc/scanbuttond/buttonpressed.sh: Zeile 15: kill: (5613) - Kein passender Prozess gefunden
😕 Was hat es mit dem delta-Wert und der sleep 0.2-Angabe auf sich? HAbe versucht, damit herumzuspielen, ohne Erfolg... so long hank
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Jetzt erscheint wieder /etc/scanbuttond/buttonpressed.sh: Zeile 15: kill: (5613) - Kein passender Prozess gefunden
Dann hast du es vermutlich geschafft genau innerhalb der kritischen Phase den Knopf zu drücken, in der sich das Skript beendet hat. Also das erste Skript hat geprüft, ob /tmp/scanbutton.pid existiert und betritt darauf hin die if-Schleife und bevor das Signal mittels kill abgesetzt wurde, hat sich sich das zweite Skript beendet, weil die Zeit abgelaufen war (und die Datei gelöscht). Die Fehlermeldung kann man unterdrücken, wenn man will:
| #!/bin/bash
PID_FILE=/tmp/scanbutton.pid
if [ -e $PID_FILE ]; then
kill -SIGUSR1 $(<"$PID_FILE") 2>&1 > /dev/null |:
else
rm -f /tmp/scanbutton.log
nohup /usr/local/bin/scanbutton_counter >> /tmp/scanbutton.log 2<&1 < /dev/null &
fi
|
Heinrich Schwietering schrieb: Was hat es mit dem delta-Wert und der sleep 0.2-Angabe auf sich? HAbe versucht, damit herumzuspielen, ohne Erfolg...
trap reagiert auf das Signal SIGUSR1 und der dort angegebene Befehl wird erst ausgeführt, nachdem der Sleep-Befehl durch ist - d.h. mit einem sleep von 0,2 Sekunden kann man theoretisch bis zu 5 mal in der Sekunde das Signal SIGUSR1 an das zweite Skript weitergeben (wobei ich gerade im Hilfetext gelesen habe, dass scanbuttond in der Voreinstellung nur alle 0,333 Sekunden nachschaut, ob der Knopf gedrückt wurde).
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Oder du hast einen Fehler im zweiten Skript, der verhindert, dass die Datei /tmp/scanbutton.pid beim Beenden des Skripts gelöscht wird.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11229
Wohnort: München
|
Man könnte das Aufräumen noch besser umsetzen, so dass die Datei zuverlässig gelöscht wird: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 | #!/bin/bash
TIMEOUT=5 # count button presses after n seconds and take appropriate actions
PID_FILE=/tmp/scanbutton.pid
echo $$ > $PID_FILE # create a file with our pid
declare -a BTN_PRESSED
BTN_PRESSED+=($(date +%s))
function cleanup {
rm -f "$PID_FILE"
}
function check_runtime {
if [[ ${BTN_PRESSED[0]} -lt $(date +%s -d "$TIMEOUT seconds ago") ]]; then
return 1 # the oldest timestamp is older than $TIMEOUT
else
return 0
fi
}
trap 'cleanup; exit 0' SIGTERM SIGINT
trap cleanup EXIT
trap "BTN_PRESSED+=($(date +%s));" SIGUSR1
while check_runtime; do
sleep 0.2 # if the button presses have a shorter delta t, then reduce this value
done
echo "Button has been pressed at ${BTN_PRESSED[@]}"
case ${#BTN_PRESSED[@]} in
1) echo "action #1"
;;
2) echo "action #2"
;;
3) echo "action #3"
;;
4) echo "action #4"
;;
*) echo "too many button presses"
esac
|
|