12

Python は初めてですが、HID デバイスと evdev の経験があります。HID デバイスとしてインターフェイスする 2D バーコード スキャナがあります。目標は、QR コードから文字列を取得することです。Linux でスキャナーを認識でき、その場所が /dev/input にあることさえわかりました。

私は evdev を見つけ、私のスキャナーで以下の例を実装しました。これは、サイトのデフォルト コードです。値を読み取りますが、ダウンとアップを含む長いイベント コードを出力します。これを文字列に変換する簡単な方法がわかりません。私がやりたいことは、Python の HID スキャナーから文字列を読み取ることだけです。助けや指示をいただければ幸いです(おそらくevdevは答えではありません)。

これが私の現在のpythonコードで、いくつかの出力例があります:

from evdev import *
dev = InputDevice('/dev/input/event1')

print(dev)

for event in dev.read_loop():
    if event.type == ecodes.EV_KEY:
        print(categorize(event))

以下は、いくつかのバーコードからの出力です。

key event at 1383327570.147000, 2 (KEY_1), down
key event at 1383327570.147990, 2 (KEY_1), up
key event at 1383327570.148997, 3 (KEY_2), down
key event at 1383327570.150010, 3 (KEY_2), up
key event at 1383327570.151009, 29 (KEY_LEFTCTRL), down
key event at 1383327570.151009, 42 (KEY_LEFTSHIFT), down
key event at 1383327570.152017, 36 (KEY_J), down
key event at 1383327570.153005, 36 (KEY_J), up
key event at 1383327570.154004, 29 (KEY_LEFTCTRL), up
key event at 1383327570.155005, 32 (KEY_D), down
key event at 1383327570.155993, 32 (KEY_D), up
key event at 1383327570.157002, 48 (KEY_B), down
key event at 1383327570.158015, 48 (KEY_B), up
key event at 1383327570.158997, 48 (KEY_B), down
key event at 1383327570.282002, 18 (KEY_E), up
key event at 1383327570.283004, 49 (KEY_N), down
key event at 1383327570.284005, 49 (KEY_N), up
key event at 1383327570.284968, 18 (KEY_E), down

どうもありがとう!

4

3 に答える 3

17

ここに欠けている変換ステップがあります。あなたの出力はすでにきれいな形式になっているので、もう少し分解するのに役立ちます。

             Timestamp        , scancode, keycode, keystate
key event at 1383327570.147000, 2         (KEY_1), down
key event at 1383327570.147990, 2         (KEY_1), up

これを有効に理解するには、いくつかのことを行う必要があります。

  1. 特定のタイプ (ダウン = 1、アップ = 0) のキーステートのみをフィルタして、key_down タイプのイベントのみをリッスンします。
  2. スキャンコードを ASCII コードに変換します。ASCII コードは、デバイスによって異なり、システムへのマッピング方法によって異なります。

ただし、それらをマップする簡単な方法があります。オンライン サービスを使用して、使用可能なすべての文字を含む既知のバーコードを生成し、そのバーコードをスキャンして、出力された各スキャンコードをスキャナーの正しい文字/数字にマッピングします。次のわずかに変更されたコードを使用して、出力をより適切に制御できます。

import evdev
from evdev import InputDevice, categorize  # import * is evil :)
dev = InputDevice('/dev/input/event1')

# Provided as an example taken from my own keyboard attached to a Centos 6 box:
scancodes = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8',
    10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R',
    20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL',
    30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u';',
    40: u'"', 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N',
    50: u'M', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 100: u'RALT'
}
for event in dev.read_loop():
    if event.type == evdev.ecodes.EV_KEY:
        data = evdev.categorize(event)  # Save the event temporarily to introspect it
        if data.keystate == 1:  # Down events only
            key_lookup = scancodes.get(data.scancode) or u'UNKNOWN:{}'.format(data.scancode)  # Lookup or return UNKNOWN:XX
            print u'You Pressed the {} key!'.format(key_lookup)  # Print it all out!

このスクリプトからのサンプル出力を次に示します。

You Pressed the A key!
You Pressed the B key!
You Pressed the C key!
You Pressed the UNKNOWN:99 key!

オンラインでバーコードを生成すると、どのスキャンコードがどの値にマッピングされるかがわかります! 独自のテーブルを構築して利益を上げましょう!

HTH

于 2013-11-02T00:33:10.400 に答える
12

VooDooNOFX のコードは非常に役に立ち、正しい方向に進むことができました。ハネウェル MS7580 または類似の光学式スキャナと、Linux 上の Python を使用したキーボード エミュレーションを接続しようとしている他の人にわかりやすくするために、私自身の質問に答えたいと思いました。

このプロジェクトは、BeagleBone Black を使用して行われました。コマンド ライン アクセスのみで、スキャナーを通常のキーボードとして使用することはできませんでした。シフトを適切に処理するために、シフト ボタンが押されたときのスキャンコードの 2 番目のグループを追加する必要がありました。QRコードから文字列を読み取るための最終的なコードは次のとおりです。

import evdev
from evdev import InputDevice, categorize, ecodes  
dev = InputDevice('/dev/input/event1')

# Provided as an example taken from my own keyboard attached to a Centos 6 box:
scancodes = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8',
    10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'q', 17: u'w', 18: u'e', 19: u'r',
    20: u't', 21: u'y', 22: u'u', 23: u'i', 24: u'o', 25: u'p', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL',
    30: u'a', 31: u's', 32: u'd', 33: u'f', 34: u'g', 35: u'h', 36: u'j', 37: u'k', 38: u'l', 39: u';',
    40: u'"', 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'z', 45: u'x', 46: u'c', 47: u'v', 48: u'b', 49: u'n',
    50: u'm', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 57: u' ', 100: u'RALT'
}

capscodes = {
    0: None, 1: u'ESC', 2: u'!', 3: u'@', 4: u'#', 5: u'$', 6: u'%', 7: u'^', 8: u'&', 9: u'*',
    10: u'(', 11: u')', 12: u'_', 13: u'+', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R',
    20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'{', 27: u'}', 28: u'CRLF', 29: u'LCTRL',
    30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u':',
    40: u'\'', 41: u'~', 42: u'LSHFT', 43: u'|', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N',
    50: u'M', 51: u'<', 52: u'>', 53: u'?', 54: u'RSHFT', 56: u'LALT',  57: u' ', 100: u'RALT'
}
#setup vars
x = ''
caps = False

#grab provides exclusive access to the device
dev.grab()

#loop
for event in dev.read_loop():
    if event.type == ecodes.EV_KEY:
        data = categorize(event)  # Save the event temporarily to introspect it
        if data.scancode == 42:
            if data.keystate == 1:
                caps = True
            if data.keystate == 0:
                caps = False
        if data.keystate == 1:  # Down events only
            if caps:
                key_lookup = u'{}'.format(capscodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode)  # Lookup or return UNKNOWN:XX
            else:
                key_lookup = u'{}'.format(scancodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode)  # Lookup or return UNKNOWN:XX
            if (data.scancode != 42) and (data.scancode != 28):
                x += key_lookup  
            if(data.scancode == 28):
                print x          # Print it all out!
                x = ''

evdev で正しい方向に向けてくれた VooDoo に感謝します。

于 2013-11-03T19:59:07.993 に答える