2016-02-20 13 views
8

Voglio rilevare quando si preme il tasto XF86Launch1 sulla mia tastiera, usando Python.Tasti multimediali in Python (Linux)

Ho un server headless con una tastiera connessa Bluetooth. Mi piacerebbe avviare un programma da riga di comando ogni volta che viene premuto un tasto multimediale specifico.

Al momento, sto usando:

import sys 
import tty, termios 

def getch(): 
    fd = sys.stdin.fileno() 
    old_settings = termios.tcgetattr(fd) 
    try: 
     tty.setraw(fd) 
     ch = sys.stdin.read(1) 
    finally: 
     termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
    return ch 

print getch() 

Ma non rileverà i tasti multimediali. Nulla viene stampato quando li preme.

C'è un modo per rilevare questi tasti su una scatola Ubuntu senza testa - o un modo migliore per avviare un programma su Keypress?

risposta

-2

Provare a leggere xinput test <id> stdout in un ciclo e catturare gli eventi necessari.

Ecco alcuni esempi in Bash:

#!/bin/bash 

keyboard_id=9 # use xinput to find your keyboard id 

xinput test $keyboard_id | while read line ; do 
    case $line in 
     "key press 44") echo -e "\n == j pressed ==" ;; 
     "key press 45") echo -e "\n == k pressed ==" ;; 
    esac 
done 
1

Io penso che il tuo problema è che i tasti multimediali non mappano terminale di ingresso.

È possibile che si possa fare progressi eseguendo xev per intrappolare la chiave e xmodmap per mappare la chiave su un input diverso.

In alternativa, utilizzare qualcosa come TKinter e verificare se un programma grafico non raccoglie i tasti premuti.

from Tkinter import * 

root = Tk() 

def key(event): 
    print "pressed", repr(event.char) 

def callback(event): 
    frame.focus_set() 

frame = Frame(root, width=100, height=100) 
frame.bind("<Key>", key) 
frame.bind("<Button-1>", callback) 
frame.pack() 

root.mainloop() 

Un'altra possibilità è quella di mappare su un tasto F anziché su un tasto multimediale. (Vale a dire F9)


Edit: ulteriori ricerche in questo ha portato in questi due link:

Extra Keyboard Keys

Extra Keyboard Keys in Console

La console di per sé non supporta i tasti multimediali. Ma supporta i tasti F personalizzati. F30-F246 sono sempre gratuiti. Piuttosto che mappare a XF86Launch1, mappare a F70. Quindi mappare F70 all'ingresso della tastiera nella keymap, oppure utilizzare lo script Python che hai già scritto per gestirlo.

2

Piuttosto che cercare di leggere lo stdin del tty, è possibile utilizzare l'API del dispositivo di input di Linux per leggerli.

su Linux, tutti i dispositivi di input si mostrano come un file con /dev/input (come /dev/input/event0) e quando si read()s da questi file, viene restituito dati strutturati che indica quando i tasti vengono premuti e rilasciati.

In C, la libreria libevdev fornisce un wrapper attorno a questi. In Python, è possibile utilizzare python-evdev library. Dovrebbe anche essere possibile leggere direttamente dal dispositivo di input (anche se potrebbe essere necessario leggere attentamente la documentazione del kernel & per gestirla correttamente).

1

pycopia può essere un'opzione. Lo sto usando con il pulsante bluetooth this e sembra funzionare abbastanza bene.Sto ancora lavorando per farlo ricollegare al pulsante quando il pulsante va a dormire e poi torna indietro. Ecco parte dello script che sto usando:
keyboard.py:

from pycopia.OS.Linux import Input 
from pycopia.OS.Linux import event 

class Satechi(Input.EventDevice): 
    DEVNAME = 'Satechi' 

    def register_callback(self, cb): 
     self._callback = cb 

    def poll(self): 
     while 1: 
      ev = self.read() 
      if ev.evtype == event.EV_KEY: 
       self._callback(ev) 

    read_handler = poll 

button.py

from keyboard import Satechi 

def callback(event): 
    pass #Do something fun 

if __name__ == '__main__': 
    pm = Satechi() 
    pm.find() 
    pm.register_callback(callback) 

    while 1: 
     try: 
      pm.poll() 
     except OSError: 
      pm = Satechi() 
      while True: 
       try: 
        pm.find() 
        pm.register_callback(callback) 
        break 
       except IOError: 
        pass 
    pm.close() 

Dove DEVNAME è il nome dei dispositivi in ​​/proc/bus/input/devices.
È possibile stampare event nel callback per capire quale sia il code e value è per il pulsante che si sta cercando

+0

hey @ Joe Hai mai finire la parte riconnessione una volta il pulsante va a dormire? – mikebertiean

Problemi correlati