From f2db2ca87cb59ee9cb407abb0d71c4723dde5357 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sun, 27 May 2018 11:41:33 -0700 Subject: [PATCH] removed old non-packet reversion and rename packet version to bus.js clean up examples update packages --- .gitignore | 2 - .npmignore | 2 + examples/bus.js | 8 +- examples/{ipc-relay.js => np-relay.js} | 0 examples/{ipc-scan.js => np-scan.js} | 1 + examples/tcp-relay.js | 51 +++++++++ examples/tcp-scan.js | 4 +- package.json | 29 ++---- readme.md | 39 +++++-- src/bus-packet.js | 115 --------------------- src/bus.js | 138 ++++++++++++++++++------- test/bus.test.js | 21 ---- 12 files changed, 203 insertions(+), 207 deletions(-) rename examples/{ipc-relay.js => np-relay.js} (100%) rename examples/{ipc-scan.js => np-scan.js} (99%) create mode 100644 examples/tcp-relay.js delete mode 100644 src/bus-packet.js delete mode 100644 test/bus.test.js diff --git a/.gitignore b/.gitignore index 2882970..ba05da9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ /node_modules/ -/coverage/ -/syncd/ *.lock diff --git a/.npmignore b/.npmignore index f16fc41..528897c 100644 --- a/.npmignore +++ b/.npmignore @@ -2,3 +2,5 @@ tests/ test/ *.test.js testing/ +examples/ +*.lock diff --git a/examples/bus.js b/examples/bus.js index 8dffb1e..4fd16c8 100644 --- a/examples/bus.js +++ b/examples/bus.js @@ -1,10 +1,10 @@ /* -* Basic i2c bus listening at 1776 (by default when tcp:true) and also named pipe +* Basic i2c bus listening at 1776 (by default when tcp:true) and also named pipe 'i2c-bus' by default in default /tmp directory * */ -import Bus from '../src/bus-packet' -// can use SOCKETS_DIR='' env variable to get a 'i2c-bus.sock' in the given environment variable path -// SOCKETS_DIR=/opt/sockets node -r @std/esm i2cbus +import Bus from '../src/bus' +// can use SOCKETS_DIR='' env variable to get a 'i2c-bus.sock' in a particular directory +// e.g. SOCKETS_DIR=/opt/sockets node -r @std/esm i2cbus ; (async () => { diff --git a/examples/ipc-relay.js b/examples/np-relay.js similarity index 100% rename from examples/ipc-relay.js rename to examples/np-relay.js diff --git a/examples/ipc-scan.js b/examples/np-scan.js similarity index 99% rename from examples/ipc-scan.js rename to examples/np-scan.js index 44bcf1b..ae0a7fa 100644 --- a/examples/ipc-scan.js +++ b/examples/np-scan.js @@ -1,3 +1,4 @@ + /* * i2c bus unix socket and client in one for demo * diff --git a/examples/tcp-relay.js b/examples/tcp-relay.js new file mode 100644 index 0000000..9e3f92a --- /dev/null +++ b/examples/tcp-relay.js @@ -0,0 +1,51 @@ +/* +* A tcp customer/client to talk with the i2c bus and scan the bus for devices +* +*/ + +const HOST = (process.env.BUS_HOST || 'sbc') +const ADDRESS = 39 + +import Base from '@uci/base' + +const delay = time => new Promise(res=>setTimeout(()=>res(),time)) +; +(async () => { + + let relays = new Base({id:'tcp-i2c-client', sockets:'tc#c>t', tc:{host:HOST, port:1776}}) + + relays.reply = async function (packet) { + console.log(`response from relays for ${packet.cmd_sent}:`,packet.args, `was ${packet.response}`) + } + await relays.init() + console.log('=============sending============') + let packet = {cmd:'read', args:{address:ADDRESS ,cmd: 0} } + console.dir(packet) + await relays.send(packet) + packet = {cmd:'write', args:{address:ADDRESS,cmd: 0, byte:0} } + console.dir(packet) + await relays.send(packet) + packet = {cmd:'read', args:{address:ADDRESS ,cmd:0} } + console.dir(packet) + await relays.send(packet) + packet = {cmd:'write', args:{address:ADDRESS,cmd: 9, byte:255} } + console.dir(packet) + await relays.send(packet) + packet = {cmd:'read', args:{address:ADDRESS ,cmd:9} } + console.dir(packet) + await relays.send(packet) + await delay(1000) + packet = {cmd:'write', args:{address:ADDRESS,cmd: 9, byte:0} } + console.dir(packet) + await relays.send(packet) + packet = {cmd:'read', args:{address:ADDRESS ,cmd:9} } + console.dir(packet) + await relays.send(packet) + + await delay(1000) + process.kill(process.pid, 'SIGTERM') + + +})().catch(err => { + console.error('FATAL: UNABLE TO START SYSTEM!\n',err) +}) diff --git a/examples/tcp-scan.js b/examples/tcp-scan.js index bb589bc..8f6a2d4 100644 --- a/examples/tcp-scan.js +++ b/examples/tcp-scan.js @@ -3,12 +3,12 @@ * */ import Base from '@uci/base' -// const HOST = '' +const HOST = (process.env.BUS_HOST || 'sbc') const delay = time => new Promise(res=>setTimeout(()=>res(),time)) ; (async () => { - let scanner = new Base({id:'tcp-i2c-client', sockets:'tc#c>t', tc:{port: 1776}}) + let scanner = new Base({id:'tcp-i2c-client', sockets:'tc#c>t', tc:{host:HOST,port: 1776}}) scanner.reply = function (packet) { let addresses = packet.response.map(device => { diff --git a/package.json b/package.json index a84178d..af31d6d 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,16 @@ { "name": "@uci/i2c-bus", - "version": "0.1.5", + "version": "0.1.6", "description": "I2c Bus Classes for Communication to I2C bus via socket or direct call", - "main": "src/bus-packet", + "main": "src/bus", "scripts": { - "irelay": "node --require esm examples/ipc-relay", - "iscan": "node --require esm examples/ipc-scan || true", + "nrelay": "node --require esm examples/np-relay", + "trelay": "node --require esm examples/tcp-relay", + "pcan": "node --require esm examples/np-scan || true", "tscan": "node --require esm examples/tcp-scan || true", "bus": "node --require esm examples/bus", - "busl": "DEBUG=true node --require esm examples/bus", - "test": "mocha -r esm test/*.test.js", - "testw": "mocha -r esm test/*.test.js --watch --recurse", - "testci": "istanbul cover ./node_modules/.bin/_mocha test/ --report lcovonly -- -R spec --recursive && codecov || true" + "busd": "DEBUG=true node --require esm examples/bus", + "busl": "UCI_LOG=true node --require esm examples/bus" }, "author": "David Kebler", "license": "MIT", @@ -30,21 +29,15 @@ }, "homepage": "https://github.com/uCOMmandIt/i2c#readme", "optionalDependencies": { - "i2c-bus": "^1.x" + "i2c-bus": "^3.x" }, "dependencies": { - "@uci/base": "^0.1.0", - "@uci/logger": "^0.0.2", + "@uci/base": "^0.1.6", + "@uci/logger": "0.0.3", "better-try-catch": "^0.6.2", "pify": "^3.0.0" }, "devDependencies": { - "chai": "^3.5.0", - "chai-as-promised": "^6.0.0", - "codecov": "^1.0.1", - "esm": "^3.0.21", - "istanbul": "^0.4.5", - "mocha": "^3.2.0", - "nodemon": "^1.14.12" + "esm": "^3.0.38" } } diff --git a/readme.md b/readme.md index 7c88bfc..3b97afe 100644 --- a/readme.md +++ b/readme.md @@ -1,10 +1,35 @@ -# uCOMmandIt I2C Bus and Device Class Library +# uCOMmandIt (UCI) - I2C Bus Class +## Raspberry Pi ONLY! -[![Build Status](https://img.shields.io/travis/uCOMmandIt/uci-pkg-template.svg?branch=master)](https://travis-ci.org/uCOMmandIt/uci-pkg-template) -[![Inline docs](http://inch-ci.org/github/uCOMmandIt/uci-pkg-template.svg?branch=master)](http://inch-ci.org/github/uCOMmandIt/uci-pkg-template) -[![Dependencies](https://img.shields.io/david/uCOMmandIt/uci-pkg-template.svg)](https://david-dm.org/uCOMmandIt/uci-pkg-template) -[![devDependencies](https://img.shields.io/david/dev/uCOMmandIt/uci-pkg-template.svg)](https://david-dm.org/uCOMmandIt/uci-pkg-template?type=dev) -[![codecov](https://img.shields.io/codecov/c/github/uCOMmandIt/uci-pkg-template/master.svg)](https://codecov.io/gh/uCOMmandIt/uci-pkg-template) +[![Build Status](https://img.shields.io/travis/uCOMmandIt/uci-i2c-bus.svg?branch=master)](https://travis-ci.org/uCOMmandIt/uci-i2c-bus) +[![Inline docs](http://inch-ci.org/github/uCOMmandIt/uci-i2c-bus.svg?branch=master)](http://inch-ci.org/github/uCOMmandIt/uci-i2c-bus) +[![Dependencies](https://img.shields.io/david/uCOMmandIt/uci-i2c-bus.svg)](https://david-dm.org/uCOMmandIt/uci-i2c-bus) +[![devDependencies](https://img.shields.io/david/dev/uCOMmandIt/uci-i2c-bus.svg)](https://david-dm.org/uCOMmandIt/uci-i2c-bus?type=dev) +[![codecov](https://img.shields.io/codecov/c/github/uCOMmandIt/uci-i2c-bus/master.svg)](https://codecov.io/gh/uCOMmandIt/uci-i2c-bus) -A promise wrapper for an I2C arm C library methods and a Device Class that is the base class for an I2C device +This is an Raspberry Pi only I2C bus socket packet listener and I2C bus master processor. See /examples/bus.js for how to implement an instance. The rest of the examples are client examples that will talk to a running i2c-bus instance + +Here is a simple script to get an instance going (on an RPI only) + +``` +/* +* Raspberry Pi (only) I2C-Bus listener +* named pipe socket 'i2c-bus' is always created by default /tmp directory unless +* env variable SOCKETS_DIR='' is used to create a 'i2c-bus.sock' in a particular directory +* e.g. command >SOCKETS_DIR=/opt/sockets node -r esm i2cbus +* add TCP listener with tcp:true. Will listen on port 1776 by default +*/ + +import Bus from '@uci/i2c-bus' +; +(async () => { + + let i2cbus = new Bus({id:'i2c-bus',tcp:true}) + + await i2cbus.init() + +})().catch(err => { + console.error('FATAL: UNABLE TO START SYSTEM!\n',err) +}) +``` diff --git a/src/bus-packet.js b/src/bus-packet.js deleted file mode 100644 index a30167e..0000000 --- a/src/bus-packet.js +++ /dev/null @@ -1,115 +0,0 @@ - -import i2c from 'i2c-bus' -import pify from 'pify' -import btc from 'better-try-catch' -import Base from '@uci/base' - -import logger from '@uci/logger' -let log = {} - -export default class Bus extends Base { - constructor(opts) { - log = logger({name:'i2c-bus',id:opts.id,file:'src/bus-packet.js',class:'Bus'}) - if (opts.path) opts.ns ={path:opts.path} - if(!opts.ns) opts.ns = {path:'i2c-bus'} - opts.sockets = (opts.sockets ? (opts.sockets+',') : '') + 'ns#s>n' - if(opts.tcp) { - if (typeof opts.tcp==='number') opts.ts ={port:opts.tcp} - else opts.ts ={port:1776} - opts.sockets = (opts.sockets ? (opts.sockets+',') : '') + 'ts#s>t' - } - super(opts) - log.info({opts:opts},'created bus with these opts') - console.log({opts:opts},'\n created bus with these opts') - this.busnum = opts.busnum || 1 - this.i2cbus = i2c.open(this.busnum, () => {}) - this.bus = bus_funcs - // this.init = this.init.bind(this) - } - - async init(){ - await super.init() - } - - // TODO see if default processing of base can handle this now - async _packetProcess (sname,packet){ - // console.log('incoming packet', sname, packet) - if (!packet.cmd) return {error: 'no cmd: key in packet', packet: packet } - if (this.bus[packet.cmd]) { - let checked = validateArgs(packet) // handle with before hook - if (checked.error) return checked.error - let [err,res] = await btc(this.bus[packet.cmd].bind(this))(packet.args) - if (err) return {error: err.msg, packet:packet} - packet.response = res - packet.cmd = 'reply' - return packet - } else return {error: 'no i2c bus function available for packet command', packet: packet } - } - -} // end of Bus Packet Class - - -const validateArgs = function (packet) { - let missing = [] - const ne = arg => { if (packet.args[arg]===undefined) missing.push(arg) } - // console.log('validate packet',packet) - if (packet.cmd==='scan' || packet.cmd ==='close') return {} - ne('address') - switch (packet.cmd) - { - case 'readRaw': - case 'writeRaw': - ne('length') - ne('buffer') - break - case 'read': - case 'read2': - case 'write': - case 'write2': - ne('cmd') - } - switch (packet.cmd) - { - case 'write': - case 'write2': - case 'send': - ne('byte') - } - if (missing.length > 0) { - return {error: `following bus arguments are missing ${missing}`, packet: packet } - } - return {} -} - -const bus_funcs = { - scan: function () { return pify(this.i2cbus.scan).bind(this.i2cbus)() }, - close: function () { return pify(this.i2cbus.close).bind(this.i2cbus)() }, - readRaw: function (args) { - return pify(this.i2cbus.i2cRead).bind(this.i2cbus)(args.address, args.length, args.buffer) - }, - writeRaw: function (args) { - return pify(this.i2cbus.i2cWrite).bind(this.i2cbus)(args.address, args.length, args.buffer) - }, - read: function (args) { - // console.log('read: address, cmd', address, cmd) - return pify(this.i2cbus.readByte).bind(this.i2cbus)(args.address, args.cmd) - }, - write: function (args) { - // console.log('write: address, cmd, byte', args.address, args.cmd, args.byte) - return pify(this.i2cbus.writeByte.bind(this.i2cbus))(args.address, args.cmd, args.byte) - }, - read2: function (args) { - return pify(this.i2cbus.readWord.bind(this.i2cbus))(args.address, args.cmd) - }, - write2: function (args) { - return pify(this.i2cbus.writeWord.bind(this.i2cbus))(args.address, args.cmd, args.byte) - }, - receive: function (args) { - // console.log('receivebyte', address) - return pify(this.i2cbus.receiveByte.bind(this.i2cbus))(args.address) - }, - send: function (args) { - // console.log('sendbyte', address,byte) - return pify(this.i2cbus.sendByte.bind(this.i2cbus))(args.address, args.byte) - } -} //end i2c functions diff --git a/src/bus.js b/src/bus.js index a6f6f3e..d8e17c8 100644 --- a/src/bus.js +++ b/src/bus.js @@ -1,53 +1,115 @@ import i2c from 'i2c-bus' import pify from 'pify' +import btc from 'better-try-catch' +import Base from '@uci/base' -export default class Bus { - constructor(busnum=1) { - this.busnum = busnum - this.bus = i2c.open(this.busnum, () => {}) +import logger from '@uci/logger' +let log = {} + +export default class Bus extends Base { + constructor(opts) { + log = logger({name:'i2c-bus',id:opts.id,file:'src/bus.js',class:'Bus'}) + if (opts.path) opts.ns ={path:opts.path} + if(!opts.ns) opts.ns = {path:'i2c-bus'} + opts.sockets = (opts.sockets ? (opts.sockets+',') : '') + 'ns#s>n' + if(opts.tcp) { + if (typeof opts.tcp==='number') opts.ts ={port:opts.tcp} + else opts.ts = {port:1776} + opts.sockets = (opts.sockets ? (opts.sockets+',') : '') + 'ts#s>t' + } + super(opts) + log.info({opts:opts},'created bus with these opts') + console.log({opts:opts},'\n created bus with these opts') + this.busnum = opts.busnum || 1 + this.i2cbus = i2c.open(this.busnum, () => {}) + this.bus = bus_funcs + // this.init = this.init.bind(this) } - // see https://github.com/fivdi/i2c-bus#busi2cfuncscb for list of functions that can be promisified - - scan() { return pify(this.bus.scan).bind(this.bus)() } - close() { return pify(this.bus.close).bind(this.bus)() } - - readRaw(address, length, buffer) { - return pify(this.bus.i2cRead).bind(this.bus)(address, length, buffer) + async init(){ + await super.init() } - writeRaw(address, length, buffer) { - return pify(this.bus.i2cWrite).bind(this.bus)(address, length, buffer) + // TODO see if default processing of base can handle this now + async _packetProcess (sname,packet){ + // console.log('incoming packet', sname, packet) + if (!packet.cmd) return {error: 'no cmd: key in packet', packet: packet } + if (this.bus[packet.cmd]) { + let checked = validateArgs(packet) // handle with before hook + if (checked.error) return checked.error + let [err,res] = await btc(this.bus[packet.cmd].bind(this))(packet.args) + if (err) return {error: err.msg, packet:packet} + packet.response = res + packet.cmd = 'reply' + return packet + } else return {error: 'no i2c bus function available for packet command', packet: packet } } - read(address, cmd) { - // console.log('read: address, cmd', address, cmd) - return pify(this.bus.readByte).bind(this.bus)(address, cmd) +} // end of Bus Packet Class + + +const validateArgs = function (packet) { + let missing = [] + const ne = arg => { if (packet.args[arg]===undefined) missing.push(arg) } + // console.log('validate packet',packet) + if (packet.cmd==='scan' || packet.cmd ==='close') return {} + ne('address') + switch (packet.cmd) + { + case 'readRaw': + case 'writeRaw': + ne('length') + ne('buffer') + break + case 'read': + case 'read2': + case 'write': + case 'write2': + ne('cmd') } - - write(address, cmd, byte) { - // console.log('write: address, cmd, byte', address, cmd, byte) - return pify(this.bus.writeByte.bind(this.bus))(address, cmd, byte) + switch (packet.cmd) + { + case 'write': + case 'write2': + case 'send': + ne('byte') } - - read2(address, cmd) { - return pify(this.bus.readWord.bind(this.bus))(address, cmd) + if (missing.length > 0) { + return {error: `following bus arguments are missing ${missing}`, packet: packet } } + return {} +} - write2(address, cmd, bytes) { - return pify(this.bus.writeWord.bind(this.bus))(address, cmd, bytes) +const bus_funcs = { + scan: function () { return pify(this.i2cbus.scan).bind(this.i2cbus)() }, + close: function () { return pify(this.i2cbus.close).bind(this.i2cbus)() }, + readRaw: function (args) { + return pify(this.i2cbus.i2cRead).bind(this.i2cbus)(args.address, args.length, args.buffer) + }, + writeRaw: function (args) { + return pify(this.i2cbus.i2cWrite).bind(this.i2cbus)(args.address, args.length, args.buffer) + }, + read: function (args) { + // console.log('read: address, cmd', address, cmd) + return pify(this.i2cbus.readByte).bind(this.i2cbus)(args.address, args.cmd) + }, + write: function (args) { + // console.log('write: address, cmd, byte', args.address, args.cmd, args.byte) + return pify(this.i2cbus.writeByte.bind(this.i2cbus))(args.address, args.cmd, args.byte) + }, + read2: function (args) { + return pify(this.i2cbus.readWord.bind(this.i2cbus))(args.address, args.cmd) + }, + write2: function (args) { + return pify(this.i2cbus.writeWord.bind(this.i2cbus))(args.address, args.cmd, args.byte) + }, + receive: function (args) { + // console.log('receivebyte', address) + return pify(this.i2cbus.receiveByte.bind(this.i2cbus))(args.address) + }, + send: function (args) { + // console.log('sendbyte', address,byte) + return pify(this.i2cbus.sendByte.bind(this.i2cbus))(args.address, args.byte) } - - receive(address) { - // console.log('receivebyte', address) - return pify(this.bus.receiveByte.bind(this.bus))(address) - } - - send(address, byte) { - // console.log('sendbyte', address,byte) - return pify(this.bus.sendByte.bind(this.bus))(address, byte) - } - - -} // end of Bus Class +} //end i2c functions diff --git a/test/bus.test.js b/test/bus.test.js deleted file mode 100644 index 6f6ecb2..0000000 --- a/test/bus.test.js +++ /dev/null @@ -1,21 +0,0 @@ -import Bus from '../src/bus' -import chai from 'chai' -import chaiAsPromised from 'chai-as-promised' - -chai.use(chaiAsPromised) - -const expect = chai.expect - -let bus = new Bus() - -const addresses = [0x25, 0x26, 0x27] -// const addresses = [] - -describe('Bus Class - ', function () { - - it('Can scan the bus for devices', function () { - - return expect(bus.scan().catch(err => console.log('an error', err))).to.eventually.deep.equal(addresses) - - }) -})