diff --git a/package.json b/package.json index 25cfcaa..b10efbd 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ }, "dependencies": { "@uci/base": "^0.1.7", - "@uci/logger": "0.0.3", + "@uci/i2c-device": "^0.1.4", + "@uci/logger": "0.0.6", "lodash.debounce": "^4.0.8" }, "devDependencies": { diff --git a/src/cjs/interrupt.js b/src/cjs/interrupt.js deleted file mode 100644 index 8eab7bd..0000000 --- a/src/cjs/interrupt.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict' - -// Creates an ES6 Interrupt class wrapper using the pigio C library and pigpio javascript wrapper package -// The pigipio C library is specifically coded for the Raspberry Pi but might be adapatable to any single board computer (sbc) with Gpios -// assuming they would be pigio C, compatiable. -// Must have pigpio C library installed first. -// On interrupt emits "fired" which can be caught by the code calling this interrupt instance for handling -// Understand there are two interrupts here. One is this class and one on the sbc/rpi via pigpio -// The sbc/pigpio interrupt emits an event which is listened for by this class which then emits -// a "fired" event which can be can be listed to by having a handle to an instance this class. - -const - pigpio = require('pigpio'), - sbcGpio = pigpio.Gpio, - EventEmitter = require('events') - -class Interrupt extends EventEmitter { - constructor(pin_number, handler, opts = {}) { - super() - this.pin_number = pin_number - this.handler = handler - this.mode = sbcGpio.INPUT - this.pull = opts.pull ? opts.pull : sbcGpio.PUD_DOWN - this.edge = opts.edge ? opts.edge : sbcGpio.RISING_EDGE - this.sbc_interrupt = new sbcGpio( - this.pin_number, { - mode: this.mode, - pullUpDown: this.pull, - // do not! set edge here as it will start the emitter -- see pigio js - } - ) - } - - // init() { - // - // // console.log(`initialize interrupt ${this.pin_number}`) - // return Promise.resolve() - // - // } - - get pin() { - return this.pin_number - } - - async start() { - - console.log(`starting interrupt on pin ${ this.pin_number}`) - - // 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)) - }) - let interrupt = this // scope `this` for use in the listener for each interrupt - // console.log(`interrupt listener set for rpi ${interrupt.pin_number}`) - this.sbc_interrupt.on('interrupt', function () { - // console.log(`the sbc interrupt tripped by sbc pin ${interrupt.pin_number}`) - interrupt.emit('fired') // emit an event that can be listened for by the device that created the interrupt instance - }) - - // rock n roll!!, start the pigpio interrupt - this.sbc_interrupt.enableInterrupt(this.edge) - - } - - // manual firing for testing - fire() { - let interrupt = this - console.log('manually firing interrupt', this.handler) - this.emit('fired') - } - - exit() { - pigpio.terminate() - return Promise.reject(`keyboard termination...terminating interrupt on pin ${this.pin_number}`) - } -} - -module.exports = Interrupt diff --git a/src/interrupt.js b/src/interrupt.js index d9743a4..bbdff54 100644 --- a/src/interrupt.js +++ b/src/interrupt.js @@ -8,92 +8,107 @@ 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 ) { +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.path = opts.path || opts.itrn.path || 'interrupt:' + pin opts.itrn.conPacket = opts.conPacket - opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrn#s>n' + opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + 'itrn#s>n' } - if (opts.topics || opts.itrm) { + 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' + 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' + 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.port = opts.itrt.port || opts.port || 9000 + pin opts.itrt.conPacket = opts.conPacket - opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrt#s>t' + 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.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.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.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 - - } // end constructor - - - async init(){ + 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 - }) + 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 + 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) + 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`) + 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 + }` + ) } - 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) + this.pin.on('interrupt', cb) // rock n roll!!, start the pigpio interrupt - if(!this.mock) this.pin.enableInterrupt(this.edge || bus.Gpio.RISING_EDGE ) + 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'}) + this.pin.emit('interrupt', 1) + return Promise.resolve({ status: 'fired' }) } exit() { @@ -102,31 +117,36 @@ export default class Interrupt extends Base { } // default processor - async _interruptProcess (packet) { + 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') + if (this._hook) packet = await this.hook(packet) + log.info({ packet: packet }, 'packet pushing to all clients') this.push(packet) } //sample hook - hook (packet) { + 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( + '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 + +export default Interrupt diff --git a/src/interrupts.js b/src/interrupts.js index 156e1d7..815e99d 100644 --- a/src/interrupts.js +++ b/src/interrupts.js @@ -3,67 +3,74 @@ import Interrupt from './interrupt' import logger from '@uci/logger' let log = {} -export default class Interrupts { - constructor(pins,opts={}) { +class Interrupts { + constructor(pins, opts = {}) { this.id = this.id || 'interrupts' this.pins = pins - this.interrupt={} - log = logger({name:'interrupts',id:this.id}) - let pinopts={} - pins.forEach (pin =>{ // remove per pin opts and store - pinopts[pin]=Object.assign({},opts[pin]) - delete(opts[pin]) + this.interrupt = {} + log = logger({ name: 'interrupts', id: this.id }) + let pinopts = {} + pins.forEach(pin => { + // remove per pin opts and store + pinopts[pin] = Object.assign({}, opts[pin]) + delete opts[pin] }) - pins.forEach (pin =>{ + pins.forEach(pin => { pinopts[pin] = Object.assign({}, opts, pinopts[pin]) - pinopts[pin].id = (opts.id ||'interrupt') + ':' + pin - pinopts[pin].conPacket = { cmd:opts.resetCmd, pin:pin } - log.info({opts:pinopts[pin]},`pin options for pin ${pin}`) - this.interrupt[pin] = new Interrupt(pin,pinopts[pin]) + pinopts[pin].id = (opts.id || 'interrupt') + ':' + pin + pinopts[pin].conPacket = { cmd: opts.resetCmd, pin: pin } + log.info({ opts: pinopts[pin] }, `pin options for pin ${pin}`) + this.interrupt[pin] = new Interrupt(pin, pinopts[pin]) }) - } async init() { - return Promise.all(this.pins.map(pin => {return this.interrupt[pin].init()})) + return Promise.all( + this.pins.map(pin => { + return this.interrupt[pin].init() + }) + ) } - // manual firing for testing fire(pin) { - if(pin) { - this.interrupt[pin].pin.emit('interrupt',1) + if (pin) { + this.interrupt[pin].pin.emit('interrupt', 1) console.log('manually firing interrupt for pin', pin) - } - else { + } else { console.log('manually firing interrupt for pins', this.pins) - this.pins.forEach (async pin =>{ - this.interrupt[pin].pin.emit('interrupt',1) + this.pins.forEach(async pin => { + this.interrupt[pin].pin.emit('interrupt', 1) }) } } setHook(func) { - this.pins.forEach (async pin =>{ - this.interrupt[pin].hook=func + this.pins.forEach(async pin => { + this.interrupt[pin].hook = func }) } // new test push(packet) { - this.pins.forEach (async pin =>{ + this.pins.forEach(async pin => { console.log('all push', pin, packet) this.interrupt[pin].push(packet) }) } - } // end Class +export default Interrupts + // default hook -const hook = (packet) => { +const hook = packet => { console.log('======Common for all Pins Default Hook=================') - console.log(`pin ${packet.pin} on sbc gpio bus has thrown ${packet.count}th interrupt`) - console.log('sending to all connected consumers/clients with default cmd:"interrupt"') + console.log( + `pin ${packet.pin} on sbc gpio bus has thrown ${packet.count}th interrupt` + ) + console.log( + 'sending to all connected consumers/clients with default cmd:"interrupt"' + ) console.dir(packet) console.log('this is the default beforeHook') console.log('add .hook for your instance or extended class')