diff --git a/src/bus.js b/src/bus.js deleted file mode 100644 index 53d2242..0000000 --- a/src/bus.js +++ /dev/null @@ -1,61 +0,0 @@ -// Solely a promise wrapper module for the basic async functions of the fivdi/i2c-bus javascript bindings C API -// https://github.com/fivdi/i2c-bus - -'use strict' - -const i2c = require('i2c-bus'), - pify = require('pify') - -class Bus { - constructor(busnum=1) { - this.busnum = busnum - this.bus = i2c.open(this.busnum, () => {}) - } - - // 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) - } - - writeRaw(address, length, buffer) { - return pify(this.bus.i2cWrite).bind(this.bus)(address, length, buffer) - } - - read(address, cmd) { - // console.log('read: address, cmd', address, cmd) - return pify(this.bus.readByte).bind(this.bus)(address, 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) - } - - read2(address, cmd) { - return pify(this.bus.readWord.bind(this.bus))(address, cmd) - } - - write2(address, cmd, bytes) { - return pify(this.bus.writeWord.bind(this.bus))(address, cmd, bytes) - } - - 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 - -module.exports = { - Bus -} diff --git a/src/device-packet.mjs b/src/device-packet.mjs new file mode 100644 index 0000000..79c3b75 --- /dev/null +++ b/src/device-packet.mjs @@ -0,0 +1,124 @@ +// import Base from '@uci/base' +import Base from '../../uci-base/src/base' + +import logger from '../../uci-logger/src/logger' +let log = {} +const LOG_OPTS = (id) => { + return { + repo:'uci-i2c-device', + npm:'@uci/i2c-device', + file:'src/device-packet.mjs', + class:'Device', + id:id, + instance_created:new Date().getTime() + }} + +export default class Device extends Base { + constructor(opts) { + opts.bus.name = opts.bus.name || 'bus' //optional bus socket name + opts.sockets = opts.sockets ||'' + // either device process instance runs on same host (use named pipe) or not (the host of bus must be given) + if (opts[opts.bus.name]) { + if (opts[opts.bus.name].host) { + opts.sockets = opts.sockets + opts.bus.name+'#c>t' + opts[opts.bus.name].port = opts[opts.bus.name].port || 1776 + } + if (opts[opts.bus.name].path) opts.sockets = opts.bus.name+'#c>n' + } else { + opts[opts.bus.name] = { path : (process.env.SOCKETS_DIR || __dirname) + '/i2c-bus.sock' } + opts.sockets = opts.bus.name+'#c>t' + } + console.log(opts) + super(opts) + log = logger.child(LOG_OPTS(this.id)) + if (!opts.address) log.fatal({opts:opts},'no i2c bus address supplied' ) + this.address = opts.address + this._bus_name = opts.bus.name + this._channel = opts.channel // if using TAC9546A channel number on which device is attached + this.bus = device_funcs + for(const func in this.bus) { // autobind + this.bus[func] = this.bus[func].bind(this) + } + + } + + async init(){ + await super.init() + let res = await this.bus.ack() // move this to device class + let socket = this.socket[this._bus_name].opts + let connection = socket.path || socket.host + ':' + socket.port + if (!res.ack) throw `no device operational on bus '${socket.id}' (${connection}) at address ${this.address}=0x${this.address.toString(16)}` + return res + } + + async _setChannel() { + // TODO convert to package - uci-mux + // console.log('before set',this.address,this.id,this._channel, await this.socket.bus.send(getState) + // if (this._channel) { + // if (!await this.socket.bus.send(address) { return Promise.reject('Channel set but no mux on bus')} + // return await this.socket.bus.send(set(this._channel) + // } + return Promise.resolve() // no channel for device either no mux or device is attached to mux bypass + } + + +} // end of MCP230XX Class + + +const device_funcs = { + + ack: async function (){ + // TODO if mux channel used check it as well + let bus = await this.send(this._bus_name,{ cmd:'scan'}) + if (bus.error) return bus + let res = { cmd:'reply', ack: false, address:this.address, scan:bus.response} + if (bus.response.indexOf(this.address) !== -1) res.ack = true + return res + }, + + receive: async function() { + await this._setChannel() + return await this.send(this._bus_name, { cmd:'receive', args: {address:this.address}}) + }, + + send: async function(byte) { + await this._setChannel() + return await this.send(this._bus_name, { cmd:'send', args: {address:this.address, byte:byte }}) + }, + + // for devices needing a buffer/stream + readRaw: async function (length, buffer) { + await this._setChannel() + return await this.send(this._bus_name, { cmd:'readRaw', args: {address:this.address, length:length, buffer:buffer }}) + }, + + writeRaw: async function (length, buffer) { + await this._setChannel() + return await this.send(this._bus_name, { cmd:'writeRaw', args: {address:this.address, length:length, buffer:buffer }}) + }, + + // both cmd and byte should be a single byte as a decimal or hex + read: async function (cmd) { + await this._setChannel() + // console.log('after set before read',this.address,this.id,this._channel,await this.socket.bus.send(getState) + return await this.send(this._bus_name, { cmd:'read', args: {address:this.address, cmd:cmd }}) + }, + + write: async function (cmd, byte) { + await this._setChannel() + // console.log('after set, before write',this.address,this.id,this._channel,await this.socket.bus.send(getState) + return await this.send(this._bus_name, { cmd:'write', args: {address:this.address, cmd:cmd, byte:byte }}) + }, + + // for I2C devices that use a word length packackage + read2: async function (cmd) { + await this._setChannel() + return await this.send(this._bus_name, { cmd:'read2', args: {address:this.address, cmd:cmd }}) + }, + + write2: async function (cmd, bytes) { + await this._setChannel() + return await this.send(this._bus_name, { cmd:'write2', args: {address:this.address, cmd:cmd, byte:bytes }}) + } + +}