Adding power and brightness ramping back in
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
63f1c10fcc
commit
5fde49c0c2
@ -44,6 +44,7 @@ export class AbsoluteMotor extends TachoMotor {
|
|||||||
if (this.isWeDo2SmartHub) {
|
if (this.isWeDo2SmartHub) {
|
||||||
throw new Error("Absolute positioning is not available on the WeDo 2.0 Smart Hub");
|
throw new Error("Absolute positioning is not available on the WeDo 2.0 Smart Hub");
|
||||||
}
|
}
|
||||||
|
this.cancelEventTimer();
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this._busy = true;
|
this._busy = true;
|
||||||
if (speed === undefined || speed === null) {
|
if (speed === undefined || speed === null) {
|
||||||
@ -78,6 +79,7 @@ export class AbsoluteMotor extends TachoMotor {
|
|||||||
if (this.isWeDo2SmartHub) {
|
if (this.isWeDo2SmartHub) {
|
||||||
throw new Error("Absolute positioning is not available on the WeDo 2.0 Smart Hub");
|
throw new Error("Absolute positioning is not available on the WeDo 2.0 Smart Hub");
|
||||||
}
|
}
|
||||||
|
this.cancelEventTimer();
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this._busy = true;
|
this._busy = true;
|
||||||
let message;
|
let message;
|
||||||
@ -97,6 +99,7 @@ export class AbsoluteMotor extends TachoMotor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async calibrateServo () {
|
public async calibrateServo () {
|
||||||
|
this.cancelEventTimer();
|
||||||
const oldMode = this.mode;
|
const oldMode = this.mode;
|
||||||
let currentAngle = 0;
|
let currentAngle = 0;
|
||||||
const listener = ({ angle }: { angle: number }) => {
|
const listener = ({ angle }: { angle: number }) => {
|
||||||
@ -142,6 +145,7 @@ export class AbsoluteMotor extends TachoMotor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async resetServo (angle: number) {
|
public async resetServo (angle: number) {
|
||||||
|
this.cancelEventTimer();
|
||||||
const oldMode = this.mode;
|
const oldMode = this.mode;
|
||||||
let currentAngle = 0;
|
let currentAngle = 0;
|
||||||
const listener = ({ angle }: { angle: number }) => {
|
const listener = ({ angle }: { angle: number }) => {
|
||||||
|
@ -4,7 +4,7 @@ import { IDeviceInterface } from "../interfaces";
|
|||||||
|
|
||||||
import * as Consts from "../consts";
|
import * as Consts from "../consts";
|
||||||
|
|
||||||
import { mapSpeed } from "../utils";
|
import { calculateRamp, mapSpeed } from "../utils";
|
||||||
|
|
||||||
export class BasicMotor extends Device {
|
export class BasicMotor extends Device {
|
||||||
|
|
||||||
@ -20,7 +20,10 @@ export class BasicMotor extends Device {
|
|||||||
* @param {number} power For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
|
* @param {number} power For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
|
||||||
* @returns {Promise} Resolved upon successful completion of command.
|
* @returns {Promise} Resolved upon successful completion of command.
|
||||||
*/
|
*/
|
||||||
public setPower (power: number) {
|
public setPower (power: number, interrupt: boolean = true) {
|
||||||
|
if (interrupt) {
|
||||||
|
this.cancelEventTimer();
|
||||||
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.writeDirect(0x00, Buffer.from([mapSpeed(power)]));
|
this.writeDirect(0x00, Buffer.from([mapSpeed(power)]));
|
||||||
return resolve();
|
return resolve();
|
||||||
@ -28,12 +31,33 @@ export class BasicMotor extends Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ramp the motor power.
|
||||||
|
* @method BasicMotor#rampPower
|
||||||
|
* @param {number} fromPower For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
|
||||||
|
* @param {number} toPower For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
|
||||||
|
* @param {number} time How long the ramp should last (in milliseconds).
|
||||||
|
* @returns {Promise} Resolved upon successful completion of command.
|
||||||
|
*/
|
||||||
|
public rampPower (fromPower: number, toPower: number, time: number) {
|
||||||
|
this.cancelEventTimer();
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
calculateRamp(this, fromPower, toPower, time)
|
||||||
|
.on("changePower", (power) => {
|
||||||
|
this.setPower(power, false);
|
||||||
|
})
|
||||||
|
.on("finished", resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the motor.
|
* Stop the motor.
|
||||||
* @method BasicMotor#stop
|
* @method BasicMotor#stop
|
||||||
* @returns {Promise} Resolved upon successful completion of command.
|
* @returns {Promise} Resolved upon successful completion of command.
|
||||||
*/
|
*/
|
||||||
public stop () {
|
public stop () {
|
||||||
|
this.cancelEventTimer();
|
||||||
return this.setPower(0);
|
return this.setPower(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +68,7 @@ export class BasicMotor extends Device {
|
|||||||
* @returns {Promise} Resolved upon successful completion of command.
|
* @returns {Promise} Resolved upon successful completion of command.
|
||||||
*/
|
*/
|
||||||
public brake () {
|
public brake () {
|
||||||
|
this.cancelEventTimer();
|
||||||
return this.setPower(127);
|
return this.setPower(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ export class Device extends EventEmitter {
|
|||||||
|
|
||||||
private _isWeDo2SmartHub: boolean;
|
private _isWeDo2SmartHub: boolean;
|
||||||
private _isVirtualPort: boolean = false;
|
private _isVirtualPort: boolean = false;
|
||||||
|
private _eventTimer: NodeJS.Timer | null = null;
|
||||||
|
|
||||||
constructor (hub: IDeviceInterface, portId: number, modeMap: {[event: string]: number} = {}, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) {
|
constructor (hub: IDeviceInterface, portId: number, modeMap: {[event: string]: number} = {}, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) {
|
||||||
super();
|
super();
|
||||||
@ -136,6 +137,17 @@ export class Device extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setEventTimer (timer: NodeJS.Timer) {
|
||||||
|
this._eventTimer = timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancelEventTimer () {
|
||||||
|
if (this._eventTimer) {
|
||||||
|
clearTimeout(this._eventTimer);
|
||||||
|
this._eventTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _ensureConnected () {
|
private _ensureConnected () {
|
||||||
if (!this.connected) {
|
if (!this.connected) {
|
||||||
throw new Error("Device is not connected");
|
throw new Error("Device is not connected");
|
||||||
|
@ -3,6 +3,7 @@ import { Device } from "./device";
|
|||||||
import { IDeviceInterface } from "../interfaces";
|
import { IDeviceInterface } from "../interfaces";
|
||||||
|
|
||||||
import * as Consts from "../consts";
|
import * as Consts from "../consts";
|
||||||
|
import { calculateRamp } from "../utils";
|
||||||
|
|
||||||
export class Light extends Device {
|
export class Light extends Device {
|
||||||
|
|
||||||
@ -14,11 +15,14 @@ export class Light extends Device {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the light brightness.
|
* Set the light brightness.
|
||||||
* @method Light#brightness
|
* @method Light#setBrightness
|
||||||
* @param {number} brightness Brightness value between 0-100 (0 is off)
|
* @param {number} brightness Brightness value between 0-100 (0 is off)
|
||||||
* @returns {Promise} Resolved upon successful completion of command.
|
* @returns {Promise} Resolved upon successful completion of command.
|
||||||
*/
|
*/
|
||||||
public setBrightness (brightness: number) {
|
public setBrightness (brightness: number, interrupt: boolean = true) {
|
||||||
|
if (interrupt) {
|
||||||
|
this.cancelEventTimer();
|
||||||
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.writeDirect(0x00, Buffer.from([brightness]));
|
this.writeDirect(0x00, Buffer.from([brightness]));
|
||||||
return resolve();
|
return resolve();
|
||||||
@ -26,4 +30,24 @@ export class Light extends Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ramp the light brightness.
|
||||||
|
* @method Light#rampBrightness
|
||||||
|
* @param {number} fromBrightness Brightness value between 0-100 (0 is off)
|
||||||
|
* @param {number} toBrightness Brightness value between 0-100 (0 is off)
|
||||||
|
* @param {number} time How long the ramp should last (in milliseconds).
|
||||||
|
* @returns {Promise} Resolved upon successful completion of command.
|
||||||
|
*/
|
||||||
|
public rampBrightness (fromBrightness: number, toBrightness: number, time: number) {
|
||||||
|
this.cancelEventTimer();
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
calculateRamp(this, fromBrightness, toBrightness, time)
|
||||||
|
.on("changePower", (power) => {
|
||||||
|
this.setBrightness(power, false);
|
||||||
|
})
|
||||||
|
.on("finished", resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ export class TachoMotor extends BasicMotor {
|
|||||||
if (this.isWeDo2SmartHub) {
|
if (this.isWeDo2SmartHub) {
|
||||||
throw new Error("Motor speed is not available on the WeDo 2.0 Smart Hub");
|
throw new Error("Motor speed is not available on the WeDo 2.0 Smart Hub");
|
||||||
}
|
}
|
||||||
|
this.cancelEventTimer();
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this._busy = true;
|
this._busy = true;
|
||||||
if (speed === undefined || speed === null) {
|
if (speed === undefined || speed === null) {
|
||||||
@ -81,6 +82,7 @@ export class TachoMotor extends BasicMotor {
|
|||||||
if (this.isWeDo2SmartHub) {
|
if (this.isWeDo2SmartHub) {
|
||||||
throw new Error("Rotation is not available on the WeDo 2.0 Smart Hub");
|
throw new Error("Rotation is not available on the WeDo 2.0 Smart Hub");
|
||||||
}
|
}
|
||||||
|
this.cancelEventTimer();
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this._busy = true;
|
this._busy = true;
|
||||||
if (speed === undefined || speed === null) {
|
if (speed === undefined || speed === null) {
|
||||||
|
33
src/utils.ts
33
src/utils.ts
@ -1,3 +1,6 @@
|
|||||||
|
import { EventEmitter } from "events";
|
||||||
|
import { Device } from "./devices/device";
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export const isWebBluetooth = (typeof navigator !== "undefined" && navigator && navigator.bluetooth);
|
export const isWebBluetooth = (typeof navigator !== "undefined" && navigator && navigator.bluetooth);
|
||||||
|
|
||||||
@ -55,3 +58,33 @@ export const roundAngleToNearest90 = (angle: number) => {
|
|||||||
}
|
}
|
||||||
return -180;
|
return -180;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const calculateRamp = (device: Device, fromPower: number, toPower: number, time: number) => {
|
||||||
|
const emitter = new EventEmitter();
|
||||||
|
const steps = Math.abs(toPower - fromPower);
|
||||||
|
let delay = time / steps;
|
||||||
|
let increment = 1;
|
||||||
|
if (delay < 50 && steps > 0) {
|
||||||
|
increment = 50 / delay;
|
||||||
|
delay = 50;
|
||||||
|
}
|
||||||
|
if (fromPower > toPower) {
|
||||||
|
increment = -increment;
|
||||||
|
}
|
||||||
|
let i = 0;
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
let power = Math.round(fromPower + (++i * increment));
|
||||||
|
if (toPower > fromPower && power > toPower) {
|
||||||
|
power = toPower;
|
||||||
|
} else if (fromPower > toPower && power < toPower) {
|
||||||
|
power = toPower;
|
||||||
|
}
|
||||||
|
emitter.emit("changePower", power);
|
||||||
|
if (power === toPower) {
|
||||||
|
clearInterval(interval);
|
||||||
|
emitter.emit("finished");
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
|
device.setEventTimer(interval);
|
||||||
|
return emitter;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user