diff --git a/lib/interrupt.js b/lib/interrupt.js index b5b2f2b..23b7479 100644 --- a/lib/interrupt.js +++ b/lib/interrupt.js @@ -1,32 +1,79 @@ -'use strict' +"use strict"; -const Gpio = require('onoff').Gpio +const fs = require('fs'), + EventEmitter = require('events'), + Epoll = require('epoll').Epoll -// ********************************** +const GPIO_ROOT_PATH = '/sys/class/gpio/' -class Interrupt { +class Interrupt extends EventEmitter { // bus is i2c-bus bus object - constructor(pin_number, processor, opts = {}) { - let dtimeout = opts.debounceTimeout ? opts.debounceTimeout : 200 - this.pin = new Gpio(pin_number, 'in', 'falling', { debounceTimeout: dtimeout }) - this.processor = processor + 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() { - this.addListener(this.processor) - process.on('SIGINT', function () { - this.pin.unexport(); - }) + + 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') } - addListener(processor) { - this.pin.watch((err, value) => { - if (err) { return Promise.reject(err) } - return processor - }); + 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 = Interrupt +module.exports = { + Interrupt +} diff --git a/package.json b/package.json index b6be39b..47a3f4b 100644 --- a/package.json +++ b/package.json @@ -1,38 +1,43 @@ { - "name": "uci-interrupt", - "version": "0.0.1", - "description": "a class for adding interrupt processesing via sysfs and gpio pins on Raspberry and similar", - "main": "index.js", - "scripts": { - "testw": "./node_modules/.bin/mocha --reporter list --recursive --watch", - "test": "istanbul cover ./node_modules/.bin/_mocha test/ --report lcovonly -- -R spec --recursive && codecov || true" - }, - "author": "David Kebler", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/uCOMmandIt/uci-interrrupt.git" - }, - "keywords": [ - "node.js", - "communication", - "serial", - "utilities", - "helpers" - ], - "bugs": { - "url": "https://github.com/uCOMmandIt/uci-interrrupt/issues" - }, - "homepage": "https://github.com/uCOMmandIt/uci-interrrupt#readme", - "dependencies": { - "onoff": "^1.1.1", - "require-all": "git+https://github.com/dkebler/node-require-all.git#merge" - }, - "devDependencies": { - "chai": "^3.5.0", - "chai-as-promised": "^6.0.0", - "codecov": "^1.0.1", - "istanbul": "^0.4.5", - "mocha": "^3.2.0" - } + "name": "uci-interrupt", + "version": "0.0.1", + "description": "a class for adding interrupt processesing via sysfs and gpio pins on Raspberry and similar", + "main": "index.js", + "watch": { + "testw": "{lib,test}/*.js" + }, + "scripts": { + "testw": "./node_modules/.bin/mocha --reporter list --recursive ", + "test": "istanbul cover ./node_modules/.bin/_mocha test/ --report lcovonly -- -R spec --recursive && codecov || true", + "watch": "./node_modules/.bin/npm-watch" + }, + "author": "David Kebler", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/uCOMmandIt/uci-interrrupt.git" + }, + "keywords": [ + "node.js", + "communication", + "serial", + "utilities", + "helpers" + ], + "bugs": { + "url": "https://github.com/uCOMmandIt/uci-interrrupt/issues" + }, + "homepage": "https://github.com/uCOMmandIt/uci-interrrupt#readme", + "dependencies": { + "onoff": "^1.1.1", + "require-all": "git+https://github.com/dkebler/node-require-all.git#merge" + }, + "devDependencies": { + "chai": "^3.5.0", + "chai-as-promised": "^6.0.0", + "codecov": "^1.0.1", + "istanbul": "^0.4.5", + "mocha": "^3.2.0", + "npm-watch": "^0.1.7" + } } diff --git a/test/interrupt.test.js b/test/interrupt.test.js index 3da57cb..342a874 100644 --- a/test/interrupt.test.js +++ b/test/interrupt.test.js @@ -1,17 +1,35 @@ 'use strict' const expect = require('chai').expect, - lib = require('../') + Interrupt = require('../').Interrupt //time-stamp for use when watching to distinguish reruns in console // place in alpha first file only let date = new Date(Date.now()) console.log(date.getMinutes(), "\:", date.getSeconds()) -describe('Test a template module ', function () { +let inter17 = new Interrupt(17, { hook: 'a hook to something to do' }) - it('Should test all methods', function () { - expect(lib.hello('Forest Gump')).to.equal('Hello Forest Gump') - }) +// console.log('inter17', inter17) +inter17.on('fired', hook => { + console.log('Listener fired and returned:', hook) }) + +inter17.init() + .then((resp) => { + console.log('return from init()', resp) + setInterval(function () { + inter17.fire() + }, 1000) + }) + .catch(err => console.log("error:", err)) + +// describe('Interrupt Class', function () { +// +// it('can be manually fired', function () { +// expect(hello('Forest Gump')).to.equal() +// }) +// +// }) +// })