From 002ad9edbb07eeada79b1fbba12f097cae80a1f3 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sun, 4 Mar 2018 15:09:18 -0800 Subject: [PATCH] added interrupts class as multiple extension of Interrupt Added single and multiple example --- examples/mock.mjs | 24 --------- examples/multi.mjs | 44 ++++++++++++++++ examples/single.mjs | 35 +++++++++++++ package.json | 4 +- src/{ => cjs}/interrupt.js | 0 src/index.mjs | 6 +++ src/interrupt-packet.mjs | 105 ------------------------------------- src/interrupt.mjs | 9 ++-- src/interrupts.mjs | 71 +++++++++++++++++++++++++ test/interrupt.test.js | 42 +++++++-------- 10 files changed, 184 insertions(+), 156 deletions(-) delete mode 100644 examples/mock.mjs create mode 100644 examples/multi.mjs create mode 100644 examples/single.mjs rename src/{ => cjs}/interrupt.js (100%) create mode 100644 src/index.mjs delete mode 100644 src/interrupt-packet.mjs create mode 100644 src/interrupts.mjs diff --git a/examples/mock.mjs b/examples/mock.mjs deleted file mode 100644 index 651cf7e..0000000 --- a/examples/mock.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import Interrupt from '../src/interrupt-packet' -const delay = time => new Promise(res=>setTimeout(()=>res(),time)) - -let interrupts = new Interrupt([9,10,24],{id:'interrupt', mock:true, itrn:{path:'/opt/sockets/mcp.sock'}}) - -interrupts.interruptProcess = function (pin) { - let packet = {cmd:'pin.interrupt.find', pin:pin} - this.send(packet) -} - -; -(async () => { - - await interrupts.init() - interrupts.fire(9) - interrupts.fire(10) - interrupts.fire(24) - await delay(3000) - process.kill(process.pid, 'SIGTERM') - -})().catch(err => { - console.error('FATAL: UNABLE TO START SYSTEM!\n',err) - // process.kill(process.pid, 'SIGTERM') -}) diff --git a/examples/multi.mjs b/examples/multi.mjs new file mode 100644 index 0000000..1c92ef6 --- /dev/null +++ b/examples/multi.mjs @@ -0,0 +1,44 @@ +import Interrupts from '../src/interrupts' +import Base from '@uci/base' + +const PINS = [9,10,24] +const HOST = 'trantor' +const PORT = 9000 +const PATH = 'interrupt' + +let hook = (packet) => +{ + packet.cmd = 'pin.interrupt.find' + console.dir(packet) + return packet +} + +let interrupts = new Interrupts(PINS,{host:HOST, hook:true, 10:{wait:200}}) +// let listener = new Base({sockets:'inter#s>t', inter:{port:9000}, id:'listener'}) + +interrupts.setHook(hook) + +// let interrupts = new Interrupts(PINS,{host:HOST, port:9000, hook:true, path:PATH}) +// let listener = new Base({sockets:'intert#s>t,intern#s>n', intern:{path:PATH}, intert:{host:HOST, port:PORT}, id:'listener'}) + +// listener.interrupt = async function (packet) { +// return new Promise((resolve) => { +// console.log('interrupt received at listener') +// console.dir(packet) +// resolve({status: 'processed'}) +// }) +// } + + + +; +(async () => { + + // console.log(await listener.init()) + await interrupts.init() + interrupts.fire() + +})().catch(err => { + console.error('FATAL: UNABLE TO START SYSTEM!\n',err) + // process.kill(process.pid, 'SIGTERM') +}) diff --git a/examples/single.mjs b/examples/single.mjs new file mode 100644 index 0000000..1e5eaf9 --- /dev/null +++ b/examples/single.mjs @@ -0,0 +1,35 @@ +import Interrupt from '../src/interrupt' +import Base from '@uci/base' + +// let interrupt = new Interrupt(24,{id:'test-interrupt', wait:0}) +// let listener = new Base({sockets:'inter#s>n', inter:{path:'interrupt:24'}, id:'listener'}) + +let interrupt = new Interrupt(24,{id:'test-interrupt', wait:0, host:'localhost', hook:true}) +let listener = new Base({sockets:'inter#s>t', inter:{port:9024}, id:'listener'}) + + +listener.interrupt = async function (packet) { + return new Promise((resolve) => { + console.log('interrupt socket listener got') + console.dir(packet) + resolve({status: 'processed'}) + }) + +} + +; +(async () => { + + console.log(await listener.init()) + await interrupt.init() + interrupt.fire() + // interrupt.fire() + // interrupt.fire() + // interrupt.fire() + // await delay(3000) + // process.kill(process.pid, 'SIGTERM') + +})().catch(err => { + console.error('FATAL: UNABLE TO START SYSTEM!\n',err) + // process.kill(process.pid, 'SIGTERM') +}) diff --git a/package.json b/package.json index d8a0896..230f553 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "description": "a class for adding interrupt processesing for gpio pins on Raspberry Pi and Similar SBCs", "scripts": { "single": "sudo node --require @std/esm examples/single", - "singlelog": "DEBUG=true node_modules/.bin/nodemon --require @std/esm examples/single" + "singlelog": "UCI_LOG=true sudo node_--require @std/esm examples/single | pino-colada", + "multi": "sudo node --require @std/esm examples/multi", + "multilog": "DEBUG=true sudo node --require @std/esm examples/multi" }, "author": "David Kebler", "license": "MIT", diff --git a/src/interrupt.js b/src/cjs/interrupt.js similarity index 100% rename from src/interrupt.js rename to src/cjs/interrupt.js diff --git a/src/index.mjs b/src/index.mjs new file mode 100644 index 0000000..72a3acb --- /dev/null +++ b/src/index.mjs @@ -0,0 +1,6 @@ +import Interrupt from './interrupt' +import Interrupts from './interrupts' + +export { Interrupt as Interrupt } +export { Interrupts as Interrupts } +export default Interrupt diff --git a/src/interrupt-packet.mjs b/src/interrupt-packet.mjs deleted file mode 100644 index 60a3204..0000000 --- a/src/interrupt-packet.mjs +++ /dev/null @@ -1,105 +0,0 @@ - -import bus, { Gpio as gpio } from 'pigpio' -// import btc from 'better-try-catch' -// import Base from '@uci/base' -import Base from '@uci/base' - -import logger from '@uci/logger' -let log = {} -const LOG_OPTS = (id) => { - return { - repo:'uci-mcp', - npm:'@uci/mcp', - file:'src/mcp230xx-packet.mjs', - class:'MCP230XX', - id:id, - instance_created:new Date().getTime() - }} - -export default class Interrupt extends Base { - constructor(pins,opts={}) { - - opts.sockets = opts.sockets ? (opts.sockets + ',') : '' - if (opts.path || opts.itrn) { - opts.itrn = opts.itrn || {} - opts.itrn.path = opts.path || opts.itrn.path || (process.env.SOCKETS_DIR || __dirname) + '/interrupt.sock' - opts.sockets = opts.sockets + 'itrn#c>n,' - } - if (opts.itrt || opts.host) { - opts.itrt = opts.itrt || {} - opts.itrt.host = opts.host || opts.itrt.host - opts.itrt.port = opts.itrt.port || opts.port || 1777 - opts.sockets = opts.sockets + 'itrt#c>t' - } - if (opts.sockets==='') throw ('must have at least one socket client') - console.dir(opts) - super(opts) - log = logger.child(LOG_OPTS(this.id)) - log.info({pins:pins, opts:opts},'create interrupts with these opts') - this.mock = opts.mock - this.mode = gpio.INPUT - this.pull = opts.pull || gpio.PUD_DOWN - this.edge = opts.edge || gpio.RISING_EDGE - this.interrupts = {} - for(let pin of pins) { - if (typeof pin==='number') {pin={num:pin}} - this.interrupts[pin.num] = { - pin: new gpio( - pin.num, - { - mode: pin.mode || this.mode, - pullUpDown: pin.pull || this.pull - // do not! set edge here as it will start the emitter -- see pigio js - }), - edge: pin.edge || this.edge, - socket: pin.socket, - cmd: pin.cmd - } - } - - } // end constructor - - - async init(){ - await super.init() - - // for cntrl-c exit of interrupt - process.on('SIGINT', () => { - this.exit().then((resp) => console.log('\n', resp)) // unexport on cntrl-c - .catch(err => console.log('error:', err)) - }) - for(const pin_num in this.interrupts) { - let pin = this.interrupts[pin_num].pin - let edge = this.interrupts[pin_num].edge - console.log(`starting interrupt on pin ${pin_num}`) - pin.on('interrupt', this.interruptProcess.bind(this,pin_num)) - // rock n roll!!, start the pigpio interrupt - console.log('edge=',edge) - if(!this.mock) pin.enableInterrupt(edge) - } - - } // end constructor - - // manual firing for testing - fire(pin_num) { - console.log('manually firing interrupt for pin', pin_num) - this.interrupts[pin_num].pin.emit('interrupt',null) - } - - exit() { - bus.terminate() - return Promise.reject('keyboard termination...terminating interrupts') - } - - interruptProcess (pin) { - console.log('=======================') - console.log(`pin ${pin} on rpi bus has thrown an interrupt`) - console.log('this is the default processor') - console.log('replace "interruptProcess" for your instance or extended class') - console.log('=======================') - } - -} // end Class - -// default handler just logs the pin number fired -// overwrite with actual socket send with appropriate packet diff --git a/src/interrupt.mjs b/src/interrupt.mjs index c816dd2..d426a8a 100644 --- a/src/interrupt.mjs +++ b/src/interrupt.mjs @@ -21,19 +21,18 @@ const LOG_OPTS = (id) => { export default class Interrupt extends Base { constructor(pin,opts={}) { - opts.sockets = opts.sockets ? (opts.sockets + ',') : '' opts.itrt = opts.itrt || {} if (opts.itrt || opts.host) { opts.itrt.host = opts.host || opts.itrt.host if (opts.itrt.host) { opts.itrt.port = opts.itrt.port || opts.port || 9000+pin - opts.sockets = opts.sockets + 'itrt#c>t' + opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrt#c>t' } } if (opts.path || opts.itrn || !opts.itrt.host) { opts.itrn = opts.itrn || {} opts.itrn.path = opts.path || opts.itrn.path || 'interrupt:'+ pin - opts.sockets = opts.sockets + 'itrn#c>n' + opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrn#c>n' } if (opts.sockets==='') throw ('must have at least one socket client') super(opts) @@ -41,7 +40,7 @@ export default class Interrupt extends Base { log = logger.child(LOG_OPTS(this.id)) log.info({pins:pin, opts:opts},'created interrupt with these opts') this.pin_num = pin - this.mock = opts.mockG + this.mock = opts.mock this.wait = opts.wait || 0 // debounce is off by default this.dbopts = { maxWait:opts.maxwait || 500, leading: opts.leading || true, trailing:opts.trailing || false} this.edge = opts.edge || Gpio.RISING_EDGE @@ -109,7 +108,7 @@ export default class Interrupt extends Base { packet.count += 1 packet.time = new Date().getTime() if(this._hook) packet = this.hook(packet) - console.log('packet from hook',packet) + // console.log('packet sending',packet) this.send(packet) } diff --git a/src/interrupts.mjs b/src/interrupts.mjs new file mode 100644 index 0000000..2263073 --- /dev/null +++ b/src/interrupts.mjs @@ -0,0 +1,71 @@ +import Interrupt from './interrupt' + +import logger from '@uci/logger' +let log = {} +const LOG_OPTS = (id) => { + return { + repo:'uci-interrupt', + npm:'@uci/interrupt', + file:'src/interrupts.mjs', + class:'Interrupts', + id:id, + instance_created:new Date().getTime() + }} + +export default class Interrupts { + constructor(pins,opts={}) { + this.id = this.id || 'interrupts' + this.pins = pins + this.interrupt={} + pins.forEach (pin =>{ + opts[pin] = opts[pin] || {} + opts[pin].id = (opts.id ||'interrupt') + ':' + pin; + ['host','port','path','hook','wait','maxwait','leading','mock','trailing','edge','pull'].forEach(prop =>{ + opts[pin][prop] = opts[pin][prop] || opts[prop] + }) + this.interrupt[pin] = new Interrupt(pin,opts[pin]) + this.interrupt[pin].hook=hook + this.interrupt[pin].reply = () =>{} + }) + log = logger.child(LOG_OPTS(this.id)) + } + + async init() { + return Promise.all(this.pins.map(pin => {return this.interrupt[pin].init()})) + } + + + // manual firing for testing + fire(pin) { + if(pin) { + this.interrupt[pin].pin.emit('interrupt',1) + console.log('manually firing interrupt for pin', pin) + } + else { + console.log('manually firing interrupt for pins', this.pins) + + this.pins.forEach (async pin =>{ + this.interrupt[pin].pin.emit('interrupt',1) + }) + } + } + + setHook(func) { + this.pins.forEach (async pin =>{ + this.interrupt[pin].hook=func + }) + } + +} // end Class + +// default hook +const hook = (packet) => { + console.log('======Common for all Pins Default Hook=================') + console.log(`pin ${packet.pin} on sbc gpio bus has thrown ${packet.count}th interrupt`) + console.log('sending to all connected sockets with default cmd:"interrupt"') + console.dir(packet) + console.log('this is the default beforeHook') + console.log('add .hook for your instance or extended class') + console.log('=======================') + return packet +} diff --git a/test/interrupt.test.js b/test/interrupt.test.js index 7a3d233..53f145b 100644 --- a/test/interrupt.test.js +++ b/test/interrupt.test.js @@ -1,46 +1,46 @@ 'use strict' const - Interrupt = require('../src/interrupt'), - expect = require('chai').expect + Interrupt = require('../src/interrupt'), + expect = require('chai').expect -// TODO finish simple test of a pin as interrupt +// TODO finish simple test of a pin as interrupt describe( - `Testing `, - function () { - hooks() - interrupt() - someothertests() - }) + 'Testing ', + function () { + hooks() + interrupt() + someothertests() + }) //****************** TESTS ********************** function interrupt() { - it('==> tests an interrupt', async function () { + it('==> tests an interrupt', async function () { - expect(result, `test failed`).to.equal('expectedresult') + expect(result, 'test failed').to.equal('expectedresult') - }) + }) } function someothertests() { - it('==> test something', async function () { + it('==> test something', async function () { - let result = await someasyncfunction() - expect(result, `test failed`).to.equal('expectedresult') - await pause(1000) + let result = await someasyncfunction() + expect(result, 'test failed').to.equal('expectedresult') + await pause(1000) - }) + }) } function hooks() { - before(async() => { + before(async() => { - }) + }) - beforeEach(async() => {}) + beforeEach(async() => {}) - after(async() => {}) + after(async() => {}) }