#USBテンキーボード
リモートコンソールで実行したpythonプログラムと、ラズパイに物理接続したUSBテンキーボードを連携させて、テンキーを押すとラズパイでプログラムが実行される実験のメモ。
キー入力はpythonで**input()**を使えばできるが、実行しているコンソールの入力を受け付けるので、物理的に接続しているキーデバイスからの入力はできない。
タクトスイッチのように、物理接続のキーボード入力を解釈してなにがしかのコマンドを実行するプログラムを作りたかったので、それを可能にするpythonライブラリevdevを使って、実験したメモ。
冒頭にある記述の通りの機能を持つ。
This package provides bindings to the generic input event interface in Linux. The evdev interface serves the purpose of passing events generated in the kernel directly to userspace through character devices that are typically located in /dev/input/.
This package also comes with bindings to uinput, the userspace input subsystem. Uinput allows userspace programs to create and handle input devices that can inject events directly into the input subsystem.
#USBテンキーボード
特にこれというものではなく、値段とメーカーから以下を購入した。使用する機種により、pythonプラグラムでUSBデバイス名は変わるし、キーマップも変わる可能性がある。
#デバイスの確認
入力デバイスは**/dev/input/by-id/**をlistすれば分かる。
ls /dev/input/by-id/
表示されたusb-SINO_WEALTH_ELECOM_10KEYBOARD-event-kbdを、pythonプログラム内で指定する。
usb-SINO_WEALTH_ELECOM_10KEYBOARD-event-kbd
#pythonプラグラム
##参考文献
以下の情報を参考にして、プログラムを作成した。というか、ほぼパクりました。。。
##ライブラリ
以下のライブラリをラズパイにインストールした。python2.7の場合はpip3ではなくpipを使う。
pip3 install evdev
##プログラム1
参考文献をほぼパクり、ENTERキーでプログラムを終了するようにした。キーマップは修正している。
キーマップはkeymap.pyに記載しておく。
# keymapping determined by trial and error
keys = {
79: "1",
80: "2",
81: "3",
75: "4",
76: "5",
77: "6",
71: "7",
72: "8",
73: "9",
82: "0",
83: ".",
96: "ENTER",
78: "+",
74: "-",
14: "BS",
15: "TAB",
55: "*",
98: "/",
# Numlock keys:
111: "N.",
110: "N0",
107: "N1",
108: "N2",
109: "N3",
105: "N4",
# notice the missing N5
106: "N6",
102: "N7",
103: "N8",
104: "N9",
}
keymap.pyをインポートして、プログラム本体を記述する。
#coding: utf-8
from evdev import InputDevice
from select import select
from keymap import keys
# look for a /dev/input/by-id/usb...kbd or something similar
DEVICE = "/dev/input/by-id/usb-SINO_WEALTH_ELECOM_10KEYBOARD-event-kbd"
dev = InputDevice(DEVICE)
while True:
# wait for keypad command
r, w, x = select([dev], [], [])
# read keypad
for event in dev.read():
if event.type==1 and event.value==1:
if event.code in keys:
print("KEY : ", keys[event.code])
#print("KEY CODE: ", event.code)
# do something with this key press
# ...
if(event.code == 96): #"ENTER"
print("終了します")
exit()
else:
pass
##プログラム2
openjtalkがインストールされ、ラズパイにスピーカを接続している前提。押したキーをラズパイが読み上げる。ENTERで終了する。
#coding: utf-8
from evdev import InputDevice
from select import select
import subprocess
def jtalk(t):
open_jtalk=['open_jtalk']
mech=['-x','/var/lib/mecab/dic/open-jtalk/naist-jdic']
htsvoice=['-m','/usr/share/hts-voice/mei/mei_normal.htsvoice']
speed=['-r','1.0']
outwav=['-ow','open_jtalk.wav']
cmd=open_jtalk+mech+htsvoice+speed+outwav
c = subprocess.Popen(cmd,stdin=subprocess.PIPE)
c.stdin.write(t)
c.stdin.close()
c.wait()
aplay = ['aplay','-q','open_jtalk.wav']
wr = subprocess.Popen(aplay)
from keymap import keys
# look for a /dev/input/by-id/usb...kbd or something similar
DEVICE = "/dev/input/by-id/usb-SINO_WEALTH_ELECOM_10KEYBOARD-event-kbd"
dev = InputDevice(DEVICE)
if __name__ == '__main__':
while True:
# wait for keypad command
r, w, x = select([dev], [], [])
# read keypad
for event in dev.read():
if event.type==1 and event.value==1:
if event.code in keys:
print("KEY : ", keys[event.code])
#print("KEY CODE: ", event.code)
text = str(keys[event.code])
jtalk(text.encode('utf-8'))
# do something with this key press
# ...
if(event.code == 96): #"ENTER"
text = "終了します"
jtalk(text.encode('utf-8'))
exit()
else:
pass
event.code別にプログラムを準備することで、物理接続のテンキーボードをタクトスイッチ代わりに使えるようになる。