Basic implementation of BasicMotor types

This commit is contained in:
Nathan Kellenicki 2019-12-06 11:31:56 -08:00
parent eb6b20adbb
commit d453fe52fb
22 changed files with 437 additions and 206 deletions

39
src/basicmotor.ts Normal file
View 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);
}
}

View File

@ -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);

View 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);
}
}

View File

@ -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,

View File

@ -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);

View 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
View 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);
}
}

View File

@ -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();
});
}

View File

@ -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,33 +287,48 @@ 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`);
this._attachedDevices.push(device);
}
/**
* Emits when an attached motor or sensor is detached from the Hub.
* @event Hub#detach
* @param {string} port
* Emits when a device is attached to the Hub.
* @event Hub#attach
* @param {Device} device
*/
if (this._virtualPorts[port.id]) {
delete this._virtualPorts[port.id];
}
this.emit("detach", port.id);
}
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;

View File

@ -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
};

View File

@ -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
};

View File

@ -1,6 +1,6 @@
import { EventEmitter } from "events";
export interface IBLEDevice extends EventEmitter {
export interface IBLEAbstraction extends EventEmitter {
uuid: string;
name: string;
connecting: boolean;

View File

@ -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) {
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;
}
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;
}
} 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.

View File

@ -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;

View File

@ -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) => {

View File

@ -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";

View File

@ -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);

View File

@ -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 = {

View 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
View 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);
}
}

View File

@ -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;

View File

@ -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 (!port) {
return;
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;
}
port.connected = data[1] === 1 ? true : false;
this._registerDeviceAttachment(port, data[3]);
this._registerDeviceAttachment(device);
}
// 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.