// import btc from 'better-try-catch' let bus = {} 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 = {} export default class Interrupt extends Base { constructor(pin,opts={}) { if (opts.path || opts.itrn ) { opts.itrn = opts.itrn || {} opts.itrn.path = opts.path || opts.itrn.path || 'interrupt:'+ pin opts.itrn.conPacket = opts.conPacket opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrn#s>n' } if (opts.topics || opts.itrm) { opts.itrm = opts.itrm || {} opts.itrm.topics = opts.topics || 'interrupt/'+ pin opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrm#s>m' } if (opts.itrw || opts.wport) { opts.itrw.port = opts.itrw.port || opts.wport || 9100+pin opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrw#s>w' } // default is a tcp socket server at 9000+pin if (opts.itrt || opts.port || !opts.sockets) { opts.itrt = opts.itrt || {} opts.itrt.port = opts.itrt.port || opts.port || 9000+pin opts.itrt.conPacket = opts.conPacket opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrt#s>t' } super(opts) this.id = (opts.id ||'interrupt') + ':' + pin log = logger({name:'interrupt',id:this.id}) log.info({pins:pin, opts:opts},'created interrupt with these opts') this.pin_num = pin this.mock = opts.mock || process.env.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 this.pull = opts.pull this.pin = {} //set at init this._hook = opts.hook this.packet = opts.packet || {} this.packet.pin = pin this.packet.cmd = this.packet.cmd || opts.pushcmd || 'interrupt' this.packet.count = 0 } // end constructor async init(){ await super.init() // for cntrl-c exit of interrupt // create the pigio pin_num if (this.mock) bus = await import('pigpio-mock') else bus = await import('pigpio') this.pin = new bus.Gpio( this.pin_num, { mode: bus.Gpio.INPUT, pullUpDown: this.pull || bus.Gpio.PUD_DOWN // do not! set edge here as it will start the emitter -- see pigio js }) process.on('SIGINT', () => { this.exit().then((resp) => console.log('\n', resp)) // unexport on cntrl-c .catch(err => console.log('error:', err)) }) let cb = () => {} if (this.wait===0) { cb = this._interruptProcess.bind(this,this.packet) console.log(`starting interrupt on pin ${this.pin_num} without debounce`) log.info({packet:this.packet},`starting interrupt on pin ${this.pin_num} without debounce`) } else { cb = debounce(this._interruptProcess.bind(this,this.packet),this.wait,this.dbopts) console.log(`starting interrupt on pin ${this.pin_num} with debounce wait:${this.wait} options:${JSON.stringify(this.dbopts)}` ) log.info({packet:this.packet, wait:this.wait, options:this.dbopts},`starting interrupt on pin ${this.pin_num} with debounce wait:${this.wait}` ) } this.pin.on('interrupt',cb) // rock n roll!!, start the pigpio interrupt if(!this.mock) this.pin.enableInterrupt(this.edge || bus.Gpio.RISING_EDGE ) } // manual firing for testing async fire() { console.log('manually firing interrupt for pin', this.pin_num) this.pin.emit('interrupt',1) return Promise.resolve({status:'fired'}) } exit() { bus.terminate() return Promise.reject('keyboard termination...terminating interrupts') } // default processor async _interruptProcess (packet) { packet.count += 1 packet.time = new Date().getTime() if(this._hook) packet = await this.hook(packet) log.info({packet:packet},'packet pushing to all clients') this.push(packet) } //sample hook hook (packet) { // return a promise if anything async happens in hook // new Promise((resolve) => { console.log('=======================') console.log(`pin ${packet.pin} on sbc gpio bus has thrown an interrupt`) console.log(`pushing to all connected socket client with cmd:${packet.cmd}`) console.dir(packet) console.log('This hook allow you to modify the packet being pushed to connected clients') console.log('add .hook method for your instance or extended class to overwrite this') console.log('Must be promise returning if anything async happens in your hook') console.log('=======================') return packet // resolve(packet) // }) } } // end Class