rpi-io 1.2.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -246
- package/addon/gpio.c +875 -0
- package/binding.gyp +33 -0
- package/esm/_util.mjs +122 -0
- package/esm/main.mjs +307 -0
- package/history.md +7 -0
- package/package.json +54 -7
- package/script/check-env.sh +192 -0
- package/script/detect-gpiod-version.sh +21 -0
- package/test/benchmark-pwm.js +44 -0
- package/test/benchmark-read.js +37 -0
- package/test/benchmark-write.js +38 -0
- package/test/close-all.js +27 -0
- package/test/duplicate-error.js +29 -0
- package/test/line-configuration.js +16 -0
- package/test/pwm-led.js +36 -0
- package/test/pwm-motor.js +40 -0
- package/test/read.js +30 -0
- package/test/write.js +29 -0
- package/esm/dev.mjs +0 -59
- package/esm/rio.mjs +0 -647
- package/esm/utl.mjs +0 -100
- package/scr/test.js +0 -168
package/binding.gyp
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "gpio",
|
|
5
|
+
"sources": [ "addon/gpio.c" ],
|
|
6
|
+
"include_dirs": [
|
|
7
|
+
"<!@(node -p \"require('node-addon-api').include\")"
|
|
8
|
+
],
|
|
9
|
+
"libraries": [
|
|
10
|
+
"-lgpiod",
|
|
11
|
+
"-lpthread"
|
|
12
|
+
],
|
|
13
|
+
"cflags": [
|
|
14
|
+
"-Wall",
|
|
15
|
+
"-Wno-implicit-function-declaration",
|
|
16
|
+
"-Wno-incompatible-pointer-types",
|
|
17
|
+
"-O2",
|
|
18
|
+
"-std=gnu99"
|
|
19
|
+
],
|
|
20
|
+
"defines": [
|
|
21
|
+
"<!@(sh -c 'chmod +x script/detect-gpiod-version.sh 2>/dev/null; bash script/detect-gpiod-version.sh 2>/dev/null || echo LIBGPIOD_V2')"
|
|
22
|
+
],
|
|
23
|
+
"conditions": [
|
|
24
|
+
["OS=='linux'", {
|
|
25
|
+
"libraries": [
|
|
26
|
+
"-lgpiod",
|
|
27
|
+
"-lpthread"
|
|
28
|
+
]
|
|
29
|
+
}]
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
package/esm/_util.mjs
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// RPI-IO: Nodejs tools and utilities
|
|
3
|
+
// -------------------------------------------------------------------
|
|
4
|
+
import {execSync} from "child_process"
|
|
5
|
+
import {spawnSync} from "node:child_process"
|
|
6
|
+
|
|
7
|
+
// -------------------------------------------------------------------
|
|
8
|
+
// DEV UTILITIES
|
|
9
|
+
// -------------------------------------------------------------------
|
|
10
|
+
let debug = {
|
|
11
|
+
trace: false,
|
|
12
|
+
warn: true
|
|
13
|
+
}
|
|
14
|
+
/** ------------------------------------------------------------------
|
|
15
|
+
* @function traceCfg
|
|
16
|
+
* @description Set log configuration
|
|
17
|
+
* @param {Number} level 0: no log, 1: warn only, 2: warn and log
|
|
18
|
+
*/
|
|
19
|
+
export const traceCfg = level => {
|
|
20
|
+
debug = {
|
|
21
|
+
trace: false,
|
|
22
|
+
warn: false
|
|
23
|
+
}
|
|
24
|
+
level > 1 ? debug.trace = true : false
|
|
25
|
+
level > 0 ? debug.warn = true : false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** ------------------------------------------------------------------
|
|
29
|
+
* @function nowStr
|
|
30
|
+
* @description Return timestamp as formatted string
|
|
31
|
+
* @return {String}
|
|
32
|
+
*/
|
|
33
|
+
const nowStr = () => {
|
|
34
|
+
const date = new Date()
|
|
35
|
+
return date.toLocaleTimeString() + "." + date.getMilliseconds().toLocaleString('en', {
|
|
36
|
+
minimumIntegerDigits: 3,
|
|
37
|
+
minimumFractionDigits: 0,
|
|
38
|
+
useGrouping: false
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** ------------------------------------------------------------------
|
|
43
|
+
* @function log
|
|
44
|
+
* @description Global customized timestamped console.log
|
|
45
|
+
* Requires global variable 'debug'
|
|
46
|
+
*/
|
|
47
|
+
export const log = function () {
|
|
48
|
+
if (debug.trace)
|
|
49
|
+
console.log.apply(console, Array.prototype.concat.apply([nowStr(), "🔎 "], arguments))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** ------------------------------------------------------------------
|
|
53
|
+
* @function warn
|
|
54
|
+
* @description Colored log for error messages ⚠️ nodejs only ~ CSS color #F50
|
|
55
|
+
*/
|
|
56
|
+
export const warn = function () {
|
|
57
|
+
if (debug.warn)
|
|
58
|
+
console.log.apply(console, Array.prototype.concat.apply([nowStr(), "⚠️", "\x1b[38;2;255;80;0m", ...arguments, "\x1b[0m"]))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** ------------------------------------------------------------------
|
|
62
|
+
* @function sleep
|
|
63
|
+
* @description Wait before continuing
|
|
64
|
+
* @param {Number} ms
|
|
65
|
+
* @param {Boolean} track
|
|
66
|
+
*/
|
|
67
|
+
export const sleep = (ms, track = true) => {
|
|
68
|
+
track ? log("sleeping", ms, "ms") : false
|
|
69
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** ------------------------------------------------------------------
|
|
73
|
+
* @function wait
|
|
74
|
+
* @description Wait before continuing (sync blocking mode)
|
|
75
|
+
* @param {Number} ms
|
|
76
|
+
*/
|
|
77
|
+
export const wait = ms => {
|
|
78
|
+
log("waiting", ms, "ms")
|
|
79
|
+
spawnSync("sleep", [ms / 1000])
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** ------------------------------------------------------------------
|
|
83
|
+
* @function ctrlC
|
|
84
|
+
* @description Intercept ctrl+c then exec callback
|
|
85
|
+
* @param {Function} callback
|
|
86
|
+
*/
|
|
87
|
+
export const ctrlC = callback => {
|
|
88
|
+
process.on("SIGINT", () => {
|
|
89
|
+
log("ctrl+c pressed")
|
|
90
|
+
typeof callback === "function" ? callback() : false
|
|
91
|
+
process.exit(0)
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** ------------------------------------------------------------------
|
|
96
|
+
* @function lineConfig
|
|
97
|
+
* @description Return line configuration
|
|
98
|
+
* @param {Number} line
|
|
99
|
+
* @return {String}
|
|
100
|
+
*/
|
|
101
|
+
export const lineConfig = line => {
|
|
102
|
+
const stdout = execSync("pinctrl get " + line, {stdio: "pipe", encoding: "utf8"}).trim().split(/\s+/)
|
|
103
|
+
return stdout[stdout.length - 1].toLowerCase()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** ------------------------------------------------------------------
|
|
107
|
+
* @function lineNumber
|
|
108
|
+
* @param {Number} nth
|
|
109
|
+
* @return {Number}
|
|
110
|
+
*/
|
|
111
|
+
export const lineNumber = nth => {
|
|
112
|
+
const arg = parseInt(process.argv[nth])
|
|
113
|
+
if (typeof arg !== "number" || arg !== arg) {
|
|
114
|
+
warn("Line number expected as argument")
|
|
115
|
+
return -1
|
|
116
|
+
}
|
|
117
|
+
return arg
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// -------------------------------------------------------------------
|
|
121
|
+
// EoF
|
|
122
|
+
// -------------------------------------------------------------------
|
package/esm/main.mjs
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// RPI-IO: Nodejs GPIO control module
|
|
3
|
+
// -------------------------------------------------------------------
|
|
4
|
+
import {createRequire} from "node:module"
|
|
5
|
+
import {writeFileSync} from "node:fs"
|
|
6
|
+
import {traceCfg, log, warn, sleep, ctrlC, lineConfig, lineNumber, wait} from "./_util.mjs"
|
|
7
|
+
|
|
8
|
+
export {traceCfg, log, warn, sleep, ctrlC, lineConfig, lineNumber}
|
|
9
|
+
// -------------------------------------------------------------------
|
|
10
|
+
// CONSTANTS + VARIABLES
|
|
11
|
+
// -------------------------------------------------------------------
|
|
12
|
+
const require = createRequire(import.meta.url)
|
|
13
|
+
const ADDON = require("../build/Release/gpio.node")
|
|
14
|
+
const CHIPNAME = "/dev/gpiochip0"
|
|
15
|
+
const RPi_GPIO_STD = [4, 5, 6, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27]
|
|
16
|
+
const RPi_GPIO_PWM = [12, 13, 18, 19]
|
|
17
|
+
const RPI_GPIO_ALL = [...RPi_GPIO_STD, ...RPi_GPIO_PWM]
|
|
18
|
+
const RPI_CHIP = "gpiochip0"
|
|
19
|
+
const PWM_CHIP = "pwmchip0"
|
|
20
|
+
|
|
21
|
+
// -------------------------------------------------------------------
|
|
22
|
+
// CLASS RIO & METHODS
|
|
23
|
+
/** ------------------------------------------------------------------
|
|
24
|
+
* @class RIO
|
|
25
|
+
* @classDesc Generic class manage GPIO lines
|
|
26
|
+
* @return {String}
|
|
27
|
+
*/
|
|
28
|
+
export class RIO {
|
|
29
|
+
|
|
30
|
+
static instances = new Map()
|
|
31
|
+
|
|
32
|
+
/** ------------------------------------------------------------------
|
|
33
|
+
* @method constructor
|
|
34
|
+
* @param {Number} line - BCM number
|
|
35
|
+
* @param {String} mode - "input", "output", "pwm"
|
|
36
|
+
* @param {Object} opt - misc options depending on mode
|
|
37
|
+
*/
|
|
38
|
+
constructor(line, mode, opt) {
|
|
39
|
+
|
|
40
|
+
const defopt = {
|
|
41
|
+
// output
|
|
42
|
+
value: 0, // Initial value
|
|
43
|
+
// input, output
|
|
44
|
+
bias: "disable", // "disable", "pull-up", "pull-down"
|
|
45
|
+
// pwm
|
|
46
|
+
exportTime: 100,
|
|
47
|
+
period: 20000, // μs ~50Hz
|
|
48
|
+
dutyMin: 0, // μs
|
|
49
|
+
dutyMax: 20000 // µs
|
|
50
|
+
}
|
|
51
|
+
opt = {...defopt, ...opt}
|
|
52
|
+
|
|
53
|
+
if (RPI_GPIO_ALL.indexOf(line) === -1)
|
|
54
|
+
throw new Error("This line is not supported: " + line)
|
|
55
|
+
|
|
56
|
+
// line is already defined
|
|
57
|
+
if (RIO.instances.has(line))
|
|
58
|
+
throw new Error("This line is already defined: " + line)
|
|
59
|
+
|
|
60
|
+
this.line = line
|
|
61
|
+
this.handle = null
|
|
62
|
+
this.mode = mode
|
|
63
|
+
this.value = opt.value
|
|
64
|
+
this.bias = opt.bias
|
|
65
|
+
this.closed = false // Instance status
|
|
66
|
+
this.monitoring = false // Monitoring status
|
|
67
|
+
this.config = lineConfig(this.line) // Required for pwm
|
|
68
|
+
this.pwmExported = false
|
|
69
|
+
this.pwmEnabled = false
|
|
70
|
+
|
|
71
|
+
switch (this.mode) {
|
|
72
|
+
case "output":
|
|
73
|
+
this.handle = ADDON.openOutput(CHIPNAME, line, this.value, opt.bias)
|
|
74
|
+
break
|
|
75
|
+
case "input":
|
|
76
|
+
this.handle = ADDON.openInput(CHIPNAME, line, opt.bias)
|
|
77
|
+
break
|
|
78
|
+
case "pwm":
|
|
79
|
+
if (RPi_GPIO_PWM.indexOf(line) === -1)
|
|
80
|
+
throw new Error("This line is not supported for PWM: " + line)
|
|
81
|
+
|
|
82
|
+
if (this.config.indexOf("pwm") === -1)
|
|
83
|
+
throw new Error("This line is not setup as PWM (see README)")
|
|
84
|
+
|
|
85
|
+
if (opt.period < 0.1 || opt.period > 1000000)
|
|
86
|
+
throw new Error("PWM period is out of range (100ns - 1s)")
|
|
87
|
+
|
|
88
|
+
// Normalize PWM values in ns
|
|
89
|
+
this.period = opt.period * 1000
|
|
90
|
+
this.dutyMin = Math.max(0, opt.dutyMin * 1000)
|
|
91
|
+
this.dutyMax = Math.min(this.period, opt.dutyMax * 1000)
|
|
92
|
+
|
|
93
|
+
// PWM channel: 0 or 1
|
|
94
|
+
this.pwmChannel = this.config.slice(-1)
|
|
95
|
+
this.pwmPath = "/sys/class/pwm/" + PWM_CHIP + "/"
|
|
96
|
+
this.pwmPathChannel = this.pwmPath + "pwm" + this.pwmChannel + "/"
|
|
97
|
+
|
|
98
|
+
log("pwm channel", this.pwmChannel, "normalized data (period, duty min, duty max):", this.period, this.dutyMin, this.dutyMax)
|
|
99
|
+
|
|
100
|
+
// Export channel
|
|
101
|
+
writeFileSync(this.pwmPath + "export", this.pwmChannel)
|
|
102
|
+
this.pwmExported = true
|
|
103
|
+
wait(opt.exportTime) // Customization required for RPi Zero
|
|
104
|
+
|
|
105
|
+
// Set period, reset duty and enable
|
|
106
|
+
try {
|
|
107
|
+
writeFileSync(this.pwmPathChannel + "period", String(this.period))
|
|
108
|
+
writeFileSync(this.pwmPathChannel + "duty_cycle", String(this.dutyMin))
|
|
109
|
+
writeFileSync(this.pwmPathChannel + "enable", "1")
|
|
110
|
+
this.pwmEnabled = true
|
|
111
|
+
|
|
112
|
+
} catch (err) {
|
|
113
|
+
warn("pwm start error:", err)
|
|
114
|
+
warn("consider increasing option exportTime for this device ")
|
|
115
|
+
this.pwmStop()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
break
|
|
119
|
+
default:
|
|
120
|
+
throw new Error("undefined mode")
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Everything OK => Add this to instance list
|
|
124
|
+
RIO.instances.set(line, this)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** ------------------------------------------------------------------
|
|
128
|
+
* @method close
|
|
129
|
+
* @description To close line and free resources
|
|
130
|
+
*/
|
|
131
|
+
close() {
|
|
132
|
+
if (this.closed) {
|
|
133
|
+
warn("this instance is already closed")
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
// Stop monitoring if active
|
|
139
|
+
if (this.monitoring)
|
|
140
|
+
this.monitoringStop()
|
|
141
|
+
|
|
142
|
+
// Free C resources and reset handle
|
|
143
|
+
if (this.handle) {
|
|
144
|
+
ADDON.close(this.handle)
|
|
145
|
+
this.handle = null
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Stop PWM if required
|
|
149
|
+
if (this.mode === "pwm")
|
|
150
|
+
this.pwmStop()
|
|
151
|
+
|
|
152
|
+
// Delete from instance list et reset flag
|
|
153
|
+
RIO.instances.delete(this.line)
|
|
154
|
+
this.closed = true
|
|
155
|
+
log("line", this.line, "is closed")
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** ------------------------------------------------------------------
|
|
159
|
+
* @method write
|
|
160
|
+
* @description Write value to GPIO line
|
|
161
|
+
* @param {Number} value
|
|
162
|
+
*/
|
|
163
|
+
write(value) {
|
|
164
|
+
|
|
165
|
+
if (this.closed)
|
|
166
|
+
throw new Error("GPIO handle has been closed")
|
|
167
|
+
|
|
168
|
+
if (this.mode !== "output")
|
|
169
|
+
throw new Error("Cannot write to this GPIO mode:", this.mode)
|
|
170
|
+
|
|
171
|
+
if ([0, 1].indexOf(value) === -1)
|
|
172
|
+
throw new Error("Value must be either 0 or 1")
|
|
173
|
+
|
|
174
|
+
ADDON.write(this.handle, value)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** ------------------------------------------------------------------
|
|
178
|
+
* @method read
|
|
179
|
+
* @description Read value from GPIO line
|
|
180
|
+
* @return {Number} 0,1
|
|
181
|
+
*/
|
|
182
|
+
read() {
|
|
183
|
+
if (this.closed)
|
|
184
|
+
throw new Error("GPIO handle has been closed")
|
|
185
|
+
|
|
186
|
+
if (this.mode !== "input")
|
|
187
|
+
throw new Error("Cannot read from this GPIO mode:", this.mode)
|
|
188
|
+
|
|
189
|
+
return ADDON.read(this.handle)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** ------------------------------------------------------------------
|
|
193
|
+
* @method monitoringStart
|
|
194
|
+
* @description Monitor input GPIO line events (rising/falling)
|
|
195
|
+
* @param {Function} callback 0,1
|
|
196
|
+
* @param {String} edge
|
|
197
|
+
* @param {Number} bounce
|
|
198
|
+
*/
|
|
199
|
+
monitoringStart(callback, edge = "both", bounce = 0) {
|
|
200
|
+
if (this.closed)
|
|
201
|
+
throw new Error("GPIO handle has been closed")
|
|
202
|
+
|
|
203
|
+
if (this.mode !== "input")
|
|
204
|
+
throw new Error("Cannot read from this GPIO mode:", this.mode)
|
|
205
|
+
|
|
206
|
+
if (this.monitoring)
|
|
207
|
+
throw new Error("Monitoring already started")
|
|
208
|
+
|
|
209
|
+
bounce < 0 ? bounce = 0 : false
|
|
210
|
+
bounce > 1000 ? bounce = 1000 : false
|
|
211
|
+
this.latestEvent = {
|
|
212
|
+
time: new Date(null),
|
|
213
|
+
edge: "none"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
ADDON.startMonitoring(this.handle, value => {
|
|
217
|
+
const evt = value === 1 ? "rising" : "falling"
|
|
218
|
+
const now = new Date()
|
|
219
|
+
const delta = Math.max(1, now - this.latestEvent.time) // delta is always > 0ms
|
|
220
|
+
|
|
221
|
+
// Bounce detected
|
|
222
|
+
if (delta <= bounce && evt === this.latestEvent.edge) {
|
|
223
|
+
log("bounce detected on gpio", this.line, evt, delta + "ms")
|
|
224
|
+
}
|
|
225
|
+
// Callback of required events
|
|
226
|
+
else {
|
|
227
|
+
if (typeof callback === "function" && (edge === "both" || edge === evt)) {
|
|
228
|
+
callback(evt)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Update latest event
|
|
232
|
+
this.latestEvent = {
|
|
233
|
+
time: now,
|
|
234
|
+
edge: evt
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
this.monitoring = true
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** ------------------------------------------------------------------
|
|
241
|
+
* @method monitoringStop
|
|
242
|
+
* @description Stop event monitoring
|
|
243
|
+
*/
|
|
244
|
+
monitoringStop() {
|
|
245
|
+
if (this.closed)
|
|
246
|
+
return
|
|
247
|
+
|
|
248
|
+
if (this.monitoring) {
|
|
249
|
+
ADDON.stopMonitoring(this.handle)
|
|
250
|
+
this.monitoring = false
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** --------------------------------------------------------------
|
|
255
|
+
* @method pwmStop
|
|
256
|
+
* @description Stop PWM modulation
|
|
257
|
+
*/
|
|
258
|
+
pwmStop() {
|
|
259
|
+
|
|
260
|
+
if (this.mode !== "pwm")
|
|
261
|
+
throw new Error("This line is not configured as PWM")
|
|
262
|
+
|
|
263
|
+
if (this.pwmEnabled) {
|
|
264
|
+
writeFileSync(this.pwmPathChannel + "enable", "0")
|
|
265
|
+
this.pwmEnabled = false
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (this.pwmExported) {
|
|
269
|
+
writeFileSync(this.pwmPath + "unexport", this.pwmChannel)
|
|
270
|
+
this.pwmExported = false
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** --------------------------------------------------------------
|
|
275
|
+
* @method pwmDuty
|
|
276
|
+
* @description Change PWM duty cycle
|
|
277
|
+
* @param {Number} percent 0 <= percent <= 100
|
|
278
|
+
*/
|
|
279
|
+
pwmDuty(percent) {
|
|
280
|
+
|
|
281
|
+
if (this.mode !== "pwm")
|
|
282
|
+
throw new Error("This line is not configured as PWM")
|
|
283
|
+
|
|
284
|
+
if (!this.pwmEnabled || !this.pwmExported)
|
|
285
|
+
throw new Error("Duty of PWM line " + this.line + " cannot be updated")
|
|
286
|
+
|
|
287
|
+
if (percent < 0 || percent > 100 || typeof percent !== "number") {
|
|
288
|
+
throw new Error("Duty value (%) of PWM line" + this.line + " is not valid")
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
writeFileSync(this.pwmPathChannel + "duty_cycle", (this.dutyMin + ((percent / 100) * (this.dutyMax - this.dutyMin))).toString())
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** ------------------------------------------------------------------
|
|
295
|
+
* @method RIO.closeAll
|
|
296
|
+
* @description Static method to close all instances
|
|
297
|
+
*/
|
|
298
|
+
static closeAll() {
|
|
299
|
+
for (const [line, instance] of RIO.instances) {
|
|
300
|
+
instance.close()
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// -------------------------------------------------------------------
|
|
306
|
+
// EoF
|
|
307
|
+
// -------------------------------------------------------------------
|
package/history.md
CHANGED
package/package.json
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rpi-io",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Nodejs module to control Raspberry Pi GPIO",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"raspberry",
|
|
7
|
+
"raspberry-pi",
|
|
7
8
|
"gpio",
|
|
8
9
|
"libgpiod",
|
|
9
10
|
"nodejs",
|
|
10
11
|
"esm",
|
|
12
|
+
"napi",
|
|
11
13
|
"output",
|
|
12
14
|
"input",
|
|
13
15
|
"monitor",
|
|
14
16
|
"pwm",
|
|
17
|
+
"linux",
|
|
15
18
|
"bookworm",
|
|
16
|
-
"trixie"
|
|
19
|
+
"trixie",
|
|
20
|
+
"iot",
|
|
21
|
+
"embedded"
|
|
17
22
|
],
|
|
18
23
|
"homepage": "https://github.com/gdorbes/rpi-io#readme",
|
|
19
24
|
"bugs": {
|
|
@@ -25,14 +30,56 @@
|
|
|
25
30
|
},
|
|
26
31
|
"license": "MIT",
|
|
27
32
|
"author": "Guillaume DORBES",
|
|
28
|
-
"type": "module",
|
|
29
33
|
"engines": {
|
|
30
34
|
"npm": ">=10.0.0",
|
|
31
35
|
"node": ">=23.0.0"
|
|
32
36
|
},
|
|
33
|
-
"main": "
|
|
34
|
-
"exports": "./esm/
|
|
37
|
+
"main": "esm/main.mjs",
|
|
38
|
+
"exports": "./esm/main.mjs",
|
|
39
|
+
"type": "module",
|
|
35
40
|
"scripts": {
|
|
36
|
-
"
|
|
41
|
+
"preinstall": "chmod +x script/*.sh 2>/dev/null || true",
|
|
42
|
+
"install": "node-gyp rebuild",
|
|
43
|
+
"postinstall": "echo 'Installation complete!'",
|
|
44
|
+
"clean": "node-gyp clean",
|
|
45
|
+
"configure": "node-gyp configure",
|
|
46
|
+
"//---- Shell scripts ----": "To check environment and libgpiod version",
|
|
47
|
+
"check": "bash script/check-env.sh",
|
|
48
|
+
"detect-version": "bash script/detect-gpiod-version.sh",
|
|
49
|
+
"//---- Javascript scripts ----": "Misc examples and tests",
|
|
50
|
+
"line-write": "node ./test/write.js",
|
|
51
|
+
"line-read": "node ./test/read.js",
|
|
52
|
+
"line-pwm-led": "node ./test/pwm-led.js",
|
|
53
|
+
"line-pwm-motor": "node ./test/pwm-motor.js",
|
|
54
|
+
"benchmark-write": "node ./test/benchmark-write.js",
|
|
55
|
+
"benchmark-read": "node ./test/benchmark-read.js",
|
|
56
|
+
"benchmark-pwm": "node ./test/benchmark-pwm.js",
|
|
57
|
+
"test-close": "node ./test/close-all.js",
|
|
58
|
+
"test-instance": "node ./test/duplicate-error.js",
|
|
59
|
+
"test-line": "node ./test/line-configuration.js"
|
|
60
|
+
},
|
|
61
|
+
"os": [
|
|
62
|
+
"linux"
|
|
63
|
+
],
|
|
64
|
+
"cpu": [
|
|
65
|
+
"arm",
|
|
66
|
+
"arm64"
|
|
67
|
+
],
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"node-addon-api": "^7.0.0"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"node-gyp": "^10.0.0"
|
|
73
|
+
},
|
|
74
|
+
"gypfile": true,
|
|
75
|
+
"binary": {
|
|
76
|
+
"napi_versions": [
|
|
77
|
+
3,
|
|
78
|
+
4,
|
|
79
|
+
5,
|
|
80
|
+
6,
|
|
81
|
+
7,
|
|
82
|
+
8
|
|
83
|
+
]
|
|
37
84
|
}
|
|
38
|
-
}
|
|
85
|
+
}
|