2017-01-21 12:21:16 -08:00
|
|
|
"use strict";
|
2017-01-18 20:31:53 -08:00
|
|
|
|
2017-01-21 12:23:45 -08:00
|
|
|
const fs = require('mz/fs'),
|
2017-01-21 12:21:16 -08:00
|
|
|
EventEmitter = require('events'),
|
2017-01-21 12:23:45 -08:00
|
|
|
Epoll = require('epoll').Epoll,
|
2017-01-21 17:21:26 -08:00
|
|
|
_ = require('uci-utils')
|
2017-01-18 20:31:53 -08:00
|
|
|
|
2017-01-21 23:48:17 -08:00
|
|
|
const pWaitFor = require('p-wait-for')
|
|
|
|
const pathExists = require('path-exists');
|
|
|
|
const debounce = require('debounce');
|
|
|
|
|
2017-01-21 12:21:16 -08:00
|
|
|
const GPIO_ROOT_PATH = '/sys/class/gpio/'
|
2017-01-18 20:31:53 -08:00
|
|
|
|
2017-01-21 12:21:16 -08:00
|
|
|
class Interrupt extends EventEmitter {
|
2017-01-18 20:31:53 -08:00
|
|
|
// bus is i2c-bus bus object
|
2017-01-21 12:21:16 -08:00
|
|
|
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'
|
2017-01-24 14:46:01 -08:00
|
|
|
this.delay = opts.delay ? opts.delay : 50
|
2017-01-21 23:48:17 -08:00
|
|
|
this.dbt = opts.debounce ? opts.debounce : 300
|
2017-01-24 14:46:01 -08:00
|
|
|
// this.poller = new Epoll(
|
|
|
|
// debounce((err, fd, events) => {
|
|
|
|
// if (err) { this.emit('error', err) } else { this.clear().then(this.emit('fired', this.hook)) }
|
|
|
|
// }, this.dbt, true)
|
|
|
|
// )
|
2017-01-18 20:31:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
init() {
|
|
|
|
|
2017-01-21 12:23:45 -08:00
|
|
|
let tasks = [
|
2017-01-24 14:46:01 -08:00
|
|
|
fs.writeFile(GPIO_ROOT_PATH + 'export', this.num).then(() => { console.log('exported', this.num) }),
|
|
|
|
pWaitFor(() => pathExists(this.path + 'direction')).then(_.pDelay(this.delay))
|
|
|
|
.then(() => { return fs.writeFile(this.path + 'direction', 'in').then(() => { console.log('direction', 'in') }) }),
|
|
|
|
fs.writeFile(this.path + 'edge', this.edge).then(() => { console.log('edge', this.edge) }),
|
|
|
|
fs.open(this.path + 'value', 'r+').then(fd => { this.valuefd = fd }),
|
|
|
|
this.clear().then(() => { return this.start() })
|
2017-01-21 12:23:45 -08:00
|
|
|
]
|
2017-01-21 12:21:16 -08:00
|
|
|
|
2017-01-21 23:48:17 -08:00
|
|
|
process.on('SIGINT', () => {
|
|
|
|
this.exit().then(() => console.log('\nunexported and closed')) // unexport on cntrl-c
|
|
|
|
})
|
|
|
|
|
|
|
|
return this.exit() // make sure pin is unexported
|
|
|
|
.then((resp) => {
|
2017-01-24 14:46:01 -08:00
|
|
|
console.log('ready to init', tasks)
|
|
|
|
return _.pSeries(tasks).then(console.log('finsihed tasks'))
|
2017-01-21 23:48:17 -08:00
|
|
|
})
|
2017-01-21 12:21:16 -08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fire(name = 'fired') {
|
|
|
|
this.emit(name, this.hook)
|
2017-01-18 20:31:53 -08:00
|
|
|
}
|
|
|
|
|
2017-01-21 12:21:16 -08:00
|
|
|
clear() {
|
2017-01-21 12:23:45 -08:00
|
|
|
let buffer = Buffer.from([0x00])
|
|
|
|
return fs.read(this.valuefd, buffer, 0, 1, 0);
|
2017-01-21 12:21:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
exit() {
|
2017-01-21 23:48:17 -08:00
|
|
|
return pathExists(this.path)
|
2017-01-21 12:23:45 -08:00
|
|
|
.then(() => {
|
|
|
|
return fs.writeFile(GPIO_ROOT_PATH + 'unexport', this.num)
|
|
|
|
})
|
|
|
|
.then(() => {
|
|
|
|
if (this.valuefd) {
|
|
|
|
this.stop()
|
|
|
|
return fs.close(this.valuefd)
|
|
|
|
}
|
|
|
|
})
|
2017-01-21 23:48:17 -08:00
|
|
|
.catch(err => { return Promise.resolve('already unexported') })
|
2017-01-21 12:21:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
start() {
|
|
|
|
this.poller.add(this.valuefd, Epoll.EPOLLPRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
stop() {
|
|
|
|
this.poller.remove(this.valuefd).close();
|
2017-01-18 20:31:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-21 12:21:16 -08:00
|
|
|
module.exports = {
|
|
|
|
Interrupt
|
|
|
|
}
|