uci-interrupt/src/interrupts.js

103 lines
3.3 KiB
JavaScript

import Interrupt from './interrupt'
import Base from '@uci/base'
import logger from '@uci-utils/logger'
let log = {}
// will more easily create a group of sbc pin interrupts
class Interrupts extends Base {
constructor(pins, opts = {}) {
super(opts)
this.id = this.id || 'interrupts'
this.pins = pins.map(pin => Number(pin)) // make sure actual numbers are passed
this._interrupts = new Map()
this.resetCmd = opts.resetCmd || 'interrupt.reset'
log = logger({ name: 'interrupts', id: this.id, package:'@uci/interrupt', file:'src/interrupts.js'})
this.amendConsumerCommands({reset:makefunc.bind(this,'reset')})
this.amendSocketCommands({
reset:makefunc.bind(this,'reset'),
status:makefunc.bind(this,'status'),
fire:makefunc.bind(this,'fire'),
intervalReset:makefunc.bind(this,'intervalReset')
})
let pinopts = {}
this.pins.forEach(pin => {
// remove per pin opts and store
pinopts[pin] = Object.assign({}, opts[pin])
delete opts[pin]
pinopts[pin].multiple=true // each pin will only extend a simple emitter, uci-base
})
this.pins.forEach(pin => {
pinopts[pin] = Object.assign({}, opts, pinopts[pin])
pinopts[pin].id = pinopts[pin].id || this.id + ':' + pin
log.debug({ opts: pinopts[pin], method:'constructor', line:25, msg:`pin options for pin ${pin}`})
this._interrupts.set(pin, new Interrupt(pin, pinopts[pin]))
// bubble up events from single interrupts
const EVENTS=['log','interrupt','reset', 'ready'] // that should emit up from pin base
EVENTS.forEach(event => {
this.interrupt(pin).on(event, obj => {
if (event==='ready') this.emit('ready:'+pin,obj)
else {
if (Object.prototype.toString.call(obj) !== '[object Object]') { // is plain object
let data=obj
obj = {}
obj.data = data
}
obj.pin = pin
obj.id = pinopts[pin].id
this.emit(event,obj) // will emit a pin specific event
}
})
})
}) // end pins construct
this.on('interrupt', async ev=>{
await this.push(ev) // push interrupt to any connected consumers
})
} // end constructor
interrupt(pin) {
if (isNaN(pin)) return null
return this._interrupts.get(Number(pin))
} // pin type here same as when instantiated above.
async init() {
await super.init()
return Promise.all(
Array.from(this._interrupts).map(inter => {
return inter[1].init()
})
)
}
registerHook(func) { // same hook for each pin
this._interrupts.forEach(inter => {
inter.registerHook(func)
})
}
} // end Class
export default Interrupts
// combines indiviudal pin function calls into single call and combines returns
async function makefunc(fn, packet={}) {
if (!packet.pin || packet.pin==='all') {
let rpacket = {pins:[]}
for (let inter of this._interrupts.entries()) {
let ipacket = Object.assign({},packet)
delete(ipacket.cmd);delete(ipacket._header)
let res = await inter[1][fn](ipacket)
res.pin = inter[0]
rpacket.pins.push(res)
}
return rpacket
}
let pin = isNaN(Number(packet)) ? packet.pin : packet
if (this._interrupts.has(Number(pin))) return await this.interrupt(packet.pin)[fn](packet)
}