linux – 是否可以在node.js中读出物理键盘笔划?

我有一个节点应用程序,运行在覆盆子pi上,跟踪一堆UPnP播放器(Sonos),我希望能够通过物理遥控器控制它.我有几个airmouses,它有小键盘和我想要使用的音量按钮.

我试图了解如何读取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请求,那将是我的第二个选项,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>

我意识到前四个字节是某种时间戳,后面的3个字节可能是微/毫秒的东西.

另一个奇怪的事情是,并非所有的按键都会产生输出,但随后的按键可能会发送两倍的数据,并且大部分时间它会开始爆破数据,这些数据会在后续按键后(或大约20秒左右后)停止.我真的不确定如何解释它.我试图阅读这个守护进程https://github.com/baskerville/shkd/blob/master的源代码,但C不是我最强的语言,我无法确定他是如何处理它的(或者甚至应该处理它).那个守护进程甚至不适合我(在树莓派上编译).

最佳答案 好吧,让我们来看看那个结构.

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

struct timeval具有以下结构:

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

这些时间类型的定义是

typedef signed long time_t;
typedef signed long suseconds_t;

一个有符号的长整数是4个字节(好吧,如果你只是按照规范,但不是在实践中,它是),所以前8个字节是一个类型戳.接下来,您有一个类型和代码.两者都很短,所以在实践中,每个都是2个字节.现在只剩下剩下的值了,这又是一个int,它将是四个字节.此外,编译器理论上可以在这里添加填充字段,但我很确定他不会.

因此,首先将您读取的字节切换为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_sec是0x515b3ea4(因为它是小端的反转顺序),十进制是1364934308.一个简单的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中无处可寻.嗯.

点赞