可以在node.js中读出物理键盘笔触吗? [英] Would it be possible to read out physical keyboard strokes in node.js?

查看:100
本文介绍了可以在node.js中读出物理键盘笔触吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在树莓派上运行的节点应用程序,该应用程序跟踪一堆UPnP播放器(Sonos),我希望能够通过物理遥控器进行控制.我有几个滑鼠,其中有小键盘和我想使用的音量按钮.

I have a node application which runs on a raspberry pi that keeps track of a bunch of UPnP-players (Sonos), which I would like to be able to control through a physical remote. I have a couple of airmouses, which has small keyboards as well as volume buttons that I would like to use.

我试图掌握如何在linux机器上读取物理按键,并得出结论,我需要从输入设备读取事件,在我的情况下是:

I have tried to get a grip on how to read out physical key strokes on a linux machine, and come to the conclusion that I need to read events from the input device, which in my case would be:

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

如何找到这样的设备和东西不是问题,真正的问题是如何解释从其中读取的数据.

How to find the device and stuff like that is not a problem, the real issue is how to interpret the data that you read from it.

我知道您会收到一个C结构,如下所示:

I know that you would receive a C struct, like this:

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

但是我不确定如何去从node读取它.如果我可以运行一个将由预定义的按键触发的外部应用程序,然后对我的节点调用HTTP请求,那将是我的第二个选择,即python脚本或某些本机守护程序.但是,我查看了一些热键守护程序,但是它们都不起作用.

But I'm not sure how I would go about reading this from node. If I could run an external app that would be triggered from pre-defined keystrokes, and then invoke an HTTP-request against my node, that would be my second option, a python script or some native daemon. I have however looked at some hotkey-daemons, but none of them worked.

如果我能以某种方式将其包含在节点中,那当然很好.

If would of course be nice if I could contain it within node somehow.

所以我做了一些测试,并做了一个简单的代码段:

So I did some testing, and made a simple snippet:

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)
    }
});

这将输出如下内容(用于空格):

This outputs something like this (for space):

<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>

我意识到前四个字节是某种时间戳,而后三个字节可能是微秒级的东西.

I realize that the first four bytes are some sort of timestamp, and the following 3 bytes could be something like a micro/millisecond thing.

另一个奇怪的是,并非所有按键都会产生输出,但是随后的按键可能会发送两倍的数据,并且在大多数情况下,它开始播放数据,而这些数据在随后的按键之后(或大约20秒后)会停止. .我不太确定该怎么解释.我已尝试阅读该守护程序的源代码 https://github.com/baskerville/shkd/blob /master ,但是C不是我最强的语言,我无法确定他的处理方式(或者是否应该处理).而且那个守护进程甚至对我都不起作用(在树莓派上编译).

Another odd thing is that not all keypresses produces output, but a subsequent press might sent twice as much data, and most of the time it starts blasting out data which would stop after subsequent keypresses (or after about 20 seconds or so). I'm not really sure how to interpret that. I have tried to read the source for this daemon https://github.com/baskerville/shkd/blob/master but C is not my strongest language and I can't identify how he handles it (or if it should even be handled). And that daemon didn't even work for me (compiled it on a raspberry pi).

推荐答案

好,让我们看一下该结构.

Well, let's have a look at that struct.

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

A struct timeval具有以下结构:

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

这些时间类型的定义是

typedef signed long time_t;
typedef signed long suseconds_t;

A signed long是4个字节(嗯,如果您只是遵循规范,不是这样,但实际上是这样),因此前8个字节是类型标记.接下来,您有一个类型和一个代码.两者都是short,因此在实践中,它们每个都是2个字节.现在只剩下一个值,这又是一个int,它将是四个字节.另外,理论上,编译器可以在此处的字段之间添加填充,但是我很确定他不会.

A signed long is 4 bytes (well, not if you just follow the spec, but in practice, it is), so the first 8 bytes are a typestamp. Next, you have a type and a code. Both are short, so in practice, they're 2 bytes each. Now there's just the value left, and that's an int again, which will be four bytes. Also, a compiler could theoretically add padding between the fields here, but I'm pretty sure he won't.

因此,首先将已读取的字节切成4+4+2+2+4=16个字节的块.这些块中的每一个都是一个事件.这适合您的样本数据.接下来,从缓冲区中提取值(因为您使用的是ARM系统,所以需要使用小的endian值,而在普通PC上则需要big endian)并解释这些值.有关如何执行此操作的说明,请阅读 http://www.mjmwired. net/kernel/Documentation/input/event-codes.txt .常量的值没有写在这里,但是您通常可以使用grep -R NAME_OF_CONSTANT /usr/include来找到它们.

So, first chop the bytes you've read into chunks of 4+4+2+2+4=16 bytes. Each of those chunks is an event. This fits your sample data. Next, extract the values from the buffer (as little endian values because you're on an ARM system – on a normal PC, you'd need big endian) and interpret the values. For instructions on how to do that, read http://www.mjmwired.net/kernel/Documentation/input/event-codes.txt. The values of the constants aren't written down there, but you can usually find those using 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_sec0x515b3ea4(因为是小尾数,所以顺序相反),十进制是1364934308.一个简单的unix时间转换器报告这表示02.04.2013 - 22:25:08.看起来不错!

tv_sec in hex is 0x515b3ea4 (reversed order because it's little endian), which is 1364934308 in decimal. A simple unix time converter reports that this means 02.04.2013 - 22:25:08. Looks good!

tv_usec0x0003cfab=249771,因此实际上,该事件在那之后的249771微秒内发生.

tv_usec is 0x0003cfab=249771, so actually, the event happened 249771 microseconds after that time.

类型为0x0004=4. /usr/include/linux/input.h告诉我们这是EV_MSC.

Type is 0x0004=4. /usr/include/linux/input.h tells us that this is a EV_MSC.

鉴于类型,我们还可以看到代码0x0004=4表示MSC_SCAN.

Given the type, we can also see the the code, 0x0004=4, means MSC_SCAN.

值是0x0007002c.在input.h中无处显示.嗯.

The value is 0x0007002c. Turns up nowhere in input.h. Hmm.

这篇关于可以在node.js中读出物理键盘笔触吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆