4

多数の UPnP プレーヤー (Sonos) を追跡するラズベリー pi で実行されるノード アプリケーションがあり、これを物理的なリモートから制御できるようにしたいと考えています。私はいくつかのエアマウスを持っています。これには、小さなキーボードと、使用したい音量ボタンがあります。

Linuxマシンで物理キーストロークを読み取る方法を把握しようとしましたが、入力デバイスからイベントを読み取る必要があるという結論に達しました。私の場合は次のようになります。

/dev/input/by-id/usb-Dell_Dell_QuietKey_Keyboard-event-kbd

デバイスなどを見つける方法は問題ではありません。実際の問題は、デバイスから読み取ったデータをどのように解釈するかです。

次のような C 構造体を受け取ることはわかっています。

struct input_event {
    struct timeval time;
    unsigned short type;
    unsigned short code;
    unsigned int value;
};

しかし、ノードからこれを読み取る方法がわかりません。事前定義されたキーストロークからトリガーされる外部アプリを実行し、ノードに対して HTTP 要求を呼び出すことができれば、それが 2 番目のオプションである Python スクリプトまたはネイティブ デーモンになります。ただし、いくつかのホットキーデーモンを見てきましたが、どれも機能しませんでした。

もちろん、何らかの形でノード内に含めることができればいいのですが。

編集:だから私はいくつかのテストを行い、簡単なスニペットを作成しました:

var fs = require('fs');

var buffer = new Buffer(16);

fs.open('/dev/input/by-id/usb-HJT_Air_Mouse-event-kbd', 'r', function (err, fd) {
    while (true) {
        fs.readSync(fd, buffer, 0, 16, null);
        console.log(buffer)
    }
});

これは次のようなものを出力します(スペース用):

<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00>
<Buffer a4 3e 5b 51 c3 cf 03 00 01 00 39 00 01 00 00 00>
<Buffer a4 3e 5b 51 cb cf 03 00 00 00 00 00 00 00 00 00>
<Buffer a4 3e 5b 51 ba 40 06 00 04 00 04 00 2c 00 07 00>
<Buffer a4 3e 5b 51 cd 40 06 00 01 00 39 00 00 00 00 00>
<Buffer a4 3e 5b 51 d2 40 06 00 00 00 00 00 00 00 00 00>

最初の 4 バイトはある種のタイムスタンプであり、次の 3 バイトはマイクロ/ミリ秒のようなものである可能性があることに気付きました。

もう 1 つの奇妙な点は、すべてのキー押下で出力が生成されるわけではなく、その後の押下で 2 倍のデータが送信される可能性があり、ほとんどの場合、後続のキー押下後 (または約 20 秒後) に停止するデータの爆発を開始します。それをどう解釈してよいのか、私にはよくわかりません。このデーモンのソースを読もうとしましたhttps://github.com/baskerville/shkd/blob/masterですが、Cは私の最強の言語ではなく、彼がそれをどのように処理するかを特定できません(または処理する必要があるかどうかもわかりません) )。そして、そのデーモンは私にとってさえ機能しませんでした(ラズベリーパイでコンパイルしました)。

4

2 に答える 2

2

さて、その構造体を見てみましょう。

struct input_event {
    struct timeval time;
    unsigned short type;
    unsigned short code;
    unsigned int value;
};

Astruct timevalは次の構造を持っています。

struct timeval
  {
    __time_t tv_sec;            /* Seconds.  */
    __suseconds_t tv_usec;      /* Microseconds.  */
  };

これらの時間型の定義は次のとおりです。

typedef signed long time_t;
typedef signed long suseconds_t;

Asigned longは 4 バイトなので (仕様に従っただけではなく、実際にはそうです)、最初の 8 バイトは型スタンプです。次に、タイプとコードがあります。どちらもshortであるため、実際にはそれぞれ 2 バイトです。これで値だけが残り、それが再び int になり、4 バイトになります。また、コンパイラは理論的にはフィールド間にパディングを追加できますが、そうしないと確信しています。

したがって、最初に読み取ったバイトをバイトのチャンクに切り刻み4+4+2+2+4=16ます。これらのチャンクのそれぞれがイベントです。これは、サンプル データに適合します。次に、バッファから値を抽出し (ARM システムを使用しているためリトル エンディアン値として - 通常の PC ではビッグ エンディアンが必要です)、値を解釈します。その方法については、http://www.mjmwired.net/kernel/Documentation/input/event-codes.txtを参照してください。定数の値はそこに書き留められていませんが、通常は を使用して見つけることができますgrep -R NAME_OF_CONSTANT /usr/include

みじん切りにしましょう

<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00>

例として。

<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00>
       |   tv_sec  |  tv_usec  |type |code |   value   |

tv_sec16 進数は0x515b3ea4(リトル エンディアンなので逆順)、136493430810 進数です。シンプルな UNIX 時間コンバーターは、これが02.04.2013 - 22:25:08. いいね!

tv_usecです0x0003cfab=249771ので、実際には、249771その時間からマイクロ秒後にイベントが発生しました。

タイプは0x0004=4です。/usr/include/linux/input.hは、これが であることを示していEV_MSCます。

0x0004=4タイプが与えられると、コード、 、手段もわかりますMSC_SCAN

値は0x0007002cです。のどこにも現れませんinput.h。うーん。

于 2013-04-02T20:57:18.453 に答える
0

あなたが探しているのは fs.createReadStream だと思うので、いくつかのイベント ハンドラーをインストールできます。

Buffer.readX ルーチンを使用して、入力イベントを構造体に解析できます。

  var i = 0;
  while((buf.length-i) >= 16) {
     var event = {
        tssec:   buf.readUInt32LE(i+0),
        tsusec:  buf.readUInt32LE(i+4),
        type:    buf.readUInt16LE(i+8),
        code:    buf.readUInt16LE(i+10),
        value:   buf.readUInt32LE(i+12)
     };
     i += 16;
  }
于 2014-06-13T20:07:33.840 に答える