139 lines
3.9 KiB
JavaScript
139 lines
3.9 KiB
JavaScript
import pify from 'pify'
|
|
// import btc from 'better-try-catch'
|
|
import to from 'await-to-js'
|
|
import i2c from 'i2c-bus'
|
|
import PQueue from 'p-queue'
|
|
import Base from '@uci/base'
|
|
|
|
import logger from '@uci-utils/logger'
|
|
let log = {}
|
|
|
|
class I2CBus extends Base {
|
|
constructor(opts) {
|
|
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'
|
|
// TODO if port is passed as option then set up tcp with that port
|
|
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)
|
|
this.id = opts.id || 'i2c-bus'
|
|
log = logger({
|
|
name: 'i2c-bus',
|
|
id: this.id,
|
|
file: 'src/bus.js',
|
|
class: 'Bus'
|
|
})
|
|
log.debug({ opts: opts }, 'created bus with these opts')
|
|
this.busnum = opts.busnum || 1
|
|
this.i2cbus = i2c.open(this.busnum, () => {})
|
|
this._funcs = bus_funcs
|
|
this.bus = {}
|
|
this.addBusFuncs(this._funcs)
|
|
this.addNamespace('bus')
|
|
this.bus.busFuncs = async (packet) => {
|
|
packet.functions = this.busFuncs
|
|
packet.cmd='reply'
|
|
return packet
|
|
}
|
|
this._queue = new PQueue({concurrency: opts.concurrency || 1})
|
|
}
|
|
|
|
async init() {
|
|
await super.init()
|
|
let count = 0
|
|
this._queue.on('active', () => {
|
|
log.debug(`Queue: working on item #${++count}. Size: ${this._queue.size} Pending: ${this._queue.pending}`)
|
|
})
|
|
}
|
|
|
|
get busFuncs() { return this._funcs}
|
|
|
|
addBusFuncs(funcs) {
|
|
for (let name in funcs) {
|
|
let func = funcs[name]
|
|
this.addBusFunc(name,func)
|
|
}
|
|
}
|
|
|
|
addBusFunc(name,func) {
|
|
this.bus[name] = busFunction.bind(this, func.name || name , func.args || [])
|
|
this._funcs[name]=func
|
|
}
|
|
|
|
} // end of Bus Packet Class
|
|
|
|
export default I2CBus
|
|
|
|
const validateArg = function (arg,value) {
|
|
let valid = false
|
|
switch (arg) {
|
|
case 'address':
|
|
valid = Number.isInteger(value) && value >=0 && value <= 119
|
|
break
|
|
case 'length':
|
|
case 'cmd':
|
|
valid = Number.isInteger(value)
|
|
break
|
|
case 'byte':
|
|
valid = Number.isInteger(value) && value >= 0 && value <= 255
|
|
break
|
|
case 'word':
|
|
valid = Number.isInteger(value) && value >= 0 && value <= 65535
|
|
break
|
|
case 'bit':
|
|
valid = Number.isInteger(value) && (value === 0 || value === 1)
|
|
break
|
|
case 'buffer':
|
|
valid = Buffer.isBuffer(value)
|
|
}
|
|
return valid
|
|
}
|
|
|
|
async function busFunction (func,args,packet) {
|
|
let argsV = []
|
|
args.some(arg => {
|
|
if (packet.args) {
|
|
let argv = packet.args[arg]
|
|
if (argv != null) {
|
|
if(validateArg(arg,argv)) argsV.push(argv)
|
|
else {
|
|
packet.error = `argument ${arg} has an invalide value ${argv} for function ${func}`
|
|
return true
|
|
}
|
|
} else {
|
|
packet.error = `missing argument, ${arg}, for function ${func}`
|
|
return true
|
|
}
|
|
}
|
|
})
|
|
if (!packet.error) {
|
|
log.trace({msg:'adding to queue', function:func,arguments:argsV})
|
|
let busfunc = pify(this.i2cbus[func].bind(this.i2cbus,...argsV))
|
|
let [err,res] = await to(this._queue.add(busfunc))
|
|
if (err) packet.error = `error during call to ${func} with arguments ${JSON.stringify(packet.args)}: ${err}`
|
|
else packet.response = res
|
|
}
|
|
packet.cmd = 'reply'
|
|
return packet
|
|
}
|
|
|
|
// default function set
|
|
const bus_funcs = {
|
|
scan: {},
|
|
close: {},
|
|
methods: {name:'i2cFuncs'},
|
|
deviceId: {args:['address']},
|
|
readRaw: {name:'i2cRead', args:['address','length','buffer']},
|
|
writeRaw: {name:'i2cWrite', args:['address','length','buffer']},
|
|
read: {name:'readByte', args:['address','cmd']},
|
|
write: {name:'writeByte', args:['address','cmd','byte']},
|
|
read2: {name:'readWord', args:['address','cmd']},
|
|
write2: {name:'writeWord', args:['address','cmd','word']},
|
|
receive: {name:'receiveByte', args:['address']},
|
|
send: {name:'sendByte', args:['address','byte']}
|
|
}
|