lunijs
Version:
Javascript client for Arduino LuniLib device drivers.
180 lines (163 loc) • 6.06 kB
JavaScript
// This module provides a high-level API interface to a Luni device driver
// running on a remote Arduino under Firmata. All calls at the API level result
// in events, not callbacks. If device-specific API functions are needed, the
// author should extend this class and define the needed functions in a subclass.
//
// This program is strict-mode throughout.
//
// Doug Johnson, May 2016
const log4js = require("log4js");
const path = require("path");
const thisModule = path.basename(module.filename,".js");
const log = log4js.getLogger(thisModule);
log.setLevel('DEBUG');
const RDD = require("../lib/RDD/RemoteDeviceDriver");
const EventEmitter = require("events");
let proxy;
/**
* Use the Luni device driver proxy methods to talk to a device
* driver running on a connected Arduino.
*/
class DeviceAPI extends EventEmitter {
/**
* This DeviceAPI class receives user calls to common device driver API
* methods and translates them to the appropriate device driver calls and
* forwards them on using Firmata. The resulting callbacks are captured and
* translated to events that the caller can act on.
*
* @param {object} opts Options
*/
constructor(opts) {
super();
this.proxy = opts.driver;
}
/**
* Open the specified unit
*
* @param {[type]} unitName [description]
* @param {[type]} flags [description]
* @param {[type]} opts [description]
* @return {[type]} [description]
*/
open(unitName, flags, opts) {
log.trace(`open(${unitName})`);
this.proxy.open(unitName, flags, opts,(response) => {
log.trace(`proxy.open(${response.unitName}) callback invoked for API open().`);
if (response.status >= 0) {
this.emit("open",{status : RDD.SC.ESUCCESS.val, unitName : response.unitName, handle : response.handle});
} else {
this.emit("error",{status : response.status, unitName : response.unitName});
}
});
}
/**
* Read data from the specified unit and register.
*
* @param {[type]} handle [description]
* @param {[type]} flags [description]
* @param {[type]} reg [description]
* @param {[type]} count [description]
* @event read [description]
*/
read(handle, flags, reg, count) {
this.proxy.read(handle, flags, reg, count,(response) => {
log.trace(`proxy.read(${response.handle}) callback invoked for API read().`);
if (response.status >= 0) {
let result = {
status : RDD.SC.ESUCCESS.val,
handle : response.handle,
register : response.register,
flags : response.flags,
data : response.datablock
};
this.emit("read",result);
} else {
this.emit("error",{status : response.status, handle : response.handle});
}
});
}
/**
* Write data to the specified unit and register.
*
* @param {[type]} handle [description]
* @param {[type]} flags [description]
* @param {[type]} reg [description]
* @param {[type]} count [description]
* @param {[type]} data [description]
* @event write [description]
*/
write(handle, flags, reg, count,data) {
this.proxy.write(handle, flags, reg, count,data,(response) => {
log.trace(`proxy.write(${response.handle}) callback invoked for API write().`);
if (response.status >= 0) {
let result = {
status : RDD.SC.ESUCCESS.val,
handle : response.handle,
register : response.register,
flags : response.flags
};
this.emit("write",result);
} else {
this.emit("error",{status : response.status, handle : response.handle});
}
});
}
/**
* Close the connection represented by the given handle.
*
* @param {[type]} handle [description]
* @param {[type]} flags [description]
* @return {[type]} [description]
*/
close(handle, flags) {
this.proxy.close(handle,flags,(response) => {
log.trace(`proxy.close(${response.handle}) close callback invoked for API close().`);
if (response.status >= 0) {
this.emit("close",{status : RDD.SC.ESUCCESS.val, handle : response.handle});
} else {
this.emit("error",{status : response.status, handle : response.handle});
}
});
}
/**
* Set one or both of the timer intervals
*
* @param {[type]} handle [description]
* @param {[type]} micros [description]
* @param {[type]} millis [description]
*/
setIntervals(handle, micros, millis) {
this.proxy.read(handle, 0, RDD.CDR.Intervals, 8, (response) => {
log.trace(`proxy.read(${response.handle}) callback invoked for API setIntervals().`);
if (response.status >= 0) {
if (typeof micros === "number") {
response.datablock.writeUInt32LE(micros,0);
}
if (typeof millis === "number") {
response.datablock.writeUInt32LE(millis,4);
}
this.proxy.write(response.handle,RDD.DAF.NONE,RDD.CDR.Intervals,8,response.datablock,(response) => {
log.trace(`proxy.write(${response.handle}) callback invoked for API setIntervals().`);
if (response.status >= 0) {
let result = {
status : RDD.SC.ESUCCESS.val,
handle : response.handle,
register : response.register,
flags : response.flags
};
this.emit("write",result);
} else {
this.emit("error",{status : response.status, handle : response.handle});
}
});
} else {
this.emit("error",{status : response.status, handle : response.handle});
}
});
}
clip(value, rangeMinMax) {
return Math.max(rangeMinMax[0],Math.min(value,rangeMinMax[1]));
}
}
module.exports.DeviceAPI = DeviceAPI;
module.exports.RDD = RDD;