added interrupts class as multiple extension of Interrupt
Added single and multiple examplemaster
parent
709fd35adf
commit
002ad9edbb
|
@ -1,24 +0,0 @@
|
||||||
import Interrupt from '../src/interrupt-packet'
|
|
||||||
const delay = time => new Promise(res=>setTimeout(()=>res(),time))
|
|
||||||
|
|
||||||
let interrupts = new Interrupt([9,10,24],{id:'interrupt', mock:true, itrn:{path:'/opt/sockets/mcp.sock'}})
|
|
||||||
|
|
||||||
interrupts.interruptProcess = function (pin) {
|
|
||||||
let packet = {cmd:'pin.interrupt.find', pin:pin}
|
|
||||||
this.send(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
;
|
|
||||||
(async () => {
|
|
||||||
|
|
||||||
await interrupts.init()
|
|
||||||
interrupts.fire(9)
|
|
||||||
interrupts.fire(10)
|
|
||||||
interrupts.fire(24)
|
|
||||||
await delay(3000)
|
|
||||||
process.kill(process.pid, 'SIGTERM')
|
|
||||||
|
|
||||||
})().catch(err => {
|
|
||||||
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
|
|
||||||
// process.kill(process.pid, 'SIGTERM')
|
|
||||||
})
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import Interrupts from '../src/interrupts'
|
||||||
|
import Base from '@uci/base'
|
||||||
|
|
||||||
|
const PINS = [9,10,24]
|
||||||
|
const HOST = 'trantor'
|
||||||
|
const PORT = 9000
|
||||||
|
const PATH = 'interrupt'
|
||||||
|
|
||||||
|
let hook = (packet) =>
|
||||||
|
{
|
||||||
|
packet.cmd = 'pin.interrupt.find'
|
||||||
|
console.dir(packet)
|
||||||
|
return packet
|
||||||
|
}
|
||||||
|
|
||||||
|
let interrupts = new Interrupts(PINS,{host:HOST, hook:true, 10:{wait:200}})
|
||||||
|
// let listener = new Base({sockets:'inter#s>t', inter:{port:9000}, id:'listener'})
|
||||||
|
|
||||||
|
interrupts.setHook(hook)
|
||||||
|
|
||||||
|
// let interrupts = new Interrupts(PINS,{host:HOST, port:9000, hook:true, path:PATH})
|
||||||
|
// let listener = new Base({sockets:'intert#s>t,intern#s>n', intern:{path:PATH}, intert:{host:HOST, port:PORT}, id:'listener'})
|
||||||
|
|
||||||
|
// listener.interrupt = async function (packet) {
|
||||||
|
// return new Promise((resolve) => {
|
||||||
|
// console.log('interrupt received at listener')
|
||||||
|
// console.dir(packet)
|
||||||
|
// resolve({status: 'processed'})
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
// console.log(await listener.init())
|
||||||
|
await interrupts.init()
|
||||||
|
interrupts.fire()
|
||||||
|
|
||||||
|
})().catch(err => {
|
||||||
|
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
|
||||||
|
// process.kill(process.pid, 'SIGTERM')
|
||||||
|
})
|
|
@ -0,0 +1,35 @@
|
||||||
|
import Interrupt from '../src/interrupt'
|
||||||
|
import Base from '@uci/base'
|
||||||
|
|
||||||
|
// let interrupt = new Interrupt(24,{id:'test-interrupt', wait:0})
|
||||||
|
// let listener = new Base({sockets:'inter#s>n', inter:{path:'interrupt:24'}, id:'listener'})
|
||||||
|
|
||||||
|
let interrupt = new Interrupt(24,{id:'test-interrupt', wait:0, host:'localhost', hook:true})
|
||||||
|
let listener = new Base({sockets:'inter#s>t', inter:{port:9024}, id:'listener'})
|
||||||
|
|
||||||
|
|
||||||
|
listener.interrupt = async function (packet) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
console.log('interrupt socket listener got')
|
||||||
|
console.dir(packet)
|
||||||
|
resolve({status: 'processed'})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
(async () => {
|
||||||
|
|
||||||
|
console.log(await listener.init())
|
||||||
|
await interrupt.init()
|
||||||
|
interrupt.fire()
|
||||||
|
// interrupt.fire()
|
||||||
|
// interrupt.fire()
|
||||||
|
// interrupt.fire()
|
||||||
|
// await delay(3000)
|
||||||
|
// process.kill(process.pid, 'SIGTERM')
|
||||||
|
|
||||||
|
})().catch(err => {
|
||||||
|
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
|
||||||
|
// process.kill(process.pid, 'SIGTERM')
|
||||||
|
})
|
|
@ -5,7 +5,9 @@
|
||||||
"description": "a class for adding interrupt processesing for gpio pins on Raspberry Pi and Similar SBCs",
|
"description": "a class for adding interrupt processesing for gpio pins on Raspberry Pi and Similar SBCs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"single": "sudo node --require @std/esm examples/single",
|
"single": "sudo node --require @std/esm examples/single",
|
||||||
"singlelog": "DEBUG=true node_modules/.bin/nodemon --require @std/esm examples/single"
|
"singlelog": "UCI_LOG=true sudo node_--require @std/esm examples/single | pino-colada",
|
||||||
|
"multi": "sudo node --require @std/esm examples/multi",
|
||||||
|
"multilog": "DEBUG=true sudo node --require @std/esm examples/multi"
|
||||||
},
|
},
|
||||||
"author": "David Kebler",
|
"author": "David Kebler",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Interrupt from './interrupt'
|
||||||
|
import Interrupts from './interrupts'
|
||||||
|
|
||||||
|
export { Interrupt as Interrupt }
|
||||||
|
export { Interrupts as Interrupts }
|
||||||
|
export default Interrupt
|
|
@ -1,105 +0,0 @@
|
||||||
|
|
||||||
import bus, { Gpio as gpio } from 'pigpio'
|
|
||||||
// import btc from 'better-try-catch'
|
|
||||||
// import Base from '@uci/base'
|
|
||||||
import Base from '@uci/base'
|
|
||||||
|
|
||||||
import logger from '@uci/logger'
|
|
||||||
let log = {}
|
|
||||||
const LOG_OPTS = (id) => {
|
|
||||||
return {
|
|
||||||
repo:'uci-mcp',
|
|
||||||
npm:'@uci/mcp',
|
|
||||||
file:'src/mcp230xx-packet.mjs',
|
|
||||||
class:'MCP230XX',
|
|
||||||
id:id,
|
|
||||||
instance_created:new Date().getTime()
|
|
||||||
}}
|
|
||||||
|
|
||||||
export default class Interrupt extends Base {
|
|
||||||
constructor(pins,opts={}) {
|
|
||||||
|
|
||||||
opts.sockets = opts.sockets ? (opts.sockets + ',') : ''
|
|
||||||
if (opts.path || opts.itrn) {
|
|
||||||
opts.itrn = opts.itrn || {}
|
|
||||||
opts.itrn.path = opts.path || opts.itrn.path || (process.env.SOCKETS_DIR || __dirname) + '/interrupt.sock'
|
|
||||||
opts.sockets = opts.sockets + 'itrn#c>n,'
|
|
||||||
}
|
|
||||||
if (opts.itrt || opts.host) {
|
|
||||||
opts.itrt = opts.itrt || {}
|
|
||||||
opts.itrt.host = opts.host || opts.itrt.host
|
|
||||||
opts.itrt.port = opts.itrt.port || opts.port || 1777
|
|
||||||
opts.sockets = opts.sockets + 'itrt#c>t'
|
|
||||||
}
|
|
||||||
if (opts.sockets==='') throw ('must have at least one socket client')
|
|
||||||
console.dir(opts)
|
|
||||||
super(opts)
|
|
||||||
log = logger.child(LOG_OPTS(this.id))
|
|
||||||
log.info({pins:pins, opts:opts},'create interrupts with these opts')
|
|
||||||
this.mock = opts.mock
|
|
||||||
this.mode = gpio.INPUT
|
|
||||||
this.pull = opts.pull || gpio.PUD_DOWN
|
|
||||||
this.edge = opts.edge || gpio.RISING_EDGE
|
|
||||||
this.interrupts = {}
|
|
||||||
for(let pin of pins) {
|
|
||||||
if (typeof pin==='number') {pin={num:pin}}
|
|
||||||
this.interrupts[pin.num] = {
|
|
||||||
pin: new gpio(
|
|
||||||
pin.num,
|
|
||||||
{
|
|
||||||
mode: pin.mode || this.mode,
|
|
||||||
pullUpDown: pin.pull || this.pull
|
|
||||||
// do not! set edge here as it will start the emitter -- see pigio js
|
|
||||||
}),
|
|
||||||
edge: pin.edge || this.edge,
|
|
||||||
socket: pin.socket,
|
|
||||||
cmd: pin.cmd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end constructor
|
|
||||||
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
await super.init()
|
|
||||||
|
|
||||||
// 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))
|
|
||||||
})
|
|
||||||
for(const pin_num in this.interrupts) {
|
|
||||||
let pin = this.interrupts[pin_num].pin
|
|
||||||
let edge = this.interrupts[pin_num].edge
|
|
||||||
console.log(`starting interrupt on pin ${pin_num}`)
|
|
||||||
pin.on('interrupt', this.interruptProcess.bind(this,pin_num))
|
|
||||||
// rock n roll!!, start the pigpio interrupt
|
|
||||||
console.log('edge=',edge)
|
|
||||||
if(!this.mock) pin.enableInterrupt(edge)
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end constructor
|
|
||||||
|
|
||||||
// manual firing for testing
|
|
||||||
fire(pin_num) {
|
|
||||||
console.log('manually firing interrupt for pin', pin_num)
|
|
||||||
this.interrupts[pin_num].pin.emit('interrupt',null)
|
|
||||||
}
|
|
||||||
|
|
||||||
exit() {
|
|
||||||
bus.terminate()
|
|
||||||
return Promise.reject('keyboard termination...terminating interrupts')
|
|
||||||
}
|
|
||||||
|
|
||||||
interruptProcess (pin) {
|
|
||||||
console.log('=======================')
|
|
||||||
console.log(`pin ${pin} on rpi bus has thrown an interrupt`)
|
|
||||||
console.log('this is the default processor')
|
|
||||||
console.log('replace "interruptProcess" for your instance or extended class')
|
|
||||||
console.log('=======================')
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end Class
|
|
||||||
|
|
||||||
// default handler just logs the pin number fired
|
|
||||||
// overwrite with actual socket send with appropriate packet
|
|
|
@ -21,19 +21,18 @@ const LOG_OPTS = (id) => {
|
||||||
export default class Interrupt extends Base {
|
export default class Interrupt extends Base {
|
||||||
constructor(pin,opts={}) {
|
constructor(pin,opts={}) {
|
||||||
|
|
||||||
opts.sockets = opts.sockets ? (opts.sockets + ',') : ''
|
|
||||||
opts.itrt = opts.itrt || {}
|
opts.itrt = opts.itrt || {}
|
||||||
if (opts.itrt || opts.host) {
|
if (opts.itrt || opts.host) {
|
||||||
opts.itrt.host = opts.host || opts.itrt.host
|
opts.itrt.host = opts.host || opts.itrt.host
|
||||||
if (opts.itrt.host) {
|
if (opts.itrt.host) {
|
||||||
opts.itrt.port = opts.itrt.port || opts.port || 9000+pin
|
opts.itrt.port = opts.itrt.port || opts.port || 9000+pin
|
||||||
opts.sockets = opts.sockets + 'itrt#c>t'
|
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrt#c>t'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (opts.path || opts.itrn || !opts.itrt.host) {
|
if (opts.path || opts.itrn || !opts.itrt.host) {
|
||||||
opts.itrn = 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.sockets = opts.sockets + 'itrn#c>n'
|
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'itrn#c>n'
|
||||||
}
|
}
|
||||||
if (opts.sockets==='') throw ('must have at least one socket client')
|
if (opts.sockets==='') throw ('must have at least one socket client')
|
||||||
super(opts)
|
super(opts)
|
||||||
|
@ -41,7 +40,7 @@ export default class Interrupt extends Base {
|
||||||
log = logger.child(LOG_OPTS(this.id))
|
log = logger.child(LOG_OPTS(this.id))
|
||||||
log.info({pins:pin, opts:opts},'created interrupt with these opts')
|
log.info({pins:pin, opts:opts},'created interrupt with these opts')
|
||||||
this.pin_num = pin
|
this.pin_num = pin
|
||||||
this.mock = opts.mockG
|
this.mock = opts.mock
|
||||||
this.wait = opts.wait || 0 // debounce is off by default
|
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.dbopts = { maxWait:opts.maxwait || 500, leading: opts.leading || true, trailing:opts.trailing || false}
|
||||||
this.edge = opts.edge || Gpio.RISING_EDGE
|
this.edge = opts.edge || Gpio.RISING_EDGE
|
||||||
|
@ -109,7 +108,7 @@ export default class Interrupt extends Base {
|
||||||
packet.count += 1
|
packet.count += 1
|
||||||
packet.time = new Date().getTime()
|
packet.time = new Date().getTime()
|
||||||
if(this._hook) packet = this.hook(packet)
|
if(this._hook) packet = this.hook(packet)
|
||||||
console.log('packet from hook',packet)
|
// console.log('packet sending',packet)
|
||||||
this.send(packet)
|
this.send(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import Interrupt from './interrupt'
|
||||||
|
|
||||||
|
import logger from '@uci/logger'
|
||||||
|
let log = {}
|
||||||
|
const LOG_OPTS = (id) => {
|
||||||
|
return {
|
||||||
|
repo:'uci-interrupt',
|
||||||
|
npm:'@uci/interrupt',
|
||||||
|
file:'src/interrupts.mjs',
|
||||||
|
class:'Interrupts',
|
||||||
|
id:id,
|
||||||
|
instance_created:new Date().getTime()
|
||||||
|
}}
|
||||||
|
|
||||||
|
export default class Interrupts {
|
||||||
|
constructor(pins,opts={}) {
|
||||||
|
this.id = this.id || 'interrupts'
|
||||||
|
this.pins = pins
|
||||||
|
this.interrupt={}
|
||||||
|
pins.forEach (pin =>{
|
||||||
|
opts[pin] = opts[pin] || {}
|
||||||
|
opts[pin].id = (opts.id ||'interrupt') + ':' + pin;
|
||||||
|
['host','port','path','hook','wait','maxwait','leading','mock','trailing','edge','pull'].forEach(prop =>{
|
||||||
|
opts[pin][prop] = opts[pin][prop] || opts[prop]
|
||||||
|
})
|
||||||
|
this.interrupt[pin] = new Interrupt(pin,opts[pin])
|
||||||
|
this.interrupt[pin].hook=hook
|
||||||
|
this.interrupt[pin].reply = () =>{}
|
||||||
|
})
|
||||||
|
log = logger.child(LOG_OPTS(this.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
async 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)
|
||||||
|
console.log('manually firing interrupt for pin', pin)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('manually firing interrupt for pins', this.pins)
|
||||||
|
|
||||||
|
this.pins.forEach (async pin =>{
|
||||||
|
this.interrupt[pin].pin.emit('interrupt',1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setHook(func) {
|
||||||
|
this.pins.forEach (async pin =>{
|
||||||
|
this.interrupt[pin].hook=func
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end Class
|
||||||
|
|
||||||
|
// default hook
|
||||||
|
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 sockets with default cmd:"interrupt"')
|
||||||
|
console.dir(packet)
|
||||||
|
console.log('this is the default beforeHook')
|
||||||
|
console.log('add .hook for your instance or extended class')
|
||||||
|
console.log('=======================')
|
||||||
|
return packet
|
||||||
|
}
|
|
@ -1,46 +1,46 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const
|
const
|
||||||
Interrupt = require('../src/interrupt'),
|
Interrupt = require('../src/interrupt'),
|
||||||
expect = require('chai').expect
|
expect = require('chai').expect
|
||||||
|
|
||||||
// TODO finish simple test of a pin as interrupt
|
// TODO finish simple test of a pin as interrupt
|
||||||
|
|
||||||
describe(
|
describe(
|
||||||
`Testing `,
|
'Testing ',
|
||||||
function () {
|
function () {
|
||||||
hooks()
|
hooks()
|
||||||
interrupt()
|
interrupt()
|
||||||
someothertests()
|
someothertests()
|
||||||
})
|
})
|
||||||
|
|
||||||
//****************** TESTS **********************
|
//****************** TESTS **********************
|
||||||
function interrupt() {
|
function interrupt() {
|
||||||
it('==> tests an interrupt', async function () {
|
it('==> tests an interrupt', async function () {
|
||||||
|
|
||||||
expect(result, `test failed`).to.equal('expectedresult')
|
expect(result, 'test failed').to.equal('expectedresult')
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function someothertests() {
|
function someothertests() {
|
||||||
it('==> test something', async function () {
|
it('==> test something', async function () {
|
||||||
|
|
||||||
let result = await someasyncfunction()
|
let result = await someasyncfunction()
|
||||||
expect(result, `test failed`).to.equal('expectedresult')
|
expect(result, 'test failed').to.equal('expectedresult')
|
||||||
await pause(1000)
|
await pause(1000)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function hooks() {
|
function hooks() {
|
||||||
|
|
||||||
before(async() => {
|
before(async() => {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async() => {})
|
beforeEach(async() => {})
|
||||||
|
|
||||||
after(async() => {})
|
after(async() => {})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue