ev3dev-lang
Version:
An interface to control an EV3 or other supported platform running ev3dev from JavaScript.
258 lines • 10.8 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var fs = require('fs');
var path = require('path');
var Promise = null;
try {
Promise = require('bluebird');
}
catch (e) {
}
var XError = (function () {
function XError() {
var tsargs = [];
for (var _i = 0; _i < arguments.length; _i++) {
tsargs[_i - 0] = arguments[_i];
}
Error.apply(this, arguments);
return new Error();
}
return XError;
}());
XError['prototype'] = new Error();
var TraceError = (function () {
function TraceError(message, innerError) {
this.message = message;
this.innerError = innerError;
}
TraceError.prototype.toString = function () {
var str = this.message.trim() + '\r\nInner error:\r\n';
var innerLines = this.innerError.toString().split('\r\n');
for (var i in innerLines) {
innerLines[i] = ' ' + innerLines[i];
}
return str + innerLines.join('\r\n');
};
return TraceError;
}());
exports.TraceError = TraceError;
var EventNotificationRequest = (function () {
function EventNotificationRequest(callbackFunction, eventPredicate, firstTriggerOnly, userData) {
if (firstTriggerOnly === void 0) { firstTriggerOnly = true; }
this.callbackFunction = callbackFunction;
this.eventPredicate = eventPredicate;
this.userData = userData;
this.firstTriggerOnly = firstTriggerOnly;
}
EventNotificationRequest.prototype.handleUpdate = function () {
var predicateResult;
try {
predicateResult = this.eventPredicate(this.userData);
}
catch (e) {
this.callbackFunction(e);
return false;
}
if (predicateResult) {
this.callbackFunction();
if (this.firstTriggerOnly)
return false;
}
return true;
};
return EventNotificationRequest;
}());
var Device = (function () {
function Device() {
this.connected = false;
this.sysClassDir = '/sys/class';
this.pendingEventRequests = [];
this.eventTimerCancellationToken = null;
}
Device.prototype.connect = function (driverName, nameConvention, propertyConstraints) {
var nameRegex = nameConvention ? new RegExp(nameConvention) : undefined;
var deviceSearchDir = path.join(Device.overrideSysClassDir || this.sysClassDir, driverName);
var availableDevices;
try {
availableDevices = fs.readdirSync(deviceSearchDir);
}
catch (error) {
return;
}
for (var deviceDirIndex in availableDevices) {
var currentDeviceDirName = availableDevices[deviceDirIndex];
if (nameRegex != undefined && !nameRegex.test(currentDeviceDirName)) {
continue;
}
var currentDeviceDir = path.join(deviceSearchDir, currentDeviceDirName);
var satisfiesConstraints = true;
if (propertyConstraints != undefined) {
for (var propName in propertyConstraints) {
var propertyValue = this.readProperty(propName, currentDeviceDir);
var constraintValue = propertyConstraints[propName];
if (constraintValue instanceof Array) {
if (constraintValue.indexOf(propertyValue) === -1) {
satisfiesConstraints = false;
}
}
else if (propertyValue != constraintValue) {
satisfiesConstraints = false;
}
}
}
if (!satisfiesConstraints)
continue;
this.deviceRoot = currentDeviceDir;
this.deviceDirName = currentDeviceDirName;
this.connected = true;
}
};
Device.prototype.constructPropertyPath = function (property, deviceRoot) {
return path.join(deviceRoot || this.deviceRoot, property);
};
Device.prototype.readNumber = function (property, deviceRoot) {
var value = this.readProperty(property, deviceRoot);
if (typeof value !== 'number')
return NaN;
return value;
};
Device.prototype.readString = function (property, deviceRoot) {
var value = this.readProperty(property, deviceRoot);
return String(value);
};
Device.prototype.readStringAsType = function (property, deviceRoot) {
return this.readString(property, deviceRoot);
};
Device.prototype.readStringArray = function (property, deviceRoot) {
return this.readString(property, deviceRoot)
.split(' ')
.map(function (value) { return value.replace(/^\[|\]$/g, ''); });
};
Device.prototype.readStringArrayAsType = function (property, deviceRoot) {
return this.readStringArray(property, deviceRoot);
};
Device.prototype.readStringSelector = function (property, deviceRoot) {
var bracketedParts = this.readString(property, deviceRoot)
.split(' ')
.filter(function (value) { return value.match(/^\[|\]$/g) != null; });
if (bracketedParts.length <= 0)
return null;
return bracketedParts[0].replace(/^\[|\]$/g, '');
};
Device.prototype.readProperty = function (property, deviceRoot) {
if (!deviceRoot && !this.connected)
throw new Error('You must be connected to a device before you can read from it. This error probably means that the target device was not found.');
var rawValue;
var propertyPath = this.constructPropertyPath(property, deviceRoot);
try {
rawValue = fs.readFileSync(propertyPath).toString();
}
catch (e) {
throw new TraceError('There was an error while reading from the property file "' + propertyPath + '".', e);
}
rawValue = rawValue.trim();
var numValue = Number(rawValue);
if (isNaN(numValue))
return rawValue;
else
return numValue;
};
Device.prototype.setProperty = function (property, value) {
if (!this.connected)
throw new Error('You must be connected to a device before you can write to it. This error probably means that the target device was not found.');
var propertyPath = this.constructPropertyPath(property);
try {
fs.writeFileSync(propertyPath, value.toString());
}
catch (e) {
throw new TraceError('There was an error while writing to the property file "' + propertyPath + '".', e);
}
};
Device.prototype.setNumber = function (property, value) {
this.setProperty(property, value);
};
Device.prototype.setString = function (property, value) {
this.setProperty(property, value);
};
Device.prototype.set = function (propertyDefs) {
for (var key in propertyDefs) {
this.setProperty(key, propertyDefs[key]);
}
};
Device.prototype.updatePendingEventRequests = function () {
this.pendingEventRequests = this.pendingEventRequests.filter(function (eventRequest, index, arr) {
return eventRequest.handleUpdate();
});
this.updateEventTimerState();
};
Device.prototype.updateEventTimerState = function () {
var _this = this;
if (this.pendingEventRequests.length > 0 && this.eventTimerCancellationToken == null) {
this.eventTimerCancellationToken = setInterval(function () { return _this.updatePendingEventRequests(); }, Device.eventTimerInterval);
}
else if (this.pendingEventRequests.length <= 0 && this.eventTimerCancellationToken != null) {
clearInterval(this.eventTimerCancellationToken);
this.eventTimerCancellationToken = null;
}
};
Device.prototype.registerEventCallback = function (callbackFunction, eventPredicate, firstTriggerOnly, userCallbackData) {
if (firstTriggerOnly === void 0) { firstTriggerOnly = false; }
var newEventRequest = new EventNotificationRequest(function (err) {
callbackFunction(err, userCallbackData);
}, eventPredicate, firstTriggerOnly, userCallbackData);
this.pendingEventRequests.push(newEventRequest);
this.updateEventTimerState();
};
Device.prototype.registerEventPromise = function (eventPredicate, userCallbackData) {
var _this = this;
if (Promise == null) {
throw new Error("Promises are currently unavailable. Install the 'bluebird' package or use 'registerEventCallback(...)' instead.");
}
return new Promise(function (resolve, reject) {
_this.registerEventCallback(function (err) {
if (err)
reject(err);
else
resolve(userCallbackData);
}, eventPredicate, true, userCallbackData);
});
};
Device.overrideSysClassDir = null;
Device.eventTimerInterval = 50;
return Device;
}());
exports.Device = Device;
var IndexedDevice = (function (_super) {
__extends(IndexedDevice, _super);
function IndexedDevice(driverTypeDirName, nameConvention, targetAddress, targetDriverName) {
_super.call(this);
this.deviceIndexRegex = new RegExp("(\\d+)", "g");
this._deviceIndex = -1;
var propertyConstraints = {};
if (targetAddress != undefined)
propertyConstraints['address'] = targetAddress;
if (targetDriverName != undefined)
propertyConstraints['driver_name'] = [].concat(targetDriverName);
this.connect(driverTypeDirName, nameConvention, propertyConstraints);
if (this.connected) {
var matches = this.deviceIndexRegex.exec(this.deviceDirName);
if (matches != null && matches[0] != undefined) {
this._deviceIndex = Number(matches[1]);
}
}
}
Object.defineProperty(IndexedDevice.prototype, "deviceIndex", {
get: function () {
return this._deviceIndex;
},
enumerable: true,
configurable: true
});
return IndexedDevice;
}(Device));
exports.IndexedDevice = IndexedDevice;
//# sourceMappingURL=io.js.map