commands.js
added pin.cfgs for multiple pin configurations
refactored pin.status, pin._state to better handle multiple pins and 08 vs 17
mpc230xx.js
  changed to not having default sockets but socket can be added by passing lport or lpath
  now supports new new uci-utils/ready module and adds an observer for when chip and pins are configured
mcp230xxi.js
   now supports new new uci-utils/ready module by adds an observer for when the interrupt process connects and also resets
   refactored the interrupt methods and commands to compliment changes in the interrupt module
master
David Kebler 2020-01-09 20:17:32 -08:00
parent 9650698683
commit 9a7fdd9539
9 changed files with 238 additions and 279 deletions

View File

@ -1,59 +0,0 @@
/*
* i2c bus unix socket and client in one for demo
*
*/
import Base from '../../uci-base/src/base'
import { spawn } from 'child_process'
const PATH = '/opt/sockets/mcp.sock'
const delay = time => new Promise(res=>setTimeout(()=>res(),time))
const i2cbus = spawn('node',['-r', '@std/esm', './examples/bus'])
i2cbus.stdout.on('data', function(buf) {
console.log('[I2C BUS]', String(buf))
})
;
(async () => {
let mcpclient = new Base({id:'mcpclient', sockets:'uc#c>n', uc:{path:PATH}})
mcpclient.reply = function (packet) {
console.log('for request ',packet._header.request)
console.log('mcp status is ',packet.status)
}
await mcpclient.init()
console.log('=============sending============')
// const pins='2,3,4'
// const pins=3
// const pins='all'
// const pins=[1,3,5,7]
let packet = {cmd:'pin.cfg', pins:'all'}
await mcpclient.send(packet)
packet = {cmd:'pin.cfg', pins:'all', port:'B'}
await mcpclient.send(packet)
packet = {cmd:'pin.state.off', pins:'all' }
await mcpclient.send(packet)
packet = {cmd:'pin.state.off', pins:'all', port:'B' }
await mcpclient.send(packet)
packet = {cmd:'pin.state.on', pins:'2,7', port:'B' }
await mcpclient.send(packet)
packet = {cmd:'pin.state.on', pins:'3,6'}
await mcpclient.send(packet)
packet = {cmd:'pin.status', pins:'all'}
await mcpclient.send(packet)
packet = {cmd:'pin.status', pins:'all', port:'B'}
await mcpclient.send(packet)
process.kill(process.pid, 'SIGTERM')
})().catch(err => {
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
})

View File

@ -1,65 +0,0 @@
/*
*
*
*/
import { MCP230XXi } from '../src'
import { MCP230XX } from '../src'
import Base from '@uci/base'
const BUS_HOST = 'sbc' // if ihost not given will be the same as host:
const BUS_PORT = 1776 // 1776 is default port for i2c-bus module
const SW_ADDRESS = 0x25 // 1776 is default port for i2c-bus module
const RY_ADDRESS = 0x27 // 1776 is default port for i2c-bus module
let announce = new Base({id:'switch:announce'})
let sw17 = new MCP230XXi([9,10],{id:'sw17', chip17:true, host:BUS_HOST, address:SW_ADDRESS+1})
// let sw8 = new MCP230XXi([24],{id:'sw8', host:BUS_HOST, address:SW_ADDRESS})
// let ry8 = new MCP230XX({id:'ry8', host:BUS_HOST, address:RY_ADDRESS})
const reply = { reply: () => {} }
// ry8.c = reply;
sw17.c=reply
// sw8.c= reply
function iprocess(details) {
console.log('--common interrupt processor--')
console.log(details)
announce.push()
// action function can do whatever but best would be to push the details to any attached client (mqtt or some database that then pushes
// local_action(details)
}
// just something to do
async function local_action (details) {
if (details.id === 'sw17') {
await ry8.pin.state.toggle({pins:'2,4,6,8'})
}
if (details.id === 'sw8') {
if (details.pin===1) {
if (details.state==='off') await ry8.pin.state.off({pins:'all'})
else ry8.pin.state.on({pins:'all'})
}
if (details.pin===8) {
if (details.state==='off') await ry8.pin.state.off({pins:'1,3,5,7'})
else await ry8.pin.state.on({pins:'1,3,5,7'})
}
}
}
(async () => {
await sw17.init()
sw17.interruptProcessor(iprocess)
// await sw8.init()
// sw8.interruptProcessor(iprocess)
//
//
// await ry8.init()
// let packet = {pins:'all', cfg:'output'}
// await ry8.pin.cfg(packet)
})().catch(err => {
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
})

View File

@ -1,23 +0,0 @@
/*
* i2c bus with both unix and tcp socket using defaults. For TCP that is host OS name and port 8080
*
*/
import MCP230XX from '../src/mcp230xx-packet'
// const PATH = ''
;
(async () => {
// let chip8 = new MCP230XX({id:'mcp8-27', address:0x27, nmcp: { path: '/opt/sockets/mcp2.sock' }})
let chip17 = new MCP230XX({id:'mcp17-26', chip17:true, address:0x26})
await chip17.init()
// await chip8.init()
console.log(await chip17.pin.cfg({pins:'all'}))
// console.log(await chip17.pin.cfg({pins:'all', cfg:'toggle_switch'}))
// console.log(await chip17.pin.cfg({pins:'all', port:'B', cfg:'toggle_switch'}))
// console.log(await chip8.pin.cfg({pins:'all', cfg:'toggle_switch'}))
})().catch(err => {
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
})

40
examples/outputs.js Normal file
View File

@ -0,0 +1,40 @@
/*
*
*
*/
import { MCP230XX } from '../src'
// const TRANSPORT = process.env.TRANSPORT || 'tcp'
const HOST = process.env.BUS_HOST || 'sbc'
const PORT = process.env.BUS_PORT || 1776
const ADDRESS = process.env.DEVICE_ADDR || 39
const CHIP17 = !!process.env.CHIP17 || false
;
(async () => {
let outputs = new MCP230XX({id:'mcp', chip17:CHIP17, address:ADDRESS, bus:{host:HOST, port:PORT}})
console.log(await outputs.socketsInit())
await new Promise((resolve) => setTimeout(resolve,50))
outputs.on('ready:mcp', async ev => {
console.log('mcpready', ev)
// all pins are outputs by default
for (var i = 0; i < 10; i++) {
console.log('pass', i)
await outputs.commands.pin.state.on({pins:'all'})
await outputs.commands.pin.state.on({port:'B', pins:'all'}) // will be ingnored on mcp23008
await new Promise((resolve) => setTimeout(resolve,50))
await outputs.commands.pin.state.off({pins:'all'})
await outputs.commands.pin.state.off({port:'B', pins:'all'}) // will be ingnored on mcp23008
}
process.kill(process.pid, 'SIGTERM')
})
})().catch(err => {
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
})

64
examples/switches.js Normal file
View File

@ -0,0 +1,64 @@
/*
*
*
*/
import { MCP230XXi } from '../src'
const HOST = process.env.BUS_HOST
const PATH = process.env.BUS_PATH
const PORT = process.env.BUS_PORT || 1776
const ADDRESS = process.env.DEVICE_ADDR || 0x26
const CHIP17 = !!process.env.CHIP17 || true
const LISTEN_PORT = process.env.PORT || 9001
let switches = new MCP230XXi([9,10],{id:'switches', chip17:CHIP17, path:PATH, host:HOST, port:PORT, address:ADDRESS, iport:LISTEN_PORT})
// switches.registerSocket('interrupt','c','t',{host:'switchesd.local', port:1777})
;
(async () => {
if (process.env.VERBOSE==='true') {
switches.on('log', async log => {
if (log.level!=='trace') {
console.log(
'LOG:',log.level,':',
log.msg,
'socket:',log.socketName,
)
if (log.packet) console.dir(log.packet)
}
})
switches.on('connection:socket', async ev => {
console.log('connection event: outbound > ', ev.state,'to socket',ev.socketName)// if (ev.state ==='connected') switches.duplex = true
})
switches.on('connection:consumer', async ev => {
// console.log(ev)
console.log('connection event: inbound >', ev.state,'from consumer',ev.name)// if (ev.state ==='connected') switches.duplex = true
})
}
console.log('ready observers for switches', switches.ready.observerNames)
switches.ready.addObserverDetails('bus',{msg:'this is some details related to bus observer'})
switches.ready.subscribe(x=>{
console.log('=====================switches ready================?',x ? 'YES':'NO')
console.log('what has failed: ',switches.ready.failure,' details:', switches.ready.details.get(switches.ready.failure)||'none')
})
// this.ready.subscribe('interrupt:connected',(res)=>console.log('interrupt connected............',res))
// this.ready.subscribe('mcp',(res)=>console.log('mcp............',res))
// this.ready.subscribe('interrupt:reset',(res)=>console.log('interrupt reset............',res))
let res = await switches.socketsInit()
if (res.errors) console.log(res)
})().catch(err => {
console.error('FATAL: UNABLE TO START SYSTEM!\n',err)
})

View File

@ -1,10 +1,11 @@
{
"name": "@uci/mcp",
"main": "src",
"version": "0.1.37",
"version": "0.1.38",
"description": "Classes and Helper Functions for using the MCP chip on I2C Bus",
"scripts": {
"relays": "node -r esm examples/relays",
"outputs": "./node_modules/.bin/nodemon -r esm --preserve-symlinks examples/outputs",
"switches": "./node_modules/.bin/nodemon -r esm --preserve-symlinks examples/switches",
"swrl": "UCI_ENV=dev node -r esm examples/mcp-switch-relay",
"swr": "node -r esm examples/mcp-switch-relay",
"test": "./node_modules/.bin/mocha --reporter list --timeout 30000",
@ -28,9 +29,16 @@
},
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
"dependencies": {
"@uci/i2c-device": "^0.1.21",
"@uci-utils/logger": "^0.0.15",
"@uci-utils/byte": "^0.2.3"
"@uci-utils/bind-funcs": "^0.2.4",
"@uci-utils/byte": "^0.2.3",
"@uci-utils/logger": "0.0.15",
"@uci-utils/ready": "^0.1.2",
"@uci/base": "^0.1.36",
"@uci/i2c-device": "^0.1.24",
"@uci/logger": "0.0.6",
"@uci/socket": "^0.2.28",
"is-plain-object": "^3.0.0",
"merge-anything": "^2.4.4"
},
"devDependencies": {
"chai": "^4.2.0",

View File

@ -4,7 +4,6 @@ import logger from '@uci-utils/logger'
let log = logger({file:'/src/commands.js', package:'@uci/mcp'})
// TODO add uci debug logging
export default {
@ -37,7 +36,7 @@ export default {
}
},
// Individual Pin Configurations
// Pin(s) Configurations
// set is for cfg: 'custom' assume a setting is zero unless given
// packet = { pin:, port:, cfg: , set:{dir: 0, ivrt: 0, pullup: 0, intr: 0, usedef: 0,defval: 0} }
// first get the current byte (pin) state for that setting
@ -45,9 +44,9 @@ export default {
cfg: async function(packet){
let cfg = {}
let reply = { cmd:'reply', status:{} }
packet.cfg = packet.cfg || 'output'
if (packet.cfg==='custom') cfg = packet.set
else cfg = PIN.cfgset[packet.cfg]
packet.config = packet.config || packet.cfg || 'output'
if (packet.config==='custom') cfg = packet.set
else cfg = PIN.cfgset[packet.config]
for(let name of Object.keys(PIN.setting)) {
let op = cfg[name] ? 'on' : 'off'
log.debug({cmd:'pin.cfg', line:28, msg:'setting pin register', operation:op, registerName:name, resgisterNum:PIN.setting[name]})
@ -58,31 +57,40 @@ export default {
return reply
},
// state is equivalent to read
cfgs: async function({configs}){
let res = await Promise.all(configs.map(config => this.commands.pin.cfg(config)))
let error = res.reduce((err,cfg) => {return (err || !!cfg.error)},false)
return ({error:error, res:res})
},
// status is equivalent to read
status: async function (packet) {
if(!this.chip17 && packet.port==='B') return {error:'sent request for port B. No such port on MCP2008'}
let reg = packet.reg ? PIN.cmd[packet.reg] : PIN.cmd.gpio
if (!reg) return {error:`unknown register ${packet.reg}`, packet:packet }
let reply = { cmd:'reply'}
let pins = parsePins(packet.pins)
let pins = parsePins(packet.pins || packet.pin)
let state = new _.Byte()
let bus = await this.bus.read(sreg(reg, packet.port))
if (bus.error) return bus
state.value = bus.response
reply.status =
{ port:state.toFmt('ARY'),
let reply = {
port:state.toFmt('ARY'),
pins: pins.value.map(pin => {
if (state.toFmt('PLC').indexOf(pin) !==-1) return [pin, 'on']
else return [pin,'off']
})
}
if (packet.pin) reply.state = reply.pins[0][1]
return reply
},
_state: async function(packet,op,reg){
if(!this.chip17 && packet.port==='B') return {error:'sent request for port B. No such port on MCP2008'}
reg = (reg!==undefined)? reg : PIN.cmd.gpio
log.debug({cmd:'pin._state', line:82, msg:'_state change request', operation:op, register:reg, packet:packet})
let reply = { cmd:'reply'}
let pins = parsePins(packet.pins)
let pins = parsePins(packet.pins || packet.pin)
let state = new _.Byte()
// TODO support setting state on both ports if non given
let bus = await this.bus.read(sreg(reg,packet.port))
if (bus.error) return bus
state.value = bus.response

View File

@ -1,7 +1,5 @@
import Device from '@uci/i2c-device'
// import Device from '../../uci-i2c-device/src/device-packet'
import { I2CDevice as Device, map, changed, isPlainObject, to, merge} from '@uci/i2c-device'
import commands from './commands'
import logger from '@uci-utils/logger'
let log = {}
@ -16,32 +14,30 @@ class MCP230XX extends Device {
})
this.chip17 = opts.chip17
this.chipCfg = opts.chipCfg || 'default'
// this._configured = false
this.pinsCfg = opts.pinsCfg || this.chip17 ? [{port:'A', pins:'all'},{port:'B', pins:'all'}] : [{pins:'all'}]
this.commands = this.bindFuncs(commands)
this.addNamespace('commands', 's') // allow access to commands via socket/server
// this._pin = this.commands.pin // add a simplier reference for local access
// this._chipcfg = this.commands.chip.cfg // add a simplier reference for local access
this.once('ready:i2c', () =>{
this.configure()
if (this._ready) this._ready.call(this)
})
}
async registerReadyFunc(func) {
this._ready = func
}
if (opts.lport) this.registerSocket('mcp-t','s','t',{port:opts.lport})
if (opts.lpath) this.registerSocket('mcp-n','s','n',{path: opts.lpath})
async configure() {
this.ready.addObserver('mcp',this.ready.getObserver('i2c').pipe(
map(async ready => {
if (ready) {
let res = await this.commands.chip.cfg({cfg:this.chipCfg})
if (res.error) {
let err={level:'fatal', msg:'unable to configure mcp chip', error:res.error, cfg:this.chipCfg, address:this.address}
log.fatal(err)
this.emit('status', err)
} else {
this.emit('status', {level:'info', msg:'mcp chip was properly configured', cfg:this.chipCfg})
this.emit('ready:mcp')
}
if (!res.error) {
let res = await this.commands.pin.cfgs({configs:this.pinsCfg})
return res.error? false :true
} return false
}
return false
})
))
} // end contructor
} // end of MCP230XX Class
export default MCP230XX
export {MCP230XX, map, changed, isPlainObject, to, merge}

View File

@ -1,5 +1,6 @@
import MCP230XX from './mcp230xx'
import {MCP230XX, map, changed, isPlainObject, to, merge} from './mcp230xx'
import { byteFormat } from '@uci-utils/byte'
// import Ready from '@uci-utils/ready'
import logger from '@uci-utils/logger'
let log = {}
@ -17,11 +18,11 @@ class MCP230XXi extends MCP230XX {
if (!Array.isArray(pins)) { options = pins; pins = options.interrupt.pins} // if pins sent via .interrupt.pins
let opts = Object.assign({},options) // don't allow passed options to mutate
if (opts.interrupt) delete opts.interrupt.pins // if .interrupt was passed then .pins must be removed
delete opts.sockets // .sockets is used by uci base so clear it if was used by enduser and sent by mistake
log.debug({method:'constructor', line:21, msg:'passed options before setting',options:opts})
opts.lport = opts.lport || (opts.interrupt || {}).port || opts.iport
if (!opts.lport) opts.lpath = opts.lpath || (opts.interrupt || {}).ipath || opts.ipath || 'interrupt' // must has a socket litener for interrupt process
super(opts)
this.opts = opts
this.pinsCfg = opts.pinsCfg || this.chip17 ? [{port:'A', pins:'all', cfg:'input_interrupt'},{port:'B', pins:'all', cfg:'input_interrupt'}] : [{pins:'all', cfg:'input_interrupt'}]
log = logger({
file: 'src/mcp230xxi.js',
class: 'MCP230XXi',
@ -29,127 +30,116 @@ class MCP230XXi extends MCP230XX {
id: this.id
})
log.debug({ method:'constructor', line:32, opts: opts, msg:'mcp interrupt options after calling super() on base'})
pins.forEach(pin => {
pins.forEach((pin,index) => {
this[pin] = opts['i' + pin] || {}
this[pin].mport = this[pin].mport || index ? 'B' : 'A'
})
this.pins = pins
this.commands.interrupt = this.bindFuncs(icommands) // add interrupt pin commands to base set in "command.js"
this.addNamespace('commands', 'c') // add access via push to same commands
this._interruptProcess = process
this.ready = false
log.debug({ opts: opts, pins: pins }, 'options for mcp interrupt processor')
}
this._interruptProcess = process.bind(this) // default processor
async init() {
if (this.ipath) await this.addSocket('inter-n','s','n',{path:this.ipath})
if (this.iport) await this.addSocket('inter-t','s','t',{port:this.iport})
await super.init()
// this will set default type to internal pullup, only need to to change indivial pins to external if desired
await this.commands.pin.cfg({port:'A',pins:'all',cfg:'input_interrupt'})
let status = await this._resetInterrupt('A')
log.debug({method:'init', line:52, msg:'default configure all port A pins as interrupts. Resetting port A interrupt', status:status})
if (this.chip17) {
await this.commands.pin.cfg({port:'B',pins:'all',cfg:'input_interrupt'})
let status = await this._resetInterrupt('B')
log.debug({method:'init', line:52, msg:'default configure all port B pins as interrupts. Resetting port B interrupt', status:status})
}
}
async _readyInterrupt(port) {
let istate = await this.bus.read(port !== 'B' ? 0x07 : 0x17)
if (istate.response) {
this.ready = false
return false
}
else {
this.ready = true
const conditionHandler = async ev => {
if ((ev||{}).state ==='connected'){
let data = (ev.data ||{})
if (data.type === 'interrupt' || [ev.name, data.name, data.id].some(name => (name||'').includes('interrupt')) ) {
return true
}
}
async _resetInterrupt(port) {
await this.bus.read(port !== 'B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register
log.debug({method:'_resetInterrupt', line:72, msg: `reset interrupt for port ${port || 'A'},${this.id} arg ${port !== 'B' ? 0x08 : 0x18}`})
return(await this._readyInterrupt(port))
return false
}
_getPortByPin(pin) {
let port = this[pin] ? this[pin].mport : null
let index = this.pins.map(pin => pin.toString()).indexOf(pin.toString())
port = port || index <= 0 ? 'A' : 'B'
return port
this.ready.addObserver('interrupt:connected',this.getSocket(`mcp-${opts.lport? 't':'n'}`),{event:'connection:consumer',condition:conditionHandler})
this.ready.addObserver('interrupt:reset',this.ready.combineObservers(['mcp','interrupt:connected']).pipe(
map(async ready=>{
if (ready) return await this.resetInterrupt()
return false
})
))
} // end constructor
async interruptState(pin) {
let istate = await this.bus.read(this.getPort(pin) !== 'B' ? 0x07 : 0x17)
let pullup = (this.chipCfg||'').includes('Pullup') ? true : false
let state = istate.response ? true && pullup : false || !pullup
return state
}
interruptProcessor(func) {
this._interruptProcess = func
async resetInterrupt(pins) {
if (!Array.isArray(pins)) pins = pins ? [pins] : this.pins
this._ireset = (await Promise.all(pins.map(async pin => {
await this.bus.read(this.getPort(pin) !== 'B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register
return(await this.interruptState(pin))
})
)).reduce((res,val) => res && val)
return this._ireset
}
getPort(pin) {
if (pin==='A' || pin==='B') return pin
return this[pin].mport
}
registerInterruptProcessor(func) {
this._interruptProcess = func.bind(this)
}
} // end of MCP230XXi Class
export default MCP230XXi
export { MCP230XXi, map, changed, isPlainObject, to, merge}
// default processor
function process(details) {
details.id = this.id
console.log('----default interrupt processor for mcp instance----')
console.log('here is where you could either locally take some action for send/push on a message to another process')
console.log('here is where you could either locally take some action or send on a message to another process')
console.log('create your own function and register it with .interruptProcesser(function)')
console.log(this.id)
console.dir(details)
console.log('------------------------------------------')
}
// commands to be added to pin packet command functions
const icommands = {
status: async function(packet) {
// pin is interrupt pin on sbc for port
let port = packet.port || this._getPortByPin(packet.pin)
let res = await this._readyInterrupt(port)
return {cmd:'reply', request:'interrupt.status', port:port, ipin:packet.pin, ready:res}
let pin = packet.ipin || packet.pin
let state = await this.interruptState(pin)
return {cmd:'reply', request:'interrupt.status', port:this.getPort(pin), ipin:pin, ready:state}
},
reset: async function(packet) {
// pin is interrupt pin on sbc for port
let port = packet.port || this._getPortByPin(packet.pin)
log.error({cmd:'interrupt.reset', line:114, packet: packet, port:port, msg:`forced remote interrupt reset for port ${port}`})
await this._resetInterrupt(port)
let res = await this._readyInterrupt(port)
return {cmd:'reply', request:'interrupt.reset', port:port, ipin:packet.pin, ready:res}
let pin = packet.ipin || packet.pin
let state = await this.resetInterrupt(pin)
let res = {level:state ? 'debug':'error', msg:`remote reset request from ${packet._header.sender.instanceID} for pin ${pin}: ${state?'ready': 'error'}` }
this.emit('log',res)
return {state:state}
},
// given a gpio interrupt then push a packet with cmd: 'pin.interrupt.find' and pin: the gpio pin number
// finds which mcp pin caused the interrupt
find: async function(inter) {
if (this.ready) {
// protects tripped interrupt before it's fully initialized, or interrupt requests arriving before porcessing is complete
this.ready = false
log.debug({cmd:'interrupt.find', line:124, msg:'raw packet from interrupt, finding pin that caused interrupt', inter:inter})
let packet = { pins: 'all', reg: 'intf' }
packet.port = inter.port || this._getPortByPin(inter.pin)
let res = await this.commands.pin.status(packet) // read port interrupt status
let status = await this._resetInterrupt(packet.port)
this.ready = true
log.debug({cmd:'interrupt.find', line:130, interrupt:res, reset:status, msg:'interrupt read and reset'})
if (!res.status) {
let ipin = inter.ipin || inter.pin
if (!await this.interruptState(ipin)) { // if it's already reset then this is false trip
let res = await this.commands.pin.status({ pins: 'all', reg: 'intf', port:this.getPort(ipin) }) // read port interrupt status
let status = await this.resetInterrupt(ipin) // now reset
let pin = byteFormat(res.port||[], { in: 'ARY', out: 'PLC' })[0]
if (!pin) {
log.warn({cmd:'interrupt.find', line:132, inter:inter, msg:'no pin associated with interrupt'})
return { error: 'no pin associated with interrupt' }
}
let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' })
res.pin = pin[0]
packet.pins = pin[0]
packet.reg = null
if (packet.pins) { // avoid bad interrupt (i.e. no pin caused interrupt)
res.ipin = inter.pin
res.port = packet.port
delete inter.cmd; delete inter._header; delete inter.pin
Object.assign(res,inter)
delete res.status
res.interrupt_ready = status || false
res.state = (await this.commands.pin.status(packet)).status.pins[0][1]
this._interruptProcess(res)
return res
} else {
log.warn({cmd:'interrupt.find', line:151, inter:inter, msg:'no pin associated with interrupt'})
return { error: 'no pin associated with interrupt' }
}
else { // avoid bad interrupt (i.e. no pin caused interrupt)
delete inter.cmd; delete inter._header
inter.ipin = ipin
inter.pin = pin
inter.port = this[ipin].mport
inter.interrupt_ready = status
inter.state = (await this.commands.pin.status({pin:pin, port:this.getPort(ipin)})).state
this._interruptProcess(inter)
// replying with reset command which is also a check
return {cmd:'reset', pin:ipin}
}
}
}
} // end commands