diff --git a/src/interrupt.mjs b/src/interrupt.mjs new file mode 100644 index 0000000..f3a499e --- /dev/null +++ b/src/interrupt.mjs @@ -0,0 +1,115 @@ +import bus, { Gpio } from 'pigpio' +// import bus, { Gpio } from 'pigpio-mock' +// import btc from 'better-try-catch' +import debounce from 'lodash.debounce' +// import throttle from 'lodash.throttle' +// import debounce from 'debounce-fn' +import Base from '@uci/base' + +import logger from '@uci/logger' +let log = {} +const LOG_OPTS = (id) => { + return { + repo:'uci-interrupt', + npm:'@uci/interrupt', + file:'src/interrupt.mjs', + class:'Interrupt', + id:id, + instance_created:new Date().getTime() + }} + +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' + } + } + 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' + } + if (opts.sockets==='') throw ('must have at least one socket client') + super(opts) + console.dir(opts) + 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.wait = opts.wait || 0 + this.dbopts = { maxWait:opts.maxwait || 300, leading: opts.leading || true, trailing:opts.trailing || false} + this.edge = opts.edge || Gpio.RISING_EDGE + this.pin = new Gpio( + pin, { + mode: Gpio.INPUT, + pullUpDown: opts.pull || Gpio.PUD_DOWN + // do not! set edge here as it will start the emitter -- see pigio js + }) + this.packet = opts.packet || {} + this.packet.pin = pin + this.packet.cmd = this.packet.cmd || 'interrupt' + this.packet.count = 0 + + + } // 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)) + }) + + // const pinDebounce = function (processor, wait, options, packet) { + // console.log(processor,wait,options,packet) + // return debounce.bind(this,processor.bind(this,packet),wait, options) + // return debounce.bind(processor.bind(this,packet),wait) + // return debounce.bind(null,processor,{ wait:wait}) + // } + + console.log(`starting interrupt on pin ${this.pin_num} with debounce wait/max:${this.wait},${this.maxwait} (0=off)`) + let cb = () => {} + if (this.wait===0) cb = this.interruptProcess.bind(this,this.packet) + // else cb = pinDebounce(this.interruptProcess,this.wait,this.dbopts,this.packet) + // else cb = debounce(()=>{console.log('debounced')},this.wait,this.dbopts) + else cb = debounce(this.interruptProcess.bind(this,this.packet),this.wait,this.dbopts) + this.pin.on('interrupt',cb) + // rock n roll!!, start the pigpio interrupt + if(!this.mock) this.pin.enableInterrupt(this.edge) + } + + + // manual firing for testing + fire() { + console.log('manually firing interrupt for pin', this.pin_num) + this.pin.emit('interrupt',1) + } + + exit() { + bus.terminate() + return Promise.reject('keyboard termination...terminating interrupts') + } + + // default processor + interruptProcess (packet) { + packet.count += 1 + packet.time = new Date().getTime() + console.log('=======================') + console.log(`pin ${packet.pin} on sbc gpio bus has thrown an interrupt`) + console.log('sending to all connected sockets with default cmd:"interrupt"') + console.dir(packet) + this.send(packet) + console.log('this is the default processor') + console.log('replace "interruptProcess" for your instance or extended class') + console.log('=======================') + } + +} // end Class