- Platform Support
- Installation
- Examples
- Usage
- Complete API
- devices = HID.devices()
- HID.setDriverType(type)
- device = new HID.HID(path)
- device = new HID.HID(vid,pid)
- device.on('data', function(data) {} )
- device.on('error, function(error) {} )
- device.write(data)
- device.close()
- device.pause()
- device.resume()
- device.read(callback)
- device.readSync()
- device.readTimeout(time_out)
- device.sendFeatureReport(data)
- device.getFeatureReport(report_id, report_length)
- Windows notes
- Linux notes
- Compiling from source
- Using node-hid in Electron projects
- Using node-hid in NW.js projects
- Support
node-hid
supports Node.js v6 and upwards. For versions before that,
you will need to build from source. The platforms, architectures and node versions node-hid
supports are the following.
In general we try to provide pre-built native library binaries for the most common platforms, Node and Electron versions.
We strive to make node-hid
cross-platform so there's a good chance any
combination not listed here will compile and work.
- Windows x86 (32-bit) (Âą)
- Windows x64 (64-bit)
- Mac OSX 10.9+
- Linux x64 (²)
- Linux x86 (Âą)
- Linux ARM / Raspberry Pi (Âą)
- Linux MIPSel (Âą)
- Linux PPC64 (Âą)
¹ prebuilt-binaries not provided for these platforms ² prebuilt binary built on Ubuntu 16.04 x64
- Node v6 to
- Node v12
- Electron v1 to (Âł)
- Electron v5
Âł Electron v1.8 currently has issues, but prebuilt binaries are provided.
For most "standard" use cases (node v4.x on mac, linux, windows on a x86 or x64 processor), node-hid
will install nice and easy with a standard:
npm install node-hid
If you install globally, the test program src/show-devices.js
is installed as hid-showdevices
. On Linux you can use it to try the difference between hidraw
and libusb
driverTypes:
$ npm install -g node-hid
$ hid-showdevices libusb
$ hid-showdevices hidraw
We are using prebuild to compile and post binaries of the library for most common use cases (linux, mac, windows on standard processor platforms). If you are on a special case, node-hid
will work, but it will compile the binary when you install.
If node-hid
doesn't have a pre-built binary for your system
(e.g. Linux on Raspberry Pi),
node-gyp
is used to compile node-hid
locally. It will need the pre-requisites
listed in Compling from source below.
In the src/
directory, various JavaScript programs can be found
that talk to specific devices in some way. Some interesting ones:
show-devices.js
- display all HID devices in the systemtest-ps3-rumbleled.js
- Read PS3 joystick and control its LED & rumblerstest-powermate.js
- Read Griffin PowerMate knob and change its LEDtest-blink1.js
- Fade colors on blink(1) RGB LEDtest-bigredbutton.js
- Read Dreamcheeky Big Red Buttontest-teensyrawhid.js
- Read/write Teensy running RawHID "Basic" Arduino sketch
To try them out, run them like node src/showdevices.js
from within the node-hid directory.
var HID = require('node-hid');
var devices = HID.devices();
devices
will contain an array of objects, one for each HID device
available. Of particular interest are the vendorId
and
productId
, as they uniquely identify a device, and the
path
, which is needed to open a particular device.
Sample output:
HID.devices();
{ vendorId: 10168,
productId: 493,
path: 'IOService:/AppleACPIPl...HIDDevice@14210000,0',
serialNumber: '20002E8C',
manufacturer: 'ThingM',
product: 'blink(1) mk2',
release: 2,
interface: -1,
usagePage: 65280,
usage: 1 },
{ vendorId: 1452,
productId: 610,
path: 'IOService:/AppleACPIPl...Keyboard@14400000,0',
serialNumber: '',
manufacturer: 'Apple Inc.',
product: 'Apple Internal Keyboard / Trackpad',
release: 549,
interface: -1,
usagePage: 1,
usage: 6 },
<and more>
Both HID.devices()
and new HID.HID()
are relatively costly, each causing a USB (and potentially Bluetooth) enumeration. This takes time and OS resources. Doing either can slow down the read/write that you do in parallel with a device, and cause other USB devices to slow down too. This is how USB works.
If you are polling HID.devices()
or doing repeated new HID.HID(vid,pid)
to detect device plug / unplug, consider instead using node-usb-detection. node-usb-detection
uses OS-specific, non-bus enumeration ways to detect device plug / unplug.
Before a device can be read from or written to, it must be opened.
The path
can be determined by a prior HID.devices() call.
Use either the path
from the list returned by a prior call to HID.devices()
:
var device = new HID.HID(path);
or open the first device matching a VID/PID pair:
var device = new HID.HID(vid,pid);
The device
variable will contain a handle to the device.
If an error occurs opening the device, an exception will be thrown.
A node-hid
device is an EventEmitter
.
While it shares some method names and usage patterns with
Readable
and Writable
streams, it is not a stream and the semantics vary.
For example, device.write
does not take encoding or callback args and
device.pause
does not do the same thing as readable.pause
.
There is also no pipe
method.
If you need to filter down the HID.devices()
list, you can use
standard Javascript array techniques:
var devices = HID.devices();
var deviceInfo = devices.find( function(d) {
var isTeensy = d.vendorId===0x16C0 && d.productId===0x0486;
return isTeensy && d.usagePage===0xFFAB && d.usage===0x200;
});
if( deviceInfo ) {
var device = new HID.HID( deviceInfo.path );
// ... use device
}
To receive FEATURE reports, use device.getFeatureReport()
.
To receive INPUT reports, use device.on("data",...)
.
A node-hid
device is an EventEmitter.
Reading from a device is performed by registering a "data" event handler:
device.on("data", function(data) {});
You can also listen for errors like this:
device.on("error", function(err) {});
For FEATURE reports:
var buf = device.getFeatureReport(reportId, reportLength)
Notes:
- Reads via
device.on("data")
are asynchronous - Reads via
device.getFeatureReport()
are synchronous - To remove an event handler, close the device with
device.close()
- When there is not yet a data handler or no data handler exists, data is not read at all -- there is no buffer.
To send FEATURE reports, use device.sendFeatureReport()
.
To send OUTPUT reports, use device.write()
.
All writing is synchronous.
device.write([0x00, 0x01, 0x01, 0x05, 0xff, 0xff]);
device.sendFeatureReport( [0x01, 'c', 0, 0xff,0x33,0x00, 70,0, 0] );
Notes:
- Both
device.write()
anddevice.sendFeatureReport()
return number of bytes written - Some devices use reportIds for OUTPUT reports. In that case,
the first byte of the array to
write()
should be the reportId. - BUG: Windows requires the prepend of an extra byte due to a bug in hidapi (see issue #187 and Windows notes below)
- Return array listing all connected HID devices
- Linux only
- Sets underlying HID driver type
type
can be"hidraw"
or"libusb"
, defaults to"hidraw"
- Open a HID device at the specified platform-specific path
- Open first HID device with specific VendorId and ProductId
data
- Buffer - the data read from the device
error
- The error Object emitted
data
- the data to be synchronously written to the device- Returns number of bytes actually written
- Closes the device. Subsequent reads will raise an error.
- Pauses reading and the emission of
data
events.
This means the underlying device is silenced until resumption -- it is not like pausing a stream, where data continues to accumulate.
-
This method will cause the HID device to resume emmitting
data
events. If no listeners are registered for thedata
event, data will be lost. -
When a
data
event is registered for this HID device, this method will be automatically called.
- Low-level function call to initiate an asynchronous read from the device.
callback
is of the formcallback(err, data)
- Return an array of numbers data. If an error occurs, an exception will be thrown.
time_out
- timeout in milliseconds- Return an array of numbers data. If an error occurs, an exception will be thrown.
data
- data of HID feature report, with 0th byte being report_id ([report_id,...]
)- Returns number of bytes actually written
report_id
- HID feature report id to getreport_length
- length of report
In general you cannot access USB HID keyboards or mice.
The OS owns these devices.
For reasons similar to mice & keyboards it appears you can't access this controller on Windows 10.
Because of a limitation in the underlying hidapi
library, if you are using hid_write()
you should prepend a byte to any data buffer, e.g.
var device = new HID.HID(vid,pid);
var buffer = Array(64).fill(0x33); // device has 64-byte report
if(os.platform === 'win32') {
buffer.unshift(0); // prepend throwaway byte
}
By default as of [email protected]
, the hidraw driver is used to talk to HID devices. Before [email protected]
, the more older but less capable libusb driver was used. With hidraw
Linux apps can now see usage
and usagePage
attributes of devices.
If you would still like to use the libusb
driver, then you can do either:
npm install [email protected]
or:
npm install node-hid --build-from-source --driver=libusb
Or during runtime, you can use HID.setDriverType('libusb')
immediately after require()-ing node-hid
:
var HID = require('node-hid');
HID.setDriverType('libusb');
Most Linux distros use udev
to manage access to physical devices,
and USB HID devices are normally owned by the root
user.
To allow non-root access, you must create a udev rule for the device,
based on the devices vendorId and productId.
This rule is a text file placed in /etc/udev/rules.d
.
For an example HID device (say a blink(1) light with vendorId = 0x27b8 and productId = 0x01ed,
the rules file to support both hidraw
and libusb
would look like:
SUBSYSTEM=="input", GROUP="input", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="27b8", ATTRS{idProduct}=="01ed", MODE:="666", GROUP="plugdev"
KERNEL=="hidraw*", ATTRS{idVendor}=="27b8", ATTRS{idProduct}=="01ed", MODE="0666", GROUP="plugdev"
Note that the values for idVendor and idProduct must be in hex and lower-case.
Save this file as /etc/udev/rules.d/51-blink1.rules
, unplug the HID device,
and reload the rules with:
sudo udevadm control --reload-rules
For a complete example, see the blink1 udev rules.
To compile & develop locally or if prebuild
cannot download a pre-built
binary for you, you will need the following tools:
-
All OSes:
node-gyp
installed globally:npm install -g node-gyp
-
Linux (kernel 2.6+) : install examples shown for Ubuntu
- Compilation tools:
apt install build-essential git
- gcc-4.8+:
apt install gcc-4.8 g++-4.8 && export CXX=g++-4.8
- libusb-1.0-0 w/headers:
sudo apt install libusb-1.0-0 libusb-1.0-0-dev
- libudev-dev: (Fedora only)
yum install libusbx-devel
- Compilation tools:
-
Mac OS X 10.8+
-
Windows XP, 7, 8, 10
- Visual C++ compiler and Python 2.7
- either:
npm install --global windows-build-tools
- add
%USERPROFILE%\.windows-build-tools\python27
toPATH
, like PowerShell:$env:Path += ";$env:USERPROFILE\.windows-build-tools\python27"
- or:
- either:
- Visual C++ compiler and Python 2.7
npm install node-hid --build-from-source
- check out a copy of this repo
- change into its directory
- update the submodules
- build the node package
For example:
git clone https://github.com/node-hid/node-hid.git
cd node-hid # must change into node-hid directory
npm run prepublish # get the needed hidapi submodule
npm install --build-from-source # rebuilds the module with C code
node ./src/show-devices.js
You will see some warnings from the C compiler as it compiles
hidapi (the underlying C library node-hid
uses).
This is expected.
For ease of development, there are also the scripts:
npm run gypclean # "node-gyp clean" clean gyp build directory
npm run gypconfigure # "node-gyp configure" configure makefiles
npm run gypbuild # "node-gyp build" build native code
In your electron project, add electron-rebuild
to your devDependencies
.
Then in your package.json scripts
add:
"postinstall": "electron-rebuild --force"
This will cause npm
to rebuild node-hid
for the version of Node that is in Electron.
If you get an error similar to The module "HID.node" was compiled against a differnt version of Node.js
then electron-rebuild
hasn't been run and Electron is trying to use node-hid
not built for it.
If you want a specific version of electron, do something like:
"postinstall": "electron-rebuild -v 0.36.5 --force -m . -w node-hid"
If using node-hid
with webpack
, you may find it useful to list node-hid
as an external in your webpack-config.js
:
externals: {
"node-hid": 'commonjs node-hid'
}
(You can see an example of this in Blink1Control2's webpack-config.js
(TBD)
Please use the node-hid github issues page for support questions and issues.