reorganizes commands

add new server/socket namespace "commands" for server side base module
add new namespace "commands" for consumer side for interrupt version of module
master
David Kebler 2018-07-31 10:29:11 -07:00
parent 1497491d9c
commit 95926a892c
5 changed files with 162 additions and 146 deletions

View File

@ -4,31 +4,35 @@
*/ */
import { MCP230XXi } from '../src' import { MCP230XXi } from '../src'
import { MCP230XX } from '../src' import { MCP230XX } from '../src'
import Base from '@uci/base'
const BUS_HOST = 'sbc' 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 BUS_PORT = 1776 // 1776 is default port for i2c-bus module
const SW_ADDRESS = 0x25 // 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 const RY_ADDRESS = 0x27 // 1776 is default port for i2c-bus module
// let chip8 = new MCP230XX({id:'mcp8-27', address:0x27, nmcp: { path: '/opt/sockets/mcp2.sock' }}) let announce = new Base({id:'switch:announce'})
// let sw17 = new MCP230XXi([9,10],{id:'sw17', chip17:true, host:BUS_HOST, address:SW_ADDRESS, iport:9000, 10:{mport:'B'}})
let sw17 = new MCP230XXi([9,10],{id:'sw17', chip17:true, host:BUS_HOST, address:SW_ADDRESS+1, iport:true, 10:{mport:'B'}}) 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, iport:true}) // 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}) // let ry8 = new MCP230XX({id:'ry8', host:BUS_HOST, address:RY_ADDRESS})
sw17.reply = () => {} const reply = { reply: () => {} }
ry8.reply = () => {} // ry8.c = reply;
sw8.reply = () => {} sw17.c=reply
// sw8.c= reply
function iprocess(details) { function iprocess(details) {
console.log('--common interrupt processor--') console.log('--common interrupt processor--')
console.log(details) console.log(details)
action(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)
} }
async function action (details) { // just something to do
async function local_action (details) {
if (details.id === 'sw17') { if (details.id === 'sw17') {
await ry8.pin.state.toggle({pins:details.pin}) await ry8.pin.state.toggle({pins:'2,4,6,8'})
} }
if (details.id === 'sw8') { if (details.id === 'sw8') {
if (details.pin===1) { if (details.pin===1) {
@ -46,19 +50,15 @@ async function action (details) {
(async () => { (async () => {
await sw17.init() await sw17.init()
let cfg = {port:'B',pins:'1', cfg:'toggle_switch_pulldown'}
console.log(await sw17.pin.cfg(cfg))
sw17.interruptProcessor(iprocess) sw17.interruptProcessor(iprocess)
// await sw8.init()
// sw8.interruptProcessor(iprocess)
await sw8.init() //
sw8.interruptProcessor(iprocess) //
// await ry8.init()
// let packet = {pins:'all', cfg:'output'}
await ry8.init() // await ry8.pin.cfg(packet)
let packet = {pins:'all', cfg:'output'}
await ry8.pin.cfg(packet)
})().catch(err => { })().catch(err => {
console.error('FATAL: UNABLE TO START SYSTEM!\n',err) console.error('FATAL: UNABLE TO START SYSTEM!\n',err)

View File

@ -1,10 +1,11 @@
{ {
"name": "@uci/mcp", "name": "@uci/mcp",
"main": "src", "main": "src",
"version": "0.1.4", "version": "0.1.8",
"description": "Classes and Helper Functions for using the MCP chip on I2C Bus", "description": "Classes and Helper Functions for using the MCP chip on I2C Bus",
"scripts": { "scripts": {
"relays": "node -r esm examples/relays", "relays": "node -r esm examples/relays",
"swrl": "UCI_LOG=true node -r esm examples/mcp-switch-relay | pino-colada",
"swr": "node -r esm examples/mcp-switch-relay", "swr": "node -r esm examples/mcp-switch-relay",
"test": "./node_modules/.bin/mocha --reporter list --timeout 30000", "test": "./node_modules/.bin/mocha --reporter list --timeout 30000",
"testw": "./node_modules/.bin/mocha --reporter list -- watch --timeout 30000", "testw": "./node_modules/.bin/mocha --reporter list -- watch --timeout 30000",

View File

@ -3,7 +3,8 @@
import _ from '@uci/utils/src/byte' import _ from '@uci/utils/src/byte'
import { CHIP, PIN } from './config' import { CHIP, PIN } from './config'
export const chip = { export default {
chip:{
// for custom chip configuration set packet.cfg='custom' then packet.setting should be a // for custom chip configuration set packet.cfg='custom' then packet.setting should be a
// configuration byte with given format ('STR' by defaul). // configuration byte with given format ('STR' by defaul).
cfg: async function(packet){ cfg: async function(packet){
@ -27,13 +28,13 @@ export const chip = {
if (bus.error) return bus if (bus.error) return bus
return { cmd:'reply', response:_.byteFormat(bus.response,{in:'DEC',out:'STR'}) } return { cmd:'reply', response:_.byteFormat(bus.response,{in:'DEC',out:'STR'}) }
} }
} },
// Individual Pin Configurations // Individual Pin Configurations
// set is for cfg: 'custom' assume a setting is zero unless given // 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} } // 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 // first get the current byte (pin) state for that setting
export const pin = { pin:{
cfg: async function(packet){ cfg: async function(packet){
let cfg = {} let cfg = {}
let reply = { cmd:'reply', status:{} } let reply = { cmd:'reply', status:{} }
@ -100,6 +101,8 @@ export const pin = {
} }
} // end pin. } // end pin.
}
const parsePins = function(pins) { const parsePins = function(pins) {
if (typeof pins==='number') pins = [pins] if (typeof pins==='number') pins = [pins]
if (typeof pins==='string') { if (typeof pins==='string') {

View File

@ -1,6 +1,6 @@
import Device from '@uci/i2c-device' import Device from '@uci/i2c-device'
// import Device from '../../uci-i2c-device/src/device-packet' // import Device from '../../uci-i2c-device/src/device-packet'
import { pin, chip } from './commands' import commands from './commands'
import logger from '@uci/logger' import logger from '@uci/logger'
let log = {} let log = {}
@ -10,13 +10,15 @@ export default class MCP230XX extends Device {
super(opts) super(opts)
log = logger({file:'src/mcp230xx.js',class:'MCP230XX',name:'mcp',id:this.id}) log = logger({file:'src/mcp230xx.js',class:'MCP230XX',name:'mcp',id:this.id})
this.chip17 = opts.chip17 this.chip17 = opts.chip17
this.pin = this.bindFuncs(pin) this.commands = this.bindFuncs(commands)
this.chip = this.bindFuncs(chip) 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
} }
async init(){ async init(){
await super.init() await super.init()
let res = await this.chip.cfg({}) let res = await this.chipcfg({})
let cfg = this.chip17 ?'10100010':'00100010' let cfg = this.chip17 ?'10100010':'00100010'
if (res.response !==cfg ) throw `could not configure mcp chip at ${this.address}=0x${this.address.toString(16)}` if (res.response !==cfg ) throw `could not configure mcp chip at ${this.address}=0x${this.address.toString(16)}`
} }

View File

@ -4,56 +4,64 @@ import { byteFormat } from '@uci/utils/src/byte'
import logger from '@uci/logger' import logger from '@uci/logger'
let log = {} let log = {}
// sockets:'inter#s>t', inter:{port:INTERRUPT_PORT} // if opts.iport not set then will be generated based on pin number
export default class MCP230XXi extends MCP230XX { export default class MCP230XXi extends MCP230XX {
constructor(pins,opts) { constructor(pins,opts) {
if (typeof opts.iport ==='number' || opts.ipath) { if (typeof opts.iport ==='number' || opts.ipath) {
if (typeof opts.iport ==='number') { if (typeof opts.iport ==='number') {
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#s>t' opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>t'
opts.inter = {port:opts.iport} opts.inter = {port:opts.iport}
opts.inter.host = opts.ihost || opts.host
} }
if (opts.ipath) { if (opts.ipath) {
opts.inter = { path: opts.ipath || 'interrupt'} opts.inter = { path: opts.ipath || 'interrupt'}
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#s>n' opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>n'
} }
} }
else { else {
pins.forEach( pin => { pins.forEach( (pin,index) => {
let ipin = 'i'+pin let ipin = 'i'+pin
opts[ipin] = opts[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') { if (opts[ipin].port || opts.iport !=='number') {
opts[ipin].port = opts[ipin].port || opts.iport opts[ipin].port = opts[ipin].port || opts.iport
if (typeof opts[ipin].port !=='number') opts[ipin].port = 9000 + pin if (typeof opts[ipin].port !=='number') opts[ipin].port = 9000 + pin
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + ipin +'#s>t' 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 // either on the same host as bus and interrupt or not - no need for both
else { else {
opts[pin].path = opts[pin].path || opts.ipath opts[pin].path = opts[pin].path || opts.ipath
if(!opts[pin].path) Object.assign(opts[pin],{path:'interrupt:'+pin}) if(!opts[pin].path) Object.assign(opts[pin],{path:'interrupt:'+pin})
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + pin+'#s>n' opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + pin+'#c>n'
} }
}) })
} }
super(opts) 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 => { pins.forEach(pin => {
this[pin] = opts[pin] || {} this[pin] = opts['i'+pin] || {}
}) })
this.pins = pins this.pins = pins
log = logger({file:'src/mcp230xxi.js',class:'MCP230XXi',name:'mcp',id:this.id}) Object.assign(this.commands.pin, this.bindFuncs(ipincommands)) // add interrupt pin commands to base set in "command.js"
Object.assign(this.pin, this.bindFuncs(pin)) // add interrupt pin commands to base set in "command.js" this.addNamespace('commands','c')
this._interruptProcess = null this._interruptProcess = null
this.ready = false
log.info({opts:opts, pins:pins}, 'options for mcp interrupt processor')
} }
async init(){ async init(){
await super.init() await super.init()
this.pins.forEach(async pin => { this.pins.forEach(async pin => {
// console.log(this.id,pin,this[pin]) let cfg = {port:this[pin].mport||'A',pins:this[pin].pins||'all', cfg:this[pin].type ||'toggle_switch'}
// let cfg = {port:this[pin].mport||'A',pins:this[pin].pins||'all', cfg:this[pin].type ||'toggle_switch'} await this.pin.cfg(cfg)
// console.log(cfg) log.info('resetting mcp port for corresponding gpio pin')
await this.pin.cfg({port:this[pin].mport||'A',pins:this[pin].pins||'all', cfg:this[pin].type ||'toggle_switch'}) await this.pin.interrupt.reset(this[pin].mport)
this.pin.interrupt.reset(this[pin].mport) this.ready=true
}) })
this.on('interrupt', function (details) { this.on('interrupt', function (details) {
@ -71,22 +79,23 @@ export default class MCP230XXi extends MCP230XX {
} // end of MCP230XX Class } // end of MCP230XX Class
const pin = { interrupt: { // commands to be added to pin command functions
const ipincommands= { interrupt: {
reset: async function (port) { reset: async function (port) {
console.log('resetting interrupt for port',port || 'A',this.id) 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 return await this.bus.read(port!=='B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register
}, },
find: async function (inter) { // given a gpio interrupt then push a packet with cmd: 'pin.interrupt.find' and pin: the gpio pin number
// console.dir(inter) 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'} let packet = {pins:'all',reg:'intf'}
packet.port = inter.port || this[inter.pin].mport || 'A' packet.port = inter.port || this[inter.pin].mport || 'A'
// console.log(`${inter.count}th interrupt fired, pin:${inter.pin}`)
// console.log('packet to read port\n',packet.port)
let res = await this.pin.status(packet) let res = await this.pin.status(packet)
this.pin.interrupt.reset(packet.port) 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'} if (!res.status) return {error:'no pin associated with interrupt'}
let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' }) let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' })
// console.log('pin and port that caused the interrupt', pin, packet.port)
res.pin = pin[0] res.pin = pin[0]
packet.pins = pin[0] packet.pins = pin[0]
packet.reg = null packet.reg = null
@ -100,3 +109,4 @@ const pin = { interrupt: {
} }
} }
} }
}