reorganizes commands
add new server/socket namespace "commands" for server side base module add new namespace "commands" for consumer side for interrupt version of modulemaster
parent
1497491d9c
commit
95926a892c
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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:{} }
|
||||||
|
@ -98,7 +99,9 @@ export const pin = {
|
||||||
return this.pin._state(packet,'toggle')
|
return this.pin._state(packet,'toggle')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end pin.
|
} // end pin.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const parsePins = function(pins) {
|
const parsePins = function(pins) {
|
||||||
if (typeof pins==='number') pins = [pins]
|
if (typeof pins==='number') pins = [pins]
|
||||||
|
|
|
@ -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)}`
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -98,5 +107,6 @@ const pin = { interrupt: {
|
||||||
this.emit('interrupt',res)
|
this.emit('interrupt',res)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue