Is it possible to read physical keyboard strokes in node.js?

I have a node application that runs on raspberries pi that tracks a bunch of UPnP players (Sonos) that I would like to control using a physical remote. I have a pair of air muscles that have small keyboards, as well as volume buttons that I would like to use.

I tried to understand how to read physical strokes on a Linux machine, and come to the conclusion that I need to read events from an input device, which in my case would be:

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

Finding a device and stuff like that is not a problem; the real problem is how to interpret the data you are reading.

I know that you will get a C structure, for example:

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

But I'm not sure how I will read this with node. If I could run an external application that would start from predefined keystrokes and then call an HTTP request against my node, this would be my second option: a python script or some kind of native daemon. However, I looked at some hot daemon keys, but none of them worked.

If, of course, it would be nice if I could somehow contain it inside the node.

EDIT: So, I did some tests 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 a 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 understand that the first four bytes are a kind of timestamp, and the next 3 bytes can be something like micro / milliseconds.

Another feature is that not all keystrokes display output, but subsequent keystrokes can send twice as much data, and most of the time it starts dumping data that stops after subsequent keystrokes (or after about 20 seconds or so ), I'm not sure how to interpret this. I tried to read the source for this daemon https://github.com/baskerville/shkd/blob/master , but C is not the strongest language, and I cannot determine how it processes it (or if it even needs to be processed). And this demon did not even work for me (compiled it on a raspberry pie).

+4
source share
2 answers

Ok, look at this structure.

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

A struct timeval has the following structure:

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

Definition of those types of time

 typedef signed long time_t; typedef signed long suseconds_t; 

A signed long - 4 bytes (well, if you just follow the specification, but in practice it is), so the first 8 bytes are typestamp. Then you have the type and code. Both values ​​are short , so in practice they are equal to 2 bytes. Now only the value remains, and again there will be an int, which will be four bytes. In addition, the compiler can theoretically add padding between fields here, but I'm sure it will not.

So, first chop off the bytes you read into pieces 4+4+2+2+4=16 bytes. Each of these pieces is an event. This matches your sample data. Then extract the values ​​from the buffer (as the minimum values, because you are on the ARM system - on a regular PC, you need a big end) and interpret the values. For instructions on how to do this, read http://www.mjmwired.net/kernel/Documentation/input/event-codes.txt . Constant values ​​are not written there, but you can usually find them with grep -R NAME_OF_CONSTANT /usr/include .

Let me chop

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

as an example.

 <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 in hexadecimal format 0x515b3ea4 (reverse order because it is a bit endian) which is 1364934308 in decimal value. A simple unix time converter reports that this means 02.04.2013 - 22:25:08 . Looks nice!

0x0003cfab=249771 , so in fact the event happened 249771 microseconds after this time.

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

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

The value is 0x0007002c . In input.h nothing happens. Hm.

+2
source

I think you are looking for fs.createReadStream, so you can install some event handlers.

You can parse input events into structures using Buffer.readX procedures:

  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; } 
0
source

All Articles