uci-interrupt/src/interrupt.js

133 lines
4.7 KiB
JavaScript

// 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