refactoring to include port/pin library. Moved some examples to become tests within repo

master
David Kebler 2017-05-26 08:14:29 -07:00
parent 0fb62e2db1
commit 1a97705ab5
11 changed files with 605 additions and 178 deletions

View File

@ -1,13 +0,0 @@
{
"globals": {
"Debug" : true,
/* MOCHA */
"describe" : false,
"it" : false,
"xit" : false,
"before" : false,
"beforeEach" : false,
"after" : false,
"afterEach" : false
}
}

View File

@ -1,70 +0,0 @@
{
// https://gist.github.com/connor/1597131
// Globals - import repo spectific globals
"extends": "./.jshglobals",
// Settings
"passfail" : false, // Stop on first error.
"maxerr" : 100, // Maximum error before stopping.
// Predefined globals whom JSHint will ignore.
"browser" : true, // Standard browser globals e.g. `window`, `document`.
"node" : true,
"rhino" : false,
"couch" : false,
"wsh" : true, // Windows Scripting Host.
"jquery" : true,
"prototypejs" : false,
"mootools" : false,
"dojo" : false,
// Development.
"debug" : false, // Allow debugger statements e.g. browser breakpoints.
"devel" : true, // Allow developments statements e.g. `console.log();`.
// ECMAScript
"esversion" : 6, //use this in new version of jshint
"strict" : false, // Require `use strict` pragma in every file.
"globalstrict" : false, // Allow global "use strict" (also enables 'strict').
// The Good Parts.
"asi" : true, // Tolerate Automatic Semicolon Insertion (no semicolons).
"laxbreak" : true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
"bitwise" : true, // Allow bitwise operators (&, |, ^, etc.).
"boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
"curly" : true, // Require {} for every new block or scope.
"eqeqeq" : true, // Require triple equals i.e. `===`.
"eqnull" : false, // Tolerate use of `== null`.
"evil" : false, // Tolerate use of `eval`.
"expr" : false, // Tolerate `ExpressionStatement` as Programs.
"forin" : false, // Tolerate `for in` loops without `hasOwnPrototype`.
"immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
"latedef" : false, // Prohipit variable use before definition.
"loopfunc" : false, // Allow functions to be defined within loops.
"noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
"regexp" : true, // Prohibit `.` and `[^...]` in regular expressions.
"regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`.
"scripturl" : true, // Tolerate script-targeted URLs.
"shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
"supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
"undef" : true, // Require all non-global variables be declared before they are used.
// Personal styling preferences.
"newcap" : false, // Require capitalization of all constructor functions e.g. `new F()`.
"noempty" : true, // Prohibit use of empty blocks.
"nonew" : true, // Prohibit use of constructors for side-effects.
"nomen" : true, // Prohibit use of initial or trailing underbars in names.
"onevar" : false, // Allow only one `var` statement per function.
"plusplus" : false, // Prohibit use of `++` & `--`.
"sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
"trailing" : true, // Prohibit trailing whitespaces.
"white" : false, // Check against strict whitespace and indentation rules.
"indent" : 2 // Specify indentation spacing
}

View File

@ -1,8 +0,0 @@
let opts = {
dirname: __dirname + '/lib',
// http://stackoverflow.com/questions/2078915/a-regular-expression-to-exclude-a-word-string
filter: /^(?!index)([^\.].*)\.js?$/,
recursive: false,
merge: true // remove or comment to have each file in /lib be a prop/key in library...see node-require-all
}
module.exports = require('require-all')(opts);

View File

@ -1,9 +1,9 @@
'use strict'
const Device = require('uci-dev').Device,
Port = require('uci-gpio').Port,
_u = require('uci-utils'),
pause = _u.pPause,
aseq = _u.aSeq
const Device = require('@uci/i2c').Device,
Port = require('./lib/port-pin').Port, // classes for MCP port and pins
pinConfigs = require('./lib/port-pin').configs, // for export so pinConfigs can be accessed at runtime
_u = require('@uci/utils'),
pause = _u.pPause
class MCP23008 extends Device {
constructor(busObj, i2cAddress, opts = {}) {
@ -77,18 +77,18 @@ class MCP23008 extends Device {
out: 'DEC'
})
return this.write(chip_config.cmd, byte)
.then(() => Promise.resolve(`mcp chip config: reg $ { chip_config.cmd } byte $ { byte } written `))
.then(() => Promise.resolve('mcp chip config: reg $ { chip_config.cmd } byte $ { byte } written '))
}
// pin configurations should already be set before calling
writePinsCfg() {
// console.log(`writing mcp pins config ${this.id}`)
let jobs = [];
let jobs = []
for (let port in this.ports) {
for (let setting in registers.pin_config) {
let reg = registers.pin_config[setting]
// TODO 0x10 should be based on chip config
let byte = 0;
let byte = 0
let pins = this.ports[port].allPins
for (let i = 0; i < 8; i++) {
let pin = pins[i]
@ -109,9 +109,9 @@ class MCP23008 extends Device {
// return u_.byteFormat(this.cur, { in: this.format, out: format })
// }
async readPort(port, cmd = "gpio") {
async readPort(port, cmd = 'gpio') {
if ('AB'.indexOf(port) === -1) {
cmd = port ? port : "gpio"
cmd = port ? port : 'gpio'
port = 'A'
}
let result = await this.read(portReg(registers.pin_cmd[cmd], port))
@ -126,13 +126,13 @@ class MCP23008 extends Device {
if (op !== 'force') {
byte = this.ports[port].state.bwOp(byte, op)
}
console.log("byte to write decimal \n", byte)
console.log('byte to write decimal \n', byte)
console.log(`byte to write \n ${_u.byteFormat(byte, { in: 'DEC', out: 'PLC' })}`)
await this.write(portReg(registers.pin_cmd.gpio, port), byte)
//update the saved state
this.ports[port].state.value = byte
console.log("\n\n")
console.log('\n\n')
}
async on(pins, port, format) {
@ -188,8 +188,6 @@ class MCP23008 extends Device {
} // end 23008
module.exports.MCP23008 = MCP23008
class MCP23017 extends MCP23008 {
constructor(busObj, i2cAddress, opts) {
super(busObj, i2cAddress, opts)
@ -223,9 +221,15 @@ class MCP23017 extends MCP23008 {
}
} // end MCP23017 Class
module.exports.MCP23017 = MCP23017
// ==============================
// EXPORTS
module.exports = {
MCP23008,
MCP23017,
pinConfigs
}
// Local Functions and Settings=============================
function portReg(reg, port) {
// TODO what to return for port B will depend on chip configuration

176
lib/port-pin.js Normal file
View File

@ -0,0 +1,176 @@
'use strict'
const _ = require('@uci/utils')
class Pin {
constructor(address, opts = {}) {
// at a minimum address is required
this.address = new _.Byte(address, opts.fmt)
// a unique pin id MUST be supplied in opts or it must be set afterwards!
this.id = opts.pid
// a custom pin configuration can be passed or choosen from one of the sets, if neither than the default output config is chosen
if (opts.pin_cfg_default) {
if (_.keyExists(config_sets, opts.pin_cfg_default)) {
this.config = _.clone(config_sets[opts.pin_cfg_default])
} else {
console.log(`WARNING config set ${opts.pin_cfg_default} not found using default output set`)
this.config = _.clone(config_sets.output)
}
} else {
this.config = _.clone(config_sets.output)
}
// after setting a default overwrite part or all of pin config with custom
if (opts.pinConfig) {
this.config = Object.assign(this.config, opts.pinConfig)
}
// this.cfgSet = false // set to true when for sure the configuration has been written, changed to false when config is changed.
}
//getters and setters
get adr() {
return this.address
}
set adr(add) {
if (Number.isInteger(add)) {
this.address.reset(add)
} else {
this.address.reset(add.val, add.fmt)
}
}
get pid() { return this.id }
set pid(pid) { this.id = pid }
// config getters and setters
get cfg() {
return this.config
}
set cfg(config) {
this.config = _.merge(this.config, config) // this merges partial changes
// write the config here.
}
show() {
console.log(`=====Pin ${this.id} =====\nAddress ${this.address.toFmt('HEX')}`)
console.log('Conifguration: ', this.config)
}
} // End GPIO Pin
//======================
// A port of 8 GPIO pins
class Port {
constructor(opts) {
if (opts) {
this.reverse = opts.reverse ? opts.reverse : false
this.id = opts.portID ? opts.portID : ''
this.desc = opts.portDesc ? opts.portDesc : ''
} else {
opts = {}
this.reverse = false
}
// Create group of 8 pins for port
this.pins = new Array(8)
let pid = ''
for (let i = 0; i < 8; i++) {
if (opts.pids) {
pid = opts.pids[i]
} else {
pid = this.reverse ? 8 - i : i + 1
}
// using default decimal for pin addresses
this.pins[i] = new Pin(Math.pow(2, i), _.merge(opts, { pid: pid }))
// console.log(`\n\n====PORT ${this.id} =====`)
// this.pins[i].show()
}
}
// return a handle to all pins on a port
get allPins() {
return this.pins
}
// return handle to a port's pin from id
pin(id) {
for (let i = 0; i < 8; i++) {
if (this.pins[i].id === id) {
return this.pins[i]
}
}
return false
}
// return pin's id on a port from address
pid(address) {
if (Number.isInteger(address)) { address = new _.Byte(address) }
let i = address.toFmt('PLC')[0] - 1
return this.pins[i].id
}
} // end GPIO Port CLass
//====================
// needs to take current pin and pick out details and make a call the contstructor.
// clone(adr, alias) {
// let newPin = _.clone(this)
// newPin.address = adr
// newPin.alias = alias
// return newPin
// }
// return list of all pin configs, handle to particular config or adding of custom pin configuration at runtime
function configs(cfg) {
if (_.isString(cfg)) {
if (cfg === 'list') {
return Object.keys(config_sets)
}
if (_.keyExists(config_sets, cfg)) {
return config_sets[cfg]
}
return 'configuration no found'
}
_.merge(config_sets, cfg)
// console.log(config_sets)
return `pin configuration ${Object.keys(cfg)} added to configuration set`
}
module.exports = {
Port,
Pin,
configs
}
let config_sets = {
output: {
dir: 0, // 0 output,1 input
ivrt: 0,
pullup: 0,
intr: 0, // if intr = 0 usedef,deval not used
usedef: 0, // if usedef = 0 defval not used
defval: 0
},
toggle_switch: {
dir: 1, // 0 output,1 input
ivrt: 1, // for reading let 1 be zero and vice versa
pullup: 1,
intr: 1, // if intr = 0 usedef,deval not used
usedef: 0, // if usedef = 0 defval not used
defval: 0
},
momentary_switch: {
dir: 1, // 0 output,1 input
ivrt: 1, // for reading let 1 be zero and vice versa
pullup: 1,
intr: 1, // if intr = 0 usedef,deval not used
usedef: 1, // if usedef = 0 defval not used
defval: 1
}
}

View File

@ -1,5 +1,6 @@
{
"name": "uci-mcp",
"name": "@uci/mcp",
"main": "lib/mcp23008-17.js",
"version": "0.0.1",
"description": "classes and functions for use the MCP chips",
"main": "index.js",
@ -24,10 +25,7 @@
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
"dependencies": {
"p-series": "^1.0.0",
"require-all": "git+https://github.com/dkebler/node-require-all.git#merge",
"uci-dev": "0.0.1",
"uci-gpio": "0.0.1",
"uci-utils": "0.0.1"
"@uci/utils": "0.0.1"
},
"devDependencies": {
"chai": "^3.5.0",

148
test/cntrl.js Normal file
View File

@ -0,0 +1,148 @@
const Bus = require('@uci/i2c').Bus,
MCP = require('@uci/mcp'),
Interrupt = require('@uci/interrupt').Interrupt,
_ = require('@uci/utils'),
pause = _.pPause,
aseq = _.aSeq
let bus = new Bus()
// let itrProcess = function (port) {
// return this.read(portReg(0x07, port)).then(resp => {
// console.log(`port ${port} resp ${resp}`)
// let sw = this.pid(resp, port)
// console.log('switch fired', sw)
// this.pinRead(sw, { cmd: 'intcap' }).then((state) => {
// console.log('switch state at interrupt', state)
// return Promise.all([
// updateRelays(sw, state),
// this.read(portReg(0x07, port)).then(_.pDelay(100)).then(() => { return this.inter(port).reset() })
// ])
// })
// })
// }
let itrProcess1 = function (port) {
console.log(`handler1 fired for ${this.id} on port ${port}`)
this.interruptReset(port)
return Promise.resolve("handler fired promise returned")
}
let itrProcess2 = function (port) {
console.log(`handler2 fired for ${this.id} on port ${port}`)
this.interruptReset(port)
return Promise.resolve("handler fired promise returned")
}
let LOAD_BANKS = [
{ id: 'lb1', address: 0x24, desc: 'left cabinet lower bank' },
{ id: 'lb3', address: 0x25, desc: 'left cabinet upper bank' },
{ id: 'lb2', address: 0x26, desc: 'right cabinet lower bank' },
{ id: 'lb4', address: 0x27, desc: 'right cabinet upper bank' }
]
let loadBanks = LOAD_BANKS.map((bank) => {
return new MCP.MCP23017(bus, bank.address, {
pin_cfg_default: 'output',
id: bank.id,
desc: bank.desc ? bank.desc : ""
})
})
// loadBanks.forEach(bank => console.log(bank.id, bank.desc))
let SWITCH_BANKS = [
{ id: 'sb4', address: 0x23, desc: 'bottom left', interruptA: 19, interruptB: 26 }, // red, orange
{ id: 'sb1', address: 0x20, desc: 'upper right', interruptA: 12, interruptB: 16 }, // purple, blue
{ id: 'sb2', address: 0x21, desc: 'upper left', interruptA: 20, interruptB: 21 }, // yellow, orange
{ id: 'sb3', address: 0x22, desc: 'bottom right', interruptA: 6, interruptB: 13 } //black, brown
]
let switchBanks = SWITCH_BANKS.map((bank) => {
return new MCP.MCP23017(bus, bank.address, {
pin_cfg_default: 'toggle_switch',
id: bank.id,
desc: bank.desc ? bank.desc : "",
interrupt: bank.interrupt ? new Interrupt(bank.interrupt, bank) : null,
interruptA: bank.interruptA ? new Interrupt(bank.interruptA, itrProcess1) : null,
interruptB: bank.interruptB ? new Interrupt(bank.interruptB, itrProcess2) : null,
pidsA: ['sw1', 'sw2', 'sw3', 'sw4', 'sw5', 'sw6', 'sw7', 'sw8'],
pidsB: ['sw9', 'sw10', 'sw11', 'sw12', 'sw13', 'sw14', 'sw15', 'sw16']
// chip_config: 'oneint'
})
})
// switchBanks.forEach(bank => console.log(bank.id, bank.desc, bank.inter('A').pin, bank.inter('B').pin))
async function init(bank) {
await bank.init()
console.log(`${bank.id} ${bank.desc} is initialized`)
// if (bank.id.charAt(0) === 's') {
// console.log(`bank ${bank.id} pi interrupt set for port A: on rpi pin ${bank.inter('A').pin_number}, for port B on rpi pin ${bank.inter('A').pin_number}`)
// console.log(`rpi pin mode port A ${bank.inter('A').sbc_interrupt.getMode()}`)
// }
}
async function start(bank) {
await bank.start()
}
async function go() {
await aseq(loadBanks.concat(switchBanks), init)
await aseq(loadBanks.concat(switchBanks), start)
}
go().catch(err => console.log(err))
// init relay board
// bus.qAdd(relays.init()
// // .then((resp) => { console.log('relays back from init', resp) })
// .catch((err) => console.log('====error====\n', err))
// )
// init switch board
// bus.qAdd(sw1_16.init()
// .then((resp) => {
// console.log('switch initilized finished\n', resp)
// return sw1_16.start()
// // .then(resp => console.log(resp))
// })
// // .then(console.log(sw1_16.inter().fire()))
// .catch((err) => console.log('====error switch ====\n', err))
// )
//
// let test = async(function () {
// return await (delay())
// })
//
// console.log(test())
// function temp() { return Promise.resolve('test') }
// let resp = await relays.init()
// console.log("relays ready", resp )
// console.log( await delay(5000) )
// sw1_16.inter('A').on('fired', (hook) => {
// console.log('interrupt fired', hook)
// process.bind(sw1_16)('A')
// .catch(err => console.log("error:", err))
// })
//
// sw1_16.inter('B').on('fired', (hook) => {
// console.log('interrupt fired', hook)
// process.bind(sw1_16)('B')
// .catch(err => console.log("error:", err))
// })
// function updateRelays(sid, state) {
// console.log(`sw ${sid} state ${state}`)
// return bus.qAdd(relays.write(0x09, 0x03 * state))
// // return _.pDelay(100).then((resp) => { console.log('relays updated') })
// }
//
// function portReg(reg, port) {
// if (port === 'B') { return reg += 0x10 } else { return reg }
// }

63
test/gpio.test.js Normal file
View File

@ -0,0 +1,63 @@
'use strict'
const expect = require('chai').expect,
gpio = require('../lib/gpio')
let pin = new gpio.Pin(128)
describe('GPIO Pin Class - ', function () {
it('Verify getter and setter ', function () {
expect(pin.cfg, 'config getter failed').to.deep.equal(gpio.configs('output'))
expect(pin.cfg.intr, 'config get subkeys failed').to.equal(0)
pin.cfg = gpio.configs('toggle_switch')
expect(pin.cfg, 'config setter failed').to.deep.equal(gpio.configs('toggle_switch'))
expect(pin.adr.value, 'pin address getter failed').to.equal(128)
expect(pin.adr.fmt, 'pin address format getter failed').to.equal('DEC')
expect(pin.id, 'pin id default from address failed').to.equal(8)
pin.adr = {
'val': 20,
'fmt': 'HEX'
}
expect(pin.adr.value, 'pin address setter failed').to.equal(20)
expect(pin.adr.fmt, 'pin address format setter failed').to.equal('HEX')
pin.id = 2
expect(pin.id, 'pin id setter failed').to.equal(2)
pin.adr = 32
expect(pin.adr.value, 'pin address setter failed').to.equal(32)
expect(pin.adr.fmt, 'pin address format setter failed').to.equal('DEC')
})
it('should merge partial config change', function () {
pin.cfg = gpio.configs('output')
pin.cfg = { dir: 15 }
let merged = { dir: 15, ivrt: 0, pullup: 0, intr: 0, usedef: 0, defval: 0 }
expect(pin.cfg, 'single config value change failed').to.deep.equal(merged)
})
// TODO waiting on new clone function
// it('should clone a new Pin with change of address', function () {
// expect(newPin.adr.val, "clone pin failed").to.equal(4)
// expect(newPin.cfg.dir, "clone pin failed").to.equal(15)
// })
})
let port = new gpio.Port({ portID: 'A1' })
describe('GPIO Port Class - ', function () {
it('should set the pin ids and addresses by default', function () {
expect(port.pin(7).id, 'a pin\'s id failed').to.equal(7)
expect(port.pin(7).adr.value, 'id and address don\'t match').to.equal(64)
})
let port2 = new gpio.Port({ reverse: true })
it('reversing pin number order should work', function () {
expect(port2.pin(2).adr.value, 'reversing pin numbers failed').to.equal(64)
})
//TODO add a pin map for the port so pins could be arranged in any order
})

View File

@ -1,80 +1,80 @@
'use strict'
'use strict'
const expect = require('chai').expect,
_u = require('uci-utils'),
MCP = require('../lib/mcp23008-17')
const expect = require('chai').expect,
_u = require('@uci/utils'),
MCP = require('../lib/mcp23008-17')
const bus = {}
const bus = {}
const config_sets = {
output: {
dir: 0, // 0 output,1 input
ivrt: 0,
pullup: 0,
intr: 0, // if intr = 0 usedef,deval not used
usedef: 0, // if usedef = 0 defval not used
defval: 0
},
toggle_switch: {
dir: 1, // 0 output,1 input
ivrt: 1, // for reading let 1 be zero and vice versa
pullup: 1,
intr: 1, // if intr = 0 usedef,deval not used
usedef: 0, // if usedef = 0 defval not used
defval: 0
},
momentary_switch: {
dir: 1, // 0 output,1 input
ivrt: 1, // for reading let 1 be zero and vice versa
pullup: 1,
intr: 1, // if intr = 0 usedef,deval not used
usedef: 1, // if usedef = 0 defval not used
defval: 1
}
}
const config_sets = {
output: {
dir: 0, // 0 output,1 input
ivrt: 0,
pullup: 0,
intr: 0, // if intr = 0 usedef,deval not used
usedef: 0, // if usedef = 0 defval not used
defval: 0
},
toggle_switch: {
dir: 1, // 0 output,1 input
ivrt: 1, // for reading let 1 be zero and vice versa
pullup: 1,
intr: 1, // if intr = 0 usedef,deval not used
usedef: 0, // if usedef = 0 defval not used
defval: 0
},
momentary_switch: {
dir: 1, // 0 output,1 input
ivrt: 1, // for reading let 1 be zero and vice versa
pullup: 1,
intr: 1, // if intr = 0 usedef,deval not used
usedef: 1, // if usedef = 0 defval not used
defval: 1
}
}
// console.log(bus1)
// bus1.scan((devs)=>{console.log('devices: ', devs)})
//bus1.scan().then(results=>console.log(results))
// console.log(bus1)
// bus1.scan((devs)=>{console.log('devices: ', devs)})
//bus1.scan().then(results=>console.log(results))
describe('I2C Device Classes - ', function () {
describe('I2C Device Classes - ', function () {
let mcp17 = new MCP.MCP23017(bus, 0x20, {
pin_cfg_default: 'momentary_switch',
name: 'switches 1-16'
})
let mcp17 = new MCP.MCP23017(bus, 0x20, {
pin_cfg_default: 'momentary_switch',
name: 'switches 1-16'
})
describe('MCP23017 Class - ', function () {
describe('MCP23017 Class - ', function () {
it('can set and get a single pin config on both ports', function () {
expect(mcp17.pin(1).cfg, "pin configs getter failed").to.deep.equal(config_sets.momentary_switch)
expect(mcp17.pin(8).cfg.dir, "pin config getter failed").to.equal(1)
mcp17.pin(8).cfg.dir = 0
expect(mcp17.pin(8).cfg.dir, "pin address setter failed").to.equal(0)
expect(mcp17.pin(8, 'B').cfg.dir, "pin address getter port B failed").to.equal(1)
mcp17.pin(8, 'B').cfg.dir = 0
expect(mcp17.pin(8, 'B').config.dir, "pin address setter failed").to.equal(0)
});
it('can set and get a single pin config on both ports', function () {
expect(mcp17.pin(1).cfg, 'pin configs getter failed').to.deep.equal(config_sets.momentary_switch)
expect(mcp17.pin(8).cfg.dir, 'pin config getter failed').to.equal(1)
mcp17.pin(8).cfg.dir = 0
expect(mcp17.pin(8).cfg.dir, 'pin address setter failed').to.equal(0)
expect(mcp17.pin(8, 'B').cfg.dir, 'pin address getter port B failed').to.equal(1)
mcp17.pin(8, 'B').cfg.dir = 0
expect(mcp17.pin(8, 'B').config.dir, 'pin address setter failed').to.equal(0)
})
});
})
let mcp8 = new MCP.MCP23008(bus, 0x21, {
pin_cfg_default: 'toggle_switch',
name: 'test 1-8'
})
let mcp8 = new MCP.MCP23008(bus, 0x21, {
pin_cfg_default: 'toggle_switch',
name: 'test 1-8'
})
describe('MCP23008 Class - ', function () {
describe('MCP23008 Class - ', function () {
it('can set and get a single pin config', function () {
expect(mcp8.pin(1).cfg, "pin configs getter failed").to.deep.equal(config_sets.toggle_switch)
expect(mcp8.pin(8).cfg.dir, "pin address getter failed").to.equal(1)
expect(mcp8.pin(8).cfg.ivrt, "pin address getter failed").to.equal(1)
expect(mcp8.pin(8).cfg.usedef, "pin address getter failed").to.equal(0)
mcp8.pin(8).cfg.dir = 0
expect(mcp8.pin(8).cfg.dir, "pin address setter failed").to.equal(0)
expect(mcp8.pin(8).cfg.ivrt, "pin address getter failed").to.equal(1)
});
it('can set and get a single pin config', function () {
expect(mcp8.pin(1).cfg, 'pin configs getter failed').to.deep.equal(config_sets.toggle_switch)
expect(mcp8.pin(8).cfg.dir, 'pin address getter failed').to.equal(1)
expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1)
expect(mcp8.pin(8).cfg.usedef, 'pin address getter failed').to.equal(0)
mcp8.pin(8).cfg.dir = 0
expect(mcp8.pin(8).cfg.dir, 'pin address setter failed').to.equal(0)
expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1)
})
});
})
});
})

44
test/relays.js Normal file
View File

@ -0,0 +1,44 @@
const Bus = require('@uci/i2c').Bus,
MCP = require('../lib/mcp'),
pause = require('@uci/utils').pPause
let bus = new Bus()
let ADDRS = [0x24, 0x25, 0x26, 0x27]
let relayBanks = ADDRS.map(devAddr => {
return new MCP.MCP23017(bus, devAddr, {
pin_cfg_default: 'output',
desc: `relays at i2c address ${devAddr.toString(16)}`,
stateB: 255, // should be read from persistant state file for when power goes out
stateA: 255
})
})
async function go(port = 'A') {
let time = 1
await relayBanks[0].init()
await pause(time * 1000)
await relayBanks[0].allOff(port)
await pause(time * 1000)
await relayBanks[0].on([1, 5, 8], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].on([1, 2, 5, 7, 8], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].off([1, 3, 5, 8], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].off([1, 3, 5, 8, 7, 2], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].toggle([1, 5, 7], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].toggle([1, 5, 8], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].toggle([8], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].force([3, 4], port, 'PLC')
await pause(time * 1000)
await relayBanks[0].allOn(port)
}
go('B') // .then(resp => console.log(resp))
.catch(reason => console.error(reason))

85
test/test-relays.js Normal file
View File

@ -0,0 +1,85 @@
const Bus = require('@uci/i2c').Bus,
MCP = require('@uci/mcp'),
_ = require('@uci/utils'),
pause = _.pPause,
pSeries = require('p-series')
const a = require('awaiting')
let bus = new Bus()
let ADDRS = [0x24, 0x25, 0x26, 0x27],
W = 0x09,
R = 0x0A,
WAIT = 1000
let relayBanks = ADDRS.map(devAddr => {
return new MCP.MCP23017(bus, devAddr, {
pin_cfg_default: 'output',
desc: `relays at i2c address ${devAddr.toString(16)}`
})
})
async function testbank(bank) {
await bank.init()
console.log(`initialized ${bank.desc}...now testing device write and read`)
for (let port in bank.ports) {
let pinAddr = 0
console.log(`Testing bank:${bank.desc} port:${port}`)
for (let i = 0; i < 8; i++) {
pinAddr = pinAddr + Math.pow(2, i)
let addr = pinAddr
await bank.write(portReg(W, port), pinAddr)
console.log(`Turning Port ${port} Pin(s) ${_.byteFormat(addr, { in: 'DEC', out: 'PLC' })} on`)
let resp = await bank.read(portReg(R, port), pinAddr)
// await pause(100)
console.log(`Port ${port} Pin(s) ${_.byteFormat(resp, { in: 'DEC', out: 'PLC' })} is/are on`)
await pause(100)
resp = await bank.write(portReg(W, port), 0x00)
console.log(`Clearing Relays On Port ${port} ${bank.desc}`)
await pause(500)
}
}
return `done ${bank.desc}`
}
// function seq(list, fn) {
// return async function () {
// await a.map(list, 1, fn)
// }
// }
async function aseq(list, fn) {
const resps = []
for (const item of list) {
let resp = await fn(item);
resps.push(resp)
}
return resps
}
async function testall() {
let resp = await aseq(relayBanks, testbank)
return resp
}
// testall()
// .then(resp => console.log("All done", resp))
// .catch(reason => console.error(reason));
async function readport(bank, port = 'A') {
let resp = await relayBanks[bank].readPins(port, { format: 'ARY', cmd: "olat" })
return resp
}
let bank = 1
readport(bank, 'A')
.then(resp => {
console.log(`Reading Bank ${bank} pins ${resp.value} are on`)
})
.catch(reason => console.error(reason));
//===========
function portReg(reg, port) {
if (port === 'B') { return reg += 0x10 } else { return reg }
}