import MCP230XX from './mcp230xx' import { byteFormat } from '@uci/utils/src/byte' import logger from '@uci/logger' let log = {} // if opts.iport not set then will be generated based on pin number export default class MCP230XXi extends MCP230XX { constructor(pins,opts) { if (typeof opts.iport ==='number' || opts.ipath) { if (typeof opts.iport ==='number') { opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>t' opts.inter = {port:opts.iport} opts.inter.host = opts.ihost || opts.host } if (opts.ipath) { opts.inter = { path: opts.ipath || 'interrupt'} opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>n' } } else { pins.forEach( (pin,index) => { let ipin = 'i'+pin opts[ipin] = opts[pin] || {} if (index===1) opts[ipin].mport = opts[ipin].mort || 'B' delete(opts[pin]) if (opts[ipin].port || opts.iport !=='number') { opts[ipin].port = opts[ipin].port || opts.iport if (typeof opts[ipin].port !=='number') opts[ipin].port = 9000 + pin opts[ipin].host = opts[ipin].host || opts.ihost || opts.host opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + ipin +'#c>t' } // either on the same host as bus and interrupt or not - no need for both else { opts[pin].path = opts[pin].path || opts.ipath if(!opts[pin].path) Object.assign(opts[pin],{path:'interrupt:'+pin}) opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + pin+'#c>n' } }) } super(opts) log = logger({file:'src/mcp230xxi.js',class:'MCP230XXi',name:'mcp',id:this.id}) log.info({opts:opts},'mcp interrupt options after calling super() on base') pins.forEach(pin => { this[pin] = opts['i'+pin] || {} }) this.pins = pins Object.assign(this.commands.pin, this.bindFuncs(ipincommands)) // add interrupt pin commands to base set in "command.js" this.addNamespace('commands','c') this._interruptProcess = null this.ready = false log.info({opts:opts, pins:pins}, 'options for mcp interrupt processor') } async init(){ await super.init() this.pins.forEach(async pin => { let cfg = {port:this[pin].mport||'A',pins:this[pin].pins||'all', cfg:this[pin].type ||'toggle_switch'} await this.pin.cfg(cfg) log.info('resetting mcp port for corresponding gpio pin') await this.pin.interrupt.reset(this[pin].mport) this.ready=true }) this.on('interrupt', function (details) { details.id = this.id if (!this._interruptProcess) { console.log('----default interrupt processor for mcp instance----') console.log(this.id) console.dir(details) } else this._interruptProcess(details) }) } interruptProcessor(func) {this._interruptProcess = func} } // end of MCP230XX Class // commands to be added to pin command functions const ipincommands= { interrupt: { reset: async function (port) { log.info(`resetting interrupt for port ${port || 'A'},${this.id}`) return await this.bus.read(port!=='B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register }, // given a gpio interrupt then push a packet with cmd: 'pin.interrupt.find' and pin: the gpio pin number find: async function (inter) { // inter is a hash packet if(this.ready){ // protects tripped interrupt before it's fully initialized and reset log.info({packet:inter},'finding mcp pin which caused interrupt') let packet = {pins:'all',reg:'intf'} packet.port = inter.port || this[inter.pin].mport || 'A' let res = await this.pin.status(packet) log.info('found pin now resetting mcp port interrupt') await this.pin.interrupt.reset(packet.port) if (!res.status) 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 res.state = (await this.pin.status(packet)).status.pins[0][1] res.port = packet.port res.count = inter.count res.inter = inter.pin delete res.status this.emit('interrupt',res) return res } } } }