diff --git a/examples/new_device_test.js b/examples/new_device_test.js index 6364a2b..188dde6 100644 --- a/examples/new_device_test.js +++ b/examples/new_device_test.js @@ -24,12 +24,37 @@ poweredUP.on("discover", async (hub) => { // Wait to discover hubs console.log(`Detached device ${device.type} from ${device.port}`); }); - if ( + if (( + device instanceof PoweredUP.SimpleMediumLinearMotor || + device instanceof PoweredUP.TrainMotor || + device instanceof PoweredUP.MediumLinearMotor || + device instanceof PoweredUP.TechnicLargeLinearMotor || + device instanceof PoweredUP.TechnicXLargeLinearMotor + ) && hub.type === PoweredUP.Consts.HubType.WEDO2_SMART_HUB) { + const motor = device; + + motor.on("rotate", (angle) => { + console.log(`Rotate ${angle}`); + }); + + motor.setPower(40); + await hub.sleep(2000); + motor.setPower(0); + await hub.sleep(2000); + motor.setPower(-40); + await hub.sleep(2000); + motor.setPower(0); + await hub.sleep(2000); + motor.setPower(20); + + } + + if (( // device instanceof PoweredUP.MoveHubMediumLinearMotor || device instanceof PoweredUP.MediumLinearMotor || device instanceof PoweredUP.TechnicLargeLinearMotor || device instanceof PoweredUP.TechnicXLargeLinearMotor - ) { + ) && hub.type !== PoweredUP.Consts.HubType.WEDO2_SMART_HUB) { const motor = device; motor.on("rotate", (angle) => { @@ -85,9 +110,9 @@ poweredUP.on("discover", async (hub) => { // Wait to discover hubs sensor.on("distance", (distance) => { console.log(`Distance ${distance}`); }); - sensor.on("color", (color) => { - console.log(`Color ${color}`); - }); + // sensor.on("color", (color) => { + // console.log(`Color ${color}`); + // }); } if (device instanceof PoweredUP.MotionSensor) { diff --git a/src/MoveHubMediumLinearMotor.ts b/src/MoveHubMediumLinearMotor.ts index ffb07a7..c0889fc 100644 --- a/src/MoveHubMediumLinearMotor.ts +++ b/src/MoveHubMediumLinearMotor.ts @@ -1,11 +1,12 @@ -import { Hub } from "./hub"; +import { TachoMotor } from "./tachomotor"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; -import { TachoMotor } from "./tachomotor"; export class MoveHubMediumLinearMotor extends TachoMotor { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.MOVE_HUB_MEDIUM_LINEAR_MOTOR); } diff --git a/src/basicmotor.ts b/src/basicmotor.ts index fc06356..2d6a5ea 100644 --- a/src/basicmotor.ts +++ b/src/basicmotor.ts @@ -1,6 +1,6 @@ import { Device } from "./device"; -import { Hub } from "./hub"; -import { WeDo2SmartHub } from "./wedo2smarthub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; @@ -9,7 +9,7 @@ import { mapSpeed } from "./utils"; export class BasicMotor extends Device { - constructor (hub: Hub, portId: number, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) { + constructor (hub: IDeviceInterface, portId: number, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) { super(hub, portId, type); } @@ -22,7 +22,8 @@ export class BasicMotor extends Device { */ public setPower (power: number) { return new Promise((resolve) => { - if (this.hub instanceof WeDo2SmartHub) { + const isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); + if (isWeDo2) { const data = Buffer.from([this.portId, 0x01, 0x02, mapSpeed(power)]); this.send(data, Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE); } else { diff --git a/src/colordistancesensor.ts b/src/colordistancesensor.ts index 2d2fc6d..05a66cc 100644 --- a/src/colordistancesensor.ts +++ b/src/colordistancesensor.ts @@ -1,18 +1,26 @@ import { Device } from "./device"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; export class ColorDistanceSensor extends Device { - constructor (hub: Hub, portId: number) { + private _isWeDo2: boolean; + + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.COLOR_DISTANCE_SENSOR); + this._isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); this.on("newListener", (event) => { if (this.autoSubscribe) { switch (event) { case "color": - this.subscribe(0x08); + if (this._isWeDo2) { + this.subscribe(0x00); + } else { + this.subscribe(0x08); + } break; case "distance": this.subscribe(0x08); @@ -28,7 +36,15 @@ export class ColorDistanceSensor extends Device { public receive (message: Buffer) { const mode = this._mode; + console.log(message); + switch (mode) { + case 0x00: + if (this._isWeDo2 && message[2] <= 10) { + const color = message[2]; + this.emit("color", color); + } + break; case 0x08: /** * Emits when a color sensor is activated. diff --git a/src/device.ts b/src/device.ts index 8d95041..f5dc017 100644 --- a/src/device.ts +++ b/src/device.ts @@ -1,5 +1,6 @@ import { EventEmitter } from "events"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; @@ -11,12 +12,12 @@ export class Device extends EventEmitter { protected _busy: boolean = false; protected _finished: (() => void) | undefined; - private _hub: Hub; + private _hub: IDeviceInterface; private _portId: number; private _connected: boolean = true; private _type: Consts.DeviceType; - constructor (hub: Hub, portId: number, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) { + constructor (hub: IDeviceInterface, portId: number, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) { super(); this._hub = hub; this._portId = portId; @@ -60,7 +61,7 @@ export class Device extends EventEmitter { this._ensureConnected(); if (mode !== this._mode) { this._mode = mode; - this.hub.subscribe(this.portId, mode); + this.hub.subscribe(this.portId, this.type, mode); } } diff --git a/src/duplotrainbase.ts b/src/duplotrainbase.ts index a28e1f4..294e650 100644 --- a/src/duplotrainbase.ts +++ b/src/duplotrainbase.ts @@ -50,7 +50,7 @@ export class DuploTrainBase extends LPF2Hub { return new Promise(async (resolve, reject) => { debug("Connecting to Duplo Train Base"); await super.connect(); - this.subscribe(0x01, 0x01); + // this.subscribe(0x01, Consts.DeviceType.DUPLO_TRAIN_BASE_SPEAKER, 0x01); debug("Connect completed"); return resolve(); }); diff --git a/src/hub.ts b/src/hub.ts index cc905e0..fb4185b 100644 --- a/src/hub.ts +++ b/src/hub.ts @@ -2,10 +2,21 @@ import { EventEmitter } from "events"; import { IBLEAbstraction } from "./interfaces"; +import { ColorDistanceSensor } from "./colordistancesensor"; +import { Device } from "./device"; +import { Light } from "./light"; +import { MediumLinearMotor } from "./mediumlinearmotor"; +import { MotionSensor } from "./motionsensor"; +import { MoveHubMediumLinearMotor } from "./movehubmediumlinearmotor"; +import { SimpleMediumLinearMotor } from "./simplemediumlinearmotor"; +import { TechnicLargeLinearMotor } from "./techniclargelinearmotor"; +import { TechnicXLargeLinearMotor } from "./technicxlargelinearmotor"; +import { TiltSensor } from "./tiltsensor"; +import { TrainMotor } from "./trainmotor"; + import * as Consts from "./consts"; import Debug = require("debug"); -import { Device } from "./device"; const debug = Debug("hub"); @@ -233,7 +244,7 @@ export class Hub extends EventEmitter { } - public subscribe (portId: number, mode: number) { + public subscribe (portId: number, deviceType: number, mode: number) { // NK Do nothing here } @@ -260,68 +271,52 @@ export class Hub extends EventEmitter { } + protected _createDevice (deviceType: number, portId: number) { + let device; + + switch (deviceType) { + case Consts.DeviceType.LIGHT: + device = new Light(this, portId); + break; + case Consts.DeviceType.TRAIN_MOTOR: + device = new TrainMotor(this, portId); + break; + case Consts.DeviceType.SIMPLE_MEDIUM_LINEAR_MOTOR: + device = new SimpleMediumLinearMotor(this, portId); + break; + case Consts.DeviceType.MOVE_HUB_MEDIUM_LINEAR_MOTOR: + device = new MoveHubMediumLinearMotor(this, portId); + break; + case Consts.DeviceType.MOTION_SENSOR: + device = new MotionSensor(this, portId); + break; + case Consts.DeviceType.TILT_SENSOR: + device = new TiltSensor(this, portId); + break; + case Consts.DeviceType.MEDIUM_LINEAR_MOTOR: + device = new MediumLinearMotor(this, portId); + break; + case Consts.DeviceType.TECHNIC_LARGE_LINEAR_MOTOR: + device = new TechnicLargeLinearMotor(this, portId); + break; + case Consts.DeviceType.TECHNIC_XLARGE_LINEAR_MOTOR: + device = new TechnicXLargeLinearMotor(this, portId); + break; + case Consts.DeviceType.COLOR_DISTANCE_SENSOR: + device = new ColorDistanceSensor(this, portId); + break; + default: + device = new Device(this, portId, deviceType); + break; + } + + return device; + } + + protected _getDeviceByPortId (portId: number) { return this._attachedDevices[portId]; } - // protected _calculateRamp (fromSpeed: number, toSpeed: number, time: number, port: Port) { - // const emitter = new EventEmitter(); - // const steps = Math.abs(toSpeed - fromSpeed); - // let delay = time / steps; - // let increment = 1; - // if (delay < 50 && steps > 0) { - // increment = 50 / delay; - // delay = 50; - // } - // if (fromSpeed > toSpeed) { - // increment = -increment; - // } - // let i = 0; - // const interval = setInterval(() => { - // let speed = Math.round(fromSpeed + (++i * increment)); - // if (toSpeed > fromSpeed && speed > toSpeed) { - // speed = toSpeed; - // } else if (fromSpeed > toSpeed && speed < toSpeed) { - // speed = toSpeed; - // } - // emitter.emit("changeSpeed", speed); - // if (speed === toSpeed) { - // clearInterval(interval); - // emitter.emit("finished"); - // } - // }, delay); - // port.setEventTimer(interval); - // return emitter; - // } - - - // private _getModeForDeviceType (type: Consts.DeviceType) { - // switch (type) { - // case Consts.DeviceType.SIMPLE_MEDIUM_LINEAR_MOTOR: - // return 0x02; - // case Consts.DeviceType.TRAIN_MOTOR: - // return 0x02; - // case Consts.DeviceType.BOOST_TACHO_MOTOR: - // return 0x02; - // case Consts.DeviceType.BOOST_MOVE_HUB_MOTOR: - // return 0x02; - // case Consts.DeviceType.CONTROL_PLUS_LARGE_MOTOR: - // return 0x02; - // case Consts.DeviceType.CONTROL_PLUS_XLARGE_MOTOR: - // return 0x02; - // case Consts.DeviceType.CONTROL_PLUS_TILT: - // return 0x00; - // case Consts.DeviceType.CONTROL_PLUS_ACCELEROMETER: - // return 0x00; - // case Consts.DeviceType.COLOR_DISTANCE_SENSOR: - // return (this.type === Consts.HubType.WEDO2_SMART_HUB ? 0x00 : 0x08); - // case Consts.DeviceType.BOOST_TILT: - // return 0x04; - // default: - // return 0x00; - // } - // } - - } diff --git a/src/interfaces.ts b/src/interfaces.ts index cdb1bce..ea7111c 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -1,5 +1,7 @@ import { EventEmitter } from "events"; +import * as Consts from "./consts"; + export interface IBLEAbstraction extends EventEmitter { uuid: string; name: string; @@ -13,3 +15,10 @@ export interface IBLEAbstraction extends EventEmitter { readFromCharacteristic: (uuid: string, callback: (err: string | null, data: Buffer | null) => void) => void; writeToCharacteristic: (uuid: string, data: Buffer, callback?: () => void) => void; } + +export interface IDeviceInterface extends EventEmitter { + type: Consts.HubType; + getPortNameForPortId: (portId: number) => string | undefined; + send: (message: Buffer, uuid: string, callback?: () => void) => void; + subscribe: (portId: number, deviceType: number, mode: number) => void; +} diff --git a/src/light.ts b/src/light.ts index fda7104..67a242e 100644 --- a/src/light.ts +++ b/src/light.ts @@ -1,13 +1,13 @@ import { Device } from "./device"; -import { Hub } from "./hub"; -import { WeDo2SmartHub } from "./wedo2smarthub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; export class Light extends Device { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.LIGHT); } @@ -20,7 +20,8 @@ export class Light extends Device { */ public setBrightness (brightness: number) { return new Promise((resolve) => { - if (this.hub instanceof WeDo2SmartHub) { + const isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); + if (isWeDo2) { const data = Buffer.from([this.portId, 0x01, 0x02, brightness]); this.send(data, Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE); } else { diff --git a/src/lpf2hub.ts b/src/lpf2hub.ts index bfd167a..6905e16 100644 --- a/src/lpf2hub.ts +++ b/src/lpf2hub.ts @@ -1,17 +1,5 @@ -import { Device } from "./device"; import { Hub } from "./hub"; -import { ColorDistanceSensor } from "./colordistancesensor"; -import { Light } from "./light"; -import { MediumLinearMotor } from "./mediumlinearmotor"; -import { MotionSensor } from "./motionsensor"; -import { MoveHubMediumLinearMotor } from "./movehubmediumlinearmotor"; -import { SimpleMediumLinearMotor } from "./simplemediumlinearmotor"; -import { TechnicLargeLinearMotor } from "./techniclargelinearmotor"; -import { TechnicXLargeLinearMotor } from "./technicxlargelinearmotor"; -import { TiltSensor } from "./tiltsensor"; -import { TrainMotor } from "./trainmotor"; - import * as Consts from "./consts"; import { decodeMACAddress, decodeVersion, toBin, toHex } from "./utils"; @@ -48,10 +36,10 @@ 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.subscribe(this._voltagePort, 0x00); // Activate voltage reports + this.subscribe(this._voltagePort, Consts.DeviceType.VOLTAGE, 0x00); // Activate voltage reports } if (this._currentPort !== undefined) { - this.subscribe(this._currentPort, 0x00); // Activate currrent reports + this.subscribe(this._currentPort, Consts.DeviceType.CURRENT, 0x00); // Activate currrent reports } await this.sleep(100); this.send(Buffer.from([0x01, 0x02, 0x02]), Consts.BLECharacteristic.LPF2_ALL); // Activate button reports @@ -149,7 +137,7 @@ export class LPF2Hub extends Hub { } - public subscribe (portId: number, mode: number) { + public subscribe (portId: number, deviceType: number, mode: number) { this.send(Buffer.from([0x41, portId, mode, 0x01, 0x00, 0x00, 0x00, 0x01]), Consts.BLECharacteristic.LPF2_ALL); } @@ -288,44 +276,6 @@ export class LPF2Hub extends Hub { // Handle device attachments if (event === 0x01) { - let device; - - switch (deviceType) { - case Consts.DeviceType.LIGHT: - device = new Light(this, portId); - break; - case Consts.DeviceType.TRAIN_MOTOR: - device = new TrainMotor(this, portId); - break; - case Consts.DeviceType.SIMPLE_MEDIUM_LINEAR_MOTOR: - device = new SimpleMediumLinearMotor(this, portId); - break; - case Consts.DeviceType.MOVE_HUB_MEDIUM_LINEAR_MOTOR: - device = new MoveHubMediumLinearMotor(this, portId); - break; - case Consts.DeviceType.MOTION_SENSOR: - device = new MotionSensor(this, portId); - break; - case Consts.DeviceType.TILT_SENSOR: - device = new TiltSensor(this, portId); - break; - case Consts.DeviceType.MEDIUM_LINEAR_MOTOR: - device = new MediumLinearMotor(this, portId); - break; - case Consts.DeviceType.TECHNIC_LARGE_LINEAR_MOTOR: - device = new TechnicLargeLinearMotor(this, portId); - break; - case Consts.DeviceType.TECHNIC_XLARGE_LINEAR_MOTOR: - device = new TechnicXLargeLinearMotor(this, portId); - break; - case Consts.DeviceType.COLOR_DISTANCE_SENSOR: - device = new ColorDistanceSensor(this, portId); - break; - default: - device = new Device(this, portId, deviceType); - break; - } - if (modeInfoDebug.enabled) { const deviceTypeName = Consts.DeviceTypeNames[message[5]] || "Unknown"; modeInfoDebug(`Port ${toHex(portId)}, type ${toHex(deviceType, 4)} (${deviceTypeName})`); @@ -335,6 +285,7 @@ export class LPF2Hub extends Hub { this._sendPortInformationRequest(portId); } + const device = this._createDevice(deviceType, portId); this._attachDevice(device); // Handle device detachments diff --git a/src/mediumlinearmotor.ts b/src/mediumlinearmotor.ts index 53680a6..b3af724 100644 --- a/src/mediumlinearmotor.ts +++ b/src/mediumlinearmotor.ts @@ -1,11 +1,12 @@ -import { Hub } from "./hub"; +import { TachoMotor } from "./tachomotor"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; -import { TachoMotor } from "./tachomotor"; export class MediumLinearMotor extends TachoMotor { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.MEDIUM_LINEAR_MOTOR); } diff --git a/src/motionsensor.ts b/src/motionsensor.ts index b68a0b0..e47d764 100644 --- a/src/motionsensor.ts +++ b/src/motionsensor.ts @@ -1,11 +1,12 @@ import { Device } from "./device"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; export class MotionSensor extends Device { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.MOTION_SENSOR); this.on("newListener", (event) => { @@ -21,12 +22,13 @@ export class MotionSensor extends Device { public receive (message: Buffer) { const mode = this._mode; + const isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); switch (mode) { case 0x00: - let distance = message[4]; - if (message[5] === 1) { - distance = message[4] + 255; + let distance = message[isWeDo2 ? 2 : 4]; + if (message[isWeDo2 ? 3 : 5] === 1) { + distance = distance + 255; } /** * Emits when a distance sensor is activated. diff --git a/src/simplemediumlinearmotor.ts b/src/simplemediumlinearmotor.ts index 824b0f3..41ca50b 100644 --- a/src/simplemediumlinearmotor.ts +++ b/src/simplemediumlinearmotor.ts @@ -1,11 +1,12 @@ import { BasicMotor } from "./basicmotor"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; export class SimpleMediumLinearMotor extends BasicMotor { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.SIMPLE_MEDIUM_LINEAR_MOTOR); } diff --git a/src/tachomotor.ts b/src/tachomotor.ts index 3fee32e..00cbe28 100644 --- a/src/tachomotor.ts +++ b/src/tachomotor.ts @@ -1,12 +1,13 @@ import { BasicMotor } from "./basicmotor"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; import { mapSpeed } from "./utils"; export class TachoMotor extends BasicMotor { - constructor (hub: Hub, portId: number, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) { + constructor (hub: IDeviceInterface, portId: number, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) { super(hub, portId, type); this.on("newListener", (event) => { @@ -22,10 +23,11 @@ export class TachoMotor extends BasicMotor { public receive (message: Buffer) { const mode = this._mode; + const isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); switch (mode) { case 0x02: - const rotation = message.readInt32LE(4); + const rotation = message.readInt32LE(isWeDo2 ? 2 : 4); /** * Emits when a rotation sensor is activated. * @event TachoMotor#rotate @@ -44,6 +46,10 @@ export class TachoMotor extends BasicMotor { * @returns {Promise} Resolved upon successful completion of command (ie. once the motor is finished). */ public rotateByAngle (angle: number, power: number = 100) { + const isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); + if (isWeDo2) { + throw new Error("Rotating by angle is not available on the WeDo 2.0 Smart Hub"); + } return new Promise((resolve) => { this._busy = true; const message = Buffer.from([0x81, this.portId, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x00, mapSpeed(power), 0x64, 0x7f, 0x03]); diff --git a/src/techniclargelinearmotor.ts b/src/techniclargelinearmotor.ts index 5f65f08..d68199e 100644 --- a/src/techniclargelinearmotor.ts +++ b/src/techniclargelinearmotor.ts @@ -1,11 +1,12 @@ -import { Hub } from "./hub"; +import { TachoMotor } from "./tachomotor"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; -import { TachoMotor } from "./tachomotor"; export class TechnicLargeLinearMotor extends TachoMotor { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.TECHNIC_LARGE_LINEAR_MOTOR); } diff --git a/src/technicxlargelinearmotor.ts b/src/technicxlargelinearmotor.ts index 4a24ccc..9974ce2 100644 --- a/src/technicxlargelinearmotor.ts +++ b/src/technicxlargelinearmotor.ts @@ -1,11 +1,12 @@ -import { Hub } from "./hub"; +import { TachoMotor } from "./tachomotor"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; -import { TachoMotor } from "./tachomotor"; export class TechnicXLargeLinearMotor extends TachoMotor { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.TECHNIC_XLARGE_LINEAR_MOTOR); } diff --git a/src/tiltsensor.ts b/src/tiltsensor.ts index 169c88a..e6f8a2a 100644 --- a/src/tiltsensor.ts +++ b/src/tiltsensor.ts @@ -1,11 +1,12 @@ import { Device } from "./device"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; export class TiltSensor extends Device { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.TILT_SENSOR); this.on("newListener", (event) => { @@ -21,11 +22,12 @@ export class TiltSensor extends Device { public receive (message: Buffer) { const mode = this._mode; + const isWeDo2 = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB); switch (mode) { case 0x00: - const tiltX = message.readInt8(4); - const tiltY = message.readInt8(5); + const tiltX = message.readInt8(isWeDo2 ? 2 : 4); + const tiltY = message.readInt8(isWeDo2 ? 3 : 5); /** * Emits when a tilt sensor is activated. * @event LPF2Hub#tilt diff --git a/src/trainmotor.ts b/src/trainmotor.ts index 6f590a6..ca591b2 100644 --- a/src/trainmotor.ts +++ b/src/trainmotor.ts @@ -1,11 +1,12 @@ import { BasicMotor } from "./basicmotor"; -import { Hub } from "./hub"; + +import { IDeviceInterface } from "./interfaces"; import * as Consts from "./consts"; export class TrainMotor extends BasicMotor { - constructor (hub: Hub, portId: number) { + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, Consts.DeviceType.TRAIN_MOTOR); } diff --git a/src/wedo2smarthub.ts b/src/wedo2smarthub.ts index dc81284..a08fdce 100644 --- a/src/wedo2smarthub.ts +++ b/src/wedo2smarthub.ts @@ -2,18 +2,8 @@ import { Peripheral } from "@abandonware/noble"; import { IBLEAbstraction } from "./interfaces"; -import { Device } from "./device"; import { Hub } from "./hub"; -import { ColorDistanceSensor } from "./colordistancesensor"; -import { Light } from "./light"; -import { MediumLinearMotor } from "./mediumlinearmotor"; -import { MoveHubMediumLinearMotor } from "./movehubmediumlinearmotor"; -import { SimpleMediumLinearMotor } from "./simplemediumlinearmotor"; -import { TechnicLargeLinearMotor } from "./techniclargelinearmotor"; -import { TechnicXLargeLinearMotor } from "./technicxlargelinearmotor"; -import { TrainMotor } from "./trainmotor"; - import * as Consts from "./consts"; import { isWebBluetooth } from "./utils"; @@ -67,8 +57,8 @@ export class WeDo2SmartHub extends Hub { await this._bleDevice.discoverCharacteristicsForService("battery_service"); await this._bleDevice.discoverCharacteristicsForService("device_information"); } - this._activatePortDevice(0x03, 0x15, 0x00, 0x00); // Activate voltage reports - this._activatePortDevice(0x04, 0x14, 0x00, 0x00); // Activate current reports + this.subscribe(0x03, 0x15, 0x00); // Activate voltage reports + this.subscribe(0x04, 0x14, 0x00); // Activate current reports debug("Connect completed"); this.emit("connect"); resolve(); @@ -230,8 +220,8 @@ export class WeDo2SmartHub extends Hub { } - protected _activatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) { - this.send(Buffer.from([0x01, 0x02, port, type, mode, 0x01, 0x00, 0x00, 0x00, format, 0x01]), Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE, callback); + public subscribe (portId: number, deviceType: number, mode: number) { + this.send(Buffer.from([0x01, 0x02, portId, deviceType, mode, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01]), Consts.BLECharacteristic.WEDO2_PORT_TYPE_WRITE); } @@ -277,47 +267,43 @@ export class WeDo2SmartHub extends Hub { const deviceType = event ? data[3] : 0; if (event === 0x01) { - - let device; - - switch (deviceType) { - case Consts.DeviceType.LIGHT: - device = new Light(this, portId); - break; - // case Consts.DeviceType.BOOST_TACHO_MOTOR: - // device = new BoostTachoMotor(this, portId); - // break; - // case Consts.DeviceType.CONTROL_PLUS_LARGE_MOTOR: - // device = new ControlPlusLargeMotor(this, portId); - // break; - // case Consts.DeviceType.CONTROL_PLUS_XLARGE_MOTOR: - // device = new ControlPlusXLargeMotor(this, portId); - // break; - case Consts.DeviceType.COLOR_DISTANCE_SENSOR: - device = new ColorDistanceSensor(this, portId); - break; - default: - device = new Device(this, portId, deviceType); - break; - } - + const device = this._createDevice(deviceType, portId); this._attachDevice(device); - + } else if (event === 0x00) { + const device = this._getDeviceByPortId(portId); + if (device) { + this._detachDevice(device); + } } } private _parseSensorMessage (message: Buffer) { + debug("Received Message (WEDO2_SENSOR_VALUE)", message); + + if (message[0] === 0x01) { + /** + * Emits when a button is pressed. + * @event WeDo2SmartHub#button + * @param {string} button + * @param {ButtonState} state + */ + this.emit("button", "GREEN", Consts.ButtonState.PRESSED); + return; + } else if (message[0] === 0x00) { + this.emit("button", "GREEN", Consts.ButtonState.RELEASED); + return; + } + const portId = message[1]; const device = this._getDeviceByPortId(portId); if (device) { + console.log(portId, device.type); device.receive(message); } - // debug("Received Message (WEDO2_SENSOR_VALUE)", data); - // if (data[0] === 0x01) { // /** // * Emits when a button is pressed. @@ -350,20 +336,6 @@ export class WeDo2SmartHub extends Hub { // if (port && port.connected) { // switch (port.type) { - // case Consts.DeviceType.WEDO2_DISTANCE: { - // let distance = data[2]; - // if (data[3] === 1) { - // distance = data[2] + 255; - // } - // /** - // * Emits when a distance sensor is activated. - // * @event WeDo2SmartHub#distance - // * @param {string} port - // * @param {number} distance Distance, in millimeters. - // */ - // this.emit("distance", port.id, distance * 10); - // break; - // } // case Consts.DeviceType.COLOR_DISTANCE_SENSOR: { // const distance = data[2]; // /** @@ -375,40 +347,6 @@ export class WeDo2SmartHub extends Hub { // this.emit("color", port.id, distance); // break; // } - // case Consts.DeviceType.WEDO2_TILT: { - // this._lastTiltX = data.readInt8(2); - // this._lastTiltY = data.readInt8(3); - // /** - // * Emits when a tilt sensor is activated. - // * @event WeDo2SmartHub#tilt - // * @param {string} port - // * @param {number} x - // * @param {number} y - // */ - // this.emit("tilt", port.id, this._lastTiltX, this._lastTiltY); - // break; - // } - // case Consts.DeviceType.BOOST_TACHO_MOTOR: { - // const rotation = data.readInt32LE(2); - // /** - // * Emits when a rotation sensor is activated. - // * @event WeDo2SmartHub#rotate - // * @param {string} port - // * @param {number} rotation - // */ - // this.emit("rotate", port.id, rotation); - // break; - // } - // case Consts.DeviceType.CONTROL_PLUS_LARGE_MOTOR: { - // const rotation = data.readInt32LE(2); - // this.emit("rotate", port.id, rotation); - // break; - // } - // case Consts.DeviceType.CONTROL_PLUS_XLARGE_MOTOR: { - // const rotation = data.readInt32LE(2); - // this.emit("rotate", port.id, rotation); - // break; - // } // } // }