// 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) { if (!opts.bus) opts.bus ={} opts.bus.name = opts.bus.name || 'bus' //optional bus socket name // 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].host) opts[opts.bus.name].port = opts[opts.bus.name].port || 1776 else opts[opts.bus.name].path = opts[opts.bus.name].path || (process.env.SOCKETS_DIR || __dirname) + '/i2c-bus.sock' opts.sockets = (opts.sockets || '') + opts.bus.name + '#c>' + ((opts[opts.bus.name].path) ? 'n' :'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 }}) } }