以下のようにすれば動くことが確認できた。
select や poll を明示的に呼び出すことができないが、edge を設定しさえすれば fs.watch でイベントを受けとれるようだ。
また、seek() もなぜか存在してないが read() の引数に position というのがあり、これが seek() 相当になるようだ。
const fs_ = require('fs');
const fs = fs_.promises;
fs.watch = fs_.watch;
async function watchInterrupt(pin, func) {
try {
await fs.writeFile(`/sys/class/gpio/export`, `${pin}`);
} catch (e) {
if (e.code === 'EBUSY') {
// ignore
} else {
throw e;
}
}
await fs.writeFile(`/sys/class/gpio/gpio${pin}/direction`, 'in');
await fs.writeFile(`/sys/class/gpio/gpio${pin}/edge`, 'both'); // falling raising both
const fh = await fs.open(`/sys/class/gpio/gpio${pin}/value`, 'r');
const buf = new Uint8Array(1);
fh.read(buf, 0, 1, 0);
const watcher = fs.watch(`/sys/class/gpio/gpio${pin}/value`, {}, (eventType, filename) => {
if (eventType === "change") {
fh.read(buf, 0, 1, 0);
const val = buf[0]-48;
func(val, pin);
} else {
// XXX
console.log(`unchecked event "${eventType}" occured with "${filename}"`);
}
});
return {
close: async () => {
watcher.close();
fh.close();
await fs.writeFile(`/sys/class/gpio/gpio${pin}/edge`, 'none');
}
};
}
(async () => {
watchInterrupt(0, (val, pin) => {
console.log(`gpio${pin} changed -> ${val}`);
});
watchInterrupt(2, (val, pin) => {
console.log(`gpio${pin} changed -> ${val}`);
});
watchInterrupt(3, (val, pin) => {
console.log(`gpio${pin} changed -> ${val}`);
});
})();