Merge branch 'master' into feature/duplotrain

This commit is contained in:
Nathan Kellenicki 2018-08-29 10:20:32 -07:00
commit 7468d52cda
6 changed files with 88 additions and 30 deletions

View File

@ -56,13 +56,23 @@ export class BoostMoveHub extends LPF2Hub {
* @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. * @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely.
* @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished. * @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished.
*/ */
public setMotorSpeed (port: string, speed: number | [number, number], time?: number) { public setMotorSpeed (port: string, speed: number | [number, number], time?: number | boolean) {
const portObj = this._portLookup(port); const portObj = this._portLookup(port);
if (portObj.id !== "AB" && speed instanceof Array) { if (portObj.id !== "AB" && speed instanceof Array) {
throw new Error(`Port ${portObj.id} can only accept a single speed`); throw new Error(`Port ${portObj.id} can only accept a single speed`);
} }
let cancelEventTimer = true;
if (typeof time === "boolean") {
if (time === true) {
cancelEventTimer = false;
}
time = undefined;
}
if (cancelEventTimer) {
portObj.cancelEventTimer();
}
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (time) { if (time && typeof time === "number") {
if (portObj.type === Consts.Devices.BOOST_TACHO_MOTOR || portObj.type === Consts.Devices.BOOST_MOVE_HUB_MOTOR) { if (portObj.type === Consts.Devices.BOOST_TACHO_MOTOR || portObj.type === Consts.Devices.BOOST_MOVE_HUB_MOTOR) {
portObj.busy = true; portObj.busy = true;
@ -82,11 +92,13 @@ export class BoostMoveHub extends LPF2Hub {
// @ts-ignore: The type of speed is properly checked at the start // @ts-ignore: The type of speed is properly checked at the start
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]); const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]);
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
setTimeout(() => { const timeout = global.setTimeout(() => {
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]); const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
return resolve(); return resolve();
// @ts-ignore: The type of time is properly checked at the start
}, time); }, time);
portObj.setEventTimer(timeout);
} }
} else { } else {
@ -125,10 +137,12 @@ export class BoostMoveHub extends LPF2Hub {
* @returns {Promise} Resolved upon successful completion of command. * @returns {Promise} Resolved upon successful completion of command.
*/ */
public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) { public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) {
const portObj = this._portLookup(port);
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._calculateRamp(fromSpeed, toSpeed, time) this._calculateRamp(fromSpeed, toSpeed, time, portObj)
.on("changeSpeed", (speed) => { .on("changeSpeed", (speed) => {
this.setMotorSpeed(port, speed); this.setMotorSpeed(port, speed, true);
}) })
.on("finished", resolve); .on("finished", resolve);
}); });
@ -151,6 +165,7 @@ export class BoostMoveHub extends LPF2Hub {
if (portObj.id !== "AB" && speed instanceof Array) { if (portObj.id !== "AB" && speed instanceof Array) {
throw new Error(`Port ${portObj.id} can only accept a single speed`); throw new Error(`Port ${portObj.id} can only accept a single speed`);
} }
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
portObj.busy = true; portObj.busy = true;
let data = null; let data = null;
@ -179,15 +194,17 @@ export class BoostMoveHub extends LPF2Hub {
*/ */
public setLightBrightness (port: string, brightness: number, time?: number) { public setLightBrightness (port: string, brightness: number, time?: number) {
const portObj = this._portLookup(port); const portObj = this._portLookup(port);
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]); const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]);
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
if (time) { if (time) {
setTimeout(() => { const timeout = global.setTimeout(() => {
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]); const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
return resolve(); return resolve();
}, time); }, time);
portObj.setEventTimer(timeout);
} else { } else {
return resolve(); return resolve();
} }

5
hub.ts
View File

@ -198,7 +198,7 @@ export class Hub extends EventEmitter {
*/ */
public sleep (delay: number) { public sleep (delay: number) {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(resolve, delay); global.setTimeout(resolve, delay);
}); });
} }
@ -303,7 +303,7 @@ export class Hub extends EventEmitter {
} }
protected _calculateRamp (fromSpeed: number, toSpeed: number, time: number) { protected _calculateRamp (fromSpeed: number, toSpeed: number, time: number, port: Port) {
const emitter = new EventEmitter(); const emitter = new EventEmitter();
const steps = Math.abs(toSpeed - fromSpeed); const steps = Math.abs(toSpeed - fromSpeed);
let delay = time / steps; let delay = time / steps;
@ -329,6 +329,7 @@ export class Hub extends EventEmitter {
emitter.emit("finished"); emitter.emit("finished");
} }
}, delay); }, delay);
port.setEventTimer(interval);
return emitter; return emitter;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "node-poweredup", "name": "node-poweredup",
"version": "1.1.2", "version": "1.1.3",
"description": "A Node.js module to interface with LEGO Powered UP components.", "description": "A Node.js module to interface with LEGO Powered UP components.",
"homepage": "https://github.com/nathankellenicki/node-poweredup/", "homepage": "https://github.com/nathankellenicki/node-poweredup/",
"main": "dist/poweredup.js", "main": "dist/poweredup.js",

21
port.ts
View File

@ -6,19 +6,28 @@ export class Port {
public id: string; public id: string;
public value: number; public value: number;
public connected: boolean;
public type: Consts.Devices; public type: Consts.Devices;
public busy: boolean; public connected: boolean = false;
public finished: (() => void) | null; public busy: boolean = false;
public finished: (() => void) | null = null;
private _eventTimer: NodeJS.Timer | null = null;
constructor (id: string, value: number) { constructor (id: string, value: number) {
this.id = id; this.id = id;
this.value = value; this.value = value;
this.connected = false;
this.busy = false;
this.finished = null;
this.type = Consts.Devices.UNKNOWN; this.type = Consts.Devices.UNKNOWN;
} }
public cancelEventTimer () {
if (this._eventTimer) {
clearTimeout(this._eventTimer);
this._eventTimer = null;
}
}
public setEventTimer (timer: NodeJS.Timer) {
this._eventTimer = timer;
}
} }

View File

@ -61,7 +61,7 @@ export class PUPHub extends LPF2Hub {
* @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. * @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely.
* @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished. * @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished.
*/ */
public setMotorSpeed (port: string, speed: number | [number, number], time?: number) { public setMotorSpeed (port: string, speed: number | [number, number], time?: number | boolean) {
const portObj = this._portLookup(port); const portObj = this._portLookup(port);
if (portObj.id !== "AB" && speed instanceof Array) { if (portObj.id !== "AB" && speed instanceof Array) {
throw new Error(`Port ${portObj.id} can only accept a single speed`); throw new Error(`Port ${portObj.id} can only accept a single speed`);
@ -73,8 +73,18 @@ export class PUPHub extends LPF2Hub {
throw new Error(`Port ${portObj.id} requires both motors be of the same type`); throw new Error(`Port ${portObj.id} requires both motors be of the same type`);
} }
} }
let cancelEventTimer = true;
if (typeof time === "boolean") {
if (time === true) {
cancelEventTimer = false;
}
time = undefined;
}
if (cancelEventTimer) {
portObj.cancelEventTimer();
}
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (time) { if (time && typeof time === "number") {
let data = null; let data = null;
if (portObj.id === "AB") { if (portObj.id === "AB") {
data = Buffer.from([0x81, portObj.value, 0x11, 0x02, this._mapSpeed(speed instanceof Array ? speed[0] : speed), this._mapSpeed(speed instanceof Array ? speed[1] : speed)]); data = Buffer.from([0x81, portObj.value, 0x11, 0x02, this._mapSpeed(speed instanceof Array ? speed[0] : speed), this._mapSpeed(speed instanceof Array ? speed[1] : speed)]);
@ -83,7 +93,7 @@ export class PUPHub extends LPF2Hub {
data = Buffer.from([0x81, portObj.value, 0x11, 0x60, 0x00, this._mapSpeed(speed), 0x00, 0x00]); data = Buffer.from([0x81, portObj.value, 0x11, 0x60, 0x00, this._mapSpeed(speed), 0x00, 0x00]);
} }
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
setTimeout(() => { const timeout = global.setTimeout(() => {
let data = null; let data = null;
if (portObj.id === "AB") { if (portObj.id === "AB") {
data = Buffer.from([0x81, portObj.value, 0x11, 0x02, 0x00, 0x00]); data = Buffer.from([0x81, portObj.value, 0x11, 0x02, 0x00, 0x00]);
@ -93,6 +103,7 @@ export class PUPHub extends LPF2Hub {
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
return resolve(); return resolve();
}, time); }, time);
portObj.setEventTimer(timeout);
} else { } else {
let data = null; let data = null;
if (portObj.id === "AB") { if (portObj.id === "AB") {
@ -118,10 +129,12 @@ export class PUPHub extends LPF2Hub {
* @returns {Promise} Resolved upon successful completion of command. * @returns {Promise} Resolved upon successful completion of command.
*/ */
public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) { public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) {
const portObj = this._portLookup(port);
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._calculateRamp(fromSpeed, toSpeed, time) this._calculateRamp(fromSpeed, toSpeed, time, portObj)
.on("changeSpeed", (speed) => { .on("changeSpeed", (speed) => {
this.setMotorSpeed(port, speed); this.setMotorSpeed(port, speed, true);
}) })
.on("finished", resolve); .on("finished", resolve);
}); });
@ -138,15 +151,17 @@ export class PUPHub extends LPF2Hub {
*/ */
public setLightBrightness (port: string, brightness: number, time?: number) { public setLightBrightness (port: string, brightness: number, time?: number) {
const portObj = this._portLookup(port); const portObj = this._portLookup(port);
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]); const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]);
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
if (time) { if (time) {
setTimeout(() => { const timeout = global.setTimeout(() => {
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]); const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data); this._writeMessage(Consts.BLECharacteristics.LPF2_ALL, data);
return resolve(); return resolve();
}, time); }, time);
portObj.setEventTimer(timeout);
} else { } else {
return resolve(); return resolve();
} }

View File

@ -123,14 +123,26 @@ export class WeDo2SmartHub extends Hub {
* @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. * @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely.
* @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished. * @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished.
*/ */
public setMotorSpeed (port: string, speed: number, time?: number) { public setMotorSpeed (port: string, speed: number, time?: number | boolean) {
const portObj = this._portLookup(port);
let cancelEventTimer = true;
if (typeof time === "boolean") {
if (time === true) {
cancelEventTimer = false;
}
time = undefined;
}
if (cancelEventTimer) {
portObj.cancelEventTimer();
}
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([this._portLookup(port).value, 0x01, 0x02, this._mapSpeed(speed)])); this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([portObj.value, 0x01, 0x02, this._mapSpeed(speed)]));
if (time) { if (time && typeof time === "number") {
setTimeout(() => { const timeout = global.setTimeout(() => {
this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([this._portLookup(port).value, 0x01, 0x02, 0x00])); this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([portObj.value, 0x01, 0x02, 0x00]));
return resolve(); return resolve();
}, time); }, time);
portObj.setEventTimer(timeout);
} else { } else {
return resolve(); return resolve();
} }
@ -148,10 +160,12 @@ export class WeDo2SmartHub extends Hub {
* @returns {Promise} Resolved upon successful completion of command. * @returns {Promise} Resolved upon successful completion of command.
*/ */
public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) { public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) {
const portObj = this._portLookup(port);
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._calculateRamp(fromSpeed, toSpeed, time) this._calculateRamp(fromSpeed, toSpeed, time, portObj)
.on("changeSpeed", (speed) => { .on("changeSpeed", (speed) => {
this.setMotorSpeed(port, speed); this.setMotorSpeed(port, speed, true);
}) })
.on("finished", resolve); .on("finished", resolve);
}); });
@ -171,7 +185,7 @@ export class WeDo2SmartHub extends Hub {
data.writeUInt16LE(frequency, 3); data.writeUInt16LE(frequency, 3);
data.writeUInt16LE(time, 5); data.writeUInt16LE(time, 5);
this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, data); this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, data);
setTimeout(resolve, time); global.setTimeout(resolve, time);
}); });
} }
@ -186,15 +200,17 @@ export class WeDo2SmartHub extends Hub {
*/ */
public setLightBrightness (port: string, brightness: number, time?: number) { public setLightBrightness (port: string, brightness: number, time?: number) {
const portObj = this._portLookup(port); const portObj = this._portLookup(port);
portObj.cancelEventTimer();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const data = Buffer.from([portObj.value, 0x01, 0x02, brightness]); const data = Buffer.from([portObj.value, 0x01, 0x02, brightness]);
this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, data); this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, data);
if (time) { if (time) {
setTimeout(() => { const timeout = global.setTimeout(() => {
const data = Buffer.from([portObj.value, 0x01, 0x02, 0x00]); const data = Buffer.from([portObj.value, 0x01, 0x02, 0x00]);
this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, data); this._writeMessage(Consts.BLECharacteristics.WEDO2_MOTOR_VALUE_WRITE, data);
return resolve(); return resolve();
}, time); }, time);
portObj.setEventTimer(timeout);
} else { } else {
return resolve(); return resolve();
} }