"use strict"; const fs = require('fs'), EventEmitter = require('events'), Epoll = require('epoll').Epoll const GPIO_ROOT_PATH = '/sys/class/gpio/' class Interrupt extends EventEmitter { // bus is i2c-bus bus object constructor(pin_number, opts = {}) { super() this.num = pin_number; this.hook = opts.hook // will be passed back with the emit this.path = GPIO_ROOT_PATH + 'gpio' + this.num + '/' this.edge = opts.edge ? opts.edge : 'falling' this.debounce = opts.debounce ? opts.debounce : 200 this.poller = new Epoll(function (err, fd, events) { if (err) { this.emit('error', err) } this.clear() this.emit('fired', this.hook) }.bind(this)) } init() { try { if (fs.existsSync(this.path)) { this.exit() } fs.writeFileSync(GPIO_ROOT_PATH + 'export', this.gpio); fs.writeFileSync(this.path + 'direction', 'in'); fs.writeFileSync(this.path + 'edge', this.edge); this.valueFd = fs.openSync(this.path + 'value', 'r+'); // Cache fd for performance. this.clear(); this.start() process.on('SIGINT', function () { console.log('\ncleaning up interrupt before exiting') this.exit(); }) } catch (err) { return Promise.reject(err) } return Promise.resolve('interrupt ready') } fire(name = 'fired') { this.emit(name, this.hook) } clear() { fs.readSync(this.valuefd, null, 0, 1, 0); } exit() { if (this.valuefd) { this.stop() fs.closeSync(this.valueFd) } try { fs.writeFileSync(GPIO_ROOT_PATH + 'unexport', this.gpio); } catch (ignore) {} } start() { this.poller.add(this.valuefd, Epoll.EPOLLPRI); } stop() { this.poller.remove(this.valuefd).close(); } } module.exports = { Interrupt }