Basic implementation of BasicMotor types
This commit is contained in:
parent
eb6b20adbb
commit
d453fe52fb
39
src/basicmotor.ts
Normal file
39
src/basicmotor.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { Device } from "./device";
|
||||
import { Hub } from "./hub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
export class BasicMotor extends Device {
|
||||
|
||||
|
||||
constructor (hub: Hub, portId: number, type: number = Consts.DeviceType.UNKNOWN) {
|
||||
super(hub, portId, type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the motor speed.
|
||||
* @method BasicMotor#setSpeed
|
||||
* @param {number} speed 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.
|
||||
*/
|
||||
public setSpeed (speed: number) {
|
||||
return new Promise((resolve) => {
|
||||
const data = Buffer.from([0x81, this.portId, 0x11, 0x51, 0x00, speed]);
|
||||
this.send(data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fully (hard) stop the motor.
|
||||
* @method BasicMotor#brake
|
||||
* @returns {Promise} Resolved upon successful completion of command.
|
||||
*/
|
||||
public brake () {
|
||||
return this.setSpeed(127);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,7 +7,7 @@ import { Port } from "./port";
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("boostmovehub");
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
protected _currentPort = 0x3b;
|
||||
protected _voltagePort = 0x3c;
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.BOOST_MOVE_HUB;
|
||||
this._ports = {
|
||||
@ -102,17 +102,17 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x09, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
data.writeUInt16LE(time > 65535 ? 65535 : time, 4);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
} else {
|
||||
// @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)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
// @ts-ignore: The type of time is properly checked at the start
|
||||
}, time);
|
||||
@ -135,14 +135,14 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
// @ts-ignore: The type of speed is properly checked at the start
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x01, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
} else {
|
||||
// @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)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
}
|
||||
|
||||
}
|
||||
@ -204,7 +204,7 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
data.writeUInt32LE(angle, 4);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
@ -241,7 +241,7 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
data.writeInt32LE(pos, 4);
|
||||
}
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
@ -265,7 +265,7 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x02, 0x00, 0x00, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
@ -295,11 +295,11 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
portObj.cancelEventTimer();
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
if (time) {
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
}, time);
|
||||
portObj.setEventTimer(timeout);
|
||||
|
12
src/colordistancesensor.ts
Normal file
12
src/colordistancesensor.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Device } from "./device";
|
||||
import { Hub } from "./hub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
export class ColorDistanceSensor extends Device {
|
||||
|
||||
constructor (hub: Hub, portId: number) {
|
||||
super(hub, portId, Consts.DeviceType.COLOR_DISTANCE_SENSOR);
|
||||
}
|
||||
|
||||
}
|
@ -52,7 +52,7 @@ export const HubTypeNames = HubType;
|
||||
*/
|
||||
export enum DeviceType {
|
||||
UNKNOWN = 0,
|
||||
BASIC_MOTOR = 1,
|
||||
SIMPLE_MEDIUM_LINEAR_MOTOR = 1,
|
||||
TRAIN_MOTOR = 2,
|
||||
LED_LIGHTS = 8,
|
||||
VOLTAGE = 20,
|
||||
@ -61,7 +61,7 @@ export enum DeviceType {
|
||||
RGB_LIGHT = 23,
|
||||
WEDO2_TILT = 34,
|
||||
WEDO2_DISTANCE = 35,
|
||||
BOOST_DISTANCE = 37,
|
||||
COLOR_DISTANCE_SENSOR = 37,
|
||||
BOOST_TACHO_MOTOR = 38,
|
||||
BOOST_MOVE_HUB_MOTOR = 39,
|
||||
BOOST_TILT = 40,
|
||||
|
@ -6,7 +6,7 @@ import { Port } from "./port";
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("ControlPlusHub");
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
protected _voltageMaxRaw = 4095;
|
||||
protected _voltageMaxV = 9.615;
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.CONTROL_PLUS_HUB;
|
||||
this._ports = {
|
||||
@ -59,7 +59,7 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
debug("Connecting to Control+ Hub");
|
||||
await super.connect();
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, 0x3d, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01])); // Temperature
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, 0x3d, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01])); // Temperature
|
||||
debug("Connect completed");
|
||||
return resolve();
|
||||
});
|
||||
@ -107,17 +107,17 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x09, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
data.writeUInt16LE(time > 65535 ? 65535 : time, 4);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
} else {
|
||||
// @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)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
// @ts-ignore: The type of time is properly checked at the start
|
||||
}, time);
|
||||
@ -135,14 +135,14 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
// @ts-ignore: The type of speed is properly checked at the start
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x01, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
} else {
|
||||
// @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)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
}
|
||||
|
||||
}
|
||||
@ -204,7 +204,7 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
data.writeUInt32LE(angle, 4);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
@ -241,7 +241,7 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
data.writeInt32LE(pos, 4);
|
||||
}
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
@ -265,7 +265,7 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x02, 0x00, 0x00, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
@ -295,11 +295,11 @@ export class ControlPlusHub extends LPF2Hub {
|
||||
portObj.cancelEventTimer();
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
if (time) {
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
}, time);
|
||||
portObj.setEventTimer(timeout);
|
||||
|
12
src/controlpluslargemotor.ts
Normal file
12
src/controlpluslargemotor.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { BasicMotor } from "./basicmotor";
|
||||
import { Hub } from "./hub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
export class ControlPlusLargeMotor extends BasicMotor {
|
||||
|
||||
constructor (hub: Hub, portId: number) {
|
||||
super(hub, portId, Consts.DeviceType.CONTROL_PLUS_LARGE_MOTOR);
|
||||
}
|
||||
|
||||
}
|
45
src/device.ts
Normal file
45
src/device.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { EventEmitter } from "events";
|
||||
import { Hub } from "./hub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
export class Device extends EventEmitter {
|
||||
|
||||
private _hub: Hub;
|
||||
private _portId: number;
|
||||
private _connected: boolean = true;
|
||||
private _type: number;
|
||||
|
||||
constructor (hub: Hub, portId: number, type: number = Consts.DeviceType.UNKNOWN) {
|
||||
super();
|
||||
this._hub = hub;
|
||||
this._portId = portId;
|
||||
this._type = type;
|
||||
console.log(`New device on ${this._portId} - ${this._type}`);
|
||||
}
|
||||
|
||||
public get connected () {
|
||||
return this._connected;
|
||||
}
|
||||
|
||||
public get hub () {
|
||||
return this._hub;
|
||||
}
|
||||
|
||||
public get portId () {
|
||||
return this._portId;
|
||||
}
|
||||
|
||||
public get port () {
|
||||
return "A"; // TODO NK: Look up the port name from the relevant hub
|
||||
}
|
||||
|
||||
public get type () {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
public send (data: Buffer, characteristic: string = Consts.BLECharacteristic.LPF2_ALL, callback?: () => void) {
|
||||
this.hub.send(characteristic, data, callback);
|
||||
}
|
||||
|
||||
}
|
@ -6,7 +6,7 @@ import { Port } from "./port";
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("duplotrainbase");
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ export class DuploTrainBase extends LPF2Hub {
|
||||
protected _voltageMaxV = 6.4;
|
||||
protected _voltageMaxRaw = 3047;
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.DUPLO_TRAIN_HUB;
|
||||
this._ports = {
|
||||
@ -80,16 +80,16 @@ export class DuploTrainBase extends LPF2Hub {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (time && typeof time === "number") {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
}, time);
|
||||
portObj.setEventTimer(timeout);
|
||||
} else {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
}
|
||||
});
|
||||
@ -138,7 +138,7 @@ export class DuploTrainBase extends LPF2Hub {
|
||||
public playSound (sound: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = Buffer.from([0x81, 0x01, 0x11, 0x51, 0x01, sound]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
83
src/hub.ts
83
src/hub.ts
@ -1,11 +1,12 @@
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { Device } from "./device";
|
||||
const debug = Debug("hub");
|
||||
|
||||
|
||||
@ -20,6 +21,8 @@ export class Hub extends EventEmitter {
|
||||
public useSpeedMap: boolean = true;
|
||||
public type: Consts.HubType = Consts.HubType.UNKNOWN;
|
||||
|
||||
protected _attachedDevices: Device[] = [];
|
||||
|
||||
protected _ports: {[port: string]: Port} = {};
|
||||
protected _virtualPorts: {[port: string]: Port} = {};
|
||||
|
||||
@ -32,12 +35,12 @@ export class Hub extends EventEmitter {
|
||||
protected _current: number = 0;
|
||||
protected _rssi: number = -60;
|
||||
|
||||
protected _bleDevice: IBLEDevice;
|
||||
protected _bleDevice: IBLEAbstraction;
|
||||
|
||||
private _isConnecting = false;
|
||||
private _isConnected = false;
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super();
|
||||
this.autoSubscribe = !!autoSubscribe;
|
||||
this._bleDevice = device;
|
||||
@ -246,6 +249,13 @@ export class Hub extends EventEmitter {
|
||||
}
|
||||
|
||||
|
||||
public send (uuid: string, message: Buffer, callback?: () => void) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// protected _getCharacteristic (uuid: string) {
|
||||
// return this._characteristics[uuid.replace(/-/g, "")];
|
||||
// }
|
||||
@ -277,34 +287,49 @@ export class Hub extends EventEmitter {
|
||||
}
|
||||
|
||||
|
||||
protected _registerDeviceAttachment (port: Port, type: number) {
|
||||
protected _registerDeviceAttachment (device: Device) {
|
||||
|
||||
if (port.connected) {
|
||||
port.type = type;
|
||||
if (this.autoSubscribe) {
|
||||
this._activatePortDevice(port.value, type, this._getModeForDeviceType(type), 0x00);
|
||||
}
|
||||
/**
|
||||
* Emits when a motor or sensor is attached to the Hub.
|
||||
* @event Hub#attach
|
||||
* @param {string} port
|
||||
* @param {DeviceType} type
|
||||
*/
|
||||
this.emit("attach", port.id, type);
|
||||
const exists = this._attachedDevices.find((attachedDevice) => attachedDevice.portId === device.portId);
|
||||
|
||||
if (exists) {
|
||||
// TODO NK: Remove existing zombie device
|
||||
} else {
|
||||
port.type = Consts.DeviceType.UNKNOWN;
|
||||
debug(`Port ${port.id} disconnected`);
|
||||
/**
|
||||
* Emits when an attached motor or sensor is detached from the Hub.
|
||||
* @event Hub#detach
|
||||
* @param {string} port
|
||||
*/
|
||||
if (this._virtualPorts[port.id]) {
|
||||
delete this._virtualPorts[port.id];
|
||||
}
|
||||
this.emit("detach", port.id);
|
||||
this._attachedDevices.push(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits when a device is attached to the Hub.
|
||||
* @event Hub#attach
|
||||
* @param {Device} device
|
||||
*/
|
||||
this.emit("attach", device);
|
||||
|
||||
// if (port.connected) {
|
||||
// port.type = type;
|
||||
// if (this.autoSubscribe) {
|
||||
// this._activatePortDevice(port.value, type, this._getModeForDeviceType(type), 0x00);
|
||||
// }
|
||||
// /**
|
||||
// * Emits when a motor or sensor is attached to the Hub.
|
||||
// * @event Hub#attach
|
||||
// * @param {string} port
|
||||
// * @param {DeviceType} type
|
||||
// */
|
||||
// this.emit("attach", port.id, type);
|
||||
// } else {
|
||||
// port.type = Consts.DeviceType.UNKNOWN;
|
||||
// debug(`Port ${port.id} disconnected`);
|
||||
// /**
|
||||
// * Emits when an attached motor or sensor is detached from the Hub.
|
||||
// * @event Hub#detach
|
||||
// * @param {string} port
|
||||
// */
|
||||
// if (this._virtualPorts[port.id]) {
|
||||
// delete this._virtualPorts[port.id];
|
||||
// }
|
||||
// this.emit("detach", port.id);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -388,7 +413,7 @@ export class Hub extends EventEmitter {
|
||||
|
||||
private _getModeForDeviceType (type: Consts.DeviceType) {
|
||||
switch (type) {
|
||||
case Consts.DeviceType.BASIC_MOTOR:
|
||||
case Consts.DeviceType.SIMPLE_MEDIUM_LINEAR_MOTOR:
|
||||
return 0x02;
|
||||
case Consts.DeviceType.TRAIN_MOTOR:
|
||||
return 0x02;
|
||||
@ -404,7 +429,7 @@ export class Hub extends EventEmitter {
|
||||
return 0x00;
|
||||
case Consts.DeviceType.CONTROL_PLUS_ACCELEROMETER:
|
||||
return 0x00;
|
||||
case Consts.DeviceType.BOOST_DISTANCE:
|
||||
case Consts.DeviceType.COLOR_DISTANCE_SENSOR:
|
||||
return (this.type === Consts.HubType.WEDO2_SMART_HUB ? 0x00 : 0x08);
|
||||
case Consts.DeviceType.BOOST_TILT:
|
||||
return 0x04;
|
||||
|
@ -1,15 +1,35 @@
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import { PoweredUP } from "./poweredup-browser";
|
||||
|
||||
import { BoostMoveHub } from "./boostmovehub";
|
||||
import { ControlPlusHub } from "./controlplushub";
|
||||
import { DuploTrainBase } from "./duplotrainbase";
|
||||
import { Hub } from "./hub";
|
||||
import { PoweredUP } from "./poweredup-browser";
|
||||
import { PUPHub } from "./puphub";
|
||||
import { PUPRemote } from "./pupremote";
|
||||
import { WeDo2SmartHub } from "./wedo2smarthub";
|
||||
|
||||
import { ColorDistanceSensor } from "./colordistancesensor";
|
||||
import { ControlPlusLargeMotor } from "./controlpluslargemotor";
|
||||
import { Device } from "./device";
|
||||
|
||||
import { isWebBluetooth } from "./utils";
|
||||
|
||||
// @ts-ignore
|
||||
window.PoweredUP = { PoweredUP, Hub, WeDo2SmartHub, BoostMoveHub, ControlPlusHub, PUPHub, PUPRemote, DuploTrainBase, Consts, isWebBluetooth };
|
||||
window.PoweredUP = {
|
||||
PoweredUP,
|
||||
Hub,
|
||||
WeDo2SmartHub,
|
||||
BoostMoveHub,
|
||||
ControlPlusHub,
|
||||
PUPHub,
|
||||
PUPRemote,
|
||||
DuploTrainBase,
|
||||
Consts,
|
||||
Device,
|
||||
ColorDistanceSensor,
|
||||
ControlPlusLargeMotor,
|
||||
isWebBluetooth
|
||||
};
|
||||
|
||||
|
@ -1,15 +1,34 @@
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import { PoweredUP } from "./poweredup-node";
|
||||
|
||||
import { BoostMoveHub } from "./boostmovehub";
|
||||
import { ControlPlusHub } from "./controlplushub";
|
||||
import { DuploTrainBase } from "./duplotrainbase";
|
||||
import { Hub } from "./hub";
|
||||
import { PoweredUP } from "./poweredup-node";
|
||||
import { PUPHub } from "./puphub";
|
||||
import { PUPRemote } from "./pupremote";
|
||||
import { WeDo2SmartHub } from "./wedo2smarthub";
|
||||
|
||||
import { ColorDistanceSensor } from "./colordistancesensor";
|
||||
import { ControlPlusLargeMotor } from "./controlpluslargemotor";
|
||||
import { Device } from "./device";
|
||||
|
||||
import { isWebBluetooth } from "./utils";
|
||||
|
||||
export default PoweredUP;
|
||||
export { PoweredUP, Hub, WeDo2SmartHub, BoostMoveHub, ControlPlusHub, PUPHub, PUPRemote, DuploTrainBase, Consts, isWebBluetooth };
|
||||
export {
|
||||
PoweredUP,
|
||||
Hub,
|
||||
WeDo2SmartHub,
|
||||
BoostMoveHub,
|
||||
ControlPlusHub,
|
||||
PUPHub,
|
||||
PUPRemote,
|
||||
DuploTrainBase,
|
||||
Consts,
|
||||
Device,
|
||||
ColorDistanceSensor,
|
||||
ControlPlusLargeMotor,
|
||||
isWebBluetooth
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
export interface IBLEDevice extends EventEmitter {
|
||||
export interface IBLEAbstraction extends EventEmitter {
|
||||
uuid: string;
|
||||
name: string;
|
||||
connecting: boolean;
|
||||
|
159
src/lpf2hub.ts
159
src/lpf2hub.ts
@ -1,8 +1,10 @@
|
||||
import { Peripheral } from "@abandonware/noble";
|
||||
|
||||
import { Device } from "./device";
|
||||
import { Hub } from "./hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import { ColorDistanceSensor } from "./colordistancesensor";
|
||||
import { ControlPlusLargeMotor } from "./controlpluslargemotor";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
import { toBin, toHex } from "./utils";
|
||||
|
||||
@ -46,21 +48,21 @@ export class LPF2Hub extends Hub {
|
||||
await this._bleDevice.discoverCharacteristicsForService(Consts.BLEService.LPF2_HUB);
|
||||
this._bleDevice.subscribeToCharacteristic(Consts.BLECharacteristic.LPF2_ALL, this._parseMessage.bind(this));
|
||||
if (this._voltagePort !== undefined) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, this._voltagePort, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])); // Activate voltage reports
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, this._voltagePort, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])); // Activate voltage reports
|
||||
}
|
||||
if (this._currentPort !== undefined) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, this._currentPort, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])); // Activate current reports
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, this._currentPort, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])); // Activate current reports
|
||||
}
|
||||
if (this.type === Consts.HubType.DUPLO_TRAIN_HUB) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]));
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01]));
|
||||
}
|
||||
await this.sleep(100);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x02, 0x02])); // Activate button reports
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x03, 0x05])); // Request firmware version
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x04, 0x05])); // Request hardware version
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x05, 0x02])); // Activate RSSI updates
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x06, 0x02])); // Activate battery level reports
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x0d, 0x05])); // Request primary MAC address
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x02, 0x02])); // Activate button reports
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x03, 0x05])); // Request firmware version
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x04, 0x05])); // Request hardware version
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x05, 0x02])); // Activate RSSI updates
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x06, 0x02])); // Activate battery level reports
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x01, 0x0d, 0x05])); // Request primary MAC address
|
||||
this.emit("connect");
|
||||
resolve();
|
||||
});
|
||||
@ -74,7 +76,7 @@ export class LPF2Hub extends Hub {
|
||||
*/
|
||||
public shutdown () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x02, 0x01]), () => {
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x02, 0x01]), () => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
@ -95,8 +97,8 @@ export class LPF2Hub extends Hub {
|
||||
let data = Buffer.from([0x01, 0x01, 0x01]);
|
||||
data = Buffer.concat([data, Buffer.from(name, "ascii")]);
|
||||
// Send this twice, as sometimes the first time doesn't take
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this._name = name;
|
||||
return resolve();
|
||||
});
|
||||
@ -112,12 +114,12 @@ export class LPF2Hub extends Hub {
|
||||
public setLEDColor (color: number | boolean) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = Buffer.from([0x41, this._ledPort, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
if (typeof color === "boolean") {
|
||||
color = 0;
|
||||
}
|
||||
data = Buffer.from([0x81, this._ledPort, 0x11, 0x51, 0x00, color]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
@ -134,9 +136,9 @@ export class LPF2Hub extends Hub {
|
||||
public setLEDRGB (red: number, green: number, blue: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = Buffer.from([0x41, this._ledPort, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
data = Buffer.from([0x81, this._ledPort, 0x11, 0x51, 0x01, red, green, blue]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
@ -144,24 +146,14 @@ export class LPF2Hub extends Hub {
|
||||
|
||||
public sendRaw (message: Buffer) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, message, () => {
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, message, () => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected _activatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, port, mode, 0x01, 0x00, 0x00, 0x00, 0x01]), callback);
|
||||
}
|
||||
|
||||
|
||||
protected _deactivatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, port, mode, 0x01, 0x00, 0x00, 0x00, 0x00]), callback);
|
||||
}
|
||||
|
||||
|
||||
protected _writeMessage (uuid: string, message: Buffer, callback?: () => void) {
|
||||
public send (uuid: string, message: Buffer, callback?: () => void) {
|
||||
message = Buffer.concat([Buffer.alloc(2), message]);
|
||||
message[0] = message.length;
|
||||
debug("Sent Message (LPF2_ALL)", message);
|
||||
@ -169,6 +161,16 @@ export class LPF2Hub extends Hub {
|
||||
}
|
||||
|
||||
|
||||
protected _activatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, port, mode, 0x01, 0x00, 0x00, 0x00, 0x01]), callback);
|
||||
}
|
||||
|
||||
|
||||
protected _deactivatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x41, port, mode, 0x01, 0x00, 0x00, 0x00, 0x00]), callback);
|
||||
}
|
||||
|
||||
|
||||
protected _combinePorts (port: string, type: number) {
|
||||
if (!this._ports[port]) {
|
||||
return;
|
||||
@ -178,7 +180,7 @@ export class LPF2Hub extends Hub {
|
||||
Object.keys(this._ports).forEach((id) => {
|
||||
if (this._ports[id].type === type && this._ports[id].value !== portObj.value && !this._virtualPorts[`${portObj.value < this._ports[id].value ? portObj.id : this._ports[id].id}${portObj.value > this._ports[id].value ? portObj.id : this._ports[id].id}`]) {
|
||||
debug("Combining ports", portObj.value < this._ports[id].value ? portObj.id : id, portObj.value > this._ports[id].value ? portObj.id : id);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x61, 0x01, portObj.value < this._ports[id].value ? portObj.value : this._ports[id].value, portObj.value > this._ports[id].value ? portObj.value : this._ports[id].value]));
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x61, 0x01, portObj.value < this._ports[id].value ? portObj.value : this._ports[id].value, portObj.value > this._ports[id].value ? portObj.value : this._ports[id].value]));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -291,48 +293,73 @@ export class LPF2Hub extends Hub {
|
||||
|
||||
private _parsePortMessage (data: Buffer) {
|
||||
|
||||
let port = this._getPortForPortNumber(data[3]);
|
||||
const type = data[4] ? data.readUInt16LE(5) : 0;
|
||||
const portId = data[3];
|
||||
const event = data[4];
|
||||
const deviceType = event ? data.readUInt16LE(5) : 0;
|
||||
|
||||
if (data[4] === 0x01 && modeInfoDebug.enabled) {
|
||||
const typeName = Consts.DeviceTypeNames[data[5]] || "unknown";
|
||||
modeInfoDebug(`Port ${toHex(data[3])}, type ${toHex(type, 4)} (${typeName})`);
|
||||
const hwVersion = LPF2Hub.decodeVersion(data.readInt32LE(7));
|
||||
const swVersion = LPF2Hub.decodeVersion(data.readInt32LE(11));
|
||||
modeInfoDebug(`Port ${toHex(data[3])}, hardware version ${hwVersion}, software version ${swVersion}`);
|
||||
this._sendPortInformationRequest(data[3]);
|
||||
}
|
||||
if (event === 0x01) {
|
||||
|
||||
if (!port) {
|
||||
if (data[4] === 0x02) {
|
||||
const portA = this._getPortForPortNumber(data[7]);
|
||||
const portB = this._getPortForPortNumber(data[8]);
|
||||
if (portA && portB) {
|
||||
this._virtualPorts[`${portA.id}${portB.id}`] = new Port(`${portA.id}${portB.id}`, data[3]);
|
||||
port = this._getPortForPortNumber(data[3]);
|
||||
if (port) {
|
||||
port.connected = true;
|
||||
this._registerDeviceAttachment(port, type);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
let device;
|
||||
|
||||
switch (deviceType) {
|
||||
case Consts.DeviceType.CONTROL_PLUS_LARGE_MOTOR:
|
||||
device = new ControlPlusLargeMotor(this, portId);
|
||||
break;
|
||||
case Consts.DeviceType.COLOR_DISTANCE_SENSOR:
|
||||
device = new ColorDistanceSensor(this, portId);
|
||||
break;
|
||||
default:
|
||||
device = new Device(this, portId, deviceType);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
port.connected = (data[4] === 0x01 || data[4] === 0x02) ? true : false;
|
||||
this._registerDeviceAttachment(port, type);
|
||||
|
||||
this._registerDeviceAttachment(device);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// let port = this._getPortForPortNumber(data[3]);
|
||||
|
||||
// if (data[4] === 0x01 && modeInfoDebug.enabled) {
|
||||
// const typeName = Consts.DeviceTypeNames[data[5]] || "unknown";
|
||||
// modeInfoDebug(`Port ${toHex(data[3])}, type ${toHex(deviceType, 4)} (${typeName})`);
|
||||
// const hwVersion = LPF2Hub.decodeVersion(data.readInt32LE(7));
|
||||
// const swVersion = LPF2Hub.decodeVersion(data.readInt32LE(11));
|
||||
// modeInfoDebug(`Port ${toHex(data[3])}, hardware version ${hwVersion}, software version ${swVersion}`);
|
||||
// this._sendPortInformationRequest(data[3]);
|
||||
// }
|
||||
|
||||
// if (!port) {
|
||||
// if (data[4] === 0x02) {
|
||||
// const portA = this._getPortForPortNumber(data[7]);
|
||||
// const portB = this._getPortForPortNumber(data[8]);
|
||||
// if (portA && portB) {
|
||||
// this._virtualPorts[`${portA.id}${portB.id}`] = new Port(`${portA.id}${portB.id}`, data[3]);
|
||||
// port = this._getPortForPortNumber(data[3]);
|
||||
// if (port) {
|
||||
// port.connected = true;
|
||||
// this._registerDeviceAttachment(port, deviceType);
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
// } else {
|
||||
// port.connected = (data[4] === 0x01 || data[4] === 0x02) ? true : false;
|
||||
// this._registerDeviceAttachment(port, deviceType);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
private _sendPortInformationRequest (port: number) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x21, port, 0x01]));
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x21, port, 0x02])); // Mode combinations
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x21, port, 0x01]));
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x21, port, 0x02])); // Mode combinations
|
||||
}
|
||||
|
||||
|
||||
@ -363,7 +390,7 @@ export class LPF2Hub extends Hub {
|
||||
|
||||
|
||||
private _sendModeInformationRequest (port: number, mode: number, type: number) {
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x22, port, mode, type]));
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, Buffer.from([0x22, port, mode, type]));
|
||||
}
|
||||
|
||||
|
||||
@ -461,7 +488,7 @@ export class LPF2Hub extends Hub {
|
||||
this.emit("distance", port.id, distance * 10);
|
||||
break;
|
||||
}
|
||||
case Consts.DeviceType.BOOST_DISTANCE: {
|
||||
case Consts.DeviceType.COLOR_DISTANCE_SENSOR: {
|
||||
|
||||
/**
|
||||
* Emits when a color sensor is activated.
|
||||
|
@ -2,11 +2,11 @@ import { Characteristic, Peripheral, Service } from "@abandonware/noble";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { EventEmitter } from "events";
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("bledevice");
|
||||
|
||||
|
||||
export class NobleDevice extends EventEmitter implements IBLEDevice {
|
||||
export class NobleDevice extends EventEmitter implements IBLEAbstraction {
|
||||
|
||||
private _noblePeripheral: Peripheral;
|
||||
|
@ -4,7 +4,7 @@ import { DuploTrainBase } from "./duplotrainbase";
|
||||
import { Hub } from "./hub";
|
||||
import { PUPHub } from "./puphub";
|
||||
import { PUPRemote } from "./pupremote";
|
||||
import { WebBLEDevice } from "./webbledevice";
|
||||
import { WebBLEDevice } from "./webbleabstraction";
|
||||
import { WeDo2SmartHub } from "./wedo2smarthub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
@ -12,7 +12,7 @@ import * as Consts from "./consts";
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("poweredup");
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ export class PoweredUP extends EventEmitter {
|
||||
}
|
||||
|
||||
|
||||
private _determineLPF2HubType (device: IBLEDevice): Promise<Consts.HubType> {
|
||||
private _determineLPF2HubType (device: IBLEAbstraction): Promise<Consts.HubType> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let buf: Buffer = Buffer.alloc(0);
|
||||
device.subscribeToCharacteristic(Consts.BLECharacteristic.LPF2_ALL, (data: Buffer) => {
|
||||
|
@ -4,7 +4,7 @@ import { BoostMoveHub } from "./boostmovehub";
|
||||
import { ControlPlusHub } from "./controlplushub";
|
||||
import { DuploTrainBase } from "./duplotrainbase";
|
||||
import { Hub } from "./hub";
|
||||
import { NobleDevice } from "./nobledevice";
|
||||
import { NobleDevice } from "./nobleabstraction";
|
||||
import { PUPHub } from "./puphub";
|
||||
import { PUPRemote } from "./pupremote";
|
||||
import { WeDo2SmartHub } from "./wedo2smarthub";
|
||||
|
@ -7,7 +7,7 @@ import { Port } from "./port";
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("puphub");
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ export class PUPHub extends LPF2Hub {
|
||||
protected _currentPort = 0x3b;
|
||||
protected _voltagePort = 0x3c;
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.POWERED_UP_HUB;
|
||||
this._ports = {
|
||||
@ -99,17 +99,17 @@ export class PUPHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x09, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
data.writeUInt16LE(time > 65535 ? 65535 : time, 4);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
} else {
|
||||
// @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)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
// @ts-ignore: The type of time is properly checked at the start
|
||||
}, time);
|
||||
@ -127,14 +127,14 @@ export class PUPHub extends LPF2Hub {
|
||||
// @ts-ignore: The type of speed is properly checked at the start
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x01, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
} else {
|
||||
// @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)]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
}
|
||||
|
||||
}
|
||||
@ -196,7 +196,7 @@ export class PUPHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
}
|
||||
data.writeUInt32LE(angle, 4);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
@ -233,7 +233,7 @@ export class PUPHub extends LPF2Hub {
|
||||
data = Buffer.from([0x81, portObj.value, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]);
|
||||
data.writeInt32LE(pos, 4);
|
||||
}
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
portObj.finished = () => {
|
||||
return resolve();
|
||||
};
|
||||
@ -257,23 +257,12 @@ export class PUPHub extends LPF2Hub {
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x02, 0x00, 0x00, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fully (hard) stop the motor on a given port.
|
||||
* @method PUPHub#brakeMotor
|
||||
* @param {string} port
|
||||
* @returns {Promise} Resolved upon successful completion of command.
|
||||
*/
|
||||
public brakeMotor (port: string) {
|
||||
return this.setMotorSpeed(port, 127);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the light brightness on a given port.
|
||||
* @method PUPHub#setLightBrightness
|
||||
@ -287,11 +276,11 @@ export class PUPHub extends LPF2Hub {
|
||||
portObj.cancelEventTimer();
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, brightness]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
if (time) {
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
this.send(Consts.BLECharacteristic.LPF2_ALL, data);
|
||||
return resolve();
|
||||
}, time);
|
||||
portObj.setEventTimer(timeout);
|
||||
|
@ -6,7 +6,7 @@ import { Port } from "./port";
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("pupremote");
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ export class PUPRemote extends LPF2Hub {
|
||||
protected _voltageMaxRaw = 3200;
|
||||
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.POWERED_UP_REMOTE;
|
||||
this._ports = {
|
||||
|
12
src/simplemediumlinearmotor.ts
Normal file
12
src/simplemediumlinearmotor.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { BasicMotor } from "./basicmotor";
|
||||
import { Hub } from "./hub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
export class SimpleMediumLinearMotor extends BasicMotor {
|
||||
|
||||
constructor (hub: Hub, portId: number) {
|
||||
super(hub, portId, Consts.DeviceType.SIMPLE_MEDIUM_LINEAR_MOTOR);
|
||||
}
|
||||
|
||||
}
|
12
src/trainmotor.ts
Normal file
12
src/trainmotor.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { BasicMotor } from "./basicmotor";
|
||||
import { Hub } from "./hub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
export class TrainMotor extends BasicMotor {
|
||||
|
||||
constructor (hub: Hub, portId: number) {
|
||||
super(hub, portId, Consts.DeviceType.TRAIN_MOTOR);
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import Debug = require("debug");
|
||||
import { EventEmitter } from "events";
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
const debug = Debug("bledevice");
|
||||
|
||||
|
||||
export class WebBLEDevice extends EventEmitter implements IBLEDevice {
|
||||
export class WebBLEDevice extends EventEmitter implements IBLEAbstraction {
|
||||
|
||||
private _webBLEServer: any;
|
||||
|
@ -1,12 +1,16 @@
|
||||
import { Peripheral } from "@abandonware/noble";
|
||||
|
||||
import { Device } from "./device";
|
||||
import { Hub } from "./hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import { ColorDistanceSensor } from "./colordistancesensor";
|
||||
import { ControlPlusLargeMotor } from "./controlpluslargemotor";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { IBLEAbstraction } from "./interfaces";
|
||||
import { isWebBluetooth } from "./utils";
|
||||
const debug = Debug("wedo2smarthub");
|
||||
|
||||
@ -32,7 +36,7 @@ export class WeDo2SmartHub extends Hub {
|
||||
private _lastTiltY: number = 0;
|
||||
|
||||
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEAbstraction, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.WEDO2_SMART_HUB;
|
||||
this._ports = {
|
||||
@ -111,8 +115,8 @@ export class WeDo2SmartHub extends Hub {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = Buffer.from(name, "ascii");
|
||||
// Send this twice, as sometimes the first time doesn't take
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_NAME_ID, data);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_NAME_ID, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_NAME_ID, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_NAME_ID, data);
|
||||
this._name = name;
|
||||
return resolve();
|
||||
});
|
||||
@ -128,12 +132,12 @@ export class WeDo2SmartHub extends Hub {
|
||||
public setLEDColor (color: number | boolean) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = Buffer.from([0x06, 0x17, 0x01, 0x01]);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, data);
|
||||
if (typeof color === "boolean") {
|
||||
color = 0;
|
||||
}
|
||||
data = Buffer.from([0x06, 0x04, 0x01, color]);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
@ -146,7 +150,7 @@ export class WeDo2SmartHub extends Hub {
|
||||
*/
|
||||
public shutdown () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_DISCONNECT, Buffer.from([0x00]), () => {
|
||||
this.send(Consts.BLECharacteristic.WEDO2_DISCONNECT, Buffer.from([0x00]), () => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
@ -164,9 +168,9 @@ export class WeDo2SmartHub extends Hub {
|
||||
public setLEDRGB (red: number, green: number, blue: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = Buffer.from([0x06, 0x17, 0x01, 0x02]);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, data);
|
||||
data = Buffer.from([0x06, 0x04, 0x03, red, green, blue]);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
@ -193,10 +197,10 @@ export class WeDo2SmartHub extends Hub {
|
||||
portObj.cancelEventTimer();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([portObj.value, 0x01, 0x02, this._mapSpeed(speed)]));
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([portObj.value, 0x01, 0x02, this._mapSpeed(speed)]));
|
||||
if (time && typeof time === "number") {
|
||||
const timeout = global.setTimeout(() => {
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([portObj.value, 0x01, 0x02, 0x00]));
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, Buffer.from([portObj.value, 0x01, 0x02, 0x00]));
|
||||
return resolve();
|
||||
}, time);
|
||||
portObj.setEventTimer(timeout);
|
||||
@ -252,7 +256,7 @@ export class WeDo2SmartHub extends Hub {
|
||||
const data = Buffer.from([0x05, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00]);
|
||||
data.writeUInt16LE(frequency, 3);
|
||||
data.writeUInt16LE(time, 5);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
global.setTimeout(resolve, time);
|
||||
});
|
||||
}
|
||||
@ -271,11 +275,11 @@ export class WeDo2SmartHub extends Hub {
|
||||
portObj.cancelEventTimer();
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = Buffer.from([portObj.value, 0x01, 0x02, brightness]);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
if (time) {
|
||||
const timeout = global.setTimeout(() => {
|
||||
const data = Buffer.from([portObj.value, 0x01, 0x02, 0x00]);
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
this.send(Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE, data);
|
||||
return resolve();
|
||||
}, time);
|
||||
portObj.setEventTimer(timeout);
|
||||
@ -286,26 +290,7 @@ export class WeDo2SmartHub extends Hub {
|
||||
}
|
||||
|
||||
|
||||
public sendRaw (message: Buffer, characteristic: string = Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._writeMessage(characteristic, message, () => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected _activatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, Buffer.from([0x01, 0x02, port, type, mode, 0x01, 0x00, 0x00, 0x00, format, 0x01]), callback);
|
||||
}
|
||||
|
||||
|
||||
protected _deactivatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this._writeMessage(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, Buffer.from([0x01, 0x02, port, type, mode, 0x01, 0x00, 0x00, 0x00, format, 0x00]), callback);
|
||||
}
|
||||
|
||||
|
||||
private _writeMessage (uuid: string, message: Buffer, callback?: () => void) {
|
||||
public send (uuid: string, message: Buffer, callback?: () => void) {
|
||||
if (debug.enabled) {
|
||||
debug(`Sent Message (${this._getCharacteristicNameFromUUID(uuid)})`, message);
|
||||
}
|
||||
@ -313,6 +298,16 @@ export class WeDo2SmartHub extends Hub {
|
||||
}
|
||||
|
||||
|
||||
protected _activatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this.send(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, Buffer.from([0x01, 0x02, port, type, mode, 0x01, 0x00, 0x00, 0x00, format, 0x01]), callback);
|
||||
}
|
||||
|
||||
|
||||
protected _deactivatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) {
|
||||
this.send(Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, Buffer.from([0x01, 0x02, port, type, mode, 0x01, 0x00, 0x00, 0x00, format, 0x00]), callback);
|
||||
}
|
||||
|
||||
|
||||
private _getCharacteristicNameFromUUID (uuid: string) {
|
||||
const keys = Object.keys(Consts.BLECharacteristic);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
@ -346,14 +341,38 @@ export class WeDo2SmartHub extends Hub {
|
||||
|
||||
debug("Received Message (WEDO2_PORT_TYPE)", data);
|
||||
|
||||
const port = this._getPortForPortNumber(data[0]);
|
||||
const portId = data[0];
|
||||
const event = data[1];
|
||||
const deviceType = event ? data[3] : 0;
|
||||
|
||||
if (event === 0x01) {
|
||||
|
||||
let device;
|
||||
|
||||
switch (deviceType) {
|
||||
case Consts.DeviceType.CONTROL_PLUS_LARGE_MOTOR:
|
||||
device = new ControlPlusLargeMotor(this, portId);
|
||||
break;
|
||||
case Consts.DeviceType.COLOR_DISTANCE_SENSOR:
|
||||
device = new ColorDistanceSensor(this, portId);
|
||||
break;
|
||||
default:
|
||||
device = new Device(this, portId);
|
||||
break;
|
||||
}
|
||||
|
||||
this._registerDeviceAttachment(device);
|
||||
|
||||
if (!port) {
|
||||
return;
|
||||
}
|
||||
|
||||
port.connected = data[1] === 1 ? true : false;
|
||||
this._registerDeviceAttachment(port, data[3]);
|
||||
// const port = this._getPortForPortNumber(data[0]);
|
||||
|
||||
// if (!port) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// port.connected = data[1] === 1 ? true : false;
|
||||
// this._registerDeviceAttachment(port, data[3]);
|
||||
|
||||
}
|
||||
|
||||
@ -408,7 +427,7 @@ export class WeDo2SmartHub extends Hub {
|
||||
this.emit("distance", port.id, distance * 10);
|
||||
break;
|
||||
}
|
||||
case Consts.DeviceType.BOOST_DISTANCE: {
|
||||
case Consts.DeviceType.COLOR_DISTANCE_SENSOR: {
|
||||
const distance = data[2];
|
||||
/**
|
||||
* Emits when a color sensor is activated.
|
||||
|
Loading…
x
Reference in New Issue
Block a user