uci-interrupt/src/interrupt.js

153 lines
4.9 KiB
JavaScript
Raw Normal View History

// 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 = {}
2019-01-01 20:02:16 -08:00
class Interrupt extends Base {
constructor(pin, opts = {}) {
if (opts.path || opts.itrn) {
opts.itrn = opts.itrn || {}
2019-01-01 20:02:16 -08:00
opts.itrn.path = opts.path || opts.itrn.path || 'interrupt:' + pin
opts.itrn.conPacket = opts.conPacket
2019-01-01 20:02:16 -08:00
opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + 'itrn#s>n'
}
2019-01-01 20:02:16 -08:00
if (opts.topics || opts.itrm) {
opts.itrm = opts.itrm || {}
2019-01-01 20:02:16 -08:00
opts.itrm.topics = opts.topics || 'interrupt/' + pin
opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + 'itrm#s>m'
}
2019-01-01 20:02:16 -08:00
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 || {}
2019-01-01 20:02:16 -08:00
opts.itrt.port = opts.itrt.port || opts.port || 9000 + pin
opts.itrt.conPacket = opts.conPacket
2019-01-01 20:02:16 -08:00
opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + 'itrt#s>t'
}
super(opts)
2019-01-01 20:02:16 -08:00
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
2019-01-01 20:02:16 -08:00
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
2019-01-01 20:02:16 -08:00
this.pin = {} //set at init
2018-03-02 08:32:37 -08:00
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
2019-01-01 20:02:16 -08:00
} // end constructor
2019-01-01 20:02:16 -08:00
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')
2019-01-01 20:02:16 -08:00
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', () => {
2019-01-01 20:02:16 -08:00
this.exit()
.then(resp => console.log('\n', resp)) // unexport on cntrl-c
.catch(err => console.log('error:', err))
})
let cb = () => {}
2019-01-01 20:02:16 -08:00
if (this.wait === 0) {
cb = this._interruptProcess.bind(this, this.packet)
2018-03-02 08:32:37 -08:00
console.log(`starting interrupt on pin ${this.pin_num} without debounce`)
2019-01-01 20:02:16 -08:00
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
}`
)
2018-03-02 08:32:37 -08:00
}
2019-01-01 20:02:16 -08:00
this.pin.on('interrupt', cb)
// rock n roll!!, start the pigpio interrupt
2019-01-01 20:02:16 -08:00
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)
2019-01-01 20:02:16 -08:00
this.pin.emit('interrupt', 1)
return Promise.resolve({ status: 'fired' })
}
exit() {
bus.terminate()
return Promise.reject('keyboard termination...terminating interrupts')
}
// default processor
2019-01-01 20:02:16 -08:00
async _interruptProcess(packet) {
packet.count += 1
packet.time = new Date().getTime()
2019-01-01 20:02:16 -08:00
if (this._hook) packet = await this.hook(packet)
log.info({ packet: packet }, 'packet pushing to all clients')
this.push(packet)
2018-03-02 08:32:37 -08:00
}
//sample hook
2019-01-01 20:02:16 -08:00
hook(packet) {
// return a promise if anything async happens in hook
2018-03-02 08:32:37 -08:00
// 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)
2019-01-01 20:02:16 -08:00
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('=======================')
2018-03-02 08:32:37 -08:00
return packet
// resolve(packet)
// })
}
} // end Class
2019-01-01 20:02:16 -08:00
export default Interrupt