staging.inyokaproject.org

Scanner-Tastendrücke in einem bestimmten Zeitraum zählen (scanbuttond)

Status: Gelöst | Ubuntu-Version: Ubuntu 14.04 (Trusty Tahr)
Antworten |

Heinrich_Schwietering Team-Icon

Wikiteam
Avatar von Heinrich_Schwietering

Anmeldungsdatum:
12. November 2005

Beiträge: 11288

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: 10978

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:

1
2
3
4
5
6
7
8
9
#!/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 Team-Icon

Wikiteam
(Themenstarter)
Avatar von Heinrich_Schwietering

Anmeldungsdatum:
12. November 2005

Beiträge: 11288

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: 10978

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 Team-Icon

Wikiteam
(Themenstarter)
Avatar von Heinrich_Schwietering

Anmeldungsdatum:
12. November 2005

Beiträge: 11288

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: 10978

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 Team-Icon

Wikiteam
(Themenstarter)
Avatar von Heinrich_Schwietering

Anmeldungsdatum:
12. November 2005

Beiträge: 11288

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: 10978

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: 10978

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 Team-Icon

Wikiteam
(Themenstarter)
Avatar von Heinrich_Schwietering

Anmeldungsdatum:
12. November 2005

Beiträge: 11288

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: 10978

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 Team-Icon

Wikiteam
(Themenstarter)
Avatar von Heinrich_Schwietering

Anmeldungsdatum:
12. November 2005

Beiträge: 11288

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: 10978

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:

1
2
3
4
5
6
7
8
9
#!/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: 10978

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: 10978

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
Antworten |