Gathering detailed insights and metrics for onoff-rts
Gathering detailed insights and metrics for onoff-rts
Gathering detailed insights and metrics for onoff-rts
Gathering detailed insights and metrics for onoff-rts
npm install onoff-rts
60.5
Supply Chain
98.3
Quality
75.4
Maintenance
100
Vulnerability
99.6
License
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
1,240 Stars
378 Commits
124 Forks
40 Watching
1 Branches
13 Contributors
Updated on 27 Nov 2024
JavaScript (97.45%)
TypeScript (1.51%)
Shell (1.04%)
Cumulative downloads
Total Downloads
Last day
0%
1
Compared to previous day
Last week
50%
6
Compared to previous week
Last month
9.1%
24
Compared to previous month
Last year
0%
116
Compared to previous year
2
GPIO access and interrupt detection with Node.js on Linux boards like the Raspberry Pi or BeagleBone.
onoff supports Node.js versions 10, 12, 14, 15 and 16.
npm install onoff
Note that although it's possible to install onoff on non-Linux systems the functionality offered by onoff is only available on Linux systems.
Assume that there's an LED connected to GPIO17 and a momentary push button connected to GPIO4.
When the button is pressed the LED should turn on, when it's released the LED should turn off. This can be achieved with the following code:
1const Gpio = require('onoff').Gpio; 2const led = new Gpio(17, 'out'); 3const button = new Gpio(4, 'in', 'both'); 4 5button.watch((err, value) => led.writeSync(value));
Here two Gpio objects are being created. One called led for the LED connected to GPIO17 which is an output, and one called button for the momentary push button connected to GPIO4 which is an input. In addition to specifying that the button is an input, the constructors optional third argument is used to specify that 'both' rising and falling interrupt edges should be configured for the button GPIO as both button presses and releases should be handled.
After everything has been setup correctly, the buttons watch method is used to specify a callback function to execute every time the button is pressed or released. The value argument passed to the callback function represents the state of the button which will be 1 for pressed and 0 for released. This value is used by the callback to turn the LED on or off using its writeSync method.
When the above program is running it can be terminated with ctrl-c. However, it doesn't free its resources. It also ignores the err argument passed to the callback. Here's a slightly modified variant of the program that handles ctrl-c gracefully and bails out on error. The resources used by the led and button Gpio objects are released by invoking their unexport method.
1const Gpio = require('onoff').Gpio; 2const led = new Gpio(17, 'out'); 3const button = new Gpio(4, 'in', 'both'); 4 5button.watch((err, value) => { 6 if (err) { 7 throw err; 8 } 9 10 led.writeSync(value); 11}); 12 13process.on('SIGINT', _ => { 14 led.unexport(); 15 button.unexport(); 16});
When working with buttons there will often be button bounce issues which result in the hardware thinking that a button was pressed several times although it was only pressed once. onoff provides a software debouncing solution for resolving bounce issues.
Assume again that there's an LED connected to GPIO17 and a momentary push button connected to GPIO4.
When the button is pressed the LED should toggle its state. This is a typical example of a situation where there will be button bounce issues. The issue can be resolved by using the debounceTimeout option when creating the Gpio object for the button. In the below program the debounceTimeout is set to 10 milliseconds. This delays invoking the watch callback for the button while the button is bouncing. The watch callback will not be invoked until the button stops bouncing and has been in a stable state for 10 milliseconds.
1const Gpio = require('onoff').Gpio; 2const led = new Gpio(17, 'out'); 3const button = new Gpio(4, 'in', 'rising', {debounceTimeout: 10}); 4 5button.watch((err, value) => { 6 if (err) { 7 throw err; 8 } 9 10 led.writeSync(led.readSync() ^ 1); 11}); 12 13process.on('SIGINT', _ => { 14 led.unexport(); 15 button.unexport(); 16});
Blink an LED connected to GPIO17 for 5 seconds using the synchronous readSync and writeSync methods.
1const Gpio = require('../onoff').Gpio; // Gpio class
2const led = new Gpio(17, 'out'); // Export GPIO17 as an output
3
4// Toggle the state of the LED connected to GPIO17 every 200ms
5const iv = setInterval(_ => led.writeSync(led.readSync() ^ 1), 200);
6
7// Stop blinking the LED after 5 seconds
8setTimeout(_ => {
9 clearInterval(iv); // Stop blinking
10 led.unexport(); // Unexport GPIO and free resources
11}, 5000);
Blink an LED connected to GPIO17 for 5 seconds using the asynchronous read and write methods and completion callbacks.
1const Gpio = require('../onoff').Gpio; // Gpio class 2const led = new Gpio(17, 'out'); // Export GPIO17 as an output 3let stopBlinking = false; 4 5// Toggle the state of the LED connected to GPIO17 every 200ms 6const blinkLed = _ => { 7 if (stopBlinking) { 8 return led.unexport(); 9 } 10 11 led.read((err, value) => { // Asynchronous read 12 if (err) { 13 throw err; 14 } 15 16 led.write(value ^ 1, err => { // Asynchronous write 17 if (err) { 18 throw err; 19 } 20 }); 21 }); 22 23 setTimeout(blinkLed, 200); 24}; 25 26blinkLed(); 27 28// Stop blinking the LED after 5 seconds 29setTimeout(_ => stopBlinking = true, 5000);
Blink an LED connected to GPIO17 for 5 seconds using the asynchronous read and write methods and Promises.
1const Gpio = require('../onoff').Gpio; // Gpio class 2const led = new Gpio(17, 'out'); // Export GPIO17 as an output 3let stopBlinking = false; 4 5// Toggle the state of the LED connected to GPIO17 every 200ms 6const blinkLed = _ => { 7 if (stopBlinking) { 8 return led.unexport(); 9 } 10 11 led.read() 12 .then(value => led.write(value ^ 1)) 13 .then(_ => setTimeout(blinkLed, 200)) 14 .catch(err => console.log(err)); 15}; 16 17blinkLed(); 18 19// Stop blinking the LED after 5 seconds 20setTimeout(_ => stopBlinking = true, 5000);
Sometimes it may be necessary to determine if the current system supports
GPIOs programmatically and mock functionality if it doesn't. Gpio.accessible
can be used to achieve this.
1const Gpio = require('onoff').Gpio; 2 3const useLed = (led, value) => led.writeSync(value); 4 5let led; 6 7if (Gpio.accessible) { 8 led = new Gpio(17, 'out'); 9 // more real code here 10} else { 11 led = { 12 writeSync: value => { 13 console.log('virtual led now uses value: ' + value); 14 } 15 }; 16} 17 18useLed(led, 1);
Configures the GPIO based on the passed arguments and returns a new Gpio object that can be used to access the GPIO.
The following options are supported:
GPIOs on Linux are identified by unsigned integers. These are the numbers that should be passed to the onoff Gpio constructor when exporting GPIOs to userspace. For example, pin 11 on the Raspberry Pi expansion header corresponds to GPIO17 in Raspbian Linux. 17 is therefore the number to pass to the onoff Gpio constructor when using pin 11 on the expansion header.
Read GPIO value asynchronously. If no completion callback is specified read returns a Promise which resolves to the value of the GPIO on success or rejects with an Error object on failure.
Note that most systems support readback of GPIOs configured as outputs. The read method can therefore be invoked for any GPIO, irrespective of whether it was configured as an input or an output. The Raspberry Pi and BeagleBone are examples of such systems.
Read GPIO value synchronously. Returns the number 0 or 1 to represent the state of the GPIO.
Note that most systems support readback of GPIOs configured as outputs. The readSync method can therefore be invoked for any GPIO, irrespective of whether it was configured as an input or an output. The Raspberry Pi and BeagleBone are examples of such systems.
Write GPIO value asynchronously. If no completion callback is specified write returns a Promise that resolves with no value on success or rejects with an Error object on failure.
Note that on most systems invoking write for a GPIO configured as an input will result in an EPERM error indicating that the operation is not permitted. The Raspberry Pi and BeagleBone are examples of such systems.
Write GPIO value synchronously.
Note that on most systems invoking writeSync for a GPIO configured as an input will result in an EPERM error indicating that the operation is not permitted. The Raspberry Pi and BeagleBone are examples of such systems.
Watch for hardware interrupts on the GPIO. The edge argument that was passed to the constructor determines which hardware interrupts to watch for.
Stop watching for hardware interrupts on the GPIO. If callback is specified, only that particular callback is removed. Otherwise all callbacks are removed.
Remove all hardware interrupt watchers for the GPIO.
Returns the string 'in' or 'out' indicating whether the GPIO is an input or output.
Set GPIO direction.
Returns the string 'none', 'falling', 'rising', or 'both' indicating the interrupt generating edge or edges for the GPIO. Whether or not interrupts are supported by an input GPIO is GPIO specific. If interrupts are not supported the edge method should not be used. Interrupts are not supported by output GPIOs.
Set GPIO interrupt generating edge.
Returns true or false indicating whether or not the values read from or written to the GPIO are inverted.
Set GPIO activeLow setting.
Reverse the effect of exporting the GPIO to userspace. A Gpio object should not be used after invoking its unexport method.
Determine whether or not GPIO access is possible. true if the current process has the permissions required to export GPIOs to userspace. false otherwise. Loosely speaking, if this property is true it should be possible for the current process to create Gpio objects.
It is notable that while this property may be false indicating that the current process does not have the permissions required to export GPIOs to userspace, existing exported GPIOs may still be accessible.
This property is useful for mocking functionality on computers used for development that do not provide access to GPIOs.
This is a static property and should be accessed as Gpio.accessible
.
Constants used when reading or writing a GPIO value. Gpio.HIGH and Gpio.LOW can be used in place of the numeric constants 1 and 0.
Internally onoff uses sysfs files located at /sys/class/gpio to access GPIOs and the epoll package to detect hardware interrupts. The Linux GPIO sysfs interface for userspace is documented here. It's a relatively simple interface which can be used to ask the Linux kernel to export control of a GPIO to userspace. After control of a GPIO has been exported to userspace, the GPIO can be configured as an input or output. Thereafter, the state of an input can be read, and the state of an output can be written. Some systems will also allow the state of a output to be read. The GPIO sysfs interface can also be used for interrupt detection. onoff can detect several thousand interrupts per second on both the BeagleBone and the Raspberry Pi.
As mentioned in section How Does onoff Work the sysfs interface is used to access GPIOs. The sysfs interface doesn't offer support for configuring pullup and pulldown resistors on GPIOs.
There are however many platform specific mechanisms for configuring pullup and pulldown resistors that are compatible with onoff. onoff itself doesn't use these mechanisms as one of the goals of onoff is to be platform independent.
Here we'll take a look at two mechanisms available on the Raspberry Pi for configuring pullup and pulldown resistors.
The first point to be aware of is that most GPIOs on a Raspberry Pi have either their pullup or pulldown resistor activated by default. The defaults can be seen in Table 6-31 on pages 102 and 103 of the BCM2835 ARM Peripherals documentation.
On Raspbian 2018-04-18 or later the gpio
configuration command can be used
in /boot/config.txt
to configure pullup and pulldown resistors. Further
information is available at
New "gpio" config command.
Device tree overlays can also be used to configure pullup and pulldown resistors. The Wiki page Enabling Pullup and Pulldown Resistors on The Raspberry Pi describes this mechanism in more detail.
Three of the onoff tests are used to monitor performance.
The results of these tests are shown in the following tables.
Raspberry Pi 4 B, 1.5GHz, Raspberry Pi OS (March 4th 2021, Buster 10.8)
node | onoff | kernel | write / sec | writeSync / sec | interrupts / sec |
---|---|---|---|---|---|
v16.0.0 | v6.0.3 | 5.10.17-v7l+ | 25124 | 280417 | 20240 |
v15.14.0 | v6.0.3 | 5.10.17-v7l+ | 24055 | 271149 | 20488 |
v14.16.1 | v6.0.3 | 5.10.17-v7l+ | 21669 | 254705 | 19703 |
v12.22.1 | v6.0.3 | 5.10.17-v7l+ | 22618 | 318417 | 21122 |
v10.24.1 | v6.0.3 | 5.10.17-v7l+ | 22405 | 329927 | 19583 |
Raspberry Pi 3 B, 1.2GHz, Raspbian Buster 10.1
node | onoff | kernel | write / sec | writeSync / sec | interrupts / sec |
---|---|---|---|---|---|
v12.14.0 | v5.0.0 | 4.19.75-v7l+ | 21670 | 207222 | 18328 |
v10.18.0 | v5.0.0 | 4.19.75-v7l+ | 23661 | 225758 | 20741 |
Raspberry Pi 2 B, 900MHz, Raspbian Buster 10.1
node | onoff | kernel | write / sec | writeSync / sec | interrupts / sec |
---|---|---|---|---|---|
v12.14.0 | v5.0.0 | 4.19.75-v7l+ | 10769 | 113107 | 10373 |
v10.18.0 | v5.0.0 | 4.19.75-v7l+ | 11843 | 129086 | 10536 |
Raspberry Pi 1 B, 700MHz, Raspbian Buster 10.1
node | onoff | kernel | write / sec | writeSync / sec | interrupts / sec |
---|---|---|---|---|---|
v12.14.0 | v5.0.0 | 4.19.75+ | 2316 | 26696 | 2112 |
v10.18.0 | v5.0.0 | 4.19.75+ | 2613 | 33129 | 2225 |
BeagleBone Black, 1GHz, Debian Buster 10.2
node | onoff | kernel | write / sec | writeSync / sec | interrupts / sec |
---|---|---|---|---|---|
v12.14.0 | v5.0.0 | 4.19.79-ti-r30 | 6855 | 70535 | 5911 |
v10.18.0 | v5.0.0 | 4.19.79-ti-r30 | 7564 | 79133 | 5920 |
BeagleBone, 720MHz, Debian Buster 10.2
node | onoff | kernel | write / sec | writeSync / sec | interrupts / sec |
---|---|---|---|---|---|
v12.14.0 | v5.0.0 | 4.19.79-ti-r30 | 5013 | 49741 | 4297 |
v10.18.0 | v5.0.0 | 4.19.79-ti-r30 | 5400 | 57157 | 4371 |
Here are a few links to other hardware specific Node.js packages that may be of interest.
onoff was tested on the following platforms:
The suitability of onoff for a particular Linux board is highly dependent on how GPIO interfaces are made available on that board. The GPIO interfaces documentation describes GPIO access conventions rather than standards that must be followed so GPIO can vary from platform to platform. For example, onoff relies on sysfs files located at /sys/class/gpio being available. However, these sysfs files for userspace GPIO are optional and may not be available on a particular platform.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
Found 1/24 approved changesets -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More