How to read external USB keyboard (or any hid device) input in node?

Hi all,

I have a project where I’m trying to read values from an external (USB-connected) RFID-reader, but I can’t get this working. The reader is a simple hid device that sends a numeric value (the rfid tag) and ‘enter’ on scanning a tag.

I wasn’t able to find anything directly related to this in the forums, which is why I’m posting this.

I’m using balenalib/raspberrypi3-debian-node:8.17.0-jessie-build as the base image. I know it’s old, but hx711 library (which is also required in this project) won’t compile against node 10, so I’m stuck with this at the moment.

I’ve tried using ‘usb’ node library and managed to start polling the reader but I wasn’t able to do anything with the stream (not enough skills on my side…). Also, ‘node-hid’ failed to work with electron (electron-rebuild didn’t help).

At the moment I have a workaround where I’m using Electron (this is used for other purposes as well, not only for the USB device) to read the values (using ‘keydown’ eventlistener) and pass them back to the main process, but I’d like to get this working without Electron as well, as most of the business logic is handled outside Electron and some applications may not require Electron at all.

All hints/tips would be greatly appreciated.


Hi Aleksi, first step would be to verify if the RFID-reader is being correctly mounted into your container. In my experience RFID readers usually show up as /dev/ttyUSB*. Can you verify that your reader is being listed in /dev? You should see it both in your container and in the hostOS.

If it is listed in the hostOS but not on your container chances are that your container is missing configuration to detect dynamically plugged devices. You can read about it here though in a nutshell you need to add privileged: true to your container on your docker-compose.yml and ENV UDEV=on to your Dockerfile.

If its’ not listed in the hostOS /dev then it’s probably a hardware issue (or the OS is missing some drivers but it’s highly unlikely this is the case for an RFID reader, more-so if you can get it to work with electron).

Hi, I can see the device as /dev/hidraw0 in both the container and the hostOS.

My dockerfile has ENV UEDV=1 set. The project is a single container app (I’m using GitHub - balena-io-playground/balena-electronjs-react: electronJS-based resin application template as a starting point) and I’m not using a docker-compose.yml yet. Could this cause issues?

Fwiw, I’m currently working in local mode.

Ah okay, if you are running single container then by default it’s a privileged container so you don’t need to specify that.

If the device is showing up in your container as /dev/hidraw0 then you should be good to go. I suggest you try setting up node-hid on a fresh nodejs container (without electron if that’s something you won’t be needing) and try to run some of their examples to get acquainted with the library.

Thanks for the pointers. I got back to the drawing board, did some quick testing and it seems node-gyp was causing most of the issues.

I managed to get node-hid working and it is reading values as intended. I have not yet tested this in the actual code, but I ssh’d into the main process and ran the following with expected results (code snippet from I cannot read proper barcode data. · Issue #228 · node-hid/node-hid · GitHub )

var HID = require('node-hid');
var vid = 16962;
var pid = 57649;
var reader = new HID.HID(vid, pid)
console.log("device:", HID.devices() );

var nfcBuffs = ''
var buffsCount = 0
var keymap = {'04':'A','05':'B','06':'C','07':'D','08':'E','09':'F','0a':'G','0b':'H','0c':'I','0d':'J','0e':'K','0f':'L','10':'M','11':'N','12':'O','13':'P','14':'Q','15':'R','16':'S','17':'T','18':'U','19':'V','1a':'W','1b':'X','1c':'Y','1d':'Z','1e':'1','1f':'2','20':'3','21':'4','22':'5','23':'6','24':'7','25':'8','26':'9','27':'0','00':''}

reader.on("data", function(data) { 
  var nfcBuf = Buffer.from([data[1]]);
  if (nfcBuf.toString('hex') == '28') {
    nfcBuffs = [] // and reset counter/buffer
    buffsCount = 0
  } else if (nfcBuf.toString('hex') != '00') {
    nfcBuffs += keymap[nfcBuf.toString('hex')]

This prints out the rfid tag as expected. All in all, seems that the issue was between keyboard and chair :wink:

Hi, glad to see it working and thanks for letting us know.